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.c259
1 files changed, 223 insertions, 36 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 4e19e58d7a..5dcf76db15 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -180,6 +180,8 @@ struct dplane_mac_info {
struct ethaddr mac;
struct in_addr vtep_ip;
bool is_sticky;
+ uint32_t nhg_id;
+ uint32_t update_flags;
};
/*
@@ -190,6 +192,7 @@ struct dplane_neigh_info {
struct ethaddr mac;
uint32_t flags;
uint16_t state;
+ uint32_t update_flags;
};
/*
@@ -204,6 +207,7 @@ struct dplane_ctx_rule {
/* Filter criteria */
uint32_t filter_bm;
uint32_t fwmark;
+ uint8_t dsfield;
struct prefix src_ip;
struct prefix dst_ip;
};
@@ -440,13 +444,14 @@ static enum zebra_dplane_result mac_update_common(
enum dplane_op_e op, const struct interface *ifp,
const struct interface *br_ifp,
vlanid_t vid, const struct ethaddr *mac,
- struct in_addr vtep_ip, bool sticky);
+ struct in_addr vtep_ip, bool sticky, uint32_t nhg_id,
+ uint32_t update_flags);
static enum zebra_dplane_result neigh_update_internal(
enum dplane_op_e op,
const struct interface *ifp,
const struct ethaddr *mac,
const struct ipaddr *ip,
- uint32_t flags, uint16_t state);
+ uint32_t flags, uint16_t state, uint32_t update_flags);
/*
* Public APIs
@@ -1551,6 +1556,18 @@ bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx)
return ctx->u.macinfo.is_sticky;
}
+uint32_t dplane_ctx_mac_get_nhg_id(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return ctx->u.macinfo.nhg_id;
+}
+
+uint32_t dplane_ctx_mac_get_update_flags(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return ctx->u.macinfo.update_flags;
+}
+
const struct ethaddr *dplane_ctx_mac_get_addr(
const struct zebra_dplane_ctx *ctx)
{
@@ -1598,6 +1615,12 @@ uint16_t dplane_ctx_neigh_get_state(const struct zebra_dplane_ctx *ctx)
return ctx->u.neigh.state;
}
+uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return ctx->u.neigh.update_flags;
+}
+
/* Accessors for PBR rule information */
int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx)
{
@@ -1676,6 +1699,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_dsfield(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.new.dsfield;
+}
+
+uint8_t dplane_ctx_rule_get_old_dsfield(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.old.dsfield;
+}
+
const struct prefix *
dplane_ctx_rule_get_src_ip(const struct zebra_dplane_ctx *ctx)
{
@@ -2001,10 +2038,19 @@ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
break;
}
- /* Need to copy flags too */
+ /* Need to copy flags and backup info too */
new_nhlfe->flags = nhlfe->flags;
new_nhlfe->nexthop->flags = nhlfe->nexthop->flags;
+ if (CHECK_FLAG(new_nhlfe->nexthop->flags,
+ NEXTHOP_FLAG_HAS_BACKUP)) {
+ new_nhlfe->nexthop->backup_num =
+ nhlfe->nexthop->backup_num;
+ memcpy(new_nhlfe->nexthop->backup_idx,
+ nhlfe->nexthop->backup_idx,
+ new_nhlfe->nexthop->backup_num);
+ }
+
if (nhlfe == lsp->best_nhlfe)
ctx->u.lsp.best_nhlfe = new_nhlfe;
}
@@ -2104,8 +2150,15 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
if (re) {
nhg = rib_get_fib_nhg(re);
- copy_nexthops(&(ctx->u.pw.nhg.nexthop),
- nhg->nexthop, NULL);
+ if (nhg && nhg->nexthop)
+ copy_nexthops(&(ctx->u.pw.nhg.nexthop),
+ nhg->nexthop, NULL);
+
+ /* Include any installed backup nexthops */
+ nhg = rib_get_fib_backup_nhg(re);
+ if (nhg && nhg->nexthop)
+ copy_nexthops(&(ctx->u.pw.nhg.nexthop),
+ nhg->nexthop, NULL);
}
route_unlock_node(rn);
}
@@ -2129,6 +2182,7 @@ 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;
prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip);
prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip);
}
@@ -2458,9 +2512,11 @@ dplane_route_notif_update(struct route_node *rn,
enum dplane_op_e op,
struct zebra_dplane_ctx *ctx)
{
- enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE;
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ int ret = EINVAL;
struct zebra_dplane_ctx *new_ctx = NULL;
struct nexthop *nexthop;
+ struct nexthop_group *nhg;
if (rn == NULL || re == NULL)
goto done;
@@ -2482,8 +2538,17 @@ dplane_route_notif_update(struct route_node *rn,
nexthops_free(new_ctx->u.rinfo.zd_ng.nexthop);
new_ctx->u.rinfo.zd_ng.nexthop = NULL;
- copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop),
- (rib_get_fib_nhg(re))->nexthop, NULL);
+ nhg = rib_get_fib_nhg(re);
+ if (nhg && nhg->nexthop)
+ copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop),
+ nhg->nexthop, NULL);
+
+ /* Check for installed backup nexthops also */
+ nhg = rib_get_fib_backup_nhg(re);
+ if (nhg && nhg->nexthop) {
+ copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop),
+ nhg->nexthop, NULL);
+ }
for (ALL_NEXTHOPS(new_ctx->u.rinfo.zd_ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
@@ -2494,12 +2559,15 @@ dplane_route_notif_update(struct route_node *rn,
dplane_ctx_set_notif_provider(new_ctx,
dplane_ctx_get_notif_provider(ctx));
- dplane_update_enqueue(new_ctx);
-
- ret = ZEBRA_DPLANE_REQUEST_QUEUED;
+ ret = dplane_update_enqueue(new_ctx);
done:
- return ret;
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else if (new_ctx)
+ dplane_ctx_free(&new_ctx);
+
+ return result;
}
/*
@@ -2583,6 +2651,8 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp,
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;
/* Obtain context block */
ctx = dplane_ctx_alloc();
@@ -2591,10 +2661,27 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp,
goto done;
}
+ /* Copy info from zebra LSP */
ret = dplane_ctx_lsp_init(ctx, op, lsp);
if (ret != AOK)
goto done;
+ /* Add any installed backup nhlfes */
+ head = &(ctx->u.lsp.backup_nhlfe_list);
+ frr_each(nhlfe_list, head, nhlfe) {
+
+ if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
+ CHECK_FLAG(nhlfe->nexthop->flags, NEXTHOP_FLAG_FIB)) {
+ new_nhlfe = zebra_mpls_lsp_add_nh(&(ctx->u.lsp),
+ nhlfe->type,
+ nhlfe->nexthop);
+
+ /* Need to copy flags too */
+ new_nhlfe->flags = nhlfe->flags;
+ new_nhlfe->nexthop->flags = nhlfe->nexthop->flags;
+ }
+ }
+
/* Capture info about the source of the notification */
dplane_ctx_set_notif_provider(
ctx,
@@ -2830,35 +2917,75 @@ static enum zebra_dplane_result intf_addr_update_internal(
/*
* Enqueue vxlan/evpn mac add (or update).
*/
-enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
+enum zebra_dplane_result dplane_rem_mac_add(const struct interface *ifp,
const struct interface *bridge_ifp,
vlanid_t vid,
const struct ethaddr *mac,
struct in_addr vtep_ip,
- bool sticky)
+ bool sticky,
+ uint32_t nhg_id,
+ bool was_static)
{
enum zebra_dplane_result result;
+ uint32_t update_flags = 0;
+
+ update_flags |= DPLANE_MAC_REMOTE;
+ if (was_static)
+ update_flags |= DPLANE_MAC_WAS_STATIC;
/* Use common helper api */
result = mac_update_common(DPLANE_OP_MAC_INSTALL, ifp, bridge_ifp,
- vid, mac, vtep_ip, sticky);
+ vid, mac, vtep_ip, sticky, nhg_id, update_flags);
return result;
}
/*
* Enqueue vxlan/evpn mac delete.
*/
-enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
+enum zebra_dplane_result dplane_rem_mac_del(const struct interface *ifp,
const struct interface *bridge_ifp,
vlanid_t vid,
const struct ethaddr *mac,
struct in_addr vtep_ip)
{
enum zebra_dplane_result result;
+ uint32_t update_flags = 0;
+
+ update_flags |= DPLANE_MAC_REMOTE;
/* Use common helper api */
result = mac_update_common(DPLANE_OP_MAC_DELETE, ifp, bridge_ifp,
- vid, mac, vtep_ip, false);
+ vid, mac, vtep_ip, false, 0, update_flags);
+ return result;
+}
+
+/*
+ * Enqueue local mac add (or update).
+ */
+enum zebra_dplane_result dplane_local_mac_add(const struct interface *ifp,
+ const struct interface *bridge_ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ bool sticky,
+ uint32_t set_static,
+ uint32_t set_inactive)
+{
+ enum zebra_dplane_result result;
+ uint32_t update_flags = 0;
+ struct in_addr vtep_ip;
+
+ if (set_static)
+ update_flags |= DPLANE_MAC_SET_STATIC;
+
+ if (set_inactive)
+ update_flags |= DPLANE_MAC_SET_INACTIVE;
+
+ vtep_ip.s_addr = 0;
+
+ /* Use common helper api */
+ result = mac_update_common(DPLANE_OP_MAC_INSTALL, ifp, bridge_ifp,
+ vid, mac, vtep_ip, sticky, 0,
+ update_flags);
return result;
}
@@ -2872,7 +2999,9 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx,
vlanid_t vid,
const struct ethaddr *mac,
struct in_addr vtep_ip,
- bool sticky)
+ bool sticky,
+ uint32_t nhg_id,
+ uint32_t update_flags)
{
struct zebra_ns *zns;
@@ -2893,6 +3022,8 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx,
ctx->u.macinfo.mac = *mac;
ctx->u.macinfo.vid = vid;
ctx->u.macinfo.is_sticky = sticky;
+ ctx->u.macinfo.nhg_id = nhg_id;
+ ctx->u.macinfo.update_flags = update_flags;
}
/*
@@ -2905,7 +3036,9 @@ mac_update_common(enum dplane_op_e op,
vlanid_t vid,
const struct ethaddr *mac,
struct in_addr vtep_ip,
- bool sticky)
+ bool sticky,
+ uint32_t nhg_id,
+ uint32_t update_flags)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
int ret;
@@ -2925,7 +3058,8 @@ mac_update_common(enum dplane_op_e op,
ctx->zd_op = op;
/* Common init for the ctx */
- dplane_mac_init(ctx, ifp, br_ifp, vid, mac, vtep_ip, sticky);
+ dplane_mac_init(ctx, ifp, br_ifp, vid, mac, vtep_ip, sticky,
+ nhg_id, update_flags);
/* Enqueue for processing on the dplane pthread */
ret = dplane_update_enqueue(ctx);
@@ -2949,15 +3083,56 @@ mac_update_common(enum dplane_op_e op,
/*
* Enqueue evpn neighbor add for the dataplane.
*/
-enum zebra_dplane_result dplane_neigh_add(const struct interface *ifp,
+enum zebra_dplane_result dplane_rem_neigh_add(const struct interface *ifp,
+ const struct ipaddr *ip,
+ const struct ethaddr *mac,
+ uint32_t flags, bool was_static)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ uint32_t update_flags = 0;
+
+ update_flags |= DPLANE_NEIGH_REMOTE;
+
+ if (was_static)
+ update_flags |= DPLANE_NEIGH_WAS_STATIC;
+
+ result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL,
+ ifp, mac, ip, flags, DPLANE_NUD_NOARP,
+ update_flags);
+
+ return result;
+}
+
+/*
+ * Enqueue local neighbor add for the dataplane.
+ */
+enum zebra_dplane_result dplane_local_neigh_add(const struct interface *ifp,
const struct ipaddr *ip,
const struct ethaddr *mac,
- uint32_t flags)
+ bool set_router, bool set_static,
+ bool set_inactive)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ uint32_t update_flags = 0;
+ uint32_t ntf = 0;
+ uint16_t state;
+
+ if (set_static)
+ update_flags |= DPLANE_NEIGH_SET_STATIC;
+
+ if (set_inactive) {
+ update_flags |= DPLANE_NEIGH_SET_INACTIVE;
+ state = DPLANE_NUD_STALE;
+ } else {
+ state = DPLANE_NUD_REACHABLE;
+ }
+
+ if (set_router)
+ ntf |= DPLANE_NTF_ROUTER;
result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL,
- ifp, mac, ip, flags, DPLANE_NUD_NOARP);
+ ifp, mac, ip, ntf,
+ state, update_flags);
return result;
}
@@ -2965,14 +3140,18 @@ enum zebra_dplane_result dplane_neigh_add(const struct interface *ifp,
/*
* Enqueue evpn neighbor update for the dataplane.
*/
-enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp,
+enum zebra_dplane_result dplane_rem_neigh_update(const struct interface *ifp,
const struct ipaddr *ip,
const struct ethaddr *mac)
{
enum zebra_dplane_result result;
+ uint32_t update_flags = 0;
+
+ update_flags |= DPLANE_NEIGH_REMOTE;
result = neigh_update_internal(DPLANE_OP_NEIGH_UPDATE,
- ifp, mac, ip, 0, DPLANE_NUD_PROBE);
+ ifp, mac, ip, 0, DPLANE_NUD_PROBE,
+ update_flags);
return result;
}
@@ -2980,13 +3159,16 @@ enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp,
/*
* Enqueue evpn neighbor delete for the dataplane.
*/
-enum zebra_dplane_result dplane_neigh_delete(const struct interface *ifp,
+enum zebra_dplane_result dplane_rem_neigh_delete(const struct interface *ifp,
const struct ipaddr *ip)
{
enum zebra_dplane_result result;
+ uint32_t update_flags = 0;
+
+ update_flags |= DPLANE_NEIGH_REMOTE;
result = neigh_update_internal(DPLANE_OP_NEIGH_DELETE,
- ifp, NULL, ip, 0, 0);
+ ifp, NULL, ip, 0, 0, update_flags);
return result;
}
@@ -3010,7 +3192,7 @@ enum zebra_dplane_result dplane_vtep_add(const struct interface *ifp,
addr.ipaddr_v4 = *ip;
result = neigh_update_internal(DPLANE_OP_VTEP_ADD,
- ifp, &mac, &addr, 0, 0);
+ ifp, &mac, &addr, 0, 0, 0);
return result;
}
@@ -3035,7 +3217,7 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
addr.ipaddr_v4 = *ip;
result = neigh_update_internal(DPLANE_OP_VTEP_DELETE,
- ifp, &mac, &addr, 0, 0);
+ ifp, &mac, &addr, 0, 0, 0);
return result;
}
@@ -3048,7 +3230,8 @@ neigh_update_internal(enum dplane_op_e op,
const struct interface *ifp,
const struct ethaddr *mac,
const struct ipaddr *ip,
- uint32_t flags, uint16_t state)
+ uint32_t flags, uint16_t state,
+ uint32_t update_flags)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
int ret;
@@ -3085,6 +3268,7 @@ neigh_update_internal(enum dplane_op_e op,
ctx->u.neigh.mac = *mac;
ctx->u.neigh.flags = flags;
ctx->u.neigh.state = state;
+ ctx->u.neigh.update_flags = update_flags;
/* Enqueue for processing on the dplane pthread */
ret = dplane_update_enqueue(ctx);
@@ -4002,19 +4186,19 @@ bool dplane_is_in_shutdown(void)
*/
void zebra_dplane_pre_finish(void)
{
- struct zebra_dplane_provider *dp;
+ struct zebra_dplane_provider *prov;
if (IS_ZEBRA_DEBUG_DPLANE)
- zlog_debug("Zebra dataplane pre-fini called");
+ zlog_debug("Zebra dataplane pre-finish called");
zdplane_info.dg_is_shutdown = true;
/* Notify provider(s) of pending shutdown. */
- TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) {
- if (dp->dp_fini == NULL)
+ TAILQ_FOREACH(prov, &zdplane_info.dg_providers_q, dp_prov_link) {
+ if (prov->dp_fini == NULL)
continue;
- dp->dp_fini(dp, true);
+ prov->dp_fini(prov, true /* early */);
}
}
@@ -4336,7 +4520,10 @@ void zebra_dplane_shutdown(void)
zdplane_info.dg_pthread = NULL;
zdplane_info.dg_master = NULL;
- /* Notify provider(s) of final shutdown. */
+ /* Notify provider(s) of final shutdown.
+ * Note that this call is in the main pthread, so providers must
+ * be prepared for that.
+ */
TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) {
if (dp->dp_fini == NULL)
continue;