diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-12-12 00:05:49 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-12-12 00:05:49 +0100 |
commit | 66acbc8d7f80ce3c197549922b60fca093129047 (patch) | |
tree | d4cd38f5b8c2b1fcc4fd31020b43871a453345dc | |
parent | fa5c09a2e708ed505ca140531b98e695fdaf989c (diff) |
Revive FIB and kernel MPLS code
-rw-r--r-- | conf/confbase.Y | 11 | ||||
-rw-r--r-- | nest/config.Y | 1 | ||||
-rw-r--r-- | nest/rt-fib.c | 3 | ||||
-rw-r--r-- | sysdep/linux/netlink.c | 27 |
4 files changed, 30 insertions, 12 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y index 16330984..7e0537c5 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -83,7 +83,7 @@ CF_DECLS %type <time> expr_us time %type <a> ipa %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa -%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ +%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_mpls_ %type <mls> label_stack_start label_stack %type <t> text opttext @@ -96,7 +96,7 @@ CF_DECLS %left '!' %nonassoc '.' -CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN) +CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS) CF_GRAMMAR @@ -234,6 +234,12 @@ net_roa6_: net_ip6_ MAX NUM AS NUM cf_error("Invalid max prefix length %u", $3); }; +net_mpls_: MPLS NUM +{ + $$ = cfg_alloc(sizeof(net_addr_roa6)); + net_fill_mpls($$, $2); +} + net_ip_: net_ip4_ | net_ip6_ ; net_vpn_: net_vpn4_ | net_vpn6_ ; net_roa_: net_roa4_ | net_roa6_ ; @@ -243,6 +249,7 @@ net_: | net_vpn_ | net_roa_ | net_flow_ + | net_mpls_ ; diff --git a/nest/config.Y b/nest/config.Y index 432dd9c7..5c4f2393 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -140,6 +140,7 @@ net_type: | ROA6 { $$ = NET_ROA6; } | FLOW4{ $$ = NET_FLOW4; } | FLOW6{ $$ = NET_FLOW6; } + | MPLS { $$ = NET_MPLS; } ; CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6) diff --git a/nest/rt-fib.c b/nest/rt-fib.c index 45f47261..60c3da55 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -213,6 +213,7 @@ fib_hash(struct fib *f, const net_addr *a) case NET_ROA6: return FIB_HASH(f, a, roa6); case NET_FLOW4: return FIB_HASH(f, a, flow4); case NET_FLOW6: return FIB_HASH(f, a, flow6); + case NET_MPLS: return FIB_HASH(f, a, mpls); default: bug("invalid type"); } } @@ -249,6 +250,7 @@ fib_find(struct fib *f, const net_addr *a) case NET_ROA6: return FIB_FIND(f, a, roa6); case NET_FLOW4: return FIB_FIND(f, a, flow4); case NET_FLOW6: return FIB_FIND(f, a, flow6); + case NET_MPLS: return FIB_FIND(f, a, mpls); default: bug("invalid type"); } } @@ -268,6 +270,7 @@ fib_insert(struct fib *f, const net_addr *a, struct fib_node *e) case NET_ROA6: FIB_INSERT(f, a, e, roa6); return; case NET_FLOW4: FIB_INSERT(f, a, e, flow4); return; case NET_FLOW6: FIB_INSERT(f, a, e, flow6); return; + case NET_MPLS: FIB_INSERT(f, a, e, mpls); return; default: bug("invalid type"); } } diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 76ffe78b..bd3dbbd9 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -561,25 +561,20 @@ nl_add_attr_mpls_encap(struct nlmsghdr *h, uint bufsize, int len, u32 *stack) static inline void nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa) { - struct rtattr *nest = nl_open_attr(h, bufsize, RTA_VIA); - struct rtvia *via = RTA_DATA(nest); - - h->nlmsg_len += sizeof(*via); + struct rtvia *via = alloca(sizeof(struct rtvia) + 16); if (ipa_is_ip4(ipa)) { via->rtvia_family = AF_INET; put_ip4(via->rtvia_addr, ipa_to_ip4(ipa)); - h->nlmsg_len += sizeof(ip4_addr); + nl_add_attr(h, bufsize, RTA_VIA, via, sizeof(struct rtvia) + 4); } else { via->rtvia_family = AF_INET6; put_ip6(via->rtvia_addr, ipa_to_ip6(ipa)); - h->nlmsg_len += sizeof(ip6_addr); + nl_add_attr(h, bufsize, RTA_VIA, via, sizeof(struct rtvia) + 16); } - - nl_close_attr(h, nest); } #endif @@ -1228,8 +1223,16 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d #ifdef HAVE_MPLS_KERNEL if (p->af == AF_MPLS) { + /* + * Kernel MPLS code is a bit picky. We must: + * 1) Always set RT_SCOPE_UNIVERSE and RTN_UNICAST (even for RTM_DELROUTE) + * 2) Never use RTA_PRIORITY + */ + u32 label = net_mpls(net->n.addr); nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label); + r->r.rtm_scope = RT_SCOPE_UNIVERSE; + r->r.rtm_type = RTN_UNICAST; } else #endif @@ -1247,7 +1250,9 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d else nl_add_attr_u32(&r->h, rsize, RTA_TABLE, krt_table_id(p)); - if (a->source == RTS_DUMMY) + if (p->af == AF_MPLS) + priority = 0; + else if (a->source == RTS_DUMMY) priority = e->u.krt.metric; else if (KRT_CF->sys.metric) priority = KRT_CF->sys.metric; @@ -1262,7 +1267,9 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d goto dest; /* Default scope is LINK for device routes, UNIVERSE otherwise */ - if (ea = ea_find(eattrs, EA_KRT_SCOPE)) + if (p->af == AF_MPLS) + r->r.rtm_scope = RT_SCOPE_UNIVERSE; + else if (ea = ea_find(eattrs, EA_KRT_SCOPE)) r->r.rtm_scope = ea->u.data; else r->r.rtm_scope = (dest == RTD_UNICAST && ipa_zero(nh->gw)) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; |