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