svn commit: r236034 - user/np/toe_iwarp/sys/netinet

Navdeep Parhar np at FreeBSD.org
Sat May 26 01:24:39 UTC 2012


Author: np
Date: Sat May 26 01:24:39 2012
New Revision: 236034
URL: http://svn.freebsd.org/changeset/base/236034

Log:
  Provide an opportunity to a TOE driver to install its hooks when
  expanding a syncache entry into a full socket.
  
  A couple of functions in toecore:
  * toe_connect_failed: to be called when an active open using a TOE
    device fails.
  * toe_4tuple_check: to check whether a 4-tuple is currently in use, and
    maybe release it if it's in TIME_WAIT and we have an incoming SYN for
    the 4-tuple.

Modified:
  user/np/toe_iwarp/sys/netinet/tcp_syncache.c
  user/np/toe_iwarp/sys/netinet/toecore.c
  user/np/toe_iwarp/sys/netinet/toecore.h

Modified: user/np/toe_iwarp/sys/netinet/tcp_syncache.c
==============================================================================
--- user/np/toe_iwarp/sys/netinet/tcp_syncache.c	Sat May 26 00:59:43 2012	(r236033)
+++ user/np/toe_iwarp/sys/netinet/tcp_syncache.c	Sat May 26 01:24:39 2012	(r236034)
@@ -858,6 +858,18 @@ syncache_socket(struct syncache *sc, str
 	if (sc->sc_rxmits > 1)
 		tp->snd_cwnd = tp->t_maxseg;
 
+#ifdef TCP_OFFLOAD
+	/*
+	 * Allow a TOE driver to install its hooks.  Note that we hold the
+	 * pcbinfo lock too and that prevents tcp_usr_accept from accepting a
+	 * new connection before the TOE driver has done its thing.
+	 */
+	if (ADDED_BY_TOE(sc)) {
+		struct toedev *tod = sc->sc_tod;
+
+		tod->tod_offload_socket(tod, sc->sc_todctx, so);
+	}
+#endif
 	/*
 	 * Copy and activate timers.
 	 */

Modified: user/np/toe_iwarp/sys/netinet/toecore.c
==============================================================================
--- user/np/toe_iwarp/sys/netinet/toecore.c	Sat May 26 00:59:43 2012	(r236033)
+++ user/np/toe_iwarp/sys/netinet/toecore.c	Sat May 26 01:24:39 2012	(r236034)
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #define TCPSTATES
 #include <netinet/tcp.h>
 #include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
 #include <netinet/tcp_var.h>
 #include <netinet/tcp_syncache.h>
 #include <netinet/tcp_offload.h>
@@ -154,6 +155,14 @@ toedev_syncache_respond(struct toedev *t
 }
 
 static void
+toedev_offload_socket(struct toedev *tod __unused, void *ctx __unused,
+    struct socket *so __unused)
+{
+
+	return;
+}
+
+static void
 toedev_ctloutput(struct toedev *tod __unused, struct tcpcb *tp __unused,
     int sopt_dir __unused, int sopt_name __unused)
 {
@@ -247,6 +256,7 @@ init_toedev(struct toedev *tod)
 	tod->tod_syncache_added = toedev_syncache_added;
 	tod->tod_syncache_removed = toedev_syncache_removed;
 	tod->tod_syncache_respond = toedev_syncache_respond;
+	tod->tod_offload_socket = toedev_offload_socket;
 	tod->tod_ctloutput = toedev_ctloutput;
 }
 
@@ -324,6 +334,41 @@ toe_syncache_expand(struct in_conninfo *
 	return (syncache_expand(inc, to, th, lsop, NULL));
 }
 
+/*
+ * General purpose check to see if a 4-tuple is in use by the kernel.  If a TCP
+ * header (presumably for an incoming SYN) is also provided, an existing 4-tuple
+ * in TIME_WAIT may be assassinated freeing it up for re-use.
+ *
+ * Note that the TCP header must have been run through tcp_fields_to_host() or
+ * equivalent.
+ */
+int
+toe_4tuple_check(struct in_conninfo *inc, struct tcphdr *th, struct ifnet *ifp)
+{
+	struct inpcb *inp;
+
+	if (inc->inc_flags & INC_ISIPV6)
+		return (ENOSYS);	/* XXX: implement */
+
+	inp = in_pcblookup(&V_tcbinfo, inc->inc_faddr, inc->inc_fport,
+	    inc->inc_laddr, inc->inc_lport, INPLOOKUP_WLOCKPCB, ifp);
+	if (inp != NULL) {
+		INP_WLOCK_ASSERT(inp);
+
+		if ((inp->inp_flags & INP_TIMEWAIT) && th != NULL) {
+
+			INP_INFO_WLOCK_ASSERT(&V_tcbinfo); /* for twcheck */
+			if (!tcp_twcheck(inp, NULL, th, NULL, 0))
+				return (EADDRINUSE);
+		} else {
+			INP_WUNLOCK(inp);
+			return (EADDRINUSE);
+		}
+	}
+
+	return (0);
+}
+
 static void
 toe_lle_event(void *arg __unused, struct llentry *lle, int evt)
 {
@@ -417,6 +462,41 @@ toe_l2_resolve(struct toedev *tod, struc
 	return (rc);
 }
 
+void
+toe_connect_failed(struct toedev *tod, struct tcpcb *tp, int err)
+{
+	struct inpcb *inp = tp->t_inpcb;
+
+	INP_WLOCK_ASSERT(inp);
+	KASSERT(tp->t_flags & TF_TOE,
+	    ("%s: tp %p not offloaded.", __func__, tp));
+
+	if (!(inp->inp_flags & INP_DROPPED)) {
+		if (err == EAGAIN) {
+
+			/*
+			 * Temporary failure during offload, take this PCB back.
+			 * Detach from the TOE driver and do the rest of what
+			 * TCP's pru_connect would have done if the connection
+			 * wasn't offloaded.
+			 */
+
+			tod->tod_pcb_detach(tod, tp);
+			KASSERT(!(tp->t_flags & TF_TOE),
+			    ("%s: tp %p still offloaded.", __func__, tp));
+			tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
+			(void) tcp_output(tp);
+		} else {
+
+			INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+			tp = tcp_drop(tp, err);
+			if (tp == NULL)
+				INP_WLOCK(inp);	/* re-acquire */
+		}
+	}
+	INP_WLOCK_ASSERT(inp);
+}
+
 static int
 toecore_load(void)
 {

Modified: user/np/toe_iwarp/sys/netinet/toecore.h
==============================================================================
--- user/np/toe_iwarp/sys/netinet/toecore.h	Sat May 26 00:59:43 2012	(r236033)
+++ user/np/toe_iwarp/sys/netinet/toecore.h	Sat May 26 01:24:39 2012	(r236034)
@@ -80,6 +80,7 @@ struct toedev {
 	void (*tod_syncache_added)(struct toedev *, void *);
 	void (*tod_syncache_removed)(struct toedev *, void *);
 	int (*tod_syncache_respond)(struct toedev *, void *, struct mbuf *);
+	void (*tod_offload_socket)(struct toedev *, void *, struct socket *);
 
 	/* TCP socket option */
 	void (*tod_ctloutput)(struct toedev *, struct tcpcb *, int, int);
@@ -105,8 +106,12 @@ int  unregister_toedev(struct toedev *);
 int toe_l2_resolve(struct toedev *, struct ifnet *, struct sockaddr *,
     uint8_t *, uint16_t *);
 
+void toe_connect_failed(struct toedev *, struct tcpcb *, int);
+
 void toe_syncache_add(struct in_conninfo *, struct tcpopt *, struct tcphdr *,
     struct inpcb *, void *, void *);
 int  toe_syncache_expand(struct in_conninfo *, struct tcpopt *, struct tcphdr *,
     struct socket **);
+
+int toe_4tuple_check(struct in_conninfo *, struct tcphdr *, struct ifnet *);
 #endif


More information about the svn-src-user mailing list