Merge pull request #1452 from donaldsharp/rip_nexthops

Blackhole Fixups for bgp and rip
This commit is contained in:
Renato Westphal 2017-11-21 14:05:19 -02:00 committed by GitHub
commit 859dd94575
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 122 additions and 71 deletions

View File

@ -6148,8 +6148,9 @@ DEFUN (no_ipv6_aggregate_address,
/* Redistribute route treatment. */ /* Redistribute route treatment. */
void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
const union g_addr *nexthop, unsigned int ifindex, const union g_addr *nexthop, ifindex_t ifindex,
u_int32_t metric, u_char type, u_short instance, enum nexthop_types_t nhtype, uint32_t metric,
u_char type, u_short instance,
route_tag_t tag) route_tag_t tag)
{ {
struct bgp_info *new; struct bgp_info *new;
@ -6164,15 +6165,31 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Make default attribute. */ /* Make default attribute. */
bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
if (nexthop) {
switch (p->family) { switch(nhtype) {
case AF_INET: case NEXTHOP_TYPE_IFINDEX:
break;
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
attr.nexthop = nexthop->ipv4; attr.nexthop = nexthop->ipv4;
break; break;
case AF_INET6: case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
attr.mp_nexthop_global = nexthop->ipv6; attr.mp_nexthop_global = nexthop->ipv6;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
break;
case NEXTHOP_TYPE_BLACKHOLE:
switch (p->family) {
case AF_INET:
attr.nexthop.s_addr = INADDR_ANY;
break;
case AF_INET6:
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; attr.nh_ifindex = ifindex;

View File

@ -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 int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add(struct bgp *, struct prefix *, extern void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
const union g_addr *, unsigned int ifindex, const union g_addr *nexthop, ifindex_t ifindex,
u_int32_t, u_char, u_short, route_tag_t); 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, extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char,
u_short); u_short);
extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, u_short); extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, u_short);

View File

@ -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, static int zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
enum nexthop_types_t nhtype;
struct zapi_route api; struct zapi_route api;
union g_addr nexthop; union g_addr nexthop;
unsigned int ifindex; ifindex_t ifindex;
int add, i; int add, i;
struct bgp *bgp; struct bgp *bgp;
@ -548,6 +549,7 @@ static int zebra_read_route(int command, struct zclient *zclient,
nexthop = api.nexthops[0].gate; nexthop = api.nexthops[0].gate;
ifindex = api.nexthops[0].ifindex; ifindex = api.nexthops[0].ifindex;
nhtype = api.nexthops[0].type;
add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD); add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
if (add) { if (add) {
@ -568,8 +570,8 @@ static int zebra_read_route(int command, struct zclient *zclient,
/* Now perform the add/update. */ /* Now perform the add/update. */
bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex, bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
api.metric, api.type, api.instance, nhtype, api.metric, api.type,
api.tag); api.instance, api.tag);
} else { } else {
bgp_redistribute_delete(bgp, &api.prefix, api.type, bgp_redistribute_delete(bgp, &api.prefix, api.type,
api.instance); api.instance);

View File

@ -559,7 +559,7 @@ int rip_if_down(struct interface *ifp)
if ((list = rp->info) != NULL) if ((list = rp->info) != NULL)
for (ALL_LIST_ELEMENTS(list, listnode, nextnode, for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
rinfo)) rinfo))
if (rinfo->ifindex == ifp->ifindex) if (rinfo->nh.ifindex == ifp->ifindex)
rip_ecmp_delete(rinfo); rip_ecmp_delete(rinfo);
ri = ifp->info; ri = ifp->info;
@ -591,6 +591,7 @@ void rip_if_down_all()
static void rip_apply_address_add(struct connected *ifc) static void rip_apply_address_add(struct connected *ifc)
{ {
struct prefix_ipv4 address; struct prefix_ipv4 address;
struct nexthop nh;
struct prefix *p; struct prefix *p;
if (!rip) if (!rip)
@ -602,18 +603,22 @@ static void rip_apply_address_add(struct connected *ifc)
p = ifc->address; p = ifc->address;
memset(&address, 0, sizeof(address)); memset(&address, 0, sizeof(address));
memset(&nh, 0, sizeof(nh));
address.family = p->family; address.family = p->family;
address.prefix = p->u.prefix4; address.prefix = p->u.prefix4;
address.prefixlen = p->prefixlen; address.prefixlen = p->prefixlen;
apply_mask_ipv4(&address); apply_mask_ipv4(&address);
nh.ifindex = ifc->ifp->ifindex;
nh.type = NEXTHOP_TYPE_IFINDEX;
/* Check if this interface is RIP enabled or not /* Check if this interface is RIP enabled or not
or Check if this address's prefix is RIP enabled */ or Check if this address's prefix is RIP enabled */
if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) if ((rip_enable_if_lookup(ifc->ifp->name) >= 0)
|| (rip_enable_network_lookup2(ifc) >= 0)) || (rip_enable_network_lookup2(ifc) >= 0))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
&address, ifc->ifp->ifindex, NULL, 0, 0, &address, &nh, 0, 0, 0);
0);
} }
int rip_interface_address_add(int command, struct zclient *zclient, 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 listnode *node, *nnode;
struct connected *connected; struct connected *connected;
struct prefix_ipv4 address; struct prefix_ipv4 address;
struct nexthop nh;
memset(&nh, 0, sizeof(nh));
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
struct prefix *p; struct prefix *p;
@ -892,6 +900,8 @@ static void rip_connect_set(struct interface *ifp, int set)
address.prefixlen = p->prefixlen; address.prefixlen = p->prefixlen;
apply_mask_ipv4(&address); apply_mask_ipv4(&address);
nh.ifindex = connected->ifp->ifindex;
nh.type = NEXTHOP_TYPE_IFINDEX;
if (set) { if (set) {
/* Check once more wether this prefix is within a /* Check once more wether this prefix is within a
* "network IF_OR_PREF" one */ * "network IF_OR_PREF" one */
@ -900,7 +910,7 @@ static void rip_connect_set(struct interface *ifp, int set)
rip_redistribute_add( rip_redistribute_add(
ZEBRA_ROUTE_CONNECT, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE, &address, RIP_ROUTE_INTERFACE, &address,
connected->ifp->ifindex, NULL, 0, 0, 0); &nh, 0, 0, 0);
} else { } else {
rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, rip_redistribute_delete(ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE, &address, RIP_ROUTE_INTERFACE, &address,
@ -909,7 +919,7 @@ static void rip_connect_set(struct interface *ifp, int set)
rip_redistribute_add( rip_redistribute_add(
ZEBRA_ROUTE_CONNECT, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_REDISTRIBUTE, &address, RIP_ROUTE_REDISTRIBUTE, &address,
connected->ifp->ifindex, NULL, 0, 0, 0); &nh, 0, 0, 0);
} }
} }
} }

View File

@ -129,7 +129,7 @@ static route_map_result_t route_match_interface(void *rule,
rinfo = object; rinfo = object;
if (rinfo->ifindex_out == ifp->ifindex if (rinfo->ifindex_out == ifp->ifindex
|| rinfo->ifindex == ifp->ifindex) || rinfo->nh.ifindex == ifp->ifindex)
return RMAP_MATCH; return RMAP_MATCH;
else else
return RMAP_NOMATCH; return RMAP_NOMATCH;
@ -171,7 +171,8 @@ static route_map_result_t route_match_ip_next_hop(void *rule,
rinfo = object; rinfo = object;
p.family = AF_INET; p.family = AF_INET;
p.prefix = 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; p.prefixlen = IPV4_MAX_BITLEN;
alist = access_list_lookup(AFI_IP, (char *)rule); 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; rinfo = object;
p.family = AF_INET; p.family = AF_INET;
p.prefix = 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; p.prefixlen = IPV4_MAX_BITLEN;
plist = prefix_list_lookup(AFI_IP, (char *)rule); plist = prefix_list_lookup(AFI_IP, (char *)rule);

View File

@ -56,7 +56,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
if (count >= MULTIPATH_NUM) if (count >= MULTIPATH_NUM)
break; break;
api_nh = &api.nexthops[count]; api_nh = &api.nexthops[count];
api_nh->gate.ipv4 = rinfo->nexthop; api_nh->gate = rinfo->nh.gate;
api_nh->type = NEXTHOP_TYPE_IPV4; api_nh->type = NEXTHOP_TYPE_IPV4;
if (cmd == ZEBRA_ROUTE_ADD) if (cmd == ZEBRA_ROUTE_ADD)
SET_FLAG(rinfo->flags, RIP_RTF_FIB); 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) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct zapi_route api; struct zapi_route api;
struct in_addr nexthop; struct nexthop nh;
unsigned long ifindex;
if (!rip) if (!rip)
return 0; 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) if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1; return -1;
nexthop = api.nexthops[0].gate.ipv4; memset(&nh, 0, sizeof(nh));
ifindex = api.nexthops[0].ifindex; nh.type = api.nexthops[0].type;
nh.gate.ipv4 = api.nexthops[0].gate.ipv4;
nh.ifindex = api.nexthops[0].ifindex;
/* Then fetch IPv4 prefixes. */ /* Then fetch IPv4 prefixes. */
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
(struct prefix_ipv4 *)&api.prefix, ifindex, (struct prefix_ipv4 *)&api.prefix, &nh,
&nexthop, api.metric, api.distance, api.metric, api.distance,
api.tag); api.tag);
else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
(struct prefix_ipv4 *)&api.prefix, (struct prefix_ipv4 *)&api.prefix,
ifindex); nh.ifindex);
return 0; return 0;
} }
@ -501,15 +502,19 @@ DEFUN (rip_default_information_originate,
"Distribute a default route\n") "Distribute a default route\n")
{ {
struct prefix_ipv4 p; struct prefix_ipv4 p;
struct nexthop nh;
if (!rip->default_information) { if (!rip->default_information) {
memset(&p, 0, sizeof(struct prefix_ipv4)); memset(&p, 0, sizeof(struct prefix_ipv4));
memset(&nh, 0, sizeof(nh));
p.family = AF_INET; p.family = AF_INET;
nh.type = NEXTHOP_TYPE_IPV4;
rip->default_information = 1; rip->default_information = 1;
rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p,
NULL, 0, 0, 0); &nh, 0, 0, 0);
} }
return CMD_SUCCESS; return CMD_SUCCESS;

View File

@ -424,9 +424,10 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
memset(&newinfo, 0, sizeof(newinfo)); memset(&newinfo, 0, sizeof(newinfo));
newinfo.type = ZEBRA_ROUTE_RIP; newinfo.type = ZEBRA_ROUTE_RIP;
newinfo.sub_type = RIP_ROUTE_RTE; newinfo.sub_type = RIP_ROUTE_RTE;
newinfo.nexthop = rte->nexthop; newinfo.nh.gate.ipv4 = rte->nexthop;
newinfo.from = from->sin_addr; 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 = rte->metric;
newinfo.metric_out = rte->metric; /* XXX */ newinfo.metric_out = rte->metric; /* XXX */
newinfo.tag = ntohs(rte->tag); /* 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); rp = route_node_get(rip->table, (struct prefix *)&p);
newinfo.rp = rp; newinfo.rp = rp;
newinfo.nexthop = *nexthop; newinfo.nh.gate.ipv4 = *nexthop;
newinfo.nh.type = NEXTHOP_TYPE_IPV4;
newinfo.metric = rte->metric; newinfo.metric = rte->metric;
newinfo.tag = ntohs(rte->tag); newinfo.tag = ntohs(rte->tag);
newinfo.distance = rip_distance_apply(&newinfo); newinfo.distance = rip_distance_apply(&newinfo);
@ -505,7 +507,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
break; break;
if (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) if (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr)
&& IPV4_ADDR_SAME(&rinfo->nexthop, nexthop)) && IPV4_ADDR_SAME(&rinfo->nh.gate.ipv4, nexthop))
break; break;
if (!listnextnode(node)) { 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 /* Only routes directly connected to an interface
* (nexthop == 0) * (nexthop == 0)
* may have a valid NULL distance */ * 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 = old_dist
? old_dist ? old_dist
: ZEBRA_RIP_DISTANCE_DEFAULT; : 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 If this datagram is from the same router as the existing
route, reinitialize the timeout. */ route, reinitialize the timeout. */
same = (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) same = (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr)
&& (rinfo->ifindex == ifp->ifindex)); && (rinfo->nh.ifindex == ifp->ifindex));
old_dist = rinfo->distance ? rinfo->distance old_dist = rinfo->distance ? rinfo->distance
: ZEBRA_RIP_DISTANCE_DEFAULT; : 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. */ /* Add redistributed route to RIP table. */
void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, 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, unsigned int metric, unsigned char distance,
route_tag_t tag) 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)); memset(&newinfo, 0, sizeof(struct rip_info));
newinfo.type = type; newinfo.type = type;
newinfo.sub_type = sub_type; newinfo.sub_type = sub_type;
newinfo.ifindex = ifindex;
newinfo.metric = 1; newinfo.metric = 1;
newinfo.external_metric = metric; newinfo.external_metric = metric;
newinfo.distance = distance; newinfo.distance = distance;
if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */ if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */
newinfo.tag = tag; newinfo.tag = tag;
newinfo.rp = rp; newinfo.rp = rp;
if (nexthop) newinfo.nh = *nh;
newinfo.nexthop = *nexthop;
if ((list = rp->info) != NULL && listcount(list) != 0) { if ((list = rp->info) != NULL && listcount(list) != 0) {
rinfo = listgetdata(listhead(list)); 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); route_unlock_node(rp);
} else } else
rinfo = rip_ecmp_add(&newinfo); (void)rip_ecmp_add(&newinfo);
if (IS_RIP_DEBUG_EVENT) { if (IS_RIP_DEBUG_EVENT) {
if (!nexthop)
zlog_debug( zlog_debug(
"Redistribute new prefix %s/%d on the interface %s", "Redistribute new prefix %s/%d",
inet_ntoa(p->prefix), p->prefixlen, 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));
} }
rip_event(RIP_TRIGGERED_UPDATE, 0); 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)); rinfo = listgetdata(listhead(list));
if (rinfo != NULL && rinfo->type == type if (rinfo != NULL && rinfo->type == type
&& rinfo->sub_type == sub_type && rinfo->sub_type == sub_type
&& rinfo->ifindex == ifindex) { && rinfo->nh.ifindex == ifindex) {
/* Perform poisoned reverse. */ /* Perform poisoned reverse. */
rinfo->metric = RIP_METRIC_INFINITY; rinfo->metric = RIP_METRIC_INFINITY;
RIP_TIMER_ON(rinfo->t_garbage_collect, 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) if (IS_RIP_DEBUG_EVENT)
zlog_debug( zlog_debug(
"Poisone %s/%d on the interface %s with an " "Poison %s/%d on the interface %s with an "
"infinity metric [delete]", "infinity metric [delete]",
inet_ntoa(p->prefix), inet_ntoa(p->prefix),
p->prefixlen, p->prefixlen,
@ -2201,7 +2193,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
for (ALL_LIST_ELEMENTS_RO(list, listnode, for (ALL_LIST_ELEMENTS_RO(list, listnode,
tmp_rinfo)) tmp_rinfo))
if (tmp_rinfo->type == ZEBRA_ROUTE_RIP if (tmp_rinfo->type == ZEBRA_ROUTE_RIP
&& tmp_rinfo->ifindex && tmp_rinfo->nh.ifindex
== ifc->ifp->ifindex) { == ifc->ifp->ifindex) {
suppress = 1; suppress = 1;
break; 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. * to avoid an IGP multi-level recursive look-up.
* see (4.4) * see (4.4)
*/ */
if (rinfo->ifindex == ifc->ifp->ifindex) if (rinfo->nh.ifindex == ifc->ifp->ifindex)
rinfo->nexthop_out = rinfo->nexthop; rinfo->nexthop_out = rinfo->nh.gate.ipv4;
/* Interface route-map */ /* Interface route-map */
if (ri->routemap[RIP_FILTER_OUT]) { 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, for (ALL_LIST_ELEMENTS_RO(list, listnode,
tmp_rinfo)) tmp_rinfo))
if (tmp_rinfo->type == ZEBRA_ROUTE_RIP if (tmp_rinfo->type == ZEBRA_ROUTE_RIP
&& tmp_rinfo->ifindex && tmp_rinfo->nh.ifindex
== ifc->ifp->ifindex) == ifc->ifp->ifindex)
rinfo->metric_out = rinfo->metric_out =
RIP_METRIC_INFINITY; RIP_METRIC_INFINITY;
@ -2647,7 +2639,8 @@ void rip_redistribute_withdraw(int type)
"Poisone %s/%d on the interface %s with an infinity metric [withdraw]", "Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
inet_ntoa(p->prefix), inet_ntoa(p->prefix),
p->prefixlen, p->prefixlen,
ifindex2ifname(rinfo->ifindex, ifindex2ifname(
rinfo->nh.ifindex,
VRF_DEFAULT)); VRF_DEFAULT));
} }
@ -2861,9 +2854,13 @@ DEFUN (rip_route,
{ {
int idx_ipv4_prefixlen = 1; int idx_ipv4_prefixlen = 1;
int ret; int ret;
struct nexthop nh;
struct prefix_ipv4 p; struct prefix_ipv4 p;
struct route_node *node; struct route_node *node;
memset(&nh, 0, sizeof(nh));
nh.type = NEXTHOP_TYPE_IPV4;
ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
if (ret < 0) { if (ret < 0) {
vty_out(vty, "Malformed address\n"); vty_out(vty, "Malformed address\n");
@ -2882,7 +2879,7 @@ DEFUN (rip_route,
node->info = (void *)1; 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); 0, 0);
return CMD_SUCCESS; return CMD_SUCCESS;
@ -3454,14 +3451,30 @@ DEFUN (show_ip_rip,
if (len > 0) if (len > 0)
vty_out(vty, "%*s", len, " "); 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 ", vty_out(vty, "%-20s %2d ",
inet_ntoa(rinfo->nexthop), inet_ntoa(rinfo->nh.gate.ipv4),
rinfo->metric); rinfo->metric);
else break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty, vty_out(vty,
"0.0.0.0 %2d ", "0.0.0.0 %2d ",
rinfo->metric); 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. */ /* Route which exist in kernel routing table. */
if ((rinfo->type == ZEBRA_ROUTE_RIP) if ((rinfo->type == ZEBRA_ROUTE_RIP)

View File

@ -23,6 +23,7 @@
#include "qobj.h" #include "qobj.h"
#include "hook.h" #include "hook.h"
#include "nexthop.h"
#include "rip_memory.h" #include "rip_memory.h"
/* RIP version number. */ /* RIP version number. */
@ -194,12 +195,9 @@ struct rip_info {
int sub_type; int sub_type;
/* RIP nexthop. */ /* RIP nexthop. */
struct in_addr nexthop; struct nexthop nh;
struct in_addr from; struct in_addr from;
/* Which interface does this route come from. */
ifindex_t ifindex;
/* Metric of this route. */ /* Metric of this route. */
u_int32_t metric; 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_neighbor_lookup(struct sockaddr_in *);
extern int rip_redistribute_check(int); extern int rip_redistribute_check(int);
extern void rip_redistribute_add(int, int, struct prefix_ipv4 *, ifindex_t, extern void rip_redistribute_add(int type, int sub_type,
struct in_addr *, unsigned int, unsigned char, struct prefix_ipv4 *p,
route_tag_t); 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_delete(int, int, struct prefix_ipv4 *, ifindex_t);
extern void rip_redistribute_withdraw(int); extern void rip_redistribute_withdraw(int);
extern void rip_zebra_ipv4_add(struct route_node *); extern void rip_zebra_ipv4_add(struct route_node *);