]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Stop perusing f_prefix for non-prefix-set uses
authorJan Moskyto Matejka <mq@ucw.cz>
Wed, 16 Dec 2015 09:25:12 +0000 (10:25 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sat, 19 Dec 2015 22:49:47 +0000 (23:49 +0100)
Multiple changes by Ondrej Santiago Zajicek

conf/confbase.Y
filter/config.Y
filter/filter.c
filter/filter.h
filter/trie.c
lib/birdlib.h
lib/ip.h
lib/net.c
lib/net.h
nest/config.Y
nest/rt-table.c

index 4bf9599bca376312bc03884eb07c1f6379a2d8ef..467ce5a42e6bf2d12451190e541ef53d1e4d9f89 100644 (file)
@@ -61,7 +61,7 @@ CF_DECLS
   struct roa_table *rot;
   void *g;
   bird_clock_t time;
-  struct prefix px;
+  struct f_prefix px;
   struct proto_spec ps;
   struct timeformat *tf;
 }
@@ -162,7 +162,7 @@ ipa:
    ipa_raw
  | SYM {
      if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected");
-     $$ = SYM_VAL($1).px.ip;
+     $$ = SYM_VAL($1).ip;
    }
  ;
 
index d684475156bb8d602485bca9d4b17d5a356d4ede..9411b7aae754f9187879d8f112aea068249ee418 100644 (file)
@@ -134,7 +134,7 @@ f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt)
 
 static inline struct f_inst *
 f_generate_empty(struct f_inst *dyn)
-{ 
+{
   struct f_inst *e = f_new_inst();
   e->code = 'E';
 
@@ -217,8 +217,8 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
     else if (val->type == T_QUAD) {
       ipv4_used = 1; key = val->val.i;
     }
-    else if (val->type == T_IP) {
-      ipv4_used = 1; key = ipa_to_u32(val->val.px.ip);
+    else if ((val->type == T_IP) && ipa_is_ip4(val->val.ip)) {
+      ipv4_used = 1; key = ipa_to_u32(val->val.ip);
     }
     else
       cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
@@ -234,7 +234,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
 
   if (c1 && c2) {
     u64 ec;
-  
+
     if (kind == EC_GENERIC) {
       ec = ec_generic(key, val2);
     }
@@ -253,7 +253,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
     NEW_F_VAL;
     rv = f_new_inst();
     rv->code = 'C';
-    rv->a1.p = val;    
+    rv->a1.p = val;
     val->type = T_EC;
     val->val.ec = ec;
   }
@@ -297,8 +297,9 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 %type <i32> pair_atom ec_expr
 %type <e> pair_item ec_item set_item switch_item set_items switch_items switch_body
 %type <trie> fprefix_set
-%type <v> set_atom switch_atom fprefix fprefix_s fipa
-%type <s> decls declsn one_decl function_params 
+%type <v> set_atom switch_atom fipa
+%type <px> fprefix
+%type <s> decls declsn one_decl function_params
 %type <h> bgp_path bgp_path_tail1 bgp_path_tail2
 
 CF_GRAMMAR
@@ -323,7 +324,7 @@ type:
    INT { $$ = T_INT; }
  | BOOL { $$ = T_BOOL; }
  | IP { $$ = T_IP; }
- | PREFIX { $$ = T_PREFIX; }
+ | PREFIX { $$ = T_NET; }
  | PAIR { $$ = T_PAIR; }
  | QUAD { $$ = T_QUAD; }
  | EC { $$ = T_EC; }
@@ -342,7 +343,7 @@ type:
               $$ = T_SET;
               break;
 
-         case T_PREFIX:
+         case T_NET:
               $$ = T_PREFIX_SET;
            break;
 
@@ -477,7 +478,7 @@ block:
  * Complex types, their bison value is struct f_val
  */
 fipa:
-   ipa_raw %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
+   ipa_raw %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.ip = $1; }
  ;
 
 
@@ -572,26 +573,20 @@ switch_items:
  | switch_items ',' switch_item { $$ = f_merge_items($1, $3); }
  ;
 
-fprefix_s:
-   ipa_raw '/' NUM %prec '/' {
-     if (($3 < 0) || ($3 > (ipa_is_ip4($1) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH)) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3);
-     $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
-   }
- ;
-
 fprefix:
-   fprefix_s { $$ = $1; }
- | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
- | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
- | fprefix_s '{' NUM ',' NUM '}' { 
-     if (! ((0 <= $3) && ($3 <= $5) && ($5 <= (ipa_is_ip4($1.val.px.ip) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH)))) cf_error("Invalid prefix pattern range: {%d, %d}.", $3, $5);
-     $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8);
+   net_ip      { $$.net = $1; $$.lo = $1.n.pxlen; $$.hi = $1.n.pxlen; }
+ | net_ip '+'  { $$.net = $1; $$.lo = $1.n.pxlen; $$.hi = net_max_prefix_length[$1.n.type]; }
+ | net_ip '-'  { $$.net = $1; $$.lo = 0; $$.hi = $1.n.pxlen; }
+ | net_ip '{' NUM ',' NUM '}' {
+     $$.net = $1; $$.lo = $3; $$.hi = $5;
+     if ((0 > $3) || ($3 > $5) || ($5 > net_max_prefix_length[$1.n.type]))
+       cf_error("Invalid prefix pattern range: {%d, %d}", $3, $5);
    }
  ;
 
 fprefix_set:
-   fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_fprefix($$, &($1.val.px)); }
- | fprefix_set ',' fprefix { $$ = $1; trie_add_fprefix($$, &($3.val.px)); }
+   fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_prefix($$, &($1.net.n), $1.lo, $1.hi); }
+ | fprefix_set ',' fprefix { $$ = $1; trie_add_prefix($$, &($3.net.n), $3.lo, $3.hi); }
  ;
 
 switch_body: /* EMPTY */ { $$ = NULL; }
@@ -602,7 +597,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
        t->data = $4;
      $$ = f_merge_items($1, $2);
    }
- | switch_body ELSECOL cmds { 
+ | switch_body ELSECOL cmds {
      struct f_tree *t = f_new_tree();
      t->from.type = t->to.type = T_VOID;
      t->right = t;
@@ -642,8 +637,8 @@ constant:
  | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1;  }
  | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0;  }
  | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
- | fipa           { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
- | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
+ | fipa          { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
+ | net_any { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_NET; val->val.net = $1; $$->a1.p = val; }
  | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
  | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET;  $$->a2.p = $2; }
  | ENUM          { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
@@ -706,7 +701,7 @@ symbol:
 static_attr:
    FROM    { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = SA_FROM;    $$->a1.i = 1; }
  | GW      { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = SA_GW;      $$->a1.i = 1; }
- | NET     { $$ = f_new_inst(); $$->aux = T_PREFIX;     $$->a2.i = SA_NET; }
+ | NET     { $$ = f_new_inst(); $$->aux = T_NET;        $$->a2.i = SA_NET; }
  | PROTO   { $$ = f_new_inst(); $$->aux = T_STRING;     $$->a2.i = SA_PROTO; }
  | SOURCE  { $$ = f_new_inst(); $$->aux = T_ENUM_RTS;   $$->a2.i = SA_SOURCE; }
  | SCOPE   { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE;   $$->a1.i = 1; }
index 0e17a8e58b542d1d76ca37a878e4e3b5be02cc3f..3859a1857cde611e46c1dbf51c3d87c6654ad972 100644 (file)
@@ -90,17 +90,8 @@ pm_format(struct f_path_mask *p, buffer *buf)
   buffer_puts(buf, "=]");
 }
 
-static inline int
-uint_cmp(uint i1, uint i2)
-{
-  return (int)(i1 > i2) - (int)(i1 < i2);
-}
-
-static inline int
-u64_cmp(u64 i1, u64 i2)
-{
-  return (int)(i1 > i2) - (int)(i1 < i2);
-}
+static inline int val_is_ip4(const struct f_val v)
+{ return (v.type == T_IP) && ipa_is_ip4(v.val.ip); }
 
 /**
  * val_compare - compare two values
@@ -114,8 +105,6 @@ u64_cmp(u64 i1, u64 i2)
 int
 val_compare(struct f_val v1, struct f_val v2)
 {
-  int rc;
-
   if (v1.type != v2.type) {
     if (v1.type == T_VOID)     /* Hack for else */
       return -1;
@@ -124,10 +113,10 @@ val_compare(struct f_val v1, struct f_val v2)
 
 #ifndef IPV6
     /* IP->Quad implicit conversion */
-    if ((v1.type == T_QUAD) && (v2.type == T_IP))
-      return uint_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip));
-    if ((v1.type == T_IP) && (v2.type == T_QUAD))
-      return uint_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i);
+    if ((v1.type == T_QUAD) && val_is_ip4(v2))
+      return uint_cmp(v1.val.i, ipa_to_u32(v2.val.ip));
+    if (val_is_ip4(v1) && (v2.type == T_QUAD))
+      return uint_cmp(ipa_to_u32(v1.val.ip), v2.val.i);
 #endif
 
     debug( "Types do not match in val_compare\n" );
@@ -146,11 +135,9 @@ val_compare(struct f_val v1, struct f_val v2)
   case T_EC:
     return u64_cmp(v1.val.ec, v2.val.ec);
   case T_IP:
-    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
-  case T_PREFIX:
-    if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
-      return rc;
-    return uint_cmp(v1.val.px.len, v2.val.px.len);
+    return ipa_compare(v1.val.ip, v2.val.ip);
+  case T_NET:
+    return net_compare(v1.val.net, v2.val.net);
   case T_STRING:
     return strcmp(v1.val.s, v2.val.s);
   default:
@@ -209,24 +196,6 @@ val_same(struct f_val v1, struct f_val v2)
   }
 }
 
-void
-fprefix_get_bounds(struct f_prefix *px, int *l, int *h)
-{
-  *l = *h = px->len & LEN_MASK;
-
-  if (px->len & LEN_MINUS)
-    *l = 0;
-
-  else if (px->len & LEN_PLUS)
-    *h = ipa_is_ip4(px->ip) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
-
-  else if (px->len & LEN_RANGE)
-    {
-      *l = 0xff & (px->len >> 16);
-      *h = 0xff & (px->len >> 8);
-    }
-}
-
 static int
 clist_set_type(struct f_tree *set, struct f_val *v)
 {
@@ -385,8 +354,8 @@ val_in_range(struct f_val v1, struct f_val v2)
     return int_set_contains(v2.val.ad, v1.val.i);
 #ifndef IPV6
   /* IP->Quad implicit conversion */
-  if ((v1.type == T_IP) && (v2.type == T_CLIST))
-    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
+  if (val_is_ip4(v1) && (v2.type == T_CLIST))
+    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.ip));
 #endif
 
   if ((v1.type == T_EC) && (v2.type == T_ECLIST))
@@ -395,14 +364,14 @@ val_in_range(struct f_val v1, struct f_val v2)
   if ((v1.type == T_STRING) && (v2.type == T_STRING))
     return patmatch(v2.val.s, v1.val.s);
 
-  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
-    return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);
+  if ((v1.type == T_IP) && (v2.type == T_NET))
+    return ipa_in_netX(v1.val.ip, v2.val.net);
 
-  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
-    return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);
+  if ((v1.type == T_NET) && (v2.type == T_NET))
+    return net_in_netX(v1.val.net, v2.val.net);
 
-  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET))
-    return trie_match_fprefix(v2.val.ti, &v1.val.px);
+  if ((v1.type == T_NET) && (v2.type == T_PREFIX_SET))
+    return trie_match_net(v2.val.ti, v1.val.net);
 
   if (v2.type != T_SET)
     return CMP_ERROR;
@@ -437,8 +406,8 @@ val_format(struct f_val v, buffer *buf)
   case T_BOOL: buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
   case T_INT:  buffer_print(buf, "%u", v.val.i); return;
   case T_STRING: buffer_print(buf, "%s", v.val.s); return;
-  case T_IP:   buffer_print(buf, "%I", v.val.px.ip); return;
-  case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); return;
+  case T_IP:   buffer_print(buf, "%I", v.val.ip); return;
+  case T_NET:   buffer_print(buf, "%N", v.val.net); return;
   case T_PAIR: buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return;
   case T_QUAD: buffer_print(buf, "%R", v.val.i); return;
   case T_EC:   ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
@@ -630,8 +599,8 @@ interpret(struct f_inst *what)
       }
 #ifndef IPV6
       /* IP->Quad implicit conversion */
-      else if (v1.type == T_IP) {
-       ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
+      else if (val_is_ip4(v1)) {
+       ipv4_used = 1; key = ipa_to_u32(v1.val.ip);
       }
 #endif
       else
@@ -715,9 +684,10 @@ interpret(struct f_inst *what)
     if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
 #ifndef IPV6
       /* IP->Quad implicit conversion */
-      if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
+      if ((sym->class == (SYM_VARIABLE | T_QUAD)) && val_is_ip4(v2))
+      {
        vp->type = T_QUAD;
-       vp->val.i = ipa_to_u32(v2.val.px.ip);
+       vp->val.i = ipa_to_u32(v2.val.ip);
        break;
       }
 #endif
@@ -790,10 +760,9 @@ interpret(struct f_inst *what)
 
       switch (what->a2.i)
       {
-      case SA_FROM:    res.val.px.ip = rta->from; break;
-      case SA_GW:      res.val.px.ip = rta->gw; break;
-      case SA_NET:     res.val.px.ip = net_prefix((*f_rte)->net->n.addr);
-                       res.val.px.len = net_pxlen((*f_rte)->net->n.addr); break;
+      case SA_FROM:    res.val.ip = rta->from; break;
+      case SA_GW:      res.val.ip = rta->gw; break;
+      case SA_NET:     res.val.net = (*f_rte)->net->n.addr; break;
       case SA_PROTO:   res.val.s = rta->src->proto->name; break;
       case SA_SOURCE:  res.val.i = rta->source; break;
       case SA_SCOPE:   res.val.i = rta->scope; break;
@@ -820,12 +789,12 @@ interpret(struct f_inst *what)
       switch (what->a2.i)
       {
       case SA_FROM:
-       rta->from = v1.val.px.ip;
+       rta->from = v1.val.ip;
        break;
 
       case SA_GW:
        {
-         ip_addr ip = v1.val.px.ip;
+         ip_addr ip = v1.val.ip;
          neighbor *n = neigh_find(rta->src->proto, &ip, 0);
          if (!n || (n->scope == SCOPE_HOST))
            runtime( "Invalid gw address" );
@@ -908,7 +877,7 @@ interpret(struct f_inst *what)
       case EAF_TYPE_IP_ADDRESS:
        res.type = T_IP;
        struct adata * ad = e->u.ptr;
-       res.val.px.ip = * (ip_addr *) ad->data;
+       res.val.ip = * (ip_addr *) ad->data;
        break;
       case EAF_TYPE_AS_PATH:
         res.type = T_PATH;
@@ -958,8 +927,8 @@ interpret(struct f_inst *what)
       case EAF_TYPE_ROUTER_ID:
 #ifndef IPV6
        /* IP->Quad implicit conversion */
-       if (v1.type == T_IP) {
-         l->attrs[0].u.data = ipa_to_u32(v1.val.px.ip);
+       if (val_is_ip4(v1)) {
+         l->attrs[0].u.data = ipa_to_u32(v1.val.ip);
          break;
        }
 #endif
@@ -978,7 +947,7 @@ interpret(struct f_inst *what)
        int len = sizeof(ip_addr);
        struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
        ad->length = len;
-       (* (ip_addr *) ad->data) = v1.val.px.ip;
+       (* (ip_addr *) ad->data) = v1.val.ip;
        l->attrs[0].u.ptr = ad;
        break;
       case EAF_TYPE_AS_PATH:
@@ -1053,7 +1022,7 @@ interpret(struct f_inst *what)
     ONEARG;
     res.type = T_INT;
     switch(v1.type) {
-    case T_PREFIX: res.val.i = v1.val.px.len; break;
+    case T_NET:    res.val.i = net_pxlen(v1.val.net); break;
     case T_PATH:   res.val.i = as_path_getlen(v1.val.ad); break;
     case T_CLIST:  res.val.i = int_set_get_size(v1.val.ad); break;
     case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
@@ -1062,14 +1031,10 @@ interpret(struct f_inst *what)
     break;
   case P('c','p'):     /* Convert prefix to ... */
     ONEARG;
-    if (v1.type != T_PREFIX)
+    if (v1.type != T_NET)
       runtime( "Prefix expected" );
-    res.type = what->aux;
-    switch(res.type) {
-      /*    case T_INT:        res.val.i = v1.val.px.len; break; Not needed any more */
-    case T_IP: res.val.px.ip = v1.val.px.ip; break;
-    default: bug( "Unknown prefix to conversion" );
-    }
+    res.type = T_IP;
+    res.val.ip = net_prefix(v1.val.net);
     break;
   case P('a','f'):     /* Get first ASN from AS PATH */
     ONEARG;
@@ -1135,7 +1100,7 @@ interpret(struct f_inst *what)
     {
       ip_addr mask = ipa_mkmask(v2.val.i);
       res.type = T_IP;
-      res.val.px.ip = ipa_and(mask, v1.val.px.ip);
+      res.val.ip = ipa_and(mask, v1.val.ip);
     }
     break;
 
@@ -1195,7 +1160,7 @@ interpret(struct f_inst *what)
 #ifndef IPV6
       /* IP->Quad implicit conversion */
       else if (v2.type == T_IP)
-       n = ipa_to_u32(v2.val.px.ip);
+       n = ipa_to_u32(v2.val.ip);
 #endif
       else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
        arg_set = 1;
@@ -1284,7 +1249,7 @@ interpret(struct f_inst *what)
     if (what->arg1)
     {
       TWOARGS;
-      if ((v1.type != T_PREFIX) || (v2.type != T_INT))
+      if ((v1.type != T_NET) || (v2.type != T_INT))
        runtime("Invalid argument to roa_check()");
 
       as = v2.val.i;
@@ -1292,8 +1257,7 @@ interpret(struct f_inst *what)
     else
     {
       ACCESS_RTE;
-      v1.val.px.ip = net_prefix((*f_rte)->net->n.addr);
-      v1.val.px.len = net_pxlen((*f_rte)->net->n.addr);
+      v1.val.net = (*f_rte)->net->n.addr;
 
       /* We ignore temporary attributes, probably not a problem here */
       /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
@@ -1310,7 +1274,8 @@ interpret(struct f_inst *what)
       runtime("Missing ROA table");
 
     res.type = T_ENUM_ROA;
-    res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as);
+    res.val.i = ROA_UNKNOWN;
+    // XXXX res.val.i = roa_check_net(rtc->table, &v1.val.net, as);
     break;
 
   default:
index e59c822602c2f7f474cce90d902c85d3a251bd72..4e8293c58fae2a1e155ec3c89043417388e99574 100644 (file)
@@ -39,13 +39,8 @@ struct f_inst_roa_check {
 };
 
 struct f_prefix {
-  ip_addr ip;
-  int len;
-#define LEN_MASK 0xff
-#define LEN_PLUS  0x1000000
-#define LEN_MINUS 0x2000000
-#define LEN_RANGE 0x4000000
-  /* If range then prefix must be in range (len >> 16 & 0xff, len >> 8 & 0xff) */
+  net_addr_union net;
+  u8 lo, hi;
 };
 
 struct f_val {
@@ -53,8 +48,8 @@ struct f_val {
   union {
     uint i;
     u64 ec;
-    /*    ip_addr ip; Folded into prefix */    
-    struct f_prefix px;
+    ip_addr ip;
+    const net_addr *net;
     char *s;
     struct f_tree *t;
     struct f_trie *ti;
@@ -81,28 +76,11 @@ int same_tree(struct f_tree *t1, struct f_tree *t2);
 void tree_format(struct f_tree *t, buffer *buf);
 
 struct f_trie *f_new_trie(linpool *lp, uint node_size);
-void *trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h);
-int trie_match_prefix(struct f_trie *t, ip_addr px, int plen);
+void *trie_add_prefix(struct f_trie *t, net_addr *n, uint l, uint h);
+int trie_match_net(struct f_trie *t, const net_addr *n);
 int trie_same(struct f_trie *t1, struct f_trie *t2);
 void trie_format(struct f_trie *t, buffer *buf);
 
-void fprefix_get_bounds(struct f_prefix *px, int *l, int *h);
-
-static inline void
-trie_add_fprefix(struct f_trie *t, struct f_prefix *px)
-{
-  int l, h;
-  fprefix_get_bounds(px, &l, &h);
-  trie_add_prefix(t, px->ip, px->len & LEN_MASK, l, h);
-}
-
-static inline int
-trie_match_fprefix(struct f_trie *t, struct f_prefix *px)
-{
-  return trie_match_prefix(t, px->ip, px->len & LEN_MASK);
-}
-
-
 struct ea_list;
 struct rte;
 
@@ -163,7 +141,7 @@ void val_format(struct f_val v, buffer *buf);
 
 /* Bigger ones */
 #define T_IP 0x20
-#define T_PREFIX 0x21
+#define T_NET 0x21
 #define T_STRING 0x22
 #define T_PATH_MASK 0x23       /* mask for BGP path */
 #define T_PATH 0x24            /* BGP path */
@@ -176,12 +154,12 @@ void val_format(struct f_val v, buffer *buf);
 #define T_PREFIX_SET 0x81
 
 
-#define SA_FROM                 1    
-#define SA_GW           2      
-#define SA_NET          3     
-#define SA_PROTO        4   
-#define SA_SOURCE       5  
-#define SA_SCOPE        6   
+#define SA_FROM                 1
+#define SA_GW           2
+#define SA_NET          3
+#define SA_PROTO        4
+#define SA_SOURCE       5
+#define SA_SCOPE        6
 #define SA_CAST         7
 #define SA_DEST         8
 #define SA_IFNAME       9
index 8af9015e96cbbc43d4fe2fd2b626e93767a68da9..9fdaac6d5b15e061043d293bfa0a89601d7c376d 100644 (file)
@@ -109,12 +109,11 @@ attach_node(struct f_trie_node *parent, struct f_trie_node *child)
 /**
  * trie_add_prefix
  * @t: trie to add to
- * @px: prefix address
- * @plen: prefix length
+ * @net: IP network prefix
  * @l: prefix lower bound
  * @h: prefix upper bound
  *
- * Adds prefix (prefix pattern) @px/@plen to trie @t.  @l and @h are lower
+ * Adds prefix (prefix pattern) @n to trie @t.  @l and @h are lower
  * and upper bounds on accepted prefix lengths, both inclusive.
  * 0 <= l, h <= 32 (128 for IPv6).
  *
@@ -124,8 +123,19 @@ attach_node(struct f_trie_node *parent, struct f_trie_node *child)
  */
 
 void *
-trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
+trie_add_prefix(struct f_trie *t, net_addr *net, uint l, uint h)
 {
+  ip_addr px = net_prefix(net);
+  uint plen = net_pxlen(net);
+
+  if (net->type == NET_IP4)
+  {
+    const uint delta = IP6_MAX_PREFIX_LENGTH - IP4_MAX_PREFIX_LENGTH;
+    plen += delta;
+    l += delta;
+    h += delta;
+  }
+
   if (l == 0)
     t->zero = 1;
   else
@@ -140,7 +150,7 @@ trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
   struct f_trie_node *o = NULL;
   struct f_trie_node *n = t->root;
 
-  while(n)
+  while (n)
     {
       ip_addr cmask = ipa_and(n->mask, pmask);
 
@@ -196,17 +206,7 @@ trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
   return a;
 }
 
-/**
- * trie_match_prefix
- * @t: trie
- * @px: prefix address
- * @plen: prefix length
- *
- * Tries to find a matching prefix pattern in the trie such that
- * prefix @px/@plen matches that prefix pattern. Returns 1 if there
- * is such prefix pattern in the trie.
- */
-int
+static int
 trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
 {
   ip_addr pmask = ipa_mkmask(plen);
@@ -241,6 +241,27 @@ trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
   return 0;
 }
 
+/**
+ * trie_match_net
+ * @t: trie
+ * @n: net address
+ *
+ * Tries to find a matching net in the trie such that
+ * prefix @n matches that prefix pattern. Returns 1 if there
+ * is such prefix pattern in the trie.
+ */
+int
+trie_match_net(struct f_trie *t, const net_addr *n)
+{
+  int add = 0;
+  switch (n->type) {
+    case NET_IP4:
+    case NET_VPN4: add = IP6_MAX_PREFIX_LENGTH - IP4_MAX_PREFIX_LENGTH;
+  }
+
+  return trie_match_prefix(t, net_prefix(n), net_pxlen(n) + add);
+}
+
 static int
 trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
 {
index 16f437ef76f5f86639b951e745390596e6164cb2..5fec6c7a5604fa4a0a5c069a11ca7a08d139fab4 100644 (file)
 #define DELTA(a,b) (((a)>=(b))?(a)-(b):(b)-(a))
 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
 
+static inline int uint_cmp(uint i1, uint i2)
+{ return (int)(i1 > i2) - (int)(i1 < i2); }
+
+static inline int u64_cmp(u64 i1, u64 i2)
+{ return (int)(i1 > i2) - (int)(i1 < i2); }
+
 
 /* Bitfield macros */
 
index 9706b397715e30c582d15859af4861f8dfe12235..1834db4f1cb8f142377167f71775ee817e04b00c 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -492,10 +492,4 @@ int ip6_pton(const char *a, ip6_addr *o);
 
 char *ip_scope_text(uint);
 
-struct prefix {
-  ip_addr addr;
-  uint len;
-};
-
-
 #endif
index 21486a9b29fcf352eaa862258981acf3bb8ed832..e276599538b60e61d6b60482769e227b37307d24 100644 (file)
--- a/lib/net.c
+++ b/lib/net.c
@@ -58,23 +58,30 @@ net_pxmask(const net_addr *a)
   }
 }
 
-
-static inline int net_validate_ip4(const net_addr_ip4 *n)
+int
+net_compare(const net_addr *a, const net_addr *b)
 {
-  return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) &&
-    ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen))));
-}
+  if (a->type != b->type)
+    return uint_cmp(a->type, b->type);
 
-static inline int net_validate_ip6(const net_addr_ip6 *n)
-{
-  return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) &&
-    ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen))));
+  switch (a->type)
+  {
+  case NET_IP4:
+    return net_compare_ip4((const net_addr_ip4 *) a, (const net_addr_ip4 *) b);
+  case NET_IP6:
+    return net_compare_ip6((const net_addr_ip6 *) a, (const net_addr_ip6 *) b);
+  case NET_VPN4:
+    return net_compare_vpn4((const net_addr_vpn4 *) a, (const net_addr_vpn4 *) b);
+  case NET_VPN6:
+    return net_compare_vpn6((const net_addr_vpn6 *) a, (const net_addr_vpn6 *) b);
+  }
+  return 0;
 }
 
 int
 net_validate(const net_addr *N)
 {
-  switch (a->type)
+  switch (N->type)
   {
   case NET_IP4:
   case NET_VPN4:
index bc1233bf61610f8b1e86d6bd58e1b8b4eb3b1ffc..c9ca349fd4f7d6f72f7933696ca975158d4ad158 100644 (file)
--- a/lib/net.h
+++ b/lib/net.h
@@ -162,6 +162,21 @@ static inline int net_zero_vpn6(const net_addr_vpn6 *a)
 { return !a->pxlen && ip6_zero(a->prefix) && !a->rd; }
 
 
+static inline int net_compare_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b)
+{ return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
+
+static inline int net_compare_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b)
+{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
+
+static inline int net_compare_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b)
+{ return u64_cmp(a->rd, b->rd) ?: ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
+
+static inline int net_compare_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b)
+{ return u64_cmp(a->rd, b->rd) ?: ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
+
+int net_compare(const net_addr *a, const net_addr *b);
+
+
 static inline void net_copy(net_addr *dst, const net_addr *src)
 { memcpy(dst, src, src->length); }
 
@@ -195,6 +210,21 @@ static inline u32 net_hash_vpn6(const net_addr_vpn6 *n)
 { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); }
 
 
+static inline int net_validate_ip4(const net_addr_ip4 *n)
+{
+  return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) &&
+    ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen))));
+}
+
+static inline int net_validate_ip6(const net_addr_ip6 *n)
+{
+  return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) &&
+    ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen))));
+}
+
+int net_validate(const net_addr *N);
+
+
 static inline void net_normalize_ip4(net_addr_ip4 *n)
 { n->prefix = ip4_and(n->prefix, ip4_mkmask(n->pxlen)); }
 
@@ -203,7 +233,6 @@ static inline void net_normalize_ip6(net_addr_ip6 *n)
 
 void net_normalize(net_addr *N);
 
-int net_validate(const net_addr *N);
 
 int net_classify(const net_addr *N);
 int net_format(const net_addr *N, char *buf, int buflen);
index e5a6e0bbafe2b3cfbd6cc1ff454946c1a9f9a083..612e4d4044e7fbab3d6cea12e84e3908d33706f6 100644 (file)
@@ -98,10 +98,8 @@ idval:
  | SYM {
      if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
        $$ = SYM_VAL($1).i;
-#ifndef IPV6
-     else if ($1->class == (SYM_CONSTANT | T_IP))
-       $$ = ipa_to_u32(SYM_VAL($1).px.ip);
-#endif
+     else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip))
+       $$ = ipa_to_u32(SYM_VAL($1).ip);
      else
        cf_error("Number of IPv4 address constant expected");
    }
index 05073ce0cd2641a9714dd5b048908ad2d7bedfae..6ac659a8c5f7e1a5e23f481d28cc3ecd679170ad 100644 (file)
@@ -2293,13 +2293,14 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
       he->igp_metric = rt_get_igp_metric(e);
     }
 
-  /* XXXX */
  done:
   /* Add a prefix range to the trie */
+  /* XXXX
   if (ipa_is_ip4(he->addr))
     trie_add_prefix(tab->hostcache->trie, he->addr, IP4_MAX_PREFIX_LENGTH, pxlen, IP4_MAX_PREFIX_LENGTH);
   else
     trie_add_prefix(tab->hostcache->trie, he->addr, IP6_MAX_PREFIX_LENGTH, pxlen, IP6_MAX_PREFIX_LENGTH);
+  */
 
   rta_free(old_src);
   return old_src != he->src;