Commit 0efd1b3a authored by John Hurley's avatar John Hurley Committed by David S. Miller
Browse files

net: sched: cls_matchall: implement offload tcf_proto_op



Add the reoffload tcf_proto_op in matchall to generate an offload message
for each filter in the given tcf_proto. Call the specified callback with
this new offload message. The function only returns an error if the
callback rejects adding a 'hardware only' rule.

Ensure matchall flags correctly report if the rule is in hw by keeping a
reference counter for the number of instances of the rule offloaded. Only
update the flag when this counter changes from or to 0.

Signed-off-by: default avatarJohn Hurley <john.hurley@netronome.com>
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 31533cba
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ struct cls_mall_head {
	struct tcf_result res;
	u32 handle;
	u32 flags;
	unsigned int in_hw_count;
	struct rcu_work rwork;
};

@@ -95,6 +96,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
		mall_destroy_hw_filter(tp, head, cookie, NULL);
		return err;
	} else if (err > 0) {
		head->in_hw_count = err;
		tcf_block_offload_inc(block, &head->flags);
	}

@@ -235,6 +237,35 @@ skip:
	arg->count++;
}

static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
			  void *cb_priv, struct netlink_ext_ack *extack)
{
	struct cls_mall_head *head = rtnl_dereference(tp->root);
	struct tc_cls_matchall_offload cls_mall = {};
	struct tcf_block *block = tp->chain->block;
	int err;

	if (tc_skip_hw(head->flags))
		return 0;

	tc_cls_common_offload_init(&cls_mall.common, tp, head->flags, extack);
	cls_mall.command = add ?
		TC_CLSMATCHALL_REPLACE : TC_CLSMATCHALL_DESTROY;
	cls_mall.exts = &head->exts;
	cls_mall.cookie = (unsigned long)head;

	err = cb(TC_SETUP_CLSMATCHALL, &cls_mall, cb_priv);
	if (err) {
		if (add && tc_skip_sw(head->flags))
			return err;
		return 0;
	}

	tc_cls_offload_cnt_update(block, &head->in_hw_count, &head->flags, add);

	return 0;
}

static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh,
		     struct sk_buff *skb, struct tcmsg *t)
{
@@ -289,6 +320,7 @@ static struct tcf_proto_ops cls_mall_ops __read_mostly = {
	.change		= mall_change,
	.delete		= mall_delete,
	.walk		= mall_walk,
	.reoffload	= mall_reoffload,
	.dump		= mall_dump,
	.bind_class	= mall_bind_class,
	.owner		= THIS_MODULE,