1*49268Sbostic /*- 2*49268Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*49268Sbostic * All rights reserved. 4*49268Sbostic * 5*49268Sbostic * %sccs.include.redist.c% 6*49268Sbostic * 7*49268Sbostic * @(#)tp_emit.c 7.8 (Berkeley) 05/06/91 8*49268Sbostic */ 9*49268Sbostic 1036399Ssklower /*********************************************************** 1136399Ssklower Copyright IBM Corporation 1987 1236399Ssklower 1336399Ssklower All Rights Reserved 1436399Ssklower 1536399Ssklower Permission to use, copy, modify, and distribute this software and its 1636399Ssklower documentation for any purpose and without fee is hereby granted, 1736399Ssklower provided that the above copyright notice appear in all copies and that 1836399Ssklower both that copyright notice and this permission notice appear in 1936399Ssklower supporting documentation, and that the name of IBM not be 2036399Ssklower used in advertising or publicity pertaining to distribution of the 2136399Ssklower software without specific, written prior permission. 2236399Ssklower 2336399Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436399Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536399Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636399Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736399Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836399Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936399Ssklower SOFTWARE. 3036399Ssklower 3136399Ssklower ******************************************************************/ 3236399Ssklower 3336399Ssklower /* 3436399Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536399Ssklower */ 3636399Ssklower /* 3736399Ssklower * ARGO TP 3836399Ssklower * 3936399Ssklower * $Header: tp_emit.c,v 5.5 88/11/18 17:27:20 nhall Exp $ 4036399Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_emit.c,v $ 4136399Ssklower * 4236399Ssklower * This file contains tp_emit() and tp_error_emit(), which 4336399Ssklower * form TPDUs and hand them to ip. 4436399Ssklower * They take data in the form of mbuf chain, allocate mbufs as 4536399Ssklower * necessary for headers, and set the fields as appropriate from 4636399Ssklower * information found in the tpcb and net-level pcb. 4736399Ssklower * 4836399Ssklower * The worst thing about this code is adding the variable-length 4936399Ssklower * options on a machine that requires alignment for any memory access 5036399Ssklower * that isn't of size 1. See the macro ADDOPTION() below. 5136399Ssklower * 5236399Ssklower * We don't do any concatenation. (There's a kludge to test the 5336399Ssklower * basic mechanism of separation under the 'w' tpdebug option, that's all.) 5436399Ssklower */ 5536399Ssklower 5636399Ssklower #include "param.h" 5736399Ssklower #include "mbuf.h" 5836399Ssklower #include "socket.h" 5936399Ssklower #include "socketvar.h" 6036399Ssklower #include "protosw.h" 6136399Ssklower #include "errno.h" 6236399Ssklower #include "types.h" 6336399Ssklower #include "time.h" 6437469Ssklower #include "iso.h" 6545900Ssklower #include "iso_pcb.h" 6637469Ssklower #include "argo_debug.h" 6737469Ssklower #include "tp_timer.h" 6837469Ssklower #include "tp_param.h" 6937469Ssklower #include "tp_stat.h" 7037469Ssklower #include "tp_pcb.h" 7137469Ssklower #include "tp_tpdu.h" 7237469Ssklower #include "tp_trace.h" 7337469Ssklower #include "tp_meas.h" 7437469Ssklower #include "tp_seq.h" 7537469Ssklower #include "iso_errno.h" 7636399Ssklower 7745900Ssklower #include "../net/if.h" 7845900Ssklower #ifdef TRUE 7945900Ssklower #undef FALSE 8045900Ssklower #undef TRUE 8145900Ssklower #endif 8245900Ssklower #include "../netccitt/x25.h" 8345900Ssklower #include "../netccitt/pk.h" 8445900Ssklower #include "../netccitt/pk_var.h" 8545900Ssklower 8636399Ssklower void iso_gen_csum(); 8736399Ssklower 8836399Ssklower 8936399Ssklower /* Here is a mighty kludge. The token ring misorders packets if you 9036399Ssklower * fire them at it too fast, and TP sans checksum is "too fast", so 9136399Ssklower * we have introduced a delay when checksumming isn't used. 9236399Ssklower */ 9336399Ssklower char tp_delay = 0x00; /* delay to keep token ring from blowing it */ 9436399Ssklower 9536399Ssklower /* 9636399Ssklower * NAME: tp_emit() 9736399Ssklower * 9836399Ssklower * CALLED FROM: tp.trans and from tp_sbsend() 9936399Ssklower * 10036399Ssklower * FUNCTION and ARGUMENTS: 10136399Ssklower * Emits one tpdu of the type (dutype), of the format appropriate 10236399Ssklower * to the connection described by the pcb (tpcb), with sequence 10336399Ssklower * number (seq) (where appropriate), end-of-tsdu bit (eot) where 10436399Ssklower * appropriate, and with the data in the mbuf chain (data). 10536399Ssklower * For DR and ER tpdus, the argument (eot) is 10636399Ssklower * the reason for issuing the tpdu rather than an end-of-tsdu indicator. 10736399Ssklower * 10836399Ssklower * RETURNS: 10936399Ssklower * 0 OK 11036399Ssklower * ENOBUFS 11136399Ssklower * E* returned from net layer output rtn 11236399Ssklower * 11336399Ssklower * SIDE EFFECTS: 11436399Ssklower * 11536399Ssklower * NOTES: 11636399Ssklower * 11736399Ssklower * WE ASSUME that the tp header + all options will fit in ONE mbuf. 11836399Ssklower * If mbufs are 256 this will most likely be true, but if they are 128 it's 11936399Ssklower * possible that they won't. 12036399Ssklower * If you used every option on the CR + max. user data you'd overrun 12136399Ssklower * 112 but unless you used > 115 bytes for the security 12236399Ssklower * parameter, it would fit in a 256-byte mbuf (240 bytes for the header) 12336399Ssklower * We don't support the security parameter, so this isn't a problem. 12436399Ssklower * If security is added, we ought to remove this assumption. 12536399Ssklower * 12636399Ssklower * We do not implement the flow control confirmation "element of procedure". 12736399Ssklower * A) it should not affect interoperability, 12836399Ssklower * B) it should not be necessary - the protocol will eventually 12936399Ssklower * straighten things out w/o FCC, as long as we don't have severely 13036399Ssklower * mismatched keepalive and inactivity timers, and 13136399Ssklower * C) it appears not to be REQUIRED, and 13236399Ssklower * D) it's incredibly grotesque, and no doubt will lengthen a few 13336399Ssklower * critical paths. 13436399Ssklower * HOWEVER, we're thinking about putting it in anyway, for 13536399Ssklower * completeness, just like we did with ack subsequencing. 13636399Ssklower */ 13736399Ssklower 13836399Ssklower int 13936399Ssklower tp_emit(dutype, tpcb, seq, eot, data) 14036399Ssklower int dutype; 14136399Ssklower struct tp_pcb *tpcb; 14236399Ssklower SeqNum seq; 14336399Ssklower u_int eot; 14436399Ssklower struct mbuf *data; 14536399Ssklower { 14636399Ssklower register struct tpdu *hdr; 14736399Ssklower register struct mbuf *m; 14836399Ssklower int csum_offset=0; 14936399Ssklower int datalen = 0; 15036399Ssklower int error = 0; 15136399Ssklower 15236399Ssklower /* NOTE: 15336399Ssklower * here we treat tpdu_li as if it DID include the li field, up until 15436399Ssklower * the end, at which time we subtract 1 15536399Ssklower * THis is because if we subtract 1 right away, we end up adding 15636399Ssklower * one every time we add an option. 15736399Ssklower */ 15836399Ssklower IFDEBUG(D_EMIT) 15936399Ssklower printf( 16037469Ssklower "tp_emit dutype 0x%x, tpcb 0x%x, eot 0x%x, seq 0x%x, data 0x%x", 16137469Ssklower dutype, tpcb, eot, seq, data); 16236399Ssklower ENDDEBUG 16336399Ssklower 16437469Ssklower if (dutype == CR_TPDU || dutype == CC_TPDU) { 16537469Ssklower m = (struct mbuf *) malloc((u_long)256, M_MBUF, M_DONTWAIT); 16637469Ssklower if (m) { 16737469Ssklower m->m_type = TPMT_TPHDR; 16837469Ssklower mbstat.m_mtypes[TPMT_TPHDR]++; 16937469Ssklower m->m_next = MNULL; 17037469Ssklower m->m_data = m->m_dat; 17137469Ssklower m->m_flags = 0; 17237469Ssklower } 17337469Ssklower } else { 17437469Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 17537469Ssklower } 17636399Ssklower if (m == NULL) { 17736399Ssklower if(data != (struct mbuf *)0) 17836399Ssklower m_freem(data); 17936399Ssklower error = ENOBUFS; 18036399Ssklower goto done; 18136399Ssklower } 18236399Ssklower m->m_len = sizeof(struct tpdu); 18336399Ssklower m->m_act = MNULL; 18436399Ssklower 18536399Ssklower hdr = mtod(m, struct tpdu *); 18637469Ssklower bzero((caddr_t)hdr, sizeof(struct tpdu)); 18736399Ssklower 18836399Ssklower { 18936399Ssklower int tp_headersize(); 19036399Ssklower 19136399Ssklower hdr->tpdu_type = dutype; 19236399Ssklower hdr->tpdu_li = tp_headersize(dutype, tpcb); 19336399Ssklower /* 19436399Ssklower * class 0 doesn't use this for DT 19536399Ssklower * it'll just get overwritten below 19636399Ssklower */ 19736399Ssklower hdr->tpdu_dref = htons(tpcb->tp_fref); 19836399Ssklower if( tpcb->tp_use_checksum || 19936399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4) )) { 20036399Ssklower csum_offset = hdr->tpdu_li + 2; /* DOESN'T include csum */ 20136399Ssklower ADDOPTION(TPP_checksum, hdr, 2, eot /* dummy arg */); 20236399Ssklower IFDEBUG(D_CHKSUM) 20336399Ssklower printf( 20436399Ssklower "tp_emit: csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 20536399Ssklower csum_offset, hdr->tpdu_li); 20636399Ssklower ENDDEBUG 20736399Ssklower } 20836399Ssklower /* 20936399Ssklower * VARIABLE PARTS... 21036399Ssklower */ 21136399Ssklower switch( dutype ) { 21236399Ssklower 21336399Ssklower case CR_TPDU_type: 21442494Ssklower hdr->tpdu_CRdref_0 = 0; /* must be zero */ 21539924Ssklower if (!tpcb->tp_cebit_off) { 21639924Ssklower tpcb->tp_win_recv = tp_start_win << 8; 21739924Ssklower LOCAL_CREDIT(tpcb); 21839924Ssklower CONG_INIT_SAMPLE(tpcb); 21939924Ssklower tpcb->tp_ackrcvd = 0; 22039924Ssklower } 22139924Ssklower else 22239924Ssklower LOCAL_CREDIT(tpcb); 22336399Ssklower 22439924Ssklower 22536399Ssklower case CC_TPDU_type: 22636399Ssklower { 22736399Ssklower u_char x; 22836399Ssklower 22936399Ssklower hdr->tpdu_CCsref = htons(tpcb->tp_lref); /* same as CRsref */ 23036399Ssklower 23136399Ssklower if( tpcb->tp_class > TP_CLASS_1 ) { 23239924Ssklower /* ifdef CE_BIT, we did this in tp_input when the CR came in */ 23339924Ssklower if (tpcb->tp_cebit_off) 23439924Ssklower LOCAL_CREDIT( tpcb ); 23536399Ssklower tpcb->tp_sent_uwe = tpcb->tp_lcredit -1; 23636399Ssklower tpcb->tp_sent_rcvnxt = 1; 23736399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 23836399Ssklower hdr->tpdu_cdt = tpcb->tp_lcredit; 23936399Ssklower } else { 24045900Ssklower #ifdef TPCONS 24145900Ssklower if (tpcb->tp_netservice == ISO_CONS) { 24245900Ssklower struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 24345900Ssklower struct pklcd *lcp = (struct pklcd *)(isop->isop_chan); 24445900Ssklower lcp->lcd_flags &= ~X25_DG_CIRCUIT; 24545900Ssklower } 24645900Ssklower #endif 24736399Ssklower hdr->tpdu_cdt = 0; 24836399Ssklower } 24936399Ssklower hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class); 25036399Ssklower hdr->tpdu_CCoptions = 25136399Ssklower (tpcb->tp_xtd_format? TPO_XTD_FMT:0) | 25236399Ssklower (tpcb->tp_use_efc? TPO_USE_EFC:0); 25336399Ssklower 25436399Ssklower IFPERF(tpcb) 25536399Ssklower u_char perf_meas = tpcb->tp_perf_on; 25636399Ssklower ADDOPTION(TPP_perf_meas, hdr, sizeof(perf_meas), perf_meas); 25736399Ssklower ENDPERF 25836399Ssklower 25936399Ssklower if( dutype == CR_TPDU_type ) { 26036399Ssklower IncStat(ts_CR_sent); 26136399Ssklower 26236399Ssklower ASSERT( tpcb->tp_lsuffixlen > 0 ); 26336399Ssklower ASSERT( tpcb->tp_fsuffixlen > 0 ); 26436399Ssklower 26536399Ssklower ADDOPTION(TPP_calling_sufx, hdr, 26637469Ssklower tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]); 26736399Ssklower ADDOPTION(TPP_called_sufx, hdr, 26837469Ssklower tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]); 26936399Ssklower } else { 27036399Ssklower IncStat(ts_CC_sent); 27136399Ssklower } 27236399Ssklower 27336399Ssklower ADDOPTION(TPP_tpdu_size, hdr, 27436399Ssklower sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize); 27536399Ssklower 27636399Ssklower if (tpcb->tp_class != TP_CLASS_0) { 27736399Ssklower short millisec = 500*(tpcb->tp_sendack_ticks); 27836399Ssklower 27936399Ssklower millisec = htons(millisec); 28036399Ssklower ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec); 28136399Ssklower 28236399Ssklower x = (tpcb->tp_use_nxpd? TPAO_USE_NXPD: 0) 28336399Ssklower | (tpcb->tp_use_rcc? TPAO_USE_RCC : 0) 28436399Ssklower | (tpcb->tp_use_checksum?0: TPAO_NO_CSUM) 28536399Ssklower | (tpcb->tp_xpd_service? TPAO_USE_TXPD: 0); 28636399Ssklower ADDOPTION(TPP_addl_opt, hdr, 1, x); 28736399Ssklower 28836399Ssklower } 28936399Ssklower 29036399Ssklower if( (dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)){ 29136399Ssklower 29236399Ssklower ASSERT( 1 == sizeof(tpcb->tp_vers) ); 29336399Ssklower ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers); 29436399Ssklower 29536399Ssklower /* for each alt protocol class x, 29636399Ssklower * x = x<<4; 29736399Ssklower * option = concat(option, x); 29836399Ssklower * Well, for now we only have TP0 for an 29936399Ssklower * alternative so... this is easy. 30036399Ssklower * 30136399Ssklower * HOWEVER... There should be NO alt protocol 30236399Ssklower * class over CLNS. Need to see if the route suggests 30336399Ssklower * CONS, and iff so add alt class. 30436399Ssklower */ 30536399Ssklower x = 0; 30636399Ssklower ADDOPTION(TPP_alt_class, hdr, 1, x); 30736399Ssklower } 30836399Ssklower 30936399Ssklower if( hdr->tpdu_li > MLEN) 31036399Ssklower panic("tp_emit CR/CC"); 31136399Ssklower } 31236399Ssklower break; 31336399Ssklower 31436399Ssklower case DR_TPDU_type: 31536399Ssklower if( hdr->tpdu_DRdref == 0 ) { 31636399Ssklower /* don't issue the DR */ 31736399Ssklower goto done; 31836399Ssklower } 31936399Ssklower hdr->tpdu_cdt = 0; 32036399Ssklower hdr->tpdu_DRsref = htons(tpcb->tp_lref); 32136399Ssklower hdr->tpdu_DRreason = (u_char)eot; /* WHICH BYTE OF THIS??? */ 32236399Ssklower 32336399Ssklower /* forget the add'l information variable part */ 32436399Ssklower IncStat(ts_DR_sent); 32536399Ssklower break; 32636399Ssklower 32736399Ssklower case DC_TPDU_type: /* not used in class 0 */ 32836399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 32936399Ssklower hdr->tpdu_DCsref = htons(tpcb->tp_lref); 33036399Ssklower hdr->tpdu_cdt = 0; 33136399Ssklower data = (struct mbuf *)0; 33236399Ssklower IncStat(ts_DC_sent); 33336399Ssklower break; 33436399Ssklower 33536399Ssklower case XAK_TPDU_type: /* xak not used in class 0 */ 33636399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 33736399Ssklower hdr->tpdu_cdt = 0; 33836399Ssklower 33936399Ssklower IFTRACE(D_XPD) 34036399Ssklower tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0); 34136399Ssklower ENDTRACE 34236399Ssklower data = (struct mbuf *)0; 34336399Ssklower if (tpcb->tp_xtd_format) { 34436399Ssklower #ifdef BYTE_ORDER 34548747Ssklower union seq_type seqeotX; 34648747Ssklower 34748747Ssklower seqeotX.s_seq = seq; 34848747Ssklower seqeotX.s_eot = 1; 34948747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 35036399Ssklower #else 35136399Ssklower hdr->tpdu_XAKseqX = seq; 35236399Ssklower #endif BYTE_ORDER 35336399Ssklower } else { 35436399Ssklower hdr->tpdu_XAKseq = seq; 35536399Ssklower } 35636399Ssklower IncStat(ts_XAK_sent); 35736399Ssklower IncPStat(tpcb, tps_XAK_sent); 35836399Ssklower break; 35936399Ssklower 36036399Ssklower case XPD_TPDU_type: /* xpd not used in class 0 */ 36136399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 36236399Ssklower hdr->tpdu_cdt = 0; 36336399Ssklower if (tpcb->tp_xtd_format) { 36436399Ssklower #ifdef BYTE_ORDER 36536399Ssklower union seq_type seqeotX; 36636399Ssklower 36736399Ssklower seqeotX.s_seq = seq; 36836399Ssklower seqeotX.s_eot = 1; 36936399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 37036399Ssklower #else 37136399Ssklower hdr->tpdu_XPDseqX = seq; 37236399Ssklower hdr->tpdu_XPDeotX = 1; /* always 1 for XPD tpdu */ 37336399Ssklower #endif BYTE_ORDER 37436399Ssklower } else { 37536399Ssklower hdr->tpdu_XPDseq = seq; 37636399Ssklower hdr->tpdu_XPDeot = 1; /* always 1 for XPD tpdu */ 37736399Ssklower } 37836399Ssklower IncStat(ts_XPD_sent); 37936399Ssklower IncPStat(tpcb, tps_XPD_sent); 38036399Ssklower 38136399Ssklower /* kludge to test the input size checking */ 38236399Ssklower IFDEBUG(D_SIZE_CHECK) 38337469Ssklower /*if(data->m_len <= 16 && data->m_off < (MLEN-18) ) { 38436399Ssklower printf("Sending too much data on XPD: 18 bytes\n"); 38536399Ssklower data->m_len = 18; 38637469Ssklower }*/ 38736399Ssklower ENDDEBUG 38836399Ssklower break; 38936399Ssklower 39036399Ssklower case DT_TPDU_type: 39136399Ssklower hdr->tpdu_cdt = 0; 39236399Ssklower IFTRACE(D_DATA) 39336399Ssklower tptraceTPCB(TPPTmisc, "emit DT: eot seq tpdu_li", eot, seq, 39436399Ssklower hdr->tpdu_li, 0); 39536399Ssklower ENDTRACE 39636399Ssklower if (tpcb->tp_xtd_format) { 39736399Ssklower #ifdef BYTE_ORDER 39836399Ssklower union seq_type seqeotX; 39936399Ssklower 40036399Ssklower seqeotX.s_seq = seq; 40136399Ssklower seqeotX.s_eot = eot; 40236399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 40336399Ssklower #else 40436399Ssklower hdr->tpdu_DTseqX = seq; 40536399Ssklower hdr->tpdu_DTeotX = eot; 40636399Ssklower #endif BYTE_ORDER 40736399Ssklower } else if (tpcb->tp_class == TP_CLASS_0) { 40836399Ssklower IFDEBUG(D_EMIT) 40936399Ssklower printf("DT tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 41036399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 41136399Ssklower ENDDEBUG 41236399Ssklower ((struct tp0du *)hdr)->tp0du_eot = eot; 41336399Ssklower ((struct tp0du *)hdr)->tp0du_mbz = 0; 41436399Ssklower IFDEBUG(D_EMIT) 41536399Ssklower printf("DT 2 tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 41636399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 41736399Ssklower ENDDEBUG 41836399Ssklower } else { 41936399Ssklower hdr->tpdu_DTseq = seq; 42036399Ssklower hdr->tpdu_DTeot = eot; 42136399Ssklower } 42236399Ssklower if(eot) { 42336399Ssklower IncStat(ts_EOT_sent); 42436399Ssklower } 42536399Ssklower IncStat(ts_DT_sent); 42636399Ssklower IncPStat(tpcb, tps_DT_sent); 42736399Ssklower break; 42836399Ssklower 42936399Ssklower case AK_TPDU_type:/* ak not used in class 0 */ 43036399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 43136399Ssklower data = (struct mbuf *)0; 43236399Ssklower { SeqNum olduwe = tpcb->tp_sent_uwe; 43336399Ssklower 43436399Ssklower tpcb->tp_sent_uwe = 43536399Ssklower SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1); 43636399Ssklower LOCAL_CREDIT( tpcb ); 43736399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 43836399Ssklower 43936399Ssklower IFDEBUG(D_RENEG) 44036399Ssklower /* occasionally fake a reneging so 44136399Ssklower you can test subsequencing */ 44236399Ssklower if( olduwe & 0x1 ) { 44336399Ssklower tpcb->tp_reneged = 1; 44436399Ssklower IncStat(ts_ldebug); 44536399Ssklower } 44636399Ssklower ENDDEBUG 44736399Ssklower /* Are we about to reneg on credit? 44836399Ssklower * When might we do so? 44936399Ssklower * a) when using optimistic credit (which we no longer do). 45036399Ssklower * b) when drain() gets implemented (not in the plans). 45136399Ssklower * c) when D_RENEG is on. 45237469Ssklower * d) when DEC BIT response is implemented. 45336399Ssklower * (not- when we do this, we'll need to implement flow control 45436399Ssklower * confirmation) 45536399Ssklower */ 45636399Ssklower if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) { 45736399Ssklower tpcb->tp_reneged = 1; 45836399Ssklower IncStat(ts_lcdt_reduced); 45936399Ssklower IFTRACE(D_CREDIT) 46036399Ssklower tptraceTPCB(TPPTmisc, 46136399Ssklower "RENEG: olduwe newuwe lcredit rcvnxt", 46236399Ssklower olduwe, 46336399Ssklower tpcb->tp_sent_uwe, tpcb->tp_lcredit, 46436399Ssklower tpcb->tp_rcvnxt); 46536399Ssklower ENDTRACE 46636399Ssklower } 46736399Ssklower 46836399Ssklower IFPERF(tpcb) 46936399Ssklower /* new lwe is less than old uwe means we're 47036399Ssklower * acking before we received a whole window full 47136399Ssklower */ 47236399Ssklower if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) { 47336399Ssklower /* tmp1 = number of pkts fewer than the full window */ 47436399Ssklower register int tmp1 = 47536399Ssklower (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt); 47636399Ssklower 47736399Ssklower if(tmp1 > TP_PM_MAX) 47836399Ssklower tmp1 = TP_PM_MAX; 47936399Ssklower IncPStat( tpcb, tps_ack_early[tmp1] ); 48036399Ssklower 48136399Ssklower /* tmp1 = amt of new cdt we're advertising */ 48236399Ssklower tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt); 48336399Ssklower if(tmp1 > TP_PM_MAX ) 48436399Ssklower tmp1 = TP_PM_MAX; 48536399Ssklower 48636399Ssklower IncPStat( tpcb, 48736399Ssklower tps_cdt_acked [ tmp1 ] 48836399Ssklower [ ((tpcb->tp_lcredit > TP_PM_MAX)? 48936399Ssklower TP_PM_MAX:tpcb->tp_lcredit) ] ); 49036399Ssklower 49136399Ssklower } 49236399Ssklower ENDPERF 49336399Ssklower } 49436399Ssklower IFTRACE(D_ACKSEND) 49536399Ssklower tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 49636399Ssklower tpcb->tp_r_subseq, 0); 49736399Ssklower ENDTRACE 49836399Ssklower if (tpcb->tp_xtd_format) { 49936399Ssklower #ifdef BYTE_ORDER 50048747Ssklower union seq_type seqeotX; 50148747Ssklower 50248747Ssklower seqeotX.s_seq = seq; 50348747Ssklower seqeotX.s_eot = 0; 50448747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 50536399Ssklower hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit); 50636399Ssklower #else 50736399Ssklower hdr->tpdu_cdt = 0; 50836399Ssklower hdr->tpdu_AKseqX = seq; 50936399Ssklower hdr->tpdu_AKcdtX = tpcb->tp_lcredit; 51036399Ssklower #endif BYTE_ORDER 51136399Ssklower } else { 51236399Ssklower hdr->tpdu_AKseq = seq; 51336399Ssklower hdr->tpdu_AKcdt = tpcb->tp_lcredit; 51436399Ssklower } 51536399Ssklower if ((tpcb->tp_class == TP_CLASS_4) && tpcb->tp_reneged ) { 51636399Ssklower /* 51736399Ssklower * Ack subsequence parameter req'd if WE reneged on 51836399Ssklower * credit offered. (ISO 8073, 12.2.3.8.2, p. 74) 51936399Ssklower */ 52036399Ssklower IFDEBUG(D_RENEG) 52136399Ssklower printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq); 52236399Ssklower ENDDEBUG 52336399Ssklower tpcb->tp_s_subseq++; 52436399Ssklower /* 52536399Ssklower * add tmp subseq and do a htons on it. 52636399Ssklower */ 52736399Ssklower ADDOPTION(TPP_subseq, hdr, 52836399Ssklower sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq); 52936399Ssklower } else 53036399Ssklower tpcb->tp_s_subseq = 0; 53136399Ssklower 53236399Ssklower if ( tpcb->tp_sendfcc || eot ) /* overloaded to mean SEND FCC */ { 53336399Ssklower /* 53436399Ssklower * Rules for sending FCC ("should" send when) : 53536399Ssklower * %a) received an ack from peer with NO NEWS whatsoever, 53636399Ssklower * and it did not contain an FCC 53736399Ssklower * b) received an ack from peer that opens its closed window. 53836399Ssklower * c) received an ack from peer after it reneged on its 53936399Ssklower * offered credit, AND this ack raises UWE but LWE is same 54036399Ssklower * and below UWE at time of reneging (reduction) 54136399Ssklower * Now, ISO 8073 12.2.3.8.3 says 54236399Ssklower * that a retransmitted AK shall not contain the FCC 54336399Ssklower * parameter. Now, how the hell you tell the difference 54436399Ssklower * between a retransmitted ack and an ack that's sent in 54536399Ssklower * response to a received ack, I don't know, because without 54636399Ssklower * any local activity, and w/o any received DTs, they 54736399Ssklower * will contain exactly the same credit/seq# information. 54836399Ssklower * Anyway, given that the "retransmission of acks" 54936399Ssklower * procedure (ISO 8073 12.2.3.8.3) is optional, and we 55036399Ssklower * don't do it (although the peer can't tell that), we 55136399Ssklower * ignore this last rule. 55236399Ssklower * 55336399Ssklower * We send FCC for reasons a) and b) only. 55436399Ssklower * To add reason c) would require a ridiculous amount of state. 55536399Ssklower * 55636399Ssklower */ 55736399Ssklower u_short bogus[4]; /* lwe(32), subseq(16), cdt(16) */ 55836399Ssklower SeqNum lwe; 55936399Ssklower u_short subseq, fcredit; 56036399Ssklower 56136399Ssklower tpcb->tp_sendfcc = 0; 56236399Ssklower 56336399Ssklower lwe = (SeqNum) htonl(tpcb->tp_snduna); 56436399Ssklower subseq = htons(tpcb->tp_r_subseq); 56536399Ssklower fcredit = htons(tpcb->tp_fcredit); 56636399Ssklower 56737469Ssklower bcopy((caddr_t) &lwe, (caddr_t)&bogus[0], sizeof(SeqNum)); 56837469Ssklower bcopy((caddr_t) &subseq, (caddr_t)&bogus[2], sizeof(u_short)); 56937469Ssklower bcopy((caddr_t) &fcredit, (caddr_t)&bogus[3], sizeof(u_short)); 57036399Ssklower 57136399Ssklower IFTRACE(D_ACKSEND) 57236399Ssklower tptraceTPCB(TPPTmisc, 57336399Ssklower "emit w/FCC: snduna r_subseq fcredit", 57436399Ssklower tpcb->tp_snduna, tpcb->tp_r_subseq, 57536399Ssklower tpcb->tp_fcredit, 0); 57636399Ssklower ENDTRACE 57736399Ssklower 57836399Ssklower IFDEBUG(D_ACKSEND) 57936399Ssklower printf("Calling ADDOPTION 0x%x, 0x%x, 0x%x,0x%x\n", 58036399Ssklower TPP_flow_cntl_conf, 58136399Ssklower hdr, sizeof(bogus), bogus[0]); 58236399Ssklower ENDDEBUG 58336399Ssklower ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]); 58436399Ssklower IFDEBUG(D_ACKSEND) 58536399Ssklower printf("after ADDOPTION hdr 0x%x hdr->tpdu_li 0x%x\n", 58636399Ssklower hdr, hdr->tpdu_li); 58736399Ssklower printf( 58836399Ssklower "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 58936399Ssklower csum_offset, hdr->tpdu_li); 59036399Ssklower ENDDEBUG 59136399Ssklower 59236399Ssklower } 59336399Ssklower tpcb->tp_reneged = 0; 59436399Ssklower tpcb->tp_sent_rcvnxt = seq; 59536399Ssklower tp_ctimeout(tpcb->tp_refp, TM_sendack, 59636399Ssklower (int)tpcb->tp_keepalive_ticks); 59736399Ssklower IncStat(ts_AK_sent); 59836399Ssklower IncPStat(tpcb, tps_AK_sent); 59936399Ssklower IFDEBUG(D_ACKSEND) 60036399Ssklower printf( 60136399Ssklower "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 60236399Ssklower csum_offset, hdr->tpdu_li); 60336399Ssklower ENDDEBUG 60436399Ssklower break; 60536399Ssklower 60636399Ssklower case ER_TPDU_type: 60736399Ssklower hdr->tpdu_ERreason = eot; 60836399Ssklower hdr->tpdu_cdt = 0; 60936399Ssklower /* no user data */ 61036399Ssklower data = (struct mbuf *)0; 61136399Ssklower IncStat(ts_ER_sent); 61236399Ssklower break; 61336399Ssklower } 61436399Ssklower 61536399Ssklower } 61636399Ssklower ASSERT( ((int)hdr->tpdu_li > 0) && ((int)hdr->tpdu_li < MLEN) ); 61736399Ssklower 61836399Ssklower m->m_next = data; 61936399Ssklower 62037469Ssklower ASSERT( hdr->tpdu_li < MLEN ); /* leave this in */ 62136399Ssklower ASSERT( hdr->tpdu_li != 0 ); /* leave this in */ 62236399Ssklower 62336399Ssklower m->m_len = hdr->tpdu_li ; 62436399Ssklower hdr->tpdu_li --; /* doesn't include the li field */ 62536399Ssklower 62636399Ssklower datalen = m_datalen( m ); /* total len */ 62736399Ssklower 62836399Ssklower ASSERT( datalen <= tpcb->tp_l_tpdusize ); /* may become a problem 62936399Ssklower when CLNP is used; leave in here for the time being */ 63036399Ssklower IFDEBUG(D_ACKSEND) 63136399Ssklower printf( 63236399Ssklower "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 63336399Ssklower csum_offset, hdr->tpdu_li); 63436399Ssklower ENDDEBUG 63536399Ssklower if( datalen > tpcb->tp_l_tpdusize ) { 63636399Ssklower printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n", 63736399Ssklower datalen, tpcb->tp_l_tpdusize); 63836399Ssklower } 63936399Ssklower IFDEBUG(D_EMIT) 64036399Ssklower printf( 64136399Ssklower "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n", 64236399Ssklower m->m_len, csum_offset, datalen); 64336399Ssklower ENDDEBUG 64436399Ssklower if( tpcb->tp_use_checksum || 64536399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4)) ) { 64636399Ssklower iso_gen_csum(m, csum_offset, datalen); 64736399Ssklower } 64836399Ssklower 64936399Ssklower IFDEBUG(D_EMIT) 65036399Ssklower printf("tp_emit before tpxxx_output tpcb 0x%x, dutype 0x%x, datalen 0x%x\n", 65136399Ssklower tpcb, dutype, datalen); 65237469Ssklower dump_buf(mtod(m, caddr_t), datalen); 65336399Ssklower ENDDEBUG 65436399Ssklower 65536399Ssklower IFPERF(tpcb) 65636399Ssklower if( dutype == DT_TPDU_type ) { 65736399Ssklower PStat(tpcb, Nb_to_ll) += (datalen - m->m_len); 65837469Ssklower tpmeas( tpcb->tp_lref, TPtime_to_ll, (struct timeval *)0, 65936399Ssklower seq, PStat(tpcb, Nb_to_ll), (datalen - m->m_len)); 66036399Ssklower } 66136399Ssklower ENDPERF 66236399Ssklower 66336399Ssklower IFTRACE(D_EMIT) 66436399Ssklower tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li+1, datalen, 0); 66536399Ssklower ENDTRACE 66636399Ssklower IFDEBUG(D_EMIT) 66736399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 66836399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 66936399Ssklower ENDDEBUG 67036399Ssklower 67136399Ssklower { extern char tp_delay; 67236399Ssklower 67336399Ssklower if( tp_delay ) 67436399Ssklower if( tpcb->tp_use_checksum == 0 ) { 67536399Ssklower register u_int i = tp_delay; 67636399Ssklower for (; i!= 0; i--) 67736399Ssklower (void) iso_check_csum(m, datalen); 67836399Ssklower } 67936399Ssklower } 68036399Ssklower ASSERT( m->m_len > 0 ); 68136399Ssklower error = (tpcb->tp_nlproto->nlp_output)(tpcb->tp_npcb, m, datalen, 68236399Ssklower !tpcb->tp_use_checksum); 68336399Ssklower IFDEBUG(D_EMIT) 68436399Ssklower printf("OUTPUT: returned 0x%x\n", error); 68536399Ssklower ENDDEBUG 68636399Ssklower IFTRACE(D_EMIT) 68736399Ssklower tptraceTPCB(TPPTmisc, 68836399Ssklower "tp_emit nlproto->output netservice returns datalen", 68936399Ssklower tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 69036399Ssklower ENDTRACE 69136399Ssklower done: 69236399Ssklower if( error == E_CO_QFULL ) { 69337469Ssklower tp_quench(tpcb, PRC_QUENCH); 69436399Ssklower return 0; 69536399Ssklower } 69636399Ssklower return error; 69736399Ssklower } 69836399Ssklower /* 69936399Ssklower * NAME: tp_error_emit() 70036399Ssklower * CALLED FROM: tp_input() when a DR or ER is to be issued in 70136399Ssklower * response to an input error. 70236399Ssklower * FUNCTION and ARGUMENTS: 70336399Ssklower * The error type is the first argument. 70436399Ssklower * The argument (sref) is the source reference on the bad incoming tpdu, 70536399Ssklower * and is used for a destination reference on the outgoing packet. 70636399Ssklower * (faddr) and (laddr) are the foreign and local addresses for this 70736399Ssklower * connection. 70836399Ssklower * (erdata) is a ptr to the errant incoming tpdu, and is copied into the 70936399Ssklower * outgoing ER, if an ER is to be issued. 71036399Ssklower * (erlen) is the number of octets of the errant tpdu that we should 71136399Ssklower * try to copy. 71236399Ssklower * (tpcb) is the pcb that describes the connection for which the bad tpdu 71336399Ssklower * arrived. 71436399Ssklower * RETURN VALUES: 71536399Ssklower * 0 OK 71636399Ssklower * ENOBUFS 71736399Ssklower * E* from net layer datagram output routine 71836399Ssklower * SIDE EFFECTS: 71936399Ssklower * 72036399Ssklower * NOTES: 72136399Ssklower */ 72236399Ssklower 72336399Ssklower int 72436399Ssklower tp_error_emit(error, sref, faddr, laddr, erdata, erlen, tpcb, cons_channel, 72536399Ssklower dgout_routine) 72636399Ssklower int error; 72736399Ssklower u_long sref; 72836399Ssklower struct sockaddr_iso *faddr, *laddr; 72936399Ssklower struct mbuf *erdata; 73036399Ssklower int erlen; 73136399Ssklower struct tp_pcb *tpcb; 73236399Ssklower int cons_channel; 73336399Ssklower int (*dgout_routine)(); 73436399Ssklower { 73536399Ssklower int dutype; 73636399Ssklower int datalen = 0; 73736399Ssklower register struct tpdu *hdr; 73836399Ssklower register struct mbuf *m; 73936399Ssklower int csum_offset; 74036399Ssklower 74136399Ssklower IFTRACE(D_ERROR_EMIT) 74236399Ssklower tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen", 74336399Ssklower error, sref, tpcb, erlen); 74436399Ssklower ENDTRACE 74536399Ssklower IFDEBUG(D_ERROR_EMIT) 74636399Ssklower printf( 74736399Ssklower "tp_error_emit error 0x%x sref 0x%x tpcb 0x%x erlen 0x%x chan 0x%x\n", 74836399Ssklower error, sref, tpcb, erlen, cons_channel); 74936399Ssklower ENDDEBUG 75036399Ssklower 75136399Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 75236399Ssklower if (m == NULL) { 75336399Ssklower return ENOBUFS; 75436399Ssklower } 75536399Ssklower m->m_len = sizeof(struct tpdu); 75636399Ssklower m->m_act = MNULL; 75736399Ssklower 75836399Ssklower hdr = mtod(m, struct tpdu *); 75936399Ssklower 76036399Ssklower IFDEBUG(D_ERROR_EMIT) 76136399Ssklower printf("[error 0x%x] [error&0xff 0x%x] [(char)error 0x%x]\n", 76236399Ssklower error, error&0xff, (char)error); 76336399Ssklower ENDDEBUG 76436399Ssklower 76536399Ssklower 76642494Ssklower if (error & TP_ERROR_SNDC) 76742494Ssklower dutype = DC_TPDU_type; 76842494Ssklower else if (error & 0x40) { 76936399Ssklower error &= ~0x40; 77036399Ssklower dutype = ER_TPDU_type; 77136399Ssklower } else 77236399Ssklower dutype = DR_TPDU_type; 77342494Ssklower error &= 0xff; 77436399Ssklower 77536399Ssklower hdr->tpdu_type = dutype; 77636399Ssklower hdr->tpdu_cdt = 0; 77736399Ssklower 77836399Ssklower switch( dutype ) { 77936399Ssklower 78042494Ssklower case DC_TPDU_type: 78142494Ssklower IncStat(ts_DC_sent); 78242494Ssklower hdr->tpdu_li = 6; 78342494Ssklower hdr->tpdu_DCdref = htons(sref); 78442494Ssklower hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0; 78542494Ssklower IFDEBUG(D_ERROR_EMIT) 78642494Ssklower printf("DC case:\n"); 78742494Ssklower dump_buf( hdr, 6); 78842494Ssklower ENDDEBUG 78942494Ssklower /* forget the add'l information variable part */ 79042494Ssklower break; 79142494Ssklower 79236399Ssklower case DR_TPDU_type: 79336399Ssklower IncStat(ts_DR_sent); 79436399Ssklower hdr->tpdu_li = 7; 79536399Ssklower hdr->tpdu_DRdref = htons(sref); 79642494Ssklower hdr->tpdu_DRsref = 0; 79736399Ssklower hdr->tpdu_DRreason = (char)error; 79836399Ssklower IFDEBUG(D_ERROR_EMIT) 79936399Ssklower printf("DR case:\n"); 80036399Ssklower dump_buf( hdr, 7); 80136399Ssklower ENDDEBUG 80236399Ssklower /* forget the add'l information variable part */ 80336399Ssklower break; 80436399Ssklower 80536399Ssklower case ER_TPDU_type: 80636399Ssklower IncStat(ts_ER_sent); 80736399Ssklower hdr->tpdu_li = 5; 80836399Ssklower hdr->tpdu_ERreason = (char)error; 80936399Ssklower break; 81036399Ssklower 81136399Ssklower default: 81236399Ssklower ASSERT(0); 81336399Ssklower printf("TP PANIC: bad dutype 0x%x\n", dutype); 81436399Ssklower } 81536399Ssklower 81636399Ssklower if(tpcb) 81736399Ssklower if( tpcb->tp_use_checksum ) { 81836399Ssklower ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */); 81936399Ssklower csum_offset = hdr->tpdu_li - 2; 82036399Ssklower } 82136399Ssklower 82237469Ssklower ASSERT( hdr->tpdu_li < MLEN ); 82336399Ssklower 82436399Ssklower if (dutype == ER_TPDU_type) { 82536399Ssklower /* copy the errant tpdu into another 'variable part' */ 82636399Ssklower register caddr_t P; 82736399Ssklower 82836399Ssklower IFTRACE(D_ERROR_EMIT) 82936399Ssklower tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li, 83036399Ssklower 0,0); 83136399Ssklower ENDTRACE 83236399Ssklower IFDEBUG(D_ERROR_EMIT) 83336399Ssklower printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li); 83436399Ssklower ENDDEBUG 83536399Ssklower 83636399Ssklower /* copy at most as many octets for which you have room */ 83736399Ssklower if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN) 83836399Ssklower erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2; 83936399Ssklower 84036399Ssklower /* add the "invalid tpdu" parameter : required in class 0 */ 84136399Ssklower P = (caddr_t)hdr + (int)(hdr->tpdu_li); 84236399Ssklower vbptr(P)->tpv_code = TPP_invalid_tpdu; /* parameter code */ 84336399Ssklower vbptr(P)->tpv_len = erlen; /* parameter length */ 84436399Ssklower m->m_len = hdr->tpdu_li + 2; /* 1 for code, 1 for length */ 84536399Ssklower 84636399Ssklower /* tp_input very likely handed us an mbuf chain w/ nothing in 84736399Ssklower * the first mbuf and the data following the empty mbuf 84836399Ssklower */ 84936399Ssklower if(erdata->m_len == 0) { 85036399Ssklower erdata = m_free(erdata); /* returns the next mbuf on the chain */ 85136399Ssklower } 85237469Ssklower /* 85337469Ssklower * copy only up to the bad octet 85437469Ssklower * (or max that will fit in a header 85537469Ssklower */ 85637469Ssklower m->m_next = m_copy(erdata, 0, erlen); 85736399Ssklower hdr->tpdu_li += erlen + 2; 85836399Ssklower m_freem(erdata); 85936399Ssklower } else { 86036399Ssklower IFDEBUG(D_ERROR_EMIT) 86136399Ssklower printf("error_emit DR error tpduli 0x%x\n", error, hdr->tpdu_li); 86236399Ssklower dump_buf( (char *)hdr, hdr->tpdu_li ); 86336399Ssklower ENDDEBUG 86436399Ssklower m->m_len = hdr->tpdu_li ; 86536399Ssklower m_freem(erdata); 86636399Ssklower } 86736399Ssklower 86836399Ssklower hdr->tpdu_li --; 86936399Ssklower IFTRACE(D_ERROR_EMIT) 87036399Ssklower tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li+1, 0, 0); 87136399Ssklower ENDTRACE 87236399Ssklower 87336399Ssklower datalen = m_datalen( m); 87436399Ssklower 87536399Ssklower if(tpcb) { 87636399Ssklower if( tpcb->tp_use_checksum ) { 87736399Ssklower IFTRACE(D_ERROR_EMIT) 87836399Ssklower tptrace(TPPTmisc, "before gen csum datalen", datalen,0,0,0); 87936399Ssklower ENDTRACE 88036399Ssklower IFDEBUG(D_ERROR_EMIT) 88136399Ssklower printf("before gen csum datalen 0x%x, csum_offset 0x%x\n", 88236399Ssklower datalen, csum_offset); 88336399Ssklower ENDDEBUG 88436399Ssklower 88536399Ssklower iso_gen_csum(m, csum_offset, datalen); 88636399Ssklower } 88736399Ssklower 88836399Ssklower IFDEBUG(D_ERROR_EMIT) 88936399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 89036399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 89136399Ssklower ENDDEBUG 89236399Ssklower /* Problem: if packet comes in on ISO but sock is listening 89336399Ssklower * in INET, this assertion will fail. 89436399Ssklower * Have to believe the argument, not the nlp_proto. 89536399Ssklower ASSERT( tpcb->tp_nlproto->nlp_dgoutput == dgout_routine ); 89636399Ssklower */ 89736399Ssklower 89836399Ssklower IFDEBUG(D_ERROR_EMIT) 89936399Ssklower printf("tp_error_emit 1 sending DG: Laddr\n"); 90037469Ssklower dump_addr((struct sockaddr *)laddr); 90136399Ssklower printf("Faddr\n"); 90237469Ssklower dump_addr((struct sockaddr *)faddr); 90336399Ssklower ENDDEBUG 90436399Ssklower return (tpcb->tp_nlproto->nlp_dgoutput)( 90536399Ssklower &laddr->siso_addr, 90636399Ssklower &faddr->siso_addr, 90736399Ssklower m, datalen, 90836399Ssklower /* no route */ (caddr_t)0, !tpcb->tp_use_checksum); 90936399Ssklower } else { 91036399Ssklower if( cons_channel ) { 91145900Ssklower #ifdef TPCONS 91245900Ssklower tpcons_dg_output(cons_channel, m, datalen); 91345900Ssklower pk_disconnect((struct pklcd *)cons_channel); 91436399Ssklower IFDEBUG(D_ERROR_EMIT) 91536399Ssklower printf("OUTPUT: dutype 0x%x channel 0x%x\n", 91636399Ssklower dutype, cons_channel); 91736399Ssklower ENDDEBUG 91845900Ssklower #else 91936399Ssklower printf("TP panic! cons channel 0x%x but not cons configured\n", 92036399Ssklower cons_channel); 92145900Ssklower #endif 92236399Ssklower } else { 92337469Ssklower #ifndef notdef 92436399Ssklower IFDEBUG(D_ERROR_EMIT) 92536399Ssklower printf("tp_error_emit sending DG: Laddr\n"); 92637469Ssklower dump_addr((struct sockaddr *)laddr); 92736399Ssklower printf("Faddr\n"); 92837469Ssklower dump_addr((struct sockaddr *)faddr); 92936399Ssklower ENDDEBUG 93036399Ssklower return (*dgout_routine)( &laddr->siso_addr, &faddr->siso_addr, 93136399Ssklower m, datalen, /* no route */ 93236399Ssklower (caddr_t)0, /* nochecksum==false */0); 93337469Ssklower #else notdef 93436399Ssklower IFDEBUG(D_ERROR_EMIT) 93536399Ssklower printf("tp_error_emit DROPPING \n", m); 93636399Ssklower ENDDEBUG 93736399Ssklower IncStat(ts_send_drop); 93836399Ssklower m_freem(m); 93936399Ssklower return 0; 94037469Ssklower #endif notdef 94136399Ssklower } 94236399Ssklower } 94336399Ssklower } 944