diff --git a/lib/pid_output.c b/lib/pid_output.c index e2e4434150..9a7307bc4f 100644 --- a/lib/pid_output.c +++ b/lib/pid_output.c @@ -57,7 +57,8 @@ pid_t pid_output(const char *path) lock.l_whence = SEEK_SET; 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); } diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 039fac4e67..d67d670277 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -526,7 +526,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, if (re->nexthop_num == 0) XFREE(MTYPE_RE, re); else - rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, + rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, re); } } else { @@ -1446,8 +1446,8 @@ static int netlink_route_multipath(int cmd, struct prefix *p, && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { routedesc = nexthop->rparent - ? "recursive, 1 hop" - : "single hop"; + ? "recursive, single-path" + : "single-path"; _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); @@ -1529,8 +1529,8 @@ static int netlink_route_multipath(int cmd, struct prefix *p, && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { routedesc = nexthop->rparent - ? "recursive, multihop" - : "multihop"; + ? "recursive, multipath" + : "multipath"; nexthop_num++; _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; const char *routedesc; struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + int route_type; struct { 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; + route_type = re_type_from_lsp_type(lsp->best_nhlfe->type); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; 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_table = RT_TABLE_MAIN; 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_type = RTN_UNICAST; @@ -2409,7 +2412,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) * chosen depend on the operation. */ if (nexthop_num == 1 || multipath_num == 1) { - routedesc = "single hop"; + routedesc = "single-path"; _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); nexthop_num = 0; @@ -2457,7 +2460,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) rta->rta_len = RTA_LENGTH(0); rtnh = RTA_DATA(rta); - routedesc = "multihop"; + routedesc = "multipath"; _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); nexthop_num = 0; diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 51279798a4..22c771c348 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -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. */ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type) { diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index bb49663319..622e001285 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2216,23 +2216,18 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, struct route_entry *same; struct nexthop *nexthop; int ret = 0; - int family; if (!re) return 0; - if (p->family == AF_INET) - family = AFI_IP; - else - family = AFI_IP6; - - assert(!src_p || family == AFI_IP6); + assert(!src_p || afi == AFI_IP6); /* Lookup table. */ - table = zebra_vrf_table_with_table_id(family, safi, re->vrf_id, - re->table); - if (!table) + table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table); + if (!table) { + XFREE(MTYPE_RE, re); return 0; + } /* Make it sure prefixlen is applied to the prefix. */ 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)) continue; - if (same->type == re->type && same->instance == re->instance - && same->table == re->table && !RIB_SYSTEM_ROUTE(same)) + if (same->type != re->type) + 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; } @@ -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) { struct route_entry *re; - struct route_entry *same = NULL; - struct route_table *table; - struct route_node *rn; - struct nexthop *rtnh; + struct nexthop *nexthop; - assert(!src_p || afi == AFI_IP6); - - /* 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. */ + /* Allocate new route_entry structure. */ re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); - re->type = type; re->instance = instance; 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->uptime = time(NULL); - rtnh = nexthop_new(); - *rtnh = *nh; - route_entry_nexthop_add(re, rtnh); + /* Add nexthop. */ + nexthop = nexthop_new(); + *nexthop = *nh; + route_entry_nexthop_add(re, nexthop); - /* If this route is kernel route, set FIB flag to the route. */ - 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; + return rib_add_multipath(afi, safi, p, src_p, re); } /* Schedule routes of a particular table (address-family) based on event. */