Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Dec 2008 10:29:39 -0500
From:      Randall Stewart <rrs@lakerest.net>
To:        freebsd-net <freebsd-net@freebsd.org>
Cc:        Max Laier <max@love2party.net>
Subject:   Re: Heads up ---  Thinking about UDP and tunneling
Message-ID:  <4A152664-B170-4C6C-85C1-58E2E1577CA3@lakerest.net>
In-Reply-To: <200812132030.15665.max@love2party.net>
References:  <D72E9703-C8E7-4A21-A71E-A4B4C2D7E8F4@lakerest.net> <494157DF.6030802@FreeBSD.org> <13C9478E-CBF6-4EDA-8E78-AD76549EB844@lakerest.net> <200812132030.15665.max@love2party.net>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail-9-483392564
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed;
	delsp=yes
Content-Transfer-Encoding: 7bit

All:

Ok here is the latest... this:

1) Incorporates Matt's changes
2) Goes with Matt's idea of adding an INP.
3) We now are holding the INP lock across the
    call to the tunnel as well as the append. Since
    the caller will have the INP they can unlock
    if they need to :-)

4) revamped my s9indent use.. I ran it and then patched back
    in just its complaints about me... that way the other s9 issues
    can stay in the file untouched by me :-D

Note to Sam, I did not make the base code use the function.. since I
thought it got a bit tricky when one started having to worry about
sockaddr's being passed to the function AND the typing there of...
So I deferred that until later .. :-)

I will wait tell all the criticisms settle down and commit eventually  
here :)

R


--Apple-Mail-9-483392564
Content-Disposition: attachment;
	filename=latest_udp_diff.txt
Content-Type: text/plain;
	x-unix-mode=0644;
	name="latest_udp_diff.txt"
Content-Transfer-Encoding: 7bit

Index: netinet/udp_usrreq.c
===================================================================
--- netinet/udp_usrreq.c	(revision 185928)
+++ netinet/udp_usrreq.c	(working copy)
@@ -488,41 +488,76 @@
 				struct mbuf *n;
 
 				n = m_copy(m, 0, M_COPYALL);
-				if (n != NULL)
-					udp_append(last, ip, n, iphlen +
-					    sizeof(struct udphdr), &udp_in);
-				INP_RUNLOCK(last);
+
+				if (last->inp_ppcb == NULL) {
+					if (n != NULL)
+						udp_append(last, ip, n, iphlen +
+						    sizeof(struct udphdr), &udp_in);
+					INP_RUNLOCK(last);
+				} else {
+					/*
+					 * Engage the tunneling protocol we
+					 * will have to leave the info_lock
+					 * up, since we are hunting through
+					 * multiple UDP inp's hope we don't
+					 * break :-(
+					 * 
+					 * XXXML: Maybe add a flag to the
+					 * prototype so that the tunneling
+					 * can defer work that can't be done
+					 * under the info lock?
+					 */
+					udp_tunnel_func_t tunnel_func;
+
+					tunnel_func = (udp_tunnel_func_t) last->inp_ppcb;
+					tunnel_func(m, iphlen, last);
+					INP_RUNLOCK(last);
+				}
 			}
 			last = inp;
 			/*
-			 * Don't look for additional matches if this one does
-			 * not have either the SO_REUSEPORT or SO_REUSEADDR
-			 * socket options set.  This heuristic avoids
-			 * searching through all pcbs in the common case of a
-			 * non-shared port.  It assumes that an application
-			 * will never clear these options after setting them.
+			 * Don't look for additional matches if this one
+			 * does not have either the SO_REUSEPORT or
+			 * SO_REUSEADDR socket options set.  This heuristic
+			 * avoids searching through all pcbs in the common
+			 * case of a non-shared port.  It assumes that an
+			 * application will never clear these options after
+			 * setting them.
 			 */
 			if ((last->inp_socket->so_options &
-			    (SO_REUSEPORT|SO_REUSEADDR)) == 0)
+			    (SO_REUSEPORT | SO_REUSEADDR)) == 0)
 				break;
 		}
 
 		if (last == NULL) {
 			/*
-			 * No matching pcb found; discard datagram.  (No need
-			 * to send an ICMP Port Unreachable for a broadcast
-			 * or multicast datgram.)
+			 * No matching pcb found; discard datagram.  (No
+			 * need to send an ICMP Port Unreachable for a
+			 * broadcast or multicast datgram.)
 			 */
 			V_udpstat.udps_noportbcast++;
 			goto badheadlocked;
 		}
-		udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
-		    &udp_in);
-		INP_RUNLOCK(last);
-		INP_INFO_RUNLOCK(&V_udbinfo);
+		if (last->inp_ppcb == NULL) {
+			udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
+			    &udp_in);
+			INP_RUNLOCK(last);
+			INP_INFO_RUNLOCK(&V_udbinfo);
+		} else {
+			/*
+			 * Engage the tunneling protocol we must make sure
+			 * all locks are released when we call the tunneling
+			 * protocol.
+			 */
+			udp_tunnel_func_t tunnel_func;
+
+			tunnel_func = (udp_tunnel_func_t) last->inp_ppcb;
+			tunnel_func(m, iphlen, last);
+			INP_RUNLOCK(last);
+			INP_INFO_RUNLOCK(&V_udbinfo);
+		}
 		return;
 	}
-
 	/*
 	 * Locate pcb for datagram.
 	 */
@@ -553,7 +588,6 @@
 		INP_INFO_RUNLOCK(&V_udbinfo);
 		return;
 	}
-
 	/*
 	 * Check the minimum TTL for socket.
 	 */
@@ -563,6 +597,18 @@
 		INP_RUNLOCK(inp);
 		goto badunlocked;
 	}
+	if (inp->inp_ppcb) {
+		/*
+		 * Engage the tunneling protocol we must make sure all locks
+		 * are released when we call the tunneling protocol.
+		 */
+		udp_tunnel_func_t tunnel_func;
+
+		tunnel_func = (udp_tunnel_func_t) inp->inp_ppcb;
+		tunnel_func(m, iphlen, inp);
+		INP_RUNLOCK(inp);
+		return;
+	}
 	udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in);
 	INP_RUNLOCK(inp);
 	return;
@@ -1138,10 +1184,41 @@
 	INP_INFO_WUNLOCK(&V_udbinfo);
 	inp->inp_vflag |= INP_IPV4;
 	inp->inp_ip_ttl = V_ip_defttl;
+	/*
+	 * UDP does not have a per-protocol
+	 * pcb (inp->inp_ppcb). We use this
+	 * pointer for kernel tunneling pointer.
+	 * If we ever need to have a protocol
+	 * block we will need to move this
+	 * function pointer there. Null
+	 * in this pointer means "do the normal
+	 * thing".
+	 */
+	inp->inp_ppcb = NULL;
 	INP_WUNLOCK(inp);
 	return (0);
 }
 
+int
+udp_set_kernel_tunneling(struct socket *so, udp_tunnel_func_t f)
+{
+	struct inpcb *inp;
+	inp = (struct inpcb *)so->so_pcb;
+
+	if (so->so_type != SOCK_DGRAM) {
+		/* Not UDP socket... sorry */
+		return (ENOTSUP);
+	}
+	if (inp == NULL) {
+		/* NULL INP? */
+		return (EINVAL);
+	}
+	INP_WLOCK(inp);
+	inp->inp_ppcb = f;
+	INP_WUNLOCK(inp);
+	return (0);
+}
+
 static int
 udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
Index: netinet/udp_var.h
===================================================================
--- netinet/udp_var.h	(revision 185928)
+++ netinet/udp_var.h	(working copy)
@@ -107,6 +107,10 @@
 void		 udp_input(struct mbuf *, int);
 struct inpcb	*udp_notify(struct inpcb *inp, int errno);
 int		 udp_shutdown(struct socket *so);
+
+
+typedef void(*udp_tunnel_func_t)(struct mbuf *, int off, struct inpcb *);
+int udp_set_kernel_tunneling(struct socket *so, udp_tunnel_func_t f);
 #endif
 
 #endif
Index: netinet6/udp6_usrreq.c
===================================================================
--- netinet6/udp6_usrreq.c	(revision 185928)
+++ netinet6/udp6_usrreq.c	(working copy)
@@ -262,54 +262,72 @@
 			if (inp->in6p_lport != uh->uh_dport)
 				continue;
 			/*
-			 * XXX: Do not check source port of incoming datagram
-			 * unless inp_connect() has been called to bind the
-			 * fport part of the 4-tuple; the source could be
-			 * trying to talk to us with an ephemeral port.
+			 * XXX: Do not check source port of incoming
+			 * datagram unless inp_connect() has been called to
+			 * bind the fport part of the 4-tuple; the source
+			 * could be trying to talk to us with an ephemeral
+			 * port.
 			 */
 			if (inp->inp_fport != 0 &&
 			    inp->inp_fport != uh->uh_sport)
 				continue;
 			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
 				if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
-							&ip6->ip6_dst))
+				    &ip6->ip6_dst))
 					continue;
 			}
 			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
 				if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
-							&ip6->ip6_src) ||
+				    &ip6->ip6_src) ||
 				    inp->in6p_fport != uh->uh_sport)
 					continue;
 			}
-
 			if (last != NULL) {
 				struct mbuf *n;
 
 				if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
 					INP_RLOCK(last);
-					udp6_append(last, n, off, &fromsa);
-					INP_RUNLOCK(last);
+					if (last->inp_ppcb) {
+						/*
+						 * Engage the tunneling
+						 * protocol we will have to
+						 * leave the info_lock up,
+						 * since we are hunting
+						 * through multiple UDP
+						 * inp's hope we don't break
+						 * :-(
+						 */
+						udp_tunnel_func_t tunnel_func;
+
+						tunnel_func = (udp_tunnel_func_t) last->inp_ppcb;
+						tunnel_func(m, off, last);
+						INP_RUNLOCK(last);
+					} else {
+						udp6_append(last, n, off, &fromsa);
+						INP_RUNLOCK(last);
+					}
 				}
 			}
 			last = inp;
 			/*
-			 * Don't look for additional matches if this one does
-			 * not have either the SO_REUSEPORT or SO_REUSEADDR
-			 * socket options set.  This heuristic avoids
-			 * searching through all pcbs in the common case of a
-			 * non-shared port.  It assumes that an application
-			 * will never clear these options after setting them.
+			 * Don't look for additional matches if this one
+			 * does not have either the SO_REUSEPORT or
+			 * SO_REUSEADDR socket options set.  This heuristic
+			 * avoids searching through all pcbs in the common
+			 * case of a non-shared port.  It assumes that an
+			 * application will never clear these options after
+			 * setting them.
 			 */
 			if ((last->inp_socket->so_options &
-			     (SO_REUSEPORT|SO_REUSEADDR)) == 0)
+			    (SO_REUSEPORT | SO_REUSEADDR)) == 0)
 				break;
 		}
 
 		if (last == NULL) {
 			/*
-			 * No matching pcb found; discard datagram.  (No need
-			 * to send an ICMP Port Unreachable for a broadcast
-			 * or multicast datgram.)
+			 * No matching pcb found; discard datagram.  (No
+			 * need to send an ICMP Port Unreachable for a
+			 * broadcast or multicast datgram.)
 			 */
 			V_udpstat.udps_noport++;
 			V_udpstat.udps_noportmcast++;
@@ -317,6 +335,19 @@
 		}
 		INP_RLOCK(last);
 		INP_INFO_RUNLOCK(&V_udbinfo);
+		if (last->inp_ppcb) {
+			/*
+			 * Engage the tunneling protocol we must make sure
+			 * all locks are released when we call the tunneling
+			 * protocol.
+			 */
+			udp_tunnel_func_t tunnel_func;
+
+			tunnel_func = (udp_tunnel_func_t) inp->inp_ppcb;
+			tunnel_func(m, off, last);
+			INP_RUNLOCK(last);
+			return (IPPROTO_DONE);
+		}
 		udp6_append(last, m, off, &fromsa);
 		INP_RUNLOCK(last);
 		return (IPPROTO_DONE);
@@ -354,6 +385,18 @@
 	}
 	INP_RLOCK(inp);
 	INP_INFO_RUNLOCK(&V_udbinfo);
+	if (inp->inp_ppcb) {
+		/*
+		 * Engage the tunneling protocol we must make sure all locks
+		 * are released when we call the tunneling protocol.
+		 */
+		udp_tunnel_func_t tunnel_func;
+
+		tunnel_func = (udp_tunnel_func_t) inp->inp_ppcb;
+		tunnel_func(m, off, inp);
+		INP_RUNLOCK(inp);
+		return (IPPROTO_DONE);
+	}
 	udp6_append(inp, m, off, &fromsa);
 	INP_RUNLOCK(inp);
 	return (IPPROTO_DONE);

--Apple-Mail-9-483392564
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed
Content-Transfer-Encoding: 7bit




------------------------------
Randall Stewart
803-317-4952 (cell)
803-345-0391(direct)


--Apple-Mail-9-483392564--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4A152664-B170-4C6C-85C1-58E2E1577CA3>