Annotation of embedaddon/bird/nest/a-set.c, revision 1.1.1.1
1.1 misho 1: /*
2: * BIRD -- Set/Community-list Operations
3: *
4: * (c) 2000 Martin Mares <mj@ucw.cz>
5: * (c) 2000 Pavel Machek <pavel@ucw.cz>
6: *
7: * Can be freely distributed and used under the terms of the GNU GPL.
8: */
9:
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"
15:
16: /**
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
23: *
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.
33: */
34: int
35: int_set_format(struct adata *set, int way, int from, byte *buf, uint size)
36: {
37: u32 *z = (u32 *) set->data;
38: byte *end = buf + size - 24;
39: int from2 = MAX(from, 0);
40: int to = set->length / 4;
41: int i;
42:
43: for (i = from2; i < to; i++)
44: {
45: if (buf > end)
46: {
47: if (from < 0)
48: strcpy(buf, " ...");
49: else
50: *buf = 0;
51: return i;
52: }
53:
54: if (i > from2)
55: *buf++ = ' ';
56:
57: if (way)
58: buf += bsprintf(buf, "(%d,%d)", z[i] >> 16, z[i] & 0xffff);
59: else
60: buf += bsprintf(buf, "%R", z[i]);
61: }
62: *buf = 0;
63: return 0;
64: }
65:
66: int
67: ec_format(byte *buf, u64 ec)
68: {
69: u32 type, key, val;
70: char tbuf[16], *kind;
71:
72: type = ec >> 48;
73: switch (type & 0xf0ff)
74: {
75: case EC_RT: kind = "rt"; break;
76: case EC_RO: kind = "ro"; break;
77:
78: default:
79: kind = tbuf;
80: bsprintf(kind, "unknown 0x%x", type);
81: }
82:
83: switch (ec >> 56)
84: {
85: /* RFC 4360 3.1. Two-Octet AS Specific Extended Community */
86: case 0x00:
87: case 0x40:
88: key = (ec >> 32) & 0xFFFF;
89: val = ec;
90: return bsprintf(buf, "(%s, %u, %u)", kind, key, val);
91:
92: /* RFC 4360 3.2. IPv4 Address Specific Extended Community */
93: case 0x01:
94: case 0x41:
95: key = ec >> 16;
96: val = ec & 0xFFFF;
97: return bsprintf(buf, "(%s, %R, %u)", kind, key, val);
98:
99: /* RFC 5668 4-Octet AS Specific BGP Extended Community */
100: case 0x02:
101: case 0x42:
102: key = ec >> 16;
103: val = ec & 0xFFFF;
104: return bsprintf(buf, "(%s, %u, %u)", kind, key, val);
105:
106: /* Generic format for unknown kinds of extended communities */
107: default:
108: key = ec >> 32;
109: val = ec;
110: return bsprintf(buf, "(generic, 0x%x, 0x%x)", key, val);
111: }
112:
113: }
114:
115: int
116: ec_set_format(struct adata *set, int from, byte *buf, uint size)
117: {
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);
122: int i;
123:
124: for (i = from2; i < to; i += 2)
125: {
126: if (buf > end)
127: {
128: if (from < 0)
129: strcpy(buf, " ...");
130: else
131: *buf = 0;
132: return i;
133: }
134:
135: if (i > from2)
136: *buf++ = ' ';
137:
138: buf += ec_format(buf, ec_get(z, i));
139: }
140: *buf = 0;
141: return 0;
142: }
143:
144: int
145: lc_format(byte *buf, lcomm lc)
146: {
147: return bsprintf(buf, "(%u, %u, %u)", lc.asn, lc.ldp1, lc.ldp2);
148: }
149:
150: int
151: lc_set_format(struct adata *set, int from, byte *buf, uint bufsize)
152: {
153: u32 *d = (u32 *) set->data;
154: byte *end = buf + bufsize - 64;
155: int from2 = MAX(from, 0);
156: int to = set->length / 4;
157: int i;
158:
159: for (i = from2; i < to; i += 3)
160: {
161: if (buf > end)
162: {
163: if (from < 0)
164: strcpy(buf, "...");
165: else
166: buf[-1] = 0;
167: return i;
168: }
169:
170: buf += bsprintf(buf, "(%u, %u, %u)", d[i], d[i+1], d[i+2]);
171: *buf++ = ' ';
172: }
173:
174: if (i != from2)
175: buf--;
176:
177: *buf = 0;
178: return 0;
179: }
180:
181: int
182: int_set_contains(struct adata *list, u32 val)
183: {
184: if (!list)
185: return 0;
186:
187: u32 *l = (u32 *) list->data;
188: int len = int_set_get_size(list);
189: int i;
190:
191: for (i = 0; i < len; i++)
192: if (*l++ == val)
193: return 1;
194:
195: return 0;
196: }
197:
198: int
199: ec_set_contains(struct adata *list, u64 val)
200: {
201: if (!list)
202: return 0;
203:
204: u32 *l = int_set_get_data(list);
205: int len = int_set_get_size(list);
206: u32 eh = ec_hi(val);
207: u32 el = ec_lo(val);
208: int i;
209:
210: for (i=0; i < len; i += 2)
211: if (l[i] == eh && l[i+1] == el)
212: return 1;
213:
214: return 0;
215: }
216:
217: int
218: lc_set_contains(struct adata *list, lcomm val)
219: {
220: if (!list)
221: return 0;
222:
223: u32 *l = int_set_get_data(list);
224: int len = int_set_get_size(list);
225: int i;
226:
227: for (i = 0; i < len; i += 3)
228: if (lc_match(l, i, val))
229: return 1;
230:
231: return 0;
232: }
233:
234: struct adata *
235: int_set_prepend(struct linpool *pool, struct adata *list, u32 val)
236: {
237: struct adata *res;
238: int len;
239:
240: if (int_set_contains(list, val))
241: return list;
242:
243: len = list ? list->length : 0;
244: res = lp_alloc(pool, sizeof(struct adata) + len + 4);
245: res->length = len + 4;
246:
247: if (list)
248: memcpy(res->data + 4, list->data, list->length);
249:
250: * (u32 *) res->data = val;
251:
252: return res;
253: }
254:
255: struct adata *
256: int_set_add(struct linpool *pool, struct adata *list, u32 val)
257: {
258: struct adata *res;
259: int len;
260:
261: if (int_set_contains(list, val))
262: return list;
263:
264: len = list ? list->length : 0;
265: res = lp_alloc(pool, sizeof(struct adata) + len + 4);
266: res->length = len + 4;
267:
268: if (list)
269: memcpy(res->data, list->data, list->length);
270:
271: * (u32 *) (res->data + len) = val;
272:
273: return res;
274: }
275:
276: struct adata *
277: ec_set_add(struct linpool *pool, struct adata *list, u64 val)
278: {
279: if (ec_set_contains(list, val))
280: return list;
281:
282: int olen = list ? list->length : 0;
283: struct adata *res = lp_alloc(pool, sizeof(struct adata) + olen + 8);
284: res->length = olen + 8;
285:
286: if (list)
287: memcpy(res->data, list->data, list->length);
288:
289: u32 *l = (u32 *) (res->data + olen);
290: l[0] = ec_hi(val);
291: l[1] = ec_lo(val);
292:
293: return res;
294: }
295:
296: struct adata *
297: lc_set_add(struct linpool *pool, struct adata *list, lcomm val)
298: {
299: if (lc_set_contains(list, val))
300: return list;
301:
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;
305:
306: if (list)
307: memcpy(res->data, list->data, list->length);
308:
309: lc_put((u32 *) (res->data + olen), val);
310:
311: return res;
312: }
313:
314: struct adata *
315: int_set_del(struct linpool *pool, struct adata *list, u32 val)
316: {
317: if (!int_set_contains(list, val))
318: return list;
319:
320: struct adata *res;
321: res = lp_alloc(pool, sizeof(struct adata) + list->length - 4);
322: res->length = list->length - 4;
323:
324: u32 *l = int_set_get_data(list);
325: u32 *k = int_set_get_data(res);
326: int len = int_set_get_size(list);
327: int i;
328:
329: for (i = 0; i < len; i++)
330: if (l[i] != val)
331: *k++ = l[i];
332:
333: return res;
334: }
335:
336: struct adata *
337: ec_set_del(struct linpool *pool, struct adata *list, u64 val)
338: {
339: if (!ec_set_contains(list, val))
340: return list;
341:
342: struct adata *res;
343: res = lp_alloc(pool, sizeof(struct adata) + list->length - 8);
344: res->length = list->length - 8;
345:
346: u32 *l = int_set_get_data(list);
347: u32 *k = int_set_get_data(res);
348: int len = int_set_get_size(list);
349: u32 eh = ec_hi(val);
350: u32 el = ec_lo(val);
351: int i;
352:
353: for (i=0; i < len; i += 2)
354: if (! (l[i] == eh && l[i+1] == el))
355: {
356: *k++ = l[i];
357: *k++ = l[i+1];
358: }
359:
360: return res;
361: }
362:
363: struct adata *
364: lc_set_del(struct linpool *pool, struct adata *list, lcomm val)
365: {
366: if (!lc_set_contains(list, val))
367: return list;
368:
369: struct adata *res;
370: res = lp_alloc(pool, sizeof(struct adata) + list->length - LCOMM_LENGTH);
371: res->length = list->length - LCOMM_LENGTH;
372:
373: u32 *l = int_set_get_data(list);
374: u32 *k = int_set_get_data(res);
375: int len = int_set_get_size(list);
376: int i;
377:
378: for (i=0; i < len; i += 3)
379: if (! lc_match(l, i, val))
380: k = lc_copy(k, l+i);
381:
382: return res;
383: }
384:
385: struct adata *
386: int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
387: {
388: if (!l1)
389: return l2;
390: if (!l2)
391: return l1;
392:
393: struct adata *res;
394: int len = int_set_get_size(l2);
395: u32 *l = int_set_get_data(l2);
396: u32 tmp[len];
397: u32 *k = tmp;
398: int i;
399:
400: for (i = 0; i < len; i++)
401: if (!int_set_contains(l1, l[i]))
402: *k++ = l[i];
403:
404: if (k == tmp)
405: return l1;
406:
407: len = (k - tmp) * 4;
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);
412: return res;
413: }
414:
415: struct adata *
416: ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
417: {
418: if (!l1)
419: return l2;
420: if (!l2)
421: return l1;
422:
423: struct adata *res;
424: int len = int_set_get_size(l2);
425: u32 *l = int_set_get_data(l2);
426: u32 tmp[len];
427: u32 *k = tmp;
428: int i;
429:
430: for (i = 0; i < len; i += 2)
431: if (!ec_set_contains(l1, ec_get(l, i)))
432: {
433: *k++ = l[i];
434: *k++ = l[i+1];
435: }
436:
437: if (k == tmp)
438: return l1;
439:
440: len = (k - tmp) * 4;
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);
445: return res;
446: }
447:
448: struct adata *
449: lc_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
450: {
451: if (!l1)
452: return l2;
453: if (!l2)
454: return l1;
455:
456: struct adata *res;
457: int len = int_set_get_size(l2);
458: u32 *l = int_set_get_data(l2);
459: u32 tmp[len];
460: u32 *k = tmp;
461: int i;
462:
463: for (i = 0; i < len; i += 3)
464: if (!lc_set_contains(l1, lc_get(l, i)))
465: k = lc_copy(k, l+i);
466:
467: if (k == tmp)
468: return l1;
469:
470: len = (k - tmp) * 4;
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);
475: return res;
476: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>