Skip to content

Commit 5fa1273

Browse files
ecree-solarflaredavem330
authored andcommitted
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>
1 parent 17266ee commit 5fa1273

File tree

1 file changed

+48
-6
lines changed

1 file changed

+48
-6
lines changed

net/ipv4/ip_input.c

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ static inline bool ip_rcv_options(struct sk_buff *skb)
307307
return true;
308308
}
309309

310-
static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
310+
static int ip_rcv_finish_core(struct net *net, struct sock *sk,
311+
struct sk_buff *skb)
311312
{
312313
const struct iphdr *iph = ip_hdr(skb);
313314
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)
393394
goto drop;
394395
}
395396

396-
return dst_input(skb);
397+
return NET_RX_SUCCESS;
397398

398399
drop:
399400
kfree_skb(skb);
@@ -405,6 +406,15 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
405406
goto drop;
406407
}
407408

409+
static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
410+
{
411+
int ret = ip_rcv_finish_core(net, sk, skb);
412+
413+
if (ret != NET_RX_DROP)
414+
ret = dst_input(skb);
415+
return ret;
416+
}
417+
408418
/*
409419
* Main IP Receive routine.
410420
*/
@@ -515,15 +525,47 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
515525
ip_rcv_finish);
516526
}
517527

518-
static void ip_sublist_rcv(struct list_head *head, struct net_device *dev,
519-
struct net *net)
528+
static void ip_sublist_rcv_finish(struct list_head *head)
520529
{
521530
struct sk_buff *skb, *next;
522531

532+
list_for_each_entry_safe(skb, next, head, list)
533+
dst_input(skb);
534+
}
535+
536+
static void ip_list_rcv_finish(struct net *net, struct sock *sk,
537+
struct list_head *head)
538+
{
539+
struct dst_entry *curr_dst = NULL;
540+
struct sk_buff *skb, *next;
541+
struct list_head sublist;
542+
543+
list_for_each_entry_safe(skb, next, head, list) {
544+
struct dst_entry *dst;
545+
546+
if (ip_rcv_finish_core(net, sk, skb) == NET_RX_DROP)
547+
continue;
548+
549+
dst = skb_dst(skb);
550+
if (curr_dst != dst) {
551+
/* dispatch old sublist */
552+
list_cut_before(&sublist, head, &skb->list);
553+
if (!list_empty(&sublist))
554+
ip_sublist_rcv_finish(&sublist);
555+
/* start new sublist */
556+
curr_dst = dst;
557+
}
558+
}
559+
/* dispatch final sublist */
560+
ip_sublist_rcv_finish(head);
561+
}
562+
563+
static void ip_sublist_rcv(struct list_head *head, struct net_device *dev,
564+
struct net *net)
565+
{
523566
NF_HOOK_LIST(NFPROTO_IPV4, NF_INET_PRE_ROUTING, net, NULL,
524567
head, dev, NULL, ip_rcv_finish);
525-
list_for_each_entry_safe(skb, next, head, list)
526-
ip_rcv_finish(net, NULL, skb);
568+
ip_list_rcv_finish(net, NULL, head);
527569
}
528570

529571
/* Receive a list of IP packets */

0 commit comments

Comments
 (0)