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 1d2f9e695f..234908703e 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 3de6661f5d..c9861b0b5e 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -63,7 +63,6 @@ #include "zebra/zebra_l2.h" #include "zebra/netconf_netlink.h" #include "zebra/zebra_trace.h" -#include "zebra/zebra_vxlan.h" extern struct zebra_privs_t zserv_privs; @@ -1817,6 +1816,20 @@ int netlink_tunneldump_read(struct zebra_ns *zns) return 0; } +static uint8_t netlink_get_dplane_vlan_state(uint8_t 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; +} + /** * netlink_vlan_change() - Read in change about vlans from the kernel * @@ -1829,7 +1842,6 @@ int netlink_tunneldump_read(struct zebra_ns *zns) 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] = {}; @@ -1837,6 +1849,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)) @@ -1856,25 +1871,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; @@ -1905,26 +1905,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 75147e7136..f88464d745 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 @@ -370,6 +372,14 @@ struct dplane_srv6_encap_ctx { struct in6_addr srcaddr; }; +/* + * 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 @@ -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 0e9a8bfb99..3e143e8dba 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 402a3104b9..5fe79b159d 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -5083,6 +5083,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 0f0464e486..0f72259951 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -41,8 +41,6 @@ #include "zebra/zebra_evpn_mh.h" #include "zebra/zebra_evpn_vxlan.h" #include "zebra/zebra_router.h" -#include "zebra/zebra_trace.h" -#include DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix"); DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash"); @@ -6249,25 +6247,26 @@ extern void zebra_evpn_init(void) hook_register(zserv_client_close, zebra_evpn_cfg_clean_up); } -const char *port_state2str(uint8_t state) +static const char *port_state2str(uint8_t state) { switch (state) { - case BR_STATE_DISABLED: + case ZEBRA_DPLANE_BR_STATE_DISABLED: return "DISABLED"; - case BR_STATE_LISTENING: + case ZEBRA_DPLANE_BR_STATE_LISTENING: return "LISTENING"; - case BR_STATE_LEARNING: + case ZEBRA_DPLANE_BR_STATE_LEARNING: return "LEARNING"; - case BR_STATE_FORWARDING: + case ZEBRA_DPLANE_BR_STATE_FORWARDING: return "FORWARDING"; - case BR_STATE_BLOCKING: + case ZEBRA_DPLANE_BR_STATE_BLOCKING: return "BLOCKING"; } return "UNKNOWN"; } -void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id, uint8_t state) +static void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id, + uint8_t state) { struct zebra_vxlan_vni *vnip; @@ -6282,23 +6281,23 @@ void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id, uint8_t state) } switch (state) { - case BR_STATE_FORWARDING: + case ZEBRA_DPLANE_BR_STATE_FORWARDING: zebra_vxlan_if_vni_up(zif->ifp, vnip); break; - case BR_STATE_BLOCKING: + case ZEBRA_DPLANE_BR_STATE_BLOCKING: zebra_vxlan_if_vni_down(zif->ifp, vnip); break; - case BR_STATE_DISABLED: - case BR_STATE_LISTENING: - case BR_STATE_LEARNING: + 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; } } -void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start, - uint16_t id_end, uint8_t state) +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; @@ -6310,3 +6309,51 @@ void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start, 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 0b37e58cfd..ef4c39c060 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -221,11 +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 vlan_id_range_state_change(struct interface *ifp, uint16_t id_start, - uint16_t id_end, uint8_t state); -extern void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id, - uint8_t state); -extern const char *port_state2str(uint8_t state); +extern void zebra_vlan_dplane_result(struct zebra_dplane_ctx *ctx); #ifdef __cplusplus } #endif