From c4e1fd52a149a4686b9c1ff1dd4b3a24740eb03b Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 25 Aug 2021 11:40:41 +0200 Subject: [PATCH 1/2] nhrp, zebra, lib: pass exact received neighbor state value to nhrp As NHRP expects some notification of neighboring entries on GRE interface, when a new interface notification is encountered, the exact neighbor state flag is found. Previously, the flag passed to the upper layer was forced to NDM_STATE which is REACHABLE, as can be seen on below trace: 2021/08/25 10:58:39 NHRP: [QQ0NK-1H449] Netlink: new-neigh 102.1.1.1 dev gre1 lladdr 10.125.0.2 nud 0x2 cache used 1 type 5 When passing the real value, NHRP received an other value like STALE. 2021/08/25 11:28:44 NHRP: [QQ0NK-1H449] Netlink: new-neigh 102.1.1.1 dev gre1 lladdr 10.125.0.2 nud 0x4 cache used 0 type 5 This flag is important for NHRP, as it permits to monitor the link layer of NHRP entries. Fixes: d603c0774eba ("nhrp, zebra, lib: enforce usage of zapi_neigh_ip structure") Signed-off-by: Philippe Guibert --- lib/zclient.c | 10 ++++------ lib/zclient.h | 8 +++----- nhrpd/nhrp_route.c | 3 ++- zebra/zapi_msg.c | 3 ++- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index 5ca5849948..a1e7194890 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4487,11 +4487,9 @@ static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add) return -1; } -int zclient_neigh_ip_encode(struct stream *s, - uint16_t cmd, - union sockunion *in, - union sockunion *out, - struct interface *ifp) +int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in, + union sockunion *out, struct interface *ifp, + int ndm_state) { int ret = 0; @@ -4506,7 +4504,7 @@ int zclient_neigh_ip_encode(struct stream *s, stream_putc(s, AF_UNSPEC); stream_putl(s, ifp->ifindex); if (out) - stream_putl(s, ZEBRA_NEIGH_STATE_REACHABLE); + stream_putl(s, ndm_state); else stream_putl(s, ZEBRA_NEIGH_STATE_FAILED); return ret; diff --git a/lib/zclient.h b/lib/zclient.h index a25c5800b7..d24f06b778 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -867,11 +867,9 @@ struct zapi_neigh_ip { 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); +int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in, + union sockunion *out, struct interface *ifp, + int ndm_state); /* * We reserve the top 4 bits for l2-NHG, everything else diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index ee8db277d9..12a2fc2fa0 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -452,7 +452,8 @@ void nhrp_send_zebra_nbr(union sockunion *in, stream_reset(s); zclient_neigh_ip_encode(s, out ? ZEBRA_NEIGH_IP_ADD : ZEBRA_NEIGH_IP_DEL, in, out, - ifp); + ifp, out ? ZEBRA_NEIGH_STATE_REACHABLE + : ZEBRA_NEIGH_STATE_FAILED); stream_putw_at(s, 0, stream_get_endp(s)); zclient_send_message(zclient); } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index ddd6a74c0b..6666b3525e 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -997,7 +997,8 @@ void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp, continue; s = stream_new(ZEBRA_MAX_PACKET_SIZ); - zclient_neigh_ip_encode(s, cmd, &ip, link_layer_ipv4, ifp); + zclient_neigh_ip_encode(s, cmd, &ip, link_layer_ipv4, ifp, + ndm_state); stream_putw_at(s, 0, stream_get_endp(s)); zserv_send_message(client, s); } From 80f6b5faeb62b9d201ddb55af847638dfb88dc8f Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 25 Aug 2021 11:46:42 +0200 Subject: [PATCH 2/2] lib, zebra: complete the ndm flags on zclient api Insist on the fact that zclient neighbor state flags are mapped over netlink state flags. List all the defines currently known on kernel, and create a netlink API to convert netlink values to zclient values. The function is simplified as it is a 1-1 match. Signed-off-by: Philippe Guibert --- lib/zclient.h | 11 ++++++++++- zebra/rt_netlink.c | 15 +++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/zclient.h b/lib/zclient.h index d24f06b778..71187ccae7 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -856,9 +856,18 @@ extern struct zclient_options zclient_options_default; * 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 + * (see linux/neighbour.h) */ +#define ZEBRA_NEIGH_STATE_INCOMPLETE (0x01) #define ZEBRA_NEIGH_STATE_REACHABLE (0x02) -#define ZEBRA_NEIGH_STATE_FAILED (0x20) +#define ZEBRA_NEIGH_STATE_STALE (0x04) +#define ZEBRA_NEIGH_STATE_DELAY (0x08) +#define ZEBRA_NEIGH_STATE_PROBE (0x10) +#define ZEBRA_NEIGH_STATE_FAILED (0x20) +#define ZEBRA_NEIGH_STATE_NOARP (0x40) +#define ZEBRA_NEIGH_STATE_PERMANENT (0x80) +#define ZEBRA_NEIGH_STATE_NONE (0x00) + struct zapi_neigh_ip { int cmd; struct ipaddr ip_in; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 48ccf91ec7..a8b4b54d29 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3658,6 +3658,15 @@ static void netlink_handle_5549(struct ndmsg *ndm, struct zebra_if *zif, #define NUD_LOCAL_ACTIVE \ (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE) +static int netlink_nbr_entry_state_to_zclient(int nbr_state) +{ + /* an exact match is done between + * - netlink neighbor state values: NDM_XXX (see in linux/neighbour.h) + * - zclient neighbor state values: ZEBRA_NEIGH_STATE_XXX + * (see in lib/zclient.h) + */ + return nbr_state; +} static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) { struct ndmsg *ndm; @@ -3747,8 +3756,10 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) &mac, l2_len); } else sockunion_family(&link_layer_ipv4) = AF_UNSPEC; - zsend_nhrp_neighbor_notify(cmd, ifp, &ip, ndm->ndm_state, - &link_layer_ipv4); + zsend_nhrp_neighbor_notify( + cmd, ifp, &ip, + netlink_nbr_entry_state_to_zclient(ndm->ndm_state), + &link_layer_ipv4); } if (h->nlmsg_type == RTM_GETNEIGH)