~brightbox/bird/bird-packaging

« back to all changes in this revision

Viewing changes to filter/filter.c

  • Committer: Ondřej Surý
  • Date: 2011-09-12 06:59:16 UTC
  • mfrom: (1.1.23)
  • Revision ID: git-v1:da868fd891ce15438ca516573979a5df54601e5a
Merge commit 'upstream/1.3.3' into debian-sid

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
#define CMP_ERROR 999
52
52
 
53
53
static struct adata *
54
 
adata_empty(struct linpool *pool)
 
54
adata_empty(struct linpool *pool, int l)
55
55
{
56
 
  struct adata *res = lp_alloc(pool, sizeof(struct adata));
57
 
  res->length = 0;
 
56
  struct adata *res = lp_alloc(pool, sizeof(struct adata) + l);
 
57
  res->length = l;
58
58
  return res;
59
59
}
60
60
 
126
126
  else return 1;
127
127
}
128
128
 
 
129
static inline int u64_cmp(u64 i1, u64 i2)
 
130
{
 
131
  if (i1 == i2) return 0;
 
132
  if (i1 < i2) return -1;
 
133
  else return 1;
 
134
}
 
135
 
129
136
/**
130
137
 * val_compare - compare two values
131
138
 * @v1: first value
167
174
  case T_PAIR:
168
175
  case T_QUAD:
169
176
    return uint_cmp(v1.val.i, v2.val.i);
 
177
  case T_EC:
 
178
    return u64_cmp(v1.val.ec, v2.val.ec);
170
179
  case T_IP:
171
180
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
172
181
  case T_PREFIX:
226
235
  if ((v1.type == T_IP) && (v2.type == T_CLIST))
227
236
    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
228
237
#endif
 
238
  if ((v1.type == T_EC) && (v2.type == T_ECLIST))
 
239
    return ec_set_contains(v2.val.ad, v1.val.ec);
 
240
 
229
241
  if ((v1.type == T_STRING) && (v2.type == T_STRING))
230
242
    return patmatch(v2.val.s, v1.val.s);
231
243
 
258
270
  }
259
271
}
260
272
 
 
273
static inline int
 
274
eclist_set_type(struct f_tree *set)
 
275
{ return set->from.type == T_EC; }
 
276
 
261
277
static int
262
278
clist_match_set(struct adata *clist, struct f_tree *set)
263
279
{
270
286
 
271
287
  u32 *l = (u32 *) clist->data;
272
288
  u32 *end = l + clist->length/4;
 
289
 
273
290
  while (l < end) {
274
291
    v.val.i = *l++;
275
292
    if (find_tree(set, v))
278
295
  return 0;
279
296
}
280
297
 
 
298
static int
 
299
eclist_match_set(struct adata *list, struct f_tree *set)
 
300
{
 
301
  if (!list)
 
302
    return 0;
 
303
 
 
304
  if (!eclist_set_type(set))
 
305
    return CMP_ERROR;
 
306
 
 
307
  struct f_val v;
 
308
  u32 *l = int_set_get_data(list);
 
309
  int len = int_set_get_size(list);
 
310
  int i;
 
311
 
 
312
  v.type = T_EC;
 
313
  for (i = 0; i < len; i += 2) {
 
314
    v.val.ec = ec_get(l, i);
 
315
    if (find_tree(set, v))
 
316
      return 1;
 
317
  }
 
318
 
 
319
  return 0;
 
320
}
 
321
 
281
322
static struct adata *
282
323
clist_filter(struct linpool *pool, struct adata *clist, struct f_tree *set, int pos)
283
324
{
302
343
  if (nl == clist->length)
303
344
    return clist;
304
345
 
305
 
  struct adata *res = lp_alloc(pool, sizeof(struct adata) + nl);
306
 
  res->length = nl;
 
346
  struct adata *res = adata_empty(pool, nl);
 
347
  memcpy(res->data, tmp, nl);
 
348
  return res;
 
349
}
 
350
 
 
351
static struct adata *
 
352
eclist_filter(struct linpool *pool, struct adata *list, struct f_tree *set, int pos)
 
353
{
 
354
  if (!list)
 
355
    return NULL;
 
356
 
 
357
  struct f_val v;
 
358
 
 
359
  int len = int_set_get_size(list);
 
360
  u32 *l = int_set_get_data(list);
 
361
  u32 tmp[len];
 
362
  u32 *k = tmp;
 
363
  int i;
 
364
 
 
365
  v.type = T_EC;
 
366
  for (i = 0; i < len; i += 2) {
 
367
    v.val.ec = ec_get(l, i);
 
368
    if (pos == !!find_tree(set, v)) {   /* pos && find_tree || !pos && !find_tree */
 
369
      *k++ = l[i];
 
370
      *k++ = l[i+1];
 
371
    }
 
372
  }
 
373
 
 
374
  int nl = (k - tmp) * 4;
 
375
  if (nl == list->length)
 
376
    return list;
 
377
 
 
378
  struct adata *res = adata_empty(pool, nl);
307
379
  memcpy(res->data, tmp, nl);
308
380
  return res;
309
381
}
332
404
  if ((v1.type == T_CLIST) && (v2.type == T_SET))
333
405
    return clist_match_set(v1.val.ad, v2.val.t);
334
406
 
 
407
  if ((v1.type == T_ECLIST) && (v2.type == T_SET))
 
408
    return eclist_match_set(v1.val.ad, v2.val.t);
 
409
 
335
410
  if (v2.type == T_SET)
336
411
    switch (v1.type) {
337
412
    case T_ENUM:
339
414
    case T_PAIR:
340
415
    case T_QUAD:
341
416
    case T_IP:
 
417
    case T_EC:
342
418
      {
343
419
        struct f_tree *n;
344
420
        n = find_tree(v2.val.t, v1);
397
473
  case T_PREFIX: logn("%I/%d", v.val.px.ip, v.val.px.len); return;
398
474
  case T_PAIR: logn("(%d,%d)", v.val.i >> 16, v.val.i & 0xffff); return;
399
475
  case T_QUAD: logn("%R", v.val.i); return;
 
476
  case T_EC: ec_format(buf2, v.val.ec); logn("%s", buf2); return;
400
477
  case T_PREFIX_SET: trie_print(v.val.ti); return;
401
478
  case T_SET: tree_print(v.val.t); return;
402
479
  case T_ENUM: logn("(enum %x)%d", v.type, v.val.i); return;
403
480
  case T_PATH: as_path_format(v.val.ad, buf2, 1000); logn("(path %s)", buf2); return;
404
481
  case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); logn("(clist %s)", buf2); return;
 
482
  case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); logn("(eclist %s)", buf2); return;
405
483
  case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1000); logn("(pathmask%s)", buf2); return;
406
484
  default: logn( "[unknown type %x]", v.type ); return;
407
485
  }
541
619
    break;
542
620
 
543
621
  case P('m','p'):
544
 
    TWOARGS_C;
 
622
    TWOARGS;
545
623
    if ((v1.type != T_INT) || (v2.type != T_INT))
546
624
      runtime( "Can't operate with value of non-integer type in pair constructor" );
547
625
    u1 = v1.val.i;
552
630
    res.type = T_PAIR;
553
631
    break;
554
632
 
 
633
  case P('m','c'):
 
634
    {
 
635
      TWOARGS;
 
636
 
 
637
      int check, ipv4_used;
 
638
      u32 key, val;
 
639
 
 
640
      if (v1.type == T_INT) {
 
641
        ipv4_used = 0; key = v1.val.i;
 
642
      } 
 
643
      else if (v1.type == T_QUAD) {
 
644
        ipv4_used = 1; key = v1.val.i;
 
645
      }
 
646
#ifndef IPV6
 
647
      /* IP->Quad implicit conversion */
 
648
      else if (v1.type == T_IP) {
 
649
        ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
 
650
      }
 
651
#endif
 
652
      else
 
653
        runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
 
654
 
 
655
      if (v2.type != T_INT)
 
656
        runtime("Can't operate with value of non-integer type in EC constructor");
 
657
      val = v2.val.i;
 
658
 
 
659
      res.type = T_EC;
 
660
 
 
661
      if (what->aux == EC_GENERIC) {
 
662
        check = 0; res.val.ec = ec_generic(key, val);
 
663
      }
 
664
      else if (ipv4_used) {
 
665
        check = 1; res.val.ec = ec_ip4(what->aux, key, val);
 
666
      }
 
667
      else if (key < 0x10000) {
 
668
        check = 0; res.val.ec = ec_as2(what->aux, key, val);
 
669
      }
 
670
      else {
 
671
        check = 1; res.val.ec = ec_as4(what->aux, key, val);
 
672
      }
 
673
 
 
674
      if (check && (val > 0xFFFF))
 
675
        runtime("Can't operate with value out of bounds in EC constructor");
 
676
 
 
677
      break;
 
678
    }
 
679
 
555
680
/* Relational operators */
556
681
 
557
682
#define COMPARE(x) \
723
848
        /* A special case: undefined int_set looks like empty int_set */
724
849
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
725
850
          res.type = T_CLIST;
726
 
          res.val.ad = adata_empty(f_pool);
727
 
          break;
728
 
        }
 
851
          res.val.ad = adata_empty(f_pool, 0);
 
852
          break;
 
853
        }
 
854
        /* The same special case for ec_set */
 
855
        else if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
 
856
          res.type = T_ECLIST;
 
857
          res.val.ad = adata_empty(f_pool, 0);
 
858
          break;
 
859
        }
 
860
 
729
861
        /* Undefined value */
730
862
        res.type = T_VOID;
731
863
        break;
757
889
        res.type = T_CLIST;
758
890
        res.val.ad = e->u.ptr;
759
891
        break;
 
892
      case EAF_TYPE_EC_SET:
 
893
        res.type = T_ECLIST;
 
894
        res.val.ad = e->u.ptr;
 
895
        break;
760
896
      case EAF_TYPE_UNDEF:
761
897
        res.type = T_VOID;
762
898
        break;
802
938
        break;
803
939
      case EAF_TYPE_INT_SET:
804
940
        if (v1.type != T_CLIST)
805
 
          runtime( "Setting int set attribute to non-clist value" );
 
941
          runtime( "Setting clist attribute to non-clist value" );
 
942
        l->attrs[0].u.ptr = v1.val.ad;
 
943
        break;
 
944
      case EAF_TYPE_EC_SET:
 
945
        if (v1.type != T_ECLIST)
 
946
          runtime( "Setting eclist attribute to non-eclist value" );
806
947
        l->attrs[0].u.ptr = v1.val.ad;
807
948
        break;
808
949
      case EAF_TYPE_UNDEF:
926
1067
 
927
1068
  case 'E':     /* Create empty attribute */
928
1069
    res.type = what->aux;
929
 
    res.val.ad = adata_empty(f_pool);
 
1070
    res.val.ad = adata_empty(f_pool, 0);
930
1071
    break;
931
1072
  case P('A','p'):      /* Path prepend */
932
1073
    TWOARGS;
939
1080
    res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
940
1081
    break;
941
1082
 
942
 
  case P('C','a'):      /* Community list add or delete */
 
1083
  case P('C','a'):      /* (Extended) Community list add or delete */
943
1084
    TWOARGS;
944
 
    if (v1.type != T_CLIST)
945
 
      runtime("Can't add/delete to non-clist");
946
 
 
947
 
    struct f_val dummy;
948
 
    int arg_set = 0;
949
 
    i = 0;
950
 
 
951
 
    if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
952
 
      i = v2.val.i;
 
1085
    if (v1.type == T_CLIST)
 
1086
    {
 
1087
      /* Community (or cluster) list */
 
1088
      struct f_val dummy;
 
1089
      int arg_set = 0;
 
1090
      i = 0;
 
1091
 
 
1092
      if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
 
1093
        i = v2.val.i;
953
1094
#ifndef IPV6
954
 
    /* IP->Quad implicit conversion */
955
 
    else if (v2.type == T_IP)
956
 
      i = ipa_to_u32(v2.val.px.ip);
 
1095
      /* IP->Quad implicit conversion */
 
1096
      else if (v2.type == T_IP)
 
1097
        i = ipa_to_u32(v2.val.px.ip);
957
1098
#endif
958
 
    else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
959
 
      arg_set = 1;
 
1099
      else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
 
1100
        arg_set = 1;
 
1101
      else
 
1102
        runtime("Can't add/delete non-pair");
 
1103
 
 
1104
      res.type = T_CLIST;
 
1105
      switch (what->aux)
 
1106
      {
 
1107
      case 'a':
 
1108
        if (arg_set)
 
1109
          runtime("Can't add set");
 
1110
        res.val.ad = int_set_add(f_pool, v1.val.ad, i);
 
1111
        break;
 
1112
      
 
1113
      case 'd':
 
1114
        if (!arg_set)
 
1115
          res.val.ad = int_set_del(f_pool, v1.val.ad, i);
 
1116
        else
 
1117
          res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 0);
 
1118
        break;
 
1119
 
 
1120
      case 'f':
 
1121
        if (!arg_set)
 
1122
          runtime("Can't filter pair");
 
1123
        res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 1);
 
1124
        break;
 
1125
 
 
1126
      default:
 
1127
        bug("unknown Ca operation");
 
1128
      }
 
1129
    }
 
1130
    else if (v1.type == T_ECLIST)
 
1131
    {
 
1132
      /* Extended community list */
 
1133
      int arg_set = 0;
 
1134
      
 
1135
      /* v2.val is either EC or EC-set */
 
1136
      if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
 
1137
        arg_set = 1;
 
1138
      else if (v2.type != T_EC)
 
1139
        runtime("Can't add/delete non-pair");
 
1140
 
 
1141
      res.type = T_ECLIST;
 
1142
      switch (what->aux)
 
1143
      {
 
1144
      case 'a':
 
1145
        if (arg_set)
 
1146
          runtime("Can't add set");
 
1147
        res.val.ad = ec_set_add(f_pool, v1.val.ad, v2.val.ec);
 
1148
        break;
 
1149
      
 
1150
      case 'd':
 
1151
        if (!arg_set)
 
1152
          res.val.ad = ec_set_del(f_pool, v1.val.ad, v2.val.ec);
 
1153
        else
 
1154
          res.val.ad = eclist_filter(f_pool, v1.val.ad, v2.val.t, 0);
 
1155
        break;
 
1156
 
 
1157
      case 'f':
 
1158
        if (!arg_set)
 
1159
          runtime("Can't filter ec");
 
1160
        res.val.ad = eclist_filter(f_pool, v1.val.ad, v2.val.t, 1);
 
1161
        break;
 
1162
 
 
1163
      default:
 
1164
        bug("unknown Ca operation");
 
1165
      }
 
1166
    }
960
1167
    else
961
 
      runtime("Can't add/delete non-pair");
962
 
 
963
 
    res.type = T_CLIST;
964
 
    switch (what->aux)
965
 
    {
966
 
    case 'a':
967
 
      if (arg_set)
968
 
        runtime("Can't add set");
969
 
      res.val.ad = int_set_add(f_pool, v1.val.ad, i);
970
 
      break;
971
 
      
972
 
    case 'd':
973
 
      if (!arg_set)
974
 
        res.val.ad = int_set_del(f_pool, v1.val.ad, i);
975
 
      else
976
 
        res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 0);
977
 
      break;
978
 
 
979
 
    case 'f':
980
 
      if (!arg_set)
981
 
        runtime("Can't filter pair");
982
 
      res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 1);
983
 
      break;
984
 
 
985
 
    default:
986
 
      bug("unknown Ca operation");
987
 
    }
 
1168
      runtime("Can't add/delete to non-(e)clist");
 
1169
 
988
1170
    break;
989
1171
 
990
1172
  default: