]> git.puffer.fish Git - mirror/frr.git/commitdiff
Zebra: Fix handling of larger table-ids
authorvivek <vivek@cumulusnetworks.com>
Fri, 25 Mar 2016 05:01:11 +0000 (22:01 -0700)
committervivek <vivek@cumulusnetworks.com>
Fri, 25 Mar 2016 05:38:40 +0000 (22:38 -0700)
Zebra code was not handling larger table-ids correctly. There were 2 issues:

a) In the netlink interface, RTA_TABLE was never sent or processed. This
pretty much limited the table-ids that zebra could understand to < 255.

b) In the interface into the zebra RIB (in particular for protocols), there
were some incorrect checks that again assumed the table id should be < 252
or be "main". This is valid only for the Default VRF (for now), for other
VRFs, the table-id should be the value learnt from the kernel.

These two issues are addressed with this change.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Ticket: CM-10087, CM-10091
Reviewed By: CCR-4359
Testing Done: Manual

zebra/rt_netlink.c
zebra/zebra_rib.c

index ffab76bbe625a514653138f199fc67cab27dbc8b..b95ef8462b80fd98b2822f3ca8c050967b257804 100644 (file)
@@ -850,12 +850,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
   if (rtm->rtm_type != RTN_UNICAST)
     return 0;
 
-  table = rtm->rtm_table;
-  if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table))
-      return 0;
-
-  vrf_id = vrf_lookup_by_table(table);
-
   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
   if (len < 0)
     return -1;
@@ -873,6 +867,21 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
   if (rtm->rtm_src_len != 0)
     return 0;
 
+  /* Table corresponding to route. */
+  if (tb[RTA_TABLE])
+    table = *(int *) RTA_DATA (tb[RTA_TABLE]);
+  else
+    table = rtm->rtm_table;
+
+  /* Map to VRF */
+  vrf_id = vrf_lookup_by_table(table);
+  if (vrf_id == VRF_DEFAULT)
+    {
+      if (!is_zebra_valid_kernel_table(table) &&
+          !is_zebra_main_routing_table(table))
+        return 0;
+    }
+
   /* Route which inserted by Zebra. */
   if (rtm->rtm_protocol == RTPROT_ZEBRA)
     flags |= ZEBRA_FLAG_SELFROUTE;
@@ -1045,12 +1054,6 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
       return 0;
     }
 
-  table = rtm->rtm_table;
-  if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table))
-      return 0;
-
-  vrf_id = vrf_lookup_by_table(table);
   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
   if (len < 0)
     return -1;
@@ -1076,6 +1079,21 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
       return 0;
     }
 
+  /* Table corresponding to route. */
+  if (tb[RTA_TABLE])
+    table = *(int *) RTA_DATA (tb[RTA_TABLE]);
+  else
+    table = rtm->rtm_table;
+
+  /* Map to VRF */
+  vrf_id = vrf_lookup_by_table(table);
+  if (vrf_id == VRF_DEFAULT)
+    {
+      if (!is_zebra_valid_kernel_table(table) &&
+          !is_zebra_main_routing_table(table))
+        return 0;
+    }
+
   index = 0;
   metric = 0;
   dest = NULL;
@@ -1654,7 +1672,6 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate,
   req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
   req.n.nlmsg_type = cmd;
   req.r.rtm_family = family;
-  req.r.rtm_table = table;
   req.r.rtm_dst_len = length;
   req.r.rtm_protocol = RTPROT_ZEBRA;
   req.r.rtm_scope = RT_SCOPE_UNIVERSE;
@@ -1687,6 +1704,15 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate,
   if (dest)
     addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
 
+  /* Table corresponding to this route. */
+  if (table < 256)
+    req.r.rtm_table = table;
+  else
+    {
+      req.r.rtm_table = RT_TABLE_UNSPEC;
+      addattr32(&req.n, sizeof req, RTA_TABLE, table);
+    }
+
   if (!discard)
     {
       if (gate)
@@ -2071,7 +2097,6 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
     req.n.nlmsg_flags |= NLM_F_REPLACE;
   req.n.nlmsg_type = cmd;
   req.r.rtm_family = family;
-  req.r.rtm_table = rib->table;
   req.r.rtm_dst_len = p->prefixlen;
   req.r.rtm_protocol = RTPROT_ZEBRA;
   req.r.rtm_scope = RT_SCOPE_UNIVERSE;
@@ -2105,6 +2130,15 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
    */
   addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
 
+  /* Table corresponding to this route. */
+  if (rib->table < 256)
+    req.r.rtm_table = rib->table;
+  else
+    {
+      req.r.rtm_table = RT_TABLE_UNSPEC;
+      addattr32(&req.n, sizeof req, RTA_TABLE, rib->table);
+    }
+
   if (discard)
     {
       if (cmd == RTM_NEWROUTE)
index 9679afe068e76e513010b1919668c55a973f28fc..8a57473e6369d9d857f8d1bb364b4426fbaf30c1 100644 (file)
@@ -2002,6 +2002,32 @@ rib_delnode (struct route_node *rn, struct rib *rib)
     }
 }
 
+/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
+ * NOTE: Table-id is relevant only in the Default VRF.
+ */
+static struct route_table *
+zebra_vrf_table_with_table_id (afi_t afi, safi_t safi,
+                               vrf_id_t vrf_id, u_int32_t table_id)
+{
+  struct route_table *table = NULL;
+
+  if (afi >= AFI_MAX || safi >= SAFI_MAX)
+    return NULL;
+
+  if (vrf_id == VRF_DEFAULT)
+    {
+      if (table_id == RT_TABLE_MAIN ||
+          table_id == zebrad.rtm_table_default)
+        table = zebra_vrf_table (afi, safi, vrf_id);
+      else
+        table = zebra_vrf_other_route_table (afi, table_id, vrf_id);
+    }
+  else
+      table = zebra_vrf_table (afi, safi, vrf_id);
+
+  return table;
+}
+
 int
 rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
              struct in_addr *gate, struct in_addr *src,
@@ -2015,14 +2041,7 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
   struct nexthop *nexthop;
 
   /* Lookup table.  */
-  if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))
-    {
-      table = zebra_vrf_table (AFI_IP, safi, vrf_id);
-    }
-  else
-    {
-      table = zebra_vrf_other_route_table (AFI_IP, table_id, vrf_id);
-    }
+  table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id);
   if (! table)
     return 0;
 
@@ -2298,14 +2317,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
   int ret = 0;
   
   /* Lookup table.  */
-  if ((rib->table == zebrad.rtm_table_default) || (rib->table == RT_TABLE_MAIN))
-    {
-      table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
-    }
-  else
-    {
-      table = zebra_vrf_other_route_table (AFI_IP, rib->table, rib->vrf_id);
-    }
+  table = zebra_vrf_table_with_table_id (AFI_IP, safi, rib->vrf_id, rib->table);
   if (! table)
     return 0;
 
@@ -2390,14 +2402,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
   char buf2[INET6_ADDRSTRLEN];
 
   /* Lookup table.  */
-  if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))
-    {
-      table = zebra_vrf_table (AFI_IP, safi, vrf_id);
-    }
-  else
-    {
-      table = zebra_vrf_other_route_table(AFI_IP, table_id, vrf_id);
-    }
+  table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id);
   if (! table)
     return 0;
 
@@ -2966,14 +2971,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
   struct nexthop *nexthop;
 
   /* Lookup table.  */
-  if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))
-    {
-      table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
-    }
-  else
-    {
-      table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id);
-    }
+  table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id);
   if (! table)
     return 0;
 
@@ -3078,7 +3076,6 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi,
   struct rib *same = NULL;
   struct nexthop *nexthop;
   int ret = 0;
-  unsigned int table_id = 0;
 
   if (p->family == AF_INET)
     {
@@ -3093,21 +3090,11 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi,
     }
   else
     {
-      if (rib)
-        table_id = rib->table;
-      else
+      if (!rib)
         return 0;                      /* why are we getting called with NULL rib */
 
       /* Lookup table.  */
-      if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))
-        {
-          table = zebra_vrf_table (AFI_IP6, safi, rib->vrf_id);
-        }
-      else
-        {
-          table = zebra_vrf_other_route_table(AFI_IP6, table_id, rib->vrf_id);
-        }
-
+      table = zebra_vrf_table_with_table_id (AFI_IP6, safi, rib->vrf_id, rib->table);
       if (! table)
         return 0;
 
@@ -3215,14 +3202,7 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
   apply_mask_ipv6 (p);
 
   /* Lookup table.  */
-  if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))
-    {
-      table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
-    }
-  else
-    {
-      table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id);
-    }
+  table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id);
   if (! table)
     return 0;