Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jun 2001 21:58:35 -0500 (CDT)
From:      Mike Silbersack <silby@silby.com>
To:        Bosko Milekic <bmilekic@technokratis.com>
Cc:        <freebsd-net@FreeBSD.ORG>
Subject:   Re: tcp template removal / scalability patch
Message-ID:  <20010621215417.K15327-200000@achilles.silby.com>
In-Reply-To: <20010619173424.A8399@technokratis.com>

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

[-- Attachment #1 --]

Ok, here's the updated tcp template removal patch.  It's functionally the
same, which is why I'm not including an updated -stable patch.  Also, I
did test it with IPv6, and it seems good.  No IPSEC testing, but I see no
reason why it would break if v4/v6 didn't.

What did change:

- Formatting all fixed (most of the problems were due to my hasty -stable
patch.  The -current patch was less quirky.)
- t_template has been replaced with unused in the tcpcb to make sure
nobody uses it accidently.  I renamed rather than removed it because
removal would probably break userland tools expecting the existing
structure.
- All t_templates = NULLs and checks to make sure it was null have been
removed.

I think it's ready for commit now, please review.

Thanks,

Mike "Silby" Silbersack


[-- Attachment #2 --]
diff -u -r netinet.old/tcp_input.c netinet/tcp_input.c
--- netinet.old/tcp_input.c	Mon Jun 18 20:45:07 2001
+++ netinet/tcp_input.c	Wed Jun 20 15:17:43 2001
@@ -1127,12 +1127,6 @@
 		}
 		FREE(sin, M_SONAME);
 	      }
-		tp->t_template = tcp_template(tp);
-		if (tp->t_template == 0) {
-			tp = tcp_drop(tp, ENOBUFS);
-			dropsocket = 0;		/* socket is already gone */
-			goto drop;
-		}
 		if ((taop = tcp_gettaocache(inp)) == NULL) {
 			taop = &tao_noncached;
 			bzero(taop, sizeof(*taop));
diff -u -r netinet.old/tcp_output.c netinet/tcp_output.c
--- netinet.old/tcp_output.c	Mon Jun 18 20:45:07 2001
+++ netinet/tcp_output.c	Thu Jun 21 21:37:57 2001
@@ -632,16 +632,11 @@
 		m->m_len = hdrlen;
 	}
 	m->m_pkthdr.rcvif = (struct ifnet *)0;
-	if (tp->t_template == 0)
-		panic("tcp_output");
 #ifdef INET6
 	if (isipv6) {
 		ip6 = mtod(m, struct ip6_hdr *);
 		th = (struct tcphdr *)(ip6 + 1);
-		bcopy((caddr_t)tp->t_template->tt_ipgen, (caddr_t)ip6,
-		      sizeof(struct ip6_hdr));
-		bcopy((caddr_t)&tp->t_template->tt_t, (caddr_t)th,
-		      sizeof(struct tcphdr));
+		tcp_fillheaders(tp, ip6, th);
 	} else
 #endif /* INET6 */
       {
@@ -649,10 +644,7 @@
 	ipov = (struct ipovly *)ip;
 	th = (struct tcphdr *)(ip + 1);
 	/* this picks up the pseudo header (w/o the length) */
-	bcopy((caddr_t)tp->t_template->tt_ipgen, (caddr_t)ip,
-	      sizeof(struct ip));
-	bcopy((caddr_t)&tp->t_template->tt_t, (caddr_t)th,
-	      sizeof(struct tcphdr));
+	tcp_fillheaders(tp, ip, th);
       }
 
 	/*
diff -u -r netinet.old/tcp_subr.c netinet/tcp_subr.c
--- netinet.old/tcp_subr.c	Mon Jun 18 20:45:07 2001
+++ netinet/tcp_subr.c	Thu Jun 21 21:43:39 2001
@@ -218,31 +218,24 @@
 }
 
 /*
- * Create template to be used to send tcp packets on a connection.
- * Call after host entry created, allocates an mbuf and fills
- * in a skeletal tcp/ip header, minimizing the amount of work
- * necessary when the connection is used.
+ * Fill in the IP and TCP headers for an outgoing packet, given the tcpcb.
+ * tcp_template used to store this data in mbufs, but we now recopy it out
+ * of the tcpcb each time to conserve mbufs.
  */
-struct tcptemp *
-tcp_template(tp)
+void
+tcp_fillheaders(tp, ip_ptr, tcp_ptr)
 	struct tcpcb *tp;
+	void *ip_ptr;
+	void *tcp_ptr;
 {
-	register struct inpcb *inp = tp->t_inpcb;
-	register struct mbuf *m;
-	register struct tcptemp *n;
+	struct inpcb *inp = tp->t_inpcb;
+	struct tcphdr *tcp_hdr = (struct tcphdr *)tcp_ptr;
 
-	if ((n = tp->t_template) == 0) {
-		m = m_get(M_DONTWAIT, MT_HEADER);
-		if (m == NULL)
-			return (0);
-		m->m_len = sizeof (struct tcptemp);
-		n = mtod(m, struct tcptemp *);
-	}
 #ifdef INET6
 	if ((inp->inp_vflag & INP_IPV6) != 0) {
-		register struct ip6_hdr *ip6;
+		struct ip6_hdr *ip6;
 
-		ip6 = (struct ip6_hdr *)n->tt_ipgen;
+		ip6 = (struct ip6_hdr *)ip_ptr;
 		ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
 			(inp->in6p_flowinfo & IPV6_FLOWINFO_MASK);
 		ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
@@ -251,29 +244,51 @@
 		ip6->ip6_plen = sizeof(struct tcphdr);
 		ip6->ip6_src = inp->in6p_laddr;
 		ip6->ip6_dst = inp->in6p_faddr;
-		n->tt_t.th_sum = 0;
+		tcp_hdr->th_sum = 0;
 	} else
 #endif
-      {
-	struct ip *ip = (struct ip *)n->tt_ipgen;
+	{
+	struct ip *ip = (struct ip *) ip_ptr;
 
-	bzero(ip, sizeof(struct ip));		/* XXX overkill? */
+	bzero(ip, sizeof(struct ip));           /* XXX overkill? */
 	ip->ip_vhl = IP_VHL_BORING;
 	ip->ip_p = IPPROTO_TCP;
 	ip->ip_src = inp->inp_laddr;
 	ip->ip_dst = inp->inp_faddr;
-	n->tt_t.th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
-	    htons(sizeof(struct tcphdr) + IPPROTO_TCP));
-      }
-	n->tt_t.th_sport = inp->inp_lport;
-	n->tt_t.th_dport = inp->inp_fport;
-	n->tt_t.th_seq = 0;
-	n->tt_t.th_ack = 0;
-	n->tt_t.th_x2 = 0;
-	n->tt_t.th_off = 5;
-	n->tt_t.th_flags = 0;
-	n->tt_t.th_win = 0;
-	n->tt_t.th_urp = 0;
+	tcp_hdr->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+		htons(sizeof(struct tcphdr) + IPPROTO_TCP));
+	}
+
+	tcp_hdr->th_sport = inp->inp_lport;
+	tcp_hdr->th_dport = inp->inp_fport;
+	tcp_hdr->th_seq = 0;
+	tcp_hdr->th_ack = 0;
+	tcp_hdr->th_x2 = 0;
+	tcp_hdr->th_off = 5;
+	tcp_hdr->th_flags = 0;
+	tcp_hdr->th_win = 0;
+	tcp_hdr->th_urp = 0;
+}
+
+/*
+ * Create template to be used to send tcp packets on a connection.
+ * Allocates an mbuf and fills in a skeletal tcp/ip header.  The only
+ * use for this function is in keepalives, which use tcp_respond.
+ */
+struct tcptemp *
+tcp_maketemplate(tp)
+	struct tcpcb *tp;
+{
+	struct mbuf *m;
+	struct tcptemp *n;
+
+	m = m_get(M_DONTWAIT, MT_HEADER);
+	if (m == NULL)
+		return (0);
+	m->m_len = sizeof(struct tcptemp);
+	n = mtod(m, struct tcptemp *);
+
+	tcp_fillheaders(tp, (void *)&n->tt_ipgen, (void *)&n->tt_t);
 	return (n);
 }
 
@@ -282,10 +297,9 @@
  * the given TCP/IP header.  If m == 0, then we make a copy
  * of the tcpiphdr at ti and send directly to the addressed host.
  * This is used to force keep alive messages out using the TCP
- * template for a connection tp->t_template.  If flags are given
- * then we send a message back to the TCP which originated the
- * segment ti, and discard the mbuf containing it and any other
- * attached mbufs.
+ * template for a connection.  If flags are given then we send
+ * a message back to the TCP which originated the * segment ti,
+ * and discard the mbuf containing it and any other attached mbufs.
  *
  * In any case the ack and sequence number of the transmitted
  * segment are as specified by the parameters.
@@ -701,8 +715,6 @@
 		m_freem(q->tqe_m);
 		FREE(q, M_TSEGQ);
 	}
-	if (tp->t_template)
-		(void) m_free(dtom(tp->t_template));
 	inp->inp_ppcb = NULL;
 	soisdisconnected(so);
 #ifdef INET6
@@ -1339,7 +1351,7 @@
 #endif /* INET6 */
 	struct tcphdr *th;
 
-	if (!tp || !tp->t_template || !(inp = tp->t_inpcb))
+	if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL))
 		return 0;
 	MGETHDR(m, M_DONTWAIT, MT_DATA);
 	if (!m)
@@ -1351,10 +1363,7 @@
 		th = (struct tcphdr *)(ip6 + 1);
 		m->m_pkthdr.len = m->m_len =
 			sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
-		bcopy((caddr_t)tp->t_template->tt_ipgen, (caddr_t)ip6,
-		      sizeof(struct ip6_hdr));
-		bcopy((caddr_t)&tp->t_template->tt_t, (caddr_t)th,
-		      sizeof(struct tcphdr));
+		tcp_fillheaders(tp, ip6, th);
 		hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
 	} else
 #endif /* INET6 */
@@ -1362,10 +1371,7 @@
 	ip = mtod(m, struct ip *);
 	th = (struct tcphdr *)(ip + 1);
 	m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr);
-	bcopy((caddr_t)tp->t_template->tt_ipgen, (caddr_t)ip,
-	      sizeof(struct ip));
-	bcopy((caddr_t)&tp->t_template->tt_t, (caddr_t)th,
-	      sizeof(struct tcphdr));
+	tcp_fillheaders(tp, ip, th);
 	ip->ip_vhl = IP_VHL_BORING;
 	hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
       }
Only in netinet.old/: tcp_subr.c.new
diff -u -r netinet.old/tcp_timer.c netinet/tcp_timer.c
--- netinet.old/tcp_timer.c	Mon Jun 18 20:45:07 2001
+++ netinet/tcp_timer.c	Thu Jun 21 21:43:59 2001
@@ -41,6 +41,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/mbuf.h>
 #include <sys/sysctl.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -222,6 +223,7 @@
 	void *xtp;
 {
 	struct tcpcb *tp = xtp;
+	struct tcptemp *t_template;
 	int s;
 #ifdef TCPDEBUG
 	int ostate;
@@ -259,9 +261,13 @@
 		 * correspondent TCP to respond.
 		 */
 		tcpstat.tcps_keepprobe++;
-		tcp_respond(tp, tp->t_template->tt_ipgen,
-			    &tp->t_template->tt_t, (struct mbuf *)NULL,
-			    tp->rcv_nxt, tp->snd_una - 1, 0);
+		t_template = tcp_maketemplate(tp);
+		if (t_template) {
+			tcp_respond(tp, t_template->tt_ipgen,
+				    &t_template->tt_t, (struct mbuf *)NULL,
+				    tp->rcv_nxt, tp->snd_una - 1, 0);
+			(void) m_free(dtom(t_template));
+		}
 		callout_reset(tp->tt_keep, tcp_keepintvl, tcp_timer_keep, tp);
 	} else
 		callout_reset(tp->tt_keep, tcp_keepidle, tcp_timer_keep, tp);
diff -u -r netinet.old/tcp_usrreq.c netinet/tcp_usrreq.c
--- netinet.old/tcp_usrreq.c	Mon Jun 18 20:45:07 2001
+++ netinet/tcp_usrreq.c	Wed Jun 20 15:18:33 2001
@@ -749,12 +749,6 @@
 	inp->inp_fport = sin->sin_port;
 	in_pcbrehash(inp);
 
-	tp->t_template = tcp_template(tp);
-	if (tp->t_template == 0) {
-		in_pcbdisconnect(inp);
-		return ENOBUFS;
-	}
-
 	/* Compute window scaling to request.  */
 	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
 	    (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
@@ -840,12 +834,6 @@
 	if ((sin6->sin6_flowinfo & IPV6_FLOWINFO_MASK) != NULL)
 		inp->in6p_flowinfo = sin6->sin6_flowinfo;
 	in_pcbrehash(inp);
-
-	tp->t_template = tcp_template(tp);
-	if (tp->t_template == 0) {
-		in6_pcbdisconnect(inp);
-		return ENOBUFS;
-	}
 
 	/* Compute window scaling to request.  */
 	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
diff -u -r netinet.old/tcp_var.h netinet/tcp_var.h
--- netinet.old/tcp_var.h	Mon Jun 18 20:45:07 2001
+++ netinet/tcp_var.h	Wed Jun 20 15:17:31 2001
@@ -66,7 +66,7 @@
 struct tcpcb {
 	struct	tsegqe_head t_segq;
 	int	t_dupacks;		/* consecutive dup acks recd */
-	struct	tcptemp	*t_template;	/* skeletal packet for transmit */
+	struct	tcptemp	*unused;	/* unused */
 
 	struct	callout *tt_rexmt;	/* retransmit timer */
 	struct	callout *tt_persist;	/* retransmit persistence */
@@ -400,7 +400,8 @@
 void	 tcp_setpersist __P((struct tcpcb *));
 void	 tcp_slowtimo __P((void));
 struct tcptemp *
-	 tcp_template __P((struct tcpcb *));
+	 tcp_maketemplate __P((struct tcpcb *));
+void	 tcp_fillheaders __P((struct tcpcb *, void *, void *));
 struct tcpcb *
 	 tcp_timers __P((struct tcpcb *, int));
 void	 tcp_trace __P((int, int, struct tcpcb *, void *, struct tcphdr *,

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