From dd127197f9f165c23ced8165b08b66b2509c5da9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Nov 2017 09:50:32 -0500 Subject: [PATCH 1/5] ripd: Convert to using 'struct nexthop' for nexthop information RIP is not using the nexthop data structure and as such when it does not fully understand when it receives some of the more exotic nexthop types what to do with it. This is the start of a series of commits to allow RIP to start understanding and properly displaying information about different nexthop types. Signed-off-by: Donald Sharp --- ripd/rip_interface.c | 2 +- ripd/rip_routemap.c | 8 +++++--- ripd/rip_zebra.c | 2 +- ripd/ripd.c | 39 +++++++++++++++++++++------------------ ripd/ripd.h | 6 ++---- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index a997ca5f2e..184f2f2b81 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -559,7 +559,7 @@ int rip_if_down(struct interface *ifp) if ((list = rp->info) != NULL) for (ALL_LIST_ELEMENTS(list, listnode, nextnode, rinfo)) - if (rinfo->ifindex == ifp->ifindex) + if (rinfo->nh.ifindex == ifp->ifindex) rip_ecmp_delete(rinfo); ri = ifp->info; diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index ad9f8cf80b..a37effa23c 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -129,7 +129,7 @@ static route_map_result_t route_match_interface(void *rule, rinfo = object; if (rinfo->ifindex_out == ifp->ifindex - || rinfo->ifindex == ifp->ifindex) + || rinfo->nh.ifindex == ifp->ifindex) return RMAP_MATCH; else return RMAP_NOMATCH; @@ -171,7 +171,8 @@ static route_map_result_t route_match_ip_next_hop(void *rule, rinfo = object; p.family = AF_INET; p.prefix = - (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; + (rinfo->nh.gate.ipv4.s_addr) ? + rinfo->nh.gate.ipv4 : rinfo->from; p.prefixlen = IPV4_MAX_BITLEN; alist = access_list_lookup(AFI_IP, (char *)rule); @@ -217,7 +218,8 @@ route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, rinfo = object; p.family = AF_INET; p.prefix = - (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; + (rinfo->nh.gate.ipv4.s_addr) ? + rinfo->nh.gate.ipv4 : rinfo->from; p.prefixlen = IPV4_MAX_BITLEN; plist = prefix_list_lookup(AFI_IP, (char *)rule); diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 3772f6223e..bd46f7e3e4 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -56,7 +56,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) if (count >= MULTIPATH_NUM) break; api_nh = &api.nexthops[count]; - api_nh->gate.ipv4 = rinfo->nexthop; + api_nh->gate = rinfo->nh.gate; api_nh->type = NEXTHOP_TYPE_IPV4; if (cmd == ZEBRA_ROUTE_ADD) SET_FLAG(rinfo->flags, RIP_RTF_FIB); diff --git a/ripd/ripd.c b/ripd/ripd.c index aece5d03cd..0415c5ba9e 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -424,9 +424,10 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, memset(&newinfo, 0, sizeof(newinfo)); newinfo.type = ZEBRA_ROUTE_RIP; newinfo.sub_type = RIP_ROUTE_RTE; - newinfo.nexthop = rte->nexthop; + newinfo.nh.gate.ipv4 = rte->nexthop; newinfo.from = from->sin_addr; - newinfo.ifindex = ifp->ifindex; + newinfo.nh.ifindex = ifp->ifindex; + newinfo.nh.type = NEXTHOP_TYPE_IPV4_IFINDEX; newinfo.metric = rte->metric; newinfo.metric_out = rte->metric; /* XXX */ newinfo.tag = ntohs(rte->tag); /* XXX */ @@ -488,7 +489,8 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, rp = route_node_get(rip->table, (struct prefix *)&p); newinfo.rp = rp; - newinfo.nexthop = *nexthop; + newinfo.nh.gate.ipv4 = *nexthop; + newinfo.nh.type = NEXTHOP_TYPE_IPV4; newinfo.metric = rte->metric; newinfo.tag = ntohs(rte->tag); newinfo.distance = rip_distance_apply(&newinfo); @@ -505,7 +507,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, break; if (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) - && IPV4_ADDR_SAME(&rinfo->nexthop, nexthop)) + && IPV4_ADDR_SAME(&rinfo->nh.gate.ipv4, nexthop)) break; if (!listnextnode(node)) { @@ -567,7 +569,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, /* Only routes directly connected to an interface * (nexthop == 0) * may have a valid NULL distance */ - if (rinfo->nexthop.s_addr != 0) + if (rinfo->nh.gate.ipv4.s_addr != 0) old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT; @@ -602,7 +604,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, If this datagram is from the same router as the existing route, reinitialize the timeout. */ same = (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) - && (rinfo->ifindex == ifp->ifindex)); + && (rinfo->nh.ifindex == ifp->ifindex)); old_dist = rinfo->distance ? rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT; @@ -1480,7 +1482,7 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, memset(&newinfo, 0, sizeof(struct rip_info)); newinfo.type = type; newinfo.sub_type = sub_type; - newinfo.ifindex = ifindex; + newinfo.nh.ifindex = ifindex; newinfo.metric = 1; newinfo.external_metric = metric; newinfo.distance = distance; @@ -1488,7 +1490,7 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, newinfo.tag = tag; newinfo.rp = rp; if (nexthop) - newinfo.nexthop = *nexthop; + newinfo.nh.gate.ipv4 = *nexthop; if ((list = rp->info) != NULL && listcount(list) != 0) { rinfo = listgetdata(listhead(list)); @@ -1527,7 +1529,7 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, zlog_debug( "Redistribute new prefix %s/%d with nexthop %s on the interface %s", inet_ntoa(p->prefix), p->prefixlen, - inet_ntoa(rinfo->nexthop), + inet_ntoa(rinfo->nh.gate.ipv4), ifindex2ifname(ifindex, VRF_DEFAULT)); } @@ -1554,7 +1556,7 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, rinfo = listgetdata(listhead(list)); if (rinfo != NULL && rinfo->type == type && rinfo->sub_type == sub_type - && rinfo->ifindex == ifindex) { + && rinfo->nh.ifindex == ifindex) { /* Perform poisoned reverse. */ rinfo->metric = RIP_METRIC_INFINITY; RIP_TIMER_ON(rinfo->t_garbage_collect, @@ -2201,7 +2203,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, for (ALL_LIST_ELEMENTS_RO(list, listnode, tmp_rinfo)) if (tmp_rinfo->type == ZEBRA_ROUTE_RIP - && tmp_rinfo->ifindex + && tmp_rinfo->nh.ifindex == ifc->ifp->ifindex) { suppress = 1; break; @@ -2233,8 +2235,8 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, * to avoid an IGP multi-level recursive look-up. * see (4.4) */ - if (rinfo->ifindex == ifc->ifp->ifindex) - rinfo->nexthop_out = rinfo->nexthop; + if (rinfo->nh.ifindex == ifc->ifp->ifindex) + rinfo->nexthop_out = rinfo->nh.gate.ipv4; /* Interface route-map */ if (ri->routemap[RIP_FILTER_OUT]) { @@ -2326,7 +2328,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, for (ALL_LIST_ELEMENTS_RO(list, listnode, tmp_rinfo)) if (tmp_rinfo->type == ZEBRA_ROUTE_RIP - && tmp_rinfo->ifindex + && tmp_rinfo->nh.ifindex == ifc->ifp->ifindex) rinfo->metric_out = RIP_METRIC_INFINITY; @@ -2647,8 +2649,9 @@ void rip_redistribute_withdraw(int type) "Poisone %s/%d on the interface %s with an infinity metric [withdraw]", inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex, - VRF_DEFAULT)); + ifindex2ifname( + rinfo->nh.ifindex, + VRF_DEFAULT)); } rip_event(RIP_TRIGGERED_UPDATE, 0); @@ -3454,9 +3457,9 @@ DEFUN (show_ip_rip, if (len > 0) vty_out(vty, "%*s", len, " "); - if (rinfo->nexthop.s_addr) + if (rinfo->nh.gate.ipv4.s_addr) vty_out(vty, "%-20s %2d ", - inet_ntoa(rinfo->nexthop), + inet_ntoa(rinfo->nh.gate.ipv4), rinfo->metric); else vty_out(vty, diff --git a/ripd/ripd.h b/ripd/ripd.h index ae34ed3f48..a66f506f48 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -23,6 +23,7 @@ #include "qobj.h" #include "hook.h" +#include "nexthop.h" #include "rip_memory.h" /* RIP version number. */ @@ -194,12 +195,9 @@ struct rip_info { int sub_type; /* RIP nexthop. */ - struct in_addr nexthop; + struct nexthop nh; struct in_addr from; - /* Which interface does this route come from. */ - ifindex_t ifindex; - /* Metric of this route. */ u_int32_t metric; From 3f5682c88d6f4f0b85539a8776c9e869f1cbd4fa Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Nov 2017 11:19:06 -0500 Subject: [PATCH 2/5] ripd: Allow rip_redistribute_add to know the nexthop type Allow rip_redistribute_add to receive and properly store the nexthop type passed up from zebra. Additionally display the different nexthop types appropriately. Signed-off-by: Donald Sharp --- ripd/rip_interface.c | 18 +++++++++++++---- ripd/rip_zebra.c | 23 +++++++++++++--------- ripd/ripd.c | 46 +++++++++++++++++++++++++++----------------- ripd/ripd.h | 8 +++++--- 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 184f2f2b81..d20954037d 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -591,6 +591,7 @@ void rip_if_down_all() static void rip_apply_address_add(struct connected *ifc) { struct prefix_ipv4 address; + struct nexthop nh; struct prefix *p; if (!rip) @@ -602,18 +603,22 @@ static void rip_apply_address_add(struct connected *ifc) p = ifc->address; memset(&address, 0, sizeof(address)); + memset(&nh, 0, sizeof(nh)); + address.family = p->family; address.prefix = p->u.prefix4; address.prefixlen = p->prefixlen; apply_mask_ipv4(&address); + nh.ifindex = ifc->ifp->ifindex; + nh.type = NEXTHOP_TYPE_IFINDEX; + /* Check if this interface is RIP enabled or not or Check if this address's prefix is RIP enabled */ if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) || (rip_enable_network_lookup2(ifc) >= 0)) rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex, NULL, 0, 0, - 0); + &address, &nh, 0, 0, 0); } int rip_interface_address_add(int command, struct zclient *zclient, @@ -879,6 +884,9 @@ static void rip_connect_set(struct interface *ifp, int set) struct listnode *node, *nnode; struct connected *connected; struct prefix_ipv4 address; + struct nexthop nh; + + memset(&nh, 0, sizeof(nh)); for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { struct prefix *p; @@ -892,6 +900,8 @@ static void rip_connect_set(struct interface *ifp, int set) address.prefixlen = p->prefixlen; apply_mask_ipv4(&address); + nh.ifindex = connected->ifp->ifindex; + nh.type = NEXTHOP_TYPE_IFINDEX; if (set) { /* Check once more wether this prefix is within a * "network IF_OR_PREF" one */ @@ -900,7 +910,7 @@ static void rip_connect_set(struct interface *ifp, int set) rip_redistribute_add( ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, - connected->ifp->ifindex, NULL, 0, 0, 0); + &nh, 0, 0, 0); } else { rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, @@ -909,7 +919,7 @@ static void rip_connect_set(struct interface *ifp, int set) rip_redistribute_add( ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE, &address, - connected->ifp->ifindex, NULL, 0, 0, 0); + &nh, 0, 0, 0); } } } diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index bd46f7e3e4..e479e2474d 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -121,8 +121,7 @@ static int rip_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct zapi_route api; - struct in_addr nexthop; - unsigned long ifindex; + struct nexthop nh; if (!rip) return 0; @@ -130,19 +129,21 @@ static int rip_zebra_read_route(int command, struct zclient *zclient, if (zapi_route_decode(zclient->ibuf, &api) < 0) return -1; - nexthop = api.nexthops[0].gate.ipv4; - ifindex = api.nexthops[0].ifindex; + memset(&nh, 0, sizeof(nh)); + nh.type = api.nexthops[0].type; + nh.gate.ipv4 = api.nexthops[0].gate.ipv4; + nh.ifindex = api.nexthops[0].ifindex; /* Then fetch IPv4 prefixes. */ if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, - (struct prefix_ipv4 *)&api.prefix, ifindex, - &nexthop, api.metric, api.distance, + (struct prefix_ipv4 *)&api.prefix, &nh, + api.metric, api.distance, api.tag); else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, (struct prefix_ipv4 *)&api.prefix, - ifindex); + nh.ifindex); return 0; } @@ -501,15 +502,19 @@ DEFUN (rip_default_information_originate, "Distribute a default route\n") { struct prefix_ipv4 p; + struct nexthop nh; if (!rip->default_information) { memset(&p, 0, sizeof(struct prefix_ipv4)); + memset(&nh, 0, sizeof(nh)); + p.family = AF_INET; + nh.type = NEXTHOP_TYPE_IPV4; rip->default_information = 1; - rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, - NULL, 0, 0, 0); + rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, + &nh, 0, 0, 0); } return CMD_SUCCESS; diff --git a/ripd/ripd.c b/ripd/ripd.c index 0415c5ba9e..4c1a12b0d5 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1463,7 +1463,7 @@ static int rip_send_packet(u_char *buf, int size, struct sockaddr_in *to, /* Add redistributed route to RIP table. */ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, - ifindex_t ifindex, struct in_addr *nexthop, + struct nexthop *nh, unsigned int metric, unsigned char distance, route_tag_t tag) { @@ -1482,15 +1482,13 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, memset(&newinfo, 0, sizeof(struct rip_info)); newinfo.type = type; newinfo.sub_type = sub_type; - newinfo.nh.ifindex = ifindex; newinfo.metric = 1; newinfo.external_metric = metric; newinfo.distance = distance; if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */ newinfo.tag = tag; newinfo.rp = rp; - if (nexthop) - newinfo.nh.gate.ipv4 = *nexthop; + newinfo.nh = *nh; if ((list = rp->info) != NULL && listcount(list) != 0) { rinfo = listgetdata(listhead(list)); @@ -1520,17 +1518,9 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, rinfo = rip_ecmp_add(&newinfo); if (IS_RIP_DEBUG_EVENT) { - if (!nexthop) - zlog_debug( - "Redistribute new prefix %s/%d on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); - else - zlog_debug( - "Redistribute new prefix %s/%d with nexthop %s on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, - inet_ntoa(rinfo->nh.gate.ipv4), - ifindex2ifname(ifindex, VRF_DEFAULT)); + zlog_debug( + "Redistribute new prefix %s/%d", + inet_ntoa(p->prefix), p->prefixlen); } rip_event(RIP_TRIGGERED_UPDATE, 0); @@ -2864,9 +2854,13 @@ DEFUN (rip_route, { int idx_ipv4_prefixlen = 1; int ret; + struct nexthop nh; struct prefix_ipv4 p; struct route_node *node; + memset(&nh, 0, sizeof(nh)); + nh.type = NEXTHOP_TYPE_IPV4; + ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); if (ret < 0) { vty_out(vty, "Malformed address\n"); @@ -2885,7 +2879,7 @@ DEFUN (rip_route, node->info = (void *)1; - rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, + rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, 0, 0); return CMD_SUCCESS; @@ -3457,14 +3451,30 @@ DEFUN (show_ip_rip, if (len > 0) vty_out(vty, "%*s", len, " "); - if (rinfo->nh.gate.ipv4.s_addr) + switch(rinfo->nh.type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out(vty, "%-20s %2d ", inet_ntoa(rinfo->nh.gate.ipv4), rinfo->metric); - else + break; + case NEXTHOP_TYPE_IFINDEX: vty_out(vty, "0.0.0.0 %2d ", rinfo->metric); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, + "blackhole %2d ", + rinfo->metric); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, + "V6 Address Hidden %2d ", + rinfo->metric); + break; + } /* Route which exist in kernel routing table. */ if ((rinfo->type == ZEBRA_ROUTE_RIP) diff --git a/ripd/ripd.h b/ripd/ripd.h index a66f506f48..9a9c081bf9 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -385,9 +385,11 @@ extern int rip_request_send(struct sockaddr_in *, struct interface *, u_char, extern int rip_neighbor_lookup(struct sockaddr_in *); extern int rip_redistribute_check(int); -extern void rip_redistribute_add(int, int, struct prefix_ipv4 *, ifindex_t, - struct in_addr *, unsigned int, unsigned char, - route_tag_t); +extern void rip_redistribute_add(int type, int sub_type, + struct prefix_ipv4 *p, + struct nexthop *nh, + unsigned int metric, unsigned char distance, + route_tag_t tag); extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t); extern void rip_redistribute_withdraw(int); extern void rip_zebra_ipv4_add(struct route_node *); From 14aa0c3d3ab0ba1647a477967849a2ee3c32ae51 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Nov 2017 11:21:56 -0500 Subject: [PATCH 3/5] ripd: Fix spelling mistake in debug Signed-off-by: Donald Sharp --- ripd/ripd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ripd/ripd.c b/ripd/ripd.c index 4c1a12b0d5..3c5451659a 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1557,7 +1557,7 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, if (IS_RIP_DEBUG_EVENT) zlog_debug( - "Poisone %s/%d on the interface %s with an " + "Poison %s/%d on the interface %s with an " "infinity metric [delete]", inet_ntoa(p->prefix), p->prefixlen, From 9de1f7ff13889391e72162a50619b2ff275209f4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Nov 2017 13:22:56 -0500 Subject: [PATCH 4/5] bgpd: Allow bgp to understand the different nexthop types When BGP is being redistributed prefixes, allow it to understand the nexthop type. This fixes the issue where a blackhole route was being interpreted to having a nexthop of 1.0.0.0( ruh-roh!!! ). This broke downstream neighbors as that they would receive a 1.0.0.0 nexthop, which is bad, very very bad. This commit sets us up for the future where we can match a route-map against a nexthop type. In that bgp is now at least nominally paying attention to the type. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 27 ++++++++++++++++++++++----- bgpd/bgp_route.h | 8 +++++--- bgpd/bgp_zebra.c | 8 +++++--- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 4ee1aafbe9..e0ae2a9611 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -6148,8 +6148,9 @@ DEFUN (no_ipv6_aggregate_address, /* Redistribute route treatment. */ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, - const union g_addr *nexthop, unsigned int ifindex, - u_int32_t metric, u_char type, u_short instance, + const union g_addr *nexthop, ifindex_t ifindex, + enum nexthop_types_t nhtype, uint32_t metric, + u_char type, u_short instance, route_tag_t tag) { struct bgp_info *new; @@ -6164,15 +6165,31 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, /* Make default attribute. */ bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); - if (nexthop) { + + switch(nhtype) { + case NEXTHOP_TYPE_IFINDEX: + break; + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + attr.nexthop = nexthop->ipv4; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + attr.mp_nexthop_global = nexthop->ipv6; + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + break; + case NEXTHOP_TYPE_BLACKHOLE: switch (p->family) { case AF_INET: - attr.nexthop = nexthop->ipv4; + attr.nexthop.s_addr = INADDR_ANY; break; case AF_INET6: - attr.mp_nexthop_global = nexthop->ipv6; + memset(&attr.mp_nexthop_global, 0, + sizeof(attr.mp_nexthop_global)); attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + break; } + break; } attr.nh_ifindex = ifindex; diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 6fbeed8963..085de3fabb 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -328,9 +328,11 @@ extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); -extern void bgp_redistribute_add(struct bgp *, struct prefix *, - const union g_addr *, unsigned int ifindex, - u_int32_t, u_char, u_short, route_tag_t); +extern void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, + const union g_addr *nexthop, ifindex_t ifindex, + enum nexthop_types_t nhtype, uint32_t metric, + u_char type, u_short instance, + route_tag_t tag); extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char, u_short); extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, u_short); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index bec7050226..b6bf008bae 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -524,9 +524,10 @@ static int bgp_interface_vrf_update(int command, struct zclient *zclient, static int zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { + enum nexthop_types_t nhtype; struct zapi_route api; union g_addr nexthop; - unsigned int ifindex; + ifindex_t ifindex; int add, i; struct bgp *bgp; @@ -548,6 +549,7 @@ static int zebra_read_route(int command, struct zclient *zclient, nexthop = api.nexthops[0].gate; ifindex = api.nexthops[0].ifindex; + nhtype = api.nexthops[0].type; add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD); if (add) { @@ -568,8 +570,8 @@ static int zebra_read_route(int command, struct zclient *zclient, /* Now perform the add/update. */ bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex, - api.metric, api.type, api.instance, - api.tag); + nhtype, api.metric, api.type, + api.instance, api.tag); } else { bgp_redistribute_delete(bgp, &api.prefix, api.type, api.instance); From 11ff71648e52a79b966cc8efc7c41e2c96650f66 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Nov 2017 08:49:02 -0500 Subject: [PATCH 5/5] ripd: Fix SA issues The rinfo variable was being set but never used. We just need to call rip_ecmp_replace or rip_ecmp_add this function does not care about the return values because the rinfo returned is stored on the rip route entry. Signed-off-by: Donald Sharp --- ripd/ripd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ripd/ripd.c b/ripd/ripd.c index 3c5451659a..b5cbc96bc3 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1512,10 +1512,10 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, } } - rinfo = rip_ecmp_replace(&newinfo); + (void)rip_ecmp_replace(&newinfo); route_unlock_node(rp); } else - rinfo = rip_ecmp_add(&newinfo); + (void)rip_ecmp_add(&newinfo); if (IS_RIP_DEBUG_EVENT) { zlog_debug(