diff --git a/lib/log.c b/lib/log.c index ce0b1c9670..ca2f501686 100644 --- a/lib/log.c +++ b/lib/log.c @@ -470,8 +470,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET), DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER), DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER), - DESC_ENTRY(ZEBRA_NEIGH_ADD), - DESC_ENTRY(ZEBRA_NEIGH_DEL), + DESC_ENTRY(ZEBRA_NEIGH_IP_ADD), + DESC_ENTRY(ZEBRA_NEIGH_IP_DEL), DESC_ENTRY(ZEBRA_CONFIGURE_ARP)}; #undef DESC_ENTRY diff --git a/lib/zclient.c b/lib/zclient.c index 8d94fe1aca..d613906d82 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4196,3 +4196,59 @@ char *zclient_evpn_dump_macip_flags(uint8_t flags, char *buf, size_t len) return buf; } + +static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add) +{ + uint8_t family; + + STREAM_GETC(s, family); + if (family != AF_INET && family != AF_INET6) + return -1; + + STREAM_GET(&add->ip.addr, s, family2addrsize(family)); + add->ipa_type = family; + return 0; + stream_failure: + return -1; +} + +int zclient_neigh_ip_encode(struct stream *s, + uint16_t cmd, + union sockunion *in, + union sockunion *out, + struct interface *ifp) +{ + int ret = 0; + + zclient_create_header(s, cmd, ifp->vrf_id); + stream_putc(s, sockunion_family(in)); + stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in)); + if (out && sockunion_family(out) != AF_UNSPEC) { + stream_putc(s, sockunion_family(out)); + stream_write(s, sockunion_get_addr(out), + sockunion_get_addrlen(out)); + } else + stream_putc(s, AF_UNSPEC); + stream_putl(s, ifp->ifindex); + if (out) + stream_putl(s, ZEBRA_NEIGH_STATE_REACHABLE); + else + stream_putl(s, ZEBRA_NEIGH_STATE_FAILED); + return ret; +} + +int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api) +{ + int ret; + + ret = zclient_neigh_ip_read_entry(s, &api->ip_in); + if (ret < 0) + return -1; + zclient_neigh_ip_read_entry(s, &api->ip_out); + + STREAM_GETL(s, api->index); + STREAM_GETL(s, api->ndm_state); + return 0; + stream_failure: + return -1; +} diff --git a/lib/zclient.h b/lib/zclient.h index 25b7103116..90240e40b2 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -229,8 +229,8 @@ typedef enum { ZEBRA_NHRP_NEIGH_GET, ZEBRA_NHRP_NEIGH_REGISTER, ZEBRA_NHRP_NEIGH_UNREGISTER, - ZEBRA_NEIGH_ADD, - ZEBRA_NEIGH_DEL, + ZEBRA_NEIGH_IP_ADD, + ZEBRA_NEIGH_IP_DEL, ZEBRA_CONFIGURE_ARP, } zebra_message_types_t; @@ -809,13 +809,23 @@ extern struct zclient_options zclient_options_default; /* link layer representation for GRE like interfaces * ip_in is the underlay IP, ip_out is the tunnel dest * index stands for the index of the interface + * ndm state stands for the NDM value in netlink */ -struct zapi_nbr { +#define ZEBRA_NEIGH_STATE_REACHABLE (0x02) +#define ZEBRA_NEIGH_STATE_FAILED (0x20) +struct zapi_neigh_ip { int cmd; struct ipaddr ip_in; struct ipaddr ip_out; ifindex_t index; + uint32_t ndm_state; }; +int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api); +int zclient_neigh_ip_encode(struct stream *s, + uint16_t cmd, + union sockunion *in, + union sockunion *out, + struct interface *ifp); /* * We reserve the top 4 bits for l2-NHG, everything else diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index 4cca177c9a..8eab7cd54d 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -154,31 +154,26 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS) { union sockunion addr = {}, lladdr = {}; struct interface *ifp; - ifindex_t idx; - struct ethaddr mac; int state, ndm_state; struct nhrp_cache *c; - unsigned short l2_len; + struct zapi_neigh_ip api = {}; - STREAM_GETL(zclient->ibuf, idx); - ifp = if_lookup_by_index(idx, vrf_id); - STREAM_GETW(zclient->ibuf, addr.sa.sa_family); - if (addr.sa.sa_family == AF_INET) { - STREAM_GET(&addr.sin.sin_addr.s_addr, - zclient->ibuf, IPV4_MAX_BYTELEN); - } else { - STREAM_GET(&addr.sin6.sin6_addr.s6_addr, - zclient->ibuf, IPV6_MAX_BYTELEN); - } - STREAM_GETL(zclient->ibuf, ndm_state); + zclient_neigh_ip_decode(zclient->ibuf, &api); + if (api.ip_in.ipa_type == AF_UNSPEC) + return; + sockunion_family(&addr) = api.ip_in.ipa_type; + memcpy((uint8_t *)sockunion_get_addr(&addr), &api.ip_in.ip.addr, + family2addrsize(api.ip_in.ipa_type)); + + sockunion_family(&lladdr) = api.ip_out.ipa_type; + if (api.ip_out.ipa_type != AF_UNSPEC) + memcpy((uint8_t *)sockunion_get_addr(&lladdr), + &api.ip_out.ip.addr, + family2addrsize(api.ip_out.ipa_type)); + + ifp = if_lookup_by_index(api.index, vrf_id); + ndm_state = api.ndm_state; - STREAM_GETL(zclient->ibuf, l2_len); - if (l2_len) { - STREAM_GET(&mac, zclient->ibuf, l2_len); - if (l2_len == IPV4_MAX_BYTELEN) - sockunion_set(&lladdr, AF_INET, (const uint8_t *)&mac, - l2_len); - } if (!ifp) return; c = nhrp_cache_get(ifp, &addr, 0); @@ -205,12 +200,9 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS) } } else { state = (cmd == ZEBRA_NHRP_NEIGH_ADDED) ? ndm_state - : NUD_FAILED; - nhrp_cache_set_used(c, state == NUD_REACHABLE); + : ZEBRA_NEIGH_STATE_FAILED; + nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE); } - return; - stream_failure: - return; } void netlink_init(void) diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 99f35b79de..23fa0771ef 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -422,18 +422,9 @@ void nhrp_send_zebra_nbr(union sockunion *in, return; s = zclient->obuf; stream_reset(s); - zclient_create_header(s, - out ? ZEBRA_NEIGH_ADD : ZEBRA_NEIGH_DEL, - ifp->vrf_id); - stream_putc(s, sockunion_family(in)); - stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in)); - if (out) { - stream_putc(s, sockunion_family(out)); - stream_write(s, sockunion_get_addr(out), - sockunion_get_addrlen(out)); - } - stream_putl(s, ifp->ifindex); - + zclient_neigh_ip_encode(s, out ? ZEBRA_NEIGH_IP_ADD : + ZEBRA_NEIGH_IP_DEL, in, out, + ifp); stream_putw_at(s, 0, stream_get_endp(s)); zclient_send_message(zclient); } diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index b641d07000..dc0c839674 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3390,9 +3390,18 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) l2_len = RTA_PAYLOAD(tb[NDA_LLADDR]); memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), l2_len); } - if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0) + if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0) { + union sockunion link_layer_ipv4; + + if (l2_len) { + sockunion_family(&link_layer_ipv4) = AF_INET; + memcpy((void *)sockunion_get_addr(&link_layer_ipv4), + &mac, l2_len); + } else + sockunion_family(&link_layer_ipv4) = AF_UNSPEC; zsend_nhrp_neighbor_notify(cmd, ifp, &ip, ndm->ndm_state, - &mac, l2_len); + &link_layer_ipv4); + } if (h->nlmsg_type == RTM_GETNEIGH) return 0; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 46e4766e97..e854d7ff3a 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -976,45 +976,30 @@ void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx, void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp, struct ipaddr *ipaddr, int ndm_state, - void *mac, int macsize) + union sockunion *link_layer_ipv4) { struct stream *s; struct listnode *node, *nnode; struct zserv *client; afi_t afi; + union sockunion ip; if (IS_ZEBRA_DEBUG_PACKET) zlog_debug("%s: Notifying Neighbor entry (%u)", __PRETTY_FUNCTION__, cmd); - if (ipaddr->ipa_type == IPADDR_V4) - afi = AFI_IP; - else if (ipaddr->ipa_type == IPADDR_V6) - afi = AFI_IP6; - else - return; + sockunion_family(&ip) = ipaddr_family(ipaddr); + afi = family2afi(sockunion_family(&ip)); + memcpy((char *)sockunion_get_addr(&ip), &ipaddr->ip.addr, + family2addrsize(sockunion_family(&ip))); + for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { if (!vrf_bitmap_check(client->nhrp_neighinfo[afi], ifp->vrf_id)) continue; s = stream_new(ZEBRA_MAX_PACKET_SIZ); - - zclient_create_header(s, cmd, ifp->vrf_id); - stream_putl(s, ifp->ifindex); - if (ipaddr->ipa_type == IPADDR_V4) { - stream_putw(s, AF_INET); - stream_put(s, &ipaddr->ip._v4_addr, IPV4_MAX_BYTELEN); - } else if (ipaddr->ipa_type == IPADDR_V6) { - stream_putw(s, AF_INET6); - stream_put(s, &ipaddr->ip._v6_addr, IPV6_MAX_BYTELEN); - } else - return; - stream_putl(s, ndm_state); - stream_putl(s, macsize); - if (mac) - stream_put(s, mac, macsize); + zclient_neigh_ip_encode(s, cmd, &ip, link_layer_ipv4, ifp); stream_putw_at(s, 0, stream_get_endp(s)); - zserv_send_message(client, s); } } @@ -3214,38 +3199,6 @@ stream_failure: return; } -static int zebra_neigh_read_ip(struct stream *s, struct ipaddr *add) -{ - uint8_t family; - - STREAM_GETC(s, family); - if (family != AF_INET && family != AF_INET6) - return -1; - - STREAM_GET(&add->ip.addr, s, family2addrsize(family)); - add->ipa_type = family; - return 0; -stream_failure: - return -1; -} - -static int zebra_neigh_get(struct stream *s, struct zapi_nbr *api, bool add) -{ - int ret; - - ret = zebra_neigh_read_ip(s, &api->ip_in); - if (ret < 0) - return -1; - if (add) { - ret = zebra_neigh_read_ip(s, &api->ip_out); - if (ret < 0) - return -1; - } - STREAM_GETL(s, api->index); - return 0; -stream_failure: - return -1; -} static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS) { @@ -3299,43 +3252,41 @@ stream_failure: return; } -static inline void zebra_neigh_add(ZAPI_HANDLER_ARGS) +static inline void zebra_neigh_ip_add(ZAPI_HANDLER_ARGS) { struct stream *s; - struct zapi_nbr api; + struct zapi_neigh_ip api = {}; int ret; const struct interface *ifp; s = msg; - memset(&api, 0, sizeof(api)); - ret = zebra_neigh_get(s, &api, true); + ret = zclient_neigh_ip_decode(s, &api); if (ret < 0) return; ifp = if_lookup_by_index(api.index, zvrf_id(zvrf)); if (!ifp) return; dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_INSTALL, ifp, &api.ip_out, - &api.ip_in, false, client->proto); + &api.ip_in, api.ndm_state, client->proto); } -static inline void zebra_neigh_del(ZAPI_HANDLER_ARGS) +static inline void zebra_neigh_ip_del(ZAPI_HANDLER_ARGS) { struct stream *s; - struct zapi_nbr api; + struct zapi_neigh_ip api = {}; int ret; struct interface *ifp; s = msg; - memset(&api, 0, sizeof(api)); - ret = zebra_neigh_get(s, &api, false); + ret = zclient_neigh_ip_decode(s, &api); if (ret < 0) return; ifp = if_lookup_by_index(api.index, zvrf_id(zvrf)); if (!ifp) return; dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_DELETE, ifp, &api.ip_out, - &api.ip_in, true, client->proto); + &api.ip_in, api.ndm_state, client->proto); } @@ -3524,8 +3475,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request, [ZEBRA_EVPN_REMOTE_NH_ADD] = zebra_evpn_proc_remote_nh, [ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh, - [ZEBRA_NEIGH_ADD] = zebra_neigh_add, - [ZEBRA_NEIGH_DEL] = zebra_neigh_del, + [ZEBRA_NEIGH_IP_ADD] = zebra_neigh_ip_add, + [ZEBRA_NEIGH_IP_DEL] = zebra_neigh_ip_del, [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register, [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister, [ZEBRA_CONFIGURE_ARP] = zebra_configure_arp, diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index 2822619da9..0beb3cc100 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -106,7 +106,7 @@ extern int zsend_sr_policy_notify_status(uint32_t color, int status); extern void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp, struct ipaddr *ipaddr, int ndm_state, - void *mac, int macsize); + union sockunion *link_layer_ipv4); extern int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client); diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 8186ab98a5..c7f396ebf9 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3509,7 +3509,7 @@ enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op, const struct interface *ifp, struct ipaddr *link_ip, struct ipaddr *ip, - bool permanent, int protocol) + uint32_t ndm_state, int protocol) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; uint16_t state = 0; @@ -3523,12 +3523,9 @@ enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op, zlog_debug("init link ctx %s: ifp %s, ip %s link %s", dplane_op2str(op), ifp->name, buf1, buf2); } - if (op == DPLANE_OP_NEIGH_IP_INSTALL) { - if (!permanent) - state = DPLANE_NUD_REACHABLE; - else - state = DPLANE_NUD_PERMANENT; - } else + if (ndm_state == ZEBRA_NEIGH_STATE_REACHABLE) + state = DPLANE_NUD_REACHABLE; + else if (ndm_state == ZEBRA_NEIGH_STATE_FAILED) state = DPLANE_NUD_FAILED; update_flags = DPLANE_NEIGH_NO_EXTENSION; diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index c678706354..8d51d93cd4 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -611,7 +611,8 @@ enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op, const struct interface *ifp, struct ipaddr *link_ip, struct ipaddr *ip, - bool permanent, int protocol); + uint32_t ndm_state, + int protocol); /* * Enqueue evpn mac operations for the dataplane.