]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Allow zebra to delete self originated routes
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 1 Sep 2017 14:28:19 +0000 (10:28 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 5 Sep 2017 22:56:36 +0000 (18:56 -0400)
With the change to make zebra pass routes to the kernel
with the 'correct' proto name, it caused zebra to
not properly recognize them on startup again
the next time such that the route would not
be deleted.

Modify rt_netlink.c to notice that we have a
self originated route and to properly mark
the type of route it was.

Modify rib_table_sweep to mark the nexthops
as active so that when we go to delete the
self originated routes it would properly
delete from the kernel.

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

index f05025e630390e2bae5e75b613320415c2b046b4..12b61853957a2011afc4cee113bc2c43d6ce0e52 100644 (file)
@@ -148,14 +148,15 @@ static inline int is_selfroute(int proto)
            || (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA)
            || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
            || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
-           || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) {
+           || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
+           || (proto == RTPROT_RIP)) {
                return 1;
        }
 
        return 0;
 }
 
-static inline int get_rt_proto(int proto)
+static inline int zebra2proto(int proto)
 {
        switch (proto) {
        case ZEBRA_ROUTE_BABEL:
@@ -197,6 +198,47 @@ static inline int get_rt_proto(int proto)
        return proto;
 }
 
+static inline int proto2zebra(int proto, int family)
+{
+       switch (proto) {
+       case RTPROT_BABEL:
+               proto = ZEBRA_ROUTE_BABEL;
+               break;
+       case RTPROT_BGP:
+               proto = ZEBRA_ROUTE_BGP;
+               break;
+       case RTPROT_OSPF:
+               proto = (family == AFI_IP) ?
+                       ZEBRA_ROUTE_OSPF : ZEBRA_ROUTE_OSPF6;
+               break;
+       case RTPROT_ISIS:
+               proto = ZEBRA_ROUTE_ISIS;
+               break;
+       case RTPROT_RIP:
+               proto = ZEBRA_ROUTE_RIP;
+               break;
+       case RTPROT_RIPNG:
+               proto = ZEBRA_ROUTE_RIPNG;
+               break;
+       case RTPROT_NHRP:
+               proto = ZEBRA_ROUTE_NHRP;
+               break;
+       case RTPROT_EIGRP:
+               proto = ZEBRA_ROUTE_EIGRP;
+               break;
+       case RTPROT_LDP:
+               proto = ZEBRA_ROUTE_LDP;
+               break;
+       case RTPROT_STATIC:
+               proto = ZEBRA_ROUTE_STATIC;
+               break;
+       default:
+               proto = ZEBRA_ROUTE_KERNEL;
+               break;
+       }
+       return proto;
+}
+
 /*
 Pending: create an efficient table_id (in a tree/hash) based lookup)
  */
@@ -231,6 +273,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
 
        char anyaddr[16] = {0};
 
+       int proto = ZEBRA_ROUTE_KERNEL;
        int index = 0;
        int table;
        int metric = 0;
@@ -300,9 +343,10 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
        }
 
        /* Route which inserted by Zebra. */
-       if (is_selfroute(rtm->rtm_protocol))
+       if (is_selfroute(rtm->rtm_protocol)) {
                flags |= ZEBRA_FLAG_SELFROUTE;
-
+               proto = proto2zebra(rtm->rtm_protocol, rtm->rtm_family);
+       }
        if (tb[RTA_OIF])
                index = *(int *)RTA_DATA(tb[RTA_OIF]);
 
@@ -409,7 +453,8 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                                memcpy(&nh.src, prefsrc, sz);
                        if (gate)
                                memcpy(&nh.gate, gate, sz);
-                       rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
+
+                       rib_add(afi, SAFI_UNICAST, vrf_id, proto,
                                0, flags, &p, NULL, &nh, table, metric, mtu, 0);
                } else {
                        /* This is a multipath route */
@@ -421,7 +466,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                        len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
 
                        re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
-                       re->type = ZEBRA_ROUTE_KERNEL;
+                       re->type = proto;
                        re->distance = 0;
                        re->flags = flags;
                        re->metric = metric;
@@ -515,13 +560,13 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                        if (gate)
                                memcpy(&nh.gate, gate, sz);
                        rib_delete(afi, SAFI_UNICAST, vrf_id,
-                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, &nh,
+                                  proto, 0, flags, &p, NULL, &nh,
                                   table, metric);
                } else {
                        /* XXX: need to compare the entire list of nexthops
                         * here for NLM_F_APPEND stupidity */
                        rib_delete(afi, SAFI_UNICAST, vrf_id,
-                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, NULL,
+                                  proto, 0, flags, &p, NULL, NULL,
                                   table, metric);
                }
        }
@@ -1272,7 +1317,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
        req.r.rtm_family = family;
        req.r.rtm_dst_len = p->prefixlen;
        req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
-       req.r.rtm_protocol = get_rt_proto(re->type);
+       req.r.rtm_protocol = zebra2proto(re->type);
        req.r.rtm_scope = RT_SCOPE_UNIVERSE;
        req.r.rtm_type = RTN_UNICAST;
 
index deb434bd350fc1fe8f7d621c735374e4e1bdc297..d74f84a1f689d84a17e76050a59ad2b545b87562 100644 (file)
@@ -2072,8 +2072,9 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
 
        for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
                inet_ntop(p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
-               zlog_debug("%s: %s %s with flags %s%s%s", func,
+               zlog_debug("%s: %s %s[%u] with flags %s%s%s", func,
                           (nexthop->rparent ? "  NH" : "NH"), straddr,
+                          nexthop->ifindex,
                           (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
                                    ? "ACTIVE "
                                    : ""),
@@ -2644,23 +2645,50 @@ static void rib_sweep_table(struct route_table *table)
        struct route_node *rn;
        struct route_entry *re;
        struct route_entry *next;
+       struct nexthop *nexthop;
        int ret = 0;
 
-       if (table)
-               for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
-                       RNODE_FOREACH_RE_SAFE(rn, re, next)
-                       {
-                               if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
-                                       continue;
+       if (!table)
+               return;
 
-                               if (re->type == ZEBRA_ROUTE_KERNEL
-                                   && CHECK_FLAG(re->flags,
-                                                 ZEBRA_FLAG_SELFROUTE)) {
-                                       ret = rib_uninstall_kernel(rn, re);
-                                       if (!ret)
-                                               rib_delnode(rn, re);
-                               }
-                       }
+       for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
+               RNODE_FOREACH_RE_SAFE(rn, re, next)
+               {
+                       if (IS_ZEBRA_DEBUG_RIB)
+                               route_entry_dump(&rn->p, NULL, re);
+
+                       if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+                               continue;
+
+                       if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE))
+                               continue;
+
+                       /*
+                        * So we are starting up and have received
+                        * routes from the kernel that we have installed
+                        * from a previous run of zebra but not cleaned
+                        * up ( say a kill -9 )
+                        * But since we haven't actually installed
+                        * them yet( we received them from the kernel )
+                        * we don't think they are active.
+                        * So let's pretend they are active to actually
+                        * remove them.
+                        * In all honesty I'm not sure if we should
+                        * mark them as active when we receive them
+                        * This is startup only so probably ok.
+                        *
+                        * If we ever decide to move rib_sweep_table
+                        * to a different spot (ie startup )
+                        * this decision needs to be revisited
+                        */
+                       for (ALL_NEXTHOPS(re->nexthop, nexthop))
+                               SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+
+                       ret = rib_uninstall_kernel(rn, re);
+                       if (!ret)
+                               rib_delnode(rn, re);
+               }
+       }
 }
 
 /* Sweep all RIB tables.  */
@@ -2669,8 +2697,10 @@ void rib_sweep_route(void)
        struct vrf *vrf;
        struct zebra_vrf *zvrf;
 
-       RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id)
-       if ((zvrf = vrf->info) != NULL) {
+       RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) {
+               if ((zvrf = vrf->info) == NULL)
+                       continue;
+
                rib_sweep_table(zvrf->table[AFI_IP][SAFI_UNICAST]);
                rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]);
        }