summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_nexthop.c13
-rw-r--r--bgpd/bgp_nexthop.h5
-rw-r--r--zebra/dpdk/zebra_dplane_dpdk.c2
-rw-r--r--zebra/dplane_fpm_nl.c1
-rw-r--r--zebra/if_netlink.c136
-rw-r--r--zebra/kernel_netlink.c15
-rw-r--r--zebra/kernel_socket.c1
-rw-r--r--zebra/zebra_dplane.c56
-rw-r--r--zebra/zebra_dplane.h32
-rw-r--r--zebra/zebra_l2.h11
-rw-r--r--zebra/zebra_rib.c3
-rw-r--r--zebra/zebra_script.c1
-rw-r--r--zebra/zebra_vxlan.c111
-rw-r--r--zebra/zebra_vxlan.h2
14 files changed, 276 insertions, 113 deletions
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 564ad118eb..401549c4e8 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -1377,16 +1377,9 @@ char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache *bnc,
return buf;
}
- snprintfrr(buf, len, "%s%s%s",
- CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
- ? "Changed "
- : "",
- CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
- ? "Metric "
- : "",
- CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CONNECTED_CHANGED)
- ? "Connected "
- : "");
+ snprintfrr(buf, len, "%s%s",
+ CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED) ? "Changed " : "",
+ CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) ? "Metric " : "");
return buf;
}
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 5014eb8f34..6a4a02dcc8 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -45,11 +45,10 @@ struct bgp_nexthop_cache {
*/
bool is_evpn_gwip_nexthop;
- uint16_t change_flags;
+ uint8_t change_flags;
#define BGP_NEXTHOP_CHANGED (1 << 0)
#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
-#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
-#define BGP_NEXTHOP_MACIP_CHANGED (1 << 3)
+#define BGP_NEXTHOP_MACIP_CHANGED (1 << 2)
struct nexthop *nexthop;
time_t last_update;
diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c
index 411155167f..ae1a3743ce 100644
--- a/zebra/dpdk/zebra_dplane_dpdk.c
+++ b/zebra/dpdk/zebra_dplane_dpdk.c
@@ -400,6 +400,7 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_VLAN_INSTALL,
break;
}
}
@@ -459,6 +460,7 @@ static void zd_dpdk_process_update(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_VLAN_INSTALL,
atomic_fetch_add_explicit(&dpdk_stat->ignored_updates, 1,
memory_order_relaxed);
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 4fb57d84d9..8a967978cb 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -1058,6 +1058,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
case DPLANE_OP_NONE:
case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_VLAN_INSTALL:
break;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 8beae125d2..62b665682f 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1610,68 +1610,18 @@ int netlink_tunneldump_read(struct zebra_ns *zns)
return 0;
}
-static const char *port_state2str(uint8_t state)
+static uint8_t netlink_get_dplane_vlan_state(uint8_t state)
{
- switch (state) {
- case BR_STATE_DISABLED:
- return "DISABLED";
- case BR_STATE_LISTENING:
- return "LISTENING";
- case BR_STATE_LEARNING:
- return "LEARNING";
- case BR_STATE_FORWARDING:
- return "FORWARDING";
- case BR_STATE_BLOCKING:
- return "BLOCKING";
- }
-
- return "UNKNOWN";
-}
-
-static void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id,
- uint8_t state)
-{
- struct zebra_vxlan_vni *vnip;
-
- vnip = zebra_vxlan_if_vlanid_vni_find(zif, id);
-
- if (!vnip) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Cannot find VNI for VID (%u) IF %s for vlan state update",
- id, zif->ifp->name);
-
- return;
- }
-
- switch (state) {
- case BR_STATE_FORWARDING:
- zebra_vxlan_if_vni_up(zif->ifp, vnip);
- break;
- case BR_STATE_BLOCKING:
- zebra_vxlan_if_vni_down(zif->ifp, vnip);
- break;
- case BR_STATE_DISABLED:
- case BR_STATE_LISTENING:
- case BR_STATE_LEARNING:
- default:
- /* Not used for anything at the moment */
- break;
- }
-}
-
-static void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start,
- uint16_t id_end, uint8_t state)
-{
- struct zebra_if *zif;
-
- zif = (struct zebra_if *)ifp->info;
-
- if (!zif)
- return;
-
- for (uint16_t i = id_start; i <= id_end; i++)
- vxlan_vni_state_change(zif, i, state);
+ if (state == BR_STATE_LISTENING)
+ return ZEBRA_DPLANE_BR_STATE_LISTENING;
+ else if (state == BR_STATE_LEARNING)
+ return ZEBRA_DPLANE_BR_STATE_LEARNING;
+ else if (state == BR_STATE_FORWARDING)
+ return ZEBRA_DPLANE_BR_STATE_FORWARDING;
+ else if (state == BR_STATE_BLOCKING)
+ return ZEBRA_DPLANE_BR_STATE_BLOCKING;
+
+ return ZEBRA_DPLANE_BR_STATE_DISABLED;
}
/**
@@ -1686,7 +1636,6 @@ static void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start,
int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
{
int len, rem;
- struct interface *ifp;
struct br_vlan_msg *bvm;
struct bridge_vlan_info *vinfo;
struct rtattr *vtb[BRIDGE_VLANDB_ENTRY_MAX + 1] = {};
@@ -1694,6 +1643,9 @@ int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
uint8_t state;
uint32_t vrange;
int type;
+ uint32_t count = 0;
+ struct zebra_dplane_ctx *ctx = NULL;
+ struct zebra_vxlan_vlan_array *vlan_array = NULL;
/* We only care about state changes for now */
if (!(h->nlmsg_type == RTM_NEWVLAN))
@@ -1713,25 +1665,10 @@ int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (bvm->family != AF_BRIDGE)
return 0;
- ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), bvm->ifindex);
- if (!ifp) {
- zlog_debug("Cannot find bridge-vlan IF (%u) for vlan update",
- bvm->ifindex);
- return 0;
- }
-
- if (!IS_ZEBRA_IF_VXLAN(ifp)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Ignoring non-vxlan IF (%s) for vlan update",
- ifp->name);
-
- return 0;
- }
-
- if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("%s %s IF %s NS %u",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(bvm->family), ifp->name, ns_id);
+ ctx = dplane_ctx_alloc();
+ dplane_ctx_set_ns_id(ctx, ns_id);
+ dplane_ctx_set_op(ctx, DPLANE_OP_VLAN_INSTALL);
+ dplane_ctx_set_vlan_ifindex(ctx, bvm->ifindex);
/* Loop over "ALL" BRIDGE_VLANDB_ENTRY */
rem = len;
@@ -1762,26 +1699,39 @@ int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (!vtb[BRIDGE_VLANDB_ENTRY_STATE])
continue;
+ count++;
+ vlan_array =
+ XREALLOC(MTYPE_VLAN_CHANGE_ARR, vlan_array,
+ sizeof(struct zebra_vxlan_vlan_array) +
+ count * sizeof(struct zebra_vxlan_vlan));
+
+ memset(&vlan_array->vlans[count - 1], 0,
+ sizeof(struct zebra_vxlan_vlan));
+
state = *(uint8_t *)RTA_DATA(vtb[BRIDGE_VLANDB_ENTRY_STATE]);
if (vtb[BRIDGE_VLANDB_ENTRY_RANGE])
vrange = *(uint32_t *)RTA_DATA(
vtb[BRIDGE_VLANDB_ENTRY_RANGE]);
- if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN) {
- if (vrange)
- zlog_debug("VLANDB_ENTRY: VID (%u-%u) state=%s",
- vinfo->vid, vrange,
- port_state2str(state));
- else
- zlog_debug("VLANDB_ENTRY: VID (%u) state=%s",
- vinfo->vid, port_state2str(state));
- }
-
- vlan_id_range_state_change(
- ifp, vinfo->vid, (vrange ? vrange : vinfo->vid), state);
+ vlan_array->vlans[count - 1].state =
+ netlink_get_dplane_vlan_state(state);
+ vlan_array->vlans[count - 1].vid = vinfo->vid;
+ vlan_array->vlans[count - 1].vrange = vrange;
}
+ if (count) {
+ vlan_array->count = count;
+ dplane_ctx_set_vxlan_vlan_array(ctx, vlan_array);
+ if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("RTM_NEWVLAN for ifindex %u NS %u, enqueuing for zebra main",
+ bvm->ifindex, ns_id);
+
+ dplane_provider_enqueue_to_zebra(ctx);
+ } else
+ dplane_ctx_fini(&ctx);
+
+
return 0;
}
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 84aabc4254..3547314f84 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -430,10 +430,6 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_NEWTFILTER:
case RTM_DELTFILTER:
return netlink_tfilter_change(h, ns_id, startup);
- case RTM_NEWVLAN:
- return netlink_vlan_change(h, ns_id, startup);
- case RTM_DELVLAN:
- return netlink_vlan_change(h, ns_id, startup);
/* Messages we may receive, but ignore */
case RTM_NEWCHAIN:
@@ -449,6 +445,8 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_NEWTUNNEL:
case RTM_DELTUNNEL:
case RTM_GETTUNNEL:
+ case RTM_NEWVLAN:
+ case RTM_DELVLAN:
return 0;
default:
/*
@@ -492,6 +490,10 @@ static int dplane_netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_DELLINK:
return netlink_link_change(h, ns_id, startup);
+ case RTM_NEWVLAN:
+ case RTM_DELVLAN:
+ return netlink_vlan_change(h, ns_id, startup);
+
default:
break;
}
@@ -1621,6 +1623,7 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_IPSET_ENTRY_ADD:
case DPLANE_OP_IPSET_ENTRY_DELETE:
case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_VLAN_INSTALL:
return FRR_NETLINK_ERROR;
case DPLANE_OP_GRE_SET:
@@ -1862,8 +1865,8 @@ void kernel_init(struct zebra_ns *zns)
* setsockopt multicast group subscriptions that don't fit in nl_groups
*/
grp = RTNLGRP_BRVLAN;
- ret = setsockopt(zns->netlink.sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
- &grp, sizeof(grp));
+ ret = setsockopt(zns->netlink_dplane_in.sock, SOL_NETLINK,
+ NETLINK_ADD_MEMBERSHIP, &grp, sizeof(grp));
if (ret < 0)
zlog_notice(
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 5cfbe7a896..4789cb62f2 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1627,6 +1627,7 @@ void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
case DPLANE_OP_INTF_ADDR_DEL:
case DPLANE_OP_STARTUP_STAGE:
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
+ case DPLANE_OP_VLAN_INSTALL:
zlog_err("Unhandled dplane data for %s",
dplane_op2str(dplane_ctx_get_op(ctx)));
res = ZEBRA_DPLANE_REQUEST_FAILURE;
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 00e990e856..dd2d212dc9 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -35,6 +35,8 @@ 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");
+DEFINE_MTYPE(ZEBRA, VLAN_CHANGE_ARR, "Vlan Change Array");
+
#ifndef AOK
# define AOK 0
#endif
@@ -371,6 +373,14 @@ struct dplane_srv6_encap_ctx {
};
/*
+ * VLAN info for the dataplane
+ */
+struct dplane_vlan_info {
+ ifindex_t ifindex;
+ struct zebra_vxlan_vlan_array *vlan_array;
+};
+
+/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
* dataplane layer (and pthread).
@@ -416,6 +426,7 @@ struct zebra_dplane_ctx {
struct dplane_pw_info pw;
struct dplane_br_port_info br_port;
struct dplane_intf_info intf;
+ struct dplane_vlan_info vlan_info;
struct dplane_mac_info macinfo;
struct dplane_neigh_info neigh;
struct dplane_rule_info rule;
@@ -885,6 +896,11 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_STARTUP_STAGE:
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
break;
+ case DPLANE_OP_VLAN_INSTALL:
+ if (ctx->u.vlan_info.vlan_array)
+ XFREE(MTYPE_VLAN_CHANGE_ARR,
+ ctx->u.vlan_info.vlan_array);
+ break;
}
}
@@ -1219,6 +1235,10 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
ret = "SRV6_ENCAP_SRCADDR_SET";
break;
+
+ case DPLANE_OP_VLAN_INSTALL:
+ ret = "NEW_VLAN";
+ break;
}
return ret;
@@ -3321,6 +3341,35 @@ uint32_t dplane_get_in_queue_len(void)
memory_order_seq_cst);
}
+void dplane_ctx_set_vlan_ifindex(struct zebra_dplane_ctx *ctx, ifindex_t ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+ ctx->u.vlan_info.ifindex = ifindex;
+}
+
+ifindex_t dplane_ctx_get_vlan_ifindex(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.vlan_info.ifindex;
+}
+
+void dplane_ctx_set_vxlan_vlan_array(struct zebra_dplane_ctx *ctx,
+ struct zebra_vxlan_vlan_array *vlan_array)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.vlan_info.vlan_array = vlan_array;
+}
+
+const struct zebra_vxlan_vlan_array *
+dplane_ctx_get_vxlan_vlan_array(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.vlan_info.vlan_array;
+}
+
/*
* Internal helper that copies information from a zebra ns object; this is
* called in the zebra main pthread context as part of dplane ctx init.
@@ -6720,6 +6769,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
dplane_op2str(dplane_ctx_get_op(ctx)),
&ctx->u.srv6_encap.srcaddr);
break;
+
+ case DPLANE_OP_VLAN_INSTALL:
+ zlog_debug("Dplane %s on idx %u",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ dplane_ctx_get_vlan_ifindex(ctx));
+ break;
}
}
@@ -6888,6 +6943,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_ADDR_ADD:
case DPLANE_OP_INTF_ADDR_DEL:
case DPLANE_OP_INTF_NETCONFIG:
+ case DPLANE_OP_VLAN_INSTALL:
break;
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index a3318bf5e9..285b00c9b7 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -24,6 +24,8 @@
extern "C" {
#endif
+DECLARE_MTYPE(VLAN_CHANGE_ARR);
+
/* Retrieve the dataplane API version number; see libfrr.h to decode major,
* minor, sub version values.
* Plugins should pay attention to the major version number, at least, to
@@ -204,6 +206,9 @@ enum dplane_op_e {
DPLANE_OP_TC_FILTER_DELETE,
DPLANE_OP_TC_FILTER_UPDATE,
+ /* VLAN update */
+ DPLANE_OP_VLAN_INSTALL,
+
/* Startup Control */
DPLANE_OP_STARTUP_STAGE,
@@ -211,6 +216,13 @@ enum dplane_op_e {
DPLANE_OP_SRV6_ENCAP_SRCADDR_SET,
};
+/* Operational status of Bridge Ports */
+#define ZEBRA_DPLANE_BR_STATE_DISABLED 0x01
+#define ZEBRA_DPLANE_BR_STATE_LISTENING 0x02
+#define ZEBRA_DPLANE_BR_STATE_LEARNING 0x04
+#define ZEBRA_DPLANE_BR_STATE_FORWARDING 0x08
+#define ZEBRA_DPLANE_BR_STATE_BLOCKING 0x10
+
/*
* The vxlan/evpn neighbor management code needs some values to use
* when programming neighbor changes. Offer some platform-neutral values
@@ -1078,6 +1090,26 @@ void dplane_set_in_queue_limit(uint32_t limit, bool set);
/* Retrieve the current queue depth of incoming, unprocessed updates */
uint32_t dplane_get_in_queue_len(void);
+void dplane_ctx_set_vlan_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t ifindex);
+ifindex_t dplane_ctx_get_vlan_ifindex(struct zebra_dplane_ctx *ctx);
+struct zebra_vxlan_vlan_array;
+
+/*
+ * In netlink_vlan_change(), the memory allocated for vlan_array is freed
+ * in two cases
+ * 1) Inline free in netlink_vlan_change() when there are no new
+ * vlans to process i.e. nothing is enqueued to main thread.
+ * 2) Dplane-ctx takes over the vlan memory which gets freed in
+ * rib_process_dplane_results() after handling the vlan install
+ *
+ * Note: MTYPE of interest for this purpose is MTYPE_VLAN_CHANGE_ARR
+ */
+void dplane_ctx_set_vxlan_vlan_array(struct zebra_dplane_ctx *ctx,
+ struct zebra_vxlan_vlan_array *vlan_array);
+const struct zebra_vxlan_vlan_array *
+dplane_ctx_get_vxlan_vlan_array(struct zebra_dplane_ctx *ctx);
+
/*
* Vty/cli apis
*/
diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h
index 588917f4c0..ad5f5eeee0 100644
--- a/zebra/zebra_l2.h
+++ b/zebra/zebra_l2.h
@@ -146,6 +146,17 @@ union zebra_l2if_info {
struct zebra_l2info_gre gre;
};
+struct zebra_vxlan_vlan {
+ uint8_t state;
+ uint32_t vrange;
+ vlanid_t vid;
+};
+
+struct zebra_vxlan_vlan_array {
+ uint16_t count;
+ struct zebra_vxlan_vlan vlans[0];
+};
+
/* NOTE: These macros are to be invoked only in the "correct" context.
* IOW, the macro VNI_FROM_ZEBRA_IF() will assume the interface is
* of type ZEBRA_IF_VXLAN.
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 8ebc193fba..b8d55012d5 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -5020,6 +5020,9 @@ static void rib_process_dplane_results(struct event *thread)
zebra_ns_startup_continue(ctx);
break;
+ case DPLANE_OP_VLAN_INSTALL:
+ zebra_vlan_dplane_result(ctx);
+ break;
} /* Dispatch by op code */
dplane_ctx_fini(&ctx);
diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c
index 6c34d12c64..a0d5e2054c 100644
--- a/zebra/zebra_script.c
+++ b/zebra/zebra_script.c
@@ -418,6 +418,7 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
case DPLANE_OP_NONE:
case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_VLAN_INSTALL:
break;
} /* Dispatch by op code */
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index f1ae42e320..0f72259951 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -6246,3 +6246,114 @@ extern void zebra_evpn_init(void)
{
hook_register(zserv_client_close, zebra_evpn_cfg_clean_up);
}
+
+static const char *port_state2str(uint8_t state)
+{
+ switch (state) {
+ case ZEBRA_DPLANE_BR_STATE_DISABLED:
+ return "DISABLED";
+ case ZEBRA_DPLANE_BR_STATE_LISTENING:
+ return "LISTENING";
+ case ZEBRA_DPLANE_BR_STATE_LEARNING:
+ return "LEARNING";
+ case ZEBRA_DPLANE_BR_STATE_FORWARDING:
+ return "FORWARDING";
+ case ZEBRA_DPLANE_BR_STATE_BLOCKING:
+ return "BLOCKING";
+ }
+
+ return "UNKNOWN";
+}
+
+static void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id,
+ uint8_t state)
+{
+ struct zebra_vxlan_vni *vnip;
+
+ vnip = zebra_vxlan_if_vlanid_vni_find(zif, id);
+
+ if (!vnip) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Cannot find VNI for VID (%u) IF %s for vlan state update",
+ id, zif->ifp->name);
+
+ return;
+ }
+
+ switch (state) {
+ case ZEBRA_DPLANE_BR_STATE_FORWARDING:
+ zebra_vxlan_if_vni_up(zif->ifp, vnip);
+ break;
+ case ZEBRA_DPLANE_BR_STATE_BLOCKING:
+ zebra_vxlan_if_vni_down(zif->ifp, vnip);
+ break;
+ case ZEBRA_DPLANE_BR_STATE_DISABLED:
+ case ZEBRA_DPLANE_BR_STATE_LISTENING:
+ case ZEBRA_DPLANE_BR_STATE_LEARNING:
+ default:
+ /* Not used for anything at the moment */
+ break;
+ }
+}
+
+static void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start,
+ uint16_t id_end, uint8_t state)
+{
+ struct zebra_if *zif;
+
+ zif = (struct zebra_if *)ifp->info;
+
+ if (!zif)
+ return;
+
+ for (uint16_t i = id_start; i <= id_end; i++)
+ vxlan_vni_state_change(zif, i, state);
+}
+
+void zebra_vlan_dplane_result(struct zebra_dplane_ctx *ctx)
+{
+ int i;
+ struct interface *ifp = NULL;
+ ns_id_t ns_id = dplane_ctx_get_ns_id(ctx);
+ enum dplane_op_e op = dplane_ctx_get_op(ctx);
+ const struct zebra_vxlan_vlan_array *vlan_array =
+ dplane_ctx_get_vxlan_vlan_array(ctx);
+ ifindex_t ifindex = dplane_ctx_get_vlan_ifindex(ctx);
+
+ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifindex);
+ if (!ifp) {
+ zlog_debug("Cannot find bridge-vlan IF (%u) for vlan update",
+ ifindex);
+ return;
+ }
+
+ if (!IS_ZEBRA_IF_VXLAN(ifp)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Ignoring non-vxlan IF (%s) for vlan update",
+ ifp->name);
+
+ return;
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Dequeuing in zebra main..%s IF %s ifindex %u NS %u",
+ dplane_op2str(op), ifp->name, ifindex, ns_id);
+
+ for (i = 0; i < vlan_array->count; i++) {
+ vlanid_t vid = vlan_array->vlans[i].vid;
+ uint8_t state = vlan_array->vlans[i].state;
+ uint32_t vrange = vlan_array->vlans[i].vrange;
+
+ if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN) {
+ if (vrange)
+ zlog_debug("VLANDB_ENTRY: VID (%u-%u) state=%s",
+ vid, vrange, port_state2str(state));
+ else
+ zlog_debug("VLANDB_ENTRY: VID (%u) state=%s",
+ vid, port_state2str(state));
+ }
+
+ vlan_id_range_state_change(ifp, vid, (vrange ? vrange : vid),
+ state);
+ }
+}
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index eb02de6f7b..ef4c39c060 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -221,7 +221,7 @@ extern int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
extern void zebra_vxlan_set_accept_bgp_seq(bool set);
extern bool zebra_vxlan_get_accept_bgp_seq(void);
-
+extern void zebra_vlan_dplane_result(struct zebra_dplane_ctx *ctx);
#ifdef __cplusplus
}
#endif