]>
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
, unsigned int 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
, unsigned int size
)
118 u32
*z
= int_set_get_data(set
);
119 byte
*end
= buf
+ size
- 24;
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 int_set_contains(struct adata
*list
, u32 val
)
150 u32
*l
= (u32
*) list
->data
;
151 int len
= int_set_get_size(list
);
154 for (i
= 0; i
< len
; i
++)
162 ec_set_contains(struct adata
*list
, u64 val
)
167 u32
*l
= int_set_get_data(list
);
168 int len
= int_set_get_size(list
);
173 for (i
=0; i
< len
; i
+= 2)
174 if (l
[i
] == eh
&& l
[i
+1] == el
)
181 int_set_add(struct linpool
*pool
, struct adata
*list
, u32 val
)
186 if (int_set_contains(list
, val
))
189 len
= list
? list
->length
: 0;
190 res
= lp_alloc(pool
, sizeof(struct adata
) + len
+ 4);
191 res
->length
= len
+ 4;
192 * (u32
*) res
->data
= val
;
194 memcpy((char *) res
->data
+ 4, list
->data
, list
->length
);
199 ec_set_add(struct linpool
*pool
, struct adata
*list
, u64 val
)
201 if (ec_set_contains(list
, val
))
204 int olen
= list
? list
->length
: 0;
205 struct adata
*res
= lp_alloc(pool
, sizeof(struct adata
) + olen
+ 8);
206 res
->length
= olen
+ 8;
209 memcpy(res
->data
, list
->data
, list
->length
);
211 u32
*l
= (u32
*) (res
->data
+ res
->length
- 8);
220 int_set_del(struct linpool
*pool
, struct adata
*list
, u32 val
)
222 if (!int_set_contains(list
, val
))
226 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- 4);
227 res
->length
= list
->length
- 4;
229 u32
*l
= int_set_get_data(list
);
230 u32
*k
= int_set_get_data(res
);
231 int len
= int_set_get_size(list
);
234 for (i
= 0; i
< len
; i
++)
242 ec_set_del(struct linpool
*pool
, struct adata
*list
, u64 val
)
244 if (!ec_set_contains(list
, val
))
248 res
= lp_alloc(pool
, sizeof(struct adata
) + list
->length
- 8);
249 res
->length
= list
->length
- 8;
251 u32
*l
= int_set_get_data(list
);
252 u32
*k
= int_set_get_data(res
);
253 int len
= int_set_get_size(list
);
258 for (i
=0; i
< len
; i
+= 2)
259 if (! (l
[i
] == eh
&& l
[i
+1] == el
))
270 int_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
278 int len
= int_set_get_size(l2
);
279 u32
*l
= int_set_get_data(l2
);
284 for (i
= 0; i
< len
; i
++)
285 if (!int_set_contains(l1
, l
[i
]))
292 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
293 res
->length
= l1
->length
+ len
;
294 memcpy(res
->data
, l1
->data
, l1
->length
);
295 memcpy(res
->data
+ l1
->length
, tmp
, len
);
300 ec_set_union(struct linpool
*pool
, struct adata
*l1
, struct adata
*l2
)
308 int len
= int_set_get_size(l2
);
309 u32
*l
= int_set_get_data(l2
);
314 for (i
= 0; i
< len
; i
+= 2)
315 if (!ec_set_contains(l1
, ec_get(l
, i
)))
325 res
= lp_alloc(pool
, sizeof(struct adata
) + l1
->length
+ len
);
326 res
->length
= l1
->length
+ len
;
327 memcpy(res
->data
, l1
->data
, l1
->length
);
328 memcpy(res
->data
+ l1
->length
, tmp
, len
);