Skip to content

Commit 1ec047e

Browse files
strssndktndavem330
authored andcommitted
ipv6: introduce per-interface counter for dad-completed ipv6 addresses
To reduce the number of unnecessary router solicitations, MLDv2 and IGMPv3 messages we need to track the number of valid (as in non-optimistic, no-dad-failed and non-tentative) link-local addresses. Therefore, this patch implements a valid_ll_addr_cnt in struct inet6_dev. We now only emit router solicitations if the first link-local address finishes duplicate address detection. The changes for MLDv2 and IGMPv3 are in a follow-up patch. While there, also simplify one if statement(one minor nit I made in one of my previous patches): if (!...) do(); else return; <<into>> if (...) return; do(); Cc: Flavio Leitner <[email protected]> Cc: YOSHIFUJI Hideaki <[email protected]> Cc: David Stevens <[email protected]> Suggested-by: David Stevens <[email protected]> Signed-off-by: Hannes Frederic Sowa <[email protected]> Acked-by: Flavio Leitner <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ae0d675 commit 1ec047e

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

include/net/if_inet6.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ struct inet6_dev {
166166
struct net_device *dev;
167167

168168
struct list_head addr_list;
169+
int valid_ll_addr_cnt;
169170

170171
struct ifmcaddr6 *mc_list;
171172
struct ifmcaddr6 *mc_tomb;

net/ipv6/addrconf.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3277,6 +3277,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
32773277
{
32783278
struct net_device *dev = ifp->idev->dev;
32793279
struct in6_addr lladdr;
3280+
bool send_rs;
32803281

32813282
addrconf_del_dad_timer(ifp);
32823283

@@ -3290,20 +3291,25 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
32903291
router advertisements, start sending router solicitations.
32913292
*/
32923293

3293-
if (ipv6_accept_ra(ifp->idev) &&
3294-
ifp->idev->cnf.rtr_solicits > 0 &&
3295-
(dev->flags&IFF_LOOPBACK) == 0 &&
3296-
(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
3294+
read_lock_bh(&ifp->idev->lock);
3295+
spin_lock(&ifp->lock);
3296+
send_rs = ipv6_accept_ra(ifp->idev) &&
3297+
ifp->idev->cnf.rtr_solicits > 0 &&
3298+
(dev->flags&IFF_LOOPBACK) == 0 &&
3299+
ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL &&
3300+
ifp->idev->valid_ll_addr_cnt == 1;
3301+
spin_unlock(&ifp->lock);
3302+
read_unlock_bh(&ifp->idev->lock);
3303+
3304+
if (send_rs) {
32973305
/*
32983306
* If a host as already performed a random delay
32993307
* [...] as part of DAD [...] there is no need
33003308
* to delay again before sending the first RS
33013309
*/
3302-
if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
3303-
ndisc_send_rs(dev, &lladdr,
3304-
&in6addr_linklocal_allrouters);
3305-
else
3310+
if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
33063311
return;
3312+
ndisc_send_rs(dev, &lladdr, &in6addr_linklocal_allrouters);
33073313

33083314
write_lock_bh(&ifp->idev->lock);
33093315
spin_lock(&ifp->lock);
@@ -4576,6 +4582,19 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
45764582
rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
45774583
}
45784584

4585+
static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count)
4586+
{
4587+
write_lock_bh(&ifp->idev->lock);
4588+
spin_lock(&ifp->lock);
4589+
if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|
4590+
IFA_F_DADFAILED)) == IFA_F_PERMANENT) &&
4591+
(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL))
4592+
ifp->idev->valid_ll_addr_cnt += count;
4593+
WARN_ON(ifp->idev->valid_ll_addr_cnt < 0);
4594+
spin_unlock(&ifp->lock);
4595+
write_unlock_bh(&ifp->idev->lock);
4596+
}
4597+
45794598
static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
45804599
{
45814600
struct net *net = dev_net(ifp->idev->dev);
@@ -4584,6 +4603,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
45844603

45854604
switch (event) {
45864605
case RTM_NEWADDR:
4606+
update_valid_ll_addr_cnt(ifp, 1);
4607+
45874608
/*
45884609
* If the address was optimistic
45894610
* we inserted the route at the start of
@@ -4599,6 +4620,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
45994620
ifp->idev->dev, 0, 0);
46004621
break;
46014622
case RTM_DELADDR:
4623+
update_valid_ll_addr_cnt(ifp, -1);
4624+
46024625
if (ifp->idev->cnf.forwarding)
46034626
addrconf_leave_anycast(ifp);
46044627
addrconf_leave_solict(ifp->idev, &ifp->addr);

0 commit comments

Comments
 (0)