|
|
1.1 root 1: /*-
2: * Copyright (c) 1991 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
1.1.1.3 ! root 33: * from: @(#)tp_subr2.c 7.10 (Berkeley) 6/27/91
! 34: * tp_subr2.c,v 1.2 1993/05/20 05:27:59 cgd Exp
1.1 root 35: */
36:
37: /***********************************************************
38: Copyright IBM Corporation 1987
39:
40: All Rights Reserved
41:
42: Permission to use, copy, modify, and distribute this software and its
43: documentation for any purpose and without fee is hereby granted,
44: provided that the above copyright notice appear in all copies and that
45: both that copyright notice and this permission notice appear in
46: supporting documentation, and that the name of IBM not be
47: used in advertising or publicity pertaining to distribution of the
48: software without specific, written prior permission.
49:
50: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
51: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
52: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
54: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
55: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56: SOFTWARE.
57:
58: ******************************************************************/
59:
60: /*
61: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
62: */
63: /*
64: * ARGO TP
65: *
66: * Some auxiliary routines:
67: * tp_protocol_error: required by xebec- called when a combo of state,
68: * event, predicate isn't covered for by the transition file.
69: * tp_indicate: gives indications(signals) to the user process
70: * tp_getoptions: initializes variables that are affected by the options
71: * chosen.
72: */
73:
74: /* this def'n is to cause the expansion of this macro in the
75: * routine tp_local_credit :
76: */
77: #define LOCAL_CREDIT_EXPAND
78:
79: #include "param.h"
80: #include "systm.h"
81: #include "mbuf.h"
82: #include "socket.h"
83: #include "socketvar.h"
84: #include "domain.h"
85: #include "protosw.h"
86: #include "errno.h"
87: #include "types.h"
88: #include "time.h"
89: #include "kernel.h"
90: #undef MNULL
91: #include "argo_debug.h"
92: #include "tp_param.h"
93: #include "tp_ip.h"
94: #include "iso.h"
95: #include "iso_errno.h"
96: #include "iso_pcb.h"
97: #include "tp_timer.h"
98: #include "tp_stat.h"
99: #include "tp_tpdu.h"
100: #include "tp_pcb.h"
101: #include "tp_seq.h"
102: #include "tp_trace.h"
103: #include "tp_user.h"
104: #include "cons.h"
105:
106: #include "../net/if.h"
107: #ifdef TRUE
108: #undef FALSE
109: #undef TRUE
110: #endif
111: #include "../netccitt/x25.h"
112: #include "../netccitt/pk.h"
113: #include "../netccitt/pk_var.h"
114:
115: /*
116: * NAME: tp_local_credit()
117: *
118: * CALLED FROM:
119: * tp_emit(), tp_usrreq()
120: *
121: * FUNCTION and ARGUMENTS:
122: * Computes the local credit and stashes it in tpcb->tp_lcredit.
123: * It's a macro in the production system rather than a procdure.
124: *
125: * RETURNS:
126: *
127: * SIDE EFFECTS:
128: *
129: * NOTES:
130: * This doesn't actually get called in a production system -
131: * the macro gets expanded instead in place of calls to this proc.
132: * But for debugging, we call this and that allows us to add
133: * debugging messages easily here.
134: */
135: void
136: tp_local_credit(tpcb)
137: struct tp_pcb *tpcb;
138: {
139: LOCAL_CREDIT(tpcb);
140: IFDEBUG(D_CREDIT)
141: printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n",
142: tpcb->tp_refp - tp_ref,
143: tpcb->tp_lcredit,
144: tpcb->tp_l_tpdusize,
145: tpcb->tp_decbit,
146: tpcb->tp_cong_win
147: );
148: ENDDEBUG
149: IFTRACE(D_CREDIT)
150: tptraceTPCB(TPPTmisc,
151: "lcdt tpdusz \n",
152: tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0);
153: ENDTRACE
154: }
155:
156: /*
157: * NAME: tp_protocol_error()
158: *
159: * CALLED FROM:
160: * tp_driver(), when it doesn't know what to do with
161: * a combo of event, state, predicate
162: *
163: * FUNCTION and ARGUMENTS:
164: * print error mesg
165: *
166: * RETURN VALUE:
167: * EIO - always
168: *
169: * SIDE EFFECTS:
170: *
171: * NOTES:
172: */
173: int
174: tp_protocol_error(e,tpcb)
175: struct tp_event *e;
176: struct tp_pcb *tpcb;
177: {
178: printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n",
179: tpcb, e->ev_number, tpcb->tp_state);
180: IFTRACE(D_DRIVER)
181: tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state",
182: tpcb, e->ev_number, tpcb->tp_state, 0 );
183: ENDTRACE
184: return EIO; /* for lack of anything better */
185: }
186:
187:
188: /* Not used at the moment */
189: ProtoHook
190: tp_drain()
191: {
192: return 0;
193: }
194:
195:
196: /*
197: * NAME: tp_indicate()
198: *
199: * CALLED FROM:
200: * tp.trans when XPD arrive, when a connection is being disconnected by
201: * the arrival of a DR or ER, and when a connection times out.
202: *
203: * FUNCTION and ARGUMENTS:
204: * (ind) is the type of indication : T_DISCONNECT, T_XPD
205: * (error) is an E* value that will be put in the socket structure
206: * to be passed along to the user later.
207: * Gives a SIGURG to the user process or group indicated by the socket
208: * attached to the tpcb.
209: *
210: * RETURNS: Rien
211: *
212: * SIDE EFFECTS:
213: *
214: * NOTES:
215: */
216: void
217: tp_indicate(ind, tpcb, error)
218: int ind;
219: u_short error;
220: register struct tp_pcb *tpcb;
221: {
222: register struct socket *so = tpcb->tp_sock;
223: IFTRACE(D_INDICATION)
224: tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix),
225: *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid);
226: ENDTRACE
227: IFDEBUG(D_INDICATION)
228: char *ls, *fs;
229: ls = tpcb->tp_lsuffix,
230: fs = tpcb->tp_fsuffix,
231:
232: printf(
233: "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n",
234: ind,
235: *ls, *(ls+1), *fs, *(fs+1),
236: error, /*so->so_pgrp,*/
237: tpcb->tp_no_disc_indications,
238: tpcb->tp_lref);
239: ENDDEBUG
240:
241: if (ind == ER_TPDU) {
242: register struct mbuf *m;
243: struct tp_disc_reason x;
244:
245: if ((so->so_state & SS_CANTRCVMORE) == 0 &&
246: (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) {
247:
248: x.dr_hdr.cmsg_len = m->m_len = sizeof(x);
249: x.dr_hdr.cmsg_level = SOL_TRANSPORT;
250: x.dr_hdr.cmsg_type= TPOPT_DISC_REASON;
251: x.dr_reason = error;
252: *mtod(m, struct tp_disc_reason *) = x;
253: sbappendrecord(&tpcb->tp_Xrcv, m);
254: error = 0;
255: } else
256: error = ECONNRESET;
257: }
258: so->so_error = error;
259:
260: if (ind == T_DISCONNECT) {
261: so->so_error = ENOTCONN;
262: if ( tpcb->tp_no_disc_indications )
263: return;
264: }
265: IFTRACE(D_INDICATION)
266: tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0);
267: ENDTRACE
268: sohasoutofband(so);
269: }
270:
271: /*
272: * NAME : tp_getoptions()
273: *
274: * CALLED FROM:
275: * tp.trans whenever we go into OPEN state
276: *
277: * FUNCTION and ARGUMENTS:
278: * sets the proper flags and values in the tpcb, to control
279: * the appropriate actions for the given class, options,
280: * sequence space, etc, etc.
281: *
282: * RETURNS: Nada
283: *
284: * SIDE EFFECTS:
285: *
286: * NOTES:
287: */
288: void
289: tp_getoptions(tpcb)
290: struct tp_pcb *tpcb;
291: {
292: tpcb->tp_seqmask =
293: tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ;
294: tpcb->tp_seqbit =
295: tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ;
296: tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
297: tpcb->tp_dt_ticks =
298: MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
299:
300: }
301:
302: /*
303: * NAME: tp_recycle_tsuffix()
304: *
305: * CALLED FROM:
306: * Called when a ref is frozen.
307: *
308: * FUNCTION and ARGUMENTS:
309: * allows the suffix to be reused.
310: *
311: * RETURNS: zilch
312: *
313: * SIDE EFFECTS:
314: *
315: * NOTES:
316: */
317: void
318: tp_recycle_tsuffix(tpcb)
319: struct tp_pcb *tpcb;
320: {
321: bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix));
322: bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix));
323: tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
324:
325: (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb);
326: }
327:
328: /*
329: * NAME: tp_quench()
330: *
331: * CALLED FROM:
332: * tp{af}_quench() when ICMP source quench or similar thing arrives.
333: *
334: * FUNCTION and ARGUMENTS:
335: * Drop the congestion window back to 1.
336: * Congestion window scheme:
337: * Initial value is 1. ("slow start" as Nagle, et. al. call it)
338: * For each good ack that arrives, the congestion window is increased
339: * by 1 (up to max size of logical infinity, which is to say,
340: * it doesn't wrap around).
341: * Source quench causes it to drop back to 1.
342: * tp_send() uses the smaller of (regular window, congestion window).
343: * One retransmission strategy option is to have any retransmission
344: * cause reset the congestion window back to 1.
345: *
346: * (cmd) is either PRC_QUENCH: source quench, or
347: * PRC_QUENCH2: dest. quench (dec bit)
348: *
349: * RETURNS:
350: *
351: * SIDE EFFECTS:
352: *
353: * NOTES:
354: */
355: void
356: tp_quench( tpcb, cmd )
357: struct tp_pcb *tpcb;
358: int cmd;
359: {
360: IFDEBUG(D_QUENCH)
361: printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n",
362: tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix));
363: printf("cong_win 0x%x decbit 0x%x \n",
364: tpcb->tp_cong_win, tpcb->tp_decbit);
365: ENDDEBUG
366: switch(cmd) {
367: case PRC_QUENCH:
368: tpcb->tp_cong_win = 1;
369: IncStat(ts_quench);
370: break;
371: case PRC_QUENCH2:
372: tpcb->tp_cong_win = 1; /* might as well quench source also */
373: tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
374: IncStat(ts_rcvdecbit);
375: break;
376: }
377: }
378:
379:
380: /*
381: * NAME: tp_netcmd()
382: *
383: * CALLED FROM:
384: *
385: * FUNCTION and ARGUMENTS:
386: *
387: * RETURNS:
388: *
389: * SIDE EFFECTS:
390: *
391: * NOTES:
392: */
393: tp_netcmd( tpcb, cmd )
394: struct tp_pcb *tpcb;
395: int cmd;
396: {
397: #ifdef TPCONS
398: struct isopcb *isop;
399: struct pklcd *lcp;
400:
401: if (tpcb->tp_netservice != ISO_CONS)
402: return;
403: isop = (struct isopcb *)tpcb->tp_npcb;
404: lcp = (struct pklcd *)isop->isop_chan;
405: switch (cmd) {
406:
407: case CONN_CLOSE:
408: case CONN_REFUSE:
409: if (isop->isop_refcnt == 1)
410: pk_disconnect(lcp);
411: isop->isop_chan = 0;
412: isop->isop_refcnt = 0;
413: break;
414:
415: default:
416: printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd);
417: break;
418: }
419: #else TPCONS
420: printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
421: #endif
422: }
423: /*
424: * CALLED FROM:
425: * tp_ctloutput() and tp_emit()
426: * FUNCTION and ARGUMENTS:
427: * Convert a class mask to the highest numeric value it represents.
428: */
429:
430: int
431: tp_mask_to_num(x)
432: u_char x;
433: {
434: register int j;
435:
436: for(j = 4; j>=0 ;j--) {
437: if(x & (1<<j))
438: break;
439: }
440: ASSERT( (j == 4) || (j == 0) ); /* for now */
441: if( (j != 4) && (j != 0) ) {
442: printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n",
443: x, j);
444: }
445: IFTRACE(D_TPINPUT)
446: tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0);
447: ENDTRACE
448: IFDEBUG(D_TPINPUT)
449: printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j);
450: ENDDEBUG
451: return j;
452: }
453:
454: static
455: copyQOSparms(src, dst)
456: struct tp_conn_param *src, *dst;
457: {
458: /* copy all but the bits stuff at the end */
459: #define COPYSIZE (12 * sizeof(short))
460:
461: bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE);
462: dst->p_tpdusize = src->p_tpdusize;
463: dst->p_ack_strat = src->p_ack_strat;
464: dst->p_rx_strat = src->p_rx_strat;
465: #undef COPYSIZE
466: }
467:
468: /*
469: * CALLED FROM:
470: * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR
471: *
472: * FUNCTION and ARGUMENTS:
473: * route directly to x.25 if the address is type 37 - GROT.
474: * furthermore, let TP0 handle only type-37 addresses
475: *
476: * Since this assumes that its address argument is in a mbuf, the
477: * parameter was changed to reflect this assumtion. This also
478: * implies that an mbuf must be allocated when this is
479: * called from tp_input
480: *
481: * RETURNS:
482: * errno value :
483: * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic)
484: * ECONNREFUSED if trying to run TP0 with non-type 37 address
485: * possibly other E* returned from cons_netcmd()
486: * NOTE:
487: * Would like to eliminate as much of this as possible --
488: * only one set of defaults (let the user set the parms according
489: * to parameters provided in the directory service).
490: * Left here for now 'cause we don't yet have a clean way to handle
491: * it on the passive end.
492: */
493: int
494: tp_route_to( m, tpcb, channel)
495: struct mbuf *m;
496: register struct tp_pcb *tpcb;
497: caddr_t channel;
498: {
499: register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */
500: extern struct tp_conn_param tp_conn_param[];
501: struct pklcd *lcp = (struct pklcd *)channel;
502: int error = 0;
503:
504: siso = mtod(m, struct sockaddr_iso *);
505: IFTRACE(D_CONN)
506: tptraceTPCB(TPPTmisc,
507: "route_to: so afi netservice class",
508: tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
509: tpcb->tp_class);
510: ENDTRACE
511: IFDEBUG(D_CONN)
512: printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n",
513: m, channel, tpcb, tpcb->tp_netservice);
514: printf("m->mlen x%x, m->m_data:\n", m->m_len);
515: dump_buf(mtod(m, caddr_t), m->m_len);
516: ENDDEBUG
517: if (siso->siso_family != tpcb->tp_domain) {
518: error = EAFNOSUPPORT;
519: goto done;
520: }
521: IFDEBUG(D_CONN)
522: printf("tp_route_to calling nlp_pcbconn, netserv %d\n",
523: tpcb->tp_netservice);
524: ENDDEBUG
525: #ifdef TPCONS
526: if (lcp) {
527: struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext,
528: *isop_new = (struct isopcb *)tpcb->tp_sock->so_pcb;
529: remque(isop_new);
530: free(isop_new, M_PCB);
531: tpcb->tp_sock->so_pcb = (caddr_t)isop;
532: if (isop->isop_refcnt == 0) {
533: extern struct isopcb tp_isopcb;
534: remque(isop);
535: insque(isop, &tp_isopcb);
536: isop->isop_head = &tp_isopcb;
537: iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL);
538: }
539: /* else there are already connections sharing this */
540: isop->isop_refcnt++;
541: } else
542: #endif
543: error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m);
544: if( error )
545: goto done;
546:
547: {
548: register int save_netservice = tpcb->tp_netservice;
549:
550: switch(tpcb->tp_netservice) {
551: case ISO_COSNS:
552: case ISO_CLNS:
553: /* This is a kludge but seems necessary so the passive end
554: * can get long enough timers. sigh.
555: if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET )
556: */
557: #define IDI_OSINET 0x0004 /* bcd of "0004" */
558: if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) {
559: if( tpcb->tp_dont_change_params == 0) {
560: copyQOSparms( &tp_conn_param[ISO_COSNS],
561: &tpcb->_tp_param);
562: }
563: tpcb->tp_flags |= TPF_NLQOS_PDN;
564: }
565: /* drop through to IN_CLNS*/
566: case IN_CLNS:
567: if (iso_localifa(siso))
568: tpcb->tp_flags |= TPF_PEER_ON_SAMENET;
569: if( (tpcb->tp_class & TP_CLASS_4)==0 ) {
570: error = EPROTOTYPE;
571: break;
572: }
573: tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */
574: break;
575:
576: case ISO_CONS:
577: #ifdef TPCONS
578: tpcb->tp_flags |= TPF_NLQOS_PDN;
579: if( tpcb->tp_dont_change_params == 0 ) {
580: copyQOSparms( &tp_conn_param[ISO_CONS],
581: &tpcb->_tp_param);
582: }
583: /*
584: * for use over x.25 really need a small receive window,
585: * need to start slowly, need small max negotiable tpdu size,
586: * and need to use the congestion window to the max
587: * IGNORES tp_dont_change_params for these!
588: */
589: if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) {
590: (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */
591: }
592: tpcb->tp_rx_strat = TPRX_USE_CW;
593:
594: if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) {
595: IFDEBUG(D_CONN)
596: printf(
597: "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
598: tpcb->tp_nlproto , &nl_protosw[ISO_CONS]);
599: ENDDEBUG
600: tpcb->tp_nlproto = &nl_protosw[ISO_CONS];
601: }
602: /* class 4 doesn't need to open a vc now - may use one already
603: * opened or may open one only when it sends a pkt.
604: */
605: #else TPCONS
606: error = ECONNREFUSED;
607: #endif TPCONS
608: break;
609: default:
610: error = EPROTOTYPE;
611: }
612:
613: ASSERT( save_netservice == tpcb->tp_netservice);
614: }
615: if (error) {
616: tp_netcmd( tpcb, CONN_CLOSE);
617: goto done;
618: }
619: { /* start with the global rtt, rtv stats */
620: register int i =
621: (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN);
622:
623: tpcb->tp_rtt = tp_stat.ts_rtt[i];
624: tpcb->tp_rtv = tp_stat.ts_rtv[i];
625: }
626: done:
627: IFDEBUG(D_CONN)
628: printf("tp_route_to returns 0x%x\n", error);
629: ENDDEBUG
630: IFTRACE(D_CONN)
631: tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error,
632: tpcb->tp_netservice, tpcb->tp_class, 0);
633: ENDTRACE
634: return error;
635: }
636:
637:
638: /* class zero version */
639: void
640: tp0_stash( tpcb, e )
641: register struct tp_pcb *tpcb;
642: register struct tp_event *e;
643: {
644: #ifndef lint
645: #define E e->ATTR(DT_TPDU)
646: #else lint
647: #define E e->ev_union.EV_DT_TPDU
648: #endif lint
649:
650: register struct sockbuf *sb = &tpcb->tp_sock->so_rcv;
651: register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb;
652:
653: IFPERF(tpcb)
654: PStat(tpcb, Nb_from_ll) += E.e_datalen;
655: tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
656: E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen);
657: ENDPERF
658:
659: IFDEBUG(D_STASH)
660: printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x",
661: E.e_seq, E.e_datalen, E.e_eot);
662: ENDDEBUG
663:
664: IFTRACE(D_STASH)
665: tptraceTPCB(TPPTmisc, "stash EQ: seq len eot",
666: E.e_seq, E.e_datalen, E.e_eot, 0);
667: ENDTRACE
668:
669: if ( E.e_eot ) {
670: register struct mbuf *n = E.e_data;
671: n->m_flags |= M_EOR;
672: n->m_act = MNULL; /* set on tp_input */
673: }
674: sbappend(sb, E.e_data);
675: IFDEBUG(D_STASH)
676: dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending");
677: ENDDEBUG
678: if (tpcb->tp_netservice != ISO_CONS)
679: printf("tp0_stash: tp running over something wierd\n");
680: else {
681: register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
682: pk_flowcontrol(lcp, sbspace(sb) <= 0, 1);
683: }
684: }
685:
686: void
687: tp0_openflow(tpcb)
688: register struct tp_pcb *tpcb;
689: {
690: register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb;
691: if (tpcb->tp_netservice != ISO_CONS)
692: printf("tp0_openflow: tp running over something wierd\n");
693: else {
694: register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
695: if (lcp->lcd_rxrnr_condition)
696: pk_flowcontrol(lcp, 0, 0);
697: }
698: }
699: #ifndef TPCONS
700: static
701: pk_flowcontrol() {}
702: #endif
703:
704: #ifdef TP_PERF_MEAS
705: /*
706: * CALLED FROM:
707: * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on
708: * and tp_newsocket() when a new connection is made from
709: * a listening socket with tp_perf_on == true.
710: * FUNCTION and ARGUMENTS:
711: * (tpcb) is the usual; this procedure gets a clear cluster mbuf for
712: * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it.
713: * RETURN VALUE:
714: * ENOBUFS if it cannot get a cluster mbuf.
715: */
716:
717: int
718: tp_setup_perf(tpcb)
719: register struct tp_pcb *tpcb;
720: {
721: register struct mbuf *q;
722:
723: if( tpcb->tp_p_meas == 0 ) {
724: MGET(q, M_WAITOK, MT_PCB);
725: if (q == 0)
726: return ENOBUFS;
727: MCLGET(q, M_WAITOK);
728: if ((q->m_flags & M_EXT) == 0) {
729: (void) m_free(q);
730: return ENOBUFS;
731: }
732: q->m_len = sizeof (struct tp_pmeas);
733: tpcb->tp_p_mbuf = q;
734: tpcb->tp_p_meas = mtod(q, struct tp_pmeas *);
735: bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) );
736: IFDEBUG(D_PERF_MEAS)
737: printf(
738: "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
739: tpcb, tpcb->tp_sock, tpcb->tp_lref,
740: tpcb->tp_p_meas, tpcb->tp_perf_on);
741: ENDDEBUG
742: tpcb->tp_perf_on = 1;
743: }
744: return 0;
745: }
746: #endif TP_PERF_MEAS
747:
748: #ifdef ARGO_DEBUG
749: dump_addr (addr)
750: register struct sockaddr *addr;
751: {
752: switch( addr->sa_family ) {
753: case AF_INET:
754: dump_inaddr((struct sockaddr_in *)addr);
755: break;
756: #ifdef ISO
757: case AF_ISO:
758: dump_isoaddr((struct sockaddr_iso *)addr);
759: break;
760: #endif ISO
761: default:
762: printf("BAD AF: 0x%x\n", addr->sa_family);
763: break;
764: }
765: }
766:
767: #define MAX_COLUMNS 8
768: /*
769: * Dump the buffer to the screen in a readable format. Format is:
770: *
771: * hex/dec where hex is the hex format, dec is the decimal format.
772: * columns of hex/dec numbers will be printed, followed by the
773: * character representations (if printable).
774: */
775: Dump_buf(buf, len)
776: caddr_t buf;
777: int len;
778: {
779: int i,j;
780: #define Buf ((u_char *)buf)
781: printf("Dump buf 0x%x len 0x%x\n", buf, len);
782: for (i = 0; i < len; i += MAX_COLUMNS) {
783: printf("+%d:\t", i);
784: for (j = 0; j < MAX_COLUMNS; j++) {
785: if (i + j < len) {
786: printf("%x/%d\t", Buf[i+j], Buf[i+j]);
787: } else {
788: printf(" ");
789: }
790: }
791:
792: for (j = 0; j < MAX_COLUMNS; j++) {
793: if (i + j < len) {
794: if (((Buf[i+j]) > 31) && ((Buf[i+j]) < 128))
795: printf("%c", Buf[i+j]);
796: else
797: printf(".");
798: }
799: }
800: printf("\n");
801: }
802: }
803:
804:
805: #endif ARGO_DEBUG
806:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.