inet: frag: set limits and make init_net's high_thresh limit global
authorNikolay Aleksandrov <nikolay@redhat.com>
Thu, 24 Jul 2014 14:50:37 +0000 (16:50 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jul 2014 05:34:36 +0000 (22:34 -0700)
This patch makes init_net's high_thresh limit to be the maximum for all
namespaces, thus introducing a global memory limit threshold equal to the
sum of the individual high_thresh limits which are capped.
It also introduces some sane minimums for low_thresh as it shouldn't be
able to drop below 0 (or > high_thresh in the unsigned case), and
overall low_thresh should not ever be above high_thresh, so we make the
following relations for a namespace:
init_net:
 high_thresh - max(not capped), min(init_net low_thresh)
 low_thresh - max(init_net high_thresh), min (0)

all other namespaces:
 high_thresh = max(init_net high_thresh), min(namespace's low_thresh)
 low_thresh = max(namespace's high_thresh), min(0)

The major issue with having low_thresh > high_thresh is that we'll
schedule eviction but never evict anything and thus rely only on the
timers.

Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/ip-sysctl.txt
net/ieee802154/reassembly.c
net/ipv4/ip_fragment.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c

index e8c304e378316bfaa1d8a72062abfff520be99d0..29a93518bf18acc7d9a0a3ac443abd03662e3792 100644 (file)
@@ -101,7 +101,8 @@ ipfrag_high_thresh - INTEGER
        Maximum memory used to reassemble IP fragments. When
        ipfrag_high_thresh bytes of memory is allocated for this purpose,
        the fragment handler will toss packets until ipfrag_low_thresh
-       is reached.
+       is reached. This also serves as a maximum limit to namespaces
+       different from the initial one.
 
 ipfrag_low_thresh - INTEGER
        Maximum memory used to reassemble IP fragments before the kernel
index 8da635d92a5848757b30a4455344521e95a160e4..f13d4f32e207e124b5f07ffd7dce4da8a2d1f2c6 100644 (file)
@@ -386,20 +386,25 @@ err:
 EXPORT_SYMBOL(lowpan_frag_rcv);
 
 #ifdef CONFIG_SYSCTL
+static int zero;
+
 static struct ctl_table lowpan_frags_ns_ctl_table[] = {
        {
                .procname       = "6lowpanfrag_high_thresh",
                .data           = &init_net.ieee802154_lowpan.frags.high_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &init_net.ieee802154_lowpan.frags.low_thresh
        },
        {
                .procname       = "6lowpanfrag_low_thresh",
                .data           = &init_net.ieee802154_lowpan.frags.low_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &init_net.ieee802154_lowpan.frags.high_thresh
        },
        {
                .procname       = "6lowpanfrag_time",
@@ -446,7 +451,10 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net)
                        goto err_alloc;
 
                table[0].data = &ieee802154_lowpan->frags.high_thresh;
+               table[0].extra1 = &ieee802154_lowpan->frags.low_thresh;
+               table[0].extra2 = &init_net.ieee802154_lowpan.frags.high_thresh;
                table[1].data = &ieee802154_lowpan->frags.low_thresh;
+               table[1].extra2 = &ieee802154_lowpan->frags.high_thresh;
                table[2].data = &ieee802154_lowpan->frags.timeout;
                table[3].data = &ieee802154_lowpan->max_dsize;
 
index ccee68dffd6e86eaef46705041efa482e507206d..634fc31aa24309698eba0718efbbe2304512a7cc 100644 (file)
@@ -700,14 +700,17 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = {
                .data           = &init_net.ipv4.frags.high_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &init_net.ipv4.frags.low_thresh
        },
        {
                .procname       = "ipfrag_low_thresh",
                .data           = &init_net.ipv4.frags.low_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &init_net.ipv4.frags.high_thresh
        },
        {
                .procname       = "ipfrag_time",
@@ -752,7 +755,10 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net)
                        goto err_alloc;
 
                table[0].data = &net->ipv4.frags.high_thresh;
+               table[0].extra1 = &net->ipv4.frags.low_thresh;
+               table[0].extra2 = &init_net.ipv4.frags.high_thresh;
                table[1].data = &net->ipv4.frags.low_thresh;
+               table[1].extra2 = &net->ipv4.frags.high_thresh;
                table[2].data = &net->ipv4.frags.timeout;
 
                /* Don't export sysctls to unprivileged users */
index 4d9da1e35f8c4279fe633d9cb5d29e979d9f947d..3d4bccf6d67d38cd84b04cda51fd9234b20f3d2e 100644 (file)
@@ -63,6 +63,8 @@ struct nf_ct_frag6_skb_cb
 static struct inet_frags nf_frags;
 
 #ifdef CONFIG_SYSCTL
+static int zero;
+
 static struct ctl_table nf_ct_frag6_sysctl_table[] = {
        {
                .procname       = "nf_conntrack_frag6_timeout",
@@ -76,14 +78,17 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
                .data           = &init_net.nf_frag.frags.low_thresh,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &init_net.nf_frag.frags.high_thresh
        },
        {
                .procname       = "nf_conntrack_frag6_high_thresh",
                .data           = &init_net.nf_frag.frags.high_thresh,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &init_net.nf_frag.frags.low_thresh
        },
        { }
 };
@@ -102,7 +107,10 @@ static int nf_ct_frag6_sysctl_register(struct net *net)
 
                table[0].data = &net->nf_frag.frags.timeout;
                table[1].data = &net->nf_frag.frags.low_thresh;
+               table[1].extra2 = &net->nf_frag.frags.high_thresh;
                table[2].data = &net->nf_frag.frags.high_thresh;
+               table[2].extra1 = &net->nf_frag.frags.low_thresh;
+               table[2].extra2 = &init_net.nf_frag.frags.high_thresh;
        }
 
        hdr = register_net_sysctl(net, "net/netfilter", table);
index 57a9707b2032df3af4545e8b954b56279d0f61e1..f1709c4a289a5802c1c1baa03bd9d87193b3b589 100644 (file)
@@ -578,20 +578,25 @@ static const struct inet6_protocol frag_protocol =
 };
 
 #ifdef CONFIG_SYSCTL
+static int zero;
+
 static struct ctl_table ip6_frags_ns_ctl_table[] = {
        {
                .procname       = "ip6frag_high_thresh",
                .data           = &init_net.ipv6.frags.high_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &init_net.ipv6.frags.low_thresh
        },
        {
                .procname       = "ip6frag_low_thresh",
                .data           = &init_net.ipv6.frags.low_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &init_net.ipv6.frags.high_thresh
        },
        {
                .procname       = "ip6frag_time",
@@ -628,7 +633,10 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net)
                        goto err_alloc;
 
                table[0].data = &net->ipv6.frags.high_thresh;
+               table[0].extra1 = &net->ipv6.frags.low_thresh;
+               table[0].extra2 = &init_net.ipv6.frags.high_thresh;
                table[1].data = &net->ipv6.frags.low_thresh;
+               table[1].extra2 = &net->ipv6.frags.high_thresh;
                table[2].data = &net->ipv6.frags.timeout;
 
                /* Don't export sysctls to unprivileged users */