diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 153 |
1 files changed, 117 insertions, 36 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 50b1a62d86..1ce3c435fe 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -126,6 +126,31 @@ static bool kernel_nexthops_supported(void) } /* + * Some people may only want to use NHGs created by protos and not + * implicitly created by Zebra. This check accounts for that. + */ +static bool proto_nexthops_only(void) +{ + return zebra_nhg_proto_nexthops_only(); +} + +/* Is this a proto created NHG? */ +static bool is_proto_nhg(uint32_t id, int type) +{ + /* If type is available, use it as the source of truth */ + if (type) { + if (type != ZEBRA_ROUTE_NHG) + return true; + return false; + } + + if (id >= ZEBRA_NHG_PROTO_LOWER) + return true; + + return false; +} + +/* * The ipv4_ll data structure is used for all 5549 * additions to the kernel. Let's figure out the * correct value one time instead for every @@ -643,6 +668,11 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, return 0; } + if (rtm->rtm_flags & RTM_F_TRAP) + flags |= ZEBRA_FLAG_TRAPPED; + if (rtm->rtm_flags & RTM_F_OFFLOAD) + flags |= ZEBRA_FLAG_OFFLOADED; + /* Route which inserted by Zebra. */ if (selfroute) { flags |= ZEBRA_FLAG_SELFROUTE; @@ -1743,7 +1773,10 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, nl_attr_nest_end(&req->n, nest); } - if ((!fpm && kernel_nexthops_supported()) || (fpm && force_nhg)) { + if ((!fpm && kernel_nexthops_supported() + && (!proto_nexthops_only() + || is_proto_nhg(dplane_ctx_get_nhe_id(ctx), 0))) + || (fpm && force_nhg)) { /* Kernel supports nexthop objects */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s: %pFX nhg_id is %u", __func__, p, @@ -2067,6 +2100,35 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, mpls_lse_t out_lse[MPLS_MAX_LABELS]; char label_buf[256]; int num_labels = 0; + uint32_t id = dplane_ctx_get_nhe_id(ctx); + int type = dplane_ctx_get_nhe_type(ctx); + + if (!id) { + flog_err( + EC_ZEBRA_NHG_FIB_UPDATE, + "Failed trying to update a nexthop group in the kernel that does not have an ID"); + return -1; + } + + /* + * Nothing to do if the kernel doesn't support nexthop objects or + * we dont want to install this type of NHG + */ + if (!kernel_nexthops_supported()) { + if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: nhg_id %u (%s): kernel nexthops not supported, ignoring", + __func__, id, zebra_route_string(type)); + return 0; + } + + if (proto_nexthops_only() && !is_proto_nhg(id, type)) { + if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: nhg_id %u (%s): proto-based nexthops only, ignoring", + __func__, id, zebra_route_string(type)); + return 0; + } label_buf[0] = '\0'; @@ -2087,15 +2149,6 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, req->nhm.nh_family = AF_UNSPEC; /* TODO: Scope? */ - uint32_t id = dplane_ctx_get_nhe_id(ctx); - - if (!id) { - flog_err( - EC_ZEBRA_NHG_FIB_UPDATE, - "Failed trying to update a nexthop group in the kernel that does not have an ID"); - return -1; - } - if (!nl_attr_put32(&req->n, buflen, NHA_ID, id)) return 0; @@ -2216,8 +2269,7 @@ nexthop_done: nh->vrf_id, label_buf); } - req->nhm.nh_protocol = - zebra2proto(dplane_ctx_get_nhe_type(ctx)); +req->nhm.nh_protocol = zebra2proto(type); } else if (cmd != RTM_DELNEXTHOP) { flog_err( @@ -2680,9 +2732,9 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, static ssize_t netlink_neigh_update_msg_encode( const struct zebra_dplane_ctx *ctx, int cmd, const struct ethaddr *mac, const struct ipaddr *ip, bool replace_obj, uint8_t family, uint8_t type, - uint8_t flags, uint16_t state, uint32_t nhg_id, - bool nfy, uint8_t nfy_flags, - void *data, size_t datalen) + uint8_t flags, uint16_t state, uint32_t nhg_id, bool nfy, + uint8_t nfy_flags, bool ext, uint32_t ext_flags, void *data, + size_t datalen) { uint8_t protocol = RTPROT_ZEBRA; struct { @@ -2731,6 +2783,12 @@ static ssize_t netlink_neigh_update_msg_encode( return 0; } + if (ext) { + if (!nl_attr_put(&req->n, datalen, NDA_EXT_FLAGS, &ext_flags, + sizeof(ext_flags))) + return 0; + } + ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; if (!nl_attr_put(&req->n, datalen, NDA_DST, &ip->ip.addr, ipa_len)) return 0; @@ -2764,7 +2822,8 @@ netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx, int cmd, return netlink_neigh_update_msg_encode( ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false, PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT), 0 /*nhg*/, - false /*nfy*/, 0 /*nfy_flags*/, buf, buflen); + false /*nfy*/, 0 /*nfy_flags*/, false /*ext*/, 0 /*ext_flags*/, + buf, buflen); } #ifndef NDA_RTA @@ -3174,30 +3233,26 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data, else vid_buf[0] = '\0'; - zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s dst %s nhg %u%s%s%s%s%s", - nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE), - dplane_ctx_get_ifname(ctx), - dplane_ctx_get_ifindex(ctx), vid_buf, - dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "", - prefix_mac2str(mac, buf, sizeof(buf)), - ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)), - nhg_id, - (update_flags & - DPLANE_MAC_REMOTE) ? " rem" : "", - (update_flags & - DPLANE_MAC_WAS_STATIC) ? " clr_sync" : "", - (update_flags & - DPLANE_MAC_SET_STATIC) ? " static" : "", - (update_flags & - DPLANE_MAC_SET_INACTIVE) ? " inactive" : "", - (nfy & - DPLANE_MAC_SET_INACTIVE) ? " nfy" : ""); + zlog_debug( + "Tx %s family %s IF %s(%u)%s %sMAC %s dst %s nhg %u%s%s%s%s%s", + nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE), + dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx), + vid_buf, dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "", + prefix_mac2str(mac, buf, sizeof(buf)), + ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)), nhg_id, + (update_flags & DPLANE_MAC_REMOTE) ? " rem" : "", + (update_flags & DPLANE_MAC_WAS_STATIC) ? " clr_sync" + : "", + (update_flags & DPLANE_MAC_SET_STATIC) ? " static" : "", + (update_flags & DPLANE_MAC_SET_INACTIVE) ? " inactive" + : "", + nfy ? " nfy" : ""); } total = netlink_neigh_update_msg_encode( ctx, cmd, dplane_ctx_mac_get_addr(ctx), &vtep_ip, true, AF_BRIDGE, 0, flags, state, nhg_id, nfy, nfy_flags, - data, datalen); + false /*ext*/, 0 /*ext_flags*/, data, datalen); return total; } @@ -3598,17 +3653,42 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx, uint8_t flags; uint16_t state; uint8_t family; + uint32_t update_flags; + uint32_t ext_flags = 0; + bool ext = false; ip = dplane_ctx_neigh_get_ipaddr(ctx); mac = dplane_ctx_neigh_get_mac(ctx); if (is_zero_mac(mac)) mac = NULL; + update_flags = dplane_ctx_neigh_get_update_flags(ctx); flags = neigh_flags_to_netlink(dplane_ctx_neigh_get_flags(ctx)); state = neigh_state_to_netlink(dplane_ctx_neigh_get_state(ctx)); family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; + if (update_flags & DPLANE_NEIGH_REMOTE) { + flags |= NTF_EXT_LEARNED; + /* if it was static-local previously we need to clear the + * ext flags on replace with remote + */ + if (update_flags & DPLANE_NEIGH_WAS_STATIC) + ext = true; + } else { + ext = true; + /* local neigh */ + if (update_flags & DPLANE_NEIGH_SET_STATIC) + ext_flags |= NTF_E_MH_PEER_SYNC; + + /* the ndm_state set for local entries can be REACHABLE or + * STALE. if the dataplane has already establish reachability + * (in the meantime) FRR must not over-write it with STALE. + * this accidental race/over-write is avoided by using the + * WEAK_OVERRIDE_STATE + */ + ext_flags |= NTF_E_WEAK_OVERRIDE_STATE; + } if (IS_ZEBRA_DEBUG_KERNEL) { char buf[INET6_ADDRSTRLEN]; char buf2[ETHER_ADDR_STRLEN]; @@ -3624,7 +3704,8 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx, return netlink_neigh_update_msg_encode( ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags, state, - 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, buf, buflen); + 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, ext, ext_flags, buf, + buflen); } static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx, |
