From d603c0774ebac58557d8814bdbc2ad16249c21a1 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 17 Mar 2021 18:12:26 +0100 Subject: [PATCH] nhrp, zebra, lib: enforce usage of zapi_neigh_ip structure zapi_nbr structure is renamed to zapi_neigh_ip. Initially used to set a neighbor ip entry for gre interfaces, this structure is used to get events from the zebra layer to nhrp layer. The ndm state has been added, as it is needed on both sides. The zebra dplane layer is slightly modified. Also, to clarify what ZEBRA_NEIGH_ADD/DEL means, a rename is done: it is called now ZEBRA_NEIGH_IP_ADD/DEL, and it signified that this zapi interface permits to set link operations by associating ip addresses to link addresses. Signed-off-by: Philippe Guibert --- lib/log.c | 4 +-- lib/zclient.c | 56 +++++++++++++++++++++++++++++ lib/zclient.h | 16 +++++++-- nhrpd/netlink_arp.c | 48 +++++++++++-------------- nhrpd/nhrp_route.c | 15 ++------ zebra/rt_netlink.c | 13 +++++-- zebra/zapi_msg.c | 85 ++++++++++---------------------------------- zebra/zapi_msg.h | 2 +- zebra/zebra_dplane.c | 11 +++--- zebra/zebra_dplane.h | 3 +- 10 files changed, 130 insertions(+), 123 deletions(-) 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; - - 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); - - 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); - } + struct zapi_neigh_ip api = {}; + + 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; + 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. -- 2.39.5