2 * Copyright (c) 1997, 2001 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 * $FreeBSD: src/sys/i4b/driver/i4b_ipr.c,v 1.8.2.3 2001/10/27 15:48:17 hm Exp $
31 * $DragonFly: src/sys/net/i4b/driver/i4b_ipr.c,v 1.21 2008/01/06 16:55:52 swildner Exp $
33 * last edit-date: [Fri Oct 26 19:32:38 2001]
35 *---------------------------------------------------------------------------*
37 * statistics counter usage (interface lifetime):
38 * ----------------------------------------------
39 * sc->sc_if.if_ipackets # of received packets
40 * sc->sc_if.if_ierrors # of error packets not going to upper layers
41 * sc->sc_if.if_opackets # of transmitted packets
42 * sc->sc_if.if_oerrors # of error packets not being transmitted
43 * sc->sc_if.if_collisions # of invalid ip packets after VJ decompression
44 * sc->sc_if.if_ibytes # of bytes coming in from the line (before VJ)
45 * sc->sc_if.if_obytes # of bytes going out to the line (after VJ)
46 * sc->sc_if.if_imcasts (currently unused)
47 * sc->sc_if.if_omcasts # of frames sent out of the fastqueue
48 * sc->sc_if.if_iqdrops # of frames dropped on input because queue full
49 * sc->sc_if.if_noproto # of frames dropped on output because !AF_INET
51 * statistics counter usage (connection lifetime):
52 * -----------------------------------------------
53 * sc->sc_iinb # of ISDN incoming bytes from HSCX
54 * sc->sc_ioutb # of ISDN outgoing bytes from HSCX
55 * sc->sc_inb # of incoming bytes after decompression
56 * sc->sc_outb # of outgoing bytes before compression
58 *---------------------------------------------------------------------------*/
60 #include "use_i4bipr.h"
66 #include <sys/param.h>
67 #include <sys/systm.h>
69 #include <sys/socket.h>
70 #include <sys/errno.h>
72 #include <sys/ioccom.h>
73 #include <sys/sockio.h>
75 #include <sys/malloc.h>
78 #include <sys/kernel.h>
79 #include <sys/thread2.h>
82 #include <net/if_types.h>
83 #include <net/netisr.h>
85 #include <netinet/in.h>
86 #include <netinet/in_systm.h>
87 #include <netinet/in_var.h>
88 #include <netinet/ip.h>
91 #include <net/slcompress.h>
92 #define IPR_COMPRESS IFF_LINK0 /* compress TCP traffic */
93 #define IPR_AUTOCOMP IFF_LINK1 /* auto-enable TCP compression */
95 /*---------------------------------------------------------------------------
96 * NOTICE: using NO separate buffer relies on the assumption, that the HSCX
97 * IRQ handler _always_ allocates a single, continuous mbuf cluster large
98 * enough to hold the maximum MTU size if the ipr interface !
100 * CAUTION: i have re-defined IPR_VJ_USEBUFFER because it makes problems
101 * with 2 i4b's back to back running cvs over ssh, cvs simply
102 * aborts because it gets bad data. Everything else (telnet/ftp?etc)
104 *---------------------------------------------------------------------------*/
105 #define IPR_VJ_USEBUFFER /* define to use an allocated separate buffer*/
106 /* undef to uncompress in the mbuf itself */
111 #if NBPFILTER > 0 || NBPF > 0
112 #include <sys/time.h>
116 #include <net/i4b/include/machine/i4b_debug.h>
117 #include <net/i4b/include/machine/i4b_ioctl.h>
119 #include "../include/i4b_global.h"
120 #include "../include/i4b_l3l4.h"
122 #include "../layer4/i4b_l4.h"
124 #define IPR_FMT "%s: "
125 #define IPR_ARG(sc) ((sc)->sc_if.if_xname)
126 #define PDEVSTATIC /* not static */
128 #define I4BIPRMTU 1500 /* regular MTU */
129 #define I4BIPRMAXMTU 2000 /* max MTU */
130 #define I4BIPRMINMTU 500 /* min MTU */
132 #define I4BIPRMAXQLEN 50 /* max queue length */
134 #define I4BIPRACCT 1 /* enable accounting messages */
135 #define I4BIPRACCTINTVL 2 /* accounting msg interval in secs */
136 #define I4BIPRADJFRXP 1 /* adjust 1st rxd packet */
138 /* initialized by L4 */
140 static drvr_link_t ipr_drvr_linktab
[NI4BIPR
];
141 static isdn_link_t
*isdn_linktab
[NI4BIPR
];
144 struct ifnet sc_if
; /* network-visible interface */
145 int sc_state
; /* state of the interface */
146 int sc_unit
; /* unit number */
147 call_desc_t
*sc_cdp
; /* ptr to call descriptor */
148 int sc_updown
; /* soft state of interface */
149 struct ifqueue sc_fastq
; /* interactive traffic */
150 int sc_dialresp
; /* dialresponse */
151 int sc_lastdialresp
;/* last dialresponse */
154 int sc_iinb
; /* isdn driver # of inbytes */
155 int sc_ioutb
; /* isdn driver # of outbytes */
156 int sc_inb
; /* # of bytes rx'd */
157 int sc_outb
; /* # of bytes tx'd */
158 int sc_linb
; /* last # of bytes rx'd */
159 int sc_loutb
; /* last # of bytes tx'd */
160 int sc_fn
; /* flag, first null acct */
163 struct callout sc_timeout
;
166 int sc_first_pkt
; /* flag, first rxd packet */
169 int sc_log_first
; /* log first n packets */
173 struct slcompress sc_compr
; /* tcp compression data */
174 #ifdef IPR_VJ_USEBUFFER
175 u_char
*sc_cbuf
; /* tcp decompression buffer */
179 } ipr_softc
[NI4BIPR
];
182 ST_IDLE
, /* initialized, ready, idle */
183 ST_DIALING
, /* dialling out to remote */
184 ST_CONNECTED_W
, /* connected to remote */
185 ST_CONNECTED_A
, /* connected to remote */
188 #define THE_UNIT sc->sc_unit
190 # define IOCTL_CMD_T u_long
192 PDEVSTATIC
void i4biprattach(void *);
193 PSEUDO_SET(i4biprattach
, i4b_ipr
);
194 static int i4biprioctl(struct ifnet
*ifp
, IOCTL_CMD_T cmd
, caddr_t data
,
196 static void iprwatchdog(struct ifnet
*ifp
);
197 static void ipr_init_linktab(int unit
);
198 static void ipr_tx_queue_empty(int unit
);
199 static int i4biproutput(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
, struct rtentry
*rtp
);
200 static void iprclearqueues(struct ipr_softc
*sc
);
202 /*===========================================================================*
203 * DEVICE DRIVER ROUTINES
204 *===========================================================================*/
206 /*---------------------------------------------------------------------------*
207 * interface attach routine at kernel boot time
208 *---------------------------------------------------------------------------*/
210 i4biprattach(void *dummy
)
212 struct ipr_softc
*sc
= ipr_softc
;
216 kprintf("i4bipr: %d IP over raw HDLC ISDN device(s) attached (VJ header compression)\n", NI4BIPR
);
218 kprintf("i4bipr: %d IP over raw HDLC ISDN device(s) attached\n", NI4BIPR
);
221 for(i
=0; i
< NI4BIPR
; sc
++, i
++)
225 NDBGL4(L4_DIALST
, "setting dial state to ST_IDLE");
227 sc
->sc_state
= ST_IDLE
;
229 if_initname(&(sc
->sc_if
), "ipr", i
);
232 sc
->sc_if
.if_flags
= IFF_POINTOPOINT
| IFF_SIMPLEX
| IPR_AUTOCOMP
;
234 sc
->sc_if
.if_flags
= IFF_POINTOPOINT
| IFF_SIMPLEX
;
237 callout_init(&sc
->sc_timeout
);
239 sc
->sc_if
.if_mtu
= I4BIPRMTU
;
240 sc
->sc_if
.if_type
= IFT_ISDNBASIC
;
241 sc
->sc_if
.if_ioctl
= i4biprioctl
;
242 sc
->sc_if
.if_output
= i4biproutput
;
244 sc
->sc_if
.if_snd
.ifq_maxlen
= I4BIPRMAXQLEN
;
245 sc
->sc_fastq
.ifq_maxlen
= I4BIPRMAXQLEN
;
247 sc
->sc_if
.if_ipackets
= 0;
248 sc
->sc_if
.if_ierrors
= 0;
249 sc
->sc_if
.if_opackets
= 0;
250 sc
->sc_if
.if_oerrors
= 0;
251 sc
->sc_if
.if_collisions
= 0;
252 sc
->sc_if
.if_ibytes
= 0;
253 sc
->sc_if
.if_obytes
= 0;
254 sc
->sc_if
.if_imcasts
= 0;
255 sc
->sc_if
.if_omcasts
= 0;
256 sc
->sc_if
.if_iqdrops
= 0;
257 sc
->sc_if
.if_noproto
= 0;
260 sc
->sc_if
.if_timer
= 0;
261 sc
->sc_if
.if_watchdog
= iprwatchdog
;
271 sc
->sc_log_first
= IPR_LOG
;
275 sl_compress_init(&sc
->sc_compr
, -1);
277 #ifdef IPR_VJ_USEBUFFER
278 sc
->sc_cbuf
= (u_char
*)kmalloc(I4BIPRMAXMTU
+128, M_DEVBUF
,
282 sc
->sc_updown
= SOFT_ENA
; /* soft enabled */
283 sc
->sc_dialresp
= DSTAT_NONE
; /* no response */
284 sc
->sc_lastdialresp
= DSTAT_NONE
;
286 if_attach(&sc
->sc_if
, NULL
);
287 bpfattach(&sc
->sc_if
, DLT_NULL
, sizeof(u_int
));
291 /*---------------------------------------------------------------------------*
292 * output a packet to the ISDN B-channel
293 *---------------------------------------------------------------------------*/
295 i4biproutput(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
,
298 struct ipr_softc
*sc
;
309 if(dst
->sa_family
!= AF_INET
)
311 kprintf(IPR_FMT
"af%d not supported\n", IPR_ARG(sc
), dst
->sa_family
);
314 sc
->sc_if
.if_noproto
++;
315 sc
->sc_if
.if_oerrors
++;
316 return(EAFNOSUPPORT
);
319 /* check interface state = UP */
321 if(!(ifp
->if_flags
& IFF_UP
))
323 NDBGL4(L4_IPRDBG
, "ipr%d: interface is DOWN!", unit
);
326 sc
->sc_if
.if_oerrors
++;
330 /* dial if necessary */
332 if(sc
->sc_state
== ST_IDLE
|| sc
->sc_state
== ST_DIALING
)
336 switch(sc
->sc_dialresp
)
338 case DSTAT_TFAIL
: /* transient failure */
339 NDBGL4(L4_IPRDBG
, "ipr%d: transient dial failure!", unit
);
342 sc
->sc_dialresp
= DSTAT_NONE
;
344 sc
->sc_if
.if_oerrors
++;
348 case DSTAT_PFAIL
: /* permanent failure */
349 NDBGL4(L4_IPRDBG
, "ipr%d: permanent dial failure!", unit
);
352 sc
->sc_dialresp
= DSTAT_NONE
;
354 sc
->sc_if
.if_oerrors
++;
355 return(EHOSTUNREACH
);
358 case DSTAT_INONLY
: /* no dialout allowed*/
359 NDBGL4(L4_IPRDBG
, "ipr%d: dialout not allowed failure!", unit
);
362 sc
->sc_dialresp
= DSTAT_NONE
;
364 sc
->sc_if
.if_oerrors
++;
365 return(EHOSTUNREACH
);
370 NDBGL4(L4_IPRDBG
, "ipr%d: send dial request message!", unit
);
371 NDBGL4(L4_DIALST
, "ipr%d: setting dial state to ST_DIALING", unit
);
372 i4b_l4_dialout(BDRV_IPR
, unit
);
373 sc
->sc_state
= ST_DIALING
;
377 if(sc
->sc_log_first
> 0)
379 --(sc
->sc_log_first
);
380 i4b_l4_packet_ind(BDRV_IPR
, unit
, 1, m
);
384 /* update access time */
386 microtime(&sc
->sc_if
.if_lastchange
);
389 * check, if type of service indicates interactive, i.e. telnet,
390 * traffic. in case it is interactive, put it into the fast queue,
391 * else (i.e. ftp traffic) put it into the "normal" queue
394 ip
= mtod(m
, struct ip
*); /* get ptr to ip header */
396 /* check for space in choosen send queue */
398 if (netisr_queue(NETISR_IP
, m
))
400 NDBGL4(L4_IPRDBG
, "ipr%d: send queue full!", unit
);
402 sc
->sc_if
.if_oerrors
++;
406 NDBGL4(L4_IPRDBG
, "ipr%d: add packet to send queue!", unit
);
408 ipr_tx_queue_empty(unit
);
415 /*---------------------------------------------------------------------------*
417 *---------------------------------------------------------------------------*/
419 i4biprioctl(struct ifnet
*ifp
, IOCTL_CMD_T cmd
, caddr_t data
, struct ucred
*cr
)
421 struct ipr_softc
*sc
= ifp
->if_softc
;
423 struct ifreq
*ifr
= (struct ifreq
*)data
;
424 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
431 case SIOCAIFADDR
: /* add interface address */
432 case SIOCSIFADDR
: /* set interface address */
433 case SIOCSIFDSTADDR
: /* set interface destination address */
434 if(ifa
->ifa_addr
->sa_family
!= AF_INET
)
435 error
= EAFNOSUPPORT
;
437 sc
->sc_if
.if_flags
|= IFF_UP
;
438 microtime(&sc
->sc_if
.if_lastchange
);
441 case SIOCSIFFLAGS
: /* set interface flags */
442 if(!(ifr
->ifr_flags
& IFF_UP
))
444 if(sc
->sc_if
.if_flags
& IFF_RUNNING
)
446 /* disconnect ISDN line */
447 i4b_l4_drvrdisc(BDRV_IPR
, sc
->sc_unit
);
448 sc
->sc_if
.if_flags
&= ~IFF_RUNNING
;
451 sc
->sc_state
= ST_IDLE
;
458 if(ifr
->ifr_flags
& IFF_DEBUG
)
460 /* enable debug messages */
463 microtime(&sc
->sc_if
.if_lastchange
);
466 case SIOCSIFMTU
: /* set interface MTU */
467 if(ifr
->ifr_mtu
> I4BIPRMAXMTU
)
469 else if(ifr
->ifr_mtu
< I4BIPRMINMTU
)
473 ifp
->if_mtu
= ifr
->ifr_mtu
;
474 microtime(&sc
->sc_if
.if_lastchange
);
479 /* not needed for FreeBSD, done in sl_compress_init() (-hm) */
481 /* need to add an ioctl: set VJ max slot ID
482 * #define IPRIOCSMAXCID _IOW('I', XXX, int)
487 struct thread
*td
= curthread
; /* XXX */
489 if ((error
= suser(td
)) != 0)
491 sl_compress_setup(sc
->sc_compr
, *(int *)data
);
506 /*---------------------------------------------------------------------------*
507 * clear the interface's send queues
508 *---------------------------------------------------------------------------*/
510 iprclearqueues(struct ipr_softc
*sc
)
517 IF_DEQUEUE(&sc
->sc_fastq
, m
);
528 IF_DEQUEUE(&sc
->sc_if
.if_snd
, m
);
538 /*---------------------------------------------------------------------------*
540 *---------------------------------------------------------------------------*/
542 iprwatchdog(struct ifnet
*ifp
)
544 struct ipr_softc
*sc
= ifp
->if_softc
;
545 int unit
= sc
->sc_unit
;
546 bchan_statistics_t bs
;
548 /* get # of bytes in and out from the HSCX driver */
550 (*isdn_linktab
[unit
]->bch_stat
)
551 (isdn_linktab
[unit
]->unit
, isdn_linktab
[unit
]->channel
, &bs
);
553 sc
->sc_ioutb
+= bs
.outbytes
;
554 sc
->sc_iinb
+= bs
.inbytes
;
556 if((sc
->sc_iinb
!= sc
->sc_linb
) || (sc
->sc_ioutb
!= sc
->sc_loutb
) || sc
->sc_fn
)
558 int ri
= (sc
->sc_iinb
- sc
->sc_linb
)/I4BIPRACCTINTVL
;
559 int ro
= (sc
->sc_ioutb
- sc
->sc_loutb
)/I4BIPRACCTINTVL
;
561 if((sc
->sc_iinb
== sc
->sc_linb
) && (sc
->sc_ioutb
== sc
->sc_loutb
))
566 sc
->sc_linb
= sc
->sc_iinb
;
567 sc
->sc_loutb
= sc
->sc_ioutb
;
569 i4b_l4_accounting(BDRV_IPR
, unit
, ACCT_DURING
,
570 sc
->sc_ioutb
, sc
->sc_iinb
, ro
, ri
, sc
->sc_outb
, sc
->sc_inb
);
572 sc
->sc_if
.if_timer
= I4BIPRACCTINTVL
;
574 #endif /* I4BIPRACCT */
576 /*===========================================================================*
577 * ISDN INTERFACE ROUTINES
578 *===========================================================================*/
580 /*---------------------------------------------------------------------------*
581 * start transmitting after connect
582 *---------------------------------------------------------------------------*/
584 i4bipr_connect_startio(struct ipr_softc
*sc
)
588 if(sc
->sc_state
== ST_CONNECTED_W
)
590 sc
->sc_state
= ST_CONNECTED_A
;
591 ipr_tx_queue_empty(THE_UNIT
);
597 /*---------------------------------------------------------------------------*
598 * this routine is called from L4 handler at connect time
599 *---------------------------------------------------------------------------*/
601 ipr_connect(int unit
, void *cdp
)
603 struct ipr_softc
*sc
= &ipr_softc
[unit
];
605 sc
->sc_cdp
= (call_desc_t
*)cdp
;
609 NDBGL4(L4_DIALST
, "ipr%d: setting dial state to ST_CONNECTED", unit
);
611 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
612 sc
->sc_state
= ST_CONNECTED_W
;
614 sc
->sc_dialresp
= DSTAT_NONE
;
615 sc
->sc_lastdialresp
= DSTAT_NONE
;
624 sc
->sc_if
.if_timer
= I4BIPRACCTINTVL
;
628 sc
->sc_first_pkt
= 1;
632 * Sometimes ISDN B-channels are switched thru asymmetic. This
633 * means that under such circumstances B-channel data (the first
634 * three packets of a TCP connection in my case) may get lost,
635 * causing a large delay until the connection is started.
636 * When the sending of the very first packet of a TCP connection
637 * is delayed for a to be empirically determined delay (close
638 * to a second in my case) those packets go thru and the TCP
639 * connection comes up "almost" immediately (-hm).
642 if(sc
->sc_cdp
->isdntxdelay
> 0)
647 delay
= sc
->sc_cdp
->isdntxdelay
; /* avoid any rounding */
649 delay
= sc
->sc_cdp
->isdntxdelay
*hz
;
653 callout_reset(&sc
->sc_timeout
, delay
,
654 (TIMEOUT_FUNC_T
)i4bipr_connect_startio
, sc
);
658 sc
->sc_state
= ST_CONNECTED_A
;
659 ipr_tx_queue_empty(unit
);
664 /* we don't need any negotiation - pass event back right now */
665 i4b_l4_negcomplete(sc
->sc_cdp
);
668 /*---------------------------------------------------------------------------*
669 * this routine is called from L4 handler at disconnect time
670 *---------------------------------------------------------------------------*/
672 ipr_disconnect(int unit
, void *cdp
)
674 call_desc_t
*cd
= (call_desc_t
*)cdp
;
675 struct ipr_softc
*sc
= &ipr_softc
[unit
];
677 /* new stuff to check that the active channel is being closed */
679 if (cd
!= sc
->sc_cdp
)
681 NDBGL4(L4_IPRDBG
, "ipr%d: channel %d not active",
682 cd
->driver_unit
, cd
->channelid
);
687 sc
->sc_if
.if_timer
= 0;
690 /* show next IPR_LOG packets again */
691 sc
->sc_log_first
= IPR_LOG
;
694 i4b_l4_accounting(BDRV_IPR
, cd
->driver_unit
, ACCT_FINAL
,
695 sc
->sc_ioutb
, sc
->sc_iinb
, 0, 0, sc
->sc_outb
, sc
->sc_inb
);
697 sc
->sc_cdp
= (call_desc_t
*)0;
699 NDBGL4(L4_DIALST
, "setting dial state to ST_IDLE");
701 sc
->sc_dialresp
= DSTAT_NONE
;
702 sc
->sc_lastdialresp
= DSTAT_NONE
;
704 sc
->sc_if
.if_flags
&= ~IFF_RUNNING
;
705 sc
->sc_state
= ST_IDLE
;
708 /*---------------------------------------------------------------------------*
709 * this routine is used to give a feedback from userland daemon
710 * in case of dial problems
711 *---------------------------------------------------------------------------*/
713 ipr_dialresponse(int unit
, int status
, cause_t cause
)
715 struct ipr_softc
*sc
= &ipr_softc
[unit
];
716 sc
->sc_dialresp
= status
;
718 NDBGL4(L4_IPRDBG
, "ipr%d: last=%d, this=%d",
719 unit
, sc
->sc_lastdialresp
, sc
->sc_dialresp
);
721 if(status
!= DSTAT_NONE
)
723 NDBGL4(L4_IPRDBG
, "ipr%d: clearing queues", unit
);
728 /*---------------------------------------------------------------------------*
729 * interface soft up/down
730 *---------------------------------------------------------------------------*/
732 ipr_updown(int unit
, int updown
)
734 struct ipr_softc
*sc
= &ipr_softc
[unit
];
735 sc
->sc_updown
= updown
;
738 /*---------------------------------------------------------------------------*
739 * this routine is called from the HSCX interrupt handler
740 * when a new frame (mbuf) has been received and was put on
741 * the rx queue. It is assumed that this routines runs in
742 * a critical section ! Keep it short !
743 *---------------------------------------------------------------------------*/
745 ipr_rx_data_rdy(int unit
)
747 struct ipr_softc
*sc
= &ipr_softc
[unit
];
750 #ifdef IPR_VJ_USEBUFFER
751 u_char
*cp
= sc
->sc_cbuf
;
755 static const uint32_t af
= AF_INET
;
757 if((m
= *isdn_linktab
[unit
]->rx_mbuf
) == NULL
)
760 m
->m_pkthdr
.rcvif
= &sc
->sc_if
;
762 m
->m_pkthdr
.len
= m
->m_len
;
764 microtime(&sc
->sc_if
.if_lastchange
);
769 * The very first packet after the B channel is switched thru
770 * has very often several bytes of random data prepended. This
771 * routine looks where the IP header starts and removes the
777 unsigned char *mp
= m
->m_data
;
780 sc
->sc_first_pkt
= 0;
782 for(i
= 0; i
< m
->m_len
; i
++, mp
++)
784 if( ((*mp
& 0xf0) == 0x40) &&
785 ((*mp
& 0x0f) >= 0x05) )
788 m
->m_pkthdr
.len
-= i
;
795 sc
->sc_if
.if_ipackets
++;
796 sc
->sc_if
.if_ibytes
+= m
->m_pkthdr
.len
;
799 if((c
= (*(mtod(m
, u_char
*)) & 0xf0)) != (IPVERSION
<< 4))
801 /* copy data to buffer */
805 #ifdef IPR_VJ_USEBUFFER
806 /* XXX */ m_copydata(m
, 0, len
, cp
);
811 c
= TYPE_COMPRESSED_TCP
;
813 else if(c
== TYPE_UNCOMPRESSED_TCP
)
815 #ifdef IPR_VJ_USEBUFFER
816 *cp
&= 0x4f; /* XXX */
818 *(mtod(m
, u_char
*)) &= 0x4f;
823 * We've got something that's not an IP packet.
824 * If compression is enabled, try to decompress it.
825 * Otherwise, if `auto-enable' compression is on and
826 * it's a reasonable packet, decompress it and then
827 * enable compression. Otherwise, drop it.
829 if(sc
->sc_if
.if_flags
& IPR_COMPRESS
)
831 #ifdef IPR_VJ_USEBUFFER
832 len
= sl_uncompress_tcp(&cp
,len
,(u_int
)c
,&sc
->sc_compr
);
834 len
= sl_uncompress_tcp((u_char
**)&m
->m_data
, len
,
835 (u_int
)c
, &sc
->sc_compr
);
841 kprintf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_COMPRESS!\n");
846 else if((sc
->sc_if
.if_flags
& IPR_AUTOCOMP
) &&
847 (c
== TYPE_UNCOMPRESSED_TCP
) && (len
>= 40))
849 #ifdef IPR_VJ_USEBUFFER
850 len
= sl_uncompress_tcp(&cp
,len
,(u_int
)c
,&sc
->sc_compr
);
852 len
= sl_uncompress_tcp((u_char
**)&m
->m_data
, len
,
853 (u_int
)c
, &sc
->sc_compr
);
859 kprintf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_AUTOCOMP!\n");
864 sc
->sc_if
.if_flags
|= IPR_COMPRESS
;
869 kprintf("i4b_ipr, ipr_input: invalid ip packet!\n");
873 sc
->sc_if
.if_ierrors
++;
874 sc
->sc_if
.if_collisions
++;
878 #ifdef IPR_VJ_USEBUFFER
879 /* XXX */ m_copyback(m
, 0, len
, cp
);
881 m
->m_len
= m
->m_pkthdr
.len
= len
;
887 /* NB. do the accounting after decompression! */
888 sc
->sc_inb
+= m
->m_pkthdr
.len
;
891 if(sc
->sc_log_first
> 0)
893 --(sc
->sc_log_first
);
894 i4b_l4_packet_ind(BDRV_IPR
, unit
, 0, m
);
898 if (sc
->sc_if
.if_bpf
)
899 bpf_ptap(sc
->sc_if
.if_bpf
, m
, &af
, sizeof(af
));
901 if (netisr_queue(NETISR_IP
, m
)) {
902 NDBGL4(L4_IPRDBG
, "ipr%d: ipintrq full!", unit
);
903 sc
->sc_if
.if_ierrors
++;
904 sc
->sc_if
.if_iqdrops
++;
908 /*---------------------------------------------------------------------------*
909 * this routine is called from the HSCX interrupt handler
910 * when the last frame has been sent out and there is no
911 * further frame (mbuf) in the tx queue.
912 *---------------------------------------------------------------------------*/
914 ipr_tx_queue_empty(int unit
)
916 static const uint32_t af
= AF_INET
;
917 struct ipr_softc
*sc
= &ipr_softc
[unit
];
924 if(sc
->sc_state
!= ST_CONNECTED_A
)
929 IF_DEQUEUE(&sc
->sc_fastq
, m
);
932 sc
->sc_if
.if_omcasts
++;
936 IF_DEQUEUE(&sc
->sc_if
.if_snd
, m
);
941 microtime(&sc
->sc_if
.if_lastchange
);
943 if (sc
->sc_if
.if_bpf
)
944 bpf_ptap(sc
->sc_if
.if_bpf
, m
, &af
, sizeof(af
));
947 sc
->sc_outb
+= m
->m_pkthdr
.len
; /* size before compression */
951 if((ip
= mtod(m
, struct ip
*))->ip_p
== IPPROTO_TCP
)
953 if(sc
->sc_if
.if_flags
& IPR_COMPRESS
)
955 *mtod(m
, u_char
*) |= sl_compress_tcp(m
, ip
,
962 if(IF_QFULL(isdn_linktab
[unit
]->tx_queue
))
964 NDBGL4(L4_IPRDBG
, "ipr%d: tx queue full!", unit
);
969 sc
->sc_if
.if_obytes
+= m
->m_pkthdr
.len
;
971 sc
->sc_if
.if_opackets
++;
973 IF_ENQUEUE(isdn_linktab
[unit
]->tx_queue
, m
);
979 (*isdn_linktab
[unit
]->bch_tx_start
)(isdn_linktab
[unit
]->unit
, isdn_linktab
[unit
]->channel
);
982 /*---------------------------------------------------------------------------*
983 * this routine is called from the HSCX interrupt handler
984 * each time a packet is received or transmitted. It should
985 * be used to implement an activity timeout mechanism.
986 *---------------------------------------------------------------------------*/
988 ipr_activity(int unit
, int rxtx
)
990 ipr_softc
[unit
].sc_cdp
->last_active_time
= SECOND
;
993 /*---------------------------------------------------------------------------*
994 * return this drivers linktab address
995 *---------------------------------------------------------------------------*/
997 ipr_ret_linktab(int unit
)
999 return(&ipr_drvr_linktab
[unit
]);
1002 /*---------------------------------------------------------------------------*
1003 * setup the isdn_linktab for this driver
1004 *---------------------------------------------------------------------------*/
1006 ipr_set_linktab(int unit
, isdn_link_t
*ilt
)
1008 isdn_linktab
[unit
] = ilt
;
1011 /*---------------------------------------------------------------------------*
1012 * initialize this drivers linktab
1013 *---------------------------------------------------------------------------*/
1015 ipr_init_linktab(int unit
)
1017 ipr_drvr_linktab
[unit
].unit
= unit
;
1018 ipr_drvr_linktab
[unit
].bch_rx_data_ready
= ipr_rx_data_rdy
;
1019 ipr_drvr_linktab
[unit
].bch_tx_queue_empty
= ipr_tx_queue_empty
;
1020 ipr_drvr_linktab
[unit
].bch_activity
= ipr_activity
;
1021 ipr_drvr_linktab
[unit
].line_connected
= ipr_connect
;
1022 ipr_drvr_linktab
[unit
].line_disconnected
= ipr_disconnect
;
1023 ipr_drvr_linktab
[unit
].dial_response
= ipr_dialresponse
;
1024 ipr_drvr_linktab
[unit
].updown_ind
= ipr_updown
;
1027 /*===========================================================================*/
1029 #endif /* NI4BIPR > 0 */