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.c656
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;
}