svn commit: r271456 - user/ae/inet6/sys/netinet6

Andrey V. Elsukov ae at FreeBSD.org
Fri Sep 12 08:35:13 UTC 2014


Author: ae
Date: Fri Sep 12 08:35:12 2014
New Revision: 271456
URL: http://svnweb.freebsd.org/changeset/base/271456

Log:
  Add some debugging to IPv6 source address selection algorithm code.

Modified:
  user/ae/inet6/sys/netinet6/in6_src.c

Modified: user/ae/inet6/sys/netinet6/in6_src.c
==============================================================================
--- user/ae/inet6/sys/netinet6/in6_src.c	Fri Sep 12 08:33:53 2014	(r271455)
+++ user/ae/inet6/sys/netinet6/in6_src.c	Fri Sep 12 08:35:12 2014	(r271456)
@@ -169,36 +169,74 @@ struct dstaddr_props {
 
 #define	REPLACE(r)	{ rule = r; goto replace; }
 #define	NEXT(r)		{ rule = r; goto next; }
+#ifndef IPV6SASDEBUG
+#define	IPV6SASDEBUG(fmt, ...)
+#else
+static char *srcrule_str[IP6S_RULESMAX] = {
+	"Rule 0: first candidate",
+	"Rule 1: prefer same address",
+	"Rule 2: prefer appropriate scope",
+	"Rule 3: avoid deprecated addresses",
+	"Rule 4: prefer home address",
+	"Rule 5: prefer outgoing interface",
+	"Rule 6: prefer matching label",
+	"Rule 7: prefer temporary addresses",
+	"Rule 8: prefer address with better virtual status",
+	"Rule 9: prefer address with `prefer_source' flag",
+	"Rule 10",
+	"Rule 11",
+	"Rule 12",
+	"Rule 13",
+	"Rule 14: use longest matching prefix",
+	"Rule 15"
+};
+#endif
 
 static int
 srcaddrcmp(struct srcaddr_choice *c, struct in6_ifaddr *ia,
     struct dstaddr_props *dst, struct ucred *cred,
     struct ip6_pktopts *opts)
 {
+#if defined(IPV6SASDEBUG)
+	char buf[INET6_ADDRSTRLEN];
+#endif
 	int srcscope, rule, label, prefer_tempaddr, prefixlen;
 
+	IPV6SASDEBUG("candidate address %s from interface %s",
+	    ip6_sprintf(buf, &ia->ia_addr.sin6_addr), ia->ia_ifp->if_xname);
 	/* Avoid unusable addresses */
 	if ((ia->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED)) ||
-	    (ia->ia_ifp->if_flags & IFF_UP) == 0)
+	    (ia->ia_ifp->if_flags & IFF_UP) == 0) {
+		IPV6SASDEBUG("address %s is unusable",
+		    ip6_sprintf(buf, &ia->ia_addr.sin6_addr));
 		return (-1);
+	}
 	/*
 	 * In any case, multicast addresses and the unspecified address
 	 * MUST NOT be included in a candidate set.
 	 */
 	if (IN6_IS_ADDR_MULTICAST(IA6_IN6(ia)) ||
-	    IN6_IS_ADDR_UNSPECIFIED(IA6_IN6(ia)))
+	    IN6_IS_ADDR_UNSPECIFIED(IA6_IN6(ia))) {
+		IPV6SASDEBUG("skip multicast and unspecified addresses");
 		return (-1);
-	if (!V_ip6_use_deprecated && IFA6_IS_DEPRECATED(ia))
+	}
+	if (!V_ip6_use_deprecated && IFA6_IS_DEPRECATED(ia)) {
+		IPV6SASDEBUG("skip deprecated addresses");
 		return (-1);
+	}
 	/* If jailed, only take addresses of the jail into account. */
-	if (cred != NULL && prison_check_ip6(cred, IA6_SIN6(ia)) != 0)
+	if (cred != NULL && prison_check_ip6(cred, IA6_SIN6(ia)) != 0) {
+		IPV6SASDEBUG("address is unusable from the jail");
 		return (-1);
+	}
 	/* Source address can not break the destination zone */
 	srcscope = in6_srcaddrscope(IA6_IN6(ia));
 	if (ia->ia_ifp != dst->ifp &&
 	    in6_getscopezone(ia->ia_ifp, srcscope) !=
-	    in6_getscopezone(dst->ifp, dst->scope))
+	    in6_getscopezone(dst->ifp, dst->scope)) {
+		IPV6SASDEBUG("scope zone mismatch");
 		return (-1);
+	}
 	label = ADDR_LABEL_NOTAPP;
 	prefixlen = -1;
 	/* Rule 1: Prefer same address. */
@@ -295,9 +333,11 @@ srcaddrcmp(struct srcaddr_choice *c, str
 		NEXT(14);
 	if (prefixlen > c->prefixlen)
 		REPLACE(14);
+	IPV6SASDEBUG("the algorithm failed to select an address");
 	return (-1);
 replace:
-	/* debug output */
+	IPV6SASDEBUG("address %s was selected according to the \"%s\"",
+	    ip6_sprintf(buf, &ia->ia_addr.sin6_addr), srcrule_str[rule]);
 	c->ia = ia;
 	c->label = label;
 	c->scope = srcscope;
@@ -307,7 +347,8 @@ replace:
 	IP6STAT_INC(ip6s_sources_rule[rule]);
 	return (rule);
 next:
-	/* debug output */
+	IPV6SASDEBUG("address %s was selected according to the \"%s\"",
+	    ip6_sprintf(buf, &c->ia->ia_addr.sin6_addr), srcrule_str[rule]);
 	return (rule);
 }
 #undef	REPLACE
@@ -455,6 +496,9 @@ in6_selectsrc(struct sockaddr_in6 *dst, 
     struct inpcb *inp, struct route_in6 *ro, struct ucred *cred,
     struct ifnet **ifpp, struct in6_addr *srcp)
 {
+#if defined(IPV6SASDEBUG)
+	char buf[INET6_ADDRSTRLEN];
+#endif
 	struct route_in6 ro6;
 	struct dstaddr_props dstprops;
 	struct srcaddr_choice best;
@@ -620,6 +664,8 @@ oif_found:
 	 * If the address is not specified, choose the best one based on
 	 * the outgoing interface and the destination address.
 	 */
+	IPV6SASDEBUG("dst %s, oif %s", ip6_sprintf(buf, &dst->sin6_addr),
+	    ifp->if_xname);
 	dstprops.ifp = ifp;
 	dstprops.addr = &dst->sin6_addr;
 	dstprops.scope = in6_srcaddrscope(&dst->sin6_addr);
@@ -633,6 +679,8 @@ oif_found:
 	 */
 	if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr) ||
 	    dstprops.scope == IPV6_ADDR_SCOPE_LINKLOCAL) {
+		IPV6SASDEBUG("use the addresses only from interface %s",
+		    ifp->if_xname);
 		IF_ADDR_RLOCK(ifp);
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 			if (ifa->ifa_addr->sa_family != AF_INET6)
@@ -657,6 +705,7 @@ oif_found:
 		IN6_IFADDR_RUNLOCK();
 	}
 	if (best.rule < 0) {
+		IPV6SASDEBUG("Failed to choose an address");
 		IP6STAT_INC(ip6s_sources_none);
 		if (ro == &ro6)
 			RO_RTFREE(ro);


More information about the svn-src-user mailing list