?? tcp_input.c
字號:
* Make ACK acceptable to originator of segment. * Don't bother to respond if destination was broadcast/multicast. */ if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST) || IN_MULTICAST(ntohl(ti->ti_dst.s_addr))) goto drop; if (tiflags & TH_ACK) tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); else { if (tiflags & TH_SYN) ti->ti_len++; tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, TH_RST|TH_ACK); } /* MIB-II Count # of Resets Sent */#ifdef VIRTUAL_STACK /* * (Former) tcpOutRsts global renamed for virtual stacks to prevent * name conflict with existing structure element in m2TcpLib.c file. */ tcpOutResets++;#else tcpOutRsts++;#endif /* destroy temporarily created socket */ if (dropsocket) (void) soabort(so); return;drop: /* * Drop space held by incoming segment and return. */ if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) (*tcpTraceRtn)(TA_DROP, ostate, tp, &tcp_saveti, 0); m_freem(m); /* destroy temporarily created socket */ if (dropsocket) (void) soabort(so); return;}voidtcp_dooptions(tp, cp, cnt, ti, ts_present, ts_val, ts_ecr) struct tcpcb *tp; u_char *cp; int cnt; struct tcpiphdr *ti; int *ts_present; u_long *ts_val, *ts_ecr;{ u_short mss = 0; int opt, optlen; for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[0]; if (opt == TCPOPT_EOL) break; if (opt == TCPOPT_NOP) optlen = 1; else { optlen = cp[1]; if (optlen <= 0) break; } switch (opt) { default: continue; case TCPOPT_MAXSEG: if (optlen != TCPOLEN_MAXSEG) continue; if (!(ti->ti_flags & TH_SYN)) continue; bcopy((char *) cp + 2, (char *) &mss, sizeof(mss)); NTOHS(mss); (void) tcp_mss(tp, mss); /* sets t_maxseg */ break; case TCPOPT_WINDOW: if (optlen != TCPOLEN_WINDOW) continue; if (!(ti->ti_flags & TH_SYN)) continue; tp->t_flags |= TF_RCVD_SCALE; tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); break; case TCPOPT_TIMESTAMP: if (optlen != TCPOLEN_TIMESTAMP) continue; *ts_present = 1; bcopy((char *)cp + 2, (char *) ts_val, sizeof(*ts_val)); NTOHL(*ts_val); bcopy((char *)cp + 6, (char *) ts_ecr, sizeof(*ts_ecr)); NTOHL(*ts_ecr); /* * A timestamp received in a SYN makes * it ok to send timestamp requests and replies. */ if (ti->ti_flags & TH_SYN) { tp->t_flags |= TF_RCVD_TSTMP; tp->ts_recent = *ts_val; tp->ts_recent_age = tcp_now; } break; } } /* * Set peer's MSS to default if option not included. The path MTU * discovery processing for TCP uses this value as a ceiling to * avoid sending larger segments than a peer can handle. */ if ( (ti->ti_flags & TH_SYN) && !mss) { if (tp->t_inpcb->inp_route.ro_rt) (tp->t_inpcb->inp_route.ro_rt)->rt_rmx.rmx_mss = tcp_mssdflt; }}/* * Pull out of band byte out of a segment so * it doesn't appear in the user's data queue. * It is still reflected in the segment length for * sequencing purposes. */voidtcp_pulloutofband(so, ti, m) struct socket *so; struct tcpiphdr *ti; register struct mbuf *m;{ int cnt = ti->ti_urp - 1; while (cnt >= 0) { if (m->m_len > cnt) { char *cp = mtod(m, caddr_t) + cnt; struct tcpcb *tp = sototcpcb(so); tp->t_iobc = *cp; tp->t_oobflags |= TCPOOB_HAVEDATA; bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1)); m->m_len--; return; } cnt -= m->m_len; m = m->m_next; if (m == 0) break; }#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_EMERGENCY, 27, 1, ti->ti_sport, ti->ti_dport, WV_NETEVENT_TCPOOB_PANIC, WV_NET_RECV, so->so_fd)#endif /* INCLUDE_WVNET */#endif panic("tcp_pulloutofband");}/* * Collect new round-trip time estimate * and update averages and current timeout. */voidtcp_xmit_timer(tp, rtt) register struct tcpcb *tp; short rtt;{ register short delta; tcpstat.tcps_rttupdated++; if (tp->t_srtt != 0) { /* * srtt is stored as fixed point with 3 bits after the * binary point (i.e., scaled by 8). The following magic * is equivalent to the smoothing algorithm in rfc793 with * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed * point). Adjust rtt to origin 0. */ delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT); if ((tp->t_srtt += delta) <= 0) tp->t_srtt = 1; /* * We accumulate a smoothed rtt variance (actually, a * smoothed mean difference), then set the retransmit * timer to smoothed rtt + 4 times the smoothed variance. * rttvar is stored as fixed point with 2 bits after the * binary point (scaled by 4). The following is * equivalent to rfc793 smoothing with an alpha of .75 * (rttvar = rttvar*3/4 + |delta| / 4). This replaces * rfc793's wired-in beta. */ if (delta < 0) delta = -delta; delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); if ((tp->t_rttvar += delta) <= 0) tp->t_rttvar = 1; } else { /* * No rtt measurement yet - use the unsmoothed rtt. * Set the variance to half the rtt (so our first * retransmit happens at 3*rtt). */ tp->t_srtt = rtt << TCP_RTT_SHIFT; tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); } tp->t_rtt = 0; tp->t_rxtshift = 0; /* * the retransmit should happen at rtt + 4 * rttvar. * Because of the way we do the smoothing, srtt and rttvar * will each average +1/2 tick of bias. When we compute * the retransmit timer, we want 1/2 tick of rounding and * 1 extra tick because of +-1/2 tick uncertainty in the * firing of the timer. The bias will give us exactly the * 1.5 tick we need. But, because the bias is * statistical, we have to test that we don't drop below * the minimum feasible timer (which is 2 ticks). */ TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), tp->t_rttmin, TCPTV_REXMTMAX); /* * We received an ack for a packet that wasn't retransmitted; * it is probably safe to discard any error indications we've * received recently. This isn't quite right, but close enough * for now (a route might have failed after we sent a segment, * and the return path might not be symmetrical). */ tp->t_softerror = 0;}/* * Determine a reasonable value for maxseg size. * If the route is known, check route for mtu. * If none, use an mss that can be handled on the outgoing * interface without forcing IP to fragment; * If no route is found, route has no mtu, * or the destination isn't local, use a default, hopefully conservative * size (usually 512 or the default IP max size, but no more than the mtu * of the interface), as we can't discover anything about intervening * gateways or networks. We also initialize the congestion/slow start * window to be a single segment if the destination isn't local. * While looking at the routing entry, we also initialize other path-dependent * parameters from pre-set or cached values in the routing entry. */inttcp_mss(tp, offer) register struct tcpcb *tp; u_int offer;{ struct route *ro; register struct rtentry *rt; struct ifnet *ifp; register int rtt, mss; u_long bufsize; struct inpcb *inp; struct socket *so; inp = tp->t_inpcb; ro = &inp->inp_route; if ((rt = ro->ro_rt) == (struct rtentry *)0) { /* No route yet, so try to acquire one */ if (inp->inp_faddr.s_addr != INADDR_ANY) { ro->ro_dst.sa_family = AF_INET; ro->ro_dst.sa_len = sizeof(ro->ro_dst); ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = inp->inp_faddr; TOS_SET (&ro->ro_dst, inp->inp_ip.ip_tos); rtalloc(ro); } if ((rt = ro->ro_rt) == (struct rtentry *)0) return (tcp_mssdflt); } ifp = rt->rt_ifp; so = inp->inp_socket; /* * While we're here, check if there's an initial rtt * or rttvar. Convert from the route-table units * to scaled multiples of the slow timeout timer. */ if (tp->t_srtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) { /* * XXX the lock bit for MTU indicates that the value * is also a minimum value; this is subject to time. */ if (rt->rt_rmx.rmx_locks & RTV_RTT) tp->t_rttmin = rtt / (RTM_RTTUNIT / PR_SLOWHZ); tp->t_srtt = rtt / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE)); if (rt->rt_rmx.rmx_rttvar) tp->t_rttvar = rt->rt_rmx.rmx_rttvar / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE)); else /* default variation is +- 1 rtt */ tp->t_rttvar = tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE; TCPT_RANGESET(tp->t_rxtcur, ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1, tp->t_rttmin, TCPTV_REXMTMAX); } /* * if there's an mtu associated with the route, use it */ if (rt->rt_rmx.rmx_mtu) mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr); else { mss = ifp->if_mtu - sizeof(struct tcpiphdr); if (!in_localaddr(inp->inp_faddr)) mss = min(mss, tcp_mssdflt); } /* * The current mss, t_maxseg, is initialized to the default value. * If we compute a smaller value, reduce the current mss. * If we compute a larger value, return it for use in sending * a max seg size option, but don't store it for use * unless we received an offer at least that large from peer. * However, do not accept offers under 32 bytes. */ if (offer) { rt->rt_rmx.rmx_mss = offer; /* Save peer's MSS for path MTU. */ mss = min(mss, offer); } mss = max(mss, 32); /* sanity */ /* * Save the maximum allowable segment size (based on mss and mtu * values only) when processing MSS option from peer. */ if (offer) tp->t_maxsize = mss; if (mss < tp->t_maxseg || offer != 0) { /* * If there's a pipesize, change the socket buffer * to that size. Make the socket buffers an integral * number of mss units; if the mss is larger than * the socket buffer, decrease the mss. */ if ((bufsize = rt->rt_rmx.rmx_sendpipe) == 0) bufsize = so->so_snd.sb_hiwat; if (bufsize < mss) mss = bufsize; /* * Record maximum segment size after adjusting * for the send buffer size. */ tp->t_maxseg = mss; if ((bufsize = rt->rt_rmx.rmx_recvpipe) == 0) bufsize = so->so_rcv.sb_hiwat; } tp->snd_cwnd = mss; if (rt->rt_rmx.rmx_ssthresh) { /* * There's some sort of gateway or interface * buffer limit on the path. Use this to set * the slow start threshhold, but set the * threshold to no less than 2*mss. */ tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh); } return (mss);}#ifdef TCP_DEBUG /* XXX just for debugging */void tcbShow ( FAST struct inpcb *pinPcb /* pointer to the pcb control block */ ) { struct tcpcb * pTcpCb; /* pointer to tcp Control block */ pTcpCb = (struct tcpcb *) pinPcb->inp_ppcb; printf ("send unacknowledged: %8u\n", pTcpCb->snd_una); printf ("send next: %8u\n", pTcpCb->snd_nxt); printf ("send window update seg seqnumber: %8u\n", pTcpCb->snd_wl1); printf ("send window updata seg ack number: %8u\n", pTcpCb->snd_wl2); printf ("send window: %8u\n", pTcpCb->snd_wnd); printf ("recv window: %8u\n", pTcpCb->rcv_wnd); printf ("recv next: %8u\n", pTcpCb->rcv_nxt); printf ("recv advertised window by other end: %8u\n", pTcpCb->rcv_adv); printf ("send highest sequence number sent: %8u\n", pTcpCb->snd_max); printf ("congestion controlled window: %8u\n", pTcpCb->snd_cwnd); printf ("congestion threshold: %8u\n", pTcpCb->snd_ssthresh); printf ("largest window peer has offered: %8u\n", pTcpCb->max_sndwnd); printf ("send scale %8u\n", pTcpCb->snd_scale) ; printf ("recv scale %8u\n", pTcpCb->rcv_scale) ; printf ("send pending window scale %8u\n", pTcpCb->request_r_scale) ; printf ("recv pending window scale %8u\n", pTcpCb->requested_s_scale) ; }#endif /* XXX just for debugging */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -