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>