mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-11 18:48:14 +00:00
Merge pull request #4778 from mjstapp/dplane_macs
zebra: use dataplane for evpn macs
This commit is contained in:
commit
ad4c7e8d4e
10
zebra/rt.h
10
zebra/rt.h
@ -41,7 +41,7 @@ extern "C" {
|
|||||||
((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
|
((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update or delete a route, LSP, or pseudowire from the kernel,
|
* Update or delete a route, LSP, pseudowire, or vxlan MAC from the kernel,
|
||||||
* using info from a dataplane context.
|
* using info from a dataplane context.
|
||||||
*/
|
*/
|
||||||
extern enum zebra_dplane_result kernel_route_update(
|
extern enum zebra_dplane_result kernel_route_update(
|
||||||
@ -55,6 +55,8 @@ enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx);
|
|||||||
enum zebra_dplane_result kernel_address_update_ctx(
|
enum zebra_dplane_result kernel_address_update_ctx(
|
||||||
struct zebra_dplane_ctx *ctx);
|
struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
|
enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
|
extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
|
||||||
int llalen, ns_id_t ns_id);
|
int llalen, ns_id_t ns_id);
|
||||||
extern int kernel_interface_set_master(struct interface *master,
|
extern int kernel_interface_set_master(struct interface *master,
|
||||||
@ -68,12 +70,6 @@ extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
|
|||||||
struct in_addr *vtep_ip);
|
struct in_addr *vtep_ip);
|
||||||
extern int kernel_del_vtep(vni_t vni, struct interface *ifp,
|
extern int kernel_del_vtep(vni_t vni, struct interface *ifp,
|
||||||
struct in_addr *vtep_ip);
|
struct in_addr *vtep_ip);
|
||||||
extern int kernel_add_mac(struct interface *ifp, vlanid_t vid,
|
|
||||||
struct ethaddr *mac, struct in_addr vtep_ip,
|
|
||||||
bool sticky);
|
|
||||||
extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
|
|
||||||
struct ethaddr *mac, struct in_addr vtep_ip);
|
|
||||||
|
|
||||||
extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
|
extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
|
||||||
struct ethaddr *mac, uint8_t flags);
|
struct ethaddr *mac, uint8_t flags);
|
||||||
extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
|
extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
|
||||||
|
@ -2292,33 +2292,70 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
|
|
||||||
struct ethaddr *mac, struct in_addr vtep_ip,
|
/*
|
||||||
int cmd, bool sticky)
|
* Netlink-specific handler for MAC updates using dataplane context object.
|
||||||
|
*/
|
||||||
|
static enum zebra_dplane_result
|
||||||
|
netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct zebra_ns *zns;
|
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr n;
|
struct nlmsghdr n;
|
||||||
struct ndmsg ndm;
|
struct ndmsg ndm;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
} req;
|
} req;
|
||||||
|
int ret;
|
||||||
int dst_alen;
|
int dst_alen;
|
||||||
struct zebra_if *zif;
|
struct zebra_if *zif;
|
||||||
struct interface *br_if;
|
struct interface *br_if;
|
||||||
struct zebra_if *br_zif;
|
struct zebra_if *br_zif;
|
||||||
char buf[ETHER_ADDR_STRLEN];
|
|
||||||
int vid_present = 0;
|
int vid_present = 0;
|
||||||
char vid_buf[20];
|
char vid_buf[20];
|
||||||
char dst_buf[30];
|
struct zebra_ns *zns;
|
||||||
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
|
struct interface *ifp;
|
||||||
|
int cmd;
|
||||||
|
struct in_addr vtep_ip;
|
||||||
|
vlanid_t vid;
|
||||||
|
|
||||||
|
if (dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL)
|
||||||
|
cmd = RTM_NEWNEIGH;
|
||||||
|
else
|
||||||
|
cmd = RTM_DELNEIGH;
|
||||||
|
|
||||||
|
/* Locate zebra ns and interface objects from context data */
|
||||||
|
zns = zebra_ns_lookup(dplane_ctx_get_ns(ctx)->ns_id);
|
||||||
|
if (zns == NULL) {
|
||||||
|
/* Nothing to be done */
|
||||||
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||||
|
zlog_debug("MAC %s on IF %s(%u) - zebra ns unknown",
|
||||||
|
(cmd == RTM_NEWNEIGH) ? "add" : "del",
|
||||||
|
dplane_ctx_get_ifname(ctx),
|
||||||
|
dplane_ctx_get_ifindex(ctx));
|
||||||
|
|
||||||
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifp = if_lookup_by_index_per_ns(zns, dplane_ctx_get_ifindex(ctx));
|
||||||
|
if (ifp == NULL) {
|
||||||
|
/* Nothing to be done */
|
||||||
|
/* Nothing to be done */
|
||||||
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||||
|
zlog_debug("MAC %s on IF %s(%u) - interface unknown",
|
||||||
|
(cmd == RTM_NEWNEIGH) ? "add" : "del",
|
||||||
|
dplane_ctx_get_ifname(ctx),
|
||||||
|
dplane_ctx_get_ifindex(ctx));
|
||||||
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vid = dplane_ctx_mac_get_vlan(ctx);
|
||||||
|
|
||||||
zns = zvrf->zns;
|
|
||||||
zif = ifp->info;
|
zif = ifp->info;
|
||||||
if ((br_if = zif->brslave_info.br_if) == NULL) {
|
if ((br_if = zif->brslave_info.br_if) == NULL) {
|
||||||
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||||
zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
|
zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
|
||||||
(cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
|
(cmd == RTM_NEWNEIGH) ? "add" : "del",
|
||||||
ifp->ifindex);
|
ifp->name, ifp->ifindex);
|
||||||
return -1;
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&req, 0, sizeof(req));
|
memset(&req, 0, sizeof(req));
|
||||||
@ -2332,16 +2369,19 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
|
|||||||
req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
|
req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
|
||||||
req.ndm.ndm_state = NUD_REACHABLE;
|
req.ndm.ndm_state = NUD_REACHABLE;
|
||||||
|
|
||||||
if (sticky)
|
if (dplane_ctx_mac_is_sticky(ctx))
|
||||||
req.ndm.ndm_state |= NUD_NOARP;
|
req.ndm.ndm_state |= NUD_NOARP;
|
||||||
else
|
else
|
||||||
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
|
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
|
||||||
|
|
||||||
addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
|
addattr_l(&req.n, sizeof(req), NDA_LLADDR,
|
||||||
|
dplane_ctx_mac_get_addr(ctx), 6);
|
||||||
req.ndm.ndm_ifindex = ifp->ifindex;
|
req.ndm.ndm_ifindex = ifp->ifindex;
|
||||||
|
|
||||||
dst_alen = 4; // TODO: hardcoded
|
dst_alen = 4; // TODO: hardcoded
|
||||||
|
vtep_ip = *(dplane_ctx_mac_get_vtep_ip(ctx));
|
||||||
addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
|
addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
|
||||||
sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
|
|
||||||
br_zif = (struct zebra_if *)br_if->info;
|
br_zif = (struct zebra_if *)br_if->info;
|
||||||
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
|
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
|
||||||
addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
|
addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
|
||||||
@ -2350,16 +2390,29 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
|
|||||||
}
|
}
|
||||||
addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
|
addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
if (IS_ZEBRA_DEBUG_KERNEL) {
|
||||||
|
char ipbuf[PREFIX_STRLEN];
|
||||||
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
|
char dst_buf[PREFIX_STRLEN + 10];
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &vtep_ip, ipbuf, sizeof(ipbuf));
|
||||||
|
snprintf(dst_buf, sizeof(dst_buf), " dst %s", ipbuf);
|
||||||
|
prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, sizeof(buf));
|
||||||
|
|
||||||
zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
|
zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
|
||||||
nl_msg_type_to_str(cmd),
|
nl_msg_type_to_str(cmd),
|
||||||
nl_family_to_str(req.ndm.ndm_family), ifp->name,
|
nl_family_to_str(req.ndm.ndm_family), ifp->name,
|
||||||
ifp->ifindex, vid_present ? vid_buf : "",
|
ifp->ifindex, vid_present ? vid_buf : "",
|
||||||
sticky ? "sticky " : "",
|
dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
|
||||||
prefix_mac2str(mac, buf, sizeof(buf)), dst_buf);
|
buf, dst_buf);
|
||||||
|
}
|
||||||
|
|
||||||
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
|
ret = netlink_talk_info(netlink_talk_filter, &req.n,
|
||||||
0);
|
dplane_ctx_get_ns(ctx), 0);
|
||||||
|
if (ret == 0)
|
||||||
|
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||||
|
else
|
||||||
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2772,17 +2825,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
|
/*
|
||||||
struct in_addr vtep_ip, bool sticky)
|
* Update MAC, using dataplane context object.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_NEWNEIGH,
|
return netlink_macfdb_update_ctx(ctx);
|
||||||
sticky);
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
|
|
||||||
struct in_addr vtep_ip)
|
|
||||||
{
|
|
||||||
return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_DELNEIGH, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
|
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
|
||||||
|
@ -386,16 +386,12 @@ int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
|
/*
|
||||||
struct in_addr vtep_ip, bool sticky)
|
* Update MAC, using dataplane context object. No-op here for now.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
return 0;
|
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||||
}
|
|
||||||
|
|
||||||
int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
|
|
||||||
struct in_addr vtep_ip)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
|
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
|
||||||
|
@ -109,8 +109,6 @@ struct dplane_route_info {
|
|||||||
* Pseudowire info for the dataplane
|
* Pseudowire info for the dataplane
|
||||||
*/
|
*/
|
||||||
struct dplane_pw_info {
|
struct dplane_pw_info {
|
||||||
char ifname[IF_NAMESIZE];
|
|
||||||
ifindex_t ifindex;
|
|
||||||
int type;
|
int type;
|
||||||
int af;
|
int af;
|
||||||
int status;
|
int status;
|
||||||
@ -130,9 +128,6 @@ struct dplane_pw_info {
|
|||||||
*/
|
*/
|
||||||
struct dplane_intf_info {
|
struct dplane_intf_info {
|
||||||
|
|
||||||
char ifname[INTERFACE_NAMSIZ];
|
|
||||||
ifindex_t ifindex;
|
|
||||||
|
|
||||||
uint32_t metric;
|
uint32_t metric;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
@ -152,6 +147,17 @@ struct dplane_intf_info {
|
|||||||
char label_buf[32];
|
char label_buf[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MAC address info for the dataplane.
|
||||||
|
*/
|
||||||
|
struct dplane_mac_info {
|
||||||
|
vlanid_t vid;
|
||||||
|
struct ethaddr mac;
|
||||||
|
struct in_addr vtep_ip;
|
||||||
|
bool is_sticky;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The context block used to exchange info about route updates across
|
* The context block used to exchange info about route updates across
|
||||||
* the boundary between the zebra main context (and pthread) and the
|
* the boundary between the zebra main context (and pthread) and the
|
||||||
@ -188,12 +194,16 @@ struct zebra_dplane_ctx {
|
|||||||
vrf_id_t zd_vrf_id;
|
vrf_id_t zd_vrf_id;
|
||||||
uint32_t zd_table_id;
|
uint32_t zd_table_id;
|
||||||
|
|
||||||
|
char zd_ifname[INTERFACE_NAMSIZ];
|
||||||
|
ifindex_t zd_ifindex;
|
||||||
|
|
||||||
/* Support info for different kinds of updates */
|
/* Support info for different kinds of updates */
|
||||||
union {
|
union {
|
||||||
struct dplane_route_info rinfo;
|
struct dplane_route_info rinfo;
|
||||||
zebra_lsp_t lsp;
|
zebra_lsp_t lsp;
|
||||||
struct dplane_pw_info pw;
|
struct dplane_pw_info pw;
|
||||||
struct dplane_intf_info intf;
|
struct dplane_intf_info intf;
|
||||||
|
struct dplane_mac_info macinfo;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
/* Namespace info, used especially for netlink kernel communication */
|
/* Namespace info, used especially for netlink kernel communication */
|
||||||
@ -273,8 +283,8 @@ static struct zebra_dplane_globals {
|
|||||||
/* Sentinel for end of shutdown */
|
/* Sentinel for end of shutdown */
|
||||||
volatile bool dg_run;
|
volatile bool dg_run;
|
||||||
|
|
||||||
/* Route-update context queue inbound to the dataplane */
|
/* Update context queue inbound to the dataplane */
|
||||||
TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_route_ctx_q;
|
TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_update_ctx_q;
|
||||||
|
|
||||||
/* Ordered list of providers */
|
/* Ordered list of providers */
|
||||||
TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
|
TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
|
||||||
@ -308,6 +318,9 @@ static struct zebra_dplane_globals {
|
|||||||
_Atomic uint32_t dg_intf_addrs_in;
|
_Atomic uint32_t dg_intf_addrs_in;
|
||||||
_Atomic uint32_t dg_intf_addr_errors;
|
_Atomic uint32_t dg_intf_addr_errors;
|
||||||
|
|
||||||
|
_Atomic uint32_t dg_macs_in;
|
||||||
|
_Atomic uint32_t dg_mac_errors;
|
||||||
|
|
||||||
_Atomic uint32_t dg_update_yields;
|
_Atomic uint32_t dg_update_yields;
|
||||||
|
|
||||||
/* Dataplane pthread */
|
/* Dataplane pthread */
|
||||||
@ -348,6 +361,10 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
|
|||||||
static enum zebra_dplane_result intf_addr_update_internal(
|
static enum zebra_dplane_result intf_addr_update_internal(
|
||||||
const struct interface *ifp, const struct connected *ifc,
|
const struct interface *ifp, const struct connected *ifc,
|
||||||
enum dplane_op_e op);
|
enum dplane_op_e op);
|
||||||
|
static enum zebra_dplane_result mac_update_internal(
|
||||||
|
enum dplane_op_e op, const struct interface *ifp,
|
||||||
|
vlanid_t vid, const struct ethaddr *mac,
|
||||||
|
struct in_addr vtep_ip, bool sticky);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Public APIs
|
* Public APIs
|
||||||
@ -466,6 +483,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DPLANE_OP_MAC_INSTALL:
|
||||||
|
case DPLANE_OP_MAC_DELETE:
|
||||||
case DPLANE_OP_NONE:
|
case DPLANE_OP_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -626,6 +645,12 @@ const char *dplane_op2str(enum dplane_op_e op)
|
|||||||
ret = "ADDR_UNINSTALL";
|
ret = "ADDR_UNINSTALL";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DPLANE_OP_MAC_INSTALL:
|
||||||
|
ret = "MAC_INSTALL";
|
||||||
|
break;
|
||||||
|
case DPLANE_OP_MAC_DELETE:
|
||||||
|
ret = "MAC_DELETE";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -744,6 +769,19 @@ void dplane_ctx_set_notif_provider(struct zebra_dplane_ctx *ctx,
|
|||||||
|
|
||||||
ctx->zd_notif_provider = id;
|
ctx->zd_notif_provider = id;
|
||||||
}
|
}
|
||||||
|
const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->zd_ifname;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->zd_ifindex;
|
||||||
|
}
|
||||||
|
|
||||||
void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type)
|
void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type)
|
||||||
{
|
{
|
||||||
@ -1030,13 +1068,6 @@ uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx)
|
|||||||
return ctx->u.lsp.num_ecmp;
|
return ctx->u.lsp.num_ecmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx)
|
|
||||||
{
|
|
||||||
DPLANE_CTX_VALID(ctx);
|
|
||||||
|
|
||||||
return ctx->u.pw.ifname;
|
|
||||||
}
|
|
||||||
|
|
||||||
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx)
|
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
DPLANE_CTX_VALID(ctx);
|
DPLANE_CTX_VALID(ctx);
|
||||||
@ -1104,20 +1135,6 @@ dplane_ctx_get_pw_nhg(const struct zebra_dplane_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Accessors for interface information */
|
/* Accessors for interface information */
|
||||||
const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
|
|
||||||
{
|
|
||||||
DPLANE_CTX_VALID(ctx);
|
|
||||||
|
|
||||||
return ctx->u.intf.ifname;
|
|
||||||
}
|
|
||||||
|
|
||||||
ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
|
|
||||||
{
|
|
||||||
DPLANE_CTX_VALID(ctx);
|
|
||||||
|
|
||||||
return ctx->u.intf.ifindex;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx)
|
uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
DPLANE_CTX_VALID(ctx);
|
DPLANE_CTX_VALID(ctx);
|
||||||
@ -1187,6 +1204,33 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx)
|
|||||||
return ctx->u.intf.label;
|
return ctx->u.intf.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Accessors for MAC information */
|
||||||
|
vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
return ctx->u.macinfo.vid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
return ctx->u.macinfo.is_sticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct ethaddr *dplane_ctx_mac_get_addr(
|
||||||
|
const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
return &(ctx->u.macinfo.mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct in_addr *dplane_ctx_mac_get_vtep_ip(
|
||||||
|
const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
return &(ctx->u.macinfo.vtep_ip);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End of dplane context accessors
|
* End of dplane context accessors
|
||||||
*/
|
*/
|
||||||
@ -1422,10 +1466,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
|
|||||||
memset(&ctx->u.pw, 0, sizeof(ctx->u.pw));
|
memset(&ctx->u.pw, 0, sizeof(ctx->u.pw));
|
||||||
|
|
||||||
/* This name appears to be c-string, so we use string copy. */
|
/* This name appears to be c-string, so we use string copy. */
|
||||||
strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
|
strlcpy(ctx->zd_ifname, pw->ifname, sizeof(ctx->zd_ifname));
|
||||||
|
|
||||||
ctx->zd_vrf_id = pw->vrf_id;
|
ctx->zd_vrf_id = pw->vrf_id;
|
||||||
ctx->u.pw.ifindex = pw->ifindex;
|
ctx->zd_ifindex = pw->ifindex;
|
||||||
ctx->u.pw.type = pw->type;
|
ctx->u.pw.type = pw->type;
|
||||||
ctx->u.pw.af = pw->af;
|
ctx->u.pw.af = pw->af;
|
||||||
ctx->u.pw.local_label = pw->local_label;
|
ctx->u.pw.local_label = pw->local_label;
|
||||||
@ -1467,10 +1511,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enqueue a new route update,
|
* Enqueue a new update,
|
||||||
* and ensure an event is active for the dataplane pthread.
|
* and ensure an event is active for the dataplane pthread.
|
||||||
*/
|
*/
|
||||||
static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
|
static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
int ret = EINVAL;
|
int ret = EINVAL;
|
||||||
uint32_t high, curr;
|
uint32_t high, curr;
|
||||||
@ -1478,7 +1522,7 @@ static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
|
|||||||
/* Enqueue for processing by the dataplane pthread */
|
/* Enqueue for processing by the dataplane pthread */
|
||||||
DPLANE_LOCK();
|
DPLANE_LOCK();
|
||||||
{
|
{
|
||||||
TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx,
|
TAILQ_INSERT_TAIL(&zdplane_info.dg_update_ctx_q, ctx,
|
||||||
zd_q_entries);
|
zd_q_entries);
|
||||||
}
|
}
|
||||||
DPLANE_UNLOCK();
|
DPLANE_UNLOCK();
|
||||||
@ -1558,7 +1602,7 @@ dplane_route_update_internal(struct route_node *rn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Enqueue context for processing */
|
/* Enqueue context for processing */
|
||||||
ret = dplane_route_enqueue(ctx);
|
ret = dplane_update_enqueue(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update counter */
|
/* Update counter */
|
||||||
@ -1724,7 +1768,7 @@ dplane_route_notif_update(struct route_node *rn,
|
|||||||
dplane_ctx_set_notif_provider(new_ctx,
|
dplane_ctx_set_notif_provider(new_ctx,
|
||||||
dplane_ctx_get_notif_provider(ctx));
|
dplane_ctx_get_notif_provider(ctx));
|
||||||
|
|
||||||
dplane_route_enqueue(new_ctx);
|
dplane_update_enqueue(new_ctx);
|
||||||
|
|
||||||
ret = ZEBRA_DPLANE_REQUEST_QUEUED;
|
ret = ZEBRA_DPLANE_REQUEST_QUEUED;
|
||||||
|
|
||||||
@ -1791,7 +1835,7 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp,
|
|||||||
ctx,
|
ctx,
|
||||||
dplane_ctx_get_notif_provider(notif_ctx));
|
dplane_ctx_get_notif_provider(notif_ctx));
|
||||||
|
|
||||||
ret = dplane_route_enqueue(ctx);
|
ret = dplane_update_enqueue(ctx);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* Update counter */
|
/* Update counter */
|
||||||
@ -1842,7 +1886,7 @@ static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
|
|||||||
if (ret != AOK)
|
if (ret != AOK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
ret = dplane_route_enqueue(ctx);
|
ret = dplane_update_enqueue(ctx);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* Update counter */
|
/* Update counter */
|
||||||
@ -1876,7 +1920,7 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
|
|||||||
if (ret != AOK)
|
if (ret != AOK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
ret = dplane_route_enqueue(ctx);
|
ret = dplane_update_enqueue(ctx);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* Update counter */
|
/* Update counter */
|
||||||
@ -1967,8 +2011,8 @@ static enum zebra_dplane_result intf_addr_update_internal(
|
|||||||
/* Init the interface-addr-specific area */
|
/* Init the interface-addr-specific area */
|
||||||
memset(&ctx->u.intf, 0, sizeof(ctx->u.intf));
|
memset(&ctx->u.intf, 0, sizeof(ctx->u.intf));
|
||||||
|
|
||||||
strlcpy(ctx->u.intf.ifname, ifp->name, sizeof(ctx->u.intf.ifname));
|
strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
|
||||||
ctx->u.intf.ifindex = ifp->ifindex;
|
ctx->zd_ifindex = ifp->ifindex;
|
||||||
ctx->u.intf.prefix = *(ifc->address);
|
ctx->u.intf.prefix = *(ifc->address);
|
||||||
|
|
||||||
if (if_is_broadcast(ifp))
|
if (if_is_broadcast(ifp))
|
||||||
@ -2003,7 +2047,7 @@ static enum zebra_dplane_result intf_addr_update_internal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dplane_route_enqueue(ctx);
|
ret = dplane_update_enqueue(ctx);
|
||||||
|
|
||||||
/* Increment counter */
|
/* Increment counter */
|
||||||
atomic_fetch_add_explicit(&zdplane_info.dg_intf_addrs_in, 1,
|
atomic_fetch_add_explicit(&zdplane_info.dg_intf_addrs_in, 1,
|
||||||
@ -2021,6 +2065,104 @@ static enum zebra_dplane_result intf_addr_update_internal(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enqueue vxlan/evpn mac add (or update).
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
|
||||||
|
vlanid_t vid,
|
||||||
|
const struct ethaddr *mac,
|
||||||
|
struct in_addr vtep_ip,
|
||||||
|
bool sticky)
|
||||||
|
{
|
||||||
|
enum zebra_dplane_result result;
|
||||||
|
|
||||||
|
/* Use common helper api */
|
||||||
|
result = mac_update_internal(DPLANE_OP_MAC_INSTALL, ifp, vid,
|
||||||
|
mac, vtep_ip, sticky);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enqueue vxlan/evpn mac delete.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
|
||||||
|
vlanid_t vid,
|
||||||
|
const struct ethaddr *mac,
|
||||||
|
struct in_addr vtep_ip)
|
||||||
|
{
|
||||||
|
enum zebra_dplane_result result;
|
||||||
|
|
||||||
|
/* Use common helper api */
|
||||||
|
result = mac_update_internal(DPLANE_OP_MAC_DELETE, ifp, vid, mac,
|
||||||
|
vtep_ip, false);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common helper api for MAC address/vxlan updates
|
||||||
|
*/
|
||||||
|
static enum zebra_dplane_result
|
||||||
|
mac_update_internal(enum dplane_op_e op,
|
||||||
|
const struct interface *ifp,
|
||||||
|
vlanid_t vid,
|
||||||
|
const struct ethaddr *mac,
|
||||||
|
struct in_addr vtep_ip,
|
||||||
|
bool sticky)
|
||||||
|
{
|
||||||
|
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
|
int ret;
|
||||||
|
struct zebra_dplane_ctx *ctx = NULL;
|
||||||
|
struct zebra_ns *zns;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
|
||||||
|
char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
|
||||||
|
|
||||||
|
zlog_debug("init mac ctx %s: mac %s, ifp %s, vtep %s",
|
||||||
|
dplane_op2str(op),
|
||||||
|
prefix_mac2str(mac, buf1, sizeof(buf1)),
|
||||||
|
ifp->name,
|
||||||
|
inet_ntop(AF_INET, &vtep_ip, buf2, sizeof(buf2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 mac-specific data area */
|
||||||
|
memset(&ctx->u.macinfo, 0, sizeof(ctx->u.macinfo));
|
||||||
|
|
||||||
|
ctx->u.macinfo.vtep_ip = vtep_ip;
|
||||||
|
ctx->u.macinfo.mac = *mac;
|
||||||
|
ctx->u.macinfo.vid = vid;
|
||||||
|
ctx->u.macinfo.is_sticky = sticky;
|
||||||
|
|
||||||
|
/* Enqueue for processing on the dplane pthread */
|
||||||
|
ret = dplane_update_enqueue(ctx);
|
||||||
|
|
||||||
|
/* Increment counter */
|
||||||
|
atomic_fetch_add_explicit(&zdplane_info.dg_macs_in, 1,
|
||||||
|
memory_order_relaxed);
|
||||||
|
|
||||||
|
if (ret == AOK)
|
||||||
|
result = ZEBRA_DPLANE_REQUEST_QUEUED;
|
||||||
|
else {
|
||||||
|
/* Error counter */
|
||||||
|
atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors, 1,
|
||||||
|
memory_order_relaxed);
|
||||||
|
dplane_ctx_free(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handler for 'show dplane'
|
* Handler for 'show dplane'
|
||||||
*/
|
*/
|
||||||
@ -2056,6 +2198,34 @@ int dplane_show_helper(struct vty *vty, bool detailed)
|
|||||||
vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max);
|
vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max);
|
||||||
vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields);
|
vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields);
|
||||||
|
|
||||||
|
incoming = atomic_load_explicit(&zdplane_info.dg_lsps_in,
|
||||||
|
memory_order_relaxed);
|
||||||
|
errs = atomic_load_explicit(&zdplane_info.dg_lsp_errors,
|
||||||
|
memory_order_relaxed);
|
||||||
|
vty_out(vty, "LSP updates: %"PRIu64"\n", incoming);
|
||||||
|
vty_out(vty, "LSP update errors: %"PRIu64"\n", errs);
|
||||||
|
|
||||||
|
incoming = atomic_load_explicit(&zdplane_info.dg_pws_in,
|
||||||
|
memory_order_relaxed);
|
||||||
|
errs = atomic_load_explicit(&zdplane_info.dg_pw_errors,
|
||||||
|
memory_order_relaxed);
|
||||||
|
vty_out(vty, "PW updates: %"PRIu64"\n", incoming);
|
||||||
|
vty_out(vty, "PW update errors: %"PRIu64"\n", errs);
|
||||||
|
|
||||||
|
incoming = atomic_load_explicit(&zdplane_info.dg_intf_addrs_in,
|
||||||
|
memory_order_relaxed);
|
||||||
|
errs = atomic_load_explicit(&zdplane_info.dg_intf_addr_errors,
|
||||||
|
memory_order_relaxed);
|
||||||
|
vty_out(vty, "Intf addr updates: %"PRIu64"\n", incoming);
|
||||||
|
vty_out(vty, "Intf addr errors: %"PRIu64"\n", errs);
|
||||||
|
|
||||||
|
incoming = atomic_load_explicit(&zdplane_info.dg_macs_in,
|
||||||
|
memory_order_relaxed);
|
||||||
|
errs = atomic_load_explicit(&zdplane_info.dg_mac_errors,
|
||||||
|
memory_order_relaxed);
|
||||||
|
vty_out(vty, "EVPN MAC updates: %"PRIu64"\n", incoming);
|
||||||
|
vty_out(vty, "EVPN MAC errors: %"PRIu64"\n", errs);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2374,7 +2544,7 @@ kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx)
|
|||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
|
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
|
||||||
zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u",
|
zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u",
|
||||||
dplane_ctx_get_pw_ifname(ctx),
|
dplane_ctx_get_ifname(ctx),
|
||||||
dplane_op2str(ctx->zd_op),
|
dplane_op2str(ctx->zd_op),
|
||||||
dplane_ctx_get_pw_af(ctx),
|
dplane_ctx_get_pw_af(ctx),
|
||||||
dplane_ctx_get_pw_local_label(ctx),
|
dplane_ctx_get_pw_local_label(ctx),
|
||||||
@ -2428,7 +2598,6 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
|
|||||||
{
|
{
|
||||||
enum zebra_dplane_result res;
|
enum zebra_dplane_result res;
|
||||||
|
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
|
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
|
||||||
char dest_str[PREFIX_STRLEN];
|
char dest_str[PREFIX_STRLEN];
|
||||||
|
|
||||||
@ -2449,6 +2618,34 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for kernel-facing MAC address updates
|
||||||
|
*/
|
||||||
|
static enum zebra_dplane_result
|
||||||
|
kernel_dplane_mac_update(struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
enum zebra_dplane_result res;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
|
||||||
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
|
|
||||||
|
prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf,
|
||||||
|
sizeof(buf));
|
||||||
|
|
||||||
|
zlog_debug("Dplane %s, mac %s, ifindex %u",
|
||||||
|
dplane_op2str(dplane_ctx_get_op(ctx)),
|
||||||
|
buf, dplane_ctx_get_ifindex(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
res = kernel_mac_update_ctx(ctx);
|
||||||
|
|
||||||
|
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||||
|
atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors,
|
||||||
|
1, memory_order_relaxed);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel provider callback
|
* Kernel provider callback
|
||||||
*/
|
*/
|
||||||
@ -2503,6 +2700,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
|
|||||||
res = kernel_dplane_address_update(ctx);
|
res = kernel_dplane_address_update(ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DPLANE_OP_MAC_INSTALL:
|
||||||
|
case DPLANE_OP_MAC_DELETE:
|
||||||
|
res = kernel_dplane_mac_update(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
/* Ignore 'notifications' - no-op */
|
/* Ignore 'notifications' - no-op */
|
||||||
case DPLANE_OP_SYS_ROUTE_ADD:
|
case DPLANE_OP_SYS_ROUTE_ADD:
|
||||||
case DPLANE_OP_SYS_ROUTE_DELETE:
|
case DPLANE_OP_SYS_ROUTE_DELETE:
|
||||||
@ -2682,7 +2884,7 @@ static bool dplane_work_pending(void)
|
|||||||
*/
|
*/
|
||||||
DPLANE_LOCK();
|
DPLANE_LOCK();
|
||||||
{
|
{
|
||||||
ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
|
ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
|
||||||
prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
|
prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
|
||||||
}
|
}
|
||||||
DPLANE_UNLOCK();
|
DPLANE_UNLOCK();
|
||||||
@ -2810,9 +3012,9 @@ static int dplane_thread_loop(struct thread *event)
|
|||||||
|
|
||||||
/* Move new work from incoming list to temp list */
|
/* Move new work from incoming list to temp list */
|
||||||
for (counter = 0; counter < limit; counter++) {
|
for (counter = 0; counter < limit; counter++) {
|
||||||
ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
|
ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
TAILQ_REMOVE(&zdplane_info.dg_route_ctx_q, ctx,
|
TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
|
||||||
zd_q_entries);
|
zd_q_entries);
|
||||||
|
|
||||||
ctx->zd_provider = prov->dp_id;
|
ctx->zd_provider = prov->dp_id;
|
||||||
@ -2997,7 +3199,7 @@ static void zebra_dplane_init_internal(void)
|
|||||||
|
|
||||||
pthread_mutex_init(&zdplane_info.dg_mutex, NULL);
|
pthread_mutex_init(&zdplane_info.dg_mutex, NULL);
|
||||||
|
|
||||||
TAILQ_INIT(&zdplane_info.dg_route_ctx_q);
|
TAILQ_INIT(&zdplane_info.dg_update_ctx_q);
|
||||||
TAILQ_INIT(&zdplane_info.dg_providers_q);
|
TAILQ_INIT(&zdplane_info.dg_providers_q);
|
||||||
|
|
||||||
zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;
|
zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "lib/nexthop.h"
|
#include "lib/nexthop.h"
|
||||||
#include "lib/nexthop_group.h"
|
#include "lib/nexthop_group.h"
|
||||||
#include "lib/queue.h"
|
#include "lib/queue.h"
|
||||||
|
#include "lib/vlan.h"
|
||||||
#include "zebra/zebra_ns.h"
|
#include "zebra/zebra_ns.h"
|
||||||
#include "zebra/rib.h"
|
#include "zebra/rib.h"
|
||||||
#include "zebra/zserv.h"
|
#include "zebra/zserv.h"
|
||||||
@ -124,6 +125,10 @@ enum dplane_op_e {
|
|||||||
/* Interface address update */
|
/* Interface address update */
|
||||||
DPLANE_OP_ADDR_INSTALL,
|
DPLANE_OP_ADDR_INSTALL,
|
||||||
DPLANE_OP_ADDR_UNINSTALL,
|
DPLANE_OP_ADDR_UNINSTALL,
|
||||||
|
|
||||||
|
/* MAC address update */
|
||||||
|
DPLANE_OP_MAC_INSTALL,
|
||||||
|
DPLANE_OP_MAC_DELETE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Enable system route notifications */
|
/* Enable system route notifications */
|
||||||
@ -180,6 +185,8 @@ const char *dplane_op2str(enum dplane_op_e op);
|
|||||||
const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx);
|
const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx);
|
||||||
void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx,
|
void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx,
|
||||||
const struct prefix *dest);
|
const struct prefix *dest);
|
||||||
|
const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx);
|
||||||
|
ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
/* Retrieve last/current provider id */
|
/* Retrieve last/current provider id */
|
||||||
uint32_t dplane_ctx_get_provider(const struct zebra_dplane_ctx *ctx);
|
uint32_t dplane_ctx_get_provider(const struct zebra_dplane_ctx *ctx);
|
||||||
@ -262,7 +269,6 @@ const zebra_nhlfe_t *dplane_ctx_set_best_nhlfe(struct zebra_dplane_ctx *ctx,
|
|||||||
uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
|
uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
/* Accessors for pseudowire information */
|
/* Accessors for pseudowire information */
|
||||||
const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx);
|
|
||||||
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx);
|
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx);
|
||||||
mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx);
|
mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx);
|
||||||
int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
|
int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
|
||||||
@ -277,8 +283,6 @@ const struct nexthop_group *dplane_ctx_get_pw_nhg(
|
|||||||
const struct zebra_dplane_ctx *ctx);
|
const struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
/* Accessors for interface information */
|
/* Accessors for interface information */
|
||||||
const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx);
|
|
||||||
ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx);
|
|
||||||
uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx);
|
uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx);
|
||||||
/* Is interface addr p2p? */
|
/* Is interface addr p2p? */
|
||||||
bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx);
|
bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx);
|
||||||
@ -292,6 +296,14 @@ const struct prefix *dplane_ctx_get_intf_dest(
|
|||||||
bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx);
|
bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx);
|
||||||
const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx);
|
const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
|
/* Accessors for MAC information */
|
||||||
|
vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx);
|
||||||
|
bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx);
|
||||||
|
const struct ethaddr *dplane_ctx_mac_get_addr(
|
||||||
|
const struct zebra_dplane_ctx *ctx);
|
||||||
|
const struct in_addr *dplane_ctx_mac_get_vtep_ip(
|
||||||
|
const struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
/* Namespace info - esp. for netlink communication */
|
/* Namespace info - esp. for netlink communication */
|
||||||
const struct zebra_dplane_info *dplane_ctx_get_ns(
|
const struct zebra_dplane_info *dplane_ctx_get_ns(
|
||||||
const struct zebra_dplane_ctx *ctx);
|
const struct zebra_dplane_ctx *ctx);
|
||||||
@ -353,6 +365,19 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp,
|
|||||||
enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
|
enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
|
||||||
const struct connected *ifc);
|
const struct connected *ifc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enqueue evpn mac operations for the dataplane.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
|
||||||
|
vlanid_t vid,
|
||||||
|
const struct ethaddr *mac,
|
||||||
|
struct in_addr vtep_ip,
|
||||||
|
bool sticky);
|
||||||
|
|
||||||
|
enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
|
||||||
|
vlanid_t vid,
|
||||||
|
const struct ethaddr *mac,
|
||||||
|
struct in_addr vtep_ip);
|
||||||
|
|
||||||
/* Retrieve the limit on the number of pending, unprocessed updates. */
|
/* Retrieve the limit on the number of pending, unprocessed updates. */
|
||||||
uint32_t dplane_get_in_queue_limit(void);
|
uint32_t dplane_get_in_queue_limit(void);
|
||||||
|
@ -369,7 +369,7 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
|
|||||||
|
|
||||||
/* ioctl */
|
/* ioctl */
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
|
strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
|
||||||
sizeof(ifr.ifr_name));
|
sizeof(ifr.ifr_name));
|
||||||
ifr.ifr_data = (caddr_t)&imr;
|
ifr.ifr_data = (caddr_t)&imr;
|
||||||
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
||||||
@ -388,7 +388,7 @@ static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx)
|
|||||||
|
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
memset(&imr, 0, sizeof(imr));
|
memset(&imr, 0, sizeof(imr));
|
||||||
strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
|
strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
|
||||||
sizeof(ifr.ifr_name));
|
sizeof(ifr.ifr_name));
|
||||||
ifr.ifr_data = (caddr_t)&imr;
|
ifr.ifr_data = (caddr_t)&imr;
|
||||||
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
||||||
|
@ -3178,7 +3178,7 @@ static int handle_pw_result(struct zebra_dplane_ctx *ctx)
|
|||||||
|
|
||||||
if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
|
if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
|
||||||
vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
|
vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
|
||||||
pw = zebra_pw_find(vrf, dplane_ctx_get_pw_ifname(ctx));
|
pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx));
|
||||||
if (pw)
|
if (pw)
|
||||||
zebra_pw_install_failure(pw);
|
zebra_pw_install_failure(pw);
|
||||||
}
|
}
|
||||||
@ -3270,6 +3270,11 @@ static int rib_process_dplane_results(struct thread *thread)
|
|||||||
dplane_ctx_fini(&ctx);
|
dplane_ctx_fini(&ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DPLANE_OP_MAC_INSTALL:
|
||||||
|
case DPLANE_OP_MAC_DELETE:
|
||||||
|
zebra_vxlan_handle_result(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Don't expect this: just return the struct? */
|
/* Don't expect this: just return the struct? */
|
||||||
dplane_ctx_fini(&ctx);
|
dplane_ctx_fini(&ctx);
|
||||||
|
@ -3733,13 +3733,14 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install remote MAC into the kernel.
|
* Install remote MAC into the forwarding plane.
|
||||||
*/
|
*/
|
||||||
static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
|
static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
|
||||||
{
|
{
|
||||||
struct zebra_if *zif;
|
struct zebra_if *zif;
|
||||||
struct zebra_l2info_vxlan *vxl;
|
struct zebra_l2info_vxlan *vxl;
|
||||||
bool sticky;
|
bool sticky;
|
||||||
|
enum zebra_dplane_result res;
|
||||||
|
|
||||||
if (!(mac->flags & ZEBRA_MAC_REMOTE))
|
if (!(mac->flags & ZEBRA_MAC_REMOTE))
|
||||||
return 0;
|
return 0;
|
||||||
@ -3752,12 +3753,16 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
|
|||||||
sticky = !!CHECK_FLAG(mac->flags,
|
sticky = !!CHECK_FLAG(mac->flags,
|
||||||
(ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
|
(ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
|
||||||
|
|
||||||
return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
|
res = dplane_mac_add(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
|
||||||
mac->fwd_info.r_vtep_ip, sticky);
|
mac->fwd_info.r_vtep_ip, sticky);
|
||||||
|
if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Uninstall remote MAC from the kernel.
|
* Uninstall remote MAC from the forwarding plane.
|
||||||
*/
|
*/
|
||||||
static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
|
static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
|
||||||
{
|
{
|
||||||
@ -3765,6 +3770,7 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
|
|||||||
struct zebra_l2info_vxlan *vxl;
|
struct zebra_l2info_vxlan *vxl;
|
||||||
struct in_addr vtep_ip;
|
struct in_addr vtep_ip;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
enum zebra_dplane_result res;
|
||||||
|
|
||||||
if (!(mac->flags & ZEBRA_MAC_REMOTE))
|
if (!(mac->flags & ZEBRA_MAC_REMOTE))
|
||||||
return 0;
|
return 0;
|
||||||
@ -3783,7 +3789,11 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
|
|||||||
ifp = zvni->vxlan_if;
|
ifp = zvni->vxlan_if;
|
||||||
vtep_ip = mac->fwd_info.r_vtep_ip;
|
vtep_ip = mac->fwd_info.r_vtep_ip;
|
||||||
|
|
||||||
return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
|
res = dplane_mac_del(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
|
||||||
|
if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4470,12 +4480,13 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install remote RMAC into the kernel.
|
* Install remote RMAC into the forwarding plane.
|
||||||
*/
|
*/
|
||||||
static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
|
static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
|
||||||
{
|
{
|
||||||
struct zebra_if *zif = NULL;
|
struct zebra_if *zif = NULL;
|
||||||
struct zebra_l2info_vxlan *vxl = NULL;
|
struct zebra_l2info_vxlan *vxl = NULL;
|
||||||
|
enum zebra_dplane_result res;
|
||||||
|
|
||||||
if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
|
if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
|
||||||
|| !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
|
|| !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
|
||||||
@ -4487,18 +4498,23 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
|
|||||||
|
|
||||||
vxl = &zif->l2info.vxl;
|
vxl = &zif->l2info.vxl;
|
||||||
|
|
||||||
return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
|
res = dplane_mac_add(zl3vni->vxlan_if, vxl->access_vlan,
|
||||||
&zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
|
&zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
|
||||||
|
if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Uninstall remote RMAC from the kernel.
|
* Uninstall remote RMAC from the forwarding plane.
|
||||||
*/
|
*/
|
||||||
static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
|
static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
|
||||||
{
|
{
|
||||||
char buf[ETHER_ADDR_STRLEN];
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
struct zebra_if *zif = NULL;
|
struct zebra_if *zif = NULL;
|
||||||
struct zebra_l2info_vxlan *vxl = NULL;
|
struct zebra_l2info_vxlan *vxl = NULL;
|
||||||
|
enum zebra_dplane_result res;
|
||||||
|
|
||||||
if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
|
if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
|
||||||
|| !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
|
|| !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
|
||||||
@ -4518,8 +4534,12 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
|
|||||||
|
|
||||||
vxl = &zif->l2info.vxl;
|
vxl = &zif->l2info.vxl;
|
||||||
|
|
||||||
return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
|
res = dplane_mac_del(zl3vni->vxlan_if, vxl->access_vlan,
|
||||||
&zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
|
&zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
|
||||||
|
if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle rmac add */
|
/* handle rmac add */
|
||||||
@ -9913,6 +9933,15 @@ static int zebra_evpn_cfg_clean_up(struct zserv *client)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle results for vxlan dataplane operations.
|
||||||
|
*/
|
||||||
|
extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
/* TODO -- anything other than freeing the context? */
|
||||||
|
dplane_ctx_fini(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* Cleanup BGP EVPN configuration upon client disconnect */
|
/* Cleanup BGP EVPN configuration upon client disconnect */
|
||||||
extern void zebra_evpn_init(void)
|
extern void zebra_evpn_init(void)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "lib/json.h"
|
#include "lib/json.h"
|
||||||
#include "zebra/zebra_vrf.h"
|
#include "zebra/zebra_vrf.h"
|
||||||
#include "zebra/zserv.h"
|
#include "zebra/zserv.h"
|
||||||
|
#include "zebra/zebra_dplane.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -213,6 +214,8 @@ extern int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
|
|||||||
extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
|
extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
|
||||||
struct zebra_vrf *zvrf,
|
struct zebra_vrf *zvrf,
|
||||||
vni_t vni);
|
vni_t vni);
|
||||||
|
extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
extern void zebra_evpn_init(void);
|
extern void zebra_evpn_init(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
Reference in New Issue
Block a user