mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-08-02 08:33:36 +00:00
zebra: move neighbor table configuration to dplane contexts
Instead of directly configuring the neighbor table after read from zapi interface, a zebra dplane context is prepared to host the interface and the family where the neighbor table is updated. Also, some other fields are hosted: app_probes, ucast_probes, and mcast_probes. More information on those fields can be found on ip-ntable configuration. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
0a27a2fef5
commit
e18747a967
@ -1337,6 +1337,7 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
case DPLANE_OP_NEIGH_IP_INSTALL:
|
||||
case DPLANE_OP_NEIGH_IP_DELETE:
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
return netlink_put_neigh_update_msg(bth, ctx);
|
||||
|
||||
case DPLANE_OP_RULE_ADD:
|
||||
|
||||
@ -81,7 +81,9 @@ extern int mpls_kernel_init(void);
|
||||
extern uint32_t kernel_get_speed(struct interface *ifp, int *error);
|
||||
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
|
||||
|
||||
extern int kernel_configure_arp(struct interface *ifp, int family, ns_id_t ns_id);
|
||||
extern int kernel_configure_if_link(struct interface *ifp,
|
||||
struct interface *link_ifp, ns_id_t ns_id);
|
||||
|
||||
/*
|
||||
* Southbound Initialization routines to get initial starting
|
||||
* state.
|
||||
|
||||
@ -1542,52 +1542,6 @@ static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
|
||||
routedesc, nl_msg_type_to_str(cmd), label);
|
||||
}
|
||||
|
||||
static int netlink_configure_arp(struct interface *ifp, int family, ns_id_t ns_id)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ndtmsg ndtm;
|
||||
char buf[256];
|
||||
} req;
|
||||
struct zebra_ns *zns = zebra_ns_lookup(ns_id);
|
||||
struct rtattr *nest;
|
||||
uint32_t val;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndtmsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE;
|
||||
req.n.nlmsg_type = RTM_SETNEIGHTBL;
|
||||
req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
|
||||
|
||||
req.ndtm.ndtm_family = family;
|
||||
|
||||
nl_attr_put(&req.n, sizeof(req), NDTA_NAME, family == AF_INET ? "arp_cache" :
|
||||
"ndisc_cache", 10);
|
||||
|
||||
nest = nl_attr_nest(&req.n, sizeof(req), NDTA_PARMS);
|
||||
if (nest == NULL)
|
||||
return;
|
||||
if (!nl_attr_put(&req.n, sizeof(req), NDTPA_IFINDEX, &ifp->ifindex,
|
||||
sizeof(ifp->ifindex)))
|
||||
return 0;
|
||||
val = 1;
|
||||
if (!nl_attr_put(&req.n, sizeof(req), NDTPA_APP_PROBES, &val,
|
||||
sizeof(val)))
|
||||
return 0;
|
||||
val = 0;
|
||||
if (!nl_attr_put(&req.n, sizeof(req), NDTPA_MCAST_PROBES, &val,
|
||||
sizeof(val)))
|
||||
return 0;
|
||||
if (!nl_attr_put(&req.n, sizeof(req), NDTPA_UCAST_PROBES, &val,
|
||||
sizeof(val)))
|
||||
return 0;
|
||||
nl_attr_nest_end(&req.n, nest);
|
||||
|
||||
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
|
||||
0);
|
||||
}
|
||||
|
||||
static int netlink_neigh_update(int cmd, int ifindex, void *addr, char *lla,
|
||||
int llalen, ns_id_t ns_id, uint8_t family,
|
||||
bool permanent, uint8_t protocol)
|
||||
@ -3817,6 +3771,53 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
|
||||
ext_flags, buf, buflen, zebra2proto(dplane_ctx_get_type(ctx)));
|
||||
}
|
||||
|
||||
static int netlink_neigh_table_update_ctx(const struct zebra_dplane_ctx *ctx,
|
||||
void *data, size_t datalen)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ndtmsg ndtm;
|
||||
char buf[];
|
||||
} *req = data;
|
||||
struct rtattr *nest;
|
||||
uint8_t family;
|
||||
ifindex_t idx;
|
||||
uint32_t val;
|
||||
|
||||
if (datalen < sizeof(*req))
|
||||
return 0;
|
||||
memset(req, 0, sizeof(*req));
|
||||
family = dplane_ctx_neightable_get_family(ctx);
|
||||
idx = dplane_ctx_get_ifindex(ctx);
|
||||
|
||||
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndtmsg));
|
||||
req->n.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE;
|
||||
req->n.nlmsg_type = RTM_SETNEIGHTBL;
|
||||
req->ndtm.ndtm_family = family;
|
||||
|
||||
nl_attr_put(&req->n, datalen, NDTA_NAME,
|
||||
family == AF_INET ? "arp_cache" : "ndisc_cache", 10);
|
||||
nest = nl_attr_nest(&req->n, datalen, NDTA_PARMS);
|
||||
if (nest == NULL)
|
||||
return 0;
|
||||
if (!nl_attr_put(&req->n, datalen, NDTPA_IFINDEX, &idx, sizeof(idx)))
|
||||
return 0;
|
||||
val = dplane_ctx_neightable_get_app_probes(ctx);
|
||||
if (!nl_attr_put(&req->n, datalen, NDTPA_APP_PROBES, &val, sizeof(val)))
|
||||
return 0;
|
||||
val = dplane_ctx_neightable_get_mcast_probes(ctx);
|
||||
if (!nl_attr_put(&req->n, datalen, NDTPA_MCAST_PROBES, &val,
|
||||
sizeof(val)))
|
||||
return 0;
|
||||
val = dplane_ctx_neightable_get_ucast_probes(ctx);
|
||||
if (!nl_attr_put(&req->n, datalen, NDTPA_UCAST_PROBES, &val,
|
||||
sizeof(val)))
|
||||
return 0;
|
||||
nl_attr_nest_end(&req->n, nest);
|
||||
|
||||
return NLMSG_ALIGN(req->n.nlmsg_len);
|
||||
}
|
||||
|
||||
static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
|
||||
void *buf, size_t buflen)
|
||||
{
|
||||
@ -3841,6 +3842,9 @@ static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
|
||||
ret = netlink_vxlan_flood_update_ctx(ctx, RTM_DELNEIGH, buf,
|
||||
buflen);
|
||||
break;
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
ret = netlink_neigh_table_update_ctx(ctx, buf, buflen);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
@ -3866,12 +3870,6 @@ netlink_put_neigh_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
|
||||
false);
|
||||
}
|
||||
|
||||
int kernel_configure_arp(struct interface *ifp, int family,
|
||||
ns_id_t ns_id)
|
||||
{
|
||||
return netlink_configure_arp(ifp, family, ns_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPLS label forwarding table change via netlink interface, using dataplane
|
||||
* context information.
|
||||
|
||||
@ -394,7 +394,8 @@ enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
|
||||
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||
}
|
||||
|
||||
int kernel_configure_arp(struct interface *ifp, int family, ns_id_t ns_id)
|
||||
int kernel_configure_if_link(struct interface *ifp, struct interface *link_ifp,
|
||||
ns_id_t ns_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3282,10 +3282,9 @@ stream_failure:
|
||||
static inline void zebra_configure_arp(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
int fam;
|
||||
uint8_t fam;
|
||||
ifindex_t idx;
|
||||
struct interface *ifp;
|
||||
ns_id_t ns_id;
|
||||
|
||||
s = msg;
|
||||
STREAM_GETC(s, fam);
|
||||
@ -3295,8 +3294,7 @@ static inline void zebra_configure_arp(ZAPI_HANDLER_ARGS)
|
||||
ifp = if_lookup_by_index_per_ns(zvrf->zns, idx);
|
||||
if (!ifp)
|
||||
return;
|
||||
ns_id = zvrf->zns->ns_id;
|
||||
kernel_configure_arp(ifp, fam, ns_id);
|
||||
dplane_neigh_table_update(ifp, fam, 1, 0, 0);
|
||||
stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
@ -229,6 +229,16 @@ struct dplane_neigh_info {
|
||||
uint32_t update_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Neighbor Table
|
||||
*/
|
||||
struct dplane_neigh_table {
|
||||
uint8_t family;
|
||||
uint32_t app_probes;
|
||||
uint32_t ucast_probes;
|
||||
uint32_t mcast_probes;
|
||||
};
|
||||
|
||||
/*
|
||||
* Policy based routing rule info for the dataplane
|
||||
*/
|
||||
@ -316,6 +326,7 @@ struct zebra_dplane_ctx {
|
||||
struct zebra_pbr_ipset_entry entry;
|
||||
struct zebra_pbr_ipset_info info;
|
||||
} ipset_entry;
|
||||
struct dplane_neigh_table neightable;
|
||||
} u;
|
||||
|
||||
/* Namespace info, used especially for netlink kernel communication */
|
||||
@ -455,6 +466,9 @@ static struct zebra_dplane_globals {
|
||||
_Atomic uint32_t dg_ipset_entry_in;
|
||||
_Atomic uint32_t dg_ipset_entry_errors;
|
||||
|
||||
_Atomic uint32_t dg_neightable_in;
|
||||
_Atomic uint32_t dg_neightable_errors;
|
||||
|
||||
/* Dataplane pthread */
|
||||
struct frr_pthread *dg_pthread;
|
||||
|
||||
@ -681,6 +695,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_IPSET_ENTRY_ADD:
|
||||
case DPLANE_OP_IPSET_ENTRY_DELETE:
|
||||
break;
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
break;
|
||||
case DPLANE_OP_IPTABLE_ADD:
|
||||
case DPLANE_OP_IPTABLE_DELETE:
|
||||
if (ctx->u.iptable.interface_name_list) {
|
||||
@ -960,6 +976,9 @@ const char *dplane_op2str(enum dplane_op_e op)
|
||||
case DPLANE_OP_NEIGH_IP_DELETE:
|
||||
ret = "NEIGH_IP_DELETE";
|
||||
break;
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
ret = "NEIGH_TABLE_UPDATE";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1995,6 +2014,37 @@ uint32_t dplane_intf_extra_get_status(const struct dplane_intf_extra *ptr)
|
||||
return ptr->status;
|
||||
}
|
||||
|
||||
uint8_t dplane_ctx_neightable_get_family(const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
DPLANE_CTX_VALID(ctx);
|
||||
|
||||
return ctx->u.neightable.family;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
dplane_ctx_neightable_get_app_probes(const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
DPLANE_CTX_VALID(ctx);
|
||||
|
||||
return ctx->u.neightable.app_probes;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
DPLANE_CTX_VALID(ctx);
|
||||
|
||||
return ctx->u.neightable.ucast_probes;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
DPLANE_CTX_VALID(ctx);
|
||||
|
||||
return ctx->u.neightable.mcast_probes;
|
||||
}
|
||||
|
||||
/*
|
||||
* End of interface extra info accessors
|
||||
*/
|
||||
@ -3759,6 +3809,62 @@ enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
|
||||
return result;
|
||||
}
|
||||
|
||||
enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
|
||||
const uint8_t family,
|
||||
const uint32_t app_probes,
|
||||
const uint32_t ucast_probes,
|
||||
const uint32_t mcast_probes)
|
||||
{
|
||||
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||
int ret;
|
||||
struct zebra_dplane_ctx *ctx = NULL;
|
||||
struct zebra_ns *zns;
|
||||
enum dplane_op_e op = DPLANE_OP_NEIGH_TABLE_UPDATE;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
|
||||
zlog_debug("set neigh ctx %s: ifp %s, family %s",
|
||||
dplane_op2str(op), ifp->name, family2str(family));
|
||||
}
|
||||
|
||||
ctx = dplane_ctx_alloc();
|
||||
|
||||
ctx->zd_op = op;
|
||||
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||
ctx->zd_vrf_id = ifp->vrf_id;
|
||||
|
||||
zns = zebra_ns_lookup(ifp->vrf_id);
|
||||
dplane_ctx_ns_init(ctx, zns, false);
|
||||
|
||||
strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
|
||||
ctx->zd_ifindex = ifp->ifindex;
|
||||
|
||||
/* Init the neighbor-specific data area */
|
||||
memset(&ctx->u.neightable, 0, sizeof(ctx->u.neightable));
|
||||
|
||||
ctx->u.neightable.family = family;
|
||||
ctx->u.neightable.app_probes = app_probes;
|
||||
ctx->u.neightable.ucast_probes = ucast_probes;
|
||||
ctx->u.neightable.mcast_probes = mcast_probes;
|
||||
|
||||
/* Enqueue for processing on the dplane pthread */
|
||||
ret = dplane_update_enqueue(ctx);
|
||||
|
||||
/* Increment counter */
|
||||
atomic_fetch_add_explicit(&zdplane_info.dg_neightable_in, 1,
|
||||
memory_order_relaxed);
|
||||
|
||||
if (ret == AOK)
|
||||
result = ZEBRA_DPLANE_REQUEST_QUEUED;
|
||||
else {
|
||||
/* Error counter */
|
||||
atomic_fetch_add_explicit(&zdplane_info.dg_neightable_errors, 1,
|
||||
memory_order_relaxed);
|
||||
dplane_ctx_free(&ctx);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common helper api for neighbor updates
|
||||
*/
|
||||
@ -4124,6 +4230,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)
|
||||
memory_order_relaxed);
|
||||
vty_out(vty, "IPset entry updates: %" PRIu64 "\n", incoming);
|
||||
vty_out(vty, "IPset entry errors: %" PRIu64 "\n", errs);
|
||||
|
||||
incoming = atomic_load_explicit(&zdplane_info.dg_neightable_in,
|
||||
memory_order_relaxed);
|
||||
errs = atomic_load_explicit(&zdplane_info.dg_neightable_errors,
|
||||
memory_order_relaxed);
|
||||
vty_out(vty, "Neighbor Table updates: %"PRIu64"\n", incoming);
|
||||
vty_out(vty, "Neighbor Table errors: %"PRIu64"\n", errs);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -4563,6 +4676,13 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
|
||||
dplane_op2str(dplane_ctx_get_op(ctx)),
|
||||
ipent.unique, ctx);
|
||||
} break;
|
||||
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
zlog_debug("Dplane neigh table op %s, ifp %s, family %s",
|
||||
dplane_op2str(dplane_ctx_get_op(ctx)),
|
||||
dplane_ctx_get_ifname(ctx),
|
||||
family2str(dplane_ctx_neightable_get_family(ctx)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4684,6 +4804,13 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
|
||||
memory_order_relaxed);
|
||||
break;
|
||||
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||
atomic_fetch_add_explicit(
|
||||
&zdplane_info.dg_neightable_errors, 1,
|
||||
memory_order_relaxed);
|
||||
break;
|
||||
|
||||
/* Ignore 'notifications' - no-op */
|
||||
case DPLANE_OP_SYS_ROUTE_ADD:
|
||||
case DPLANE_OP_SYS_ROUTE_DELETE:
|
||||
|
||||
@ -169,6 +169,8 @@ enum dplane_op_e {
|
||||
/* LINK LAYER IP address update */
|
||||
DPLANE_OP_NEIGH_IP_INSTALL,
|
||||
DPLANE_OP_NEIGH_IP_DELETE,
|
||||
|
||||
DPLANE_OP_NEIGH_TABLE_UPDATE,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -516,6 +518,15 @@ dplane_ctx_get_br_port_sph_filters(const struct zebra_dplane_ctx *ctx);
|
||||
uint32_t
|
||||
dplane_ctx_get_br_port_backup_nhg_id(const struct zebra_dplane_ctx *ctx);
|
||||
|
||||
/* Accessors for neighbor table information */
|
||||
uint8_t dplane_ctx_neightable_get_family(const struct zebra_dplane_ctx *ctx);
|
||||
uint32_t
|
||||
dplane_ctx_neightable_get_app_probes(const struct zebra_dplane_ctx *ctx);
|
||||
uint32_t
|
||||
dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx);
|
||||
uint32_t
|
||||
dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx);
|
||||
|
||||
/* Namespace info - esp. for netlink communication */
|
||||
const struct zebra_dplane_info *dplane_ctx_get_ns(
|
||||
const struct zebra_dplane_ctx *ctx);
|
||||
@ -674,6 +685,15 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
|
||||
enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
|
||||
const struct ipaddr *ip);
|
||||
|
||||
/*
|
||||
* Enqueue a neighbor table parameter set
|
||||
*/
|
||||
enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
|
||||
const uint8_t family,
|
||||
const uint32_t app_probes,
|
||||
const uint32_t ucast_probes,
|
||||
const uint32_t mcast_probes);
|
||||
|
||||
/* Forward ref of zebra_pbr_rule */
|
||||
struct zebra_pbr_rule;
|
||||
|
||||
|
||||
@ -2914,6 +2914,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_IPSET_DELETE:
|
||||
case DPLANE_OP_IPSET_ENTRY_ADD:
|
||||
case DPLANE_OP_IPSET_ENTRY_DELETE:
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -3931,6 +3931,7 @@ static int rib_process_dplane_results(struct thread *thread)
|
||||
case DPLANE_OP_VTEP_DELETE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
case DPLANE_OP_BR_PORT_UPDATE:
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
case DPLANE_OP_NONE:
|
||||
/* Don't expect this: just return the struct? */
|
||||
dplane_ctx_fini(&ctx);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user