📄 tp_subr2.c
字号:
*/inttp_mask_to_num(x) u_char x;{ register int j; for(j = 4; j>=0 ;j--) { if(x & (1<<j)) break; } ASSERT( (j == 4) || (j == 0) ); /* for now */ if( (j != 4) && (j != 0) ) { printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", x, j); } IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); ENDTRACE IFDEBUG(D_TPINPUT) printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); ENDDEBUG return j;}static copyQOSparms(src, dst) struct tp_conn_param *src, *dst;{ /* copy all but the bits stuff at the end */#define COPYSIZE (12 * sizeof(short)) bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE); dst->p_tpdusize = src->p_tpdusize; dst->p_ack_strat = src->p_ack_strat; dst->p_rx_strat = src->p_rx_strat;#undef COPYSIZE}/* * Determine a reasonable value for maxseg size. * If the route is known, check route for mtu. * 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. */voidtp_mss(tpcb, nhdr_size) register struct tp_pcb *tpcb; int nhdr_size;{ register struct rtentry *rt; struct ifnet *ifp; register int rtt, mss; u_long bufsize; int i, ssthresh = 0, rt_mss; struct socket *so; if (tpcb->tp_ptpdusize) mss = tpcb->tp_ptpdusize << 7; else mss = 1 << tpcb->tp_tpdusize; so = tpcb->tp_sock; if ((rt = *(tpcb->tp_routep)) == 0) { bufsize = so->so_rcv.sb_hiwat; goto punt_route; } ifp = rt->rt_ifp;#ifdef RTV_MTU /* if route characteristics exist ... */ /* * While we're here, check if there's an initial rtt * or rttvar. Convert from the route-table units * to hz ticks for the smoothed timers and slow-timeout units * for other inital variables. */ if (tpcb->tp_rtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) { tpcb->tp_rtt = rtt * hz / RTM_RTTUNIT; if (rt->rt_rmx.rmx_rttvar) tpcb->tp_rtv = rt->rt_rmx.rmx_rttvar * hz / RTM_RTTUNIT; else tpcb->tp_rtv = tpcb->tp_rtt; } /* * if there's an mtu associated with the route, use it */ if (rt->rt_rmx.rmx_mtu) rt_mss = rt->rt_rmx.rmx_mtu - nhdr_size; else#endif /* RTV_MTU */ rt_mss = (ifp->if_mtu - nhdr_size); if (tpcb->tp_ptpdusize == 0 || /* assume application doesn't care */ mss > rt_mss /* network won't support what was asked for */) mss = rt_mss; /* can propose mtu which are multiples of 128 */ mss &= ~0x7f; /* * If there's a pipesize, change the socket buffer * to that size. */#ifdef RTV_SPIPE if ((bufsize = rt->rt_rmx.rmx_sendpipe) > 0) {#endif bufsize = min(bufsize, so->so_snd.sb_hiwat); (void) sbreserve(&so->so_snd, bufsize); }#ifdef RTV_SPIPE if ((bufsize = rt->rt_rmx.rmx_recvpipe) > 0) {#endif bufsize = min(bufsize, so->so_rcv.sb_hiwat); (void) sbreserve(&so->so_rcv, bufsize); } else bufsize = so->so_rcv.sb_hiwat;#ifdef RTV_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. */ ssthresh = rt->rt_rmx.rmx_ssthresh;punt_route: /* * The current mss 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. * If we received an offer, don't exceed it. * However, do not accept offers under 128 bytes. */ if (tpcb->tp_l_tpdusize) mss = min(mss, tpcb->tp_l_tpdusize); /* * We want a minimum recv window of 4 packets to * signal packet loss by duplicate acks. */ mss = min(mss, bufsize >> 2) & ~0x7f; mss = max(mss, 128); /* sanity */ tpcb->tp_cong_win = (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) ? mss : bufsize; tpcb->tp_l_tpdusize = mss; tp_rsyset(tpcb); tpcb->tp_ssthresh = max(2 * mss, ssthresh); /* Calculate log2 of mss */ for (i = TP_MIN_TPDUSIZE + 1; i <= TP_MAX_TPDUSIZE; i++) if ((1 << i) > mss) break; i--; tpcb->tp_tpdusize = i;#endif /* RTV_MTU */}/* * CALLED FROM: * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR * * FUNCTION and ARGUMENTS: * -- An mbuf containing the peer's network address. * -- Our control block, which will be modified * -- In the case of cons, a control block for that layer. * * * RETURNS: * errno value : * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) * ECONNREFUSED if trying to run TP0 with non-type 37 address * possibly other E* returned from cons_netcmd() * * SIDE EFFECTS: * Determines recommended tpdusize, buffering and intial delays * based on information cached on the route. */inttp_route_to( m, tpcb, channel) struct mbuf *m; register struct tp_pcb *tpcb; caddr_t channel;{ register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ extern struct tp_conn_param tp_conn_param[]; int error = 0, save_netservice = tpcb->tp_netservice; register struct rtentry *rt = 0; int nhdr_size, mtu, bufsize; siso = mtod(m, struct sockaddr_iso *); IFTRACE(D_CONN) tptraceTPCB(TPPTmisc, "route_to: so afi netservice class", tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice, tpcb->tp_class); ENDTRACE IFDEBUG(D_CONN) printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", m, channel, tpcb, tpcb->tp_netservice); printf("m->mlen x%x, m->m_data:\n", m->m_len); dump_buf(mtod(m, caddr_t), m->m_len); ENDDEBUG if (channel) {#ifdef TPCONS struct pklcd *lcp = (struct pklcd *)channel; struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext, *isop_new = (struct isopcb *)tpcb->tp_npcb; /* The next 2 lines believe that you haven't set any network level options or done a pcbconnect and XXXXXXX'edly apply to both inpcb's and isopcb's */ remque(isop_new); free(isop_new, M_PCB); tpcb->tp_npcb = (caddr_t)isop; tpcb->tp_netservice = ISO_CONS; tpcb->tp_nlproto = nl_protosw + ISO_CONS; if (isop->isop_refcnt++ == 0) { iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL); isop->isop_socket = tpcb->tp_sock; } else /* there are already connections sharing this */;#endif } else { switch (siso->siso_family) { default: error = EAFNOSUPPORT; goto done;#ifdef ISO case AF_ISO: { struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; int flags = tpcb->tp_sock->so_options & SO_DONTROUTE; tpcb->tp_netservice = ISO_CLNS; if (clnp_route(&siso->siso_addr, &isop->isop_route, flags, (void **)0, (void **)0) == 0) { rt = isop->isop_route.ro_rt; if (rt && rt->rt_flags & RTF_PROTO1) tpcb->tp_netservice = ISO_CONS; } } break;#endif#ifdef INET case AF_INET: tpcb->tp_netservice = IN_CLNS;#endif } if (tpcb->tp_nlproto->nlp_afamily != siso->siso_family) { IFDEBUG(D_CONN) printf("tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", save_netservice, tpcb->tp_netservice); ENDDEBUG if (error = tp_set_npcb(tpcb)) goto done; } IFDEBUG(D_CONN) printf("tp_route_to calling nlp_pcbconn, netserv %d\n", tpcb->tp_netservice); ENDDEBUG tpcb->tp_nlproto = nl_protosw + tpcb->tp_netservice; error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_npcb, m); } if (error) goto done; nhdr_size = tpcb->tp_nlproto->nlp_mtu(tpcb); /* only gets common info */ tp_mss(tpcb, nhdr_size);done: IFDEBUG(D_CONN) printf("tp_route_to returns 0x%x\n", error); ENDDEBUG IFTRACE(D_CONN) tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, tpcb->tp_netservice, tpcb->tp_class, 0); ENDTRACE return error;}/* class zero version */voidtp0_stash( tpcb, e ) register struct tp_pcb *tpcb; register struct tp_event *e;{#ifndef lint#define E e->ATTR(DT_TPDU)#else /* lint */#define E e->ev_union.EV_DT_TPDU#endif /* lint */ register struct sockbuf *sb = &tpcb->tp_sock->so_rcv; register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; IFPERF(tpcb) PStat(tpcb, Nb_from_ll) += E.e_datalen; tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time, E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen); ENDPERF IFDEBUG(D_STASH) printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x", E.e_seq, E.e_datalen, E.e_eot); ENDDEBUG IFTRACE(D_STASH) tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", E.e_seq, E.e_datalen, E.e_eot, 0); ENDTRACE if ( E.e_eot ) { register struct mbuf *n = E.e_data; n->m_flags |= M_EOR; n->m_act = MNULL; /* set on tp_input */ } sbappend(sb, E.e_data); IFDEBUG(D_STASH) dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending"); ENDDEBUG if (tpcb->tp_netservice != ISO_CONS) printf("tp0_stash: tp running over something wierd\n"); else { register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; pk_flowcontrol(lcp, sbspace(sb) <= 0, 1); }} voidtp0_openflow(tpcb)register struct tp_pcb *tpcb;{ register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; if (tpcb->tp_netservice != ISO_CONS) printf("tp0_openflow: tp running over something wierd\n"); else { register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; if (lcp->lcd_rxrnr_condition) pk_flowcontrol(lcp, 0, 0); }}#ifndef TPCONSstaticpk_flowcontrol() {}#endif#ifdef TP_PERF_MEAS/* * CALLED FROM: * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on * and tp_newsocket() when a new connection is made from * a listening socket with tp_perf_on == true. * FUNCTION and ARGUMENTS: * (tpcb) is the usual; this procedure gets a clear cluster mbuf for * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. * RETURN VALUE: * ENOBUFS if it cannot get a cluster mbuf. */int tp_setup_perf(tpcb) register struct tp_pcb *tpcb;{ register struct mbuf *q; if( tpcb->tp_p_meas == 0 ) { MGET(q, M_WAITOK, MT_PCB); if (q == 0) return ENOBUFS; MCLGET(q, M_WAITOK); if ((q->m_flags & M_EXT) == 0) { (void) m_free(q); return ENOBUFS; } q->m_len = sizeof (struct tp_pmeas); tpcb->tp_p_mbuf = q; tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); IFDEBUG(D_PERF_MEAS) printf( "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", tpcb, tpcb->tp_sock, tpcb->tp_lref, tpcb->tp_p_meas, tpcb->tp_perf_on); ENDDEBUG tpcb->tp_perf_on = 1; } return 0;}#endif /* TP_PERF_MEAS */#ifdef ARGO_DEBUGdump_addr (addr) register struct sockaddr *addr;{ switch( addr->sa_family ) { case AF_INET: dump_inaddr((struct sockaddr_in *)addr); break;#ifdef ISO case AF_ISO: dump_isoaddr((struct sockaddr_iso *)addr); break;#endif /* ISO */ default: printf("BAD AF: 0x%x\n", addr->sa_family); break; }}#define MAX_COLUMNS 8/* * Dump the buffer to the screen in a readable format. Format is: * * hex/dec where hex is the hex format, dec is the decimal format. * columns of hex/dec numbers will be printed, followed by the * character representations (if printable). */Dump_buf(buf, len)caddr_t buf;int len;{ int i,j;#define Buf ((u_char *)buf) printf("Dump buf 0x%x len 0x%x\n", buf, len); for (i = 0; i < len; i += MAX_COLUMNS) { printf("+%d:\t", i); for (j = 0; j < MAX_COLUMNS; j++) { if (i + j < len) { printf("%x/%d\t", Buf[i+j], Buf[i+j]); } else { printf(" "); } } for (j = 0; j < MAX_COLUMNS; j++) { if (i + j < len) { if (((Buf[i+j]) > 31) && ((Buf[i+j]) < 128)) printf("%c", Buf[i+j]); else printf("."); } } printf("\n"); }}#endif /* ARGO_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -