lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <2c9e2cbc-3c1a-bc7d-fe66-d1ff8e26f1bb@solarflare.com> Date: Thu, 30 Aug 2018 21:00:30 +0100 From: Edward Cree <ecree@...arflare.com> To: <linux-net-drivers@...arflare.com>, <davem@...emloft.net> CC: <netdev@...r.kernel.org> Subject: [RFC PATCH net-next 3/4] net: make listified RX functions return number of good packets Signed-off-by: Edward Cree <ecree@...arflare.com> --- include/linux/netdevice.h | 4 +-- include/net/ip.h | 4 +-- include/net/ipv6.h | 4 +-- net/core/dev.c | 63 +++++++++++++++++++++++++++++------------------ net/ipv4/ip_input.c | 39 ++++++++++++++++++----------- net/ipv6/ip6_input.c | 37 +++++++++++++++++----------- 6 files changed, 92 insertions(+), 59 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a4f55142d3eb..ba5f985688eb 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2322,7 +2322,7 @@ struct packet_type { struct net_device *, struct packet_type *, struct net_device *); - void (*list_func) (struct list_head *, + int (*list_func) (struct list_head *, struct packet_type *, struct net_device *); bool (*id_match)(struct packet_type *ptype, @@ -3519,7 +3519,7 @@ int netif_rx(struct sk_buff *skb); int netif_rx_ni(struct sk_buff *skb); int netif_receive_skb(struct sk_buff *skb); int netif_receive_skb_core(struct sk_buff *skb); -void netif_receive_skb_list(struct list_head *head); +int netif_receive_skb_list(struct list_head *head); gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); int napi_gro_receive_list(struct napi_struct *napi, struct list_head *head); void napi_gro_flush(struct napi_struct *napi, bool flush_old); diff --git a/include/net/ip.h b/include/net/ip.h index e44b1a44f67a..aab1f7eea1e1 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -152,8 +152,8 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, struct ip_options_rcu *opt); int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); -void ip_list_rcv(struct list_head *head, struct packet_type *pt, - struct net_device *orig_dev); +int ip_list_rcv(struct list_head *head, struct packet_type *pt, + struct net_device *orig_dev); int ip_local_deliver(struct sk_buff *skb); int ip_mr_input(struct sk_buff *skb); int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb); diff --git a/include/net/ipv6.h b/include/net/ipv6.h index ff33f498c137..f15651eabfe0 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -914,8 +914,8 @@ static inline __be32 flowi6_get_flowlabel(const struct flowi6 *fl6) int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); -void ipv6_list_rcv(struct list_head *head, struct packet_type *pt, - struct net_device *orig_dev); +int ipv6_list_rcv(struct list_head *head, struct packet_type *pt, + struct net_device *orig_dev); int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb); diff --git a/net/core/dev.c b/net/core/dev.c index d1e55bef84eb..ac9741273c62 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4920,24 +4920,27 @@ int netif_receive_skb_core(struct sk_buff *skb) } EXPORT_SYMBOL(netif_receive_skb_core); -static inline void __netif_receive_skb_list_ptype(struct list_head *head, - struct packet_type *pt_prev, - struct net_device *orig_dev) +static inline int __netif_receive_skb_list_ptype(struct list_head *head, + struct packet_type *pt_prev, + struct net_device *orig_dev) { struct sk_buff *skb, *next; + int kept = 0; if (!pt_prev) - return; + return 0; if (list_empty(head)) - return; + return 0; if (pt_prev->list_func != NULL) - pt_prev->list_func(head, pt_prev, orig_dev); + kept = pt_prev->list_func(head, pt_prev, orig_dev); else list_for_each_entry_safe(skb, next, head, list) - pt_prev->func(skb, skb->dev, pt_prev, orig_dev); + if (pt_prev->func(skb, skb->dev, pt_prev, orig_dev) == NET_RX_SUCCESS) + kept++; + return kept; } -static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc) +static int __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc) { /* Fast-path assumptions: * - There is no RX handler. @@ -4954,6 +4957,7 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo struct net_device *od_curr = NULL; struct list_head sublist; struct sk_buff *skb, *next; + int kept = 0, ret; INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { @@ -4961,12 +4965,15 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo struct packet_type *pt_prev = NULL; list_del(&skb->list); - __netif_receive_skb_core(skb, pfmemalloc, &pt_prev); - if (!pt_prev) + ret = __netif_receive_skb_core(skb, pfmemalloc, &pt_prev); + if (!pt_prev) { + if (ret == NET_RX_SUCCESS) + kept++; continue; + } if (pt_curr != pt_prev || od_curr != orig_dev) { /* dispatch old sublist */ - __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr); + kept += __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr); /* start new sublist */ INIT_LIST_HEAD(&sublist); pt_curr = pt_prev; @@ -4976,7 +4983,8 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo } /* dispatch final sublist */ - __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr); + kept += __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr); + return kept; } static int __netif_receive_skb(struct sk_buff *skb) @@ -5004,11 +5012,12 @@ static int __netif_receive_skb(struct sk_buff *skb) return ret; } -static void __netif_receive_skb_list(struct list_head *head) +static int __netif_receive_skb_list(struct list_head *head) { unsigned long noreclaim_flag = 0; struct sk_buff *skb, *next; bool pfmemalloc = false; /* Is current sublist PF_MEMALLOC? */ + int kept = 0; list_for_each_entry_safe(skb, next, head, list) { if ((sk_memalloc_socks() && skb_pfmemalloc(skb)) != pfmemalloc) { @@ -5017,7 +5026,7 @@ static void __netif_receive_skb_list(struct list_head *head) /* Handle the previous sublist */ list_cut_before(&sublist, head, &skb->list); if (!list_empty(&sublist)) - __netif_receive_skb_list_core(&sublist, pfmemalloc); + kept += __netif_receive_skb_list_core(&sublist, pfmemalloc); pfmemalloc = !pfmemalloc; /* See comments in __netif_receive_skb */ if (pfmemalloc) @@ -5028,10 +5037,11 @@ static void __netif_receive_skb_list(struct list_head *head) } /* Handle the remaining sublist */ if (!list_empty(head)) - __netif_receive_skb_list_core(head, pfmemalloc); + kept += __netif_receive_skb_list_core(head, pfmemalloc); /* Restore pflags */ if (pfmemalloc) memalloc_noreclaim_restore(noreclaim_flag); + return kept; } static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp) @@ -5107,17 +5117,20 @@ static int netif_receive_skb_internal(struct sk_buff *skb) return ret; } -static void netif_receive_skb_list_internal(struct list_head *head) +static int netif_receive_skb_list_internal(struct list_head *head) { struct bpf_prog *xdp_prog = NULL; struct sk_buff *skb, *next; struct list_head sublist; + int kept = 0; INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { net_timestamp_check(netdev_tstamp_prequeue, skb); list_del(&skb->list); - if (!skb_defer_rx_timestamp(skb)) + if (skb_defer_rx_timestamp(skb)) + kept++; + else list_add_tail(&skb->list, &sublist); } list_splice_init(&sublist, head); @@ -5147,13 +5160,15 @@ static void netif_receive_skb_list_internal(struct list_head *head) if (cpu >= 0) { /* Will be handled, remove from list */ list_del(&skb->list); - enqueue_to_backlog(skb, cpu, &rflow->last_qtail); + if (enqueue_to_backlog(skb, cpu, &rflow->last_qtail) == NET_RX_SUCCESS) + kept++; } } } #endif - __netif_receive_skb_list(head); + kept += __netif_receive_skb_list(head); rcu_read_unlock(); + return kept; } /** @@ -5183,21 +5198,21 @@ EXPORT_SYMBOL(netif_receive_skb); * netif_receive_skb_list - process many receive buffers from network * @head: list of skbs to process. * - * Since return value of netif_receive_skb() is normally ignored, and - * wouldn't be meaningful for a list, this function returns void. + * Returns the number of skbs for which netif_receive_skb() would have + * returned %NET_RX_SUCCESS. * * This function may only be called from softirq context and interrupts * should be enabled. */ -void netif_receive_skb_list(struct list_head *head) +int netif_receive_skb_list(struct list_head *head) { struct sk_buff *skb; if (list_empty(head)) - return; + return 0; list_for_each_entry(skb, head, list) trace_netif_receive_skb_list_entry(skb); - netif_receive_skb_list_internal(head); + return netif_receive_skb_list_internal(head); } EXPORT_SYMBOL(netif_receive_skb_list); diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 3196cf58f418..75cc5a6ef9b8 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -526,9 +526,10 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, ip_rcv_finish); } -static void ip_sublist_rcv_finish(struct list_head *head) +static int ip_sublist_rcv_finish(struct list_head *head) { struct sk_buff *skb, *next; + int kept = 0; list_for_each_entry_safe(skb, next, head, list) { list_del(&skb->list); @@ -536,16 +537,19 @@ static void ip_sublist_rcv_finish(struct list_head *head) * another kind of SKB-list usage (see validate_xmit_skb_list) */ skb->next = NULL; - dst_input(skb); + if (dst_input(skb) == NET_RX_SUCCESS) + kept++; } + return kept; } -static void ip_list_rcv_finish(struct net *net, struct sock *sk, - struct list_head *head) +static int 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; + int kept = 0; INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { @@ -556,8 +560,10 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk, * skb to its handler for processing */ skb = l3mdev_ip_rcv(skb); - if (!skb) + if (!skb) { + kept++; continue; + } if (ip_rcv_finish_core(net, sk, skb) == NET_RX_DROP) continue; @@ -565,7 +571,7 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk, if (curr_dst != dst) { /* dispatch old sublist */ if (!list_empty(&sublist)) - ip_sublist_rcv_finish(&sublist); + kept += ip_sublist_rcv_finish(&sublist); /* start new sublist */ INIT_LIST_HEAD(&sublist); curr_dst = dst; @@ -573,25 +579,27 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk, list_add_tail(&skb->list, &sublist); } /* dispatch final sublist */ - ip_sublist_rcv_finish(&sublist); + kept += ip_sublist_rcv_finish(&sublist); + return kept; } -static void ip_sublist_rcv(struct list_head *head, struct net_device *dev, - struct net *net) +static int 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); - ip_list_rcv_finish(net, NULL, head); + return ip_list_rcv_finish(net, NULL, head); } -/* Receive a list of IP packets */ -void ip_list_rcv(struct list_head *head, struct packet_type *pt, - struct net_device *orig_dev) +/* Receive a list of IP packets; return number of successful receives */ +int ip_list_rcv(struct list_head *head, struct packet_type *pt, + struct net_device *orig_dev) { struct net_device *curr_dev = NULL; struct net *curr_net = NULL; struct sk_buff *skb, *next; struct list_head sublist; + int kept = 0; INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { @@ -606,7 +614,7 @@ void ip_list_rcv(struct list_head *head, struct packet_type *pt, if (curr_dev != dev || curr_net != net) { /* dispatch old sublist */ if (!list_empty(&sublist)) - ip_sublist_rcv(&sublist, curr_dev, curr_net); + kept += ip_sublist_rcv(&sublist, curr_dev, curr_net); /* start new sublist */ INIT_LIST_HEAD(&sublist); curr_dev = dev; @@ -615,5 +623,6 @@ void ip_list_rcv(struct list_head *head, struct packet_type *pt, list_add_tail(&skb->list, &sublist); } /* dispatch final sublist */ - ip_sublist_rcv(&sublist, curr_dev, curr_net); + kept += ip_sublist_rcv(&sublist, curr_dev, curr_net); + return kept; } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 6242682be876..e64b830c9f0f 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -76,20 +76,24 @@ int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) return dst_input(skb); } -static void ip6_sublist_rcv_finish(struct list_head *head) +static int ip6_sublist_rcv_finish(struct list_head *head) { struct sk_buff *skb, *next; + int kept = 0; list_for_each_entry_safe(skb, next, head, list) - dst_input(skb); + if (dst_input(skb) == NET_RX_SUCCESS) + kept++; + return kept; } -static void ip6_list_rcv_finish(struct net *net, struct sock *sk, - struct list_head *head) +static int ip6_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; + int kept = 0; INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { @@ -100,14 +104,16 @@ static void ip6_list_rcv_finish(struct net *net, struct sock *sk, * skb to its handler for processing */ skb = l3mdev_ip6_rcv(skb); - if (!skb) + if (!skb) { + kept++; continue; + } ip6_rcv_finish_core(net, sk, skb); dst = skb_dst(skb); if (curr_dst != dst) { /* dispatch old sublist */ if (!list_empty(&sublist)) - ip6_sublist_rcv_finish(&sublist); + kept += ip6_sublist_rcv_finish(&sublist); /* start new sublist */ INIT_LIST_HEAD(&sublist); curr_dst = dst; @@ -115,7 +121,8 @@ static void ip6_list_rcv_finish(struct net *net, struct sock *sk, list_add_tail(&skb->list, &sublist); } /* dispatch final sublist */ - ip6_sublist_rcv_finish(&sublist); + kept += ip6_sublist_rcv_finish(&sublist); + return kept; } static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev, @@ -273,22 +280,23 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ip6_rcv_finish); } -static void ip6_sublist_rcv(struct list_head *head, struct net_device *dev, - struct net *net) +static int ip6_sublist_rcv(struct list_head *head, struct net_device *dev, + struct net *net) { NF_HOOK_LIST(NFPROTO_IPV6, NF_INET_PRE_ROUTING, net, NULL, head, dev, NULL, ip6_rcv_finish); - ip6_list_rcv_finish(net, NULL, head); + return ip6_list_rcv_finish(net, NULL, head); } /* Receive a list of IPv6 packets */ -void ipv6_list_rcv(struct list_head *head, struct packet_type *pt, - struct net_device *orig_dev) +int ipv6_list_rcv(struct list_head *head, struct packet_type *pt, + struct net_device *orig_dev) { struct net_device *curr_dev = NULL; struct net *curr_net = NULL; struct sk_buff *skb, *next; struct list_head sublist; + int kept = 0; INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { @@ -303,7 +311,7 @@ void ipv6_list_rcv(struct list_head *head, struct packet_type *pt, if (curr_dev != dev || curr_net != net) { /* dispatch old sublist */ if (!list_empty(&sublist)) - ip6_sublist_rcv(&sublist, curr_dev, curr_net); + kept += ip6_sublist_rcv(&sublist, curr_dev, curr_net); /* start new sublist */ INIT_LIST_HEAD(&sublist); curr_dev = dev; @@ -312,7 +320,8 @@ void ipv6_list_rcv(struct list_head *head, struct packet_type *pt, list_add_tail(&skb->list, &sublist); } /* dispatch final sublist */ - ip6_sublist_rcv(&sublist, curr_dev, curr_net); + kept += ip6_sublist_rcv(&sublist, curr_dev, curr_net); + return kept; } /*
Powered by blists - more mailing lists