diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index f05025e630..12b6185395 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index deb434bd35..d74f84a1f6 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -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]); }