net: ipv4: listify ip_rcv_finish
ip_rcv_finish_core(), if it does not drop, sets skb->dst by either early demux or route lookup. The last step, calling dst_input(skb), is left to the caller; in the listified case, we split to form sublists with a common dst, but then ip_sublist_rcv_finish() just calls dst_input(skb) in a loop. The next step in listification would thus be to add a list_input() method to struct dst_entry. Early demux is an indirect call based on iph->protocol; this is another opportunity for listification which is not taken here (it would require slicing up ip_rcv_finish_core() to allow splitting on protocol changes). Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									17266ee939
								
							
						
					
					
						commit
						5fa12739a5
					
				| @ -307,7 +307,8 @@ drop: | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||
| static int ip_rcv_finish_core(struct net *net, struct sock *sk, | ||||
| 			      struct sk_buff *skb) | ||||
| { | ||||
| 	const struct iphdr *iph = ip_hdr(skb); | ||||
| 	int (*edemux)(struct sk_buff *skb); | ||||
| @ -393,7 +394,7 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||
| 			goto drop; | ||||
| 	} | ||||
| 
 | ||||
| 	return dst_input(skb); | ||||
| 	return NET_RX_SUCCESS; | ||||
| 
 | ||||
| drop: | ||||
| 	kfree_skb(skb); | ||||
| @ -405,6 +406,15 @@ drop_error: | ||||
| 	goto drop; | ||||
| } | ||||
| 
 | ||||
| static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||
| { | ||||
| 	int ret = ip_rcv_finish_core(net, sk, skb); | ||||
| 
 | ||||
| 	if (ret != NET_RX_DROP) | ||||
| 		ret = dst_input(skb); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 	Main IP Receive routine. | ||||
|  */ | ||||
| @ -515,15 +525,47 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, | ||||
| 		       ip_rcv_finish); | ||||
| } | ||||
| 
 | ||||
| static void ip_sublist_rcv(struct list_head *head, struct net_device *dev, | ||||
| 			   struct net *net) | ||||
| static void ip_sublist_rcv_finish(struct list_head *head) | ||||
| { | ||||
| 	struct sk_buff *skb, *next; | ||||
| 
 | ||||
| 	list_for_each_entry_safe(skb, next, head, list) | ||||
| 		dst_input(skb); | ||||
| } | ||||
| 
 | ||||
| static void ip_list_rcv_finish(struct net *net, struct sock *sk, | ||||
| 			       struct list_head *head) | ||||
| { | ||||
| 	struct dst_entry *curr_dst = NULL; | ||||
| 	struct sk_buff *skb, *next; | ||||
| 	struct list_head sublist; | ||||
| 
 | ||||
| 	list_for_each_entry_safe(skb, next, head, list) { | ||||
| 		struct dst_entry *dst; | ||||
| 
 | ||||
| 		if (ip_rcv_finish_core(net, sk, skb) == NET_RX_DROP) | ||||
| 			continue; | ||||
| 
 | ||||
| 		dst = skb_dst(skb); | ||||
| 		if (curr_dst != dst) { | ||||
| 			/* dispatch old sublist */ | ||||
| 			list_cut_before(&sublist, head, &skb->list); | ||||
| 			if (!list_empty(&sublist)) | ||||
| 				ip_sublist_rcv_finish(&sublist); | ||||
| 			/* start new sublist */ | ||||
| 			curr_dst = dst; | ||||
| 		} | ||||
| 	} | ||||
| 	/* dispatch final sublist */ | ||||
| 	ip_sublist_rcv_finish(head); | ||||
| } | ||||
| 
 | ||||
| static void ip_sublist_rcv(struct list_head *head, struct net_device *dev, | ||||
| 			   struct net *net) | ||||
| { | ||||
| 	NF_HOOK_LIST(NFPROTO_IPV4, NF_INET_PRE_ROUTING, net, NULL, | ||||
| 		     head, dev, NULL, ip_rcv_finish); | ||||
| 	list_for_each_entry_safe(skb, next, head, list) | ||||
| 		ip_rcv_finish(net, NULL, skb); | ||||
| 	ip_list_rcv_finish(net, NULL, head); | ||||
| } | ||||
| 
 | ||||
| /* Receive a list of IP packets */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user