diff options
author | Philippe Guibert <philippe.guibert@6wind.com> | 2019-12-12 16:06:59 +0100 |
---|---|---|
committer | Philippe Guibert <philippe.guibert@6wind.com> | 2021-04-09 18:29:58 +0200 |
commit | 7723e8d3fd86a2e00b99df6fbb64083c23c1e637 (patch) | |
tree | fd558e4e24409dc4487ae53ca6ec98e487b48ce7 /zebra | |
parent | lib: link layer neighbor registration and notification, define API msgs (diff) | |
download | frr-7723e8d3fd86a2e00b99df6fbb64083c23c1e637.tar.xz frr-7723e8d3fd86a2e00b99df6fbb64083c23c1e637.zip |
zebra: link layer config and notification, implementation in zebra
zebra implements zebra api for configuring link layer information. that
can be an arp entry (for ipv4) or ipv6 neighbor discovery entry. This
can also be an ipv4/ipv6 entry associated to an underlay ipv4 address,
as it is used in gre point to multipoint interfaces.
this api will also be used as monitoring. an hash list is instantiated
into zebra (this is the vrf bitmap). each client interested in those entries
in a specific vrf, will listen for following messages: entries added, removed,
or who-has messages.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/rt.h | 2 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 33 | ||||
-rw-r--r-- | zebra/rt_socket.c | 6 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 81 | ||||
-rw-r--r-- | zebra/zapi_msg.h | 3 | ||||
-rw-r--r-- | zebra/zserv.c | 2 | ||||
-rw-r--r-- | zebra/zserv.h | 3 |
7 files changed, 129 insertions, 1 deletions
diff --git a/zebra/rt.h b/zebra/rt.h index 48f1df286..00ff37875 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -70,6 +70,8 @@ kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx); extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, int llalen, ns_id_t ns_id); +extern int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, + bool reg); extern int kernel_interface_set_master(struct interface *master, struct interface *slave); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 55e0775a8..82ef78d29 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3307,6 +3307,8 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) bool local_inactive; uint32_t ext_flags = 0; bool dp_static = false; + int l2_len = 0; + int cmd; ndm = NLMSG_DATA(h); @@ -3348,6 +3350,34 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (h->nlmsg_type == RTM_NEWNEIGH && !(ndm->ndm_state & NUD_VALID)) netlink_handle_5549(ndm, zif, ifp, &ip, true); + /* we send link layer information to client: + * - nlmsg_type = RTM_DELNEIGH|NEWNEIGH|GETNEIGH + * - struct ipaddr ( for DEL and GET) + * - struct ethaddr mac; (for NEW) + */ + if (h->nlmsg_type == RTM_NEWNEIGH) + cmd = ZEBRA_NHRP_NEIGH_ADDED; + else if (h->nlmsg_type == RTM_GETNEIGH) + cmd = ZEBRA_NHRP_NEIGH_GET; + else if (h->nlmsg_type == RTM_DELNEIGH) + cmd = ZEBRA_NHRP_NEIGH_REMOVED; + else { + zlog_debug("%s(): unknown nlmsg type %u", __func__, + h->nlmsg_type); + return 0; + } + if (tb[NDA_LLADDR]) { + /* copy LLADDR information */ + 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) + zsend_nhrp_neighbor_notify(cmd, ifp, &ip, ndm->ndm_state, + &mac, l2_len); + + if (h->nlmsg_type == RTM_GETNEIGH) + return 0; + /* The neighbor is present on an SVI. From this, we locate the * underlying * bridge because we're only interested in neighbors on a VxLAN bridge. @@ -3615,7 +3645,8 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id) int len; struct ndmsg *ndm; - if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH)) + if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH + || h->nlmsg_type == RTM_GETNEIGH)) return 0; /* Length validity. */ diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index a0f401c33..5fdf58962 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -362,6 +362,12 @@ enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx) return ZEBRA_DPLANE_REQUEST_SUCCESS; } +int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, bool reg) +{ + /* TODO */ + return 0; +} + int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, int llalen, ns_id_t ns_id) { diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index b48291441..304a6a03f 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -974,6 +974,52 @@ void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx, zserv_send_message(client, s); } +void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp, + struct ipaddr *ipaddr, int ndm_state, + void *mac, int macsize) +{ + struct stream *s; + struct listnode *node, *nnode; + struct zserv *client; + afi_t afi; + + 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; + 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); + stream_putw_at(s, 0, stream_get_endp(s)); + + zserv_send_message(client, s); + } +} + + /* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */ int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p, vrf_id_t vrf_id) @@ -2277,6 +2323,7 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS) vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf)); vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf)); vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf)); + vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf)); } } @@ -3167,6 +3214,38 @@ stream_failure: return; } +static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS) +{ + afi_t afi; + + STREAM_GETW(msg, afi); + if (afi <= AFI_UNSPEC || afi >= AFI_MAX) { + zlog_warn( + "Invalid AFI %u while registering for neighbors notifications", + afi); + goto stream_failure; + } + vrf_bitmap_set(client->nhrp_neighinfo[afi], zvrf_id(zvrf)); +stream_failure: + return; +} + +static inline void zebra_neigh_unregister(ZAPI_HANDLER_ARGS) +{ + afi_t afi; + + STREAM_GETW(msg, afi); + if (afi <= AFI_UNSPEC || afi >= AFI_MAX) { + zlog_warn( + "Invalid AFI %u while unregistering from neighbor notifications", + afi); + goto stream_failure; + } + vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf)); +stream_failure: + return; +} + static inline void zread_iptable(ZAPI_HANDLER_ARGS) { struct zebra_pbr_iptable *zpi = @@ -3352,6 +3431,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_NHRP_NEIGH_REGISTER] = zebra_neigh_register, + [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister, }; /* diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index ca471f8d9..2822619da 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -104,6 +104,9 @@ extern int zsend_label_manager_connect_response(struct zserv *client, extern int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint, char *name, int status); +extern void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp, + struct ipaddr *ipaddr, int ndm_state, + void *mac, int macsize); extern int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client); diff --git a/zebra/zserv.c b/zebra/zserv.c index 6c5eebe6f..f89b6fe47 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -638,6 +638,7 @@ static void zserv_client_free(struct zserv *client) vrf_bitmap_free(client->redist_default[afi]); vrf_bitmap_free(client->ridinfo[afi]); + vrf_bitmap_free(client->nhrp_neighinfo[afi]); } /* @@ -760,6 +761,7 @@ static struct zserv *zserv_client_create(int sock) client->redist[afi][i] = vrf_bitmap_init(); client->redist_default[afi] = vrf_bitmap_init(); client->ridinfo[afi] = vrf_bitmap_init(); + client->nhrp_neighinfo[afi] = vrf_bitmap_init(); } /* Add this client to linked list. */ diff --git a/zebra/zserv.h b/zebra/zserv.h index c60799b8b..203670ac1 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -137,6 +137,9 @@ struct zserv { /* Router-id information. */ vrf_bitmap_t ridinfo[AFI_MAX]; + /* Router-id information. */ + vrf_bitmap_t nhrp_neighinfo[AFI_MAX]; + bool notify_owner; /* Indicates if client is synchronous. */ |