aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-04-08 23:47:16 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-09 13:12:23 -0400
commit617fe29d45bdfffba2739e6512c83e766e6ae72c (patch)
tree8eb3d331f1c042893a990af3ee48e2aab4061fef
parentfc403832f7bd94014fe3d965e0652a857160f1c9 (diff)
net: ipv6: only invalidate previously tokenized addresses
Instead of invalidating all IPv6 addresses with global scope when one decides to use IPv6 tokens, we should only invalidate previous tokens and leave the rest intact until they expire eventually (or are intact forever). For doing this less greedy approach, we're adding a bool at the end of inet6_ifaddr structure instead, for two reasons: i) per-inet6_ifaddr flag space is already used up, making it wider might not be a good idea, since ii) also we do not necessarily need to export this information into user space. Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/if_inet6.h2
-rw-r--r--net/ipv6/addrconf.c7
2 files changed, 7 insertions, 2 deletions
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index f1063d62cd13..100fb8cec17c 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -71,6 +71,8 @@ struct inet6_ifaddr {
71 struct inet6_ifaddr *ifpub; 71 struct inet6_ifaddr *ifpub;
72 int regen_count; 72 int regen_count;
73#endif 73#endif
74 bool tokenized;
75
74 struct rcu_head rcu; 76 struct rcu_head rcu;
75}; 77};
76 78
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 713ebe303f61..28b61e89bbb8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -878,6 +878,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
878 ifa->prefix_len = pfxlen; 878 ifa->prefix_len = pfxlen;
879 ifa->flags = flags | IFA_F_TENTATIVE; 879 ifa->flags = flags | IFA_F_TENTATIVE;
880 ifa->cstamp = ifa->tstamp = jiffies; 880 ifa->cstamp = ifa->tstamp = jiffies;
881 ifa->tokenized = false;
881 882
882 ifa->rt = rt; 883 ifa->rt = rt;
883 884
@@ -2134,6 +2135,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
2134 struct inet6_ifaddr *ifp; 2135 struct inet6_ifaddr *ifp;
2135 struct in6_addr addr; 2136 struct in6_addr addr;
2136 int create = 0, update_lft = 0; 2137 int create = 0, update_lft = 0;
2138 bool tokenized = false;
2137 2139
2138 if (pinfo->prefix_len == 64) { 2140 if (pinfo->prefix_len == 64) {
2139 memcpy(&addr, &pinfo->prefix, 8); 2141 memcpy(&addr, &pinfo->prefix, 8);
@@ -2143,6 +2145,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
2143 memcpy(addr.s6_addr + 8, 2145 memcpy(addr.s6_addr + 8,
2144 in6_dev->token.s6_addr + 8, 8); 2146 in6_dev->token.s6_addr + 8, 8);
2145 read_unlock_bh(&in6_dev->lock); 2147 read_unlock_bh(&in6_dev->lock);
2148 tokenized = true;
2146 } else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) && 2149 } else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
2147 ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) { 2150 ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
2148 in6_dev_put(in6_dev); 2151 in6_dev_put(in6_dev);
@@ -2185,6 +2188,7 @@ ok:
2185 2188
2186 update_lft = create = 1; 2189 update_lft = create = 1;
2187 ifp->cstamp = jiffies; 2190 ifp->cstamp = jiffies;
2191 ifp->tokenized = tokenized;
2188 addrconf_dad_start(ifp); 2192 addrconf_dad_start(ifp);
2189 } 2193 }
2190 2194
@@ -4339,8 +4343,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
4339 /* Well, that's kinda nasty ... */ 4343 /* Well, that's kinda nasty ... */
4340 list_for_each_entry(ifp, &idev->addr_list, if_list) { 4344 list_for_each_entry(ifp, &idev->addr_list, if_list) {
4341 spin_lock(&ifp->lock); 4345 spin_lock(&ifp->lock);
4342 if (ipv6_addr_src_scope(&ifp->addr) == 4346 if (ifp->tokenized) {
4343 IPV6_ADDR_SCOPE_GLOBAL) {
4344 ifp->valid_lft = 0; 4347 ifp->valid_lft = 0;
4345 ifp->prefered_lft = 0; 4348 ifp->prefered_lft = 0;
4346 } 4349 }