⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpmisc.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 5 页
字号:
    {        if ((svp->sv_state == ESTAB) || (svp->sv_state == CLOSE_WAIT))        count++;    }    normal;    return count;   /* 's ok */}#endif  /* SNMP */#ifdef  SV_SKEPTIC/* called by h_nwfree() *//* quickly scan the state vectors for any reference to the item being freed. */export  boolean sv_check (fast u32 * ref){    fast    tcpsv_t * svp;    use_critical;    if (tcp_prp == (pr_t *)0)        return true;    /* allow time to initialize */    critical;    for (svp = (tcpsv_t *)tcp_q.q_next; svp != (tcpsv_t *)&tcp_q;               svp = (tcpsv_t *)svp->sv_q.q_next)     {        fast    int     i;        for (i = 0; i < MAXREF; i++)            if (svp->sv_ref[i] == ref) {                normal;                return false;   /* there is a reference! */            }    }    normal;    return true;    /* it's ok */}#endif/* msd:  There are several notions that are wrong with this attach/detach * code. First, the idea that TCP needs a private shared resource mechanism * with such control is ludicrous; this mechanism should be generalized and * this code omitted.  Second, the assumption is made here that the argument * bound to the 'ref' parameter is always a data space pointer (such as is * used with 'os_sleep'); however, this assumption is routinely violated by * TCP by its passing function pointers as 'ref', thus providing ambiguity  * on machines where code and data pointers are not mutually exclusive. *//* detach a state vector in tcp_q, returning the next state vector in the    queue. */export  tcpsv_t *#ifdef  SV_SKEPTIC_sv_detach (fast tcpsv_t * svp, fast u32 * ref, fast boolean m_ok)#else_sv_detach (fast tcpsv_t * svp)#endif{#ifdef  SV_SKEPTIC    fast    int     i, cnt;#endif    tcpsv_t * nsvp;    use_critical;    critical;    assert(svp->sv_refcnt != 0, "sv_detach: incorrect refcnt!\n");#ifdef  SV_SKEPTIC    for (i = 0, cnt = 0; i < MAXREF; i++) {        if (svp->sv_ref[i] == ref) {            cnt++;            if (cnt == 1)                svp->sv_ref[i] = (u32 *)0;        }    }    if (cnt == 0  &&  svp->sv_overflow > 0) {        /* might have been one that overflowed... */        svp->sv_overflow--;        cnt = 1;        /* pretend that we found it */    }    debug2(!m_ok  &&  cnt > 1, "sv_detach: multiple references (%d) @ 0x%x\n", cnt, ref);    assert(cnt > 0, "sv_detach: not referenced\n");    assert(m_ok  ||  (cnt == 1), "sv_detach: multiple references\n");#endif  /*SV_SKEPTIC*/    nsvp = (tcpsv_t *)svp->sv_q.q_next;     /* pointer to the next state vector */    if (--svp->sv_refcnt == 0) {        if (svp->sv_q.q_flags & F_Q_ZAPPED) {   /* zombie */            q_out(&svp->sv_q);            h_free((i32 *)svp);        }    }    normal;    return nsvp;} /* _sv_detach *//* bind a state vector so it won't go away on us */export  void#ifdef  SV_SKEPTIC_sv_bind (fast tcpsv_t * svp, fast u32 * ref, fast boolean m_ok)#else_sv_bind (fast tcpsv_t * svp)#endif{#ifdef  SV_SKEPTIC    fast    int     i;        boolean stored;    use_critical;    critical;    if (!m_ok) {    /* some types of references can be multiple (like routines) */    /* check for multiple reference */    for (i = 0; i < MAXREF; i++)        if (svp->sv_ref[i] == ref)           {            OS_PANIC0("sv_bind: already referenced\n");           }    }    /* store the reference in an available slot (if any) */    for (i = 0, stored = false; i < MAXREF; i++)        if (svp->sv_ref[i] == (u32 *)0) {            svp->sv_ref[i] = ref;            stored = true;            break;  /* for */        }    if (!stored)        svp->sv_overflow++;    svp->sv_refcnt++;    normal;#else    svp->sv_refcnt++;#endif} /* _sv_bind */ /*******************************************************************/static void tcp_free_saved_messages(tcpsv_t *svp){ int iter; m *dmp; /* Free any saved MSS-sized messages that have been saved for reuse */ for (iter = 0; iter < svp->sv_num_mss_sized_msgs; iter++) {	 dmp = svp->sv_tcp_mss_sized_msgs[iter];	 if (dmp == (m *) 0 ) { 		 continue; }	 svp->sv_tcp_mss_sized_msgs[iter] = (m *) 0; 	 dmp->m_dispfn = smnil;	 dmp->m_owners = 1; /* hack to make sure m_free frees this message						   even if its gone thru m_free before and not						   gotten freed due to m_termfn, but the owners						   field would have been decremented then */     sv_m_detach(dmp);	 smkill(dmp); } /* for */ svp->sv_num_mss_sized_msgs = 0;  /* Free any saved ACK-sized messages that have been saved for reuse */ for (iter = 0; iter < svp->sv_num_ack_sized_msgs; iter++) {     dmp = svp->sv_tcp_ack_sized_msgs[iter];	 if (dmp == (m *) 0 ) {		 continue; 	 }	 svp->sv_tcp_ack_sized_msgs[iter] = (m *) 0;	 dmp->m_dispfn = smnil;	 dmp->m_owners = 1; /* hack to make sure m_free frees this message						   even if its gone thru m_free before and not						   gotten freed due to m_termfn, but the owners						   field would have been decremented then */     sv_m_detach(dmp);	 smkill(dmp); } /* for */ svp->sv_num_ack_sized_msgs = 0; } /* tcp_free_saved_messages *//*******************************************************************//* Retransmission Timeout Event */export  int     tcp_rextimer (void * uarg){#define lsvp    ((tcpsv_t *)uarg)    so_t    * sop;    use_critical;    trace0(tcp_trxmit, "tcp_rextimer\n");    assert((lsvp->sv_q.q_flags & F_Q_ZAPPED) == 0, "tcp_rextimer: called with zapped sv\n");    critical;    (void) t_stop(lsvp->sv_rextcb);  /* stop further timer events on this sv */    if (lsvp->sv_flags & SV_EOF)        tcp_finpkt((m *)0, lsvp);        /* generate an EOF packet */    if (lsvp->sv_abort  &&  --lsvp->sv_abort == 0) {  /* check for abortion */      trace0(tcp_trxmit,"ABORT ABORT ABORT \n");        /* abort a state vector, according to state */      switch (lsvp->sv_state)       {        case CLOSED:    /* MUST be the only place the sv is ZAPPED */            /* mark it for death, (zombie) */            lsvp->sv_q.q_flags |= F_Q_ZAPPED;            /* delete the acknowledgement and performance timers */#ifdef TCP_KEEP_ALIVE            tcp_end_ka(lsvp); /* no more Keep-alives */#endif            tcp_no_more_data_in(lsvp);            /* now delete this (the retransmission) timer;             * note that the state vector evaporates during             * the 'sv_detach' call, since this is the last             * reference */            t_delete(lsvp->sv_rextcb);            /* Before "evaporating" the state vector, free any mss-sized messages 			   and any ack-sized messages that may still be hanging on to this svp */            tcp_free_saved_messages(lsvp);            sv_detach(lsvp, lsvp->sv_rextcb, false);            break;                    case TIME_WAIT:            tcp_rslf(lsvp, AB_UC);   /* normal close */            /* Reset self changes state to CLOSED. */            break;                    default:        /* reset(current) */            sop = sv_valid_sop(lsvp, sop);            if (sop != (so_t *)0)                so_notify(sop, TIMEOUT_NOTIFY);            tcpabort(lsvp, FNS_ETIMEDOUT);            debug0(tcp_debug, "tcp_rextimer: connection timed out\n");        }        normal;        return 0;    }#if 0	else	os_printf("\n(%d) tcp_rextimer: retransmit timeout, period=%d\n", 	          t_time,t_period(lsvp->sv_rextcb));#endif#ifdef TCP_SS_CA_FRETR_FREC 	/* When slow-start/congestion avoidance is enabled, a retransmission timeout	   causes us to reduce the congestion window to the "slow start" value (one 	   segment), and to set the "slow start threshold" to 1/2 the current 	   operational send window (but not less than two segments). */	if (lsvp->sv_flags2 & SV_SLOW_START_CA) {       lsvp->sv_ssthresh = ((TCP_OPERATIONAL_SEND_WINDOW(lsvp)) >> 1);	   if (lsvp->sv_ssthresh <  ( ((u32) lsvp->sv_mssd) << 1) ) {	      lsvp->sv_ssthresh = (lsvp->sv_mssd << 1);	   }	   lsvp->sv_cwnd = lsvp->sv_mssd; /* puts us into slow-start */	} /* if */#endif	/* Retransmission timer backoff -- double the retrnasmission timer until	   we get a good rtt measurment again -- but keep it bounded by the 	   configured limits */		{u32 delay = (lsvp->sv_retrtim <<= 1);	 if (delay > lsvp->sv_maxretrim) { delay = lsvp->sv_maxretrim;}	 else if (delay < lsvp->sv_minretrim) { delay = lsvp->sv_minretrim;}	 lsvp->sv_retrtim = delay;	}#    /*  bug fix do not include re-transmission in RTT computation */    lsvp->sv_flags &= ~(SV_NOPROBE|SV_XTIME);   /* can probe again now */  /* Retransmission */   trace2(tcp_trxmit, "<RETRANSMIT: RTT %d S %d> "                /*msddebug*/            ,(int)(lsvp->sv_retrtim)                              /*msddebug*/            ,(u16)(MU32(lsvp->sv_suna) % 10000L));                /*msddebug*/    tcp_retransmit_fsm(lsvp, TCP_RETR_TIMEOUT); /* will always return true in 												   this circumstance so no need												   to check return value, just												   call sqxmit */    normal;    tcp_sqxmit(lsvp); /* retransmit */    return 0;#undef lsvp}#ifdef TCP_WND_SCALE/************************************************************************//* Set the receive scale factor for a connection according to the size  *//* of the socket receive buffer. This value will be advertised in the   *//* Window Scale option of a SYN we send out. It will be stored in the   *//* state vector if windowscaling is negotiated by the exchanged of SYNs *//* This function assumes that the size of the receive buffer for this   *//* connection is already finalized.                                     */export u16 tcp_rcv_wscale_value(fast tcpsv_t *svp){ so_t    *sop; int rqmax; u16 wscale;	 sop = sv_valid_sop(svp,sop); assert(sop != (so_t *) 0, "tcp_rcv_wscale_set: NULL socket pointer"); wscale = 0; rqmax = svp->sv_rq_max; while (rqmax >= 65536) {	 wscale++;	 rqmax >>= 1; } /* while */ return(wscale);} /* tcp_rcv_wscale_value */#endif/************************************************************************//* set a potentially new  send MSS *//* MUST be called in critical section *//* This routine is called from tcp_rsyn on receipt of a SYN packet with the * remote side's MSS option, and from tcp_dink when sending a SYN.  It just * sets the MSS in the state vector to the smaller of it's present value * (if any) and the new value. *//* MBM -- added "source" parameter to indicate whether this value comes from   a received SYN or not. If the SV_USE_PEER_MSS_OPTION flag is set (meaning   the corresponding socket option was set), then an mss coming from a received   SYN overrides any other value *//* MBM -- its getting more complicated all the time. For transaction TCP, we   cache the MSS from the previous (if any) transaction with the other host.   And we use that initally for this transaction. */export  void    tcp_set_send_mss (fast tcpsv_t *svp, fast u16 mss, int source){    so_t    *sop;	int its_been_decided = 0;	use_critical;		sop = sv_valid_sop(svp,sop);    assert(sop != (so_t *) 0, "tcp_set_send_mss: NULL socket pointer");#ifdef IP_RFC_1191    /* some pre-processing based on the source of this MSS value */	if (source == TCP_MSS_SOURCE_PEER) {	    /* remember the peer-sent MSS for later use */		svp->sv_peer_mss = mss;	} else if (source == TCP_MSS_SOURCE_PATH_MTU) {	   /* Don't allow an MSS coming from path-mtu-discovery 	      cause us to set our send MSS larger than that which 		  came from the peer */	   if ( (svp->sv_peer_mss != 0) && (mss > svp->sv_peer_mss) ) {	      mss = svp->sv_peer_mss;	   }	}#endif /* IP_RFC_1191 */    /* never allow an MSS to be set beyond the absolute configured maximum */	if ((u16)tcp_max_mss  &&  mss > (u16)tcp_max_mss)        mss = (u16)tcp_max_mss;    /* If this socket is configured to let the peer's MSS option override	   any other considerations, take care of that */    if (svp->sv_flags2 & SV_USE_PEER_MSS_OPTION) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -