]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Revive FIB and kernel MPLS code
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 11 Dec 2017 23:05:49 +0000 (00:05 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 11 Dec 2017 23:05:49 +0000 (00:05 +0100)
conf/confbase.Y
nest/config.Y
nest/rt-fib.c
sysdep/linux/netlink.c

index 16330984aa164b1d446e8a2b8b4264036f9b1865..7e0537c5b8398131c05193979315ae20ae8c7967 100644 (file)
@@ -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_
  ;
 
 
index 432dd9c75f940b92d01fba3b9ff60cddf33a85e5..5c4f239384af3f9b3cf984f3816b27a0b9cf9842 100644 (file)
@@ -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)
index 45f472610647b3012750e8af14a997848ebf0a4d..60c3da555e9cc8f5a54752eeb6ee114c397e0ec5 100644 (file)
@@ -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");
   }
 }
index 76ffe78b31fbe1e2c67db15118535acabafbaae1..bd3dbbd9a7b50c9e3e0f85a70f5effafbade6d2f 100644 (file)
@@ -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;