From 90dc0f08434323535f84d64e113dae84675c46b2 Mon Sep 17 00:00:00 2001 From: Ondrej Filip Date: Sat, 4 Jun 2016 12:38:06 +0200 Subject: Small typo in documentation example, submitted by Felix Eckhofer. --- doc/bird.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/bird.sgml b/doc/bird.sgml index 014225d1..f3c34a14 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1035,7 +1035,7 @@ foot). or ipaddress/netmask. There are two special operators on prefixes: 1.2.0.0/16.pxlen = 16 is true. + So 1.2.0.0/16.len = 16 is true. Date: Wed, 8 Jun 2016 16:22:44 +0200 Subject: Add AS# ranges to bgpmask. --- doc/bird.sgml | 6 ++++-- filter/config.Y | 1 + filter/filter.c | 4 ++++ filter/test.conf | 9 ++++++--- nest/a-path.c | 26 ++++++++++++++++++-------- nest/attrs.h | 2 ++ 6 files changed, 35 insertions(+), 13 deletions(-) (limited to 'doc') diff --git a/doc/bird.sgml b/doc/bird.sgml index f3c34a14..de7041a9 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1165,8 +1165,10 @@ foot). is 4 3 2 1, then: bgp_path ˜ [= * 4 3 * =] is true, but bgp_path ˜ [= * 4 5 * =] is false. BGP mask expressions can also contain integer expressions enclosed in parenthesis - and integer variables, for example [= * 4 (1+2) a =]. There is - also old syntax that uses / .. / instead of [= .. =] and ? instead of *. + and integer variables, for example [= * 4 (1+2) a =]. You can + also use ranges, for example [= * 3..5 2 100..200 * =]. + There is also old (deprecated) syntax that uses / .. / instead of [= .. =] + and ? instead of *. next = $2; $$->kind = PM_ASN; $$->val = $1; } + | NUM DDOT NUM bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $4; $$->kind = PM_ASN_RANGE; $$->val = $1; $$->val2 = $3; } | '*' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val = 0; } | '?' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; $$->val = 0; } | bgp_path_expr bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; } diff --git a/filter/filter.c b/filter/filter.c index eddf4228..dce98e4d 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -79,6 +79,10 @@ pm_format(struct f_path_mask *p, buffer *buf) buffer_puts(buf, "* "); break; + case PM_ASN_RANGE: + buffer_print(buf, "%u..%u ", p->val, p->val2); + break; + case PM_ASN_EXPR: buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val)); break; diff --git a/filter/test.conf b/filter/test.conf index a99d0a51..ad8f9386 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -90,20 +90,23 @@ clist l2; eclist el; eclist el2; { + print "Entering path test..."; pm1 = / 4 3 2 1 /; - pm2 = [= 4 3 2 1 =]; + pm2 = [= 3..6 3 2 1..2 =]; print "Testing path masks: ", pm1, " ", pm2; p2 = prepend( + empty +, 1 ); p2 = prepend( p2, 2 ); p2 = prepend( p2, 3 ); p2 = prepend( p2, 4 ); - print "Testing paths: ", p2; + print "Testing path: (4 3 2 1) = ", p2; print "Should be true: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 3 ~ p2, " ", p2 ~ [2, 10..20], " ", p2 ~ [4, 10..20]; print "4 = ", p2.len; p2 = prepend( p2, 5 ); - print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, ten..(2*ten)]; + print "Testing path: (5 4 3 2 1) = ", p2; + print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, ten..(2*ten)], " ", p2 ~ [= 1..4 4 3 2 1 =], " ", p2 ~ [= 5 4 4..100 2 1 =]; print "Should be true: ", p2 ~ / ? 4 3 2 1 /, " ", p2, " ", / ? 4 3 2 1 /; print "Should be true: ", p2 ~ [= * 4 3 * 1 =], " ", p2, " ", [= * 4 3 * 1 =]; + print "Should be true: ", p2 ~ [= 5..6 4..10 1..3 1..3 1..65536 =]; print "Should be true: ", p2 ~ [= (3+2) (2*2) 3 2 1 =], " ", p2 ~ mkpath(5, 4); print "Should be true: ", p2.len = 5, " ", p2.first = 5, " ", p2.last = 1; print "5 = ", p2.len; diff --git a/nest/a-path.c b/nest/a-path.c index 32e2d27e..e1031b7b 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -435,18 +435,23 @@ parse_path(struct adata *path, struct pm_pos *pos) static int -pm_match(struct pm_pos *pos, u32 asn) +pm_match(struct pm_pos *pos, u32 asn, u32 asn2) { + u32 gas; if (! pos->set) - return pos->val.asn == asn; + return ((pos->val.asn >= asn) && (pos->val.asn <= asn2)); u8 *p = pos->val.sp; int len = *p++; int i; for (i = 0; i < len; i++) - if (get_as(p + i * BS) == asn) + { + gas = get_as(p + i * BS); + + if ((gas >= asn) && (gas <= asn2)) return 1; + } return 0; } @@ -490,7 +495,7 @@ pm_mark(struct pm_pos *pos, int i, int plen, int *nl, int *nh) * next part of mask, we advance each marked state. * We start with marked first position, when we * run out of marked positions, we reject. When - * we process the whole mask, we accept iff final position + * we process the whole mask, we accept if final position * (auxiliary position after last real position in AS path) * is marked. */ @@ -502,6 +507,7 @@ as_path_match(struct adata *path, struct f_path_mask *mask) int plen = parse_path(path, pos); int l, h, i, nh, nl; u32 val = 0; + u32 val2 = 0; /* l and h are bound of interval of positions where are marked states */ @@ -525,12 +531,16 @@ as_path_match(struct adata *path, struct f_path_mask *mask) h = plen; break; - case PM_ASN: - val = mask->val; + case PM_ASN: /* Define single ASN as ASN..ASN - very narrow interval */ + val2 = val = mask->val; goto step; case PM_ASN_EXPR: - val = f_eval_asn((struct f_inst *) mask->val); + val2 = val = f_eval_asn((struct f_inst *) mask->val); goto step; + case PM_ASN_RANGE: + val = mask->val; + val2 = mask->val2; + goto step; case PM_QUESTION: step: nh = nl = -1; @@ -538,7 +548,7 @@ as_path_match(struct adata *path, struct f_path_mask *mask) if (pos[i].mark) { pos[i].mark = 0; - if ((mask->kind == PM_QUESTION) || pm_match(pos + i, val)) + if ((mask->kind == PM_QUESTION) || pm_match(pos + i, val, val2)) pm_mark(pos, i, plen, &nl, &nh); } diff --git a/nest/attrs.h b/nest/attrs.h index 0171c6a8..670b048f 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -45,11 +45,13 @@ struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_ #define PM_QUESTION 1 #define PM_ASTERISK 2 #define PM_ASN_EXPR 3 +#define PM_ASN_RANGE 4 struct f_path_mask { struct f_path_mask *next; int kind; uintptr_t val; + uintptr_t val2; }; int as_path_match(struct adata *path, struct f_path_mask *mask); -- cgit v1.2.3 From 12640c149976e1eca54d9c22c593d07a27c49d42 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 19 Jul 2016 12:16:51 +0200 Subject: Babel: Documentation updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates the documentation to correctly mention Babel when protocols are listed, and adds examples and route attribute documentation to the Babel section of the docs. Signed-off-by: Toke Høiland-Jørgensen --- doc/bird.sgml | 34 +++++++++++++++++++++++++++++++--- nest/config.Y | 2 +- nest/rt-attr.c | 2 +- 3 files changed, 33 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/doc/bird.sgml b/doc/bird.sgml index de7041a9..b90f65d1 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -610,8 +610,8 @@ agreement"). options, in that case for given interface the first matching interface option is used. - This option is allowed in BFD, Direct, OSPF, RAdv and RIP protocols, but - in OSPF protocol it is used in the Route type (Currently ] { yes. +Attributes + +

Babel defines just one attribute: the internal babel metric of the route. It +is exposed as the Example + +

+protocol babel { + interface "eth*" { + type wired; + }; + interface "wlan0", "wlan1" { + type wireless; + hello interval 1; + rxcost 512; + }; + interface "tap0"; + + # This matches the default of babeld: redistribute all addresses + # configured on local interfaces, plus re-distribute all routes received + # from other babel peers. + + export where (source = RTS_DEVICE) || (source = RTS_BABEL); +} + +

In Linux, there is also a plenty of obscure route attributes mostly focused diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h index 96688e34..6d6586d1 100644 --- a/sysdep/linux/krt-sys.h +++ b/sysdep/linux/krt-sys.h @@ -36,6 +36,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; } #define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0x10) #define EA_KRT_REALM EA_CODE(EAP_KRT, 0x11) +#define EA_KRT_SCOPE EA_CODE(EAP_KRT, 0x12) #define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */ diff --git a/sysdep/linux/netlink.Y b/sysdep/linux/netlink.Y index a1c22f3e..f577244d 100644 --- a/sysdep/linux/netlink.Y +++ b/sysdep/linux/netlink.Y @@ -10,7 +10,7 @@ CF_HDR CF_DECLS -CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW, +CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_SCOPE, KRT_MTU, KRT_WINDOW, KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING, KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK, KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR, @@ -28,6 +28,7 @@ kern_sys_item: CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); }) CF_ADDTO(dynamic_attr, KRT_REALM { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); }) +CF_ADDTO(dynamic_attr, KRT_SCOPE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SCOPE); }) CF_ADDTO(dynamic_attr, KRT_MTU { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_MTU); }) CF_ADDTO(dynamic_attr, KRT_WINDOW { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_WINDOW); }) diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 9bdcc0d2..1490213e 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -899,7 +899,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d r.r.rtm_family = BIRD_AF; r.r.rtm_dst_len = net->n.pxlen; r.r.rtm_protocol = RTPROT_BIRD; - r.r.rtm_scope = RT_SCOPE_UNIVERSE; + r.r.rtm_scope = RT_SCOPE_NOWHERE; nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix); /* @@ -928,6 +928,12 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d if (op == NL_OP_DELETE) goto dest; + /* Default scope is LINK for device routes, UNIVERSE otherwise */ + if (ea = ea_find(eattrs, EA_KRT_SCOPE)) + r.r.rtm_scope = ea->u.data; + else + r.r.rtm_scope = (dest == RTD_DEVICE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; + if (ea = ea_find(eattrs, EA_KRT_PREFSRC)) nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data); @@ -1135,6 +1141,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) u32 oif = ~0; u32 table; u32 priority = 0; + u32 def_scope = RT_SCOPE_UNIVERSE; int src; if (!(i = nl_checkin(h, sizeof(*i)))) @@ -1157,7 +1164,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } - if (a[RTA_DST]) { memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst)); @@ -1195,11 +1201,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) SKIP("strange class/scope\n"); - // ignore rtm_scope, it is not a real scope - // if (i->rtm_scope != RT_SCOPE_UNIVERSE) - // SKIP("scope %u\n", i->rtm_scope); - - switch (i->rtm_protocol) { case RTPROT_UNSPEC: @@ -1286,6 +1287,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) else { ra->dest = RTD_DEVICE; + def_scope = RT_SCOPE_LINK; } break; @@ -1304,6 +1306,19 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } + if (i->rtm_scope != def_scope) + { + ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + sizeof(eattr)); + ea->next = ra->eattrs; + ra->eattrs = ea; + ea->flags = EALF_SORTED; + ea->count = 1; + ea->attrs[0].id = EA_KRT_SCOPE; + ea->attrs[0].flags = 0; + ea->attrs[0].type = EAF_TYPE_INT; + ea->attrs[0].u.data = i->rtm_scope; + } + if (a[RTA_PREFSRC]) { ip_addr ps; @@ -1633,6 +1648,10 @@ krt_sys_get_attr(eattr *a, byte *buf, int buflen UNUSED) bsprintf(buf, "realm"); return GA_NAME; + case EA_KRT_SCOPE: + bsprintf(buf, "scope"); + return GA_NAME; + case EA_KRT_LOCK: buf += bsprintf(buf, "lock:"); ea_format_bitfield(a, buf, buflen, krt_metrics_names, 2, KRT_METRICS_MAX); -- cgit v1.2.3 From 768d5e1058693d2bfb7c3bcbe04306097c3246a0 Mon Sep 17 00:00:00 2001 From: Pavel Tvrdik Date: Tue, 20 Sep 2016 15:13:01 +0200 Subject: Add !~ operator to filter grammar --- conf/cf-lex.l | 1 + conf/confbase.Y | 2 +- doc/bird.sgml | 38 +++++++++++++++++++------------------- filter/config.Y | 1 + filter/filter.c | 10 ++++++++++ 5 files changed, 32 insertions(+), 20 deletions(-) (limited to 'doc') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 61ea4527..d2aa6402 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -246,6 +246,7 @@ else: { . \!\= return NEQ; +\!\~ return NMA; \<\= return LEQ; \>\= return GEQ; \&\& return AND; diff --git a/conf/confbase.Y b/conf/confbase.Y index 5f487c1d..c14c23c7 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -82,7 +82,7 @@ CF_DECLS %nonassoc PREFIX_DUMMY %left AND OR -%nonassoc '=' '<' '>' '~' GEQ LEQ NEQ PO PC +%nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC %left '+' '-' %left '*' '/' '%' %left '!' diff --git a/doc/bird.sgml b/doc/bird.sgml index af5b7980..07a2d470 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1016,9 +1016,9 @@ foot). of type @@ -1213,19 +1213,19 @@ foot).

The filter language supports common integer operators (+,-,*,/), parentheses There is one operator related to ROA infrastructure - ' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; } | term GEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $3; $$->a2.p = $1; } | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; } + | term NMA term { $$ = f_new_inst(); $$->code = P('!','~'); $$->a1.p = $1; $$->a2.p = $3; } | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; } | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; } diff --git a/filter/filter.c b/filter/filter.c index ccdfed36..2f5f00d8 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -716,6 +716,16 @@ interpret(struct f_inst *what) runtime( "~ applied on unknown type pair" ); res.val.i = !!res.val.i; break; + + case P('!','~'): + TWOARGS; + res.type = T_BOOL; + res.val.i = val_in_range(v1, v2); + if (res.val.i == CMP_ERROR) + runtime( "!~ applied on unknown type pair" ); + res.val.i = !res.val.i; + break; + case P('d','e'): ONEARG; res.type = T_BOOL; -- cgit v1.2.3 From 5bf35a9aee448ce7e3493ec7b80c84c8f5f39242 Mon Sep 17 00:00:00 2001 From: Pavel Tvrdik Date: Thu, 29 Sep 2016 13:28:18 +0200 Subject: Docs: fix BFD label BFD headline will appear in Table of Contents again. --- doc/bird.sgml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/bird.sgml b/doc/bird.sgml index 07a2d470..26673f03 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1506,7 +1506,8 @@ protocol babel { -