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:
Philippe Guibert 2021-02-26 10:04:25 +01:00
parent 0a27a2fef5
commit e18747a967
9 changed files with 207 additions and 58 deletions

View File

@ -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:

View File

@ -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.

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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:

View File

@ -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;

View File

@ -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;
}

View File

@ -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);