diff options
author | silby <silby@FreeBSD.org> | 2001-06-23 03:21:46 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2001-06-23 03:21:46 +0000 |
commit | f41767543e91978acb89276274f32fe6566ef613 (patch) | |
tree | 8d364d91b3427e5e39be4b2952a487aee0ba2a8c | |
parent | cb05fc6c2a8bdf494106b7b9b73e2a36ef37f0df (diff) | |
download | FreeBSD-src-f41767543e91978acb89276274f32fe6566ef613.zip FreeBSD-src-f41767543e91978acb89276274f32fe6566ef613.tar.gz |
Eliminate the allocation of a tcp template structure for each
connection. The information contained in a tcptemp can be
reconstructed from a tcpcb when needed.
Previously, tcp templates required the allocation of one
mbuf per connection. On large systems, this change should
free up a large number of mbufs.
Reviewed by: bmilekic, jlemon, ru
MFC after: 2 weeks
-rw-r--r-- | sys/netinet/tcp_input.c | 6 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 12 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 6 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 102 | ||||
-rw-r--r-- | sys/netinet/tcp_timer.c | 12 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 102 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 12 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 5 |
8 files changed, 122 insertions, 135 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 3554dae..225e682 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1127,12 +1127,6 @@ findpcb: } 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 --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index a2a2cf3..2740c72 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -632,16 +632,11 @@ send: 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 @@ send: 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 --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 3554dae..225e682 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -1127,12 +1127,6 @@ findpcb: } 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 --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 2782f70..331b6d5 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -218,31 +218,24 @@ tcp_init() } /* - * 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 @@ tcp_template(tp) 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? */ 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 @@ tcp_template(tp) * 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 @@ tcp_close(tp) 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 @@ ipsec_hdrsiz_tcp(tp) #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 @@ ipsec_hdrsiz_tcp(tp) 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 @@ ipsec_hdrsiz_tcp(tp) 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); } diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index a035989..488c293 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -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 @@ tcp_timer_keep(xtp) void *xtp; { struct tcpcb *tp = xtp; + struct tcptemp *t_template; int s; #ifdef TCPDEBUG int ostate; @@ -259,9 +261,13 @@ tcp_timer_keep(xtp) * 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 --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 2782f70..331b6d5 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -218,31 +218,24 @@ tcp_init() } /* - * 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 @@ tcp_template(tp) 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? */ 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 @@ tcp_template(tp) * 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 @@ tcp_close(tp) 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 @@ ipsec_hdrsiz_tcp(tp) #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 @@ ipsec_hdrsiz_tcp(tp) 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 @@ ipsec_hdrsiz_tcp(tp) 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); } diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index aea92c0..ddd7d9b 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -749,12 +749,6 @@ tcp_connect(tp, nam, p) 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) @@ -841,12 +835,6 @@ tcp6_connect(tp, nam, p) 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 && (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index ecac451..294699f 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -66,7 +66,7 @@ struct tcptemp { 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 @@ struct rtentry * 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 *, |