diff options
Diffstat (limited to 'zebra/zebra_dplane.c')
| -rw-r--r-- | zebra/zebra_dplane.c | 259 |
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; |
