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>
 | 
					#include <net/net_namespace.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int
 | 
					static inline int
 | 
				
			||||||
tcf_change_indev(struct tcf_proto *tp, char *indev, struct nlattr *indev_tlv)
 | 
					tcf_change_indev(struct net *net, 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)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						char indev[IFNAMSIZ];
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (indev[0]) {
 | 
						if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
 | 
				
			||||||
		if  (!skb->skb_iif)
 | 
							return -EINVAL;
 | 
				
			||||||
			return 0;
 | 
						dev = __dev_get_by_name(net, indev);
 | 
				
			||||||
		dev = __dev_get_by_index(dev_net(skb->dev), skb->skb_iif);
 | 
						if (!dev)
 | 
				
			||||||
		if (!dev || strcmp(indev, dev->name))
 | 
							return -ENODEV;
 | 
				
			||||||
			return 0;
 | 
						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 */
 | 
					#endif /* CONFIG_NET_CLS_IND */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ struct fw_filter {
 | 
				
			||||||
	u32			id;
 | 
						u32			id;
 | 
				
			||||||
	struct tcf_result	res;
 | 
						struct tcf_result	res;
 | 
				
			||||||
#ifdef CONFIG_NET_CLS_IND
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
	char			indev[IFNAMSIZ];
 | 
						int			ifindex;
 | 
				
			||||||
#endif /* CONFIG_NET_CLS_IND */
 | 
					#endif /* CONFIG_NET_CLS_IND */
 | 
				
			||||||
	struct tcf_exts		exts;
 | 
						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) {
 | 
								if (f->id == id) {
 | 
				
			||||||
				*res = f->res;
 | 
									*res = f->res;
 | 
				
			||||||
#ifdef CONFIG_NET_CLS_IND
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
				if (!tcf_match_indev(skb, f->indev))
 | 
									if (!tcf_match_indev(skb, f->ifindex))
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
#endif /* CONFIG_NET_CLS_IND */
 | 
					#endif /* CONFIG_NET_CLS_IND */
 | 
				
			||||||
				r = tcf_exts_exec(skb, &f->exts, res);
 | 
									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
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
	if (tb[TCA_FW_INDEV]) {
 | 
						if (tb[TCA_FW_INDEV]) {
 | 
				
			||||||
		err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV]);
 | 
							int ret;
 | 
				
			||||||
		if (err < 0)
 | 
							ret = tcf_change_indev(net, tb[TCA_FW_INDEV]);
 | 
				
			||||||
 | 
							if (ret < 0)
 | 
				
			||||||
			goto errout;
 | 
								goto errout;
 | 
				
			||||||
 | 
							f->ifindex = ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif /* CONFIG_NET_CLS_IND */
 | 
					#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))
 | 
						    nla_put_u32(skb, TCA_FW_CLASSID, f->res.classid))
 | 
				
			||||||
		goto nla_put_failure;
 | 
							goto nla_put_failure;
 | 
				
			||||||
#ifdef CONFIG_NET_CLS_IND
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
	if (strlen(f->indev) &&
 | 
						if (f->ifindex) {
 | 
				
			||||||
	    nla_put_string(skb, TCA_FW_INDEV, f->indev))
 | 
							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;
 | 
								goto nla_put_failure;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
#endif /* CONFIG_NET_CLS_IND */
 | 
					#endif /* CONFIG_NET_CLS_IND */
 | 
				
			||||||
	if (head->mask != 0xFFFFFFFF &&
 | 
						if (head->mask != 0xFFFFFFFF &&
 | 
				
			||||||
	    nla_put_u32(skb, TCA_FW_MASK, head->mask))
 | 
						    nla_put_u32(skb, TCA_FW_MASK, head->mask))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ struct tc_u_knode {
 | 
				
			||||||
	struct tc_u_hnode	*ht_up;
 | 
						struct tc_u_hnode	*ht_up;
 | 
				
			||||||
	struct tcf_exts		exts;
 | 
						struct tcf_exts		exts;
 | 
				
			||||||
#ifdef CONFIG_NET_CLS_IND
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
	char                     indev[IFNAMSIZ];
 | 
						int			ifindex;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	u8			fshift;
 | 
						u8			fshift;
 | 
				
			||||||
	struct tcf_result	res;
 | 
						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;
 | 
									*res = n->res;
 | 
				
			||||||
#ifdef CONFIG_NET_CLS_IND
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
				if (!tcf_match_indev(skb, n->indev)) {
 | 
									if (!tcf_match_indev(skb, n->ifindex)) {
 | 
				
			||||||
					n = n->next;
 | 
										n = n->next;
 | 
				
			||||||
					goto next_knode;
 | 
										goto next_knode;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -527,9 +527,11 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NET_CLS_IND
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
	if (tb[TCA_U32_INDEV]) {
 | 
						if (tb[TCA_U32_INDEV]) {
 | 
				
			||||||
		err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV]);
 | 
							int ret;
 | 
				
			||||||
		if (err < 0)
 | 
							ret = tcf_change_indev(net, tb[TCA_U32_INDEV]);
 | 
				
			||||||
 | 
							if (ret < 0)
 | 
				
			||||||
			goto errout;
 | 
								goto errout;
 | 
				
			||||||
 | 
							n->ifindex = ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	tcf_exts_change(tp, &n->exts, &e);
 | 
						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;
 | 
								goto nla_put_failure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NET_CLS_IND
 | 
					#ifdef CONFIG_NET_CLS_IND
 | 
				
			||||||
		if (strlen(n->indev) &&
 | 
							if (n->ifindex) {
 | 
				
			||||||
		    nla_put_string(skb, TCA_U32_INDEV, n->indev))
 | 
								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;
 | 
									goto nla_put_failure;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef CONFIG_CLS_U32_PERF
 | 
					#ifdef CONFIG_CLS_U32_PERF
 | 
				
			||||||
		if (nla_put(skb, TCA_U32_PCNT,
 | 
							if (nla_put(skb, TCA_U32_PCNT,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue