mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-02-01 18:56:52 +00:00
lib, zebra: add support for sending ARP requests
We can make the Linux kernel send an ARP/NDP request by adding a neighbour with the 'NUD_INCOMPLETE' state and the 'NTF_USE' flag. This commit adds new dataplane operation as well as new zapi message to allow other daemons send ARP/NDP requests. Signed-off-by: Jakub Urbańczyk <xthaid@gmail.com>
This commit is contained in:
parent
c2e6684110
commit
d68e74b41c
@ -382,9 +382,11 @@ Zebra Protocol Commands
|
||||
+------------------------------------+-------+
|
||||
| ZEBRA_OPAQUE_UNREGISTER | 109 |
|
||||
+------------------------------------+-------+
|
||||
| ZEBRA_NEIGH_DISCOVER | 110 |
|
||||
+------------------------------------+-------+
|
||||
|
||||
Dataplane batching
|
||||
=========================
|
||||
==================
|
||||
|
||||
Dataplane batching is an optimization feature that reduces the processing
|
||||
time involved in the user space to kernel space transition for every message we
|
||||
|
||||
@ -138,3 +138,9 @@ keyword. At present, no sharp commands will be preserved in the config.
|
||||
|
||||
Remove a test zapi client session that was created with the
|
||||
specified session id.
|
||||
|
||||
.. index:: sharp neigh discover
|
||||
.. clicmd:: sharp neigh discover [vrf NAME] <A.B.C.D|X:X::X:X> IFNAME
|
||||
|
||||
Send an ARP/NDP request to trigger the addition of a neighbor in the ARP
|
||||
table.
|
||||
|
||||
@ -451,7 +451,8 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES),
|
||||
DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE),
|
||||
DESC_ENTRY(ZEBRA_OPAQUE_REGISTER),
|
||||
DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER)};
|
||||
DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER),
|
||||
DESC_ENTRY(ZEBRA_NEIGH_DISCOVER)};
|
||||
#undef DESC_ENTRY
|
||||
|
||||
static const struct zebra_desc_table unknown = {0, "unknown", '?'};
|
||||
|
||||
@ -3953,3 +3953,23 @@ int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
|
||||
stream_failure:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zclient_send_neigh_discovery_req(struct zclient *zclient,
|
||||
const struct interface *ifp,
|
||||
const struct prefix *p)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf_id);
|
||||
stream_putl(s, ifp->ifindex);
|
||||
|
||||
stream_putc(s, p->family);
|
||||
stream_putc(s, p->prefixlen);
|
||||
stream_put(s, &p->u.prefix, prefix_blen(p));
|
||||
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
@ -214,6 +214,7 @@ typedef enum {
|
||||
ZEBRA_OPAQUE_MESSAGE,
|
||||
ZEBRA_OPAQUE_REGISTER,
|
||||
ZEBRA_OPAQUE_UNREGISTER,
|
||||
ZEBRA_NEIGH_DISCOVER,
|
||||
} zebra_message_types_t;
|
||||
|
||||
enum zebra_error_types {
|
||||
@ -956,6 +957,10 @@ enum zapi_opaque_registry {
|
||||
*/
|
||||
extern int zclient_send_hello(struct zclient *client);
|
||||
|
||||
extern int zclient_send_neigh_discovery_req(struct zclient *zclient,
|
||||
const struct interface *ifp,
|
||||
const struct prefix *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1417,6 +1417,7 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
|
||||
case DPLANE_OP_NEIGH_DELETE:
|
||||
case DPLANE_OP_VTEP_ADD:
|
||||
case DPLANE_OP_VTEP_DELETE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
return netlink_put_neigh_update_msg(bth, ctx);
|
||||
|
||||
case DPLANE_OP_RULE_ADD:
|
||||
|
||||
@ -1526,6 +1526,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
|
||||
case DPLANE_OP_NEIGH_DELETE:
|
||||
case DPLANE_OP_VTEP_ADD:
|
||||
case DPLANE_OP_VTEP_DELETE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
res = kernel_neigh_update_ctx(ctx);
|
||||
break;
|
||||
|
||||
|
||||
@ -147,6 +147,8 @@ static uint8_t neigh_flags_to_netlink(uint8_t dplane_flags)
|
||||
flags |= NTF_EXT_LEARNED;
|
||||
if (dplane_flags & DPLANE_NTF_ROUTER)
|
||||
flags |= NTF_ROUTER;
|
||||
if (dplane_flags & DPLANE_NTF_USE)
|
||||
flags |= NTF_USE;
|
||||
|
||||
return flags;
|
||||
}
|
||||
@ -166,6 +168,8 @@ static uint16_t neigh_state_to_netlink(uint16_t dplane_state)
|
||||
state |= NUD_NOARP;
|
||||
if (dplane_state & DPLANE_NUD_PROBE)
|
||||
state |= NUD_PROBE;
|
||||
if (dplane_state & DPLANE_NUD_INCOMPLETE)
|
||||
state |= NUD_INCOMPLETE;
|
||||
|
||||
return state;
|
||||
}
|
||||
@ -3631,6 +3635,7 @@ static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
|
||||
switch (dplane_ctx_get_op(ctx)) {
|
||||
case DPLANE_OP_NEIGH_INSTALL:
|
||||
case DPLANE_OP_NEIGH_UPDATE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
ret = netlink_neigh_update_ctx(ctx, RTM_NEWNEIGH, buf, buflen);
|
||||
break;
|
||||
case DPLANE_OP_NEIGH_DELETE:
|
||||
|
||||
@ -2962,6 +2962,41 @@ stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void zread_neigh_discover(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
ifindex_t ifindex;
|
||||
struct interface *ifp;
|
||||
struct prefix p;
|
||||
struct ipaddr ip;
|
||||
|
||||
s = msg;
|
||||
|
||||
STREAM_GETL(s, ifindex);
|
||||
|
||||
ifp = if_lookup_by_index_per_ns(zvrf->zns, ifindex);
|
||||
if (!ifp) {
|
||||
zlog_debug("Failed to lookup ifindex: %u", ifindex);
|
||||
return;
|
||||
}
|
||||
|
||||
STREAM_GETC(s, p.family);
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
STREAM_GET(&p.u.prefix, s, prefix_blen(&p));
|
||||
|
||||
if (p.family == AF_INET)
|
||||
SET_IPADDR_V4(&ip);
|
||||
else
|
||||
SET_IPADDR_V6(&ip);
|
||||
|
||||
memcpy(&ip.ip.addr, &p.u.prefix, prefix_blen(&p));
|
||||
|
||||
dplane_neigh_discover(ifp, &ip);
|
||||
|
||||
stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
|
||||
struct zmsghdr *bad_hdr)
|
||||
{
|
||||
@ -3065,8 +3100,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
||||
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
|
||||
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
|
||||
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
|
||||
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities
|
||||
};
|
||||
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
|
||||
[ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover};
|
||||
|
||||
#if defined(HANDLE_ZAPI_FUZZING)
|
||||
extern struct zebra_privs_t zserv_privs;
|
||||
|
||||
@ -185,7 +185,7 @@ struct dplane_mac_info {
|
||||
};
|
||||
|
||||
/*
|
||||
* EVPN neighbor info for the dataplane
|
||||
* Neighbor info for the dataplane
|
||||
*/
|
||||
struct dplane_neigh_info {
|
||||
struct ipaddr ip_addr;
|
||||
@ -607,6 +607,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_RULE_ADD:
|
||||
case DPLANE_OP_RULE_DELETE:
|
||||
case DPLANE_OP_RULE_UPDATE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
case DPLANE_OP_NONE:
|
||||
break;
|
||||
}
|
||||
@ -839,6 +840,10 @@ const char *dplane_op2str(enum dplane_op_e op)
|
||||
case DPLANE_OP_RULE_UPDATE:
|
||||
ret = "RULE_UPDATE";
|
||||
break;
|
||||
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
ret = "NEIGH_DISCOVER";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -3223,8 +3228,19 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
|
||||
return result;
|
||||
}
|
||||
|
||||
enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
|
||||
const struct ipaddr *ip)
|
||||
{
|
||||
enum zebra_dplane_result result;
|
||||
|
||||
result = neigh_update_internal(DPLANE_OP_NEIGH_DISCOVER, ifp, NULL, ip,
|
||||
DPLANE_NTF_USE, DPLANE_NUD_INCOMPLETE, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common helper api for evpn neighbor updates
|
||||
* Common helper api for neighbor updates
|
||||
*/
|
||||
static enum zebra_dplane_result
|
||||
neigh_update_internal(enum dplane_op_e op,
|
||||
@ -3243,9 +3259,8 @@ neigh_update_internal(enum dplane_op_e op,
|
||||
char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
|
||||
|
||||
zlog_debug("init neigh ctx %s: ifp %s, mac %s, ip %s",
|
||||
dplane_op2str(op),
|
||||
dplane_op2str(op), ifp->name,
|
||||
prefix_mac2str(mac, buf1, sizeof(buf1)),
|
||||
ifp->name,
|
||||
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||
}
|
||||
|
||||
@ -3446,7 +3461,9 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
|
||||
out_max = atomic_load_explicit(&prov->dp_out_max,
|
||||
memory_order_relaxed);
|
||||
|
||||
vty_out(vty, "%s (%u): in: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q_max: %"PRIu64"\n",
|
||||
vty_out(vty,
|
||||
"%s (%u): in: %" PRIu64 ", q_max: %" PRIu64
|
||||
", out: %" PRIu64 ", q_max: %" PRIu64 "\n",
|
||||
prov->dp_name, prov->dp_id, in, in_max, out, out_max);
|
||||
|
||||
DPLANE_LOCK();
|
||||
@ -3780,6 +3797,7 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_NEIGH_DELETE:
|
||||
case DPLANE_OP_VTEP_ADD:
|
||||
case DPLANE_OP_VTEP_DELETE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
ipaddr2str(dplane_ctx_neigh_get_ipaddr(ctx), buf,
|
||||
sizeof(buf));
|
||||
|
||||
@ -3886,6 +3904,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_NEIGH_DELETE:
|
||||
case DPLANE_OP_VTEP_ADD:
|
||||
case DPLANE_OP_VTEP_DELETE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||
atomic_fetch_add_explicit(&zdplane_info.dg_neigh_errors,
|
||||
1, memory_order_relaxed);
|
||||
|
||||
@ -149,6 +149,9 @@ enum dplane_op_e {
|
||||
DPLANE_OP_RULE_ADD,
|
||||
DPLANE_OP_RULE_DELETE,
|
||||
DPLANE_OP_RULE_UPDATE,
|
||||
|
||||
/* Link layer address discovery */
|
||||
DPLANE_OP_NEIGH_DISCOVER,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -160,12 +163,14 @@ enum dplane_op_e {
|
||||
/* Neighbor cache flags */
|
||||
#define DPLANE_NTF_EXT_LEARNED 0x01
|
||||
#define DPLANE_NTF_ROUTER 0x02
|
||||
#define DPLANE_NTF_USE 0x04
|
||||
|
||||
/* Neighbor cache states */
|
||||
#define DPLANE_NUD_REACHABLE 0x01
|
||||
#define DPLANE_NUD_STALE 0x02
|
||||
#define DPLANE_NUD_NOARP 0x04
|
||||
#define DPLANE_NUD_PROBE 0x08
|
||||
#define DPLANE_NUD_INCOMPLETE 0x10
|
||||
|
||||
/* MAC update flags - dplane_mac_info.update_flags */
|
||||
#define DPLANE_MAC_REMOTE (1 << 0)
|
||||
@ -572,6 +577,12 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
|
||||
const struct in_addr *ip,
|
||||
vni_t vni);
|
||||
|
||||
/*
|
||||
* Enqueue a neighbour discovery request for the dataplane.
|
||||
*/
|
||||
enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
|
||||
const struct ipaddr *ip);
|
||||
|
||||
/* Forward ref of zebra_pbr_rule */
|
||||
struct zebra_pbr_rule;
|
||||
|
||||
|
||||
@ -2663,6 +2663,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_RULE_ADD:
|
||||
case DPLANE_OP_RULE_DELETE:
|
||||
case DPLANE_OP_RULE_UPDATE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
case DPLANE_OP_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3764,6 +3764,7 @@ static int rib_process_dplane_results(struct thread *thread)
|
||||
case DPLANE_OP_NEIGH_DELETE:
|
||||
case DPLANE_OP_VTEP_ADD:
|
||||
case DPLANE_OP_VTEP_DELETE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
case DPLANE_OP_NONE:
|
||||
/* Don't expect this: just return the struct? */
|
||||
dplane_ctx_fini(&ctx);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user