Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Jul 2015 10:53:43 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286003 - head/sys/netpfil/ipfw
Message-ID:  <201507291053.t6TArh5u085620@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Wed Jul 29 10:53:42 2015
New Revision: 286003
URL: https://svnweb.freebsd.org/changeset/base/286003

Log:
  Reduce overhead of ipfw's me6 opcode.
  
  Skip checks for IPv6 multicast addresses.
  Use in6_localip() for global unicast.
  And for IPv6 link-local addresses do search in the IPv6 addresses list.
  Since LLA are stored in the kernel internal form, use
  IN6_ARE_MASKED_ADDR_EQUAL() macro with lla_mask for addresses comparison.
  lla_mask has zero bits in the second word, where we keep sin6_scope_id.
  
  Obtained from:	Yandex LLC
  Sponsored by:	Yandex LLC

Modified:
  head/sys/netpfil/ipfw/ip_fw2.c

Modified: head/sys/netpfil/ipfw/ip_fw2.c
==============================================================================
--- head/sys/netpfil/ipfw/ip_fw2.c	Wed Jul 29 09:57:34 2015	(r286002)
+++ head/sys/netpfil/ipfw/ip_fw2.c	Wed Jul 29 10:53:42 2015	(r286003)
@@ -503,31 +503,35 @@ flow6id_match( int curr_flow, ipfw_insn_
 }
 
 /* support for IP6_*_ME opcodes */
+static const struct in6_addr lla_mask = {{{
+	0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+}}};
+
 static int
-search_ip6_addr_net (struct in6_addr * ip6_addr)
+ipfw_localip6(struct in6_addr *in6)
 {
-	struct ifnet *mdc;
-	struct ifaddr *mdc2;
-	struct in6_ifaddr *fdm;
-	struct in6_addr copia;
-
-	TAILQ_FOREACH(mdc, &V_ifnet, if_link) {
-		if_addr_rlock(mdc);
-		TAILQ_FOREACH(mdc2, &mdc->if_addrhead, ifa_link) {
-			if (mdc2->ifa_addr->sa_family == AF_INET6) {
-				fdm = (struct in6_ifaddr *)mdc2;
-				copia = fdm->ia_addr.sin6_addr;
-				/* need for leaving scope_id in the sock_addr */
-				in6_clearscope(&copia);
-				if (IN6_ARE_ADDR_EQUAL(ip6_addr, &copia)) {
-					if_addr_runlock(mdc);
-					return 1;
-				}
-			}
+	struct rm_priotracker in6_ifa_tracker;
+	struct in6_ifaddr *ia;
+
+	if (IN6_IS_ADDR_MULTICAST(in6))
+		return (0);
+
+	if (!IN6_IS_ADDR_LINKLOCAL(in6))
+		return (in6_localip(in6));
+
+	IN6_IFADDR_RLOCK(&in6_ifa_tracker);
+	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+		if (!IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr))
+			continue;
+		if (IN6_ARE_MASKED_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
+		    in6, &lla_mask)) {
+			IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
+			return (1);
 		}
-		if_addr_runlock(mdc);
 	}
-	return 0;
+	IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
+	return (0);
 }
 
 static int
@@ -1597,7 +1601,7 @@ do {								\
 #ifdef INET6
 				/* FALLTHROUGH */
 			case O_IP6_SRC_ME:
-				match= is_ipv6 && search_ip6_addr_net(&args->f_id.src_ip6);
+				match= is_ipv6 && ipfw_localip6(&args->f_id.src_ip6);
 #endif
 				break;
 
@@ -1636,7 +1640,7 @@ do {								\
 #ifdef INET6
 				/* FALLTHROUGH */
 			case O_IP6_DST_ME:
-				match= is_ipv6 && search_ip6_addr_net(&args->f_id.dst_ip6);
+				match= is_ipv6 && ipfw_localip6(&args->f_id.dst_ip6);
 #endif
 				break;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507291053.t6TArh5u085620>