]>
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
))
236 int_set_add(struct linpool
*pool
, struct adata
*list
, u32 val
)
241 if (int_set_contains(list
, val
))
244 len
= list
? list
->length
: 0;
245 res
= lp_alloc(pool
, sizeof(struct adata
) + len
+ 4);
246 res
->length
= len
+ 4;
247 * (u32
*) res
->data
= val
;
249 memcpy((char *) res
->data
+ 4, list
->data
, list
->length
);
254 ec_set_add(struct linpool
*pool
, struct adata
*list
, u64 val
)
256 if (ec_set_contains(list
, val
))
259 int olen
= list
? list
->length
: 0;
260 struct adata
*res
= lp_alloc(pool
, sizeof(struct adata
) + olen
+ 8);
261 res
->length
= olen
+ 8;
264 memcpy(res
->data
, list
->data
, list
->length
);
266 u32
*l
= (u32
*) (res
->data
+ olen
);
274 lc_set_add(struct linpool
*pool
, struct adata
*list
, lcomm val
)
276 if (lc_set_contains(list
, val
))
279 int olen
= list
? list
->length
: 0;
280 struct adata
*res
= lp_alloc(pool
, sizeof(struct adata
) + olen
+ LCOMM_LENGTH
);
281 res
->length
= olen
+ LCOMM_LENGTH
;
284 memcpy(res
->data
, list
->data
, list
->length
);
286 lc_put((u32
*) (res
->data
+ olen
), val
);
292 int_set_del(struct linpool
*pool
, struct adata
*list
, u32 val
)
294 if (!int_set_contains(list
, val
))
298 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- 4);
299 res
->length
= list
->length
- 4;
301 u32
*l
= int_set_get_data(list
);
302 u32
*k
= int_set_get_data(res
);
303 int len
= int_set_get_size(list
);
306 for (i
= 0; i
< len
; i
++)
314 ec_set_del(struct linpool
*pool
, struct adata
*list
, u64 val
)
316 if (!ec_set_contains(list
, val
))
320 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- 8);
321 res
->length
= list
->length
- 8;
323 u32
*l
= int_set_get_data(list
);
324 u32
*k
= int_set_get_data(res
);
325 int len
= int_set_get_size(list
);
330 for (i
=0; i
< len
; i
+= 2)
331 if (! (l
[i
] == eh
&& l
[i
+1] == el
))
341 lc_set_del(struct linpool
*pool
, struct adata
*list
, lcomm val
)
343 if (!lc_set_contains(list
, val
))
347 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- LCOMM_LENGTH
);
348 res
->length
= list
->length
- LCOMM_LENGTH
;
350 u32
*l
= int_set_get_data(list
);
351 u32
*k
= int_set_get_data(res
);
352 int len
= int_set_get_size(list
);
355 for (i
=0; i
< len
; i
+= 3)
356 if (! lc_match(l
, i
, val
))
363 int_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
371 int len
= int_set_get_size(l2
);
372 u32
*l
= int_set_get_data(l2
);
377 for (i
= 0; i
< len
; i
++)
378 if (!int_set_contains(l1
, l
[i
]))
385 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
386 res
->length
= l1
->length
+ len
;
387 memcpy(res
->data
, l1
->data
, l1
->length
);
388 memcpy(res
->data
+ l1
->length
, tmp
, len
);
393 ec_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
401 int len
= int_set_get_size(l2
);
402 u32
*l
= int_set_get_data(l2
);
407 for (i
= 0; i
< len
; i
+= 2)
408 if (!ec_set_contains(l1
, ec_get(l
, i
)))
418 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
419 res
->length
= l1
->length
+ len
;
420 memcpy(res
->data
, l1
->data
, l1
->length
);
421 memcpy(res
->data
+ l1
->length
, tmp
, len
);
426 lc_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
434 int len
= int_set_get_size(l2
);
435 u32
*l
= int_set_get_data(l2
);
440 for (i
= 0; i
< len
; i
+= 3)
441 if (!lc_set_contains(l1
, lc_get(l
, i
)))
448 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
449 res
->length
= l1
->length
+ len
;
450 memcpy(res
->data
, l1
->data
, l1
->length
);
451 memcpy(res
->data
+ l1
->length
, tmp
, len
);