diff options
author | Jeffrey Hsu <hsu@FreeBSD.org> | 2002-08-17 02:05:25 +0000 |
---|---|---|
committer | Jeffrey Hsu <hsu@FreeBSD.org> | 2002-08-17 02:05:25 +0000 |
commit | c068736a6139e9a60b6b4747f762a572e1b002f4 (patch) | |
tree | 8d2a5afa1f6bf1d9d0a40e2c4dd0ffb33a836efb /sys/netinet | |
parent | 74495bcdabc1d78a0a859b00ccbb687b7cf1f41e (diff) | |
download | src-c068736a6139e9a60b6b4747f762a572e1b002f4.tar.gz src-c068736a6139e9a60b6b4747f762a572e1b002f4.zip |
Cosmetic-only changes for readability.
Reviewed by: (early form passed by) bde
Approved by: itojun (from core@kame.net)
Notes
Notes:
svn path=/head/; revision=102002
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/tcp_input.c | 604 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 604 |
2 files changed, 556 insertions, 652 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 531efcf6a532..6744b2caf2b8 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -68,32 +68,25 @@ #include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */ #include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> -#ifdef INET6 #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <netinet6/in6_pcb.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> -#endif #include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> -#ifdef INET6 #include <netinet6/tcp6_var.h> -#endif #include <netinet/tcpip.h> #ifdef TCPDEBUG #include <netinet/tcp_debug.h> - #endif /* TCPDEBUG */ #ifdef IPSEC #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif #include <netkey/key.h> #endif /*IPSEC*/ @@ -101,7 +94,7 @@ MALLOC_DEFINE(M_TSEGQ, "tseg_qent", "TCP segment queue entry"); -static int tcprexmtthresh = 3; +static const int tcprexmtthresh = 3; tcp_cc tcp_ccgen; struct tcpstat tcpstat; @@ -138,7 +131,7 @@ static void tcp_pulloutofband(struct socket *, static int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *); static void tcp_xmit_timer(struct tcpcb *, int); -static int tcp_newreno(struct tcpcb *, struct tcphdr *); +static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *); /* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */ #ifdef INET6 @@ -350,29 +343,35 @@ tcp_input(m, off0) struct rmxp_tao *taop; /* pointer to our TAO cache entry */ struct rmxp_tao tao_noncached; /* in case there's no cached entry */ int headlocked = 0; + struct sockaddr_in *next_hop = NULL; + int rstreason; /* For badport_bandlim accounting purposes */ + + struct ip6_hdr *ip6 = NULL; +#ifdef INET6 + int isipv6; +#else + const int isipv6 = 0; +#endif #ifdef TCPDEBUG + /* + * The size of tcp_saveipgen must be the size of the max ip header, + * now IPv6. + */ u_char tcp_saveipgen[40]; - /* the size of the above must be of max ip header, now IPv6 */ struct tcphdr tcp_savetcp; short ostate = 0; #endif -#ifdef INET6 - struct ip6_hdr *ip6 = NULL; - int isipv6; -#endif /* INET6 */ - struct sockaddr_in *next_hop = NULL; + #ifdef MAC int error; #endif - int rstreason; /* For badport_bandlim accounting purposes */ /* Grab info from MT_TAG mbufs prepended to the chain. */ for (;m && m->m_type == MT_TAG; m = m->m_next) { if (m->m_tag_id == PACKET_TAG_IPFORWARD) next_hop = (struct sockaddr_in *)m->m_hdr.mh_data; } - #ifdef INET6 isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0; #endif @@ -380,7 +379,6 @@ tcp_input(m, off0) tcpstat.tcps_rcvtotal++; -#ifdef INET6 if (isipv6) { /* IP6_EXTHDR_CHECK() is already done at tcp6_input() */ ip6 = mtod(m, struct ip6_hdr *); @@ -403,55 +401,55 @@ tcp_input(m, off0) /* XXX stat */ goto drop; } - } else -#endif /* INET6 */ - { - /* - * Get IP and TCP header together in first mbuf. - * Note: IP leaves IP header in first mbuf. - */ - if (off0 > sizeof (struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - off0 = sizeof(struct ip); - } - if (m->m_len < sizeof (struct tcpiphdr)) { - if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { - tcpstat.tcps_rcvshort++; - return; - } - } - ip = mtod(m, struct ip *); - ipov = (struct ipovly *)ip; - th = (struct tcphdr *)((caddr_t)ip + off0); - tlen = ip->ip_len; - - if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { - if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) - th->th_sum = m->m_pkthdr.csum_data; - else - th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, htonl(m->m_pkthdr.csum_data + - ip->ip_len + IPPROTO_TCP)); - th->th_sum ^= 0xffff; } else { /* - * Checksum extended TCP header and data. + * Get IP and TCP header together in first mbuf. + * Note: IP leaves IP header in first mbuf. */ - len = sizeof (struct ip) + tlen; - bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); - ipov->ih_len = (u_short)tlen; - ipov->ih_len = htons(ipov->ih_len); - th->th_sum = in_cksum(m, len); - } - if (th->th_sum) { - tcpstat.tcps_rcvbadsum++; - goto drop; - } + if (off0 > sizeof (struct ip)) { + ip_stripoptions(m, (struct mbuf *)0); + off0 = sizeof(struct ip); + } + if (m->m_len < sizeof (struct tcpiphdr)) { + if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { + tcpstat.tcps_rcvshort++; + return; + } + } + ip = mtod(m, struct ip *); + ipov = (struct ipovly *)ip; + th = (struct tcphdr *)((caddr_t)ip + off0); + tlen = ip->ip_len; + + if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { + if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) + th->th_sum = m->m_pkthdr.csum_data; + else + th->th_sum = in_pseudo(ip->ip_src.s_addr, + ip->ip_dst.s_addr, + htonl(m->m_pkthdr.csum_data + + ip->ip_len + + IPPROTO_TCP)); + th->th_sum ^= 0xffff; + } else { + /* + * Checksum extended TCP header and data. + */ + len = sizeof (struct ip) + tlen; + bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); + ipov->ih_len = (u_short)tlen; + ipov->ih_len = htons(ipov->ih_len); + th->th_sum = in_cksum(m, len); + } + if (th->th_sum) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } #ifdef INET6 - /* Re-initialization for later version check */ - ip->ip_v = IPVERSION; + /* Re-initialization for later version check */ + ip->ip_v = IPVERSION; #endif - } + } /* * Check that TCP offset makes sense, @@ -464,24 +462,22 @@ tcp_input(m, off0) } tlen -= off; /* tlen is used instead of ti->ti_len */ if (off > sizeof (struct tcphdr)) { -#ifdef INET6 if (isipv6) { IP6_EXTHDR_CHECK(m, off0, off, ); ip6 = mtod(m, struct ip6_hdr *); th = (struct tcphdr *)((caddr_t)ip6 + off0); - } else -#endif /* INET6 */ - { - if (m->m_len < sizeof(struct ip) + off) { - if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) { - tcpstat.tcps_rcvshort++; - return; + } else { + if (m->m_len < sizeof(struct ip) + off) { + if ((m = m_pullup(m, sizeof (struct ip) + off)) + == 0) { + tcpstat.tcps_rcvshort++; + return; + } + ip = mtod(m, struct ip *); + ipov = (struct ipovly *)ip; + th = (struct tcphdr *)((caddr_t)ip + off0); } - ip = mtod(m, struct ip *); - ipov = (struct ipovly *)ip; - th = (struct tcphdr *)((caddr_t)ip + off0); } - } optlen = off - sizeof (struct tcphdr); optp = (u_char *)(th + 1); } @@ -526,60 +522,50 @@ tcp_input(m, off0) headlocked = 1; findpcb: /* IPFIREWALL_FORWARD section */ - if (next_hop != NULL -#ifdef INET6 - && isipv6 == NULL /* IPv6 support is not yet */ -#endif /* INET6 */ - ) { + if (next_hop != NULL && isipv6 == 0) { /* IPv6 support is not yet */ /* * Transparently forwarded. Pretend to be the destination. * already got one like this? */ inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport, - ip->ip_dst, th->th_dport, 0, m->m_pkthdr.rcvif); + ip->ip_dst, th->th_dport, + 0, m->m_pkthdr.rcvif); if (!inp) { - /* - * No, then it's new. Try find the ambushing socket - */ - if (next_hop->sin_port == 0) { - inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, - th->th_sport, next_hop->sin_addr, - th->th_dport, 1, m->m_pkthdr.rcvif); - } else { - inp = in_pcblookup_hash(&tcbinfo, - ip->ip_src, th->th_sport, - next_hop->sin_addr, - ntohs(next_hop->sin_port), 1, - m->m_pkthdr.rcvif); - } + /* It's new. Try find the ambushing socket. */ + inp = in_pcblookup_hash(&tcbinfo, + ip->ip_src, th->th_sport, + next_hop->sin_addr, + next_hop->sin_port ? + ntohs(next_hop->sin_port) : + th->th_dport, + 1, m->m_pkthdr.rcvif); } - } else - { -#ifdef INET6 - if (isipv6) - inp = in6_pcblookup_hash(&tcbinfo, &ip6->ip6_src, th->th_sport, - &ip6->ip6_dst, th->th_dport, 1, - m->m_pkthdr.rcvif); - else -#endif /* INET6 */ - inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport, - ip->ip_dst, th->th_dport, 1, m->m_pkthdr.rcvif); + } else { + if (isipv6) + inp = in6_pcblookup_hash(&tcbinfo, + &ip6->ip6_src, th->th_sport, + &ip6->ip6_dst, th->th_dport, + 1, m->m_pkthdr.rcvif); + else + inp = in_pcblookup_hash(&tcbinfo, + ip->ip_src, th->th_sport, + ip->ip_dst, th->th_dport, + 1, m->m_pkthdr.rcvif); } #ifdef IPSEC -#ifdef INET6 if (isipv6) { if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket)) { ipsec6stat.in_polvio++; goto drop; } - } else -#endif /* INET6 */ - if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket)) { - ipsecstat.in_polvio++; - goto drop; + } else { + if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket)) { + ipsecstat.in_polvio++; + goto drop; + } } -#endif /*IPSEC*/ +#endif /* * If the state is CLOSED (i.e., TCB does not exist) then @@ -591,34 +577,32 @@ findpcb: if (log_in_vain) { #ifdef INET6 char dbuf[INET6_ADDRSTRLEN], sbuf[INET6_ADDRSTRLEN]; -#else /* INET6 */ +#else char dbuf[4*sizeof "123"], sbuf[4*sizeof "123"]; -#endif /* INET6 */ +#endif -#ifdef INET6 if (isipv6) { strcpy(dbuf, ip6_sprintf(&ip6->ip6_dst)); strcpy(sbuf, ip6_sprintf(&ip6->ip6_src)); - } else -#endif - { - strcpy(dbuf, inet_ntoa(ip->ip_dst)); - strcpy(sbuf, inet_ntoa(ip->ip_src)); - } + } else { + strcpy(dbuf, inet_ntoa(ip->ip_dst)); + strcpy(sbuf, inet_ntoa(ip->ip_src)); + } switch (log_in_vain) { case 1: - if(thflags & TH_SYN) + if (thflags & TH_SYN) log(LOG_INFO, - "Connection attempt to TCP %s:%d from %s:%d\n", - dbuf, ntohs(th->th_dport), - sbuf, - ntohs(th->th_sport)); + "Connection attempt to TCP %s:%d " + "from %s:%d\n", + dbuf, ntohs(th->th_dport), sbuf, + ntohs(th->th_sport)); break; case 2: log(LOG_INFO, - "Connection attempt to TCP %s:%d from %s:%d flags:0x%x\n", - dbuf, ntohs(th->th_dport), sbuf, - ntohs(th->th_sport), thflags); + "Connection attempt to TCP %s:%d " + "from %s:%d flags:0x%x\n", + dbuf, ntohs(th->th_dport), sbuf, + ntohs(th->th_sport), thflags); break; default: break; @@ -666,13 +650,12 @@ findpcb: #ifdef TCPDEBUG if (so->so_options & SO_DEBUG) { ostate = tp->t_state; -#ifdef INET6 if (isipv6) bcopy((char *)ip6, (char *)tcp_saveipgen, - sizeof(*ip6)); + sizeof(*ip6)); else -#endif /* INET6 */ - bcopy((char *)ip, (char *)tcp_saveipgen, sizeof(*ip)); + bcopy((char *)ip, (char *)tcp_saveipgen, + sizeof(*ip)); tcp_savetcp = *th; } #endif @@ -681,14 +664,12 @@ findpcb: goto after_listen; #ifdef INET6 inc.inc_isipv6 = isipv6; +#endif if (isipv6) { inc.inc6_faddr = ip6->ip6_src; inc.inc6_laddr = ip6->ip6_dst; inc.inc6_route.ro_rt = NULL; /* XXX */ - - } else -#endif /* INET6 */ - { + } else { inc.inc_faddr = ip->ip_src; inc.inc_laddr = ip->ip_dst; inc.inc_route.ro_rt = NULL; /* XXX */ @@ -817,15 +798,14 @@ findpcb: * Don't bother responding if the destination was a broadcast. */ if (th->th_dport == th->th_sport) { -#ifdef INET6 if (isipv6) { if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ip6->ip6_src)) goto drop; - } else -#endif /* INET6 */ - if (ip->ip_dst.s_addr == ip->ip_src.s_addr) - goto drop; + } else { + if (ip->ip_dst.s_addr == ip->ip_src.s_addr) + goto drop; + } } /* * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN @@ -836,18 +816,17 @@ findpcb: */ if (m->m_flags & (M_BCAST|M_MCAST)) goto drop; -#ifdef INET6 if (isipv6) { if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) goto drop; - } else -#endif - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || - IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || - ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || - in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) - goto drop; + } else { + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || + in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) + goto drop; + } /* * SYN appears to be valid; create compressed TCP state * for syncache, or perform t/tcp connection. @@ -884,20 +863,13 @@ findpcb: * segment. Otherwise must send ACK now in case * the other side is slow starting. */ - if (DELAY_ACK(tp) && ((thflags & TH_FIN) || - (tlen != 0 && -#ifdef INET6 - ((isipv6 && in6_localaddr(&inp->in6p_faddr)) - || - (!isipv6 && -#endif - in_localaddr(inp->inp_faddr) -#ifdef INET6 - )) -#endif - ))) { - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + if (DELAY_ACK(tp) && + ((thflags & TH_FIN) || + (tlen != 0 && + ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || + (!isipv6 && in_localaddr(inp->inp_faddr)))))) { + callout_reset(tp->tt_delack, tcp_delacktime, + tcp_timer_delack, tp); tp->t_flags |= TF_NEEDSYN; } else tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN); @@ -984,7 +956,7 @@ after_listen: * proposal of the tcplw@cray.com list (Braden 1993/04/26). */ if ((to.to_flags & TOF_TS) != 0 && - SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { + SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { tp->ts_recent_age = ticks; tp->ts_recent = to.to_tsval; } @@ -1017,7 +989,8 @@ after_listen: ticks - to.to_tsecr + 1); else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, ticks - tp->t_rtttime); + tcp_xmit_timer(tp, + ticks - tp->t_rtttime); acked = th->th_ack - tp->snd_una; tcpstat.tcps_rcvackpack++; tcpstat.tcps_rcvackbyte += acked; @@ -1223,15 +1196,16 @@ after_listen: tcp_timer_keep, tp); } } else { - /* - * Received initial SYN in SYN-SENT[*] state => simul- - * taneous open. If segment contains CC option and there is - * a cached CC, apply TAO test; if it succeeds, connection is - * half-synchronized. Otherwise, do 3-way handshake: - * SYN-SENT -> SYN-RECEIVED - * SYN-SENT* -> SYN-RECEIVED* - * If there was no CC option, clear cached CC value. - */ + /* + * Received initial SYN in SYN-SENT[*] state => + * simultaneous open. If segment contains CC option + * and there is a cached CC, apply TAO test. + * If it succeeds, connection is * half-synchronized. + * Otherwise, do 3-way handshake: + * SYN-SENT -> SYN-RECEIVED + * SYN-SENT* -> SYN-RECEIVED* + * If there was no CC option, clear cached CC value. + */ tp->t_flags |= TF_ACKNOW; callout_stop(tp->tt_rexmt); if (to.to_flags & TOF_CC) { @@ -1282,15 +1256,17 @@ trimthenstep6: tp->snd_wl1 = th->th_seq - 1; tp->rcv_up = th->th_seq; /* - * Client side of transaction: already sent SYN and data. - * If the remote host used T/TCP to validate the SYN, - * our data will be ACK'd; if so, enter normal data segment - * processing in the middle of step 5, ack processing. - * Otherwise, goto step 6. + * Client side of transaction: already sent SYN and data. + * If the remote host used T/TCP to validate the SYN, + * our data will be ACK'd; if so, enter normal data segment + * processing in the middle of step 5, ack processing. + * Otherwise, goto step 6. */ if (thflags & TH_ACK) goto process_ACK; + goto step6; + /* * If the state is LAST_ACK or CLOSING or TIME_WAIT: * if segment contains a SYN and CC [not CC.NEW] option: @@ -1701,8 +1677,9 @@ trimthenstep6: u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; - if (tcp_do_newreno && SEQ_LT(th->th_ack, - tp->snd_recover)) { + if (tcp_do_newreno && + SEQ_LT(th->th_ack, + tp->snd_recover)) { /* False retransmit, should not * cut window */ @@ -1721,7 +1698,7 @@ trimthenstep6: tp->snd_cwnd = tp->t_maxseg; (void) tcp_output(tp); tp->snd_cwnd = tp->snd_ssthresh + - tp->t_maxseg * tp->t_dupacks; + tp->t_maxseg * tp->t_dupacks; if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; @@ -1738,34 +1715,48 @@ trimthenstep6: * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - if (tcp_do_newreno == 0) { + if (tcp_do_newreno) { + int is_partialack = SEQ_LT(th->th_ack, tp->snd_recover); + if (tp->t_dupacks >= tcprexmtthresh) { + if (is_partialack) { + tcp_newreno_partial_ack(tp, th); + } else { + /* + * Window inflation should have left us + * with approximately snd_ssthresh + * outstanding data. + * But in case we would be inclined to + * send a burst, better to do it via + * the slow start mechanism. + */ + if (SEQ_GT(th->th_ack + + tp->snd_ssthresh, + tp->snd_max)) + tp->snd_cwnd = tp->snd_max - + th->th_ack + + tp->t_maxseg; + else + tp->snd_cwnd = tp->snd_ssthresh; + } + } + /* + * Reset dupacks, except on partial acks in + * fast recovery. + */ + if (!(tp->t_dupacks >= tcprexmtthresh && is_partialack)) + tp->t_dupacks = 0; + } else { if (tp->t_dupacks >= tcprexmtthresh && - tp->snd_cwnd > tp->snd_ssthresh) - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = 0; - } else if (tp->t_dupacks >= tcprexmtthresh && - !tcp_newreno(tp, th)) { - /* - * Window inflation should have left us with approx. - * snd_ssthresh outstanding data. But in case we - * would be inclined to send a burst, better to do - * it via the slow start mechanism. - */ - if (SEQ_GT(th->th_ack + tp->snd_ssthresh, tp->snd_max)) - tp->snd_cwnd = - tp->snd_max - th->th_ack + tp->t_maxseg; - else - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = 0; - } - if (tp->t_dupacks < tcprexmtthresh) + tp->snd_cwnd > tp->snd_ssthresh) + tp->snd_cwnd = tp->snd_ssthresh; tp->t_dupacks = 0; + } if (SEQ_GT(th->th_ack, tp->snd_max)) { tcpstat.tcps_rcvacktoomuch++; goto dropafterack; } /* - * If we reach this point, ACK is not a duplicate, + * If we reach this point, ACK is not a duplicate, * i.e., it ACKs something we sent. */ if (tp->t_flags & TF_NEEDSYN) { @@ -1858,7 +1849,7 @@ process_ACK: * in NewReno fast recovery mode, so we leave the congestion * window alone. */ - if (tcp_do_newreno == 0 || tp->t_dupacks == 0) + if (!tcp_do_newreno || tp->t_dupacks == 0) tp->snd_cwnd = min(cw + incr,TCP_MAXWIN<<tp->snd_scale); } if (acked > so->so_snd.sb_cc) { @@ -2022,7 +2013,7 @@ step6: ) tcp_pulloutofband(so, th, m, drop_hdrlen); /* hdr drop is delayed */ - } else + } else { /* * If no out of band data is expected, * pull receive urgent pointer along @@ -2030,6 +2021,7 @@ step6: */ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) tp->rcv_up = tp->rcv_nxt; + } dodata: /* XXX */ KASSERT(headlocked, ("headlocked")); INP_INFO_WUNLOCK(&tcbinfo); @@ -2042,25 +2034,27 @@ dodata: /* XXX */ * case PRU_RCVD). If a FIN has already been received on this * connection then we just ignore the text. */ - if ((tlen || (thflags&TH_FIN)) && + if ((tlen || (thflags & TH_FIN)) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { m_adj(m, drop_hdrlen); /* delayed header drop */ /* - * Insert segment which inludes th into reassembly queue of tcp with - * control block tp. Return TH_FIN if reassembly now includes - * a segment with FIN. This handle the common case inline (segment - * is the next to be received on an established connection, and the - * queue is empty), avoiding linkage into and removal from the queue - * and repetition of various conversions. - * Set DELACK for segments received in order, but ack immediately - * when segments are out of order (so fast retransmit can work). + * Insert segment which includes th into TCP reassembly queue + * with control block tp. Set thflags to whether reassembly now + * includes a segment with FIN. This handles the common case + * inline (segment is the next to be received on an established + * connection, and the queue is empty), avoiding linkage into + * and removal from the queue and repetition of various + * conversions. + * Set DELACK for segments received in order, but ack + * immediately when segments are out of order (so + * fast retransmit can work). */ if (th->th_seq == tp->rcv_nxt && LIST_EMPTY(&tp->t_segq) && TCPS_HAVEESTABLISHED(tp->t_state)) { if (DELAY_ACK(tp)) callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + tcp_timer_delack, tp); else tp->t_flags |= TF_ACKNOW; tp->rcv_nxt += tlen; @@ -2094,11 +2088,11 @@ dodata: /* XXX */ if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { socantrcvmore(so); /* - * If connection is half-synchronized - * (ie NEEDSYN flag on) then delay ACK, - * so it may be piggybacked when SYN is sent. - * Otherwise, since we received a FIN then no - * more input can be expected, send ACK now. + * If connection is half-synchronized + * (ie NEEDSYN flag on) then delay ACK, + * so it may be piggybacked when SYN is sent. + * Otherwise, since we received a FIN then no + * more input can be expected, send ACK now. */ if (DELAY_ACK(tp) && (tp->t_flags & TF_NEEDSYN)) callout_reset(tp->tt_delack, tcp_delacktime, @@ -2217,18 +2211,17 @@ dropwithreset: */ if ((thflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST)) goto drop; -#ifdef INET6 if (isipv6) { if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) goto drop; - } else -#endif /* INET6 */ - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || - IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || - ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || - in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) - goto drop; + } else { + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || + in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) + goto drop; + } /* IPv6 anycast check is done at tcp6_input() */ /* @@ -2518,35 +2511,27 @@ tcp_mss(tp, offer) struct ifnet *ifp; register int rtt, mss; u_long bufsize; - struct inpcb *inp; + struct inpcb *inp = tp->t_inpcb; struct socket *so; struct rmxp_tao *taop; int origoffer = offer; #ifdef INET6 - int isipv6; - int min_protoh; -#endif - - inp = tp->t_inpcb; -#ifdef INET6 - isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0; - min_protoh = isipv6 ? sizeof (struct ip6_hdr) + sizeof (struct tcphdr) - : sizeof (struct tcpiphdr); + int isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0; + size_t min_protoh = isipv6 ? + sizeof (struct ip6_hdr) + sizeof (struct tcphdr) : + sizeof (struct tcpiphdr); #else -#define min_protoh (sizeof (struct tcpiphdr)) + const int isipv6 = 0; + const size_t min_protoh = sizeof (struct tcpiphdr); #endif -#ifdef INET6 + if (isipv6) rt = tcp_rtlookup6(&inp->inp_inc); else -#endif - rt = tcp_rtlookup(&inp->inp_inc); + rt = tcp_rtlookup(&inp->inp_inc); if (rt == NULL) { tp->t_maxopd = tp->t_maxseg = -#ifdef INET6 - isipv6 ? tcp_v6mssdflt : -#endif /* INET6 */ - tcp_mssdflt; + isipv6 ? tcp_v6mssdflt : tcp_mssdflt; return; } ifp = rt->rt_ifp; @@ -2564,11 +2549,7 @@ tcp_mss(tp, offer) * in this case we use tcp_mssdflt. */ if (offer == 0) - offer = -#ifdef INET6 - isipv6 ? tcp_v6mssdflt : -#endif /* INET6 */ - tcp_mssdflt; + offer = isipv6 ? tcp_v6mssdflt : tcp_mssdflt; else /* * Sanity check: make sure that maxopd will be large @@ -2612,25 +2593,17 @@ tcp_mss(tp, offer) */ if (rt->rt_rmx.rmx_mtu) mss = rt->rt_rmx.rmx_mtu - min_protoh; - else - { - mss = -#ifdef INET6 - (isipv6 ? nd_ifinfo[rt->rt_ifp->if_index].linkmtu : -#endif - ifp->if_mtu -#ifdef INET6 - ) -#endif - - min_protoh; -#ifdef INET6 + else { if (isipv6) { + mss = nd_ifinfo[rt->rt_ifp->if_index].linkmtu - + min_protoh; if (!in6_localaddr(&inp->in6p_faddr)) mss = min(mss, tcp_v6mssdflt); - } else -#endif - if (!in_localaddr(inp->inp_faddr)) - mss = min(mss, tcp_mssdflt); + } else { + mss = ifp->if_mtu - min_protoh; + if (!in_localaddr(inp->inp_faddr)) + mss = min(mss, tcp_mssdflt); + } } mss = min(mss, offer); /* @@ -2700,16 +2673,8 @@ tcp_mss(tp, offer) * Set the slow-start flight size depending on whether this * is a local network or not. */ - if ( -#ifdef INET6 - (isipv6 && in6_localaddr(&inp->in6p_faddr)) || - (!isipv6 && -#endif - in_localaddr(inp->inp_faddr) -#ifdef INET6 - ) -#endif - ) + if ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || + (!isipv6 && in_localaddr(inp->inp_faddr))) tp->snd_cwnd = mss * ss_fltsz_local; else tp->snd_cwnd = mss * ss_fltsz; @@ -2735,68 +2700,55 @@ tcp_mssopt(tp) { struct rtentry *rt; #ifdef INET6 - int isipv6; - int min_protoh; -#endif - -#ifdef INET6 - isipv6 = ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) ? 1 : 0; - min_protoh = isipv6 ? sizeof (struct ip6_hdr) + sizeof (struct tcphdr) - : sizeof (struct tcpiphdr); + int isipv6 = ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) ? 1 : 0; + size_t min_protoh = isipv6 ? + sizeof (struct ip6_hdr) + sizeof (struct tcphdr) : + sizeof (struct tcpiphdr); #else -#define min_protoh (sizeof (struct tcpiphdr)) + const int isipv6 = 0; + const size_t min_protoh = sizeof (struct tcpiphdr); #endif -#ifdef INET6 + if (isipv6) rt = tcp_rtlookup6(&tp->t_inpcb->inp_inc); else -#endif /* INET6 */ - rt = tcp_rtlookup(&tp->t_inpcb->inp_inc); + rt = tcp_rtlookup(&tp->t_inpcb->inp_inc); if (rt == NULL) - return -#ifdef INET6 - isipv6 ? tcp_v6mssdflt : -#endif /* INET6 */ - tcp_mssdflt; + return (isipv6 ? tcp_v6mssdflt : tcp_mssdflt); - return rt->rt_ifp->if_mtu - min_protoh; + return (rt->rt_ifp->if_mtu - min_protoh); } /* - * Checks for partial ack. If partial ack arrives, force the retransmission - * of the next unacknowledged segment, do not clear tp->t_dupacks, and return - * 1. By setting snd_nxt to ti_ack, this forces retransmission timer to - * be started again. If the ack advances at least to tp->snd_recover, return 0. + * On a partial ack arrives, force the retransmission of the + * next unacknowledged segment. Do not clear tp->t_dupacks. + * By setting snd_nxt to ti_ack, this forces retransmission timer to + * be started again. */ -static int -tcp_newreno(tp, th) +static void +tcp_newreno_partial_ack(tp, th) struct tcpcb *tp; struct tcphdr *th; { - if (SEQ_LT(th->th_ack, tp->snd_recover)) { - tcp_seq onxt = tp->snd_nxt; - u_long ocwnd = tp->snd_cwnd; + tcp_seq onxt = tp->snd_nxt; + u_long ocwnd = tp->snd_cwnd; - callout_stop(tp->tt_rexmt); - tp->t_rtttime = 0; - tp->snd_nxt = th->th_ack; - /* - * Set snd_cwnd to one segment beyond acknowledged offset - * (tp->snd_una has not yet been updated when this function - * is called) - */ - tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una); - (void) tcp_output(tp); - tp->snd_cwnd = ocwnd; - if (SEQ_GT(onxt, tp->snd_nxt)) - tp->snd_nxt = onxt; - /* - * Partial window deflation. Relies on fact that tp->snd_una - * not updated yet. - */ - tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); - return (1); - } - return (0); + callout_stop(tp->tt_rexmt); + tp->t_rtttime = 0; + tp->snd_nxt = th->th_ack; + /* + * Set snd_cwnd to one segment beyond acknowledged offset. + * (tp->snd_una has not yet been updated when this function is called.) + */ + tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una); + (void) tcp_output(tp); + tp->snd_cwnd = ocwnd; + if (SEQ_GT(onxt, tp->snd_nxt)) + tp->snd_nxt = onxt; + /* + * Partial window deflation. Relies on fact that tp->snd_una + * not updated yet. + */ + tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); } diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 531efcf6a532..6744b2caf2b8 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -68,32 +68,25 @@ #include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */ #include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> -#ifdef INET6 #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <netinet6/in6_pcb.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> -#endif #include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> -#ifdef INET6 #include <netinet6/tcp6_var.h> -#endif #include <netinet/tcpip.h> #ifdef TCPDEBUG #include <netinet/tcp_debug.h> - #endif /* TCPDEBUG */ #ifdef IPSEC #include <netinet6/ipsec.h> -#ifdef INET6 #include <netinet6/ipsec6.h> -#endif #include <netkey/key.h> #endif /*IPSEC*/ @@ -101,7 +94,7 @@ MALLOC_DEFINE(M_TSEGQ, "tseg_qent", "TCP segment queue entry"); -static int tcprexmtthresh = 3; +static const int tcprexmtthresh = 3; tcp_cc tcp_ccgen; struct tcpstat tcpstat; @@ -138,7 +131,7 @@ static void tcp_pulloutofband(struct socket *, static int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *); static void tcp_xmit_timer(struct tcpcb *, int); -static int tcp_newreno(struct tcpcb *, struct tcphdr *); +static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *); /* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */ #ifdef INET6 @@ -350,29 +343,35 @@ tcp_input(m, off0) struct rmxp_tao *taop; /* pointer to our TAO cache entry */ struct rmxp_tao tao_noncached; /* in case there's no cached entry */ int headlocked = 0; + struct sockaddr_in *next_hop = NULL; + int rstreason; /* For badport_bandlim accounting purposes */ + + struct ip6_hdr *ip6 = NULL; +#ifdef INET6 + int isipv6; +#else + const int isipv6 = 0; +#endif #ifdef TCPDEBUG + /* + * The size of tcp_saveipgen must be the size of the max ip header, + * now IPv6. + */ u_char tcp_saveipgen[40]; - /* the size of the above must be of max ip header, now IPv6 */ struct tcphdr tcp_savetcp; short ostate = 0; #endif -#ifdef INET6 - struct ip6_hdr *ip6 = NULL; - int isipv6; -#endif /* INET6 */ - struct sockaddr_in *next_hop = NULL; + #ifdef MAC int error; #endif - int rstreason; /* For badport_bandlim accounting purposes */ /* Grab info from MT_TAG mbufs prepended to the chain. */ for (;m && m->m_type == MT_TAG; m = m->m_next) { if (m->m_tag_id == PACKET_TAG_IPFORWARD) next_hop = (struct sockaddr_in *)m->m_hdr.mh_data; } - #ifdef INET6 isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0; #endif @@ -380,7 +379,6 @@ tcp_input(m, off0) tcpstat.tcps_rcvtotal++; -#ifdef INET6 if (isipv6) { /* IP6_EXTHDR_CHECK() is already done at tcp6_input() */ ip6 = mtod(m, struct ip6_hdr *); @@ -403,55 +401,55 @@ tcp_input(m, off0) /* XXX stat */ goto drop; } - } else -#endif /* INET6 */ - { - /* - * Get IP and TCP header together in first mbuf. - * Note: IP leaves IP header in first mbuf. - */ - if (off0 > sizeof (struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - off0 = sizeof(struct ip); - } - if (m->m_len < sizeof (struct tcpiphdr)) { - if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { - tcpstat.tcps_rcvshort++; - return; - } - } - ip = mtod(m, struct ip *); - ipov = (struct ipovly *)ip; - th = (struct tcphdr *)((caddr_t)ip + off0); - tlen = ip->ip_len; - - if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { - if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) - th->th_sum = m->m_pkthdr.csum_data; - else - th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, htonl(m->m_pkthdr.csum_data + - ip->ip_len + IPPROTO_TCP)); - th->th_sum ^= 0xffff; } else { /* - * Checksum extended TCP header and data. + * Get IP and TCP header together in first mbuf. + * Note: IP leaves IP header in first mbuf. */ - len = sizeof (struct ip) + tlen; - bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); - ipov->ih_len = (u_short)tlen; - ipov->ih_len = htons(ipov->ih_len); - th->th_sum = in_cksum(m, len); - } - if (th->th_sum) { - tcpstat.tcps_rcvbadsum++; - goto drop; - } + if (off0 > sizeof (struct ip)) { + ip_stripoptions(m, (struct mbuf *)0); + off0 = sizeof(struct ip); + } + if (m->m_len < sizeof (struct tcpiphdr)) { + if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { + tcpstat.tcps_rcvshort++; + return; + } + } + ip = mtod(m, struct ip *); + ipov = (struct ipovly *)ip; + th = (struct tcphdr *)((caddr_t)ip + off0); + tlen = ip->ip_len; + + if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { + if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) + th->th_sum = m->m_pkthdr.csum_data; + else + th->th_sum = in_pseudo(ip->ip_src.s_addr, + ip->ip_dst.s_addr, + htonl(m->m_pkthdr.csum_data + + ip->ip_len + + IPPROTO_TCP)); + th->th_sum ^= 0xffff; + } else { + /* + * Checksum extended TCP header and data. + */ + len = sizeof (struct ip) + tlen; + bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); + ipov->ih_len = (u_short)tlen; + ipov->ih_len = htons(ipov->ih_len); + th->th_sum = in_cksum(m, len); + } + if (th->th_sum) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } #ifdef INET6 - /* Re-initialization for later version check */ - ip->ip_v = IPVERSION; + /* Re-initialization for later version check */ + ip->ip_v = IPVERSION; #endif - } + } /* * Check that TCP offset makes sense, @@ -464,24 +462,22 @@ tcp_input(m, off0) } tlen -= off; /* tlen is used instead of ti->ti_len */ if (off > sizeof (struct tcphdr)) { -#ifdef INET6 if (isipv6) { IP6_EXTHDR_CHECK(m, off0, off, ); ip6 = mtod(m, struct ip6_hdr *); th = (struct tcphdr *)((caddr_t)ip6 + off0); - } else -#endif /* INET6 */ - { - if (m->m_len < sizeof(struct ip) + off) { - if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) { - tcpstat.tcps_rcvshort++; - return; + } else { + if (m->m_len < sizeof(struct ip) + off) { + if ((m = m_pullup(m, sizeof (struct ip) + off)) + == 0) { + tcpstat.tcps_rcvshort++; + return; + } + ip = mtod(m, struct ip *); + ipov = (struct ipovly *)ip; + th = (struct tcphdr *)((caddr_t)ip + off0); } - ip = mtod(m, struct ip *); - ipov = (struct ipovly *)ip; - th = (struct tcphdr *)((caddr_t)ip + off0); } - } optlen = off - sizeof (struct tcphdr); optp = (u_char *)(th + 1); } @@ -526,60 +522,50 @@ tcp_input(m, off0) headlocked = 1; findpcb: /* IPFIREWALL_FORWARD section */ - if (next_hop != NULL -#ifdef INET6 - && isipv6 == NULL /* IPv6 support is not yet */ -#endif /* INET6 */ - ) { + if (next_hop != NULL && isipv6 == 0) { /* IPv6 support is not yet */ /* * Transparently forwarded. Pretend to be the destination. * already got one like this? */ inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport, - ip->ip_dst, th->th_dport, 0, m->m_pkthdr.rcvif); + ip->ip_dst, th->th_dport, + 0, m->m_pkthdr.rcvif); if (!inp) { - /* - * No, then it's new. Try find the ambushing socket - */ - if (next_hop->sin_port == 0) { - inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, - th->th_sport, next_hop->sin_addr, - th->th_dport, 1, m->m_pkthdr.rcvif); - } else { - inp = in_pcblookup_hash(&tcbinfo, - ip->ip_src, th->th_sport, - next_hop->sin_addr, - ntohs(next_hop->sin_port), 1, - m->m_pkthdr.rcvif); - } + /* It's new. Try find the ambushing socket. */ + inp = in_pcblookup_hash(&tcbinfo, + ip->ip_src, th->th_sport, + next_hop->sin_addr, + next_hop->sin_port ? + ntohs(next_hop->sin_port) : + th->th_dport, + 1, m->m_pkthdr.rcvif); } - } else - { -#ifdef INET6 - if (isipv6) - inp = in6_pcblookup_hash(&tcbinfo, &ip6->ip6_src, th->th_sport, - &ip6->ip6_dst, th->th_dport, 1, - m->m_pkthdr.rcvif); - else -#endif /* INET6 */ - inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport, - ip->ip_dst, th->th_dport, 1, m->m_pkthdr.rcvif); + } else { + if (isipv6) + inp = in6_pcblookup_hash(&tcbinfo, + &ip6->ip6_src, th->th_sport, + &ip6->ip6_dst, th->th_dport, + 1, m->m_pkthdr.rcvif); + else + inp = in_pcblookup_hash(&tcbinfo, + ip->ip_src, th->th_sport, + ip->ip_dst, th->th_dport, + 1, m->m_pkthdr.rcvif); } #ifdef IPSEC -#ifdef INET6 if (isipv6) { if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket)) { ipsec6stat.in_polvio++; goto drop; } - } else -#endif /* INET6 */ - if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket)) { - ipsecstat.in_polvio++; - goto drop; + } else { + if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket)) { + ipsecstat.in_polvio++; + goto drop; + } } -#endif /*IPSEC*/ +#endif /* * If the state is CLOSED (i.e., TCB does not exist) then @@ -591,34 +577,32 @@ findpcb: if (log_in_vain) { #ifdef INET6 char dbuf[INET6_ADDRSTRLEN], sbuf[INET6_ADDRSTRLEN]; -#else /* INET6 */ +#else char dbuf[4*sizeof "123"], sbuf[4*sizeof "123"]; -#endif /* INET6 */ +#endif -#ifdef INET6 if (isipv6) { strcpy(dbuf, ip6_sprintf(&ip6->ip6_dst)); strcpy(sbuf, ip6_sprintf(&ip6->ip6_src)); - } else -#endif - { - strcpy(dbuf, inet_ntoa(ip->ip_dst)); - strcpy(sbuf, inet_ntoa(ip->ip_src)); - } + } else { + strcpy(dbuf, inet_ntoa(ip->ip_dst)); + strcpy(sbuf, inet_ntoa(ip->ip_src)); + } switch (log_in_vain) { case 1: - if(thflags & TH_SYN) + if (thflags & TH_SYN) log(LOG_INFO, - "Connection attempt to TCP %s:%d from %s:%d\n", - dbuf, ntohs(th->th_dport), - sbuf, - ntohs(th->th_sport)); + "Connection attempt to TCP %s:%d " + "from %s:%d\n", + dbuf, ntohs(th->th_dport), sbuf, + ntohs(th->th_sport)); break; case 2: log(LOG_INFO, - "Connection attempt to TCP %s:%d from %s:%d flags:0x%x\n", - dbuf, ntohs(th->th_dport), sbuf, - ntohs(th->th_sport), thflags); + "Connection attempt to TCP %s:%d " + "from %s:%d flags:0x%x\n", + dbuf, ntohs(th->th_dport), sbuf, + ntohs(th->th_sport), thflags); break; default: break; @@ -666,13 +650,12 @@ findpcb: #ifdef TCPDEBUG if (so->so_options & SO_DEBUG) { ostate = tp->t_state; -#ifdef INET6 if (isipv6) bcopy((char *)ip6, (char *)tcp_saveipgen, - sizeof(*ip6)); + sizeof(*ip6)); else -#endif /* INET6 */ - bcopy((char *)ip, (char *)tcp_saveipgen, sizeof(*ip)); + bcopy((char *)ip, (char *)tcp_saveipgen, + sizeof(*ip)); tcp_savetcp = *th; } #endif @@ -681,14 +664,12 @@ findpcb: goto after_listen; #ifdef INET6 inc.inc_isipv6 = isipv6; +#endif if (isipv6) { inc.inc6_faddr = ip6->ip6_src; inc.inc6_laddr = ip6->ip6_dst; inc.inc6_route.ro_rt = NULL; /* XXX */ - - } else -#endif /* INET6 */ - { + } else { inc.inc_faddr = ip->ip_src; inc.inc_laddr = ip->ip_dst; inc.inc_route.ro_rt = NULL; /* XXX */ @@ -817,15 +798,14 @@ findpcb: * Don't bother responding if the destination was a broadcast. */ if (th->th_dport == th->th_sport) { -#ifdef INET6 if (isipv6) { if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ip6->ip6_src)) goto drop; - } else -#endif /* INET6 */ - if (ip->ip_dst.s_addr == ip->ip_src.s_addr) - goto drop; + } else { + if (ip->ip_dst.s_addr == ip->ip_src.s_addr) + goto drop; + } } /* * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN @@ -836,18 +816,17 @@ findpcb: */ if (m->m_flags & (M_BCAST|M_MCAST)) goto drop; -#ifdef INET6 if (isipv6) { if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) goto drop; - } else -#endif - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || - IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || - ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || - in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) - goto drop; + } else { + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || + in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) + goto drop; + } /* * SYN appears to be valid; create compressed TCP state * for syncache, or perform t/tcp connection. @@ -884,20 +863,13 @@ findpcb: * segment. Otherwise must send ACK now in case * the other side is slow starting. */ - if (DELAY_ACK(tp) && ((thflags & TH_FIN) || - (tlen != 0 && -#ifdef INET6 - ((isipv6 && in6_localaddr(&inp->in6p_faddr)) - || - (!isipv6 && -#endif - in_localaddr(inp->inp_faddr) -#ifdef INET6 - )) -#endif - ))) { - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + if (DELAY_ACK(tp) && + ((thflags & TH_FIN) || + (tlen != 0 && + ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || + (!isipv6 && in_localaddr(inp->inp_faddr)))))) { + callout_reset(tp->tt_delack, tcp_delacktime, + tcp_timer_delack, tp); tp->t_flags |= TF_NEEDSYN; } else tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN); @@ -984,7 +956,7 @@ after_listen: * proposal of the tcplw@cray.com list (Braden 1993/04/26). */ if ((to.to_flags & TOF_TS) != 0 && - SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { + SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { tp->ts_recent_age = ticks; tp->ts_recent = to.to_tsval; } @@ -1017,7 +989,8 @@ after_listen: ticks - to.to_tsecr + 1); else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, ticks - tp->t_rtttime); + tcp_xmit_timer(tp, + ticks - tp->t_rtttime); acked = th->th_ack - tp->snd_una; tcpstat.tcps_rcvackpack++; tcpstat.tcps_rcvackbyte += acked; @@ -1223,15 +1196,16 @@ after_listen: tcp_timer_keep, tp); } } else { - /* - * Received initial SYN in SYN-SENT[*] state => simul- - * taneous open. If segment contains CC option and there is - * a cached CC, apply TAO test; if it succeeds, connection is - * half-synchronized. Otherwise, do 3-way handshake: - * SYN-SENT -> SYN-RECEIVED - * SYN-SENT* -> SYN-RECEIVED* - * If there was no CC option, clear cached CC value. - */ + /* + * Received initial SYN in SYN-SENT[*] state => + * simultaneous open. If segment contains CC option + * and there is a cached CC, apply TAO test. + * If it succeeds, connection is * half-synchronized. + * Otherwise, do 3-way handshake: + * SYN-SENT -> SYN-RECEIVED + * SYN-SENT* -> SYN-RECEIVED* + * If there was no CC option, clear cached CC value. + */ tp->t_flags |= TF_ACKNOW; callout_stop(tp->tt_rexmt); if (to.to_flags & TOF_CC) { @@ -1282,15 +1256,17 @@ trimthenstep6: tp->snd_wl1 = th->th_seq - 1; tp->rcv_up = th->th_seq; /* - * Client side of transaction: already sent SYN and data. - * If the remote host used T/TCP to validate the SYN, - * our data will be ACK'd; if so, enter normal data segment - * processing in the middle of step 5, ack processing. - * Otherwise, goto step 6. + * Client side of transaction: already sent SYN and data. + * If the remote host used T/TCP to validate the SYN, + * our data will be ACK'd; if so, enter normal data segment + * processing in the middle of step 5, ack processing. + * Otherwise, goto step 6. */ if (thflags & TH_ACK) goto process_ACK; + goto step6; + /* * If the state is LAST_ACK or CLOSING or TIME_WAIT: * if segment contains a SYN and CC [not CC.NEW] option: @@ -1701,8 +1677,9 @@ trimthenstep6: u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; - if (tcp_do_newreno && SEQ_LT(th->th_ack, - tp->snd_recover)) { + if (tcp_do_newreno && + SEQ_LT(th->th_ack, + tp->snd_recover)) { /* False retransmit, should not * cut window */ @@ -1721,7 +1698,7 @@ trimthenstep6: tp->snd_cwnd = tp->t_maxseg; (void) tcp_output(tp); tp->snd_cwnd = tp->snd_ssthresh + - tp->t_maxseg * tp->t_dupacks; + tp->t_maxseg * tp->t_dupacks; if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; @@ -1738,34 +1715,48 @@ trimthenstep6: * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - if (tcp_do_newreno == 0) { + if (tcp_do_newreno) { + int is_partialack = SEQ_LT(th->th_ack, tp->snd_recover); + if (tp->t_dupacks >= tcprexmtthresh) { + if (is_partialack) { + tcp_newreno_partial_ack(tp, th); + } else { + /* + * Window inflation should have left us + * with approximately snd_ssthresh + * outstanding data. + * But in case we would be inclined to + * send a burst, better to do it via + * the slow start mechanism. + */ + if (SEQ_GT(th->th_ack + + tp->snd_ssthresh, + tp->snd_max)) + tp->snd_cwnd = tp->snd_max - + th->th_ack + + tp->t_maxseg; + else + tp->snd_cwnd = tp->snd_ssthresh; + } + } + /* + * Reset dupacks, except on partial acks in + * fast recovery. + */ + if (!(tp->t_dupacks >= tcprexmtthresh && is_partialack)) + tp->t_dupacks = 0; + } else { if (tp->t_dupacks >= tcprexmtthresh && - tp->snd_cwnd > tp->snd_ssthresh) - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = 0; - } else if (tp->t_dupacks >= tcprexmtthresh && - !tcp_newreno(tp, th)) { - /* - * Window inflation should have left us with approx. - * snd_ssthresh outstanding data. But in case we - * would be inclined to send a burst, better to do - * it via the slow start mechanism. - */ - if (SEQ_GT(th->th_ack + tp->snd_ssthresh, tp->snd_max)) - tp->snd_cwnd = - tp->snd_max - th->th_ack + tp->t_maxseg; - else - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = 0; - } - if (tp->t_dupacks < tcprexmtthresh) + tp->snd_cwnd > tp->snd_ssthresh) + tp->snd_cwnd = tp->snd_ssthresh; tp->t_dupacks = 0; + } if (SEQ_GT(th->th_ack, tp->snd_max)) { tcpstat.tcps_rcvacktoomuch++; goto dropafterack; } /* - * If we reach this point, ACK is not a duplicate, + * If we reach this point, ACK is not a duplicate, * i.e., it ACKs something we sent. */ if (tp->t_flags & TF_NEEDSYN) { @@ -1858,7 +1849,7 @@ process_ACK: * in NewReno fast recovery mode, so we leave the congestion * window alone. */ - if (tcp_do_newreno == 0 || tp->t_dupacks == 0) + if (!tcp_do_newreno || tp->t_dupacks == 0) tp->snd_cwnd = min(cw + incr,TCP_MAXWIN<<tp->snd_scale); } if (acked > so->so_snd.sb_cc) { @@ -2022,7 +2013,7 @@ step6: ) tcp_pulloutofband(so, th, m, drop_hdrlen); /* hdr drop is delayed */ - } else + } else { /* * If no out of band data is expected, * pull receive urgent pointer along @@ -2030,6 +2021,7 @@ step6: */ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) tp->rcv_up = tp->rcv_nxt; + } dodata: /* XXX */ KASSERT(headlocked, ("headlocked")); INP_INFO_WUNLOCK(&tcbinfo); @@ -2042,25 +2034,27 @@ dodata: /* XXX */ * case PRU_RCVD). If a FIN has already been received on this * connection then we just ignore the text. */ - if ((tlen || (thflags&TH_FIN)) && + if ((tlen || (thflags & TH_FIN)) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { m_adj(m, drop_hdrlen); /* delayed header drop */ /* - * Insert segment which inludes th into reassembly queue of tcp with - * control block tp. Return TH_FIN if reassembly now includes - * a segment with FIN. This handle the common case inline (segment - * is the next to be received on an established connection, and the - * queue is empty), avoiding linkage into and removal from the queue - * and repetition of various conversions. - * Set DELACK for segments received in order, but ack immediately - * when segments are out of order (so fast retransmit can work). + * Insert segment which includes th into TCP reassembly queue + * with control block tp. Set thflags to whether reassembly now + * includes a segment with FIN. This handles the common case + * inline (segment is the next to be received on an established + * connection, and the queue is empty), avoiding linkage into + * and removal from the queue and repetition of various + * conversions. + * Set DELACK for segments received in order, but ack + * immediately when segments are out of order (so + * fast retransmit can work). */ if (th->th_seq == tp->rcv_nxt && LIST_EMPTY(&tp->t_segq) && TCPS_HAVEESTABLISHED(tp->t_state)) { if (DELAY_ACK(tp)) callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + tcp_timer_delack, tp); else tp->t_flags |= TF_ACKNOW; tp->rcv_nxt += tlen; @@ -2094,11 +2088,11 @@ dodata: /* XXX */ if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { socantrcvmore(so); /* - * If connection is half-synchronized - * (ie NEEDSYN flag on) then delay ACK, - * so it may be piggybacked when SYN is sent. - * Otherwise, since we received a FIN then no - * more input can be expected, send ACK now. + * If connection is half-synchronized + * (ie NEEDSYN flag on) then delay ACK, + * so it may be piggybacked when SYN is sent. + * Otherwise, since we received a FIN then no + * more input can be expected, send ACK now. */ if (DELAY_ACK(tp) && (tp->t_flags & TF_NEEDSYN)) callout_reset(tp->tt_delack, tcp_delacktime, @@ -2217,18 +2211,17 @@ dropwithreset: */ if ((thflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST)) goto drop; -#ifdef INET6 if (isipv6) { if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) goto drop; - } else -#endif /* INET6 */ - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || - IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || - ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || - in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) - goto drop; + } else { + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || + in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) + goto drop; + } /* IPv6 anycast check is done at tcp6_input() */ /* @@ -2518,35 +2511,27 @@ tcp_mss(tp, offer) struct ifnet *ifp; register int rtt, mss; u_long bufsize; - struct inpcb *inp; + struct inpcb *inp = tp->t_inpcb; struct socket *so; struct rmxp_tao *taop; int origoffer = offer; #ifdef INET6 - int isipv6; - int min_protoh; -#endif - - inp = tp->t_inpcb; -#ifdef INET6 - isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0; - min_protoh = isipv6 ? sizeof (struct ip6_hdr) + sizeof (struct tcphdr) - : sizeof (struct tcpiphdr); + int isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0; + size_t min_protoh = isipv6 ? + sizeof (struct ip6_hdr) + sizeof (struct tcphdr) : + sizeof (struct tcpiphdr); #else -#define min_protoh (sizeof (struct tcpiphdr)) + const int isipv6 = 0; + const size_t min_protoh = sizeof (struct tcpiphdr); #endif -#ifdef INET6 + if (isipv6) rt = tcp_rtlookup6(&inp->inp_inc); else -#endif - rt = tcp_rtlookup(&inp->inp_inc); + rt = tcp_rtlookup(&inp->inp_inc); if (rt == NULL) { tp->t_maxopd = tp->t_maxseg = -#ifdef INET6 - isipv6 ? tcp_v6mssdflt : -#endif /* INET6 */ - tcp_mssdflt; + isipv6 ? tcp_v6mssdflt : tcp_mssdflt; return; } ifp = rt->rt_ifp; @@ -2564,11 +2549,7 @@ tcp_mss(tp, offer) * in this case we use tcp_mssdflt. */ if (offer == 0) - offer = -#ifdef INET6 - isipv6 ? tcp_v6mssdflt : -#endif /* INET6 */ - tcp_mssdflt; + offer = isipv6 ? tcp_v6mssdflt : tcp_mssdflt; else /* * Sanity check: make sure that maxopd will be large @@ -2612,25 +2593,17 @@ tcp_mss(tp, offer) */ if (rt->rt_rmx.rmx_mtu) mss = rt->rt_rmx.rmx_mtu - min_protoh; - else - { - mss = -#ifdef INET6 - (isipv6 ? nd_ifinfo[rt->rt_ifp->if_index].linkmtu : -#endif - ifp->if_mtu -#ifdef INET6 - ) -#endif - - min_protoh; -#ifdef INET6 + else { if (isipv6) { + mss = nd_ifinfo[rt->rt_ifp->if_index].linkmtu - + min_protoh; if (!in6_localaddr(&inp->in6p_faddr)) mss = min(mss, tcp_v6mssdflt); - } else -#endif - if (!in_localaddr(inp->inp_faddr)) - mss = min(mss, tcp_mssdflt); + } else { + mss = ifp->if_mtu - min_protoh; + if (!in_localaddr(inp->inp_faddr)) + mss = min(mss, tcp_mssdflt); + } } mss = min(mss, offer); /* @@ -2700,16 +2673,8 @@ tcp_mss(tp, offer) * Set the slow-start flight size depending on whether this * is a local network or not. */ - if ( -#ifdef INET6 - (isipv6 && in6_localaddr(&inp->in6p_faddr)) || - (!isipv6 && -#endif - in_localaddr(inp->inp_faddr) -#ifdef INET6 - ) -#endif - ) + if ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || + (!isipv6 && in_localaddr(inp->inp_faddr))) tp->snd_cwnd = mss * ss_fltsz_local; else tp->snd_cwnd = mss * ss_fltsz; @@ -2735,68 +2700,55 @@ tcp_mssopt(tp) { struct rtentry *rt; #ifdef INET6 - int isipv6; - int min_protoh; -#endif - -#ifdef INET6 - isipv6 = ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) ? 1 : 0; - min_protoh = isipv6 ? sizeof (struct ip6_hdr) + sizeof (struct tcphdr) - : sizeof (struct tcpiphdr); + int isipv6 = ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) ? 1 : 0; + size_t min_protoh = isipv6 ? + sizeof (struct ip6_hdr) + sizeof (struct tcphdr) : + sizeof (struct tcpiphdr); #else -#define min_protoh (sizeof (struct tcpiphdr)) + const int isipv6 = 0; + const size_t min_protoh = sizeof (struct tcpiphdr); #endif -#ifdef INET6 + if (isipv6) rt = tcp_rtlookup6(&tp->t_inpcb->inp_inc); else -#endif /* INET6 */ - rt = tcp_rtlookup(&tp->t_inpcb->inp_inc); + rt = tcp_rtlookup(&tp->t_inpcb->inp_inc); if (rt == NULL) - return -#ifdef INET6 - isipv6 ? tcp_v6mssdflt : -#endif /* INET6 */ - tcp_mssdflt; + return (isipv6 ? tcp_v6mssdflt : tcp_mssdflt); - return rt->rt_ifp->if_mtu - min_protoh; + return (rt->rt_ifp->if_mtu - min_protoh); } /* - * Checks for partial ack. If partial ack arrives, force the retransmission - * of the next unacknowledged segment, do not clear tp->t_dupacks, and return - * 1. By setting snd_nxt to ti_ack, this forces retransmission timer to - * be started again. If the ack advances at least to tp->snd_recover, return 0. + * On a partial ack arrives, force the retransmission of the + * next unacknowledged segment. Do not clear tp->t_dupacks. + * By setting snd_nxt to ti_ack, this forces retransmission timer to + * be started again. */ -static int -tcp_newreno(tp, th) +static void +tcp_newreno_partial_ack(tp, th) struct tcpcb *tp; struct tcphdr *th; { - if (SEQ_LT(th->th_ack, tp->snd_recover)) { - tcp_seq onxt = tp->snd_nxt; - u_long ocwnd = tp->snd_cwnd; + tcp_seq onxt = tp->snd_nxt; + u_long ocwnd = tp->snd_cwnd; - callout_stop(tp->tt_rexmt); - tp->t_rtttime = 0; - tp->snd_nxt = th->th_ack; - /* - * Set snd_cwnd to one segment beyond acknowledged offset - * (tp->snd_una has not yet been updated when this function - * is called) - */ - tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una); - (void) tcp_output(tp); - tp->snd_cwnd = ocwnd; - if (SEQ_GT(onxt, tp->snd_nxt)) - tp->snd_nxt = onxt; - /* - * Partial window deflation. Relies on fact that tp->snd_una - * not updated yet. - */ - tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); - return (1); - } - return (0); + callout_stop(tp->tt_rexmt); + tp->t_rtttime = 0; + tp->snd_nxt = th->th_ack; + /* + * Set snd_cwnd to one segment beyond acknowledged offset. + * (tp->snd_una has not yet been updated when this function is called.) + */ + tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una); + (void) tcp_output(tp); + tp->snd_cwnd = ocwnd; + if (SEQ_GT(onxt, tp->snd_nxt)) + tp->snd_nxt = onxt; + /* + * Partial window deflation. Relies on fact that tp->snd_una + * not updated yet. + */ + tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); } |