Skip to content

Commit 88eb194

Browse files
ecree-solarflaredavem330
authored andcommitted
net: core: propagate SKB lists through packet_type lookup
__netif_receive_skb_core() does a depressingly large amount of per-packet work that can't easily be listified, because the another_round looping makes it nontrivial to slice up into smaller functions. Fortunately, most of that work disappears in the fast path: * Hardware devices generally don't have an rx_handler * Unless you're tcpdumping or something, there is usually only one ptype * VLAN processing comes before the protocol ptype lookup, so doesn't force a pt_prev deliver so normally, __netif_receive_skb_core() will run straight through and pass back the one ptype found in ptype_base[hash of skb->protocol]. Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4ce0017 commit 88eb194

File tree

1 file changed

+64
-8
lines changed

1 file changed

+64
-8
lines changed

net/core/dev.c

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4608,7 +4608,8 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,
46084608
return 0;
46094609
}
46104610

4611-
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
4611+
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
4612+
struct packet_type **ppt_prev)
46124613
{
46134614
struct packet_type *ptype, *pt_prev;
46144615
rx_handler_func_t *rx_handler;
@@ -4738,8 +4739,7 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
47384739
if (pt_prev) {
47394740
if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC)))
47404741
goto drop;
4741-
else
4742-
ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
4742+
*ppt_prev = pt_prev;
47434743
} else {
47444744
drop:
47454745
if (!deliver_exact)
@@ -4757,6 +4757,18 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
47574757
return ret;
47584758
}
47594759

4760+
static int __netif_receive_skb_one_core(struct sk_buff *skb, bool pfmemalloc)
4761+
{
4762+
struct net_device *orig_dev = skb->dev;
4763+
struct packet_type *pt_prev = NULL;
4764+
int ret;
4765+
4766+
ret = __netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
4767+
if (pt_prev)
4768+
ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
4769+
return ret;
4770+
}
4771+
47604772
/**
47614773
* netif_receive_skb_core - special purpose version of netif_receive_skb
47624774
* @skb: buffer to process
@@ -4777,19 +4789,63 @@ int netif_receive_skb_core(struct sk_buff *skb)
47774789
int ret;
47784790

47794791
rcu_read_lock();
4780-
ret = __netif_receive_skb_core(skb, false);
4792+
ret = __netif_receive_skb_one_core(skb, false);
47814793
rcu_read_unlock();
47824794

47834795
return ret;
47844796
}
47854797
EXPORT_SYMBOL(netif_receive_skb_core);
47864798

4787-
static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc)
4799+
static inline void __netif_receive_skb_list_ptype(struct list_head *head,
4800+
struct packet_type *pt_prev,
4801+
struct net_device *orig_dev)
47884802
{
47894803
struct sk_buff *skb, *next;
47904804

4805+
if (!pt_prev)
4806+
return;
4807+
if (list_empty(head))
4808+
return;
4809+
47914810
list_for_each_entry_safe(skb, next, head, list)
4792-
__netif_receive_skb_core(skb, pfmemalloc);
4811+
pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
4812+
}
4813+
4814+
static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc)
4815+
{
4816+
/* Fast-path assumptions:
4817+
* - There is no RX handler.
4818+
* - Only one packet_type matches.
4819+
* If either of these fails, we will end up doing some per-packet
4820+
* processing in-line, then handling the 'last ptype' for the whole
4821+
* sublist. This can't cause out-of-order delivery to any single ptype,
4822+
* because the 'last ptype' must be constant across the sublist, and all
4823+
* other ptypes are handled per-packet.
4824+
*/
4825+
/* Current (common) ptype of sublist */
4826+
struct packet_type *pt_curr = NULL;
4827+
/* Current (common) orig_dev of sublist */
4828+
struct net_device *od_curr = NULL;
4829+
struct list_head sublist;
4830+
struct sk_buff *skb, *next;
4831+
4832+
list_for_each_entry_safe(skb, next, head, list) {
4833+
struct net_device *orig_dev = skb->dev;
4834+
struct packet_type *pt_prev = NULL;
4835+
4836+
__netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
4837+
if (pt_curr != pt_prev || od_curr != orig_dev) {
4838+
/* dispatch old sublist */
4839+
list_cut_before(&sublist, head, &skb->list);
4840+
__netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr);
4841+
/* start new sublist */
4842+
pt_curr = pt_prev;
4843+
od_curr = orig_dev;
4844+
}
4845+
}
4846+
4847+
/* dispatch final sublist */
4848+
__netif_receive_skb_list_ptype(head, pt_curr, od_curr);
47934849
}
47944850

47954851
static int __netif_receive_skb(struct sk_buff *skb)
@@ -4809,10 +4865,10 @@ static int __netif_receive_skb(struct sk_buff *skb)
48094865
* context down to all allocation sites.
48104866
*/
48114867
noreclaim_flag = memalloc_noreclaim_save();
4812-
ret = __netif_receive_skb_core(skb, true);
4868+
ret = __netif_receive_skb_one_core(skb, true);
48134869
memalloc_noreclaim_restore(noreclaim_flag);
48144870
} else
4815-
ret = __netif_receive_skb_core(skb, false);
4871+
ret = __netif_receive_skb_one_core(skb, false);
48164872

48174873
return ret;
48184874
}

0 commit comments

Comments
 (0)