2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_ipr.c - isdn4bsd IP over raw HDLC ISDN network driver
28 * ---------------------------------------------------------
30 * $Id: i4b_ipr.c,v 1.33 2009/03/18 10:22:43 cegger Exp $
34 * last edit-date: [Fri Jan 5 11:33:47 2001]
36 *---------------------------------------------------------------------------*
38 * statistics counter usage (interface lifetime):
39 * ----------------------------------------------
40 * sc->sc_if.if_ipackets # of received packets
41 * sc->sc_if.if_ierrors # of error packets not going to upper layers
42 * sc->sc_if.if_opackets # of transmitted packets
43 * sc->sc_if.if_oerrors # of error packets not being transmitted
44 * sc->sc_if.if_collisions # of invalid ip packets after VJ decompression
45 * sc->sc_if.if_ibytes # of bytes coming in from the line (before VJ)
46 * sc->sc_if.if_obytes # of bytes going out to the line (after VJ)
47 * sc->sc_if.if_imcasts (currently unused)
48 * sc->sc_if.if_omcasts # of frames sent out of the fastqueue
49 * sc->sc_if.if_iqdrops # of frames dropped on input because queue full
50 * sc->sc_if.if_noproto # of frames dropped on output because !AF_INET
52 * statistics counter usage (connection lifetime):
53 * -----------------------------------------------
54 * sc->sc_iinb # of ISDN incoming bytes from HSCX
55 * sc->sc_ioutb # of ISDN outgoing bytes from HSCX
56 * sc->sc_inb # of incoming bytes after decompression
57 * sc->sc_outb # of outgoing bytes before compression
59 *---------------------------------------------------------------------------*/
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: i4b_ipr.c,v 1.32 2009/03/14 14:46:10 dsl Exp $");
73 #include <sys/param.h>
74 #include <sys/systm.h>
76 #include <sys/socket.h>
77 #include <sys/errno.h>
78 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
79 #include <sys/ioccom.h>
80 #include <sys/sockio.h>
82 #include <sys/malloc.h>
85 #include <sys/ioctl.h>
88 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
89 #include <sys/callout.h>
92 #include <sys/kernel.h>
93 #include <sys/protosw.h>
96 #include <net/if_types.h>
97 #include <net/netisr.h>
98 #include <net/route.h>
100 #include <netinet/in.h>
101 #include <netinet/in_systm.h>
102 #include <netinet/in_var.h>
103 #include <netinet/ip.h>
106 #include <net/slcompress.h>
107 #define IPR_COMPRESS IFF_LINK0 /* compress TCP traffic */
108 #define IPR_AUTOCOMP IFF_LINK1 /* auto-enable TCP compression */
110 /*---------------------------------------------------------------------------
111 * NOTICE: using NO separate buffer relies on the assumption, that the HSCX
112 * IRQ handler _always_ allocates a single, continuous mbuf cluster large
113 * enough to hold the maximum MTU size if the ipr interface !
115 * CAUTION: i have re-defined IPR_VJ_USEBUFFER because it makes problems
116 * with 2 i4b's back to back running cvs over ssh, cvs simply
117 * aborts because it gets bad data. Everything else (telnet/ftp?etc)
119 *---------------------------------------------------------------------------*/
120 #define IPR_VJ_USEBUFFER /* define to use an allocated separate buffer*/
121 /* undef to uncompress in the mbuf itself */
124 #if defined(__FreeBSD_version) && __FreeBSD_version >= 400008
127 #include "bpfilter.h"
129 #if NBPFILTER > 0 || NBPF > 0
130 #include <sys/time.h>
135 #include <machine/i4b_ioctl.h>
136 #include <machine/i4b_debug.h>
138 #include <netisdn/i4b_debug.h>
139 #include <netisdn/i4b_ioctl.h>
142 #include <netisdn/i4b_global.h>
143 #include <netisdn/i4b_mbuf.h>
144 #include <netisdn/i4b_l3l4.h>
146 #include <netisdn/i4b_l4.h>
149 #include <sys/cpu.h> /* For softnet */
153 #define IPR_FMT "irip%d: "
154 #define IPR_ARG(sc) ((sc)->sc_if.if_unit)
155 #define PDEVSTATIC static
156 #elif defined(__bsdi__)
157 #define IPR_FMT "irip%d: "
158 #define IPR_ARG(sc) ((sc)->sc_if.if_unit)
159 #define PDEVSTATIC /* not static */
161 #define IPR_FMT "%s: "
162 #define IPR_ARG(sc) ((sc)->sc_if.if_xname)
163 #define PDEVSTATIC /* not static */
166 #define I4BIPRMTU 1500 /* regular MTU */
167 #define I4BIPRMAXMTU 2000 /* max MTU */
168 #define I4BIPRMINMTU 500 /* min MTU */
170 #define I4BIPRMAXQLEN 50 /* max queue length */
172 #define I4BIPRACCT 1 /* enable accounting messages */
173 #define I4BIPRACCTINTVL 2 /* accounting msg interval in secs */
174 #define I4BIPRADJFRXP 1 /* adjust 1st rxd packet */
178 struct ifnet sc_if
; /* network-visible interface */
179 int sc_state
; /* state of the interface */
181 call_desc_t
*sc_cdp
; /* ptr to call descriptor */
182 isdn_link_t
*sc_ilt
; /* ptr to B channel driver/state */
184 int sc_unit
; /* which instance are we? */
185 int sc_updown
; /* soft state of interface */
186 struct ifqueue sc_fastq
; /* interactive traffic */
187 int sc_dialresp
; /* dialresponse */
188 int sc_lastdialresp
;/* last dialresponse */
191 int sc_iinb
; /* isdn driver # of inbytes */
192 int sc_ioutb
; /* isdn driver # of outbytes */
193 int sc_inb
; /* # of bytes rx'd */
194 int sc_outb
; /* # of bytes tx'd */
195 int sc_linb
; /* last # of bytes rx'd */
196 int sc_loutb
; /* last # of bytes tx'd */
197 int sc_fn
; /* flag, first null acct */
200 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
201 struct callout sc_callout
;
203 #if defined(__FreeBSD__)
204 struct callout_handle sc_callout
;
208 int sc_first_pkt
; /* flag, first rxd packet */
211 int sc_log_first
; /* log first n packets */
215 struct slcompress sc_compr
; /* tcp compression data */
216 #ifdef IPR_VJ_USEBUFFER
217 u_char
*sc_cbuf
; /* tcp decompression buffer */
224 ST_IDLE
, /* initialized, ready, idle */
225 ST_DIALING
, /* dialling out to remote */
226 ST_CONNECTED_W
, /* connected to remote */
227 ST_CONNECTED_A
, /* connected to remote */
230 #if defined(__FreeBSD__) || defined(__bsdi__)
231 #define THE_UNIT sc->sc_if.if_unit
233 #define THE_UNIT sc->sc_unit
237 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
238 # define IOCTL_CMD_T u_long
241 # define IOCTL_CMD_T u_long
243 # define IOCTL_CMD_T int
246 PDEVSTATIC
void iripattach(void *);
247 PSEUDO_SET(iripattach
, i4b_ipr
);
248 static int irpioctl(struct ifnet
*ifp
, IOCTL_CMD_T cmd
, void *data
);
250 PDEVSTATIC
void iripattach(void);
251 static int iripioctl(struct ifnet
*ifp
, u_long cmd
, void *data
);
255 static int iprwatchdog(int unit
);
257 static void iprwatchdog(struct ifnet
*ifp
);
259 static void ipr_tx_queue_empty(void *);
260 static int iripoutput(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*dst
, struct rtentry
*rtp
);
261 static void iripclearqueues(struct ipr_softc
*sc
);
262 static void ipr_set_linktab(void *softc
, isdn_link_t
*ilt
);
263 static void ipr_activity(void *softc
, int rxtx
);
264 static void ipr_rx_data_rdy(void *softc
);
265 static void ipr_disconnect(void *softc
, void *cdp
);
266 static void ipr_connect(void *softc
, void *cdp
);
267 static void ipr_dialresponse(void *softc
, int status
, cause_t cause
);
268 static void ipr_updown(void *softc
, int updown
);
269 static void* ipr_get_softc(int unit
);
271 static const struct isdn_l4_driver_functions
285 static int irip_driver_id
= -1;
287 /*===========================================================================*
288 * DEVICE DRIVER ROUTINES
289 *===========================================================================*/
291 /*---------------------------------------------------------------------------*
292 * interface attach routine at kernel boot time
293 *---------------------------------------------------------------------------*/
296 iripattach(void *dummy
)
301 struct ipr_softc
*sc
= ipr_softc
;
304 irip_driver_id
= isdn_l4_driver_attach("irip", NIRIP
, &ipr_l4_functions
);
306 for(i
=0; i
< NIRIP
; sc
++, i
++)
308 NDBGL4(L4_DIALST
, "setting dial state to ST_IDLE");
310 sc
->sc_state
= ST_IDLE
;
314 sc
->sc_if
.if_name
= "irip";
316 sc
->sc_if
.if_next
= NULL
;
318 sc
->sc_if
.if_unit
= i
;
319 #elif defined(__bsdi__)
320 sc
->sc_if
.if_name
= "irip";
321 sc
->sc_if
.if_unit
= i
;
323 snprintf(sc
->sc_if
.if_xname
, sizeof(sc
->sc_if
.if_xname
),
325 sc
->sc_if
.if_softc
= sc
;
329 sc
->sc_if
.if_flags
= IFF_POINTOPOINT
| IFF_SIMPLEX
| IPR_AUTOCOMP
;
331 sc
->sc_if
.if_flags
= IFF_POINTOPOINT
| IFF_SIMPLEX
;
334 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
335 callout_init(&sc
->sc_callout
, 0);
338 sc
->sc_if
.if_mtu
= I4BIPRMTU
;
339 sc
->sc_if
.if_type
= IFT_ISDNBASIC
;
340 sc
->sc_if
.if_ioctl
= iripioctl
;
341 sc
->sc_if
.if_output
= iripoutput
;
343 IFQ_SET_MAXLEN(&sc
->sc_if
.if_snd
, I4BIPRMAXQLEN
);
344 sc
->sc_fastq
.ifq_maxlen
= I4BIPRMAXQLEN
;
345 IFQ_SET_READY(&sc
->sc_if
.if_snd
);
347 sc
->sc_if
.if_ipackets
= 0;
348 sc
->sc_if
.if_ierrors
= 0;
349 sc
->sc_if
.if_opackets
= 0;
350 sc
->sc_if
.if_oerrors
= 0;
351 sc
->sc_if
.if_collisions
= 0;
352 sc
->sc_if
.if_ibytes
= 0;
353 sc
->sc_if
.if_obytes
= 0;
354 sc
->sc_if
.if_imcasts
= 0;
355 sc
->sc_if
.if_omcasts
= 0;
356 sc
->sc_if
.if_iqdrops
= 0;
357 sc
->sc_if
.if_noproto
= 0;
360 sc
->sc_if
.if_timer
= 0;
361 sc
->sc_if
.if_watchdog
= iprwatchdog
;
371 sc
->sc_log_first
= IPR_LOG
;
376 sl_compress_init(&sc
->sc_compr
, -1);
378 sl_compress_init(&sc
->sc_compr
);
381 #ifdef IPR_VJ_USEBUFFER
383 (u_char
*)malloc(I4BIPRMAXMTU
+128, M_DEVBUF
, M_WAITOK
))))
385 panic("if_ipr.c, ipr_attach: VJ malloc failed");
390 sc
->sc_updown
= SOFT_ENA
; /* soft enabled */
392 sc
->sc_dialresp
= DSTAT_NONE
; /* no response */
393 sc
->sc_lastdialresp
= DSTAT_NONE
;
395 #if defined(__FreeBSD_version) && ((__FreeBSD_version >= 500009) || (410000 <= __FreeBSD_version && __FreeBSD_version < 500000))
396 /* do not call bpfattach in ether_ifattach */
397 ether_ifattach(&sc
->sc_if
, 0);
399 if_attach(&sc
->sc_if
);
400 if_alloc_sadl(&sc
->sc_if
);
403 #if NBPFILTER > 0 || NBPF > 0
405 bpfattach(&sc
->sc_if
, DLT_NULL
, sizeof(u_int
));
407 bpfattach(&sc
->sc_if
, DLT_NULL
, sizeof(u_int
));
413 /*---------------------------------------------------------------------------*
414 * output a packet to the ISDN B-channel
415 *---------------------------------------------------------------------------*/
417 iripoutput(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*dst
,
420 struct ipr_softc
*sc
;
422 struct ifqueue
*ifq
= NULL
;
424 ALTQ_DECL(struct altq_pktattr pktattr
;)
428 #if defined(__FreeBSD__) || defined(__bsdi__)
430 sc
= &ipr_softc
[unit
];
437 if(dst
->sa_family
!= AF_INET
)
439 printf(IPR_FMT
"af%d not supported\n", IPR_ARG(sc
), dst
->sa_family
);
442 sc
->sc_if
.if_noproto
++;
443 sc
->sc_if
.if_oerrors
++;
444 return(EAFNOSUPPORT
);
447 /* check interface state = UP */
449 if(!(ifp
->if_flags
& IFF_UP
))
451 NDBGL4(L4_IPRDBG
, "%s: interface is DOWN!", sc
->sc_if
.if_xname
);
454 sc
->sc_if
.if_oerrors
++;
458 /* dial if necessary */
460 if(sc
->sc_state
== ST_IDLE
|| sc
->sc_state
== ST_DIALING
)
464 switch(sc
->sc_dialresp
)
466 case DSTAT_TFAIL
: /* transient failure */
467 NDBGL4(L4_IPRDBG
, "%s: transient dial failure!", sc
->sc_if
.if_xname
);
470 sc
->sc_dialresp
= DSTAT_NONE
;
472 sc
->sc_if
.if_oerrors
++;
476 case DSTAT_PFAIL
: /* permanent failure */
477 NDBGL4(L4_IPRDBG
, "%s: permanent dial failure!", sc
->sc_if
.if_xname
);
480 sc
->sc_dialresp
= DSTAT_NONE
;
482 sc
->sc_if
.if_oerrors
++;
483 return(EHOSTUNREACH
);
486 case DSTAT_INONLY
: /* no dialout allowed*/
487 NDBGL4(L4_IPRDBG
, "%s: dialout not allowed failure!", sc
->sc_if
.if_xname
);
490 sc
->sc_dialresp
= DSTAT_NONE
;
492 sc
->sc_if
.if_oerrors
++;
493 return(EHOSTUNREACH
);
498 NDBGL4(L4_IPRDBG
, "%s: send dial request message!", sc
->sc_if
.if_xname
);
499 NDBGL4(L4_DIALST
, "%s: setting dial state to ST_DIALING", sc
->sc_if
.if_xname
);
500 i4b_l4_dialout(irip_driver_id
, sc
->sc_unit
);
501 sc
->sc_state
= ST_DIALING
;
505 if(sc
->sc_log_first
> 0)
507 --(sc
->sc_log_first
);
508 i4b_l4_packet_ind(irip_driver_id
, sc
->sc_unit
, 1, m
);
513 * check, if type of service indicates interactive, i.e. telnet,
514 * traffic. in case it is interactive, put it into the fast queue,
515 * else (i.e. ftp traffic) put it into the "normal" queue
518 IFQ_CLASSIFY(&ifp
->if_snd
, m
, dst
->sa_family
, &pktattr
);
520 ip
= mtod(m
, struct ip
*); /* get ptr to ip header */
522 if(ip
->ip_tos
& IPTOS_LOWDELAY
)
525 /* check for space in choosen send queue */
529 && ALTQ_IS_ENABLED(&sc
->sc_if
.if_snd
) == 0
534 NDBGL4(L4_IPRDBG
, "%s: send queue full!", sc
->sc_if
.if_xname
);
537 sc
->sc_if
.if_oerrors
++;
543 IFQ_ENQUEUE(&sc
->sc_if
.if_snd
, m
, &pktattr
, rv
);
545 sc
->sc_if
.if_oerrors
++;
551 NDBGL4(L4_IPRDBG
, "%s: added packet to send queue!", sc
->sc_if
.if_xname
);
553 ipr_tx_queue_empty(sc
);
560 /*---------------------------------------------------------------------------*
562 *---------------------------------------------------------------------------*/
564 iripioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
566 struct ipr_softc
*sc
= ifp
->if_softc
;
568 struct ifreq
*ifr
= (struct ifreq
*)data
;
569 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
577 case SIOCAIFADDR
: /* add interface address */
578 case SIOCINITIFADDR
: /* set interface address */
579 case SIOCSIFDSTADDR
: /* set interface destination address */
580 if(ifa
->ifa_addr
->sa_family
!= AF_INET
)
581 error
= EAFNOSUPPORT
;
583 sc
->sc_if
.if_flags
|= IFF_UP
;
586 case SIOCSIFFLAGS
: /* set interface flags */
587 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
589 if ((ifr
->ifr_flags
& IFF_UP
) == 0) {
590 if (sc
->sc_if
.if_flags
& IFF_RUNNING
) {
591 /* disconnect ISDN line */
592 i4b_l4_drvrdisc(sc
->sc_cdp
->cdid
);
593 sc
->sc_if
.if_flags
&= ~IFF_RUNNING
;
596 sc
->sc_state
= ST_IDLE
;
604 if(ifr
->ifr_flags
& IFF_DEBUG
)
605 ; /* enable debug messages */
610 #if !defined(__OpenBSD__)
611 case SIOCSIFMTU
: /* set interface MTU */
612 if(ifr
->ifr_mtu
> I4BIPRMAXMTU
)
614 else if(ifr
->ifr_mtu
< I4BIPRMINMTU
)
616 else if ((error
= ifioctl_common(ifp
, cmd
, data
)) == ENETRESET
)
619 #endif /* __OPENBSD__ */
622 /* not needed for FreeBSD, done in sl_compress_init() (-hm) */
624 /* need to add an ioctl: set VJ max slot ID
625 * #define IPRIOCSMAXCID _IOW('I', XXX, int)
630 struct lwp
*l
= curlwp
; /* XXX */
632 if((error
= kauth_authorize_network(l
->l_cred
,
633 KAUTH_NETWORK_INTERFACE
,
634 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
,
635 (void *)cmd
, NULL
)) != 0)
637 sl_compress_setup(sc
->sc_compr
, *(int *)data
);
643 error
= ifioctl_common(ifp
, cmd
, data
);
644 if (error
== ENETRESET
)
654 /*---------------------------------------------------------------------------*
655 * clear the interface's send queues
656 *---------------------------------------------------------------------------*/
658 iripclearqueues(struct ipr_softc
*sc
)
666 IF_DEQUEUE(&sc
->sc_fastq
, m
);
678 IFQ_DEQUEUE(&sc
->sc_if
.if_snd
, m
);
689 /*---------------------------------------------------------------------------*
691 *---------------------------------------------------------------------------*/
694 iprwatchdog(int unit
)
698 iprwatchdog(struct ifnet
*ifp
)
702 int unit
= ifp
->if_unit
;
703 struct ipr_softc
*sc
= &ipr_softc
[unit
];
704 #elif defined(__bsdi__)
705 struct ipr_softc
*sc
= &ipr_softc
[unit
];
706 struct ifnet
*ifp
= &ipr_softc
[unit
].sc_if
;
708 struct ipr_softc
*sc
= ifp
->if_softc
;
710 bchan_statistics_t bs
;
712 /* get # of bytes in and out from the HSCX driver */
714 (*sc
->sc_ilt
->bchannel_driver
->bch_stat
)
715 (sc
->sc_ilt
->l1token
, sc
->sc_ilt
->channel
, &bs
);
717 sc
->sc_ioutb
+= bs
.outbytes
;
718 sc
->sc_iinb
+= bs
.inbytes
;
720 if((sc
->sc_iinb
!= sc
->sc_linb
) || (sc
->sc_ioutb
!= sc
->sc_loutb
) || sc
->sc_fn
)
722 int ri
= (sc
->sc_iinb
- sc
->sc_linb
)/I4BIPRACCTINTVL
;
723 int ro
= (sc
->sc_ioutb
- sc
->sc_loutb
)/I4BIPRACCTINTVL
;
725 if((sc
->sc_iinb
== sc
->sc_linb
) && (sc
->sc_ioutb
== sc
->sc_loutb
))
730 sc
->sc_linb
= sc
->sc_iinb
;
731 sc
->sc_loutb
= sc
->sc_ioutb
;
734 i4b_l4_accounting(sc
->sc_cdp
->cdid
, ACCT_DURING
,
735 sc
->sc_ioutb
, sc
->sc_iinb
, ro
, ri
, sc
->sc_outb
, sc
->sc_inb
);
737 sc
->sc_if
.if_timer
= I4BIPRACCTINTVL
;
742 #endif /* I4BIPRACCT */
744 /*===========================================================================*
745 * ISDN INTERFACE ROUTINES
746 *===========================================================================*/
748 /*---------------------------------------------------------------------------*
749 * start transmitting after connect
750 *---------------------------------------------------------------------------*/
752 i4bipr_connect_startio(struct ipr_softc
*sc
)
756 if(sc
->sc_state
== ST_CONNECTED_W
)
758 sc
->sc_state
= ST_CONNECTED_A
;
759 ipr_tx_queue_empty(sc
);
765 /*---------------------------------------------------------------------------*
766 * this routine is called from L4 handler at connect time
767 *---------------------------------------------------------------------------*/
769 ipr_connect(void *softc
, void *cdp
)
771 struct ipr_softc
*sc
= softc
;
774 sc
->sc_cdp
= (call_desc_t
*)cdp
;
778 NDBGL4(L4_DIALST
, "%s: setting dial state to ST_CONNECTED", sc
->sc_if
.if_xname
);
780 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
781 sc
->sc_state
= ST_CONNECTED_W
;
783 sc
->sc_dialresp
= DSTAT_NONE
;
784 sc
->sc_lastdialresp
= DSTAT_NONE
;
793 sc
->sc_if
.if_timer
= I4BIPRACCTINTVL
;
797 sc
->sc_first_pkt
= 1;
801 * Sometimes ISDN B-channels are switched thru asymmetic. This
802 * means that under such circumstances B-channel data (the first
803 * three packets of a TCP connection in my case) may get lost,
804 * causing a large delay until the connection is started.
805 * When the sending of the very first packet of a TCP connection
806 * is delayed for a to be empirically determined delay (close
807 * to a second in my case) those packets go thru and the TCP
808 * connection comes up "almost" immediately (-hm).
811 if(sc
->sc_cdp
->isdntxdelay
> 0)
816 xdelay
= sc
->sc_cdp
->isdntxdelay
; /* avoid any rounding */
818 xdelay
= sc
->sc_cdp
->isdntxdelay
*hz
;
822 START_TIMER(sc
->sc_callout
, (TIMEOUT_FUNC_T
)i4bipr_connect_startio
, (void *)sc
, xdelay
);
826 sc
->sc_state
= ST_CONNECTED_A
;
827 ipr_tx_queue_empty(sc
);
832 /* we don't need any negotiation - pass event back right now */
833 i4b_l4_negcomplete(sc
->sc_cdp
);
836 /*---------------------------------------------------------------------------*
837 * this routine is called from L4 handler at disconnect time
838 *---------------------------------------------------------------------------*/
840 ipr_disconnect(void *softc
, void *cdp
)
842 call_desc_t
*cd
= (call_desc_t
*)cdp
;
843 struct ipr_softc
*sc
= softc
;
845 /* new stuff to check that the active channel is being closed */
847 if (cd
!= sc
->sc_cdp
)
849 NDBGL4(L4_IPRDBG
, "%s: channel %d not active",
850 sc
->sc_if
.if_xname
, cd
->channelid
);
855 sc
->sc_if
.if_timer
= 0;
858 /* show next IPR_LOG packets again */
859 sc
->sc_log_first
= IPR_LOG
;
862 i4b_l4_accounting(cd
->cdid
, ACCT_FINAL
,
863 sc
->sc_ioutb
, sc
->sc_iinb
, 0, 0, sc
->sc_outb
, sc
->sc_inb
);
867 NDBGL4(L4_DIALST
, "setting dial state to ST_IDLE");
869 sc
->sc_dialresp
= DSTAT_NONE
;
870 sc
->sc_lastdialresp
= DSTAT_NONE
;
872 sc
->sc_if
.if_flags
&= ~IFF_RUNNING
;
873 sc
->sc_state
= ST_IDLE
;
876 /*---------------------------------------------------------------------------*
877 * this routine is used to give a feedback from userland daemon
878 * in case of dial problems
879 *---------------------------------------------------------------------------*/
881 ipr_dialresponse(void *softc
, int status
, cause_t cause
)
883 struct ipr_softc
*sc
= softc
;
884 sc
->sc_dialresp
= status
;
886 NDBGL4(L4_IPRDBG
, "%s: last=%d, this=%d",
887 sc
->sc_if
.if_xname
, sc
->sc_lastdialresp
, sc
->sc_dialresp
);
889 if(status
!= DSTAT_NONE
)
891 NDBGL4(L4_IPRDBG
, "%s: clearing queues", sc
->sc_if
.if_xname
);
896 /*---------------------------------------------------------------------------*
897 * interface soft up/down
898 *---------------------------------------------------------------------------*/
900 ipr_updown(void *softc
, int updown
)
902 struct ipr_softc
*sc
= softc
;
903 sc
->sc_updown
= updown
;
906 /*---------------------------------------------------------------------------*
907 * this routine is called from the HSCX interrupt handler
908 * when a new frame (mbuf) has been received and was put on
909 * the rx queue. It is assumed that this routines runs at
910 * appropriate protection level! Keep it short !
911 *---------------------------------------------------------------------------*/
913 ipr_rx_data_rdy(void *softc
)
915 register struct ipr_softc
*sc
= softc
;
916 register struct mbuf
*m
;
918 #ifdef IPR_VJ_USEBUFFER
919 u_char
*cp
= sc
->sc_cbuf
;
924 if((m
= *sc
->sc_ilt
->rx_mbuf
) == NULL
)
927 m
->m_pkthdr
.rcvif
= &sc
->sc_if
;
929 m
->m_pkthdr
.len
= m
->m_len
;
934 * The very first packet after the B channel is switched thru
935 * has very often several bytes of random data prepended. This
936 * routine looks where the IP header starts and removes the
942 unsigned char *mp
= m
->m_data
;
945 sc
->sc_first_pkt
= 0;
947 for(i
= 0; i
< m
->m_len
; i
++, mp
++)
949 if( ((*mp
& 0xf0) == 0x40) &&
950 ((*mp
& 0x0f) >= 0x05) )
953 m
->m_pkthdr
.len
-= i
;
960 sc
->sc_if
.if_ipackets
++;
961 sc
->sc_if
.if_ibytes
+= m
->m_pkthdr
.len
;
964 if((c
= (*(mtod(m
, u_char
*)) & 0xf0)) != (IPVERSION
<< 4))
966 /* copy data to buffer */
970 #ifdef IPR_VJ_USEBUFFER
971 /* XXX */ m_copydata(m
, 0, len
, cp
);
976 c
= TYPE_COMPRESSED_TCP
;
978 else if(c
== TYPE_UNCOMPRESSED_TCP
)
980 #ifdef IPR_VJ_USEBUFFER
981 *cp
&= 0x4f; /* XXX */
983 *(mtod(m
, u_char
*)) &= 0x4f;
988 * We've got something that's not an IP packet.
989 * If compression is enabled, try to decompress it.
990 * Otherwise, if `auto-enable' compression is on and
991 * it's a reasonable packet, decompress it and then
992 * enable compression. Otherwise, drop it.
994 if(sc
->sc_if
.if_flags
& IPR_COMPRESS
)
996 #ifdef IPR_VJ_USEBUFFER
997 len
= sl_uncompress_tcp(&cp
,len
,(u_int
)c
,&sc
->sc_compr
);
999 len
= sl_uncompress_tcp((u_char
**)&m
->m_data
, len
,
1000 (u_int
)c
, &sc
->sc_compr
);
1006 printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_COMPRESS!\n");
1011 else if((sc
->sc_if
.if_flags
& IPR_AUTOCOMP
) &&
1012 (c
== TYPE_UNCOMPRESSED_TCP
) && (len
>= 40))
1014 #ifdef IPR_VJ_USEBUFFER
1015 len
= sl_uncompress_tcp(&cp
,len
,(u_int
)c
,&sc
->sc_compr
);
1017 len
= sl_uncompress_tcp((u_char
**)&m
->m_data
, len
,
1018 (u_int
)c
, &sc
->sc_compr
);
1024 printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_AUTOCOMP!\n");
1029 sc
->sc_if
.if_flags
|= IPR_COMPRESS
;
1034 printf("i4b_ipr, ipr_input: invalid ip packet!\n");
1038 sc
->sc_if
.if_ierrors
++;
1039 sc
->sc_if
.if_collisions
++;
1043 #ifdef IPR_VJ_USEBUFFER
1044 /* XXX */ m_copyback(m
, 0, len
, cp
);
1046 m
->m_len
= m
->m_pkthdr
.len
= len
;
1052 /* NB. do the accounting after decompression! */
1053 sc
->sc_inb
+= m
->m_pkthdr
.len
;
1056 if(sc
->sc_log_first
> 0)
1058 --(sc
->sc_log_first
);
1059 i4b_l4_packet_ind(irip_driver_id
, sc
->sc_unit
, 0, m
);
1063 #if NBPFILTER > 0 || NBPF > 0
1064 if(sc
->sc_if
.if_bpf
)
1066 /* prepend the address family as a four byte field */
1071 mm
.m_data
= (char *)&af
;
1074 bpf_mtap(&sc
->sc_if
, &mm
);
1076 bpf_mtap(sc
->sc_if
.if_bpf
, &mm
);
1079 #endif /* NBPFILTER > 0 || NBPF > 0 */
1081 if(IF_QFULL(&ipintrq
))
1083 NDBGL4(L4_IPRDBG
, "%s: ipintrq full!", sc
->sc_if
.if_xname
);
1086 sc
->sc_if
.if_ierrors
++;
1087 sc
->sc_if
.if_iqdrops
++;
1092 IF_ENQUEUE(&ipintrq
, m
);
1093 schednetisr(NETISR_IP
);
1097 /*---------------------------------------------------------------------------*
1098 * this routine is called from the HSCX interrupt handler
1099 * when the last frame has been sent out and there is no
1100 * further frame (mbuf) in the tx queue.
1101 *---------------------------------------------------------------------------*/
1103 ipr_tx_queue_empty(void *softc
)
1105 register struct ipr_softc
*sc
= softc
;
1106 register struct mbuf
*m
;
1112 if(sc
->sc_state
!= ST_CONNECTED_A
)
1117 IF_DEQUEUE(&sc
->sc_fastq
, m
);
1120 sc
->sc_if
.if_omcasts
++;
1124 IFQ_DEQUEUE(&sc
->sc_if
.if_snd
, m
);
1129 #if NBPFILTER > 0 || NBPF > 0
1130 if(sc
->sc_if
.if_bpf
)
1132 /* prepend the address family as a four byte field */
1138 mm
.m_data
= (char *)&af
;
1141 bpf_mtap(&sc
->sc_if
, &mm
);
1143 bpf_mtap(sc
->sc_if
.if_bpf
, &mm
);
1146 #endif /* NBPFILTER */
1149 sc
->sc_outb
+= m
->m_pkthdr
.len
; /* size before compression */
1153 if((ip
= mtod(m
, struct ip
*))->ip_p
== IPPROTO_TCP
)
1155 if(sc
->sc_if
.if_flags
& IPR_COMPRESS
)
1157 *mtod(m
, u_char
*) |= sl_compress_tcp(m
, ip
,
1164 if(IF_QFULL(sc
->sc_ilt
->tx_queue
))
1166 NDBGL4(L4_IPRDBG
, "%s: tx queue full!", sc
->sc_if
.if_xname
);
1171 IF_ENQUEUE(sc
->sc_ilt
->tx_queue
, m
);
1173 sc
->sc_if
.if_obytes
+= m
->m_pkthdr
.len
;
1175 sc
->sc_if
.if_opackets
++;
1180 (*sc
->sc_ilt
->bchannel_driver
->bch_tx_start
)(sc
->sc_ilt
->l1token
, sc
->sc_ilt
->channel
);
1183 /*---------------------------------------------------------------------------*
1184 * this routine is called from the HSCX interrupt handler
1185 * each time a packet is received or transmitted. It should
1186 * be used to implement an activity timeout mechanism.
1187 *---------------------------------------------------------------------------*/
1189 ipr_activity(void *softc
, int rxtx
)
1191 struct ipr_softc
*sc
= softc
;
1192 sc
->sc_cdp
->last_active_time
= SECOND
;
1195 /*---------------------------------------------------------------------------*
1196 * return this drivers linktab address
1197 *---------------------------------------------------------------------------*/
1199 ipr_get_softc(int unit
)
1201 return &ipr_softc
[unit
];
1204 /*---------------------------------------------------------------------------*
1205 * setup the isdn_linktab for this driver
1206 *---------------------------------------------------------------------------*/
1208 ipr_set_linktab(void *softc
, isdn_link_t
*ilt
)
1210 struct ipr_softc
*sc
= softc
;
1214 /*===========================================================================*/
1216 #endif /* NIRIP > 0 */