netns: Use net_eq() to compare net-namespaces for optimization.
[safe/jmp/linux-2.6] / net / ipv4 / devinet.c
index 4a10dbb..2e667e2 100644 (file)
@@ -1,8 +1,6 @@
 /*
  *     NET3    IP device support routines.
  *
- *     Version: $Id: devinet.c,v 1.44 2001/10/31 21:55:54 davem Exp $
- *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
  *             as published by the Free Software Foundation; either version
@@ -90,7 +88,6 @@ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
        [IFA_LOCAL]             = { .type = NLA_U32 },
        [IFA_ADDRESS]           = { .type = NLA_U32 },
        [IFA_BROADCAST]         = { .type = NLA_U32 },
-       [IFA_ANYCAST]           = { .type = NLA_U32 },
        [IFA_LABEL]             = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
 };
 
@@ -165,12 +162,14 @@ static struct in_device *inetdev_init(struct net_device *dev)
        if (!in_dev)
                goto out;
        INIT_RCU_HEAD(&in_dev->rcu_head);
-       memcpy(&in_dev->cnf, dev->nd_net->ipv4.devconf_dflt,
+       memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt,
                        sizeof(in_dev->cnf));
        in_dev->cnf.sysctl = NULL;
        in_dev->dev = dev;
        if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)
                goto out_kfree;
+       if (IPV4_DEVCONF(in_dev->cnf, FORWARDING))
+               dev_disable_lro(dev);
        /* Reference in_dev->dev */
        dev_hold(dev);
        /* Account for reference dev->ip_ptr (below) */
@@ -437,7 +436,7 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
 
 static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        struct nlattr *tb[IFA_MAX+1];
        struct in_device *in_dev;
        struct ifaddrmsg *ifm;
@@ -536,9 +535,6 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh)
        if (tb[IFA_BROADCAST])
                ifa->ifa_broadcast = nla_get_be32(tb[IFA_BROADCAST]);
 
-       if (tb[IFA_ANYCAST])
-               ifa->ifa_anycast = nla_get_be32(tb[IFA_ANYCAST]);
-
        if (tb[IFA_LABEL])
                nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
        else
@@ -552,7 +548,7 @@ errout:
 
 static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        struct in_ifaddr *ifa;
 
        ASSERT_RTNL();
@@ -745,7 +741,6 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                                break;
                        inet_del_ifa(in_dev, ifap, 0);
                        ifa->ifa_broadcast = 0;
-                       ifa->ifa_anycast = 0;
                        ifa->ifa_scope = 0;
                }
 
@@ -872,7 +867,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
 {
        __be32 addr = 0;
        struct in_device *in_dev;
-       struct net *net = dev->nd_net;
+       struct net *net = dev_net(dev);
 
        rcu_read_lock();
        in_dev = __in_dev_get_rcu(dev);
@@ -974,7 +969,7 @@ __be32 inet_confirm_addr(struct in_device *in_dev,
        if (scope != RT_SCOPE_LINK)
                return confirm_addr_indev(in_dev, dst, local, scope);
 
-       net = in_dev->dev->nd_net;
+       net = dev_net(in_dev->dev);
        read_lock(&dev_base_lock);
        rcu_read_lock();
        for_each_netdev(net, dev) {
@@ -1018,7 +1013,7 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev)
                memcpy(old, ifa->ifa_label, IFNAMSIZ);
                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
                if (named++ == 0)
-                       continue;
+                       goto skip;
                dot = strchr(old, ':');
                if (dot == NULL) {
                        sprintf(old, ":%d", named);
@@ -1029,6 +1024,8 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev)
                } else {
                        strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot);
                }
+skip:
+               rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
        }
 }
 
@@ -1113,7 +1110,6 @@ static inline size_t inet_nlmsg_size(void)
               + nla_total_size(4) /* IFA_ADDRESS */
               + nla_total_size(4) /* IFA_LOCAL */
               + nla_total_size(4) /* IFA_BROADCAST */
-              + nla_total_size(4) /* IFA_ANYCAST */
               + nla_total_size(IFNAMSIZ); /* IFA_LABEL */
 }
 
@@ -1143,9 +1139,6 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
        if (ifa->ifa_broadcast)
                NLA_PUT_BE32(skb, IFA_BROADCAST, ifa->ifa_broadcast);
 
-       if (ifa->ifa_anycast)
-               NLA_PUT_BE32(skb, IFA_ANYCAST, ifa->ifa_anycast);
-
        if (ifa->ifa_label[0])
                NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
 
@@ -1158,7 +1151,7 @@ nla_put_failure:
 
 static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        int idx, ip_idx;
        struct net_device *dev;
        struct in_device *in_dev;
@@ -1203,7 +1196,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
        int err = -ENOBUFS;
        struct net *net;
 
-       net = ifa->ifa_dev->dev->nd_net;
+       net = dev_net(ifa->ifa_dev->dev);
        skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
        if (skb == NULL)
                goto errout;
@@ -1250,6 +1243,8 @@ static void inet_forward_change(struct net *net)
        read_lock(&dev_base_lock);
        for_each_netdev(net, dev) {
                struct in_device *in_dev;
+               if (on)
+                       dev_disable_lro(dev);
                rcu_read_lock();
                in_dev = __in_dev_get_rcu(dev);
                if (in_dev)
@@ -1257,8 +1252,6 @@ static void inet_forward_change(struct net *net)
                rcu_read_unlock();
        }
        read_unlock(&dev_base_lock);
-
-       rt_cache_flush(0);
 }
 
 static int devinet_conf_proc(ctl_table *ctl, int write,
@@ -1344,10 +1337,19 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
        if (write && *valp != val) {
                struct net *net = ctl->extra2;
 
-               if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING))
-                       inet_forward_change(net);
-               else if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING))
-                       rt_cache_flush(0);
+               if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) {
+                       rtnl_lock();
+                       if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) {
+                               inet_forward_change(net);
+                       } else if (*valp) {
+                               struct ipv4_devconf *cnf = ctl->extra1;
+                               struct in_device *idev =
+                                       container_of(cnf, struct in_device, cnf);
+                               dev_disable_lro(idev->dev);
+                       }
+                       rtnl_unlock();
+                       rt_cache_flush(net, 0);
+               }
        }
 
        return ret;
@@ -1360,9 +1362,10 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write,
        int *valp = ctl->data;
        int val = *valp;
        int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+       struct net *net = ctl->extra2;
 
        if (write && *valp != val)
-               rt_cache_flush(0);
+               rt_cache_flush(net, 0);
 
        return ret;
 }
@@ -1373,9 +1376,10 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
 {
        int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
                                      newval, newlen);
+       struct net *net = table->extra2;
 
        if (ret == 1)
-               rt_cache_flush(0);
+               rt_cache_flush(net, 0);
 
        return ret;
 }
@@ -1517,7 +1521,7 @@ static void devinet_sysctl_register(struct in_device *idev)
 {
        neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4,
                        NET_IPV4_NEIGH, "ipv4", NULL, NULL);
-       __devinet_sysctl_register(idev->dev->nd_net, idev->dev->name,
+       __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
                        idev->dev->ifindex, &idev->cnf);
 }