]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Allow multiple rib deletes from linux kernel 234/head
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 16 Feb 2017 21:59:20 +0000 (16:59 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 1 Mar 2017 13:30:55 +0000 (08:30 -0500)
The kernel can send a DELROUTE with a individual
nexthop.  Technically this is meant to delete that
individual nexthop from the route but zebra
has no way to do this currently.  So we just delete
the route.

V4 -> Never sends a DELROUTE with multiple nexthops
as a way to modify the rib.  It sends a a NEWROUTE
with RTM_REPLACE with the new appropriate route.

V6 -> Sends a DELROUTE with multiple nexthops
which is supposed to be interpreted as a
subtraction from the route.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
zebra/rt_netlink.c

index 0c3d17dbdac155a7cd306e345f8bac044ac98420..450e15e0f7b6a625471daebaae2e2e9b68c55574 100644 (file)
@@ -353,8 +353,41 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
         }
     }
   else
-    rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
-                &p, NULL, gate, index, table);
+    {
+      if (!tb[RTA_MULTIPATH])
+        rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
+                    &p, NULL, gate, index, table);
+      else
+        {
+          struct rtnexthop *rtnh =
+            (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
+
+          len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
+
+          for (;;)
+            {
+              if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
+                break;
+
+              gate = NULL;
+              if (rtnh->rtnh_len > sizeof (*rtnh))
+                {
+                  memset (tb, 0, sizeof (tb));
+                  netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
+                                        rtnh->rtnh_len - sizeof (*rtnh));
+                  if (tb[RTA_GATEWAY])
+                    gate = RTA_DATA (tb[RTA_GATEWAY]);
+                }
+
+              if (gate)
+                rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
+                            &p, NULL, gate, index, table);
+
+              len -= NLMSG_ALIGN(rtnh->rtnh_len);
+              rtnh = RTNH_NEXT(rtnh);
+            }
+        }
+    }
 
   return 0;
 }