Merge pull request #1213 from opensourcerouting/zebra-netlink

Misc RIB/Netlink fixes
This commit is contained in:
Donald Sharp 2017-09-25 14:33:14 -04:00 committed by GitHub
commit 5176f7b713
4 changed files with 56 additions and 110 deletions

View File

@ -57,7 +57,8 @@ pid_t pid_output(const char *path)
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &lock) < 0) { if (fcntl(fd, F_SETLK, &lock) < 0) {
zlog_err("Could not lock pid_file %s, exiting", path); zlog_err("Could not lock pid_file %s (%s), exiting",
path, safe_strerror(errno));
exit(1); exit(1);
} }

View File

@ -526,7 +526,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
if (re->nexthop_num == 0) if (re->nexthop_num == 0)
XFREE(MTYPE_RE, re); XFREE(MTYPE_RE, re);
else else
rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, rib_add_multipath(afi, SAFI_UNICAST, &p,
NULL, re); NULL, re);
} }
} else { } else {
@ -1446,8 +1446,8 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
&& CHECK_FLAG(nexthop->flags, && CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB))) { NEXTHOP_FLAG_FIB))) {
routedesc = nexthop->rparent routedesc = nexthop->rparent
? "recursive, 1 hop" ? "recursive, single-path"
: "single hop"; : "single-path";
_netlink_route_debug(cmd, p, nexthop, routedesc, _netlink_route_debug(cmd, p, nexthop, routedesc,
family, zvrf); family, zvrf);
@ -1529,8 +1529,8 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
&& CHECK_FLAG(nexthop->flags, && CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB))) { NEXTHOP_FLAG_FIB))) {
routedesc = nexthop->rparent routedesc = nexthop->rparent
? "recursive, multihop" ? "recursive, multipath"
: "multihop"; : "multipath";
nexthop_num++; nexthop_num++;
_netlink_route_debug(cmd, p, nexthop, routedesc, _netlink_route_debug(cmd, p, nexthop, routedesc,
@ -2349,6 +2349,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
unsigned int nexthop_num; unsigned int nexthop_num;
const char *routedesc; const char *routedesc;
struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
int route_type;
struct { struct {
struct nlmsghdr n; struct nlmsghdr n;
@ -2382,9 +2383,11 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
} }
} }
if (nexthop_num == 0) // unexpected if (nexthop_num == 0 || !lsp->best_nhlfe) // unexpected
return 0; return 0;
route_type = re_type_from_lsp_type(lsp->best_nhlfe->type);
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
req.n.nlmsg_type = cmd; req.n.nlmsg_type = cmd;
@ -2393,7 +2396,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
req.r.rtm_family = AF_MPLS; req.r.rtm_family = AF_MPLS;
req.r.rtm_table = RT_TABLE_MAIN; req.r.rtm_table = RT_TABLE_MAIN;
req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
req.r.rtm_protocol = RTPROT_ZEBRA; req.r.rtm_protocol = zebra2proto(route_type);
req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_scope = RT_SCOPE_UNIVERSE;
req.r.rtm_type = RTN_UNICAST; req.r.rtm_type = RTN_UNICAST;
@ -2409,7 +2412,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
* chosen depend on the operation. * chosen depend on the operation.
*/ */
if (nexthop_num == 1 || multipath_num == 1) { if (nexthop_num == 1 || multipath_num == 1) {
routedesc = "single hop"; routedesc = "single-path";
_netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
nexthop_num = 0; nexthop_num = 0;
@ -2457,7 +2460,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
rta->rta_len = RTA_LENGTH(0); rta->rta_len = RTA_LENGTH(0);
rtnh = RTA_DATA(rta); rtnh = RTA_DATA(rta);
routedesc = "multihop"; routedesc = "multipath";
_netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
nexthop_num = 0; nexthop_num = 0;

View File

@ -436,6 +436,24 @@ static inline enum lsp_types_t lsp_type_from_re_type(int re_type)
} }
} }
/*
* Map LSP type to RIB type.
*/
static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type)
{
switch (lsp_type) {
case ZEBRA_LSP_STATIC:
return ZEBRA_ROUTE_STATIC;
case ZEBRA_LSP_LDP:
return ZEBRA_ROUTE_LDP;
case ZEBRA_LSP_BGP:
return ZEBRA_ROUTE_BGP;
case ZEBRA_LSP_NONE:
default:
return ZEBRA_ROUTE_KERNEL;
}
}
/* NHLFE type as printable string. */ /* NHLFE type as printable string. */
static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type) static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
{ {

View File

@ -2216,23 +2216,18 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
struct route_entry *same; struct route_entry *same;
struct nexthop *nexthop; struct nexthop *nexthop;
int ret = 0; int ret = 0;
int family;
if (!re) if (!re)
return 0; return 0;
if (p->family == AF_INET) assert(!src_p || afi == AFI_IP6);
family = AFI_IP;
else
family = AFI_IP6;
assert(!src_p || family == AFI_IP6);
/* Lookup table. */ /* Lookup table. */
table = zebra_vrf_table_with_table_id(family, safi, re->vrf_id, table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table);
re->table); if (!table) {
if (!table) XFREE(MTYPE_RE, re);
return 0; return 0;
}
/* Make it sure prefixlen is applied to the prefix. */ /* Make it sure prefixlen is applied to the prefix. */
apply_mask(p); apply_mask(p);
@ -2258,8 +2253,18 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
continue; continue;
if (same->type == re->type && same->instance == re->instance if (same->type != re->type)
&& same->table == re->table && !RIB_SYSTEM_ROUTE(same)) continue;
if (same->instance != re->instance)
continue;
if (same->type == ZEBRA_ROUTE_KERNEL &&
same->metric != re->metric)
continue;
/*
* We should allow duplicate connected routes because of
* IPv6 link-local routes and unnumbered interfaces on Linux.
*/
if (same->type != ZEBRA_ROUTE_CONNECT)
break; break;
} }
@ -2437,70 +2442,10 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
u_int32_t mtu, u_char distance) u_int32_t mtu, u_char distance)
{ {
struct route_entry *re; struct route_entry *re;
struct route_entry *same = NULL; struct nexthop *nexthop;
struct route_table *table;
struct route_node *rn;
struct nexthop *rtnh;
assert(!src_p || afi == AFI_IP6); /* Allocate new route_entry structure. */
/* Lookup table. */
table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id);
if (!table)
return 0;
/* Make sure mask is applied. */
apply_mask(p);
if (src_p)
apply_mask_ipv6(src_p);
/* Set default distance by route type. */
if (distance == 0) {
distance = route_distance(type);
/* iBGP distance is 200. */
if (type == ZEBRA_ROUTE_BGP
&& CHECK_FLAG(flags, ZEBRA_FLAG_IBGP))
distance = 200;
}
/* Lookup route node.*/
rn = srcdest_rnode_get(table, p, src_p);
/* If same type of route are installed, treat it as a implicit
withdraw. */
RNODE_FOREACH_RE (rn, re) {
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
continue;
if (re->type != type)
continue;
if (re->instance != instance)
continue;
if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != metric)
continue;
if (!RIB_SYSTEM_ROUTE(re)) {
same = re;
break;
}
/* Duplicate system route comes in. */
rtnh = re->nexthop;
if (nexthop_same_no_recurse(rtnh, nh))
return 0;
/*
* Nexthop is different. Remove the old route unless it's
* a connected route. This exception is necessary because
* of IPv6 link-local routes and unnumbered interfaces on
* Linux.
*/
else if (type != ZEBRA_ROUTE_CONNECT)
same = re;
}
/* Allocate new re structure. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
re->type = type; re->type = type;
re->instance = instance; re->instance = instance;
re->distance = distance; re->distance = distance;
@ -2512,33 +2457,12 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
re->nexthop_num = 0; re->nexthop_num = 0;
re->uptime = time(NULL); re->uptime = time(NULL);
rtnh = nexthop_new(); /* Add nexthop. */
*rtnh = *nh; nexthop = nexthop_new();
route_entry_nexthop_add(re, rtnh); *nexthop = *nh;
route_entry_nexthop_add(re, nexthop);
/* If this route is kernel route, set FIB flag to the route. */ return rib_add_multipath(afi, safi, p, src_p, re);
if (RIB_SYSTEM_ROUTE(re))
for (rtnh = re->nexthop; rtnh; rtnh = rtnh->next)
SET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB);
/* Link new rib to node.*/
if (IS_ZEBRA_DEBUG_RIB) {
rnode_debug(
rn, vrf_id,
"Inserting route rn %p, re %p (type %d) existing %p",
(void *)rn, (void *)re, re->type, (void *)same);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
route_entry_dump(p, src_p, re);
}
rib_addnode(rn, re, 1);
/* Free implicit route.*/
if (same)
rib_delnode(rn, same);
route_unlock_node(rn);
return 0;
} }
/* Schedule routes of a particular table (address-family) based on event. */ /* Schedule routes of a particular table (address-family) based on event. */