forked from Mirror/frr
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>
This commit is contained in:
parent
fda64ab443
commit
7723e8d3fd
|
@ -467,7 +467,9 @@ static const struct zebra_desc_table command_types[] = {
|
|||
DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL),
|
||||
DESC_ENTRY(ZEBRA_NHRP_NEIGH_ADDED),
|
||||
DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED),
|
||||
DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET)};
|
||||
DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET),
|
||||
DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER),
|
||||
DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER)};
|
||||
|
||||
#undef DESC_ENTRY
|
||||
|
||||
|
|
|
@ -226,6 +226,8 @@ typedef enum {
|
|||
ZEBRA_NHRP_NEIGH_ADDED,
|
||||
ZEBRA_NHRP_NEIGH_REMOVED,
|
||||
ZEBRA_NHRP_NEIGH_GET,
|
||||
ZEBRA_NHRP_NEIGH_REGISTER,
|
||||
ZEBRA_NHRP_NEIGH_UNREGISTER,
|
||||
} zebra_message_types_t;
|
||||
|
||||
enum zebra_error_types {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in a new issue