📄 if_ppp.c
字号:
/* * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. * * Copyright (c) 1989 Carnegie Mellon University. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by Carnegie Mellon University. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Drew D. Perkins * Carnegie Mellon University * 4910 Forbes Ave. * Pittsburgh, PA 15213 * (412) 268-8576 * ddp@andrew.cmu.edu * * Based on: * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 * * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Serial Line interface * * Rick Adams * Center for Seismic Studies * 1300 N 17th Street, Suite 1450 * Arlington, Virginia 22209 * (703)276-7900 * rick@seismo.ARPA * seismo!rick * * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). * Converted to 4.3BSD Beta by Chris Torek. * Other changes made at Berkeley, based in part on code by Kirk Smith. * * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) * Added VJ tcp header compression; more unified ioctls * * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). * Cleaned up a lot of the mbuf-related code to fix bugs that * caused system crashes and packet corruption. Changed pppstart * so that it doesn't just give up with a collision if the whole * packet doesn't fit in the output ring buffer. * * Added priority queueing for interactive IP packets, following * the model of if_sl.c, plus hooks for bpf. * Paul Mackerras (paulus@cs.anu.edu.au). *//* $Id: if_ppp.c,v 1.5.2.1 2004/01/30 14:43:05 joel Exp $ *//* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp *//* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */#include "ppp.h"#if NPPP > 0#include <termios.h>#include <rtems/termiostypes.h>#include <rtems/rtems_bsdnet.h>#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/kernel.h>#include <sys/time.h>#include <sys/malloc.h>#include <net/if.h>#include <net/if_types.h>#include <net/netisr.h>#include <net/route.h>#ifdef PPP_FILTER#include <net/bpf.h>#endif#if INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#endif#include "bpfilter.h"#if NBPFILTER > 0#include <net/bpf.h>#endif#ifdef VJC#include <net/pppcompress.h>#endif#include <net/ppp_defs.h>#include <net/if_ppp.h>#include <net/if_pppvar.h>#include <machine/cpu.h>#define splsoftnet splnet#ifdef PPP_COMPRESS#define PACKETPTR struct mbuf *#include <net/ppp-comp.h>#endifstatic int pppsioctl __P((struct ifnet *, int, caddr_t));static void ppp_requeue __P((struct ppp_softc *));#ifdef PPP_COMPRESSstatic void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));static void ppp_ccp_closed __P((struct ppp_softc *));#endifstatic struct mbuf *ppp_inproc __P((struct ppp_softc *, struct mbuf *));static void pppdumpm __P((struct mbuf *m0));/* * Some useful mbuf macros not in mbuf.h. */#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)#define M_DATASTART(m) \ (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)#define M_DATASIZE(m) \ (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)/* * We steal two bits in the mbuf m_flags, to mark high-priority packets * for output, and received packets following lost/corrupted packets. */#define M_HIGHPRI 0x2000 /* output packet for sc_fastq */#define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */#ifdef PPP_COMPRESS/* * List of compressors we know about. * We leave some space so maybe we can modload compressors. */extern struct compressor ppp_bsd_compress;extern struct compressor ppp_deflate, ppp_deflate_draft;struct compressor *ppp_compressors[8] = {#if DO_BSD_COMPRESS &ppp_bsd_compress,#endif#if DO_DEFLATE &ppp_deflate, &ppp_deflate_draft,#endif NULL};#endif /* PPP_COMPRESS */extern struct ifqueue ipintrq;static struct timeval ppp_time;#ifndef __rtems__TEXT_SET(pseudo_set, ppp_rxdaemon);#endifstatic rtems_task ppp_rxdaemon(rtems_task_argument arg){ rtems_event_set events; rtems_interrupt_level level; struct ppp_softc *sc = (struct ppp_softc *)arg; struct mbuf *mp = (struct mbuf *)0; struct mbuf *m; /* enter processing loop */ while ( 1 ) { /* wait for event */ rtems_event_receive(RX_PACKET|RX_MBUF|RX_EMPTY,RTEMS_WAIT|RTEMS_EVENT_ANY,RTEMS_NO_TIMEOUT,&events); if ( events & RX_EMPTY ) { printf("RX: QUEUE is EMPTY\n"); events &= ~RX_EMPTY; } if ( events ) { /* get the network semaphore */ rtems_bsdnet_semaphore_obtain(); /* check to see if new packet was received */ if ( events & RX_PACKET ) { /* get received packet mbuf chain */ rtems_interrupt_disable(level); IF_DEQUEUE(&sc->sc_rawq, m); rtems_interrupt_enable(level); /* ensure packet was retrieved */ if ( m != (struct mbuf *)0 ) { /* process the received packet */ mp = ppp_inproc(sc, m); } } /* allocate a new mbuf to replace one */ if ( mp == NULL ) { pppallocmbuf(sc, &mp); } /* place mbuf on freeq */ rtems_interrupt_disable(level); IF_ENQUEUE(&sc->sc_freeq, mp); rtems_interrupt_enable(level); mp = (struct mbuf *)0; /* release the network semaphore */ rtems_bsdnet_semaphore_release(); /* check to see if queue is empty */ if ( sc->sc_rawq.ifq_head ) { /* queue is not empty - post another event */ rtems_event_send(sc->sc_rxtask, RX_PACKET); } } }}static rtems_task ppp_txdaemon(rtems_task_argument arg){ rtems_event_set events; int iprocess = (int )0; struct ppp_softc *sc = (struct ppp_softc *)arg; struct mbuf *mp; struct mbuf *mf; struct mbuf *m; struct rtems_termios_tty *tp; int frag; /* enter processing loop */ while ( 1 ) { /* wait for event */ rtems_event_receive(TX_PACKET|TX_TRANSMIT,RTEMS_WAIT|RTEMS_EVENT_ANY,RTEMS_NO_TIMEOUT,&events); if ( events & TX_TRANSMIT ) { /* received event from interrupt handler - free current mbuf */ rtems_bsdnet_semaphore_obtain(); m_freem(sc->sc_outm); rtems_bsdnet_semaphore_release(); /* chain is done - clear the values */ sc->sc_outm = (struct mbuf *)0; sc->sc_outmc = (struct mbuf *)0; /* now set flag to fake receive of TX_PACKET event */ /* this will check to see if we have any pending packets */ events |= TX_PACKET;
} /* received event from pppasyncstart */ if ( events & TX_PACKET ) { /* ensure we are not busy */ if ( sc->sc_outm == (struct mbuf *)0 ) { /* try dequeuing a packet */ sc->sc_outm = ppp_dequeue(sc); if ( sc->sc_outm == NULL ) { /* clear output flags */ sc->sc_outflag = 0; sc->sc_if.if_flags &= ~IFF_OACTIVE; } else { /* set flag to start process */ iprocess = 1; sc->sc_outflag = SC_TX_BUSY; sc->sc_if.if_flags |= IFF_OACTIVE; } } } /* check to see if there is any processing required */ if ( iprocess ) { /* clear process flag */ iprocess = (int)0; frag=0; /* initialize output values */ sc->sc_outfcs = PPP_INITFCS; sc->sc_outbuf = (u_char *)0; sc->sc_outlen = (short )0; sc->sc_outoff = (short )0; sc->sc_outfcslen = (short )0;
/* printf("Start Transmit Packet..\n"); */ /* loop over all mbufs in chain */ mf = NULL; mp = NULL; m = sc->sc_outm; sc->sc_outmc = m; sc->sc_outlen = m->m_len; sc->sc_outbuf = mtod(m, u_char *); while (( m != (struct mbuf *)0 ) && ( m->m_len > 0 )) { frag++; /* update the FCS value and then check next packet length */ if(m->m_len){ sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len); }
if(( m->m_next != NULL ) && ( m->m_next->m_len == 0 )) {
if(mf){
printf(" if_ppp.c : MBUF Error !!!!\n");
}
else{
mf = m->m_next; m->m_next = NULL;
} }
#ifdef LALL_X /* check next packet to see if it is empty */ while (( m->m_next != NULL ) && ( m->m_next->m_len == 0 )) { /* next mbuf is zero length */ /* add empty mbuf to free chain */ if ( mp == NULL ) { /* item is head of free list */ mf = m->m_next; mp = mf; } else { /* add item to end of the free list */ mp->m_next = m->m_next; mp = m->m_next; } /* remove empty item from process chain */ m->m_next = m->m_next->m_next; mp->m_next = NULL; }#endif /* move to next packet */ m = m->m_next; } /* ensure there is data to be sent out */ tp = (struct rtems_termios_tty *)sc->sc_devp; if (( tp != NULL ) && ( sc->sc_outmc != (struct mbuf *)0 )) { /* place FCS value into buffer */ sc->sc_outfcsbuf[sc->sc_outfcslen++] = ~sc->sc_outfcs & 0xff; sc->sc_outfcsbuf[sc->sc_outfcslen++] = (~sc->sc_outfcs >> 8) & 0xff; microtime(&sc->sc_if.if_lastchange); /* write out frame byte to start the transmission */ sc->sc_outchar = (u_char)PPP_FLAG; (*tp->device.write)(tp->minor, &sc->sc_outchar, 1); } /* check to see if we need to free some empty mbufs */ if ( mf != (struct mbuf *)0 ) { /* free empty mbufs */ rtems_bsdnet_semaphore_obtain(); m_freem(mf); rtems_bsdnet_semaphore_release(); }
} }}static void ppp_init(struct ppp_softc *sc){ rtems_status_code status; rtems_unsigned32 priority = 100; /* determine priority value */ if ( rtems_bsdnet_config.network_task_priority ) { priority = rtems_bsdnet_config.network_task_priority; } /* check to see if we need to start up daemons */ if ( sc->sc_rxtask == 0 ) { /* start rx daemon task */ status = rtems_task_create(rtems_build_name('R','x','P','0'+sc->sc_if.if_unit), priority, 2048, RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, &sc->sc_rxtask); if (status != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred(status); } else { status = rtems_task_start(sc->sc_rxtask, ppp_rxdaemon, (rtems_task_argument)sc); if (status != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred(status); } } /* start tx daemon task */ status = rtems_task_create(rtems_build_name('T','x','P','0'+sc->sc_if.if_unit), priority, 2048, RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, &sc->sc_txtask); if (status != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred(status); } else { status = rtems_task_start(sc->sc_txtask, ppp_txdaemon, (rtems_task_argument)sc); if (status != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred(status); } } } /* mark driver running and output inactive */ /* ilya: IFF_RUNNING flag will be marked after the IPCP goes up *//* sc->sc_if.if_flags |= IFF_RUNNING; */}/* * Called from boot code to establish ppp interfaces. */int rtems_ppp_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching){/* int i = (int)0; */ struct ppp_softc *sc; char *name; int number; number = rtems_bsdnet_parse_driver_name (config, &name); if (!attaching || (number >= NPPP)) return 0; sc = &ppp_softc[number]; if (sc->sc_if.if_name != NULL) return 0; /* interface is already attached */ /* for (sc = ppp_softc; i < NPPP; sc++) { */ sc->sc_if.if_name = name /*"ppp"*/; sc->sc_if.if_unit = number /*i++*/; sc->sc_if.if_mtu = PPP_MTU; sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; sc->sc_if.if_type = IFT_PPP; sc->sc_if.if_hdrlen = PPP_HDRLEN; sc->sc_if.if_ioctl = pppsioctl; sc->sc_if.if_output = pppoutput; sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; sc->sc_freeq.ifq_maxlen = NUM_MBUFQ; /* initialize and attach */ ppp_init(sc); if_attach(&sc->sc_if);#if NBPFILTER > 0 bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);#endif/* } */ return ( 1 );}/* * Allocate a ppp interface unit and initialize it. */struct ppp_softc *pppalloc(pid) pid_t pid;{ int nppp, i; struct ppp_softc *sc; for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) if (sc->sc_xfer == pid) { sc->sc_xfer = 0; return sc; } for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) if (sc->sc_devp == NULL) break; if (nppp >= NPPP) return NULL; sc->sc_flags = 0; sc->sc_mru = PPP_MRU; sc->sc_relinq = NULL; bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));#ifdef VJC MALLOC(sc->sc_comp, struct vjcompress *, sizeof(struct vjcompress), M_DEVBUF, M_NOWAIT); if (sc->sc_comp) vj_compress_init(sc->sc_comp, -1);#endif#ifdef PPP_COMPRESS sc->sc_xc_state = NULL; sc->sc_rc_state = NULL;#endif /* PPP_COMPRESS */ for (i = 0; i < NUM_NP; ++i) sc->sc_npmode[i] = NPMODE_ERROR; sc->sc_npqueue = NULL; sc->sc_npqtail = &sc->sc_npqueue; microtime(&ppp_time); sc->sc_last_sent = sc->sc_last_recv = ppp_time.tv_sec; return sc;}/* * Deallocate a ppp unit. Must be called at splsoftnet or higher. */voidpppdealloc(sc) struct ppp_softc *sc;{ struct mbuf *m; rtems_interrupt_level level; if_down(&sc->sc_if); sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); sc->sc_devp = NULL; sc->sc_xfer = 0; rtems_interrupt_disable(level); if ( sc->sc_m != NULL ) { m_freem(sc->sc_m); sc->sc_m = (struct mbuf *)0; } if ( sc->sc_outm != NULL ) { m_freem(sc->sc_outm); sc->sc_outm = (struct mbuf *)0; sc->sc_outmc = (struct mbuf *)0; sc->sc_outflag = 0; } do { IF_DEQUEUE(&sc->sc_freeq, m); if (m != NULL) { m_freem(m); } } while ( m != NULL ); do { IF_DEQUEUE(&sc->sc_rawq, m); if (m != NULL) { m_freem(m); } } while ( m != NULL ); rtems_interrupt_enable(level); for (;;) { IF_DEQUEUE(&sc->sc_inq, m); if (m == NULL) break; m_freem(m); } for (;;) { IF_DEQUEUE(&sc->sc_fastq, m); if (m == NULL) break; m_freem(m); } while ((m = sc->sc_npqueue) != NULL) { sc->sc_npqueue = m->m_nextpkt; m_freem(m); }#ifdef PPP_COMPRESS ppp_ccp_closed(sc); sc->sc_xc_state = NULL; sc->sc_rc_state = NULL;#endif /* PPP_COMPRESS */#ifdef PPP_FILTER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -