summaryrefslogtreecommitdiff
path: root/zebra/zebra_dplane.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_dplane.c')
-rw-r--r--zebra/zebra_dplane.c287
1 files changed, 254 insertions, 33 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 76d7d00e4a..22cc234b2f 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -36,15 +36,22 @@
#include "zebra/rt.h"
#include "zebra/debug.h"
#include "zebra/zebra_pbr.h"
+#include "printfrr.h"
/* Memory type for context blocks */
DEFINE_MTYPE_STATIC(ZEBRA, DP_CTX, "Zebra DPlane Ctx")
+DEFINE_MTYPE_STATIC(ZEBRA, DP_INTF, "Zebra DPlane Intf")
DEFINE_MTYPE_STATIC(ZEBRA, DP_PROV, "Zebra DPlane Provider")
#ifndef AOK
# define AOK 0
#endif
+/* Control for collection of extra interface info with route updates; a plugin
+ * can enable the extra info via a dplane api.
+ */
+static bool dplane_collect_extra_intf_info;
+
/* Enable test dataplane provider */
/*#define DPLANE_TEST_PROVIDER 1 */
@@ -84,6 +91,18 @@ struct dplane_nexthop_info {
};
/*
+ * Optional extra info about interfaces used in route updates' nexthops.
+ */
+struct dplane_intf_extra {
+ vrf_id_t vrf_id;
+ uint32_t ifindex;
+ uint32_t flags;
+ uint32_t status;
+
+ TAILQ_ENTRY(dplane_intf_extra) link;
+};
+
+/*
* Route information captured for route updates.
*/
struct dplane_route_info {
@@ -126,8 +145,8 @@ struct dplane_route_info {
struct nexthop_group zd_old_ng;
struct nexthop_group old_backup_ng;
- /* TODO -- use fixed array of nexthops, to avoid mallocs? */
-
+ /* Optional list of extra interface info */
+ TAILQ_HEAD(dp_intf_extra_q, dplane_intf_extra) intf_extra_q;
};
/*
@@ -149,6 +168,17 @@ struct dplane_pw_info {
};
/*
+ * Bridge port info for the dataplane
+ */
+struct dplane_br_port_info {
+ uint32_t sph_filter_cnt;
+ struct in_addr sph_filters[ES_VTEP_MAX_CNT];
+ /* DPLANE_BR_PORT_XXX - see zebra_dplane.h*/
+ uint32_t flags;
+ uint32_t backup_nhg_id;
+};
+
+/*
* Interface/prefix info for the dataplane
*/
struct dplane_intf_info {
@@ -272,6 +302,7 @@ struct zebra_dplane_ctx {
struct dplane_route_info rinfo;
zebra_lsp_t lsp;
struct dplane_pw_info pw;
+ struct dplane_br_port_info br_port;
struct dplane_intf_info intf;
struct dplane_mac_info macinfo;
struct dplane_neigh_info neigh;
@@ -390,6 +421,9 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_pws_in;
_Atomic uint32_t dg_pw_errors;
+ _Atomic uint32_t dg_br_port_in;
+ _Atomic uint32_t dg_br_port_errors;
+
_Atomic uint32_t dg_intf_addrs_in;
_Atomic uint32_t dg_intf_addr_errors;
@@ -491,6 +525,8 @@ void dplane_enable_sys_route_notifs(void)
*/
static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
{
+ struct dplane_intf_extra *if_extra, *if_tmp;
+
/*
* Some internal allocations may need to be freed, depending on
* the type of info captured in the ctx.
@@ -533,6 +569,14 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
ctx->u.rinfo.old_backup_ng.nexthop = NULL;
}
+ /* Optional extra interface info */
+ TAILQ_FOREACH_SAFE(if_extra, &ctx->u.rinfo.intf_extra_q,
+ link, if_tmp) {
+ TAILQ_REMOVE(&ctx->u.rinfo.intf_extra_q, if_extra,
+ link);
+ XFREE(MTYPE_DP_INTF, if_extra);
+ }
+
break;
case DPLANE_OP_NH_INSTALL:
@@ -610,6 +654,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_RULE_DELETE:
case DPLANE_OP_RULE_UPDATE:
case DPLANE_OP_NEIGH_DISCOVER:
+ case DPLANE_OP_BR_PORT_UPDATE:
case DPLANE_OP_NONE:
break;
}
@@ -803,6 +848,10 @@ const char *dplane_op2str(enum dplane_op_e op)
ret = "SYS_ROUTE_DEL";
break;
+ case DPLANE_OP_BR_PORT_UPDATE:
+ ret = "BR_PORT_UPDATE";
+ break;
+
case DPLANE_OP_ADDR_INSTALL:
ret = "ADDR_INSTALL";
break;
@@ -1763,10 +1812,80 @@ dplane_ctx_rule_get_old_dst_ip(const struct zebra_dplane_ctx *ctx)
return &(ctx->u.rule.old.dst_ip);
}
+uint32_t dplane_ctx_get_br_port_flags(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.br_port.flags;
+}
+
+uint32_t
+dplane_ctx_get_br_port_sph_filter_cnt(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.br_port.sph_filter_cnt;
+}
+
+const struct in_addr *
+dplane_ctx_get_br_port_sph_filters(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.br_port.sph_filters;
+}
+
+uint32_t
+dplane_ctx_get_br_port_backup_nhg_id(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.br_port.backup_nhg_id;
+}
+
/*
* End of dplane context accessors
*/
+/* Optional extra info about interfaces in nexthops - a plugin must enable
+ * this extra info.
+ */
+const struct dplane_intf_extra *
+dplane_ctx_get_intf_extra(const struct zebra_dplane_ctx *ctx)
+{
+ return TAILQ_FIRST(&ctx->u.rinfo.intf_extra_q);
+}
+
+const struct dplane_intf_extra *
+dplane_ctx_intf_extra_next(const struct zebra_dplane_ctx *ctx,
+ const struct dplane_intf_extra *ptr)
+{
+ return TAILQ_NEXT(ptr, link);
+}
+
+vrf_id_t dplane_intf_extra_get_vrfid(const struct dplane_intf_extra *ptr)
+{
+ return ptr->vrf_id;
+}
+
+uint32_t dplane_intf_extra_get_ifindex(const struct dplane_intf_extra *ptr)
+{
+ return ptr->ifindex;
+}
+
+uint32_t dplane_intf_extra_get_flags(const struct dplane_intf_extra *ptr)
+{
+ return ptr->flags;
+}
+
+uint32_t dplane_intf_extra_get_status(const struct dplane_intf_extra *ptr)
+{
+ return ptr->status;
+}
+
+/*
+ * End of interface extra info accessors
+ */
/*
* Retrieve the limit on the number of pending, unprocessed updates.
@@ -1835,10 +1954,14 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
struct zebra_vrf *zvrf;
struct nexthop *nexthop;
zebra_l3vni_t *zl3vni;
+ const struct interface *ifp;
+ struct dplane_intf_extra *if_extra;
if (!ctx || !rn || !re)
goto done;
+ TAILQ_INIT(&ctx->u.rinfo.intf_extra_q);
+
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
@@ -1900,6 +2023,27 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
nexthop->nh_encap_type = NET_VXLAN;
nexthop->nh_encap.vni = zl3vni->vni;
}
+
+ /* Optionally capture extra interface info while we're in the
+ * main zebra pthread - a plugin has to ask for this info.
+ */
+ if (dplane_collect_extra_intf_info) {
+ ifp = if_lookup_by_index(nexthop->ifindex,
+ nexthop->vrf_id);
+
+ if (ifp) {
+ if_extra = XCALLOC(
+ MTYPE_DP_INTF,
+ sizeof(struct dplane_intf_extra));
+ if_extra->vrf_id = nexthop->vrf_id;
+ if_extra->ifindex = nexthop->ifindex;
+ if_extra->flags = ifp->flags;
+ if_extra->status = ifp->status;
+
+ TAILQ_INSERT_TAIL(&ctx->u.rinfo.intf_extra_q,
+ if_extra, link);
+ }
+ }
}
/* Don't need some info when capturing a system notification */
@@ -2224,20 +2368,14 @@ static int dplane_ctx_rule_init(struct zebra_dplane_ctx *ctx,
struct zebra_pbr_rule *new_rule,
struct zebra_pbr_rule *old_rule)
{
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- char buf1[PREFIX_STRLEN];
- char buf2[PREFIX_STRLEN];
-
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug(
- "init dplane ctx %s: IF %s Prio %u Fwmark %u Src %s Dst %s Table %u",
+ "init dplane ctx %s: IF %s Prio %u Fwmark %u Src %pFX Dst %pFX Table %u",
dplane_op2str(op), new_rule->ifname,
new_rule->rule.priority, new_rule->rule.filter.fwmark,
- prefix2str(&new_rule->rule.filter.src_ip, buf1,
- sizeof(buf1)),
- prefix2str(&new_rule->rule.filter.dst_ip, buf2,
- sizeof(buf2)),
+ &new_rule->rule.filter.src_ip,
+ &new_rule->rule.filter.dst_ip,
new_rule->rule.action.table);
- }
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
@@ -2845,6 +2983,80 @@ done:
}
/*
+ * Enqueue access br_port update.
+ */
+enum zebra_dplane_result
+dplane_br_port_update(const struct interface *ifp, bool non_df,
+ uint32_t sph_filter_cnt,
+ const struct in_addr *sph_filters, uint32_t backup_nhg_id)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ uint32_t flags = 0;
+ int ret;
+ struct zebra_dplane_ctx *ctx = NULL;
+ struct zebra_ns *zns;
+ enum dplane_op_e op = DPLANE_OP_BR_PORT_UPDATE;
+
+ if (non_df)
+ flags |= DPLANE_BR_PORT_NON_DF;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL || IS_ZEBRA_DEBUG_EVPN_MH_ES) {
+ uint32_t i;
+ char vtep_str[ES_VTEP_LIST_STR_SZ];
+
+ vtep_str[0] = '\0';
+ for (i = 0; i < sph_filter_cnt; ++i) {
+ snprintfrr(vtep_str + strlen(vtep_str),
+ sizeof(vtep_str) - strlen(vtep_str), "%pI4 ",
+ &sph_filters[i]);
+ }
+ zlog_debug(
+ "init br_port ctx %s: ifp %s, flags 0x%x backup_nhg 0x%x sph %s",
+ dplane_op2str(op), ifp->name, flags, backup_nhg_id,
+ vtep_str);
+ }
+
+ 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);
+
+ ctx->zd_ifindex = ifp->ifindex;
+ strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+
+ /* Init the br-port-specific data area */
+ memset(&ctx->u.br_port, 0, sizeof(ctx->u.br_port));
+
+ ctx->u.br_port.flags = flags;
+ ctx->u.br_port.backup_nhg_id = backup_nhg_id;
+ ctx->u.br_port.sph_filter_cnt = sph_filter_cnt;
+ memcpy(ctx->u.br_port.sph_filters, sph_filters,
+ sizeof(ctx->u.br_port.sph_filters[0]) * sph_filter_cnt);
+
+ /* Enqueue for processing on the dplane pthread */
+ ret = dplane_update_enqueue(ctx);
+
+ /* Increment counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_br_port_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK) {
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ } else {
+ /* Error counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_br_port_errors, 1,
+ memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
+/*
* Enqueue interface address add for the dataplane.
*/
enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp,
@@ -2895,15 +3107,10 @@ static enum zebra_dplane_result intf_addr_update_internal(
struct zebra_dplane_ctx *ctx = NULL;
struct zebra_ns *zns;
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- char addr_str[PREFIX_STRLEN];
-
- prefix2str(ifc->address, addr_str, sizeof(addr_str));
-
- zlog_debug("init intf ctx %s: idx %d, addr %u:%s",
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("init intf ctx %s: idx %d, addr %u:%pFX",
dplane_op2str(op), ifp->ifindex, ifp->vrf_id,
- addr_str);
- }
+ ifc->address);
ctx = dplane_ctx_alloc();
@@ -3220,8 +3427,8 @@ enum zebra_dplane_result dplane_vtep_add(const struct interface *ifp,
struct ipaddr addr;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
- inet_ntoa(*ip), vni, ifp->name, ifp->ifindex);
+ zlog_debug("Install %pI4 into flood list for VNI %u intf %s(%u)",
+ ip, vni, ifp->name, ifp->ifindex);
SET_IPADDR_V4(&addr);
addr.ipaddr_v4 = *ip;
@@ -3245,8 +3452,8 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Uninstall %s from flood list for VNI %u intf %s(%u)",
- inet_ntoa(*ip), vni, ifp->name, ifp->ifindex);
+ "Uninstall %pI4 from flood list for VNI %u intf %s(%u)",
+ ip, vni, ifp->name, ifp->ifindex);
SET_IPADDR_V4(&addr);
addr.ipaddr_v4 = *ip;
@@ -3461,6 +3668,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)
vty_out(vty, "Rule updates: %" PRIu64 "\n", incoming);
vty_out(vty, "Rule errors: %" PRIu64 "\n", errs);
+ incoming = atomic_load_explicit(&zdplane_info.dg_br_port_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_br_port_errors,
+ memory_order_relaxed);
+ vty_out(vty, "Bridge port updates: %" PRIu64 "\n", incoming);
+ vty_out(vty, "Bridge port errors: %" PRIu64 "\n", errs);
+
return CMD_SUCCESS;
}
@@ -3773,11 +3987,9 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_ROUTE_INSTALL:
case DPLANE_OP_ROUTE_UPDATE:
case DPLANE_OP_ROUTE_DELETE:
- prefix2str(dplane_ctx_get_dest(ctx), buf, sizeof(buf));
-
- zlog_debug("%u:%s Dplane route update ctx %p op %s",
- dplane_ctx_get_vrf(ctx), buf, ctx,
- dplane_op2str(dplane_ctx_get_op(ctx)));
+ zlog_debug("%u:%pFX Dplane route update ctx %p op %s",
+ dplane_ctx_get_vrf(ctx), dplane_ctx_get_dest(ctx),
+ ctx, dplane_op2str(dplane_ctx_get_op(ctx)));
break;
case DPLANE_OP_NH_INSTALL:
@@ -3804,11 +4016,10 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_ADDR_INSTALL:
case DPLANE_OP_ADDR_UNINSTALL:
- prefix2str(dplane_ctx_get_intf_addr(ctx), buf, sizeof(buf));
-
- zlog_debug("Dplane intf %s, idx %u, addr %s",
+ zlog_debug("Dplane intf %s, idx %u, addr %pFX",
dplane_op2str(dplane_ctx_get_op(ctx)),
- dplane_ctx_get_ifindex(ctx), buf);
+ dplane_ctx_get_ifindex(ctx),
+ dplane_ctx_get_intf_addr(ctx));
break;
case DPLANE_OP_MAC_INSTALL:
@@ -3848,6 +4059,7 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_SYS_ROUTE_DELETE:
case DPLANE_OP_ROUTE_NOTIFY:
case DPLANE_OP_LSP_NOTIFY:
+ case DPLANE_OP_BR_PORT_UPDATE:
case DPLANE_OP_NONE:
break;
@@ -3952,6 +4164,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_SYS_ROUTE_DELETE:
case DPLANE_OP_ROUTE_NOTIFY:
case DPLANE_OP_LSP_NOTIFY:
+ case DPLANE_OP_BR_PORT_UPDATE:
break;
case DPLANE_OP_NONE:
@@ -4123,6 +4336,14 @@ bool dplane_is_in_shutdown(void)
}
/*
+ * Enable collection of extra info about interfaces in route updates.
+ */
+void dplane_enable_intf_extra_info(void)
+{
+ dplane_collect_extra_intf_info = true;
+}
+
+/*
* Early or pre-shutdown, de-init notification api. This runs pretty
* early during zebra shutdown, as a signal to stop new work and prepare
* for updates generated by shutdown/cleanup activity, as zebra tries to