Revision 42a0c054 filter/filter.c

View differences:

filter/filter.c
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);
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);
727 858
	  break;
728 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;
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;
950 1091

  
951
    if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
952
      i = v2.val.i;
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;
960
    else
961
      runtime("Can't add/delete non-pair");
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;
962 1119

  
963
    res.type = T_CLIST;
964
    switch (what->aux)
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)
965 1131
    {
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;
1132
      /* Extended community list */
1133
      int arg_set = 0;
971 1134
      
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;
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;
978 1156

  
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;
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;
984 1162

  
985
    default:
986
      bug("unknown Ca operation");
1163
      default:
1164
	bug("unknown Ca operation");
1165
      }
987 1166
    }
1167
    else
1168
      runtime("Can't add/delete to non-(e)clist");
1169

  
988 1170
    break;
989 1171

  
990 1172
  default:

Also available in: Unified diff