diff options
Diffstat (limited to 'net/sched/cls_api.c')
| -rw-r--r-- | net/sched/cls_api.c | 87 | 
1 files changed, 40 insertions, 47 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index e3e79e9bd706..2ef8f5a6205a 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -634,6 +634,7 @@ static void tcf_block_offload_init(struct flow_block_offload *bo,  	bo->block_shared = shared;  	bo->extack = extack;  	bo->sch = sch; +	bo->cb_list_head = &flow_block->cb_list;  	INIT_LIST_HEAD(&bo->cb_list);  } @@ -1577,21 +1578,11 @@ reset:  #endif  } -int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, +int tcf_classify(struct sk_buff *skb, +		 const struct tcf_block *block, +		 const struct tcf_proto *tp,  		 struct tcf_result *res, bool compat_mode)  { -	u32 last_executed_chain = 0; - -	return __tcf_classify(skb, tp, tp, res, compat_mode, -			      &last_executed_chain); -} -EXPORT_SYMBOL(tcf_classify); - -int tcf_classify_ingress(struct sk_buff *skb, -			 const struct tcf_block *ingress_block, -			 const struct tcf_proto *tp, -			 struct tcf_result *res, bool compat_mode) -{  #if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT)  	u32 last_executed_chain = 0; @@ -1603,20 +1594,22 @@ int tcf_classify_ingress(struct sk_buff *skb,  	struct tc_skb_ext *ext;  	int ret; -	ext = skb_ext_find(skb, TC_SKB_EXT); +	if (block) { +		ext = skb_ext_find(skb, TC_SKB_EXT); -	if (ext && ext->chain) { -		struct tcf_chain *fchain; +		if (ext && ext->chain) { +			struct tcf_chain *fchain; -		fchain = tcf_chain_lookup_rcu(ingress_block, ext->chain); -		if (!fchain) -			return TC_ACT_SHOT; +			fchain = tcf_chain_lookup_rcu(block, ext->chain); +			if (!fchain) +				return TC_ACT_SHOT; -		/* Consume, so cloned/redirect skbs won't inherit ext */ -		skb_ext_del(skb, TC_SKB_EXT); +			/* Consume, so cloned/redirect skbs won't inherit ext */ +			skb_ext_del(skb, TC_SKB_EXT); -		tp = rcu_dereference_bh(fchain->filter_chain); -		last_executed_chain = fchain->index; +			tp = rcu_dereference_bh(fchain->filter_chain); +			last_executed_chain = fchain->index; +		}  	}  	ret = __tcf_classify(skb, tp, orig_tp, res, compat_mode, @@ -1635,7 +1628,7 @@ int tcf_classify_ingress(struct sk_buff *skb,  	return ret;  #endif  } -EXPORT_SYMBOL(tcf_classify_ingress); +EXPORT_SYMBOL(tcf_classify);  struct tcf_chain_info {  	struct tcf_proto __rcu **pprev; @@ -1870,13 +1863,10 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,  	}  	if (unicast) -		err = netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT); +		err = rtnl_unicast(skb, net, portid);  	else  		err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,  				     n->nlmsg_flags & NLM_F_ECHO); - -	if (err > 0) -		err = 0;  	return err;  } @@ -1909,15 +1899,13 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,  	}  	if (unicast) -		err = netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT); +		err = rtnl_unicast(skb, net, portid);  	else  		err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,  				     n->nlmsg_flags & NLM_F_ECHO);  	if (err < 0)  		NL_SET_ERR_MSG(extack, "Failed to send filter delete notification"); -	if (err > 0) -		err = 0;  	return err;  } @@ -1962,6 +1950,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,  	int err;  	int tp_created;  	bool rtnl_held = false; +	u32 flags;  	if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))  		return -EPERM; @@ -1982,6 +1971,7 @@ replay:  	tp = NULL;  	cl = 0;  	block = NULL; +	flags = 0;  	if (prio == 0) {  		/* If no priority is provided by the user, @@ -2125,9 +2115,12 @@ replay:  		goto errout;  	} +	if (!(n->nlmsg_flags & NLM_F_CREATE)) +		flags |= TCA_ACT_FLAGS_REPLACE; +	if (!rtnl_held) +		flags |= TCA_ACT_FLAGS_NO_RTNL;  	err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh, -			      n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE, -			      rtnl_held, extack); +			      flags, extack);  	if (err == 0) {  		tfilter_notify(net, skb, n, tp, block, q, parent, fh,  			       RTM_NEWTFILTER, false, rtnl_held); @@ -2711,13 +2704,11 @@ static int tc_chain_notify(struct tcf_chain *chain, struct sk_buff *oskb,  	}  	if (unicast) -		err = netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT); +		err = rtnl_unicast(skb, net, portid);  	else  		err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,  				     flags & NLM_F_ECHO); -	if (err > 0) -		err = 0;  	return err;  } @@ -2741,7 +2732,7 @@ static int tc_chain_notify_delete(const struct tcf_proto_ops *tmplt_ops,  	}  	if (unicast) -		return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT); +		return rtnl_unicast(skb, net, portid);  	return rtnetlink_send(skb, net, portid, RTNLGRP_TC, flags & NLM_F_ECHO);  } @@ -3035,8 +3026,8 @@ void tcf_exts_destroy(struct tcf_exts *exts)  EXPORT_SYMBOL(tcf_exts_destroy);  int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, -		      struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr, -		      bool rtnl_held, struct netlink_ext_ack *extack) +		      struct nlattr *rate_tlv, struct tcf_exts *exts, +		      u32 flags, struct netlink_ext_ack *extack)  {  #ifdef CONFIG_NET_CLS_ACT  	{ @@ -3047,13 +3038,15 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,  		if (exts->police && tb[exts->police]) {  			struct tc_action_ops *a_o; -			a_o = tc_action_load_ops("police", tb[exts->police], rtnl_held, extack); +			a_o = tc_action_load_ops(tb[exts->police], true, +						 !(flags & TCA_ACT_FLAGS_NO_RTNL), +						 extack);  			if (IS_ERR(a_o))  				return PTR_ERR(a_o); +			flags |= TCA_ACT_FLAGS_POLICE | TCA_ACT_FLAGS_BIND;  			act = tcf_action_init_1(net, tp, tb[exts->police], -						rate_tlv, "police", ovr, -						TCA_ACT_BIND, a_o, init_res, -						rtnl_held, extack); +						rate_tlv, a_o, init_res, flags, +						extack);  			module_put(a_o->owner);  			if (IS_ERR(act))  				return PTR_ERR(act); @@ -3065,10 +3058,10 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,  		} else if (exts->action && tb[exts->action]) {  			int err; +			flags |= TCA_ACT_FLAGS_BIND;  			err = tcf_action_init(net, tp, tb[exts->action], -					      rate_tlv, NULL, ovr, TCA_ACT_BIND, -					      exts->actions, init_res, -					      &attr_size, rtnl_held, extack); +					      rate_tlv, exts->actions, init_res, +					      &attr_size, flags, extack);  			if (err < 0)  				return err;  			exts->nr_actions = err; @@ -3832,7 +3825,7 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru  	fl = rcu_dereference_bh(qe->filter_chain); -	switch (tcf_classify(skb, fl, &cl_res, false)) { +	switch (tcf_classify(skb, NULL, fl, &cl_res, false)) {  	case TC_ACT_SHOT:  		qdisc_qstats_drop(sch);  		__qdisc_drop(skb, to_free);  |