diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 85 |
1 files changed, 48 insertions, 37 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 573f60f4ca..0cc2e0217f 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -267,7 +267,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, struct rtattr *tb[RTA_MAX + 1]; u_char flags = 0; struct prefix p; - struct prefix_ipv6 src_p; + struct prefix_ipv6 src_p = {}; vrf_id_t vrf_id = VRF_DEFAULT; char anyaddr[16] = {0}; @@ -277,6 +277,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, int table; int metric = 0; u_int32_t mtu = 0; + uint8_t distance = 0; void *dest = NULL; void *gate = NULL; @@ -405,16 +406,38 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, return 0; } + /* + * For ZEBRA_ROUTE_KERNEL types: + * + * The metric/priority of the route received from the kernel + * is a 32 bit number. We are going to interpret the high + * order byte as the Admin Distance and the low order 3 bytes + * as the metric. + * + * This will allow us to do two things: + * 1) Allow the creation of kernel routes that can be + * overridden by zebra. + * 2) Allow the old behavior for 'most' kernel route types + * if a user enters 'ip route ...' v4 routes get a metric + * of 0 and v6 routes get a metric of 1024. Both of these + * values will end up with a admin distance of 0, which + * will cause them to win for the purposes of zebra. + */ + if (proto == ZEBRA_ROUTE_KERNEL) { + distance = (metric >> 24) & 0xFF; + metric = (metric & 0x00FFFFFF); + } + if (IS_ZEBRA_DEBUG_KERNEL) { char buf[PREFIX_STRLEN]; char buf2[PREFIX_STRLEN]; zlog_debug( - "%s %s%s%s vrf %u", nl_msg_type_to_str(h->nlmsg_type), + "%s %s%s%s vrf %u metric: %d Admin Distance: %d", nl_msg_type_to_str(h->nlmsg_type), prefix2str(&p, buf, sizeof(buf)), src_p.prefixlen ? " from " : "", src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", - vrf_id); + vrf_id, metric, distance); } afi_t afi = AFI_IP; @@ -454,7 +477,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, memcpy(&nh.gate, gate, sz); rib_add(afi, SAFI_UNICAST, vrf_id, proto, - 0, flags, &p, NULL, &nh, table, metric, mtu, 0); + 0, flags, &p, NULL, &nh, table, metric, mtu, distance); } else { /* This is a multipath route */ @@ -466,7 +489,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); re->type = proto; - re->distance = 0; + re->distance = distance; re->flags = flags; re->metric = metric; re->mtu = mtu; @@ -822,7 +845,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, { struct nexthop_label *nh_label; mpls_lse_t out_lse[MPLS_MAX_LABELS]; - char label_buf[100]; + char label_buf[256]; /* * label_buf is *only* currently used within debugging. @@ -853,12 +876,13 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, 0, 0, bos); if (IS_ZEBRA_DEBUG_KERNEL) { if (!num_labels) - sprintf(label_buf, "label %d", + sprintf(label_buf, "label %u", nh_label->label[i]); else { - sprintf(label_buf1, "/%d", + sprintf(label_buf1, "/%u", nh_label->label[i]); - strcat(label_buf, label_buf1); + strlcat(label_buf, label_buf1, + sizeof(label_buf)); } } num_labels++; @@ -1021,7 +1045,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, { struct nexthop_label *nh_label; mpls_lse_t out_lse[MPLS_MAX_LABELS]; - char label_buf[100]; + char label_buf[256]; rtnh->rtnh_len = sizeof(*rtnh); rtnh->rtnh_flags = 0; @@ -1057,12 +1081,13 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, 0, 0, bos); if (IS_ZEBRA_DEBUG_KERNEL) { if (!num_labels) - sprintf(label_buf, "label %d", + sprintf(label_buf, "label %u", nh_label->label[i]); else { - sprintf(label_buf1, "/%d", + sprintf(label_buf1, "/%u", nh_label->label[i]); - strcat(label_buf, label_buf1); + strlcat(label_buf, label_buf1, + sizeof(label_buf)); } } num_labels++; @@ -1716,7 +1741,6 @@ static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h, struct ndmsg *ndm; struct interface *ifp; struct zebra_if *zif; - struct zebra_vrf *zvrf; struct rtattr *tb[NDA_MAX + 1]; struct interface *br_if; struct ethaddr mac; @@ -1730,20 +1754,14 @@ static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h, ndm = NLMSG_DATA(h); + /* We only process macfdb notifications if EVPN is enabled */ + if (!is_evpn_enabled()) + return 0; + /* The interface should exist. */ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ndm->ndm_ifindex); - if (!ifp) - return 0; - - /* Locate VRF corresponding to interface. We only process MAC - * notifications - * if EVPN is enabled on this VRF. - */ - zvrf = vrf_info_lookup(ifp->vrf_id); - if (!zvrf || !EVPN_ENABLED(zvrf)) - return 0; - if (!ifp->info) + if (!ifp || !ifp->info) return 0; /* The interface should be something we're interested in. */ @@ -2033,7 +2051,6 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, struct ndmsg *ndm; struct interface *ifp; struct zebra_if *zif; - struct zebra_vrf *zvrf; struct rtattr *tb[NDA_MAX + 1]; struct interface *link_if; struct ethaddr mac; @@ -2045,20 +2062,14 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, ndm = NLMSG_DATA(h); + /* We only process neigh notifications if EVPN is enabled */ + if (!is_evpn_enabled()) + return 0; + /* The interface should exist. */ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ndm->ndm_ifindex); - if (!ifp) - return 0; - - /* Locate VRF corresponding to interface. We only process neigh - * notifications - * if EVPN is enabled on this VRF. - */ - zvrf = vrf_info_lookup(ifp->vrf_id); - if (!zvrf || !EVPN_ENABLED(zvrf)) - return 0; - if (!ifp->info) + if (!ifp || !ifp->info) return 0; /* Drop "permanent" entries. */ |
