Heads up --- Thinking about UDP and tunneling

Randall Stewart rrs at lakerest.net
Fri Dec 12 05:46:32 PST 2008


Ok:

Here is an updated patch it:

1) Fixes style9 issues (I hope.. I went back to vi and tried  
tabs :-0.. sigh one of
    these doys I will figure out why my .emacs settings just never cut  
it :-()
2) move to _t typedef
3) Allow multicast/broadcast to also be tunneled.
4) Binding is now no longer a requirement to set tunneling mode, in  
fact most
    protocols had better NOT have bound.. first set options, then  
bind :-)

There was one thing I was a bit leary of for <3>. In the loop for
going through all the inp's of UDP that are listening to a m-cast/b-cast
I could not release the INP_INFO_LOCK() in other cases I make sure all
locks are released when we call into the tunneling protocol. I think  
this
will be ok as long as the tunnelee does not try to use the  
INP_INFO_LOCK of
the UDP world... I know for SCTP this is a non-issue.. but it may be  
something
we want to think about... not sure.

If there are no serious objections I will submit this into head.. and  
followed behind it
I will send in the changes so SCTP can be tunneled over this new  
mechanism :-)

R

-------------- next part --------------
Index: netinet/udp_usrreq.c
===================================================================
--- netinet/udp_usrreq.c	(revision 185928)
+++ netinet/udp_usrreq.c	(working copy)
@@ -488,10 +488,25 @@
 				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 :-(
+					 */
+					udp_tunnel_function_t tunnel_func;
+
+					INP_RUNLOCK(last);
+					tunnel_func = (udp_tunnel_function_t)last->inp_ppcb;
+					INP_RUNLOCK(last);
+					tunnel_func(m, iphlen);
+				}
 			}
 			last = inp;
 			/*
@@ -516,10 +531,25 @@
 			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_function_t tunnel_func;
+
+			INP_RUNLOCK(last);
+			INP_INFO_RUNLOCK(&V_udbinfo);
+			tunnel_func = (udp_tunnel_function_t)last->inp_ppcb;
+			INP_RUNLOCK(last);
+			tunnel_func(m, iphlen);
+		}
 		return;
 	}
 
@@ -563,6 +593,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_function_t tunnel_func;
+		tunnel_func = (udp_tunnel_function_t)inp->inp_ppcb;
+		INP_RUNLOCK(inp);
+		tunnel_func(m, iphlen);
+		return;
+	}
 	udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in);
 	INP_RUNLOCK(inp);
 	return;
@@ -1138,10 +1180,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_function_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_function_t)(struct mbuf *, int off);
+int udp_set_kernel_tunneling(struct socket *so, udp_tunnel_function_t f);
 #endif
 
 #endif
Index: netinet6/udp6_usrreq.c
===================================================================
--- netinet6/udp6_usrreq.c	(revision 185928)
+++ netinet6/udp6_usrreq.c	(working copy)
@@ -286,9 +286,21 @@
 				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_function_t tunnel_func;
+						tunnel_func = (udp_tunnel_function_t)last->inp_ppcb;
+						INP_RUNLOCK(last);
+						tunnel_func(m, off);
+					} else {
+						INP_RLOCK(last);
+						udp6_append(last, n, off, &fromsa);
+						INP_RUNLOCK(last);
+					}	
 				}
 			}
 			last = inp;
@@ -317,6 +329,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_function_t tunnel_func;
+
+			tunnel_func = (udp_tunnel_function_t)inp->inp_ppcb;
+			INP_RUNLOCK(last);
+			tunnel_func(m, off);
+			return (IPPROTO_DONE);
+		}
 		udp6_append(last, m, off, &fromsa);
 		INP_RUNLOCK(last);
 		return (IPPROTO_DONE);
@@ -354,6 +379,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_function_t tunnel_func;
+		tunnel_func = (udp_tunnel_function_t)inp->inp_ppcb;
+		INP_RUNLOCK(inp);
+		tunnel_func(m, off);
+		return (IPPROTO_DONE);
+	}
 	udp6_append(inp, m, off, &fromsa);
 	INP_RUNLOCK(inp);
 	return (IPPROTO_DONE);
-------------- next part --------------



On Dec 11, 2008, at 1:11 PM, Bruce M. Simpson wrote:

> Hi,
>
> I am missing context of what Max's suggestion was, do you have a  
> reference to an old email thread?
>
> Style bugs:
> * needs style(9) and whitespace cleanup.
> * C typedefs should be suffixed with _t for consistency with other  
> kernel typedefs.
> * Function typedefs usually named like foo_func_t (see other  
> subsystems)
>
> Have you looked at m_apply() ? It already exists for stuff like this  
> i.e. functions which act on an mbuf chain, although it doesn't  
> necessarily expect chain heads.
>
> cheers
> BMS
>

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



More information about the freebsd-net mailing list