forked from mirrors/linux
		
	net_sched: optimize tcf_match_indev()
tcf_match_indev() is called in fast path, it is not wise to search for a netdev by ifindex and then compare by its name, just compare the ifindex. Also, dev->name could be changed by user-space, therefore the match would be always fail, but dev->ifindex could be consistent. BTW, this will also save some bytes from the core struct of u32. Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									832d1d5bfa
								
							
						
					
					
						commit
						2519a602c2
					
				
					 3 changed files with 41 additions and 31 deletions
				
			
		| 
						 | 
				
			
			@ -338,27 +338,27 @@ static inline int tcf_valid_offset(const struct sk_buff *skb,
 | 
			
		|||
#include <net/net_namespace.h>
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
tcf_change_indev(struct tcf_proto *tp, char *indev, struct nlattr *indev_tlv)
 | 
			
		||||
{
 | 
			
		||||
	if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
tcf_match_indev(struct sk_buff *skb, char *indev)
 | 
			
		||||
tcf_change_indev(struct net *net, struct nlattr *indev_tlv)
 | 
			
		||||
{
 | 
			
		||||
	char indev[IFNAMSIZ];
 | 
			
		||||
	struct net_device *dev;
 | 
			
		||||
 | 
			
		||||
	if (indev[0]) {
 | 
			
		||||
		if  (!skb->skb_iif)
 | 
			
		||||
			return 0;
 | 
			
		||||
		dev = __dev_get_by_index(dev_net(skb->dev), skb->skb_iif);
 | 
			
		||||
		if (!dev || strcmp(indev, dev->name))
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	dev = __dev_get_by_name(net, indev);
 | 
			
		||||
	if (!dev)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	return dev->ifindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
static inline bool
 | 
			
		||||
tcf_match_indev(struct sk_buff *skb, int ifindex)
 | 
			
		||||
{
 | 
			
		||||
	if (!ifindex)
 | 
			
		||||
		return true;
 | 
			
		||||
	if  (!skb->skb_iif)
 | 
			
		||||
		return false;
 | 
			
		||||
	return ifindex == skb->skb_iif;
 | 
			
		||||
}
 | 
			
		||||
#endif /* CONFIG_NET_CLS_IND */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ struct fw_filter {
 | 
			
		|||
	u32			id;
 | 
			
		||||
	struct tcf_result	res;
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
	char			indev[IFNAMSIZ];
 | 
			
		||||
	int			ifindex;
 | 
			
		||||
#endif /* CONFIG_NET_CLS_IND */
 | 
			
		||||
	struct tcf_exts		exts;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +86,7 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 | 
			
		|||
			if (f->id == id) {
 | 
			
		||||
				*res = f->res;
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
				if (!tcf_match_indev(skb, f->indev))
 | 
			
		||||
				if (!tcf_match_indev(skb, f->ifindex))
 | 
			
		||||
					continue;
 | 
			
		||||
#endif /* CONFIG_NET_CLS_IND */
 | 
			
		||||
				r = tcf_exts_exec(skb, &f->exts, res);
 | 
			
		||||
| 
						 | 
				
			
			@ -207,9 +207,11 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
 | 
			
		|||
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
	if (tb[TCA_FW_INDEV]) {
 | 
			
		||||
		err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV]);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
		int ret;
 | 
			
		||||
		ret = tcf_change_indev(net, tb[TCA_FW_INDEV]);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		f->ifindex = ret;
 | 
			
		||||
	}
 | 
			
		||||
#endif /* CONFIG_NET_CLS_IND */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -348,9 +350,12 @@ static int fw_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
 | 
			
		|||
	    nla_put_u32(skb, TCA_FW_CLASSID, f->res.classid))
 | 
			
		||||
		goto nla_put_failure;
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
	if (strlen(f->indev) &&
 | 
			
		||||
	    nla_put_string(skb, TCA_FW_INDEV, f->indev))
 | 
			
		||||
	if (f->ifindex) {
 | 
			
		||||
		struct net_device *dev;
 | 
			
		||||
		dev = __dev_get_by_index(net, f->ifindex);
 | 
			
		||||
		if (dev && nla_put_string(skb, TCA_FW_INDEV, dev->name))
 | 
			
		||||
			goto nla_put_failure;
 | 
			
		||||
	}
 | 
			
		||||
#endif /* CONFIG_NET_CLS_IND */
 | 
			
		||||
	if (head->mask != 0xFFFFFFFF &&
 | 
			
		||||
	    nla_put_u32(skb, TCA_FW_MASK, head->mask))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ struct tc_u_knode {
 | 
			
		|||
	struct tc_u_hnode	*ht_up;
 | 
			
		||||
	struct tcf_exts		exts;
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
	char                     indev[IFNAMSIZ];
 | 
			
		||||
	int			ifindex;
 | 
			
		||||
#endif
 | 
			
		||||
	u8			fshift;
 | 
			
		||||
	struct tcf_result	res;
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +152,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct
 | 
			
		|||
 | 
			
		||||
				*res = n->res;
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
				if (!tcf_match_indev(skb, n->indev)) {
 | 
			
		||||
				if (!tcf_match_indev(skb, n->ifindex)) {
 | 
			
		||||
					n = n->next;
 | 
			
		||||
					goto next_knode;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -527,9 +527,11 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
 | 
			
		|||
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
	if (tb[TCA_U32_INDEV]) {
 | 
			
		||||
		err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV]);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
		int ret;
 | 
			
		||||
		ret = tcf_change_indev(net, tb[TCA_U32_INDEV]);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		n->ifindex = ret;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	tcf_exts_change(tp, &n->exts, &e);
 | 
			
		||||
| 
						 | 
				
			
			@ -760,9 +762,12 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
 | 
			
		|||
			goto nla_put_failure;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_NET_CLS_IND
 | 
			
		||||
		if (strlen(n->indev) &&
 | 
			
		||||
		    nla_put_string(skb, TCA_U32_INDEV, n->indev))
 | 
			
		||||
		if (n->ifindex) {
 | 
			
		||||
			struct net_device *dev;
 | 
			
		||||
			dev = __dev_get_by_index(net, n->ifindex);
 | 
			
		||||
			if (dev && nla_put_string(skb, TCA_U32_INDEV, dev->name))
 | 
			
		||||
				goto nla_put_failure;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_CLS_U32_PERF
 | 
			
		||||
		if (nla_put(skb, TCA_U32_PCNT,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue