[NET]: Make /proc/net per network namespace
[linux-block.git] / net / ipv4 / proc.c
index ae68a691e8cdc47b387721dcb9c1b88d716aa994..95a8f8f2de71af73ce64beab13f28b2edebf8dd3 100644 (file)
@@ -34,6 +34,7 @@
  *             2 of the License, or (at your option) any later version.
  */
 #include <linux/types.h>
+#include <net/net_namespace.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
@@ -87,19 +88,6 @@ static const struct file_operations sockstat_seq_fops = {
        .release = single_release,
 };
 
-static unsigned long
-fold_field(void *mib[], int offt)
-{
-       unsigned long res = 0;
-       int i;
-
-       for_each_possible_cpu(i) {
-               res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
-               res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
-       }
-       return res;
-}
-
 /* snmp items */
 static const struct snmp_mib snmp4_ipstats_list[] = {
        SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
@@ -122,6 +110,17 @@ static const struct snmp_mib snmp4_ipstats_list[] = {
        SNMP_MIB_SENTINEL
 };
 
+/* Following RFC4293 items are displayed in /proc/net/netstat */
+static const struct snmp_mib snmp4_ipextstats_list[] = {
+       SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
+       SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
+       SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
+       SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
+       SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
+       SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
+       SNMP_MIB_SENTINEL
+};
+
 static const struct snmp_mib snmp4_icmp_list[] = {
        SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS),
        SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS),
@@ -246,6 +245,9 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPAbortOnLinger", LINUX_MIB_TCPABORTONLINGER),
        SNMP_MIB_ITEM("TCPAbortFailed", LINUX_MIB_TCPABORTFAILED),
        SNMP_MIB_ITEM("TCPMemoryPressures", LINUX_MIB_TCPMEMORYPRESSURES),
+       SNMP_MIB_ITEM("TCPSACKDiscard", LINUX_MIB_TCPSACKDISCARD),
+       SNMP_MIB_ITEM("TCPDSACKIgnoredOld", LINUX_MIB_TCPDSACKIGNOREDOLD),
+       SNMP_MIB_ITEM("TCPDSACKIgnoredNoUndo", LINUX_MIB_TCPDSACKIGNOREDNOUNDO),
        SNMP_MIB_SENTINEL
 };
 
@@ -262,12 +264,12 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
                seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
 
        seq_printf(seq, "\nIp: %d %d",
-                       ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
+                  IPV4_DEVCONF_ALL(FORWARDING) ? 1 : 2, sysctl_ip_default_ttl);
 
        for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
                seq_printf(seq, " %lu",
-                          fold_field((void **) ip_statistics,
-                                     snmp4_ipstats_list[i].entry));
+                          snmp_fold_field((void **)ip_statistics,
+                                          snmp4_ipstats_list[i].entry));
 
        seq_puts(seq, "\nIcmp:");
        for (i = 0; snmp4_icmp_list[i].name != NULL; i++)
@@ -276,8 +278,8 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
        seq_puts(seq, "\nIcmp:");
        for (i = 0; snmp4_icmp_list[i].name != NULL; i++)
                seq_printf(seq, " %lu",
-                          fold_field((void **) icmp_statistics,
-                                     snmp4_icmp_list[i].entry));
+                          snmp_fold_field((void **)icmp_statistics,
+                                          snmp4_icmp_list[i].entry));
 
        seq_puts(seq, "\nTcp:");
        for (i = 0; snmp4_tcp_list[i].name != NULL; i++)
@@ -288,12 +290,12 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
                /* MaxConn field is signed, RFC 2012 */
                if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN)
                        seq_printf(seq, " %ld",
-                                  fold_field((void **) tcp_statistics,
-                                             snmp4_tcp_list[i].entry));
+                                  snmp_fold_field((void **)tcp_statistics,
+                                                  snmp4_tcp_list[i].entry));
                else
                        seq_printf(seq, " %lu",
-                                  fold_field((void **) tcp_statistics,
-                                             snmp4_tcp_list[i].entry));
+                                  snmp_fold_field((void **)tcp_statistics,
+                                                  snmp4_tcp_list[i].entry));
        }
 
        seq_puts(seq, "\nUdp:");
@@ -303,8 +305,8 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
        seq_puts(seq, "\nUdp:");
        for (i = 0; snmp4_udp_list[i].name != NULL; i++)
                seq_printf(seq, " %lu",
-                          fold_field((void **) udp_statistics,
-                                     snmp4_udp_list[i].entry));
+                          snmp_fold_field((void **)udp_statistics,
+                                          snmp4_udp_list[i].entry));
 
        /* the UDP and UDP-Lite MIBs are the same */
        seq_puts(seq, "\nUdpLite:");
@@ -314,8 +316,8 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
        seq_puts(seq, "\nUdpLite:");
        for (i = 0; snmp4_udp_list[i].name != NULL; i++)
                seq_printf(seq, " %lu",
-                          fold_field((void **) udplite_statistics,
-                                     snmp4_udp_list[i].entry)     );
+                          snmp_fold_field((void **)udplite_statistics,
+                                          snmp4_udp_list[i].entry));
 
        seq_putc(seq, '\n');
        return 0;
@@ -348,8 +350,18 @@ static int netstat_seq_show(struct seq_file *seq, void *v)
        seq_puts(seq, "\nTcpExt:");
        for (i = 0; snmp4_net_list[i].name != NULL; i++)
                seq_printf(seq, " %lu",
-                          fold_field((void **) net_statistics,
-                                     snmp4_net_list[i].entry));
+                          snmp_fold_field((void **)net_statistics,
+                                          snmp4_net_list[i].entry));
+
+       seq_puts(seq, "\nIpExt:");
+       for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++)
+               seq_printf(seq, " %s", snmp4_ipextstats_list[i].name);
+
+       seq_puts(seq, "\nIpExt:");
+       for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++)
+               seq_printf(seq, " %lu",
+                          snmp_fold_field((void **)ip_statistics,
+                                          snmp4_ipextstats_list[i].entry));
 
        seq_putc(seq, '\n');
        return 0;
@@ -372,20 +384,20 @@ int __init ip_misc_proc_init(void)
 {
        int rc = 0;
 
-       if (!proc_net_fops_create("netstat", S_IRUGO, &netstat_seq_fops))
+       if (!proc_net_fops_create(&init_net, "netstat", S_IRUGO, &netstat_seq_fops))
                goto out_netstat;
 
-       if (!proc_net_fops_create("snmp", S_IRUGO, &snmp_seq_fops))
+       if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops))
                goto out_snmp;
 
-       if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops))
+       if (!proc_net_fops_create(&init_net, "sockstat", S_IRUGO, &sockstat_seq_fops))
                goto out_sockstat;
 out:
        return rc;
 out_sockstat:
-       proc_net_remove("snmp");
+       proc_net_remove(&init_net, "snmp");
 out_snmp:
-       proc_net_remove("netstat");
+       proc_net_remove(&init_net, "netstat");
 out_netstat:
        rc = -ENOMEM;
        goto out;