]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: fix kernel-route's deletion on vrf
authorHiroki Shirokura <slank.dev@gmail.com>
Fri, 24 Jan 2020 04:45:54 +0000 (23:45 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 4 Feb 2020 15:19:31 +0000 (10:19 -0500)
zebra can catch the kernel's route deletion by netlink.
but current FRR can't delete kernel-route on vrf(l3mdev)
when kernel operator delete the route on out-side of FRR.
It looks problem about kernel-route deletion.

This problem is caused around _nexthop_cmp_no_labels(nh1,nh2)
that checks the each nexthop's member 'vrf_id'.
And _nexthop_cmp_no_labels's caller doesn't set the vrf_id
of nexthop structure. This commit fix that case.

Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
zebra/rt_netlink.c

index 5edcf9bb8af517dd6acce09075a3c7098d66b92b..073515ae6f565f8867a0f79427f98cb6b2c3484a 100644 (file)
@@ -330,6 +330,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
        struct prefix p;
        struct prefix_ipv6 src_p = {};
        vrf_id_t vrf_id;
+       struct interface *ifp;
+       vrf_id_t nh_vrf_id;
 
        char anyaddr[16] = {0};
 
@@ -546,10 +548,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
        if (rtm->rtm_family == AF_INET6)
                afi = AFI_IP6;
 
+       nh_vrf_id = vrf_id;
        if (h->nlmsg_type == RTM_NEWROUTE) {
-               struct interface *ifp;
-               vrf_id_t nh_vrf_id = vrf_id;
-
                if (!tb[RTA_MULTIPATH]) {
                        struct nexthop nh;
                        size_t sz = (afi == AFI_IP) ? 4 : 16;
@@ -755,9 +755,29 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                                nh.bh_type = bh_type;
                        }
                        nh.ifindex = index;
+
+                       if (index) {
+                               ifp = if_lookup_by_index_per_ns(
+                                       zebra_ns_lookup(ns_id), index);
+                               if (ifp)
+                                       nh_vrf_id = ifp->vrf_id;
+                               else {
+                                       flog_warn(
+                                               EC_ZEBRA_UNKNOWN_INTERFACE,
+                                               "%s: Unknown interface %u specified, defaulting to VRF_DEFAULT",
+                                               __PRETTY_FUNCTION__,
+                                               index);
+                                       nh_vrf_id = VRF_DEFAULT;
+                               }
+                       } else
+                               nh_vrf_id = vrf_id;
+
+                       if (prefsrc)
+                               memcpy(&nh.src, prefsrc, sz);
                        if (gate)
                                memcpy(&nh.gate, gate, sz);
-                       rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
+
+                       rib_delete(afi, SAFI_UNICAST, nh_vrf_id, proto, 0, flags,
                                   &p, &src_p, &nh, table, metric, distance,
                                   true);
                } else {