diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index a1c891fc66..0fb650c149 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); diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index a997ca5f2e..d20954037d 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; @@ -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_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..e479e2474d 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); @@ -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 aece5d03cd..b5cbc96bc3 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; @@ -1461,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) { @@ -1480,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.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.nexthop = *nexthop; + newinfo.nh = *nh; if ((list = rp->info) != NULL && listcount(list) != 0) { rinfo = listgetdata(listhead(list)); @@ -1512,23 +1512,15 @@ 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) { - 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->nexthop), - ifindex2ifname(ifindex, VRF_DEFAULT)); + zlog_debug( + "Redistribute new prefix %s/%d", + inet_ntoa(p->prefix), p->prefixlen); } rip_event(RIP_TRIGGERED_UPDATE, 0); @@ -1554,7 +1546,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, @@ -1565,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, @@ -2201,7 +2193,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 +2225,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 +2318,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 +2639,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); @@ -2861,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"); @@ -2882,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; @@ -3454,14 +3451,30 @@ DEFUN (show_ip_rip, if (len > 0) vty_out(vty, "%*s", len, " "); - if (rinfo->nexthop.s_addr) + switch(rinfo->nh.type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out(vty, "%-20s %2d ", - inet_ntoa(rinfo->nexthop), + 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 ae34ed3f48..9a9c081bf9 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; @@ -387,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 *);