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.c365
1 files changed, 305 insertions, 60 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 04411fa0d2..9e9844390d 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -37,11 +37,12 @@
#include "zebra/zebra_pbr.h"
#include "printfrr.h"
-/* Memory type for context blocks */
+/* Memory types */
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");
DEFINE_MTYPE_STATIC(ZEBRA, DP_NETFILTER, "Zebra Netfilter Internal Object");
+DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes");
#ifndef AOK
# define AOK 0
@@ -259,6 +260,14 @@ struct dplane_ctx_rule {
uint8_t dsfield;
struct prefix src_ip;
struct prefix dst_ip;
+ uint8_t ip_proto;
+
+ uint8_t action_pcp;
+ uint16_t action_vlan_id;
+ uint16_t action_vlan_flags;
+
+ uint32_t action_queue_id;
+
char ifname[INTERFACE_NAMSIZ + 1];
};
@@ -323,7 +332,7 @@ struct zebra_dplane_ctx {
/* Support info for different kinds of updates */
union {
struct dplane_route_info rinfo;
- zebra_lsp_t lsp;
+ struct zebra_lsp lsp;
struct dplane_pw_info pw;
struct dplane_br_port_info br_port;
struct dplane_intf_info intf;
@@ -401,6 +410,19 @@ struct zebra_dplane_provider {
TAILQ_ENTRY(zebra_dplane_provider) dp_prov_link;
};
+/* Declare types for list of zns info objects */
+PREDECL_DLIST(zns_info_list);
+
+struct dplane_zns_info {
+ struct zebra_dplane_info info;
+
+ /* Read event */
+ struct thread *t_read;
+
+ /* List linkage */
+ struct zns_info_list_item link;
+};
+
/*
* Globals
*/
@@ -423,6 +445,9 @@ static struct zebra_dplane_globals {
/* Ordered list of providers */
TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
+ /* List of info about each zns */
+ struct zns_info_list_head dg_zns_list;
+
/* Counter used to assign internal ids to providers */
uint32_t dg_provider_id;
@@ -497,6 +522,9 @@ static struct zebra_dplane_globals {
} zdplane_info;
+/* Instantiate zns list type */
+DECLARE_DLIST(zns_info_list, struct dplane_zns_info, link);
+
/*
* Lock and unlock for interactions with the zebra 'core' pthread
*/
@@ -514,7 +542,7 @@ static struct zebra_dplane_globals {
static int dplane_thread_loop(struct thread *event);
static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
struct zebra_ns *zns);
-static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
+static enum zebra_dplane_result lsp_update_internal(struct zebra_lsp *lsp,
enum dplane_op_e op);
static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
enum dplane_op_e op);
@@ -640,7 +668,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_LSP_DELETE:
case DPLANE_OP_LSP_NOTIFY:
{
- zebra_nhlfe_t *nhlfe;
+ struct zebra_nhlfe *nhlfe;
/* Unlink and free allocated NHLFEs */
frr_each_safe(nhlfe_list, &ctx->u.lsp.nhlfe_list, nhlfe) {
@@ -689,6 +717,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_ADDR_INSTALL:
case DPLANE_OP_ADDR_UNINSTALL:
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
/* Maybe free label string, if allocated */
if (ctx->u.intf.label != NULL &&
ctx->u.intf.label != ctx->u.intf.label_buf) {
@@ -1010,6 +1040,12 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_GRE_SET:
ret = "GRE_SET";
break;
+
+ case DPLANE_OP_INTF_ADDR_ADD:
+ return "INTF_ADDR_ADD";
+
+ case DPLANE_OP_INTF_ADDR_DEL:
+ return "INTF_ADDR_DEL";
}
return ret;
@@ -1107,6 +1143,21 @@ vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx)
return ctx->zd_vrf_id;
}
+/* In some paths we have only a namespace id */
+void dplane_ctx_set_ns_id(struct zebra_dplane_ctx *ctx, ns_id_t nsid)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->zd_ns_info.ns_id = nsid;
+}
+
+ns_id_t dplane_ctx_get_ns_id(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->zd_ns_info.ns_id;
+}
+
bool dplane_ctx_is_from_notif(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1153,6 +1204,13 @@ ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
return ctx->zd_ifindex;
}
+void dplane_ctx_set_ifindex(struct zebra_dplane_ctx *ctx, ifindex_t ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->zd_ifindex = ifindex;
+}
+
void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type)
{
DPLANE_CTX_VALID(ctx);
@@ -1511,15 +1569,14 @@ const struct nhlfe_list_head *dplane_ctx_get_backup_nhlfe_list(
return &(ctx->u.lsp.backup_nhlfe_list);
}
-zebra_nhlfe_t *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx,
- enum lsp_types_t lsp_type,
- enum nexthop_types_t nh_type,
- const union g_addr *gate,
- ifindex_t ifindex,
- uint8_t num_labels,
- mpls_label_t *out_labels)
+struct zebra_nhlfe *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx,
+ enum lsp_types_t lsp_type,
+ enum nexthop_types_t nh_type,
+ const union g_addr *gate,
+ ifindex_t ifindex, uint8_t num_labels,
+ mpls_label_t *out_labels)
{
- zebra_nhlfe_t *nhlfe;
+ struct zebra_nhlfe *nhlfe;
DPLANE_CTX_VALID(ctx);
@@ -1530,15 +1587,12 @@ zebra_nhlfe_t *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx,
return nhlfe;
}
-zebra_nhlfe_t *dplane_ctx_add_backup_nhlfe(struct zebra_dplane_ctx *ctx,
- enum lsp_types_t lsp_type,
- enum nexthop_types_t nh_type,
- const union g_addr *gate,
- ifindex_t ifindex,
- uint8_t num_labels,
- mpls_label_t *out_labels)
+struct zebra_nhlfe *dplane_ctx_add_backup_nhlfe(
+ struct zebra_dplane_ctx *ctx, enum lsp_types_t lsp_type,
+ enum nexthop_types_t nh_type, const union g_addr *gate,
+ ifindex_t ifindex, uint8_t num_labels, mpls_label_t *out_labels)
{
- zebra_nhlfe_t *nhlfe;
+ struct zebra_nhlfe *nhlfe;
DPLANE_CTX_VALID(ctx);
@@ -1550,7 +1604,7 @@ zebra_nhlfe_t *dplane_ctx_add_backup_nhlfe(struct zebra_dplane_ctx *ctx,
return nhlfe;
}
-const zebra_nhlfe_t *
+const struct zebra_nhlfe *
dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1558,9 +1612,9 @@ dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.best_nhlfe;
}
-const zebra_nhlfe_t *
+const struct zebra_nhlfe *
dplane_ctx_set_best_nhlfe(struct zebra_dplane_ctx *ctx,
- zebra_nhlfe_t *nhlfe)
+ struct zebra_nhlfe *nhlfe)
{
DPLANE_CTX_VALID(ctx);
@@ -1672,6 +1726,13 @@ uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx)
return ctx->u.intf.metric;
}
+void dplane_ctx_set_intf_metric(struct zebra_dplane_ctx *ctx, uint32_t metric)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.metric = metric;
+}
+
/* Is interface addr p2p? */
bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx)
{
@@ -1694,6 +1755,27 @@ bool dplane_ctx_intf_is_broadcast(const struct zebra_dplane_ctx *ctx)
return (ctx->u.intf.flags & DPLANE_INTF_BROADCAST);
}
+void dplane_ctx_intf_set_connected(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.flags |= DPLANE_INTF_CONNECTED;
+}
+
+void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.flags |= DPLANE_INTF_SECONDARY;
+}
+
+void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.flags |= DPLANE_INTF_BROADCAST;
+}
+
const struct prefix *dplane_ctx_get_intf_addr(
const struct zebra_dplane_ctx *ctx)
{
@@ -1702,6 +1784,14 @@ const struct prefix *dplane_ctx_get_intf_addr(
return &(ctx->u.intf.prefix);
}
+void dplane_ctx_set_intf_addr(struct zebra_dplane_ctx *ctx,
+ const struct prefix *p)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ prefix_copy(&(ctx->u.intf.prefix), p);
+}
+
bool dplane_ctx_intf_has_dest(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1714,10 +1804,15 @@ const struct prefix *dplane_ctx_get_intf_dest(
{
DPLANE_CTX_VALID(ctx);
- if (ctx->u.intf.flags & DPLANE_INTF_HAS_DEST)
- return &(ctx->u.intf.dest_prefix);
- else
- return NULL;
+ return &(ctx->u.intf.dest_prefix);
+}
+
+void dplane_ctx_set_intf_dest(struct zebra_dplane_ctx *ctx,
+ const struct prefix *p)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ prefix_copy(&(ctx->u.intf.dest_prefix), p);
}
bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx)
@@ -1734,6 +1829,35 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx)
return ctx->u.intf.label;
}
+void dplane_ctx_set_intf_label(struct zebra_dplane_ctx *ctx, const char *label)
+{
+ size_t len;
+
+ DPLANE_CTX_VALID(ctx);
+
+ if (ctx->u.intf.label && ctx->u.intf.label != ctx->u.intf.label_buf)
+ free(ctx->u.intf.label);
+
+ ctx->u.intf.label = NULL;
+
+ if (label) {
+ ctx->u.intf.flags |= DPLANE_INTF_HAS_LABEL;
+
+ /* Use embedded buffer if it's adequate; else allocate. */
+ len = strlen(label);
+
+ if (len < sizeof(ctx->u.intf.label_buf)) {
+ strlcpy(ctx->u.intf.label_buf, label,
+ sizeof(ctx->u.intf.label_buf));
+ ctx->u.intf.label = ctx->u.intf.label_buf;
+ } else {
+ ctx->u.intf.label = strdup(label);
+ }
+ } else {
+ ctx->u.intf.flags &= ~DPLANE_INTF_HAS_LABEL;
+ }
+}
+
/* Accessors for MAC information */
vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx)
{
@@ -1929,6 +2053,20 @@ uint32_t dplane_ctx_rule_get_old_fwmark(const struct zebra_dplane_ctx *ctx)
return ctx->u.rule.old.fwmark;
}
+uint8_t dplane_ctx_rule_get_ipproto(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.new.ip_proto;
+}
+
+uint8_t dplane_ctx_rule_get_old_ipproto(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.old.ip_proto;
+}
+
uint8_t dplane_ctx_rule_get_dsfield(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -2166,9 +2304,9 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx,
* two messages in some 'update' cases.
*/
if (is_update)
- zns->netlink_dplane.seq += 2;
+ zns->netlink_dplane_out.seq += 2;
else
- zns->netlink_dplane.seq++;
+ zns->netlink_dplane_out.seq++;
#endif /* HAVE_NETLINK */
return AOK;
@@ -2187,7 +2325,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
struct zebra_ns *zns;
struct zebra_vrf *zvrf;
struct nexthop *nexthop;
- zebra_l3vni_t *zl3vni;
+ struct zebra_l3vni *zl3vni;
const struct interface *ifp;
struct dplane_intf_extra *if_extra;
@@ -2389,10 +2527,10 @@ done:
* Capture information for an LSP update in a dplane context.
*/
int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
- zebra_lsp_t *lsp)
+ struct zebra_lsp *lsp)
{
int ret = AOK;
- zebra_nhlfe_t *nhlfe, *new_nhlfe;
+ struct zebra_nhlfe *nhlfe, *new_nhlfe;
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
@@ -2636,8 +2774,15 @@ static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule,
dplane_rule->filter_bm = rule->rule.filter.filter_bm;
dplane_rule->fwmark = rule->rule.filter.fwmark;
dplane_rule->dsfield = rule->rule.filter.dsfield;
+ dplane_rule->ip_proto = rule->rule.filter.ip_proto;
prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip);
prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip);
+
+ dplane_rule->action_pcp = rule->rule.action.pcp;
+ dplane_rule->action_vlan_flags = rule->rule.action.vlan_flags;
+ dplane_rule->action_vlan_id = rule->rule.action.vlan_id;
+ dplane_rule->action_queue_id = rule->rule.action.queue_id;
+
strlcpy(dplane_rule->ifname, rule->ifname, INTERFACE_NAMSIZ);
}
@@ -2672,7 +2817,7 @@ static int dplane_ctx_rule_init(struct zebra_dplane_ctx *ctx,
ctx->zd_is_update = (op == DPLANE_OP_RULE_UPDATE);
ctx->zd_vrf_id = new_rule->vrf_id;
- memcpy(ctx->zd_ifname, new_rule->ifname, sizeof(new_rule->ifname));
+ strlcpy(ctx->zd_ifname, new_rule->ifname, sizeof(ctx->zd_ifname));
ctx->u.rule.sock = new_rule->sock;
ctx->u.rule.unique = new_rule->rule.unique;
@@ -3211,7 +3356,7 @@ enum zebra_dplane_result dplane_nexthop_delete(struct nhg_hash_entry *nhe)
/*
* Enqueue LSP add for the dataplane.
*/
-enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp)
+enum zebra_dplane_result dplane_lsp_add(struct zebra_lsp *lsp)
{
enum zebra_dplane_result ret =
lsp_update_internal(lsp, DPLANE_OP_LSP_INSTALL);
@@ -3222,7 +3367,7 @@ enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp)
/*
* Enqueue LSP update for the dataplane.
*/
-enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp)
+enum zebra_dplane_result dplane_lsp_update(struct zebra_lsp *lsp)
{
enum zebra_dplane_result ret =
lsp_update_internal(lsp, DPLANE_OP_LSP_UPDATE);
@@ -3233,7 +3378,7 @@ enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp)
/*
* Enqueue LSP delete for the dataplane.
*/
-enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp)
+enum zebra_dplane_result dplane_lsp_delete(struct zebra_lsp *lsp)
{
enum zebra_dplane_result ret =
lsp_update_internal(lsp, DPLANE_OP_LSP_DELETE);
@@ -3243,15 +3388,14 @@ enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp)
/* Update or un-install resulting from an async notification */
enum zebra_dplane_result
-dplane_lsp_notif_update(zebra_lsp_t *lsp,
- enum dplane_op_e op,
+dplane_lsp_notif_update(struct zebra_lsp *lsp, enum dplane_op_e op,
struct zebra_dplane_ctx *notif_ctx)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
int ret = EINVAL;
struct zebra_dplane_ctx *ctx = NULL;
struct nhlfe_list_head *head;
- zebra_nhlfe_t *nhlfe, *new_nhlfe;
+ struct zebra_nhlfe *nhlfe, *new_nhlfe;
/* Obtain context block */
ctx = dplane_ctx_alloc();
@@ -3323,7 +3467,7 @@ enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw)
/*
* Common internal LSP update utility
*/
-static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
+static enum zebra_dplane_result lsp_update_internal(struct zebra_lsp *lsp,
enum dplane_op_e op)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
@@ -3479,18 +3623,6 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp,
return ZEBRA_DPLANE_REQUEST_FAILURE;
}
-
- /* Ensure that no existing installed v4 route conflicts with
- * the new interface prefix. This check must be done in the
- * zebra pthread context, and any route delete (if needed)
- * is enqueued before the interface address programming attempt.
- */
- if (ifc->address->family == AF_INET) {
- struct prefix_ipv4 *p;
-
- p = (struct prefix_ipv4 *)ifc->address;
- rib_lookup_and_pushup(p, ifp->vrf_id);
- }
#endif
return intf_addr_update_internal(ifp, ifc, DPLANE_OP_ADDR_INSTALL);
@@ -3640,14 +3772,10 @@ enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op,
uint16_t state = 0;
uint32_t update_flags;
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- char buf1[PREFIX_STRLEN], buf2[PREFIX_STRLEN];
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%s: init link ctx %s: ifp %s, link_ip %pIA ip %pIA",
+ __func__, dplane_op2str(op), ifp->name, link_ip, ip);
- ipaddr2str(link_ip, buf1, sizeof(buf1));
- ipaddr2str(ip, buf2, sizeof(buf2));
- zlog_debug("init link ctx %s: ifp %s, ip %s link %s",
- dplane_op2str(op), ifp->name, buf1, buf2);
- }
if (ndm_state == ZEBRA_NEIGH_STATE_REACHABLE)
state = DPLANE_NUD_REACHABLE;
else if (ndm_state == ZEBRA_NEIGH_STATE_FAILED)
@@ -4714,10 +4842,92 @@ static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
#if defined(HAVE_NETLINK)
ns_info->is_cmd = true;
- ns_info->nls = zns->netlink_dplane;
+ ns_info->nls = zns->netlink_dplane_out;
#endif /* NETLINK */
}
+#ifdef HAVE_NETLINK
+/*
+ * Callback when an OS (netlink) incoming event read is ready. This runs
+ * in the dplane pthread.
+ */
+static int dplane_incoming_read(struct thread *event)
+{
+ struct dplane_zns_info *zi = THREAD_ARG(event);
+
+ kernel_dplane_read(&zi->info);
+
+ /* Re-start read task */
+ thread_add_read(zdplane_info.dg_master, dplane_incoming_read, zi,
+ zi->info.nls.sock, &zi->t_read);
+
+ return 0;
+}
+#endif /* HAVE_NETLINK */
+
+/*
+ * Notify dplane when namespaces are enabled and disabled. The dplane
+ * needs to start and stop reading incoming events from the zns. In the
+ * common case where vrfs are _not_ namespaces, there will only be one
+ * of these.
+ *
+ * This is called in the main pthread.
+ */
+void zebra_dplane_ns_enable(struct zebra_ns *zns, bool enabled)
+{
+ struct dplane_zns_info *zi;
+
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("%s: %s for nsid %u", __func__,
+ (enabled ? "ENABLED" : "DISABLED"), zns->ns_id);
+
+ /* Search for an existing zns info entry */
+ frr_each (zns_info_list, &zdplane_info.dg_zns_list, zi) {
+ if (zi->info.ns_id == zns->ns_id)
+ break;
+ }
+
+ if (enabled) {
+ /* Create a new entry if necessary; start reading. */
+ if (zi == NULL) {
+ zi = XCALLOC(MTYPE_DP_NS, sizeof(*zi));
+
+ zi->info.ns_id = zns->ns_id;
+
+ zns_info_list_add_tail(&zdplane_info.dg_zns_list, zi);
+
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("%s: nsid %u, new zi %p", __func__,
+ zns->ns_id, zi);
+ }
+
+ /* Make sure we're up-to-date with the zns object */
+#if defined(HAVE_NETLINK)
+ zi->info.is_cmd = false;
+ zi->info.nls = zns->netlink_dplane_in;
+
+ /* Start read task for the dplane pthread. */
+ if (zdplane_info.dg_master)
+ thread_add_read(zdplane_info.dg_master,
+ dplane_incoming_read, zi,
+ zi->info.nls.sock, &zi->t_read);
+#endif
+ } else if (zi) {
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("%s: nsid %u, deleting zi %p", __func__,
+ zns->ns_id, zi);
+
+ /* Stop reading, free memory */
+ zns_info_list_del(&zdplane_info.dg_zns_list, zi);
+
+ if (zdplane_info.dg_master)
+ thread_cancel_async(zdplane_info.dg_master, &zi->t_read,
+ NULL);
+
+ XFREE(MTYPE_DP_NS, zi);
+ }
+}
+
/*
* Provider api to signal that work/events are available
* for the dataplane pthread.
@@ -4883,6 +5093,14 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_ifname(ctx),
ctx->u.gre.link_ifindex);
break;
+
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
+ zlog_debug("Dplane incoming op %s, intf %s, addr %pFX",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ dplane_ctx_get_ifname(ctx),
+ dplane_ctx_get_intf_addr(ctx));
+ break;
}
}
@@ -5025,6 +5243,11 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_BR_PORT_UPDATE:
break;
+ /* TODO -- error counters for incoming events? */
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
+ break;
+
case DPLANE_OP_NONE:
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
atomic_fetch_add_explicit(&zdplane_info.dg_other_errors,
@@ -5360,9 +5583,21 @@ done:
*/
static int dplane_check_shutdown_status(struct thread *event)
{
+ struct dplane_zns_info *zi;
+
if (IS_ZEBRA_DEBUG_DPLANE)
zlog_debug("Zebra dataplane shutdown status check called");
+ /* Remove any zns info entries as we stop the dplane pthread. */
+ frr_each_safe (zns_info_list, &zdplane_info.dg_zns_list, zi) {
+ zns_info_list_del(&zdplane_info.dg_zns_list, zi);
+
+ if (zdplane_info.dg_master)
+ thread_cancel(&zi->t_read);
+
+ XFREE(MTYPE_DP_NS, zi);
+ }
+
if (dplane_work_pending()) {
/* Reschedule dplane check on a short timer */
thread_add_timer_msec(zdplane_info.dg_master,
@@ -5657,6 +5892,7 @@ static void zebra_dplane_init_internal(void)
TAILQ_INIT(&zdplane_info.dg_update_ctx_q);
TAILQ_INIT(&zdplane_info.dg_providers_q);
+ zns_info_list_init(&zdplane_info.dg_zns_list);
zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;
@@ -5672,6 +5908,7 @@ static void zebra_dplane_init_internal(void)
*/
void zebra_dplane_start(void)
{
+ struct dplane_zns_info *zi;
struct zebra_dplane_provider *prov;
struct frr_pthread_attr pattr = {
.start = frr_pthread_attr_default.start,
@@ -5691,6 +5928,14 @@ void zebra_dplane_start(void)
thread_add_event(zdplane_info.dg_master, dplane_thread_loop, NULL, 0,
&zdplane_info.dg_t_update);
+ /* Enqueue reads if necessary */
+ frr_each (zns_info_list, &zdplane_info.dg_zns_list, zi) {
+#if defined(HAVE_NETLINK)
+ thread_add_read(zdplane_info.dg_master, dplane_incoming_read,
+ zi, zi->info.nls.sock, &zi->t_read);
+#endif
+ }
+
/* Call start callbacks for registered providers */
DPLANE_LOCK();