Commit 5e173e9f authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka Committed by Ondrej Zajicek (work)
Browse files

Stop perusing f_prefix for non-prefix-set uses

Multiple changes by Ondrej Santiago Zajicek
parent d7661fbe
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
   }
 ;

+24 −29
Original line number Diff line number Diff line
@@ -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");
@@ -297,7 +297,8 @@ 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 <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

@@ -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; }
@@ -643,7 +638,7 @@ constant:
 | 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; }
 | 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; }
+43 −78
Original line number Diff line number Diff line
@@ -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:
+13 −35
Original line number Diff line number Diff line
@@ -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 */
+37 −16
Original line number Diff line number Diff line
@@ -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
@@ -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)
{
Loading