* [PATCH net-next] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
@ 2015-07-10 6:50 YOSHIFUJI Hideaki/吉藤英明
2015-07-10 7:19 ` Erik Kline
0 siblings, 1 reply; 3+ messages in thread
From: YOSHIFUJI Hideaki/吉藤英明 @ 2015-07-10 6:50 UTC (permalink / raw)
To: davem, netdev, ek
Cc: hannes, lorenzo,
YOSHIFUJI Hideaki/吉藤英明
If outgoing interface is specified and the candidate addresses
are restricted to the outgoing interface, it is enough to iterate
over that given interface only.
Signed-off-by: YOSHIFUJI Hideaki <hideaki.yoshifuji@miraclelinux.com>
---
net/ipv6/addrconf.c | 201 +++++++++++++++++++++++++++++-----------------------
1 file changed, 111 insertions(+), 90 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 21c2c81..b4c82d8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1358,15 +1358,94 @@ out:
return ret;
}
+static void __ipv6_dev_get_saddr(struct net *net,
+ struct ipv6_saddr_dst *dst,
+ unsigned int prefs,
+ const struct in6_addr *saddr,
+ struct inet6_dev *idev,
+ struct ipv6_saddr_score *scores)
+{
+ struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1];
+
+ read_lock_bh(&idev->lock);
+ list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
+ int i;
+
+ /*
+ * - Tentative Address (RFC2462 section 5.4)
+ * - A tentative address is not considered
+ * "assigned to an interface" in the traditional
+ * sense, unless it is also flagged as optimistic.
+ * - Candidate Source Address (section 4)
+ * - In any case, anycast addresses, multicast
+ * addresses, and the unspecified address MUST
+ * NOT be included in a candidate set.
+ */
+ if ((score->ifa->flags & IFA_F_TENTATIVE) &&
+ (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
+ continue;
+
+ score->addr_type = __ipv6_addr_type(&score->ifa->addr);
+
+ if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
+ score->addr_type & IPV6_ADDR_MULTICAST)) {
+ net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s",
+ idev->dev->name);
+ continue;
+ }
+
+ score->rule = -1;
+ bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
+
+ for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
+ int minihiscore, miniscore;
+
+ minihiscore = ipv6_get_saddr_eval(net, hiscore, dst, i);
+ miniscore = ipv6_get_saddr_eval(net, score, dst, i);
+
+ if (minihiscore > miniscore) {
+ if (i == IPV6_SADDR_RULE_SCOPE &&
+ score->scopedist > 0) {
+ /*
+ * special case:
+ * each remaining entry
+ * has too small (not enough)
+ * scope, because ifa entries
+ * are sorted by their scope
+ * values.
+ */
+ goto out;
+ }
+ break;
+ } else if (minihiscore < miniscore) {
+ if (hiscore->ifa)
+ in6_ifa_put(hiscore->ifa);
+
+ in6_ifa_hold(score->ifa);
+
+ swap(hiscore, score);
+
+ /* restore our iterator */
+ score->ifa = hiscore->ifa;
+
+ break;
+ }
+ }
+ }
+out:
+ read_unlock_bh(&idev->lock);
+}
+
int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
const struct in6_addr *daddr, unsigned int prefs,
struct in6_addr *saddr)
{
- struct ipv6_saddr_score scores[2],
- *score = &scores[0], *hiscore = &scores[1];
+ struct ipv6_saddr_score scores[2], *hiscore = &scores[1];
struct ipv6_saddr_dst dst;
+ struct inet6_dev *idev;
struct net_device *dev;
int dst_type;
+ bool use_oif_addr = false;
dst_type = __ipv6_addr_type(daddr);
dst.addr = daddr;
@@ -1380,97 +1459,39 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
rcu_read_lock();
- for_each_netdev_rcu(net, dev) {
- struct inet6_dev *idev;
-
- /* Candidate Source Address (section 4)
- * - multicast and link-local destination address,
- * the set of candidate source address MUST only
- * include addresses assigned to interfaces
- * belonging to the same link as the outgoing
- * interface.
- * (- For site-local destination addresses, the
- * set of candidate source addresses MUST only
- * include addresses assigned to interfaces
- * belonging to the same site as the outgoing
- * interface.)
- */
- if (((dst_type & IPV6_ADDR_MULTICAST) ||
- dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
- dst.ifindex && dev->ifindex != dst.ifindex)
- continue;
-
- idev = __in6_dev_get(dev);
- if (!idev)
- continue;
-
- read_lock_bh(&idev->lock);
- list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
- int i;
-
- /*
- * - Tentative Address (RFC2462 section 5.4)
- * - A tentative address is not considered
- * "assigned to an interface" in the traditional
- * sense, unless it is also flagged as optimistic.
- * - Candidate Source Address (section 4)
- * - In any case, anycast addresses, multicast
- * addresses, and the unspecified address MUST
- * NOT be included in a candidate set.
- */
- if ((score->ifa->flags & IFA_F_TENTATIVE) &&
- (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
- continue;
-
- score->addr_type = __ipv6_addr_type(&score->ifa->addr);
+ /* Candidate Source Address (section 4)
+ * - multicast and link-local destination address,
+ * the set of candidate source address MUST only
+ * include addresses assigned to interfaces
+ * belonging to the same link as the outgoing
+ * interface.
+ * (- For site-local destination addresses, the
+ * set of candidate source addresses MUST only
+ * include addresses assigned to interfaces
+ * belonging to the same site as the outgoing
+ * interface.)
+ * - "It is RECOMMENDED that the candidate source addresses
+ * be the set of unicast addresses assigned to the
+ * interface that will be used to send to the destination
+ * (the 'outgoing' interface)." (RFC 6724)
+ */
+ if (dst_dev) {
+ if ((dst_type & IPV6_ADDR_MULTICAST) ||
+ dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) {
+ idev = __in6_dev_get(dst_dev);
+ use_oif_addr = true;
+ }
+ }
- if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
- score->addr_type & IPV6_ADDR_MULTICAST)) {
- net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s",
- dev->name);
+ if (use_oif_addr) {
+ __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
+ } else {
+ for_each_netdev_rcu(net, dev) {
+ idev = __in6_dev_get(dev);
+ if (!idev)
continue;
- }
-
- score->rule = -1;
- bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
-
- for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
- int minihiscore, miniscore;
-
- minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i);
- miniscore = ipv6_get_saddr_eval(net, score, &dst, i);
-
- if (minihiscore > miniscore) {
- if (i == IPV6_SADDR_RULE_SCOPE &&
- score->scopedist > 0) {
- /*
- * special case:
- * each remaining entry
- * has too small (not enough)
- * scope, because ifa entries
- * are sorted by their scope
- * values.
- */
- goto try_nextdev;
- }
- break;
- } else if (minihiscore < miniscore) {
- if (hiscore->ifa)
- in6_ifa_put(hiscore->ifa);
-
- in6_ifa_hold(score->ifa);
-
- swap(hiscore, score);
-
- /* restore our iterator */
- score->ifa = hiscore->ifa;
-
- break;
- }
- }
+ __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
}
-try_nextdev:
- read_unlock_bh(&idev->lock);
}
rcu_read_unlock();
--
1.9.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net-next] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
2015-07-10 6:50 [PATCH net-next] ipv6: Do not iterate over all interfaces when finding source address on specific interface YOSHIFUJI Hideaki/吉藤英明
@ 2015-07-10 7:19 ` Erik Kline
2015-07-10 7:31 ` YOSHIFUJI Hideaki
0 siblings, 1 reply; 3+ messages in thread
From: Erik Kline @ 2015-07-10 7:19 UTC (permalink / raw)
To: YOSHIFUJI Hideaki/吉藤英明
Cc: David Miller, netdev, Hannes Frederic Sowa, Lorenzo Colitti
On 10 July 2015 at 15:50, YOSHIFUJI Hideaki/吉藤英明
<hideaki.yoshifuji@miraclelinux.com> wrote:
> If outgoing interface is specified and the candidate addresses
> are restricted to the outgoing interface, it is enough to iterate
> over that given interface only.
>
> Signed-off-by: YOSHIFUJI Hideaki <hideaki.yoshifuji@miraclelinux.com>
> ---
> net/ipv6/addrconf.c | 201 +++++++++++++++++++++++++++++-----------------------
> 1 file changed, 111 insertions(+), 90 deletions(-)
>
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 21c2c81..b4c82d8 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -1358,15 +1358,94 @@ out:
> return ret;
> }
>
> +static void __ipv6_dev_get_saddr(struct net *net,
> + struct ipv6_saddr_dst *dst,
> + unsigned int prefs,
> + const struct in6_addr *saddr,
> + struct inet6_dev *idev,
> + struct ipv6_saddr_score *scores)
> +{
> + struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1];
> +
> + read_lock_bh(&idev->lock);
> + list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
> + int i;
> +
> + /*
> + * - Tentative Address (RFC2462 section 5.4)
> + * - A tentative address is not considered
> + * "assigned to an interface" in the traditional
> + * sense, unless it is also flagged as optimistic.
> + * - Candidate Source Address (section 4)
> + * - In any case, anycast addresses, multicast
> + * addresses, and the unspecified address MUST
> + * NOT be included in a candidate set.
> + */
> + if ((score->ifa->flags & IFA_F_TENTATIVE) &&
> + (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
> + continue;
> +
> + score->addr_type = __ipv6_addr_type(&score->ifa->addr);
> +
> + if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
> + score->addr_type & IPV6_ADDR_MULTICAST)) {
> + net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s",
> + idev->dev->name);
> + continue;
> + }
> +
> + score->rule = -1;
> + bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
> +
> + for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
> + int minihiscore, miniscore;
> +
> + minihiscore = ipv6_get_saddr_eval(net, hiscore, dst, i);
> + miniscore = ipv6_get_saddr_eval(net, score, dst, i);
> +
> + if (minihiscore > miniscore) {
> + if (i == IPV6_SADDR_RULE_SCOPE &&
> + score->scopedist > 0) {
> + /*
> + * special case:
> + * each remaining entry
> + * has too small (not enough)
> + * scope, because ifa entries
> + * are sorted by their scope
> + * values.
> + */
> + goto out;
> + }
> + break;
> + } else if (minihiscore < miniscore) {
> + if (hiscore->ifa)
> + in6_ifa_put(hiscore->ifa);
> +
> + in6_ifa_hold(score->ifa);
> +
> + swap(hiscore, score);
> +
> + /* restore our iterator */
> + score->ifa = hiscore->ifa;
> +
> + break;
> + }
> + }
> + }
> +out:
> + read_unlock_bh(&idev->lock);
> +}
> +
> int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
> const struct in6_addr *daddr, unsigned int prefs,
> struct in6_addr *saddr)
> {
> - struct ipv6_saddr_score scores[2],
> - *score = &scores[0], *hiscore = &scores[1];
> + struct ipv6_saddr_score scores[2], *hiscore = &scores[1];
> struct ipv6_saddr_dst dst;
> + struct inet6_dev *idev;
> struct net_device *dev;
> int dst_type;
> + bool use_oif_addr = false;
>
> dst_type = __ipv6_addr_type(daddr);
> dst.addr = daddr;
> @@ -1380,97 +1459,39 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
>
> rcu_read_lock();
>
> - for_each_netdev_rcu(net, dev) {
> - struct inet6_dev *idev;
> -
> - /* Candidate Source Address (section 4)
> - * - multicast and link-local destination address,
> - * the set of candidate source address MUST only
> - * include addresses assigned to interfaces
> - * belonging to the same link as the outgoing
> - * interface.
> - * (- For site-local destination addresses, the
> - * set of candidate source addresses MUST only
> - * include addresses assigned to interfaces
> - * belonging to the same site as the outgoing
> - * interface.)
> - */
> - if (((dst_type & IPV6_ADDR_MULTICAST) ||
> - dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
> - dst.ifindex && dev->ifindex != dst.ifindex)
> - continue;
> -
> - idev = __in6_dev_get(dev);
> - if (!idev)
> - continue;
> -
> - read_lock_bh(&idev->lock);
> - list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
> - int i;
> -
> - /*
> - * - Tentative Address (RFC2462 section 5.4)
> - * - A tentative address is not considered
> - * "assigned to an interface" in the traditional
> - * sense, unless it is also flagged as optimistic.
> - * - Candidate Source Address (section 4)
> - * - In any case, anycast addresses, multicast
> - * addresses, and the unspecified address MUST
> - * NOT be included in a candidate set.
> - */
> - if ((score->ifa->flags & IFA_F_TENTATIVE) &&
> - (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
> - continue;
> -
> - score->addr_type = __ipv6_addr_type(&score->ifa->addr);
> + /* Candidate Source Address (section 4)
> + * - multicast and link-local destination address,
> + * the set of candidate source address MUST only
> + * include addresses assigned to interfaces
> + * belonging to the same link as the outgoing
> + * interface.
> + * (- For site-local destination addresses, the
> + * set of candidate source addresses MUST only
> + * include addresses assigned to interfaces
> + * belonging to the same site as the outgoing
> + * interface.)
> + * - "It is RECOMMENDED that the candidate source addresses
> + * be the set of unicast addresses assigned to the
> + * interface that will be used to send to the destination
> + * (the 'outgoing' interface)." (RFC 6724)
> + */
> + if (dst_dev) {
> + if ((dst_type & IPV6_ADDR_MULTICAST) ||
> + dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) {
> + idev = __in6_dev_get(dst_dev);
> + use_oif_addr = true;
> + }
> + }
>
> - if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
> - score->addr_type & IPV6_ADDR_MULTICAST)) {
> - net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s",
> - dev->name);
> + if (use_oif_addr) {
> + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
> + } else {
> + for_each_netdev_rcu(net, dev) {
> + idev = __in6_dev_get(dev);
> + if (!idev)
> continue;
> - }
> -
> - score->rule = -1;
> - bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
> -
> - for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
> - int minihiscore, miniscore;
> -
> - minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i);
> - miniscore = ipv6_get_saddr_eval(net, score, &dst, i);
> -
> - if (minihiscore > miniscore) {
> - if (i == IPV6_SADDR_RULE_SCOPE &&
> - score->scopedist > 0) {
> - /*
> - * special case:
> - * each remaining entry
> - * has too small (not enough)
> - * scope, because ifa entries
> - * are sorted by their scope
> - * values.
> - */
> - goto try_nextdev;
> - }
> - break;
> - } else if (minihiscore < miniscore) {
> - if (hiscore->ifa)
> - in6_ifa_put(hiscore->ifa);
> -
> - in6_ifa_hold(score->ifa);
> -
> - swap(hiscore, score);
> -
> - /* restore our iterator */
> - score->ifa = hiscore->ifa;
> -
> - break;
> - }
> - }
> + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
> }
> -try_nextdev:
> - read_unlock_bh(&idev->lock);
> }
> rcu_read_unlock();
>
> --
> 1.9.1
>
LGTM, and thanks again.
Acked-by: Erik Kline <ek@google.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net-next] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
2015-07-10 7:19 ` Erik Kline
@ 2015-07-10 7:31 ` YOSHIFUJI Hideaki
0 siblings, 0 replies; 3+ messages in thread
From: YOSHIFUJI Hideaki @ 2015-07-10 7:31 UTC (permalink / raw)
To: Erik Kline
Cc: hideaki.yoshifuji, David Miller, netdev, Hannes Frederic Sowa,
Lorenzo Colitti
Hi,
Erik Kline wrote:
>> + /* Candidate Source Address (section 4)
>> + * - multicast and link-local destination address,
>> + * the set of candidate source address MUST only
>> + * include addresses assigned to interfaces
>> + * belonging to the same link as the outgoing
>> + * interface.
>> + * (- For site-local destination addresses, the
>> + * set of candidate source addresses MUST only
>> + * include addresses assigned to interfaces
>> + * belonging to the same site as the outgoing
>> + * interface.)
>> + * - "It is RECOMMENDED that the candidate source addresses
>> + * be the set of unicast addresses assigned to the
>> + * interface that will be used to send to the destination
>> + * (the 'outgoing' interface)." (RFC 6724)
>> + */
Sorry, I forgot to remove 3rd one, which should be removed for now; I'll
resubmit.
--
Hideaki Yoshifuji <hideaki.yoshifuji@miraclelinux.com>
Technical Division, MIRACLE LINUX CORPORATION
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-07-10 7:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-10 6:50 [PATCH net-next] ipv6: Do not iterate over all interfaces when finding source address on specific interface YOSHIFUJI Hideaki/吉藤英明
2015-07-10 7:19 ` Erik Kline
2015-07-10 7:31 ` YOSHIFUJI Hideaki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).