]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net:Add sysctl_max_skb_frags
authorHans Westgaard Ry <hans.westgaard.ry@oracle.com>
Wed, 3 Feb 2016 08:26:57 +0000 (09:26 +0100)
committerJiri Slaby <jslaby@suse.cz>
Wed, 2 Mar 2016 15:29:07 +0000 (16:29 +0100)
[ Upstream commit 5f74f82ea34c0da80ea0b49192bb5ea06e063593 ]

Devices may have limits on the number of fragments in an skb they support.
Current codebase uses a constant as maximum for number of fragments one
skb can hold and use.
When enabling scatter/gather and running traffic with many small messages
the codebase uses the maximum number of fragments and may thereby violate
the max for certain devices.
The patch introduces a global variable as max number of fragments.

Signed-off-by: Hans Westgaard Ry <hans.westgaard.ry@oracle.com>
Reviewed-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
include/linux/skbuff.h
net/core/skbuff.c
net/core/sysctl_net_core.c
net/ipv4/tcp.c

index 16e753a9922ab666cf04b80cc7a311a25e57a8cf..e492ab7aadbfdea88b127e4f569dc51800bd8349 100644 (file)
@@ -149,6 +149,7 @@ struct sk_buff;
 #else
 #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1)
 #endif
+extern int sysctl_max_skb_frags;
 
 typedef struct skb_frag_struct skb_frag_t;
 
index 56cdf3bb1e7fee831adba2e42277ee86921577a5..7df6f539a402c43ea6e0b64504a45e13d343a177 100644 (file)
@@ -76,6 +76,8 @@
 
 struct kmem_cache *skbuff_head_cache __read_mostly;
 static struct kmem_cache *skbuff_fclone_cache __read_mostly;
+int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
+EXPORT_SYMBOL(sysctl_max_skb_frags);
 
 /**
  *     skb_panic - private function for out-of-line support
index f3413ae3d973edafa377043770cf9381b2ca3c48..d7962397d90ffc6eea9e623b6393454a03fbbd65 100644 (file)
@@ -27,6 +27,7 @@ static int one = 1;
 static int ushort_max = USHRT_MAX;
 static int min_sndbuf = SOCK_MIN_SNDBUF;
 static int min_rcvbuf = SOCK_MIN_RCVBUF;
+static int max_skb_frags = MAX_SKB_FRAGS;
 
 #ifdef CONFIG_RPS
 static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
@@ -362,6 +363,15 @@ static struct ctl_table net_core_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
+       {
+               .procname       = "max_skb_frags",
+               .data           = &sysctl_max_skb_frags,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &one,
+               .extra2         = &max_skb_frags,
+       },
        { }
 };
 
index a880ccc10f61d85b1ad2ddfc47612d818fcee006..392d3259f9ad57dc4c3a492fa251d8100231ee52 100644 (file)
@@ -886,7 +886,7 @@ new_segment:
 
                i = skb_shinfo(skb)->nr_frags;
                can_coalesce = skb_can_coalesce(skb, i, page, offset);
-               if (!can_coalesce && i >= MAX_SKB_FRAGS) {
+               if (!can_coalesce && i >= sysctl_max_skb_frags) {
                        tcp_mark_push(tp, skb);
                        goto new_segment;
                }
@@ -1169,7 +1169,7 @@ new_segment:
 
                                if (!skb_can_coalesce(skb, i, pfrag->page,
                                                      pfrag->offset)) {
-                                       if (i == MAX_SKB_FRAGS || !sg) {
+                                       if (i == sysctl_max_skb_frags || !sg) {
                                                tcp_mark_push(tp, skb);
                                                goto new_segment;
                                        }