summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2013-04-15 21:02:40 +0000
committerae <ae@FreeBSD.org>2013-04-15 21:02:40 +0000
commitdec8b563fa4d3dabcdc7025ece5f860cd8ad5ed5 (patch)
tree009f34b1729918ce4c376155c8e61ebd03f79a15 /sys/netinet6
parent7eee57bac27246cd0b3d6d7681964c9e5dbdd395 (diff)
downloadFreeBSD-src-dec8b563fa4d3dabcdc7025ece5f860cd8ad5ed5.zip
FreeBSD-src-dec8b563fa4d3dabcdc7025ece5f860cd8ad5ed5.tar.gz
The source address selection algorithm tries to apply several rules
for the set of IPv6 addresses. Now each attempt goes into IPv6 statistics, even if given rule did not won. Change this and take into account only those rules, that won. Also add accounting for cases, when algorithm fails to select an address.
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6_src.c17
1 files changed, 7 insertions, 10 deletions
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 2a46812..7a2c6bc 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -151,9 +151,7 @@ static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *);
* an entry to the caller for later use.
*/
#define REPLACE(r) do {\
- if ((r) < sizeof(V_ip6stat.ip6s_sources_rule) / \
- sizeof(V_ip6stat.ip6s_sources_rule[0])) /* check for safety */ \
- IP6STAT_INC(ip6s_sources_rule[(r)]); \
+ rule = (r); \
/* { \
char ip6buf[INET6_ADDRSTRLEN], ip6b[INET6_ADDRSTRLEN]; \
printf("in6_selectsrc: replace %s with %s by %d\n", ia_best ? ip6_sprintf(ip6buf, &ia_best->ia_addr.sin6_addr) : "none", ip6_sprintf(ip6b, &ia->ia_addr.sin6_addr), (r)); \
@@ -161,9 +159,6 @@ static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *);
goto replace; \
} while(0)
#define NEXT(r) do {\
- if ((r) < sizeof(V_ip6stat.ip6s_sources_rule) / \
- sizeof(V_ip6stat.ip6s_sources_rule[0])) /* check for safety */ \
- IP6STAT_INC(ip6s_sources_rule[(r)]); \
/* { \
char ip6buf[INET6_ADDRSTRLEN], ip6b[INET6_ADDRSTRLEN]; \
printf("in6_selectsrc: keep %s against %s by %d\n", ia_best ? ip6_sprintf(ip6buf, &ia_best->ia_addr.sin6_addr) : "none", ip6_sprintf(ip6b, &ia->ia_addr.sin6_addr), (r)); \
@@ -171,9 +166,7 @@ static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *);
goto next; /* XXX: we can't use 'continue' here */ \
} while(0)
#define BREAK(r) do { \
- if ((r) < sizeof(V_ip6stat.ip6s_sources_rule) / \
- sizeof(V_ip6stat.ip6s_sources_rule[0])) /* check for safety */ \
- IP6STAT_INC(ip6s_sources_rule[(r)]); \
+ rule = (r); \
goto out; /* XXX: we can't use 'break' here */ \
} while(0)
@@ -190,7 +183,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL;
u_int32_t odstzone;
int prefer_tempaddr;
- int error;
+ int error, rule;
struct ip6_moptions *mopts;
KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__));
@@ -306,6 +299,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if (error)
return (error);
+ rule = 0;
IN6_IFADDR_RLOCK();
TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
int new_scope = -1, new_matchlen = -1;
@@ -487,6 +481,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if ((ia = ia_best) == NULL) {
IN6_IFADDR_RUNLOCK();
+ IP6STAT_INC(ip6s_sources_none);
return (EADDRNOTAVAIL);
}
@@ -503,6 +498,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL &&
(inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) {
IN6_IFADDR_RUNLOCK();
+ IP6STAT_INC(ip6s_sources_none);
return (EADDRNOTAVAIL);
}
@@ -511,6 +507,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
bcopy(&tmp, srcp, sizeof(*srcp));
IN6_IFADDR_RUNLOCK();
+ IP6STAT_INC(ip6s_sources_rule[rule]);
return (0);
}
OpenPOWER on IntegriCloud