]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/a-set.c
2 * BIRD -- Set/Community-list Operations
4 * (c) 2000 Martin Mares <mj@ucw.cz>
5 * (c) 2000 Pavel Machek <pavel@ucw.cz>
7 * Can be freely distributed and used under the terms of the GNU GPL.
10 #include "nest/bird.h"
11 #include "nest/route.h"
12 #include "nest/attrs.h"
13 #include "lib/resource.h"
14 #include "lib/string.h"
17 * int_set_format - format an &set for printing
18 * @set: set attribute to be formatted
19 * @way: style of format (0 for router ID list, 1 for community list)
20 * @from: starting position in set
21 * @buf: destination buffer
22 * @size: size of buffer
24 * This function takes a set attribute and formats it. @way specifies
25 * the style of format (router ID / community). @from argument can be
26 * used to specify the first printed value for the purpose of printing
27 * untruncated sets even with smaller buffers. If the output fits in
28 * the buffer, 0 is returned, otherwise the position of the first not
29 * printed item is returned. This value can be used as @from argument
30 * in subsequent calls. If truncated output suffices, -1 can be
31 * instead used as @from, in that case " ..." is eventually added at
32 * the buffer to indicate truncation.
35 int_set_format(struct adata
*set
, int way
, int from
, byte
*buf
, uint size
)
37 u32
*z
= (u32
*) set
->data
;
38 byte
*end
= buf
+ size
- 24;
39 int from2
= MAX(from
, 0);
40 int to
= set
->length
/ 4;
43 for (i
= from2
; i
< to
; i
++)
58 buf
+= bsprintf(buf
, "(%d,%d)", z
[i
] >> 16, z
[i
] & 0xffff);
60 buf
+= bsprintf(buf
, "%R", z
[i
]);
67 ec_format(byte
*buf
, u64 ec
)
73 switch (type
& 0xf0ff)
75 case EC_RT
: kind
= "rt"; break;
76 case EC_RO
: kind
= "ro"; break;
80 bsprintf(kind
, "unknown 0x%x", type
);
85 /* RFC 4360 3.1. Two-Octet AS Specific Extended Community */
88 key
= (ec
>> 32) & 0xFFFF;
90 return bsprintf(buf
, "(%s, %u, %u)", kind
, key
, val
);
92 /* RFC 4360 3.2. IPv4 Address Specific Extended Community */
97 return bsprintf(buf
, "(%s, %R, %u)", kind
, key
, val
);
99 /* RFC 5668 4-Octet AS Specific BGP Extended Community */
104 return bsprintf(buf
, "(%s, %u, %u)", kind
, key
, val
);
106 /* Generic format for unknown kinds of extended communities */
110 return bsprintf(buf
, "(generic, 0x%x, 0x%x)", key
, val
);
116 ec_set_format(struct adata
*set
, int from
, byte
*buf
, uint size
)
118 u32
*z
= int_set_get_data(set
);
119 byte
*end
= buf
+ size
- 64;
120 int from2
= MAX(from
, 0);
121 int to
= int_set_get_size(set
);
124 for (i
= from2
; i
< to
; i
+= 2)
138 buf
+= ec_format(buf
, ec_get(z
, i
));
145 lc_format(byte
*buf
, lcomm lc
)
147 return bsprintf(buf
, "(%u, %u, %u)", lc
.asn
, lc
.ldp1
, lc
.ldp2
);
151 lc_set_format(struct adata
*set
, int from
, byte
*buf
, uint bufsize
)
153 u32
*d
= (u32
*) set
->data
;
154 byte
*end
= buf
+ bufsize
- 64;
155 int from2
= MAX(from
, 0);
156 int to
= set
->length
/ 4;
159 for (i
= from2
; i
< to
; i
+= 3)
170 buf
+= bsprintf(buf
, "(%u, %u, %u)", d
[i
], d
[i
+1], d
[i
+2]);
182 int_set_contains(struct adata
*list
, u32 val
)
187 u32
*l
= (u32
*) list
->data
;
188 int len
= int_set_get_size(list
);
191 for (i
= 0; i
< len
; i
++)
199 ec_set_contains(struct adata
*list
, u64 val
)
204 u32
*l
= int_set_get_data(list
);
205 int len
= int_set_get_size(list
);
210 for (i
=0; i
< len
; i
+= 2)
211 if (l
[i
] == eh
&& l
[i
+1] == el
)
218 lc_set_contains(struct adata
*list
, lcomm val
)
223 u32
*l
= int_set_get_data(list
);
224 int len
= int_set_get_size(list
);
227 for (i
= 0; i
< len
; i
+= 3)
228 if (lc_match(l
, i
, val
))
235 int_set_prepend(struct linpool
*pool
, struct adata
*list
, u32 val
)
240 if (int_set_contains(list
, val
))
243 len
= list
? list
->length
: 0;
244 res
= lp_alloc(pool
, sizeof(struct adata
) + len
+ 4);
245 res
->length
= len
+ 4;
248 memcpy(res
->data
+ 4, list
->data
, list
->length
);
250 * (u32
*) res
->data
= val
;
256 int_set_add(struct linpool
*pool
, struct adata
*list
, u32 val
)
261 if (int_set_contains(list
, val
))
264 len
= list
? list
->length
: 0;
265 res
= lp_alloc(pool
, sizeof(struct adata
) + len
+ 4);
266 res
->length
= len
+ 4;
269 memcpy(res
->data
, list
->data
, list
->length
);
271 * (u32
*) (res
->data
+ len
) = val
;
277 ec_set_add(struct linpool
*pool
, struct adata
*list
, u64 val
)
279 if (ec_set_contains(list
, val
))
282 int olen
= list
? list
->length
: 0;
283 struct adata
*res
= lp_alloc(pool
, sizeof(struct adata
) + olen
+ 8);
284 res
->length
= olen
+ 8;
287 memcpy(res
->data
, list
->data
, list
->length
);
289 u32
*l
= (u32
*) (res
->data
+ olen
);
297 lc_set_add(struct linpool
*pool
, struct adata
*list
, lcomm val
)
299 if (lc_set_contains(list
, val
))
302 int olen
= list
? list
->length
: 0;
303 struct adata
*res
= lp_alloc(pool
, sizeof(struct adata
) + olen
+ LCOMM_LENGTH
);
304 res
->length
= olen
+ LCOMM_LENGTH
;
307 memcpy(res
->data
, list
->data
, list
->length
);
309 lc_put((u32
*) (res
->data
+ olen
), val
);
315 int_set_del(struct linpool
*pool
, struct adata
*list
, u32 val
)
317 if (!int_set_contains(list
, val
))
321 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- 4);
322 res
->length
= list
->length
- 4;
324 u32
*l
= int_set_get_data(list
);
325 u32
*k
= int_set_get_data(res
);
326 int len
= int_set_get_size(list
);
329 for (i
= 0; i
< len
; i
++)
337 ec_set_del(struct linpool
*pool
, struct adata
*list
, u64 val
)
339 if (!ec_set_contains(list
, val
))
343 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- 8);
344 res
->length
= list
->length
- 8;
346 u32
*l
= int_set_get_data(list
);
347 u32
*k
= int_set_get_data(res
);
348 int len
= int_set_get_size(list
);
353 for (i
=0; i
< len
; i
+= 2)
354 if (! (l
[i
] == eh
&& l
[i
+1] == el
))
364 lc_set_del(struct linpool
*pool
, struct adata
*list
, lcomm val
)
366 if (!lc_set_contains(list
, val
))
370 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- LCOMM_LENGTH
);
371 res
->length
= list
->length
- LCOMM_LENGTH
;
373 u32
*l
= int_set_get_data(list
);
374 u32
*k
= int_set_get_data(res
);
375 int len
= int_set_get_size(list
);
378 for (i
=0; i
< len
; i
+= 3)
379 if (! lc_match(l
, i
, val
))
386 int_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
394 int len
= int_set_get_size(l2
);
395 u32
*l
= int_set_get_data(l2
);
400 for (i
= 0; i
< len
; i
++)
401 if (!int_set_contains(l1
, l
[i
]))
408 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
409 res
->length
= l1
->length
+ len
;
410 memcpy(res
->data
, l1
->data
, l1
->length
);
411 memcpy(res
->data
+ l1
->length
, tmp
, len
);
416 ec_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
424 int len
= int_set_get_size(l2
);
425 u32
*l
= int_set_get_data(l2
);
430 for (i
= 0; i
< len
; i
+= 2)
431 if (!ec_set_contains(l1
, ec_get(l
, i
)))
441 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
442 res
->length
= l1
->length
+ len
;
443 memcpy(res
->data
, l1
->data
, l1
->length
);
444 memcpy(res
->data
+ l1
->length
, tmp
, len
);
449 lc_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
457 int len
= int_set_get_size(l2
);
458 u32
*l
= int_set_get_data(l2
);
463 for (i
= 0; i
< len
; i
+= 3)
464 if (!lc_set_contains(l1
, lc_get(l
, i
)))
471 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
472 res
->length
= l1
->length
+ len
;
473 memcpy(res
->data
, l1
->data
, l1
->length
);
474 memcpy(res
->data
+ l1
->length
, tmp
, len
);