diff options
Diffstat (limited to 'zebra/zebra_dplane.c')
| -rw-r--r-- | zebra/zebra_dplane.c | 656 |
1 files changed, 517 insertions, 139 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 6a691a222f..84dae7f2d6 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -37,6 +37,7 @@ #include "zebra/debug.h" #include "zebra/zebra_pbr.h" #include "zebra/zebra_neigh.h" +#include "zebra/zebra_tc.h" #include "printfrr.h" /* Memory types */ @@ -134,6 +135,8 @@ struct dplane_route_info { uint32_t zd_mtu; uint32_t zd_nexthop_mtu; + uint32_t zd_flags; + /* Nexthop hash entry info */ struct dplane_nexthop_info nhe; @@ -313,23 +316,36 @@ struct dplane_netconf_info { enum dplane_netconf_status_e linkdown_val; }; -/* - * Traffic control contexts for the dplane - */ -struct dplane_tc_info { - /* Rate spec (unit: Bytes/s) */ +struct dplane_tc_qdisc_info { + enum tc_qdisc_kind kind; + const char *kind_str; +}; + +struct dplane_tc_class_info { + uint32_t handle; + enum tc_qdisc_kind kind; + const char *kind_str; uint64_t rate; uint64_t ceil; +}; - /* TODO: custom burst */ - - /* Filter components for "tfilter" */ +struct dplane_tc_filter_info { + uint32_t handle; + uint16_t priority; + enum tc_filter_kind kind; + const char *kind_str; uint32_t filter_bm; + uint16_t eth_proto; + uint8_t ip_proto; struct prefix src_ip; struct prefix dst_ip; - uint8_t ip_proto; - - /* TODO: more filter components */ + uint16_t src_port_min; + uint16_t src_port_max; + uint16_t dst_port_min; + uint16_t dst_port_max; + uint8_t dsfield; + uint8_t dsfield_mask; + uint32_t classid; }; /* @@ -381,7 +397,9 @@ struct zebra_dplane_ctx { struct dplane_mac_info macinfo; struct dplane_neigh_info neigh; struct dplane_rule_info rule; - struct dplane_tc_info tc; + struct dplane_tc_qdisc_info tc_qdisc; + struct dplane_tc_class_info tc_class; + struct dplane_tc_filter_info tc_filter; struct zebra_pbr_iptable iptable; struct zebra_pbr_ipset ipset; struct { @@ -800,9 +818,14 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) case DPLANE_OP_INTF_INSTALL: case DPLANE_OP_INTF_UPDATE: case DPLANE_OP_INTF_DELETE: - case DPLANE_OP_TC_INSTALL: - case DPLANE_OP_TC_UPDATE: - case DPLANE_OP_TC_DELETE: + case DPLANE_OP_TC_QDISC_INSTALL: + case DPLANE_OP_TC_QDISC_UNINSTALL: + case DPLANE_OP_TC_CLASS_ADD: + case DPLANE_OP_TC_CLASS_DELETE: + case DPLANE_OP_TC_CLASS_UPDATE: + case DPLANE_OP_TC_FILTER_ADD: + case DPLANE_OP_TC_FILTER_DELETE: + case DPLANE_OP_TC_FILTER_UPDATE: break; case DPLANE_OP_IPSET_ENTRY_ADD: @@ -812,20 +835,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) break; case DPLANE_OP_IPTABLE_ADD: case DPLANE_OP_IPTABLE_DELETE: - if (ctx->u.iptable.interface_name_list) { - struct listnode *node, *nnode; - char *ifname; - - for (ALL_LIST_ELEMENTS( - ctx->u.iptable.interface_name_list, node, - nnode, ifname)) { - LISTNODE_DETACH( - ctx->u.iptable.interface_name_list, - node); - XFREE(MTYPE_DP_NETFILTER, ifname); - } + if (ctx->u.iptable.interface_name_list) list_delete(&ctx->u.iptable.interface_name_list); - } break; case DPLANE_OP_GRE_SET: case DPLANE_OP_INTF_NETCONFIG: @@ -1127,14 +1138,29 @@ const char *dplane_op2str(enum dplane_op_e op) ret = "INTF_DELETE"; break; - case DPLANE_OP_TC_INSTALL: - ret = "TC_INSTALL"; + case DPLANE_OP_TC_QDISC_INSTALL: + ret = "TC_QDISC_INSTALL"; + break; + case DPLANE_OP_TC_QDISC_UNINSTALL: + ret = "TC_QDISC_UNINSTALL"; + break; + case DPLANE_OP_TC_CLASS_ADD: + ret = "TC_CLASS_ADD"; + break; + case DPLANE_OP_TC_CLASS_DELETE: + ret = "TC_CLASS_DELETE"; + break; + case DPLANE_OP_TC_CLASS_UPDATE: + ret = "TC_CLASS_UPDATE"; break; - case DPLANE_OP_TC_UPDATE: - ret = "TC_UPDATE"; + case DPLANE_OP_TC_FILTER_ADD: + ret = "TC_FILTER_ADD"; break; - case DPLANE_OP_TC_DELETE: - ret = "TC_DELETE"; + case DPLANE_OP_TC_FILTER_DELETE: + ret = "TC_FILTER_DELETE"; + break; + case DPLANE_OP_TC_FILTER_UPDATE: + ret = "TC__FILTER_UPDATE"; break; } @@ -1406,6 +1432,20 @@ uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx) return ctx->u.rinfo.zd_old_instance; } +uint32_t dplane_ctx_get_flags(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.rinfo.zd_flags; +} + +void dplane_ctx_set_flags(struct zebra_dplane_ctx *ctx, uint32_t flags) +{ + DPLANE_CTX_VALID(ctx); + + ctx->u.rinfo.zd_flags = flags; +} + uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1455,48 +1495,175 @@ uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx) return ctx->u.rinfo.zd_old_distance; } -uint64_t dplane_ctx_tc_get_rate(const struct zebra_dplane_ctx *ctx) +int dplane_ctx_tc_qdisc_get_kind(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_qdisc.kind; +} + +const char *dplane_ctx_tc_qdisc_get_kind_str(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->u.tc.rate; + return ctx->u.tc_qdisc.kind_str; } -uint64_t dplane_ctx_tc_get_ceil(const struct zebra_dplane_ctx *ctx) +uint32_t dplane_ctx_tc_class_get_handle(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->u.tc.ceil; + return ctx->u.tc_class.handle; } -uint32_t dplane_ctx_tc_get_filter_bm(const struct zebra_dplane_ctx *ctx) +int dplane_ctx_tc_class_get_kind(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->u.tc.filter_bm; + return ctx->u.tc_class.kind; +} + +const char *dplane_ctx_tc_class_get_kind_str(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_class.kind_str; +} + +uint64_t dplane_ctx_tc_class_get_rate(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_class.rate; +} + +uint64_t dplane_ctx_tc_class_get_ceil(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_class.ceil; +} + +int dplane_ctx_tc_filter_get_kind(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.kind; +} + +const char * +dplane_ctx_tc_filter_get_kind_str(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.kind_str; +} + +uint32_t dplane_ctx_tc_filter_get_priority(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.priority; +} + +uint32_t dplane_ctx_tc_filter_get_handle(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.handle; +} + +uint16_t dplane_ctx_tc_filter_get_eth_proto(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.eth_proto; +} + +uint32_t dplane_ctx_tc_filter_get_filter_bm(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.filter_bm; } const struct prefix * -dplane_ctx_tc_get_src_ip(const struct zebra_dplane_ctx *ctx) +dplane_ctx_tc_filter_get_src_ip(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return &ctx->u.tc_filter.src_ip; +} + +uint16_t +dplane_ctx_tc_filter_get_src_port_min(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.src_port_min; +} + + +uint16_t +dplane_ctx_tc_filter_get_src_port_max(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return &(ctx->u.tc.src_ip); + return ctx->u.tc_filter.src_port_max; } const struct prefix * -dplane_ctx_tc_get_dst_ip(const struct zebra_dplane_ctx *ctx) +dplane_ctx_tc_filter_get_dst_ip(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return &ctx->u.tc_filter.dst_ip; +} + +uint16_t +dplane_ctx_tc_filter_get_dst_port_min(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.dst_port_min; +} + + +uint16_t +dplane_ctx_tc_filter_get_dst_port_max(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.dst_port_max; +} + +uint8_t dplane_ctx_tc_filter_get_ip_proto(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.ip_proto; +} + +uint8_t dplane_ctx_tc_filter_get_dsfield(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.tc_filter.dsfield; +} + +uint8_t +dplane_ctx_tc_filter_get_dsfield_mask(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return &(ctx->u.tc.dst_ip); + return ctx->u.tc_filter.dsfield_mask; } -uint8_t dplane_ctx_tc_get_ip_proto(const struct zebra_dplane_ctx *ctx) +uint32_t dplane_ctx_tc_filter_get_classid(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->u.tc.ip_proto; + return ctx->u.tc_filter.classid; } /* @@ -2615,25 +2782,16 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx, return AOK; } -/* - * Initialize a context block for a route update from zebra data structs. - */ -int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, - struct route_node *rn, struct route_entry *re) +int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx, + enum dplane_op_e op, struct route_entry *re, + const struct prefix *p, + const struct prefix_ipv6 *src_p, afi_t afi, + safi_t safi) { int ret = EINVAL; - const struct route_table *table = NULL; - const struct rib_table_info *info; - const struct prefix *p, *src_p; - struct zebra_ns *zns; - struct zebra_vrf *zvrf; - struct nexthop *nexthop; - struct zebra_l3vni *zl3vni; - const struct interface *ifp; - struct dplane_intf_extra *if_extra; - if (!ctx || !rn || !re) - goto done; + if (!ctx || !re) + return ret; TAILQ_INIT(&ctx->u.rinfo.intf_extra_q); @@ -2643,9 +2801,6 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ctx->u.rinfo.zd_type = re->type; ctx->u.rinfo.zd_old_type = re->type; - /* Prefixes: dest, and optional source */ - srcdest_rnode_prefixes(rn, &p, &src_p); - prefix_copy(&(ctx->u.rinfo.zd_dest), p); if (src_p) @@ -2655,6 +2810,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ctx->zd_table_id = re->table; + ctx->u.rinfo.zd_flags = re->flags; ctx->u.rinfo.zd_metric = re->metric; ctx->u.rinfo.zd_old_metric = re->metric; ctx->zd_vrf_id = re->vrf_id; @@ -2665,11 +2821,46 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ctx->u.rinfo.zd_old_tag = re->tag; ctx->u.rinfo.zd_distance = re->distance; + ctx->u.rinfo.zd_afi = afi; + ctx->u.rinfo.zd_safi = safi; + + return AOK; +} + +/* + * Initialize a context block for a route update from zebra data structs. + */ +int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + struct route_node *rn, struct route_entry *re) +{ + int ret = EINVAL; + const struct route_table *table = NULL; + const struct rib_table_info *info; + const struct prefix *p; + const struct prefix_ipv6 *src_p; + struct zebra_ns *zns; + struct zebra_vrf *zvrf; + struct nexthop *nexthop; + struct zebra_l3vni *zl3vni; + const struct interface *ifp; + struct dplane_intf_extra *if_extra; + + if (!ctx || !rn || !re) + return ret; + + /* + * Let's grab the data from the route_node + * so that we can call a helper function + */ + + /* Prefixes: dest, and optional source */ + srcdest_rnode_prefixes(rn, &p, (const struct prefix **)&src_p); table = srcdest_rnode_table(rn); info = table->info; - ctx->u.rinfo.zd_afi = info->afi; - ctx->u.rinfo.zd_safi = info->safi; + if (dplane_ctx_route_init_basic(ctx, op, re, p, src_p, info->afi, + info->safi) != AOK) + return ret; /* Copy nexthops; recursive info is included too */ copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), @@ -2724,8 +2915,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, /* Don't need some info when capturing a system notification */ if (op == DPLANE_OP_SYS_ROUTE_ADD || op == DPLANE_OP_SYS_ROUTE_DELETE) { - ret = AOK; - goto done; + return AOK; } /* Extract ns info - can't use pointers to 'core' structs */ @@ -2746,14 +2936,12 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, * If its a delete we only use the prefix anyway, so this only * matters for INSTALL/UPDATE. */ - if (zebra_nhg_kernel_nexthops_enabled() - && (((op == DPLANE_OP_ROUTE_INSTALL) - || (op == DPLANE_OP_ROUTE_UPDATE)) - && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) - && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED))) { - ret = ENOENT; - goto done; - } + if (zebra_nhg_kernel_nexthops_enabled() && + (((op == DPLANE_OP_ROUTE_INSTALL) || + (op == DPLANE_OP_ROUTE_UPDATE)) && + !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) && + !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED))) + return ENOENT; re->nhe_installed_id = nhe->id; } @@ -2765,13 +2953,36 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, re->dplane_sequence = zebra_router_get_next_sequence(); ctx->zd_seq = re->dplane_sequence; + return AOK; +} + +static int dplane_ctx_tc_qdisc_init(struct zebra_dplane_ctx *ctx, + enum dplane_op_e op, + const struct zebra_tc_qdisc *qdisc) +{ + int ret = EINVAL; + + struct zebra_ns *zns = NULL; + + ctx->zd_op = op; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + ctx->zd_ifindex = qdisc->qdisc.ifindex; + ctx->u.tc_qdisc.kind = qdisc->qdisc.kind; + ctx->u.tc_qdisc.kind_str = tc_qdisc_kind2str(qdisc->qdisc.kind); + + /* TODO: init traffic control qdisc */ + zns = zebra_ns_lookup(NS_DEFAULT); + + dplane_ctx_ns_init(ctx, zns, true); + ret = AOK; -done: return ret; } -int dplane_ctx_tc_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op) +static int dplane_ctx_tc_class_init(struct zebra_dplane_ctx *ctx, + enum dplane_op_e op, + struct zebra_tc_class *class) { int ret = EINVAL; @@ -2779,8 +2990,55 @@ int dplane_ctx_tc_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op) ctx->zd_op = op; ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + ctx->zd_ifindex = class->class.ifindex; + + ctx->u.tc_class.handle = class->class.handle; + ctx->u.tc_class.kind = class->class.kind; + ctx->u.tc_class.kind_str = tc_qdisc_kind2str(class->class.kind); + ctx->u.tc_class.rate = class->class.u.htb.rate; + ctx->u.tc_class.ceil = class->class.u.htb.ceil; + + zns = zebra_ns_lookup(NS_DEFAULT); + + dplane_ctx_ns_init(ctx, zns, true); + + ret = AOK; + + return ret; +} + +static int dplane_ctx_tc_filter_init(struct zebra_dplane_ctx *ctx, + enum dplane_op_e op, + struct zebra_tc_filter *filter) +{ + int ret = EINVAL; + + struct zebra_ns *zns = NULL; + + ctx->zd_op = op; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + ctx->zd_ifindex = filter->filter.ifindex; + + ctx->u.tc_filter.eth_proto = filter->filter.protocol; + ctx->u.tc_filter.ip_proto = filter->filter.u.flower.ip_proto; + + ctx->u.tc_filter.kind = filter->filter.kind; + ctx->u.tc_filter.kind_str = tc_filter_kind2str(filter->filter.kind); + + ctx->u.tc_filter.filter_bm = filter->filter.u.flower.filter_bm; + prefix_copy(&ctx->u.tc_filter.src_ip, &filter->filter.u.flower.src_ip); + ctx->u.tc_filter.src_port_min = filter->filter.u.flower.src_port_min; + ctx->u.tc_filter.src_port_max = filter->filter.u.flower.src_port_max; + prefix_copy(&ctx->u.tc_filter.dst_ip, &filter->filter.u.flower.dst_ip); + ctx->u.tc_filter.dst_port_min = filter->filter.u.flower.dst_port_min; + ctx->u.tc_filter.dst_port_max = filter->filter.u.flower.dst_port_max; + ctx->u.tc_filter.dsfield = filter->filter.u.flower.dsfield; + ctx->u.tc_filter.dsfield_mask = filter->filter.u.flower.dsfield_mask; + ctx->u.tc_filter.classid = filter->filter.u.flower.classid; + + ctx->u.tc_filter.priority = filter->filter.priority; + ctx->u.tc_filter.handle = filter->filter.handle; - /* TODO: init traffic control qdisc */ zns = zebra_ns_lookup(NS_DEFAULT); dplane_ctx_ns_init(ctx, zns, true); @@ -2807,7 +3065,7 @@ int dplane_ctx_nexthop_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, int ret = EINVAL; if (!ctx || !nhe) - goto done; + return ret; ctx->zd_op = op; ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; @@ -2842,7 +3100,6 @@ int dplane_ctx_nexthop_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ret = AOK; -done: return ret; } @@ -2864,7 +3121,7 @@ int dplane_ctx_intf_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, bool set_pdown, unset_pdown; if (!ctx || !ifp) - goto done; + return ret; ctx->zd_op = op; ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; @@ -2909,7 +3166,6 @@ int dplane_ctx_intf_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ret = AOK; -done: return ret; } @@ -2937,10 +3193,8 @@ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, /* This may be called to create/init a dplane context, not necessarily * to copy an lsp object. */ - if (lsp == NULL) { - ret = AOK; - goto done; - } + if (lsp == NULL) + return ret; if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug("init dplane ctx %s: in-label %u ecmp# %d", @@ -2983,7 +3237,7 @@ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, } if (ret != AOK) - goto done; + return ret; /* Capture backup nhlfes/nexthops */ frr_each(nhlfe_list, &lsp->backup_nhlfe_list, nhlfe) { @@ -3004,11 +3258,6 @@ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, new_nhlfe->nexthop->flags = nhlfe->nexthop->flags; } - /* On error the ctx will be cleaned-up, so we don't need to - * deal with any allocated nhlfe or nexthop structs here. - */ -done: - return ret; } @@ -3069,11 +3318,11 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx, afi = (pw->af == AF_INET) ? AFI_IP : AFI_IP6; table = zebra_vrf_table(afi, SAFI_UNICAST, pw->vrf_id); if (table == NULL) - goto done; + return ret; rn = route_node_match(table, &p); if (rn == NULL) - goto done; + return ret; re = NULL; RNODE_FOREACH_RE(rn, re) { @@ -3141,10 +3390,7 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx, } route_unlock_node(rn); - ret = AOK; - -done: - return ret; + return AOK; } /** @@ -3240,6 +3486,11 @@ static int dplane_ctx_rule_init(struct zebra_dplane_ctx *ctx, return AOK; } +static void zebra_dplane_interface_name_list_deletion(void *data) +{ + XFREE(MTYPE_DP_NETFILTER, data); +} + /** * dplane_ctx_iptable_init() - Initialize a context block for a PBR iptable * update. @@ -3273,9 +3524,10 @@ static int dplane_ctx_iptable_init(struct zebra_dplane_ctx *ctx, ctx->zd_vrf_id = iptable->vrf_id; memcpy(&ctx->u.iptable, iptable, sizeof(struct zebra_pbr_iptable)); - ctx->u.iptable.interface_name_list = NULL; if (iptable->nb_interface > 0) { ctx->u.iptable.interface_name_list = list_new(); + ctx->u.iptable.interface_name_list->del = + zebra_dplane_interface_name_list_deletion; for (ALL_LIST_ELEMENTS_RO(iptable->interface_name_list, node, ifname)) { listnode_add(ctx->u.iptable.interface_name_list, @@ -3509,7 +3761,9 @@ dplane_route_update_internal(struct route_node *rn, return result; } -static enum zebra_dplane_result dplane_tc_update_internal(enum dplane_op_e op) +static enum zebra_dplane_result +tc_qdisc_update_internal(enum dplane_op_e op, + const struct zebra_tc_qdisc *qdisc) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; int ret; @@ -3524,7 +3778,7 @@ static enum zebra_dplane_result dplane_tc_update_internal(enum dplane_op_e op) } /* Init context with info from zebra data structs */ - ret = dplane_ctx_tc_init(ctx, op); + ret = dplane_ctx_tc_qdisc_init(ctx, op, qdisc); if (ret == AOK) ret = dplane_update_enqueue(ctx); @@ -3545,9 +3799,118 @@ done: return result; } -enum zebra_dplane_result dplane_tc_update(void) +static enum zebra_dplane_result +tc_class_update_internal(enum dplane_op_e op, struct zebra_tc_class *class) { - return dplane_tc_update_internal(DPLANE_OP_TC_UPDATE); + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + int ret; + struct zebra_dplane_ctx *ctx = NULL; + + /* Obtain context block */ + ctx = dplane_ctx_alloc(); + + if (!ctx) { + ret = ENOMEM; + goto done; + } + + /* Init context with info from zebra data structs */ + ret = dplane_ctx_tc_class_init(ctx, op, class); + + if (ret == AOK) + ret = dplane_update_enqueue(ctx); + +done: + /* Update counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1, + memory_order_relaxed); + if (ret == AOK) { + result = ZEBRA_DPLANE_REQUEST_QUEUED; + } else { + atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors, 1, + memory_order_relaxed); + if (ctx) + dplane_ctx_free(&ctx); + } + + return result; +} + +static enum zebra_dplane_result +tc_filter_update_internal(enum dplane_op_e op, struct zebra_tc_filter *filter) +{ + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + int ret; + struct zebra_dplane_ctx *ctx = NULL; + + /* Obtain context block */ + ctx = dplane_ctx_alloc(); + + if (!ctx) { + ret = ENOMEM; + goto done; + } + + /* Init context with info from zebra data structs */ + ret = dplane_ctx_tc_filter_init(ctx, op, filter); + + if (ret == AOK) + ret = dplane_update_enqueue(ctx); + +done: + /* Update counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1, + memory_order_relaxed); + if (ret == AOK) { + result = ZEBRA_DPLANE_REQUEST_QUEUED; + } else { + atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors, 1, + memory_order_relaxed); + if (ctx) + dplane_ctx_free(&ctx); + } + + return result; +} + +enum zebra_dplane_result dplane_tc_qdisc_install(struct zebra_tc_qdisc *qdisc) +{ + return tc_qdisc_update_internal(DPLANE_OP_TC_QDISC_INSTALL, qdisc); +} + +enum zebra_dplane_result dplane_tc_qdisc_uninstall(struct zebra_tc_qdisc *qdisc) +{ + return tc_qdisc_update_internal(DPLANE_OP_TC_QDISC_UNINSTALL, qdisc); +} + +enum zebra_dplane_result dplane_tc_class_add(struct zebra_tc_class *class) +{ + return tc_class_update_internal(DPLANE_OP_TC_CLASS_ADD, class); +} + +enum zebra_dplane_result dplane_tc_class_delete(struct zebra_tc_class *class) +{ + return tc_class_update_internal(DPLANE_OP_TC_CLASS_DELETE, class); +} + +enum zebra_dplane_result dplane_tc_class_update(struct zebra_tc_class *class) +{ + return tc_class_update_internal(DPLANE_OP_TC_CLASS_UPDATE, class); +} + +enum zebra_dplane_result dplane_tc_filter_add(struct zebra_tc_filter *filter) +{ + return tc_filter_update_internal(DPLANE_OP_TC_FILTER_ADD, filter); +} + +enum zebra_dplane_result dplane_tc_filter_delete(struct zebra_tc_filter *filter) +{ + return tc_filter_update_internal(DPLANE_OP_TC_FILTER_DELETE, filter); +} + +enum zebra_dplane_result dplane_tc_filter_update(struct zebra_tc_filter *filter) +{ + return tc_filter_update_internal(DPLANE_OP_TC_FILTER_UPDATE, filter); } /** @@ -3602,12 +3965,11 @@ enum zebra_dplane_result dplane_route_add(struct route_node *rn, enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; if (rn == NULL || re == NULL) - goto done; + return ret; ret = dplane_route_update_internal(rn, re, NULL, DPLANE_OP_ROUTE_INSTALL); -done: return ret; } @@ -3621,11 +3983,11 @@ enum zebra_dplane_result dplane_route_update(struct route_node *rn, enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; if (rn == NULL || re == NULL) - goto done; + return ret; ret = dplane_route_update_internal(rn, re, old_re, DPLANE_OP_ROUTE_UPDATE); -done: + return ret; } @@ -3638,12 +4000,11 @@ enum zebra_dplane_result dplane_route_delete(struct route_node *rn, enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; if (rn == NULL || re == NULL) - goto done; + return ret; ret = dplane_route_update_internal(rn, re, NULL, DPLANE_OP_ROUTE_DELETE); -done: return ret; } @@ -3656,18 +4017,16 @@ enum zebra_dplane_result dplane_sys_route_add(struct route_node *rn, enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; /* Ignore this event unless a provider plugin has requested it. */ - if (!zdplane_info.dg_sys_route_notifs) { - ret = ZEBRA_DPLANE_REQUEST_SUCCESS; - goto done; - } + if (!zdplane_info.dg_sys_route_notifs) + return ZEBRA_DPLANE_REQUEST_SUCCESS; + if (rn == NULL || re == NULL) - goto done; + return ret; ret = dplane_route_update_internal(rn, re, NULL, DPLANE_OP_SYS_ROUTE_ADD); -done: return ret; } @@ -3680,18 +4039,15 @@ enum zebra_dplane_result dplane_sys_route_del(struct route_node *rn, enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; /* Ignore this event unless a provider plugin has requested it. */ - if (!zdplane_info.dg_sys_route_notifs) { - ret = ZEBRA_DPLANE_REQUEST_SUCCESS; - goto done; - } + if (!zdplane_info.dg_sys_route_notifs) + return ZEBRA_DPLANE_REQUEST_SUCCESS; if (rn == NULL || re == NULL) - goto done; + return ret; ret = dplane_route_update_internal(rn, re, NULL, DPLANE_OP_SYS_ROUTE_DELETE); -done: return ret; } @@ -5733,10 +6089,18 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx) break; /* TODO: more detailed log */ - case DPLANE_OP_TC_INSTALL: - case DPLANE_OP_TC_UPDATE: - case DPLANE_OP_TC_DELETE: - zlog_debug("Dplane tc ifidx %u", dplane_ctx_get_ifindex(ctx)); + case DPLANE_OP_TC_QDISC_INSTALL: + case DPLANE_OP_TC_QDISC_UNINSTALL: + zlog_debug("Dplane tc qdisc ifidx %u", + dplane_ctx_get_ifindex(ctx)); + break; + case DPLANE_OP_TC_CLASS_ADD: + case DPLANE_OP_TC_CLASS_DELETE: + case DPLANE_OP_TC_CLASS_UPDATE: + break; + case DPLANE_OP_TC_FILTER_ADD: + case DPLANE_OP_TC_FILTER_DELETE: + case DPLANE_OP_TC_FILTER_UPDATE: break; } } @@ -5881,9 +6245,14 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx) 1, memory_order_relaxed); break; - case DPLANE_OP_TC_INSTALL: - case DPLANE_OP_TC_UPDATE: - case DPLANE_OP_TC_DELETE: + case DPLANE_OP_TC_QDISC_INSTALL: + case DPLANE_OP_TC_QDISC_UNINSTALL: + case DPLANE_OP_TC_CLASS_ADD: + case DPLANE_OP_TC_CLASS_DELETE: + case DPLANE_OP_TC_CLASS_UPDATE: + case DPLANE_OP_TC_FILTER_ADD: + case DPLANE_OP_TC_FILTER_DELETE: + case DPLANE_OP_TC_FILTER_UPDATE: if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors, 1, memory_order_relaxed); @@ -5933,6 +6302,20 @@ kernel_dplane_process_ipset_entry(struct zebra_dplane_provider *prov, dplane_provider_enqueue_out_ctx(prov, ctx); } +void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct route_entry *re, + struct nexthop_group *ng, int startup, + struct zebra_dplane_ctx *ctx) +{ + if (!ctx) + rib_add_multipath(afi, safi, p, src_p, re, ng, startup); + else { + dplane_ctx_route_init_basic(ctx, dplane_ctx_get_op(ctx), re, p, + src_p, afi, safi); + dplane_provider_enqueue_to_zebra(ctx); + } +} + /* * Kernel provider callback */ @@ -6109,7 +6492,7 @@ int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx, TAILQ_INIT(&work_list); if (context_cb == NULL) - goto done; + return AOK; /* Walk the pending context queue under the dplane lock. */ DPLANE_LOCK(); @@ -6133,9 +6516,7 @@ int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx, dplane_ctx_fini(&ctx); } -done: - - return 0; + return AOK; } /* Indicates zebra shutdown/exit is in progress. Some operations may be @@ -6199,10 +6580,8 @@ static bool dplane_work_pending(void) } DPLANE_UNLOCK(); - if (ctx != NULL) { - ret = true; - goto done; - } + if (ctx != NULL) + return true; while (prov) { @@ -6225,7 +6604,6 @@ static bool dplane_work_pending(void) if (ctx != NULL) ret = true; -done: return ret; } |
