[XFRM]: Optimize MTU calculation
[powerpc.git] / net / ipv4 / af_inet.c
index cf358c8..45ced52 100644 (file)
@@ -87,6 +87,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -217,6 +218,26 @@ out:
        return err;
 }
 
+u32 inet_ehash_secret __read_mostly;
+EXPORT_SYMBOL(inet_ehash_secret);
+
+/*
+ * inet_ehash_secret must be set exactly once
+ * Instead of using a dedicated spinlock, we (ab)use inetsw_lock
+ */
+void build_ehash_secret(void)
+{
+       u32 rnd;
+       do {
+               get_random_bytes(&rnd, sizeof(rnd));
+       } while (rnd == 0);
+       spin_lock_bh(&inetsw_lock);
+       if (!inet_ehash_secret)
+               inet_ehash_secret = rnd;
+       spin_unlock_bh(&inetsw_lock);
+}
+EXPORT_SYMBOL(build_ehash_secret);
+
 /*
  *     Create an inet socket.
  */
@@ -233,6 +254,11 @@ static int inet_create(struct socket *sock, int protocol)
        int try_loading_module = 0;
        int err;
 
+       if (sock->type != SOCK_RAW &&
+           sock->type != SOCK_DGRAM &&
+           !inet_ehash_secret)
+               build_ehash_secret();
+
        sock->state = SS_UNCONNECTED;
 
        /* Look for the requested type/protocol pair. */
@@ -755,6 +781,9 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCGSTAMP:
                        err = sock_get_timestamp(sk, (struct timeval __user *)arg);
                        break;
+               case SIOCGSTAMPNS:
+                       err = sock_get_timestampns(sk, (struct timespec __user *)arg);
+                       break;
                case SIOCADDRT:
                case SIOCDELRT:
                case SIOCRTMSG:
@@ -1109,7 +1138,7 @@ static int inet_gso_send_check(struct sk_buff *skb)
        if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
                goto out;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        ihl = iph->ihl * 4;
        if (ihl < sizeof(*iph))
                goto out;
@@ -1117,8 +1146,9 @@ static int inet_gso_send_check(struct sk_buff *skb)
        if (unlikely(!pskb_may_pull(skb, ihl)))
                goto out;
 
-       skb->h.raw = __skb_pull(skb, ihl);
-       iph = skb->nh.iph;
+       __skb_pull(skb, ihl);
+       skb_reset_transport_header(skb);
+       iph = ip_hdr(skb);
        proto = iph->protocol & (MAX_INET_PROTOS - 1);
        err = -EPROTONOSUPPORT;
 
@@ -1152,7 +1182,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
        if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
                goto out;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        ihl = iph->ihl * 4;
        if (ihl < sizeof(*iph))
                goto out;
@@ -1160,8 +1190,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
        if (unlikely(!pskb_may_pull(skb, ihl)))
                goto out;
 
-       skb->h.raw = __skb_pull(skb, ihl);
-       iph = skb->nh.iph;
+       __skb_pull(skb, ihl);
+       skb_reset_transport_header(skb);
+       iph = ip_hdr(skb);
        id = ntohs(iph->id);
        proto = iph->protocol & (MAX_INET_PROTOS - 1);
        segs = ERR_PTR(-EPROTONOSUPPORT);
@@ -1177,11 +1208,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
 
        skb = segs;
        do {
-               iph = skb->nh.iph;
+               iph = ip_hdr(skb);
                iph->id = htons(id++);
                iph->tot_len = htons(skb->len - skb->mac_len);
                iph->check = 0;
-               iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
+               iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
        } while ((skb = skb->next));
 
 out:
@@ -1336,7 +1367,7 @@ static int __init inet_init(void)
         *      Initialise per-cpu ipv4 mibs
         */
 
-       if(init_ipv4_mibs())
+       if (init_ipv4_mibs())
                printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;
 
        ipv4_proc_init();