From f2010f9c65ca69584c34c762fb3e5e957958478e Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Mon, 13 Jun 2016 15:49:53 +0200 Subject: Static: Protocol rework wrt. struct nexthop changes; MPLS label support --- doc/bird.sgml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'doc/bird.sgml') diff --git a/doc/bird.sgml b/doc/bird.sgml index 999fa294..23026eae 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -4141,8 +4141,8 @@ specific destination for them and you don't want to send them out through the default route to prevent routing loops).

There are five types of static routes: `classical' routes telling to forward -packets to a neighboring router, multipath routes specifying several (possibly -weighted) neighboring routers, device routes specifying forwarding to hosts on a +packets to a neighboring router (single path or multipath, possibly weighted), +device routes specifying forwarding to hosts on a directly connected network, recursive routes computing their nexthops by doing route table lookups for a given IP, and special routes (sink, blackhole etc.) which specify a special action to be done instead of forwarding the packet. @@ -4174,14 +4174,14 @@ definition of the protocol contains mainly a list of static routes.

Route definitions (each may also contain a block of per-route options): -

There are five types of static routes: `classical' routes telling to forward +

There are four types of static routes: `classical' routes telling to forward packets to a neighboring router (single path or multipath, possibly weighted), -device routes specifying forwarding to hosts on a -directly connected network, recursive routes computing their nexthops by doing -route table lookups for a given IP, and special routes (sink, blackhole etc.) -which specify a special action to be done instead of forwarding the packet. +device routes specifying forwarding to hosts on a directly connected network, +recursive routes computing their nexthops by doing route table lookups for a +given IP, and special routes (sink, blackhole etc.) which specify a special +action to be done instead of forwarding the packet.

When the particular destination is not available (the interface is down or the next hop of the route is not a neighbor at the moment), Static just diff --git a/filter/filter.h b/filter/filter.h index 0482b83b..855219ec 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -174,9 +174,9 @@ void val_format(struct f_val v, buffer *buf); #define SA_PROTO 4 #define SA_SOURCE 5 #define SA_SCOPE 6 -#define SA_DEST 8 -#define SA_IFNAME 9 -#define SA_IFINDEX 10 +#define SA_DEST 7 +#define SA_IFNAME 8 +#define SA_IFINDEX 9 struct f_tree { diff --git a/lib/alloca.h b/lib/alloca.h index f0d61bb4..e5557cdb 100644 --- a/lib/alloca.h +++ b/lib/alloca.h @@ -15,4 +15,6 @@ #include #endif +#define allocz(len) ({ void *_x = alloca(len); memset(_x, 0, len); _x; }) + #endif diff --git a/lib/net.c b/lib/net.c index e46be8b2..74cea277 100644 --- a/lib/net.c +++ b/lib/net.c @@ -69,21 +69,20 @@ net_format(const net_addr *N, char *buf, int buflen) case NET_VPN4: switch (n->vpn4.rd >> 48) { - case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); - case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); - case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); + case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); + case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); + case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); + default: return bsnprintf(buf, buflen, "X:%08x:%08x %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); } - return bsnprintf(buf, buflen, "X: %016x %I4/%d", (n->vpn4.rd), n->vpn4.prefix, n->vpn4.pxlen); - - /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4. */ case NET_VPN6: + /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4 */ switch (n->vpn6.rd >> 48) { - case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); - case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); - case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); + case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); + case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); + case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); + default: return bsnprintf(buf, buflen, "X:%08x:%08x %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); } - return bsnprintf(buf, buflen, "X: %016x %I6/%d", (n->vpn6.rd), n->vpn6.prefix, n->vpn6.pxlen); case NET_ROA4: return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn); case NET_ROA6: diff --git a/lib/net.h b/lib/net.h index 7c124fc0..7144bcb9 100644 --- a/lib/net.h +++ b/lib/net.h @@ -306,6 +306,9 @@ static inline int net_equal_flow4(const net_addr_flow4 *a, const net_addr_flow4 static inline int net_equal_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b) { return net_equal((const net_addr *) a, (const net_addr *) b); } +static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b) +{ return !memcmp(a, b, sizeof(net_addr_mpls)); } + static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b) { return ip4_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } @@ -313,8 +316,6 @@ static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_r static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b) { return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } -static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b) -{ return !memcmp(a, b, sizeof(net_addr_mpls)); } static inline int net_zero_ip4(const net_addr_ip4 *a) { return !a->pxlen && ip4_zero(a->prefix); } @@ -404,16 +405,17 @@ static inline void net_copy_flow6(net_addr_flow6 *dst, const net_addr_flow6 *src static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src) { memcpy(dst, src, sizeof(net_addr_mpls)); } + +/* XXXX */ +static inline u32 u64_hash(u64 a) +{ return u32_hash(a); } + static inline u32 net_hash_ip4(const net_addr_ip4 *n) { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } static inline u32 net_hash_ip6(const net_addr_ip6 *n) { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } -/* XXXX */ -static inline u32 u64_hash(u64 a) -{ return u32_hash(a); } - static inline u32 net_hash_vpn4(const net_addr_vpn4 *n) { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } @@ -452,7 +454,7 @@ static inline int net_validate_ip6(const net_addr_ip6 *n) static inline int net_validate_mpls(const net_addr_mpls *n) { - return n->label < (1<<20); + return n->label < (1 << 20); } int net_validate(const net_addr *N); diff --git a/nest/route.h b/nest/route.h index eb98b609..1e0a14bc 100644 --- a/nest/route.h +++ b/nest/route.h @@ -390,11 +390,11 @@ typedef struct rta { #define RTC_MULTICAST 2 #define RTC_ANYCAST 3 /* IPv6 Anycast */ -#define RTD_UNICAST 0 /* Next hop is neighbor router */ +#define RTD_NONE 0 /* Undefined next hop */ +#define RTD_UNICAST 1 /* Next hop is neighbor router */ #define RTD_BLACKHOLE 2 /* Silently drop packets */ #define RTD_UNREACHABLE 3 /* Reject as unreachable */ #define RTD_PROHIBIT 4 /* Administratively prohibited */ -#define RTD_NONE 6 /* Invalid RTD */ /* Flags for net->n.flags, used by kernel syncer */ #define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */ @@ -408,7 +408,7 @@ typedef struct rta { /* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */ static inline int rte_is_reachable(rte *r) -{ uint d = r->attrs->dest; return (d == RTD_UNICAST); } +{ return r->attrs->dest == RTD_UNICAST; } /* @@ -523,7 +523,7 @@ static inline int nexthop_same(struct nexthop *x, struct nexthop *y) struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp); static inline void nexthop_link(struct rta *a, struct nexthop *from) { memcpy(&a->nh, from, nexthop_size(from)); } -void nexthop_insert(struct nexthop *n, struct nexthop *y); +void nexthop_insert(struct nexthop **n, struct nexthop *y); int nexthop_is_sorted(struct nexthop *x); void rta_init(void); diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 120a8e24..afc97e22 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -150,7 +150,8 @@ nexthop_hash(struct nexthop *x) for (; x; x = x->next) { h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9); - for (int i=0; ilabels; i++) + + for (int i = 0; i < x->labels; i++) h ^= x->label[i] ^ (h << 6) ^ (h >> 7); } @@ -164,12 +165,13 @@ nexthop__same(struct nexthop *x, struct nexthop *y) { if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels)) return 0; - for (int i=0; ilabels; i++) + + for (int i = 0; i < x->labels; i++) if (x->label[i] != y->label[i]) return 0; } - return 1; + return x == y; } static int @@ -195,7 +197,7 @@ nexthop_compare_node(struct nexthop *x, struct nexthop *y) if (r) return r; - for (int i=0; ilabels; i++) + for (int i = 0; i < y->labels; i++) { r = ((int) y->label[i]) - ((int) x->label[i]); if (r) @@ -271,34 +273,22 @@ nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, lin } void -nexthop_insert(struct nexthop *n, struct nexthop *x) +nexthop_insert(struct nexthop **n, struct nexthop *x) { - struct nexthop tmp; - memcpy(&tmp, n, sizeof(struct nexthop)); - if (nexthop_compare_node(n, x) > 0) /* Insert to the included nexthop */ - { - memcpy(n, x, sizeof(struct nexthop)); - memcpy(x, &tmp, sizeof(struct nexthop)); - n->next = x; - return; - } - - for (struct nexthop **nn = &(n->next); *nn; nn = &((*nn)->next)) + for (; *n; n = &((*n)->next)) { - int cmp = nexthop_compare_node(*nn, x); + int cmp = nexthop_compare_node(*n, x); if (cmp < 0) continue; - - if (cmp > 0) - { - x->next = *nn; - *nn = x; - } - - return; + else if (cmp > 0) + break; + else + return; } + x->next = *n; + *n = x; } int @@ -314,7 +304,7 @@ nexthop_is_sorted(struct nexthop *x) static inline slab * nexthop_slab(struct nexthop *nh) { - return nexthop_slab_[nh->labels > 2 ? 3 : nh->labels]; + return nexthop_slab_[MIN(nh->labels, 3)]; } static struct nexthop * diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 5edd1c5d..9993da24 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -79,9 +79,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad) .source = RTS_DEVICE, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, - .nh = { - .iface = ad->iface - } + .nh.iface = ad->iface, }; a = rta_lookup(&a0); diff --git a/nest/rt-table.c b/nest/rt-table.c index ef402f28..a33b7909 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1768,7 +1768,6 @@ static inline void rta_apply_hostentry(rta *a, struct hostentry *he) { a->hostentry = he; - a->dest = he->dest; a->igp_metric = he->igp_metric; @@ -1810,14 +1809,14 @@ rta_apply_hostentry(rta *a, struct hostentry *he) static inline rte * rt_next_hop_update_rte(rtable *tab UNUSED, rte *old) { - rta *ap = alloca(RTA_MAX_SIZE); - memcpy(ap, old->attrs, rta_size(old->attrs)); - rta_apply_hostentry(ap, old->attrs->hostentry); - ap->aflags = 0; + rta *a = alloca(RTA_MAX_SIZE); + memcpy(a, old->attrs, rta_size(old->attrs)); + rta_apply_hostentry(a, old->attrs->hostentry); + a->aflags = 0; rte *e = sl_alloc(rte_slab); memcpy(e, old, sizeof(rte)); - e->attrs = rta_lookup(ap); + e->attrs = rta_lookup(a); return e; } @@ -2373,7 +2372,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) } if ((a->dest == RTD_UNICAST) && ipa_zero(a->nh.gw) && !a->next) - { /* We have singlepath device route */ + { + /* We have singlepath device route */ if (if_local_addr(he->addr, a->nh.iface)) { /* The host address is a local address, this is not valid */ @@ -2389,7 +2389,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) else { /* The host is reachable through some route entry */ - he->nh = (&a->nh); + he->nh = &(a->nh); he->dest = a->dest; } diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 11666f30..1b124a17 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1461,8 +1461,7 @@ bgp_get_neighbor(rte *r) static inline int rte_resolvable(rte *rt) { - int rd = rt->attrs->dest; - return (rd == RTD_UNICAST); + return rt->attrs->dest == RTD_UNICAST; } int diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 9c59e6d8..9380f999 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -700,9 +700,7 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll) WITHDRAW(BAD_NEXT_HOP); a->dest = RTD_UNICAST; - a->nh.gw = nbr->addr; - a->nh.iface = nbr->iface; - a->nh.next = NULL; + a->nh = (struct nexthop){ .gw = nbr->addr, .iface = nbr->iface }; a->hostentry = NULL; a->igp_metric = 0; } @@ -749,8 +747,8 @@ bgp_use_gateway(struct bgp_export_state *s) if (s->channel->cf->next_hop_self) return 0; - /* We need valid global gateway */ - if ((ra->dest != RTD_UNICAST) || (ra->nh.next) || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw)) + /* We need one valid global gateway */ + if ((ra->dest != RTD_UNICAST) || ra->nh.next || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw)) return 0; /* Use it when exported to internal peers */ @@ -1434,12 +1432,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis if (ea) { - a = alloca(sizeof(struct rta)); - memset(a, 0, sizeof(struct rta)); + a = allocz(sizeof(struct rta)); a->source = RTS_BGP; a->scope = SCOPE_UNIVERSE; - a->dest = RTD_UNREACHABLE; a->from = s->proto->cf->remote_ip; a->eattrs = ea; diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 74f47810..1b0ac5e9 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -36,11 +36,9 @@ unresolved_vlink(ort *ort) static inline struct nexthop * new_nexthop(struct ospf_proto *p, ip_addr gw, struct iface *iface, byte weight) { - struct nexthop *nh = lp_alloc(p->nhpool, sizeof(struct nexthop)); - nh->labels = 0; + struct nexthop *nh = lp_allocz(p->nhpool, sizeof(struct nexthop)); nh->gw = gw; nh->iface = iface; - nh->next = NULL; nh->weight = weight; return nh; } @@ -1907,7 +1905,6 @@ ort_changed(ort *nf, rta *nr) (nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) || (nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid) || (nr->source != or->source) || (nr->dest != or->dest) || - (nr->nh.iface != or->nh.iface) || !ipa_equal(nr->nh.gw, or->nh.gw) || !nexthop_same(&(nr->nh), &(or->nh)); } @@ -1952,11 +1949,10 @@ again1: .src = p->p.main_source, .source = nf->n.type, .scope = SCOPE_UNIVERSE, + .dest = RTD_UNICAST, + .nh = *(nf->n.nhs), }; - nexthop_link(&a0, nf->n.nhs); - a0.dest = RTD_UNICAST; - if (reload || ort_changed(nf, &a0)) { rta *a = rta_lookup(&a0); diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index a4d371fe..310f3c01 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -43,8 +43,6 @@ #include "pipe.h" -#include - static void pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs) { diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 9bed9249..157093aa 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -147,20 +147,16 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) .src = p->p.main_source, .source = RTS_RIP, .scope = SCOPE_UNIVERSE, + .dest = RTD_UNICAST, }; u8 rt_metric = rt->metric; u16 rt_tag = rt->tag; - struct rip_rte *rt2 = rt->next; - /* Find second valid rte */ - while (rt2 && !rip_valid_rte(rt2)) - rt2 = rt2->next; - - a0.dest = RTD_UNICAST; - if (p->ecmp && rt2) + if (p->ecmp) { /* ECMP route */ + struct nexthop *nhs = NULL; int num = 0; for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next) @@ -168,28 +164,27 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) if (!rip_valid_rte(rt)) continue; - struct nexthop *nh = (a0.nh.next ? &(a0.nh) : alloca(sizeof(struct nexthop))); + struct nexthop *nh = allocz(sizeof(struct nexthop)); nh->gw = rt->next_hop; nh->iface = rt->from->nbr->iface; nh->weight = rt->from->ifa->cf->ecmp_weight; - if (a0.nh.next) - nexthop_insert(&(a0.nh), nh); - + nexthop_insert(&nhs, nh); num++; if (rt->tag != rt_tag) rt_tag = 0; } + + a0.nh = *nhs; } else { /* Unipath route */ - a0.nh.next = NULL; + a0.from = rt->from->nbr->addr; a0.nh.gw = rt->next_hop; a0.nh.iface = rt->from->nbr->iface; - a0.from = rt->from->nbr->addr; } rta *a = rta_lookup(&a0); diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 81268e83..497edd3c 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -124,7 +124,7 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_ .src = p->p.main_source, .source = RTS_RPKI, .scope = SCOPE_UNIVERSE, - .dest = RTD_BLACKHOLE, + .dest = RTD_NONE, }; rta *a = rta_lookup(&a0); diff --git a/proto/static/config.Y b/proto/static/config.Y index 2fb54448..16c276ce 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -13,9 +13,33 @@ CF_HDR CF_DEFINES #define STATIC_CFG ((struct static_config *) this_proto) -static struct static_route *this_srt, *last_srt; +static struct static_route *this_srt, *this_snh; static struct f_inst **this_srt_last_cmd; +static struct static_route * +static_nexthop_new(void) +{ + struct static_route *nh; + + if (!this_snh) + { + /* First next hop */ + nh = this_srt; + rem_node(&this_srt->n); + } + else + { + /* Additional next hop */ + nh = cfg_allocz(sizeof(struct static_route)); + nh->net = this_srt->net; + this_snh->mp_next = nh; + } + + nh->dest = RTD_UNICAST; + nh->mp_head = this_srt; + return nh; +}; + static void static_route_finish(void) { } @@ -45,48 +69,35 @@ static_proto: | static_proto stat_route stat_route_opt_list ';' { static_route_finish(); } ; -stat_nexthop_via: VIA -{ - if (last_srt) - { - last_srt = (last_srt->mp_next = cfg_allocz(sizeof(struct static_route))); - last_srt->net = this_srt->net; - } - else - { - last_srt = this_srt; - rem_node(&this_srt->n); - } - - last_srt->mp_head = this_srt; - last_srt->dest = RTD_UNICAST; -}; - -stat_nexthop_ident: - stat_nexthop_via ipa ipa_scope { - last_srt->via = $2; - last_srt->iface = $3; - add_tail(&STATIC_CFG->neigh_routes, &last_srt->n); +stat_nexthop: + VIA ipa ipa_scope { + this_snh = static_nexthop_new(); + this_snh->via = $2; + this_snh->iface = $3; + add_tail(&STATIC_CFG->neigh_routes, &this_snh->n); } - | stat_nexthop_via TEXT { - last_srt->via = IPA_NONE; - last_srt->if_name = $2; - add_tail(&STATIC_CFG->iface_routes, &last_srt->n); + | VIA TEXT { + this_snh = static_nexthop_new(); + this_snh->via = IPA_NONE; + this_snh->if_name = $2; + add_tail(&STATIC_CFG->iface_routes, &this_snh->n); } - | stat_nexthop_ident MPLS label_stack { - last_srt->label_count = $3[0]; - last_srt->label_stack = &($3[1]); + | stat_nexthop MPLS label_stack { + this_snh->label_count = $3[0]; + this_snh->label_stack = &($3[1]); } - | stat_nexthop_ident WEIGHT expr { - last_srt->weight = $3 - 1; + | stat_nexthop WEIGHT expr { + this_snh->weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256"); } - | stat_nexthop_ident BFD bool { last_srt->use_bfd = $3; cf_check_bfd($3); } + | stat_nexthop BFD bool { + this_snh->use_bfd = $3; cf_check_bfd($3); + } ; -stat_nexthop: - stat_nexthop_ident - | stat_nexthop stat_nexthop_ident +stat_nexthops: + stat_nexthop + | stat_nexthops stat_nexthop ; stat_route0: ROUTE net_any { @@ -95,12 +106,12 @@ stat_route0: ROUTE net_any { this_srt->net = $2; this_srt_last_cmd = &(this_srt->cmds); this_srt->mp_next = NULL; - last_srt = NULL; + this_snh = NULL; } ; stat_route: - stat_route0 stat_nexthop + stat_route0 stat_nexthops | stat_route0 RECURSIVE ipa { this_srt->dest = RTDX_RECURSIVE; this_srt->via = $3; diff --git a/proto/static/static.c b/proto/static/static.c index 3e03708c..e5251bf6 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -60,54 +60,44 @@ p_igp_table(struct proto *p) static void static_install(struct proto *p, struct static_route *r) { - rta *ap = alloca(RTA_MAX_SIZE); + rta *ap = allocz(RTA_MAX_SIZE); rte *e; if (!(r->state & STS_WANT) && (r->state & (STS_INSTALLED | STS_FORCE)) && r->dest != RTD_UNICAST) goto drop; DBG("Installing static route %N, rtd=%d\n", r->net, r->dest); - bzero(ap, RTA_MAX_SIZE); ap->src = p->main_source; - ap->source = ((r->dest == RTD_UNICAST) && ipa_zero(r->via)) ? RTS_STATIC_DEVICE : RTS_STATIC; + ap->source = RTS_STATIC; ap->scope = SCOPE_UNIVERSE; ap->dest = r->dest; if (r->dest == RTD_UNICAST) { + struct nexthop *nhs = NULL; struct static_route *r2; - int num = 0, update = 0; + int update = 0; + r = r->mp_head; for (r2 = r; r2; r2 = r2->mp_next) { - if ((r2->state & STS_FORCE) || (!!(r2->state & STS_INSTALLED) != !!(r2->state & STS_WANT))) update++; if (r2->state & STS_WANT) - { - struct nexthop *nh = (ap->nh.next) ? alloca(NEXTHOP_MAX_SIZE) : &(ap->nh); - if (ipa_zero(r2->via)) // Device nexthop - { - nh->gw = IPA_NONE; - nh->iface = r2->iface; - } - else // Router nexthop - { - nh->gw = r2->via; - nh->iface = r2->neigh->iface; - } - nh->weight = r2->weight; - nh->labels = r2->label_count; - for (int i=0; ilabels; i++) - nh->label[i] = r2->label_stack[i]; - - if (ap->nh.next) - nexthop_insert(&(ap->nh), nh); - r2->state |= STS_INSTALLED; - num++; - } + { + struct nexthop *nh = allocz(NEXTHOP_MAX_SIZE); + + nh->gw = r2->via; + nh->iface = r2->neigh ? r2->neigh->iface : r2->iface; + nh->weight = r2->weight; + nh->labels = r2->label_count; + memcpy(nh->label, r2->label_stack, r2->label_count * sizeof(u32)); + + r2->state |= STS_INSTALLED; + nexthop_insert(&nhs, nh); + } else r2->state = 0; } @@ -115,18 +105,19 @@ static_install(struct proto *p, struct static_route *r) if (!update) // Nothing changed return; - r = r->mp_head; - - if (!num) // No nexthop to install + if (!nhs) // No nexthop to install { drop: rte_update(p, r->net, NULL); return; } + + ap->dest = RTD_UNICAST; + nexthop_link(ap, nhs); } else r->state |= STS_INSTALLED; - + if (r->dest == RTDX_RECURSIVE) { ap->nh.labels_append = ap->nh.labels = r->label_count; diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 2e0f194b..c65cba65 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -193,7 +193,6 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) struct ks_msg msg; char *body = (char *)msg.buf; sockaddr gate, mask, dst; - ip_addr gw; DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw); @@ -223,14 +222,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) msg.rtm.rtm_flags |= RTF_BLACKHOLE; #endif - /* This is really very nasty, but I'm not able - * to add "(reject|blackhole)" route without - * gateway set + /* + * This is really very nasty, but I'm not able to add reject/blackhole route + * without gateway address. */ - if(!i) + if (!i) { - i = HEAD(iface_list); - WALK_LIST(j, iface_list) { if (j->flags & IF_LOOPBACK) @@ -239,13 +236,13 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) break; } } - } - gw = a->nh.gw; - - /* Embed interface ID to link-local address */ - if (ipa_is_link_local(gw)) - _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); + if (!i) + { + log(L_ERR "KRT: Cannot find loopback iface"); + return -1; + } + } int af = AF_UNSPEC; @@ -261,45 +258,51 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) return -1; } - sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0); sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0); - sockaddr_fill(&gate, af, gw, NULL, 0); switch (a->dest) { - case RTD_UNICAST: - if (ipa_zero(gw)) - { - if(i) - { -#ifdef RTF_CLONING - if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ - msg.rtm.rtm_flags |= RTF_CLONING; -#endif + case RTD_UNICAST: + if (ipa_nonzero(a->nh.gw)) + { + ip_addr gw = a->nh.gw; - if(!i->addr) { - log(L_ERR "KRT: interface %s has no IP addess", i->name); - return -1; - } - - sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); - msg.rtm.rtm_addrs |= RTA_GATEWAY; - } - } else { - msg.rtm.rtm_flags |= RTF_GATEWAY; - msg.rtm.rtm_addrs |= RTA_GATEWAY; - } + /* Embed interface ID to link-local address */ + if (ipa_is_link_local(gw)) + _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); + + sockaddr_fill(&gate, af, gw, NULL, 0); + msg.rtm.rtm_flags |= RTF_GATEWAY; + msg.rtm.rtm_addrs |= RTA_GATEWAY; break; + } #ifdef RTF_REJECT - case RTD_UNREACHABLE: + case RTD_UNREACHABLE: #endif #ifdef RTF_BLACKHOLE - case RTD_BLACKHOLE: + case RTD_BLACKHOLE: #endif - default: - bug("krt-sock: unknown flags, but not filtered"); + { + /* Fallback for all other valid cases */ + if (!i->addr) + { + log(L_ERR "KRT: interface %s has no IP addess", i->name); + return -1; + } + +#ifdef RTF_CLONING + if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ + msg.rtm.rtm_flags |= RTF_CLONING; +#endif + + sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); + msg.rtm.rtm_addrs |= RTA_GATEWAY; + } + + default: + bug("krt-sock: unknown flags, but not filtered"); } msg.rtm.rtm_index = i->index; @@ -497,7 +500,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) } a.dest = RTD_UNICAST; - a.nh.next = NULL; if (flags & RTF_GATEWAY) { neighbor *ng; @@ -520,8 +522,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) return; } } - else - a.nh.gw = IPA_NONE; done: e = rte_get_temp(&a); diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 23431172..80439c47 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -320,6 +320,7 @@ static struct nl_want_attrs ifa_attr_want4[BIRD_IFA_MAX] = { [IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) }, [IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) }, [IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) }, + [IFA_FLAGS] = { 1, 1, sizeof(u32) }, }; static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = { @@ -543,18 +544,17 @@ nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa) h->nlmsg_len += sizeof(*via); - if (ipa_is_ip4(ipa)) { - ip4_addr ip4 = ipa_to_ip4(ipa); - ip4 = ip4_hton(ip4); + if (ipa_is_ip4(ipa)) + { via->rtvia_family = AF_INET; - memcpy(via->rtvia_addr, &ip4, sizeof(ip4)); - h->nlmsg_len += sizeof(ip4); - } else { - ip6_addr ip6 = ipa_to_ip6(ipa); - ip6 = ip6_hton(ip6); + put_ip4(via->rtvia_addr, ipa_to_ip4(ipa)); + h->nlmsg_len += sizeof(ip4_addr); + } + else + { via->rtvia_family = AF_INET6; - memcpy(via->rtvia_addr, &ip6, sizeof(ip6)); - h->nlmsg_len += sizeof(ip6); + put_ip6(via->rtvia_addr, ipa_to_ip6(ipa)); + h->nlmsg_len += sizeof(ip6_addr); } nl_close_attr(h, nest); @@ -669,6 +669,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra) } else rv->gw = IPA_NONE; + if (a[RTA_ENCAP_TYPE]) { if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) { @@ -1092,20 +1093,16 @@ krt_capable(rte *e) rta *a = e->attrs; switch (a->dest) - { + { case RTD_UNICAST: - for (struct nexthop *nh = &(a->nh); nh; nh = nh->next) - if (nh->iface) - return 1; - return 0; case RTD_BLACKHOLE: case RTD_UNREACHABLE: case RTD_PROHIBIT: - break; + return 1; + default: return 0; - } - return 1; + } } static inline int @@ -1210,7 +1207,6 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d dest: - /* a->iface != NULL checked in krt_capable() for router and device routes */ switch (dest) { case RTD_UNICAST: @@ -1502,6 +1498,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) switch (i->rtm_type) { case RTN_UNICAST: + ra->dest = RTD_UNICAST; if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET)) { @@ -1512,7 +1509,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } - nexthop_link(ra, nh); + ra->nh = *nh; break; } @@ -1698,9 +1695,20 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) else { /* Merge next hops with the stored route */ - rta *a = s->attrs; + rta *oa = s->attrs; - nexthop_insert(&a->nh, &ra->nh); + struct nexthop *nhs = &oa->nh; + nexthop_insert(&nhs, &ra->nh); + + /* Perhaps new nexthop is inserted at the first position */ + if (nhs == &ra->nh) + { + /* Swap rtas */ + s->attrs = ra; + + /* Keep old eattrs */ + ra->eattrs = oa->eattrs; + } } } diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index c273cb10..c6ff6275 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -984,7 +984,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs) static int krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) { - struct krt_proto *p = (struct krt_proto *) P; + // struct krt_proto *p = (struct krt_proto *) P; rte *e = *new; if (e->attrs->src->proto == P) @@ -1005,17 +1005,6 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li return -1; } - if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE)) - { - struct nexthop *nh = &(e->attrs->nh); - for (; nh; nh = nh->next) - if (ipa_nonzero(nh->gw)) - break; - - if (!nh) /* Gone through all the nexthops and no explicit GW found */ - return -1; - } - if (!krt_capable(e)) return -1; -- cgit v1.2.3 From 8c9986d310c58b26c000375be00be0deb9c2e360 Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Mon, 13 Mar 2017 13:50:32 +0100 Subject: Filters: VPN Route Distinguishers, Prefix Type, Docs Update --- doc/Makefile | 4 ++-- doc/bird.sgml | 24 +++++++++++++++++++++--- filter/config.Y | 6 +++++- filter/filter.c | 27 +++++++++++++++++++++++++++ filter/filter.h | 3 +++ filter/test.conf | 36 +++++++++++++++++++++++++++++++++--- lib/net.c | 30 +++++++++++++++++++----------- lib/net.h | 17 ++++++++++++++++- nest/config.Y | 2 ++ 9 files changed, 128 insertions(+), 21 deletions(-) (limited to 'doc/bird.sgml') diff --git a/doc/Makefile b/doc/Makefile index 4e7e91eb..f36642be 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -36,8 +36,8 @@ $(o)%.ps: $(o)%.dvi dvips -D600 -ta4 -o $@ $< $(o)%.pdf: $(o)%.tex - pdflatex -output-directory=$(dir $@) $< - pdflatex -output-directory=$(dir $@) $< + TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex pdflatex -output-directory=$(dir $@) $< + TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex pdflatex -output-directory=$(dir $@) $< $(o)%.txt: $(o)%.sgml cd $(dir $@) && $(sgml2)txt $(notdir $<) diff --git a/doc/bird.sgml b/doc/bird.sgml index 2f8f18f3..e85ebf18 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1193,13 +1193,31 @@ foot).