Stop perusing f_prefix for non-prefix-set uses

Multiple changes by Ondrej Santiago Zajicek
This commit is contained in:
Jan Moskyto Matejka 2015-12-16 10:25:12 +01:00 committed by Ondrej Zajicek (work)
parent d7661fbe9d
commit 5e173e9f63
11 changed files with 176 additions and 182 deletions

View file

@ -61,7 +61,7 @@ CF_DECLS
struct roa_table *rot; struct roa_table *rot;
void *g; void *g;
bird_clock_t time; bird_clock_t time;
struct prefix px; struct f_prefix px;
struct proto_spec ps; struct proto_spec ps;
struct timeformat *tf; struct timeformat *tf;
} }
@ -162,7 +162,7 @@ ipa:
ipa_raw ipa_raw
| SYM { | SYM {
if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected"); if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected");
$$ = SYM_VAL($1).px.ip; $$ = SYM_VAL($1).ip;
} }
; ;

View file

@ -217,8 +217,8 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
else if (val->type == T_QUAD) { else if (val->type == T_QUAD) {
ipv4_used = 1; key = val->val.i; ipv4_used = 1; key = val->val.i;
} }
else if (val->type == T_IP) { else if ((val->type == T_IP) && ipa_is_ip4(val->val.ip)) {
ipv4_used = 1; key = ipa_to_u32(val->val.px.ip); ipv4_used = 1; key = ipa_to_u32(val->val.ip);
} }
else else
cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor"); 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 <i32> pair_atom ec_expr
%type <e> pair_item ec_item set_item switch_item set_items switch_items switch_body %type <e> pair_item ec_item set_item switch_item set_items switch_items switch_body
%type <trie> fprefix_set %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 <s> decls declsn one_decl function_params
%type <h> bgp_path bgp_path_tail1 bgp_path_tail2 %type <h> bgp_path bgp_path_tail1 bgp_path_tail2
@ -323,7 +324,7 @@ type:
INT { $$ = T_INT; } INT { $$ = T_INT; }
| BOOL { $$ = T_BOOL; } | BOOL { $$ = T_BOOL; }
| IP { $$ = T_IP; } | IP { $$ = T_IP; }
| PREFIX { $$ = T_PREFIX; } | PREFIX { $$ = T_NET; }
| PAIR { $$ = T_PAIR; } | PAIR { $$ = T_PAIR; }
| QUAD { $$ = T_QUAD; } | QUAD { $$ = T_QUAD; }
| EC { $$ = T_EC; } | EC { $$ = T_EC; }
@ -342,7 +343,7 @@ type:
$$ = T_SET; $$ = T_SET;
break; break;
case T_PREFIX: case T_NET:
$$ = T_PREFIX_SET; $$ = T_PREFIX_SET;
break; break;
@ -477,7 +478,7 @@ block:
* Complex types, their bison value is struct f_val * Complex types, their bison value is struct f_val
*/ */
fipa: 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); } | 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:
fprefix_s { $$ = $1; } net_ip { $$.net = $1; $$.lo = $1.n.pxlen; $$.hi = $1.n.pxlen; }
| fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; } | net_ip '+' { $$.net = $1; $$.lo = $1.n.pxlen; $$.hi = net_max_prefix_length[$1.n.type]; }
| fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; } | net_ip '-' { $$.net = $1; $$.lo = 0; $$.hi = $1.n.pxlen; }
| fprefix_s '{' NUM ',' NUM '}' { | net_ip '{' 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); $$.net = $1; $$.lo = $3; $$.hi = $5;
$$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); 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_set:
fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_fprefix($$, &($1.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_fprefix($$, &($3.val.px)); } | fprefix_set ',' fprefix { $$ = $1; trie_add_prefix($$, &($3.net.n), $3.lo, $3.hi); }
; ;
switch_body: /* EMPTY */ { $$ = NULL; } switch_body: /* EMPTY */ { $$ = NULL; }
@ -643,7 +638,7 @@ constant:
| FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; } | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; }
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; } | 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; } | 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" ); } | '[' 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; } | '[' 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; } | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
@ -706,7 +701,7 @@ symbol:
static_attr: static_attr:
FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_FROM; $$->a1.i = 1; } 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; } | 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; } | PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_PROTO; }
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = SA_SOURCE; } | 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; } | SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE; $$->a1.i = 1; }

View file

@ -90,17 +90,8 @@ pm_format(struct f_path_mask *p, buffer *buf)
buffer_puts(buf, "=]"); buffer_puts(buf, "=]");
} }
static inline int static inline int val_is_ip4(const struct f_val v)
uint_cmp(uint i1, uint i2) { return (v.type == T_IP) && ipa_is_ip4(v.val.ip); }
{
return (int)(i1 > i2) - (int)(i1 < i2);
}
static inline int
u64_cmp(u64 i1, u64 i2)
{
return (int)(i1 > i2) - (int)(i1 < i2);
}
/** /**
* val_compare - compare two values * val_compare - compare two values
@ -114,8 +105,6 @@ u64_cmp(u64 i1, u64 i2)
int int
val_compare(struct f_val v1, struct f_val v2) val_compare(struct f_val v1, struct f_val v2)
{ {
int rc;
if (v1.type != v2.type) { if (v1.type != v2.type) {
if (v1.type == T_VOID) /* Hack for else */ if (v1.type == T_VOID) /* Hack for else */
return -1; return -1;
@ -124,10 +113,10 @@ val_compare(struct f_val v1, struct f_val v2)
#ifndef IPV6 #ifndef IPV6
/* IP->Quad implicit conversion */ /* IP->Quad implicit conversion */
if ((v1.type == T_QUAD) && (v2.type == T_IP)) if ((v1.type == T_QUAD) && val_is_ip4(v2))
return uint_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip)); return uint_cmp(v1.val.i, ipa_to_u32(v2.val.ip));
if ((v1.type == T_IP) && (v2.type == T_QUAD)) if (val_is_ip4(v1) && (v2.type == T_QUAD))
return uint_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i); return uint_cmp(ipa_to_u32(v1.val.ip), v2.val.i);
#endif #endif
debug( "Types do not match in val_compare\n" ); 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: case T_EC:
return u64_cmp(v1.val.ec, v2.val.ec); return u64_cmp(v1.val.ec, v2.val.ec);
case T_IP: case T_IP:
return ipa_compare(v1.val.px.ip, v2.val.px.ip); return ipa_compare(v1.val.ip, v2.val.ip);
case T_PREFIX: case T_NET:
if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip)) return net_compare(v1.val.net, v2.val.net);
return rc;
return uint_cmp(v1.val.px.len, v2.val.px.len);
case T_STRING: case T_STRING:
return strcmp(v1.val.s, v2.val.s); return strcmp(v1.val.s, v2.val.s);
default: 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 static int
clist_set_type(struct f_tree *set, struct f_val *v) 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); return int_set_contains(v2.val.ad, v1.val.i);
#ifndef IPV6 #ifndef IPV6
/* IP->Quad implicit conversion */ /* IP->Quad implicit conversion */
if ((v1.type == T_IP) && (v2.type == T_CLIST)) if (val_is_ip4(v1) && (v2.type == T_CLIST))
return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip)); return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.ip));
#endif #endif
if ((v1.type == T_EC) && (v2.type == T_ECLIST)) 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)) if ((v1.type == T_STRING) && (v2.type == T_STRING))
return patmatch(v2.val.s, v1.val.s); return patmatch(v2.val.s, v1.val.s);
if ((v1.type == T_IP) && (v2.type == T_PREFIX)) if ((v1.type == T_IP) && (v2.type == T_NET))
return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len); return ipa_in_netX(v1.val.ip, v2.val.net);
if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) if ((v1.type == T_NET) && (v2.type == T_NET))
return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len); return net_in_netX(v1.val.net, v2.val.net);
if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET)) if ((v1.type == T_NET) && (v2.type == T_PREFIX_SET))
return trie_match_fprefix(v2.val.ti, &v1.val.px); return trie_match_net(v2.val.ti, v1.val.net);
if (v2.type != T_SET) if (v2.type != T_SET)
return CMP_ERROR; 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_BOOL: buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
case T_INT: buffer_print(buf, "%u", v.val.i); 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_STRING: buffer_print(buf, "%s", v.val.s); return;
case T_IP: buffer_print(buf, "%I", v.val.px.ip); return; case T_IP: buffer_print(buf, "%I", v.val.ip); return;
case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); 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_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_QUAD: buffer_print(buf, "%R", v.val.i); return;
case T_EC: ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); 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 #ifndef IPV6
/* IP->Quad implicit conversion */ /* IP->Quad implicit conversion */
else if (v1.type == T_IP) { else if (val_is_ip4(v1)) {
ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip); ipv4_used = 1; key = ipa_to_u32(v1.val.ip);
} }
#endif #endif
else else
@ -715,9 +684,10 @@ interpret(struct f_inst *what)
if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) { if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
#ifndef IPV6 #ifndef IPV6
/* IP->Quad implicit conversion */ /* 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->type = T_QUAD;
vp->val.i = ipa_to_u32(v2.val.px.ip); vp->val.i = ipa_to_u32(v2.val.ip);
break; break;
} }
#endif #endif
@ -790,10 +760,9 @@ interpret(struct f_inst *what)
switch (what->a2.i) switch (what->a2.i)
{ {
case SA_FROM: res.val.px.ip = rta->from; break; case SA_FROM: res.val.ip = rta->from; break;
case SA_GW: res.val.px.ip = rta->gw; break; case SA_GW: res.val.ip = rta->gw; break;
case SA_NET: res.val.px.ip = net_prefix((*f_rte)->net->n.addr); case SA_NET: res.val.net = (*f_rte)->net->n.addr; break;
res.val.px.len = net_pxlen((*f_rte)->net->n.addr); break;
case SA_PROTO: res.val.s = rta->src->proto->name; break; case SA_PROTO: res.val.s = rta->src->proto->name; break;
case SA_SOURCE: res.val.i = rta->source; break; case SA_SOURCE: res.val.i = rta->source; break;
case SA_SCOPE: res.val.i = rta->scope; break; case SA_SCOPE: res.val.i = rta->scope; break;
@ -820,12 +789,12 @@ interpret(struct f_inst *what)
switch (what->a2.i) switch (what->a2.i)
{ {
case SA_FROM: case SA_FROM:
rta->from = v1.val.px.ip; rta->from = v1.val.ip;
break; break;
case SA_GW: 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); neighbor *n = neigh_find(rta->src->proto, &ip, 0);
if (!n || (n->scope == SCOPE_HOST)) if (!n || (n->scope == SCOPE_HOST))
runtime( "Invalid gw address" ); runtime( "Invalid gw address" );
@ -908,7 +877,7 @@ interpret(struct f_inst *what)
case EAF_TYPE_IP_ADDRESS: case EAF_TYPE_IP_ADDRESS:
res.type = T_IP; res.type = T_IP;
struct adata * ad = e->u.ptr; struct adata * ad = e->u.ptr;
res.val.px.ip = * (ip_addr *) ad->data; res.val.ip = * (ip_addr *) ad->data;
break; break;
case EAF_TYPE_AS_PATH: case EAF_TYPE_AS_PATH:
res.type = T_PATH; res.type = T_PATH;
@ -958,8 +927,8 @@ interpret(struct f_inst *what)
case EAF_TYPE_ROUTER_ID: case EAF_TYPE_ROUTER_ID:
#ifndef IPV6 #ifndef IPV6
/* IP->Quad implicit conversion */ /* IP->Quad implicit conversion */
if (v1.type == T_IP) { if (val_is_ip4(v1)) {
l->attrs[0].u.data = ipa_to_u32(v1.val.px.ip); l->attrs[0].u.data = ipa_to_u32(v1.val.ip);
break; break;
} }
#endif #endif
@ -978,7 +947,7 @@ interpret(struct f_inst *what)
int len = sizeof(ip_addr); int len = sizeof(ip_addr);
struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len); struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
ad->length = 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; l->attrs[0].u.ptr = ad;
break; break;
case EAF_TYPE_AS_PATH: case EAF_TYPE_AS_PATH:
@ -1053,7 +1022,7 @@ interpret(struct f_inst *what)
ONEARG; ONEARG;
res.type = T_INT; res.type = T_INT;
switch(v1.type) { 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_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_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; case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
@ -1062,14 +1031,10 @@ interpret(struct f_inst *what)
break; break;
case P('c','p'): /* Convert prefix to ... */ case P('c','p'): /* Convert prefix to ... */
ONEARG; ONEARG;
if (v1.type != T_PREFIX) if (v1.type != T_NET)
runtime( "Prefix expected" ); runtime( "Prefix expected" );
res.type = what->aux; res.type = T_IP;
switch(res.type) { res.val.ip = net_prefix(v1.val.net);
/* 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" );
}
break; break;
case P('a','f'): /* Get first ASN from AS PATH */ case P('a','f'): /* Get first ASN from AS PATH */
ONEARG; ONEARG;
@ -1135,7 +1100,7 @@ interpret(struct f_inst *what)
{ {
ip_addr mask = ipa_mkmask(v2.val.i); ip_addr mask = ipa_mkmask(v2.val.i);
res.type = T_IP; 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; break;
@ -1195,7 +1160,7 @@ interpret(struct f_inst *what)
#ifndef IPV6 #ifndef IPV6
/* IP->Quad implicit conversion */ /* IP->Quad implicit conversion */
else if (v2.type == T_IP) else if (v2.type == T_IP)
n = ipa_to_u32(v2.val.px.ip); n = ipa_to_u32(v2.val.ip);
#endif #endif
else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy)) else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
arg_set = 1; arg_set = 1;
@ -1284,7 +1249,7 @@ interpret(struct f_inst *what)
if (what->arg1) if (what->arg1)
{ {
TWOARGS; 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()"); runtime("Invalid argument to roa_check()");
as = v2.val.i; as = v2.val.i;
@ -1292,8 +1257,7 @@ interpret(struct f_inst *what)
else else
{ {
ACCESS_RTE; ACCESS_RTE;
v1.val.px.ip = net_prefix((*f_rte)->net->n.addr); v1.val.net = (*f_rte)->net->n.addr;
v1.val.px.len = net_pxlen((*f_rte)->net->n.addr);
/* We ignore temporary attributes, probably not a problem here */ /* 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 */ /* 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"); runtime("Missing ROA table");
res.type = T_ENUM_ROA; 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; break;
default: default:

View file

@ -39,13 +39,8 @@ struct f_inst_roa_check {
}; };
struct f_prefix { struct f_prefix {
ip_addr ip; net_addr_union net;
int len; u8 lo, hi;
#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) */
}; };
struct f_val { struct f_val {
@ -53,8 +48,8 @@ struct f_val {
union { union {
uint i; uint i;
u64 ec; u64 ec;
/* ip_addr ip; Folded into prefix */ ip_addr ip;
struct f_prefix px; const net_addr *net;
char *s; char *s;
struct f_tree *t; struct f_tree *t;
struct f_trie *ti; 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); void tree_format(struct f_tree *t, buffer *buf);
struct f_trie *f_new_trie(linpool *lp, uint node_size); 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); void *trie_add_prefix(struct f_trie *t, net_addr *n, uint l, uint h);
int trie_match_prefix(struct f_trie *t, ip_addr px, int plen); int trie_match_net(struct f_trie *t, const net_addr *n);
int trie_same(struct f_trie *t1, struct f_trie *t2); int trie_same(struct f_trie *t1, struct f_trie *t2);
void trie_format(struct f_trie *t, buffer *buf); 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 ea_list;
struct rte; struct rte;
@ -163,7 +141,7 @@ void val_format(struct f_val v, buffer *buf);
/* Bigger ones */ /* Bigger ones */
#define T_IP 0x20 #define T_IP 0x20
#define T_PREFIX 0x21 #define T_NET 0x21
#define T_STRING 0x22 #define T_STRING 0x22
#define T_PATH_MASK 0x23 /* mask for BGP path */ #define T_PATH_MASK 0x23 /* mask for BGP path */
#define T_PATH 0x24 /* BGP path */ #define T_PATH 0x24 /* BGP path */

View file

@ -109,12 +109,11 @@ attach_node(struct f_trie_node *parent, struct f_trie_node *child)
/** /**
* trie_add_prefix * trie_add_prefix
* @t: trie to add to * @t: trie to add to
* @px: prefix address * @net: IP network prefix
* @plen: prefix length
* @l: prefix lower bound * @l: prefix lower bound
* @h: prefix upper 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. * and upper bounds on accepted prefix lengths, both inclusive.
* 0 <= l, h <= 32 (128 for IPv6). * 0 <= l, h <= 32 (128 for IPv6).
* *
@ -124,8 +123,19 @@ attach_node(struct f_trie_node *parent, struct f_trie_node *child)
*/ */
void * 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) if (l == 0)
t->zero = 1; t->zero = 1;
else 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 *o = NULL;
struct f_trie_node *n = t->root; struct f_trie_node *n = t->root;
while(n) while (n)
{ {
ip_addr cmask = ipa_and(n->mask, pmask); 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; return a;
} }
/** static int
* 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
trie_match_prefix(struct f_trie *t, ip_addr px, int plen) trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
{ {
ip_addr pmask = ipa_mkmask(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; 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 static int
trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2) trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
{ {

View file

@ -35,6 +35,12 @@
#define DELTA(a,b) (((a)>=(b))?(a)-(b):(b)-(a)) #define DELTA(a,b) (((a)>=(b))?(a)-(b):(b)-(a))
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(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 */ /* Bitfield macros */

View file

@ -492,10 +492,4 @@ int ip6_pton(const char *a, ip6_addr *o);
char *ip_scope_text(uint); char *ip_scope_text(uint);
struct prefix {
ip_addr addr;
uint len;
};
#endif #endif

View file

@ -58,23 +58,30 @@ net_pxmask(const net_addr *a)
} }
} }
int
static inline int net_validate_ip4(const net_addr_ip4 *n) net_compare(const net_addr *a, const net_addr *b)
{ {
return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) && if (a->type != b->type)
ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen)))); return uint_cmp(a->type, b->type);
}
static inline int net_validate_ip6(const net_addr_ip6 *n) switch (a->type)
{ {
return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) && case NET_IP4:
ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen)))); 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 int
net_validate(const net_addr *N) net_validate(const net_addr *N)
{ {
switch (a->type) switch (N->type)
{ {
case NET_IP4: case NET_IP4:
case NET_VPN4: case NET_VPN4:

View file

@ -162,6 +162,21 @@ static inline int net_zero_vpn6(const net_addr_vpn6 *a)
{ return !a->pxlen && ip6_zero(a->prefix) && !a->rd; } { 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) static inline void net_copy(net_addr *dst, const net_addr *src)
{ memcpy(dst, src, src->length); } { 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); } { 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) static inline void net_normalize_ip4(net_addr_ip4 *n)
{ n->prefix = ip4_and(n->prefix, ip4_mkmask(n->pxlen)); } { 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); void net_normalize(net_addr *N);
int net_validate(const net_addr *N);
int net_classify(const net_addr *N); int net_classify(const net_addr *N);
int net_format(const net_addr *N, char *buf, int buflen); int net_format(const net_addr *N, char *buf, int buflen);

View file

@ -98,10 +98,8 @@ idval:
| SYM { | SYM {
if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
$$ = SYM_VAL($1).i; $$ = SYM_VAL($1).i;
#ifndef IPV6 else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip))
else if ($1->class == (SYM_CONSTANT | T_IP)) $$ = ipa_to_u32(SYM_VAL($1).ip);
$$ = ipa_to_u32(SYM_VAL($1).px.ip);
#endif
else else
cf_error("Number of IPv4 address constant expected"); cf_error("Number of IPv4 address constant expected");
} }

View file

@ -2293,13 +2293,14 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
he->igp_metric = rt_get_igp_metric(e); he->igp_metric = rt_get_igp_metric(e);
} }
/* XXXX */
done: done:
/* Add a prefix range to the trie */ /* Add a prefix range to the trie */
/* XXXX
if (ipa_is_ip4(he->addr)) if (ipa_is_ip4(he->addr))
trie_add_prefix(tab->hostcache->trie, he->addr, IP4_MAX_PREFIX_LENGTH, pxlen, IP4_MAX_PREFIX_LENGTH); trie_add_prefix(tab->hostcache->trie, he->addr, IP4_MAX_PREFIX_LENGTH, pxlen, IP4_MAX_PREFIX_LENGTH);
else else
trie_add_prefix(tab->hostcache->trie, he->addr, IP6_MAX_PREFIX_LENGTH, pxlen, IP6_MAX_PREFIX_LENGTH); trie_add_prefix(tab->hostcache->trie, he->addr, IP6_MAX_PREFIX_LENGTH, pxlen, IP6_MAX_PREFIX_LENGTH);
*/
rta_free(old_src); rta_free(old_src);
return old_src != he->src; return old_src != he->src;