Skip to content

Commit f37c605

Browse files
alexaringdavem330
authored andcommitted
addrconf: add functionality to check on rpl requirements
This patch adds a functionality to addrconf to check on a specific RPL address configuration. According to RFC 6554: To detect loops in the SRH, a router MUST determine if the SRH includes multiple addresses assigned to any interface on that router. If such addresses appear more than once and are separated by at least one address not assigned to that router. Signed-off-by: Alexander Aring <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent cfa933d commit f37c605

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

include/net/addrconf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
9090
int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
9191
#endif
9292

93+
int ipv6_chk_rpl_srh_loop(struct net *net, const struct in6_addr *segs,
94+
unsigned char nsegs);
95+
9396
bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
9497
const unsigned int prefix_len,
9598
struct net_device *dev);

net/ipv6/addrconf.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4398,6 +4398,59 @@ int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
43984398
}
43994399
#endif
44004400

4401+
/* RFC6554 has some algorithm to avoid loops in segment routing by
4402+
* checking if the segments contains any of a local interface address.
4403+
*
4404+
* Quote:
4405+
*
4406+
* To detect loops in the SRH, a router MUST determine if the SRH
4407+
* includes multiple addresses assigned to any interface on that router.
4408+
* If such addresses appear more than once and are separated by at least
4409+
* one address not assigned to that router.
4410+
*/
4411+
int ipv6_chk_rpl_srh_loop(struct net *net, const struct in6_addr *segs,
4412+
unsigned char nsegs)
4413+
{
4414+
const struct in6_addr *addr;
4415+
int i, ret = 0, found = 0;
4416+
struct inet6_ifaddr *ifp;
4417+
bool separated = false;
4418+
unsigned int hash;
4419+
bool hash_found;
4420+
4421+
rcu_read_lock();
4422+
for (i = 0; i < nsegs; i++) {
4423+
addr = &segs[i];
4424+
hash = inet6_addr_hash(net, addr);
4425+
4426+
hash_found = false;
4427+
hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
4428+
if (!net_eq(dev_net(ifp->idev->dev), net))
4429+
continue;
4430+
4431+
if (ipv6_addr_equal(&ifp->addr, addr)) {
4432+
hash_found = true;
4433+
break;
4434+
}
4435+
}
4436+
4437+
if (hash_found) {
4438+
if (found > 1 && separated) {
4439+
ret = 1;
4440+
break;
4441+
}
4442+
4443+
separated = false;
4444+
found++;
4445+
} else {
4446+
separated = true;
4447+
}
4448+
}
4449+
rcu_read_unlock();
4450+
4451+
return ret;
4452+
}
4453+
44014454
/*
44024455
* Periodic address status verification
44034456
*/

0 commit comments

Comments
 (0)