*: The onlink attribute should be owned by the nexthop not the route.

The onlink attribute was being passed from upper level protocols
as an attribute of the route *not* the individual nexthop.  When
we pass this data to the kernel, we treat the onlink as a attribute
of the nexthop.  This commit modifies the code base to allow
us to pass the ONLINK attribute as an attribute of the nexthop.

This commit also fixes static routes that have multiple nexthops
some onlink and some not.

ip route 4.5.6.7/32 192.168.41.1 eveth1 onlink
ip route 4.5.6.7/32 192.168.42.2

S>* 4.5.6.7/32 [1/0] via 192.168.41.1, eveth1 onlink, 00:03:04
  *                  via 192.168.42.2, eveth2, 00:03:04

sharpd@robot ~/frr2> sudo ip netns exec EVA ip route show
4.5.6.7 proto 196 metric 20
	nexthop via 192.168.41.1 dev eveth1 weight 1 onlink
	nexthop via 192.168.42.2 dev eveth2 weight 1

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2019-01-26 20:44:42 -05:00
parent d57e451387
commit fe85601c96
7 changed files with 25 additions and 17 deletions

View File

@ -249,8 +249,6 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
return;
memset(&api, 0, sizeof(api));
if (fabricd)
api.flags |= ZEBRA_FLAG_ONLINK;
api.vrf_id = VRF_DEFAULT;
api.type = PROTO_TYPE;
api.safi = SAFI_UNICAST;
@ -275,6 +273,8 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
if (count >= MULTIPATH_NUM)
break;
api_nh = &api.nexthops[count];
if (fabricd)
api_nh->onlink = true;
api_nh->vrf_id = VRF_DEFAULT;
/* FIXME: can it be ? */
if (nexthop->ip.s_addr != INADDR_ANY) {
@ -298,6 +298,8 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
}
api_nh = &api.nexthops[count];
if (fabricd)
api_nh->onlink = true;
api_nh->vrf_id = VRF_DEFAULT;
api_nh->gate.ipv6 = nexthop6->ip6;
api_nh->ifindex = nexthop6->ifindex;

View File

@ -807,6 +807,7 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
stream_putl(s, api_nh->vrf_id);
stream_putc(s, api_nh->type);
stream_putc(s, api_nh->onlink);
switch (api_nh->type) {
case NEXTHOP_TYPE_BLACKHOLE:
stream_putc(s, api_nh->bh_type);
@ -973,6 +974,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
STREAM_GETL(s, api_nh->vrf_id);
STREAM_GETC(s, api_nh->type);
STREAM_GETC(s, api_nh->onlink);
switch (api_nh->type) {
case NEXTHOP_TYPE_BLACKHOLE:
STREAM_GETC(s, api_nh->bh_type);

View File

@ -306,6 +306,7 @@ struct zapi_nexthop {
enum nexthop_types_t type;
vrf_id_t vrf_id;
ifindex_t ifindex;
bool onlink;
union {
union g_addr gate;
enum blackhole_type bh_type;

View File

@ -446,11 +446,6 @@ extern const char *zserv_command_string(unsigned int command);
* route entry. This mainly is used for backup static routes.
*/
#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
/*
* This flag tells Zebra that the passed down route is ONLINK and the
* kernel install flag for it should be turned on
*/
#define ZEBRA_FLAG_ONLINK 0x80
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */

View File

@ -370,8 +370,6 @@ extern void static_zebra_route_add(struct route_node *rn,
memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix));
}
SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
if (si_changed->onlink)
SET_FLAG(api.flags, ZEBRA_FLAG_ONLINK);
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
if (si_changed->distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
@ -397,6 +395,8 @@ extern void static_zebra_route_add(struct route_node *rn,
continue;
api_nh->vrf_id = si->nh_vrf_id;
api_nh->onlink = si->onlink;
switch (si->type) {
case STATIC_IFNAME:
if (si->ifindex == IFINDEX_INTERNAL)

View File

@ -1521,6 +1521,9 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
XFREE(MTYPE_RE, re);
return;
}
if (api_nh->onlink)
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)
&& api_nh->type != NEXTHOP_TYPE_IFINDEX

View File

@ -277,8 +277,7 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
There was a crash because ifp here was coming to be NULL */
if (ifp)
if (connected_is_unnumbered(ifp)
|| CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)
|| CHECK_FLAG(re->flags, ZEBRA_FLAG_ONLINK)) {
|| CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) {
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
}
@ -315,10 +314,8 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
nexthop->gate.ipv6 = *ipv6;
nexthop->ifindex = ifindex;
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)
|| CHECK_FLAG(re->flags, ZEBRA_FLAG_ONLINK)) {
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
}
route_entry_nexthop_add(re, nexthop);
@ -457,8 +454,15 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
*/
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
if ((ifp && connected_is_unnumbered(ifp))
|| CHECK_FLAG(re->flags, ZEBRA_FLAG_ONLINK)) {
if (!ifp) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
"\t%s: Onlink and interface: %u[%u] does not exist",
__PRETTY_FUNCTION__, nexthop->ifindex,
nexthop->vrf_id);
return 0;
}
if (connected_is_unnumbered(ifp)) {
if (if_is_operative(ifp))
return 1;
else {
@ -468,7 +472,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
__PRETTY_FUNCTION__, ifp->name);
return 0;
}
} else {
}
if (!if_is_operative(ifp)) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
"\t%s: Interface %s is not unnumbered",