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