Commit 80cd22c3 authored by Paul Blakey's avatar Paul Blakey Committed by Jakub Kicinski
Browse files

net/sched: cls_api: Support hardware miss to tc action



For drivers to support partial offload of a filter's action list,
add support for action miss to specify an action instance to
continue from in sw.

CT action in particular can't be fully offloaded, as new connections
need to be handled in software. This imposes other limitations on
the actions that can be offloaded together with the CT action, such
as packet modifications.

Assign each action on a filter's action list a unique miss_cookie
which drivers can then use to fill action_miss part of the tc skb
extension. On getting back this miss_cookie, find the action
instance with relevant cookie and continue classifying from there.

Signed-off-by: default avatarPaul Blakey <paulb@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Reviewed-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent db4b4902
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -319,12 +319,16 @@ struct nf_bridge_info {
 * and read by ovs to recirc_id.
 */
struct tc_skb_ext {
	union {
		u64 act_miss_cookie;
		__u32 chain;
	};
	__u16 mru;
	__u16 zone;
	u8 post_ct:1;
	u8 post_ct_snat:1;
	u8 post_ct_dnat:1;
	u8 act_miss:1; /* Set if act_miss_cookie is used */
};
#endif

+1 −0
Original line number Diff line number Diff line
@@ -229,6 +229,7 @@ struct flow_action_entry {
	enum flow_action_id		id;
	u32				hw_index;
	unsigned long			cookie;
	u64				miss_cookie;
	enum flow_action_hw_stats	hw_stats;
	action_destr			destructor;
	void				*destructor_priv;
+20 −14
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
void tcf_block_put(struct tcf_block *block);
void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
		       struct tcf_block_ext_info *ei);
int tcf_exts_init_ex(struct tcf_exts *exts, struct net *net, int action,
		     int police, struct tcf_proto *tp, u32 handle, bool used_action_miss);

static inline bool tcf_block_shared(struct tcf_block *block)
{
@@ -229,6 +231,7 @@ struct tcf_exts {
	struct tc_action **actions;
	struct net	*net;
	netns_tracker	ns_tracker;
	struct tcf_exts_miss_cookie_node *miss_cookie_node;
#endif
	/* Map to export classifier specific extension TLV types to the
	 * generic extensions API. Unsupported extensions must be set to 0.
@@ -240,21 +243,11 @@ struct tcf_exts {
static inline int tcf_exts_init(struct tcf_exts *exts, struct net *net,
				int action, int police)
{
#ifdef CONFIG_NET_CLS_ACT
	exts->type = 0;
	exts->nr_actions = 0;
	/* Note: we do not own yet a reference on net.
	 * This reference might be taken later from tcf_exts_get_net().
	 */
	exts->net = net;
	exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
				GFP_KERNEL);
	if (!exts->actions)
		return -ENOMEM;
#ifdef CONFIG_NET_CLS
	return tcf_exts_init_ex(exts, net, action, police, NULL, 0, false);
#else
	return -EOPNOTSUPP;
#endif
	exts->action = action;
	exts->police = police;
	return 0;
}

/* Return false if the netns is being destroyed in cleanup_net(). Callers
@@ -360,6 +353,18 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
	return TC_ACT_OK;
}

static inline int
tcf_exts_exec_ex(struct sk_buff *skb, struct tcf_exts *exts, int act_index,
		 struct tcf_result *res)
{
#ifdef CONFIG_NET_CLS_ACT
	return tcf_action_exec(skb, exts->actions + act_index,
			       exts->nr_actions - act_index, res);
#else
	return TC_ACT_OK;
#endif
}

int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
		      struct nlattr **tb, struct nlattr *rate_tlv,
		      struct tcf_exts *exts, u32 flags,
@@ -584,6 +589,7 @@ int tc_setup_offload_action(struct flow_action *flow_action,
void tc_cleanup_offload_action(struct flow_action *flow_action);
int tc_setup_action(struct flow_action *flow_action,
		    struct tc_action *actions[],
		    u32 miss_cookie_base,
		    struct netlink_ext_ack *extack);

int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
+2 −0
Original line number Diff line number Diff line
@@ -369,6 +369,8 @@ struct tcf_proto_ops {
						struct nlattr **tca,
						struct netlink_ext_ack *extack);
	void			(*tmplt_destroy)(void *tmplt_priv);
	struct tcf_exts *	(*get_exts)(const struct tcf_proto *tp,
					    u32 handle);

	/* rtnetlink specific */
	int			(*dump)(struct net*, struct tcf_proto*, void *,
+2 −1
Original line number Diff line number Diff line
@@ -1041,7 +1041,8 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
	if (tc_skb_ext_tc_enabled()) {
		tc_ext = skb_ext_find(skb, TC_SKB_EXT);
		key->recirc_id = tc_ext ? tc_ext->chain : 0;
		key->recirc_id = tc_ext && !tc_ext->act_miss ?
				 tc_ext->chain : 0;
		OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0;
		post_ct = tc_ext ? tc_ext->post_ct : false;
		post_ct_snat = post_ct ? tc_ext->post_ct_snat : false;
Loading