📄 if_sl.c
字号:
#ifndef lintstatic char *sccsid = "@(#)if_sl.c 4.3 (ULTRIX) 2/1/91";#endif lint/* * Copyright (c) 1989 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. * * Based on - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: * - Initial distribution. * * As modified for Ultrix V4.0 by - * Tim Theisen Department of Computer Sciences * tim@cs.wisc.edu University of Wisconsin-Madison * uwvax!tim 1210 West Dayton Street * (608)262-0438 Madison, WI 53706 * * And finally the NSL version is by - * Michael Reilly Network Systems Lab * reilly@nsl.dec.com Digital Equipment corporation * 505 Hamilton Avenue * Palo Alto, CA 94301 * * For Ultrix V3.1 or V4.0 on a mips based DECstation * *//* * NOTE: You must define either ULTRIX_3 for an Ultrix V3.1 driver or * ULTRIX_4 for an Ultrix V4.0 driver *//* * Serial Line interface * * Originally written by * Rick Adams * Center for Seismic Studies * 1300 N 17th Street, Suite 1450 * Arlington, Virginia 22209 * (703)276-7900 * rick@seismo.css.gov * seismo!rick * * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). * N.B.: this belongs in netinet, not net, the way it stands now. * Should have a link-layer type designation, but wouldn't be * backwards-compatible. * * Converted to 4.3BSD Beta by Chris Torek. * Other changes made at Berkeley, based in part on code by Kirk Smith. * * Hacked almost beyond recognition by Van Jacobson (van@helios.ee.lbl.gov). * Added priority queuing for "interactive" traffic; hooks for TCP * header compression; ICMP filtering (at 2400 baud, some cretin * pinging you can use up all your bandwidth); conditionals for Sun * OS 3.x in addition to 4.x BSD. Made low clist behavior more robust * and slightly less likely to hang serial line. Sped up a bunch of * things. *//* originally from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp *//* And from if_sl.c,v 1.12 90/08/20 14:24:28 tim Exp */#define ULTRIX_4#ifdef ultrix#if !defined(ULTRIX_3) && !defined(ULTRIX_4)#include "Either option ULTRIX_3 or ULTRIX_4 must be defined"#endif#endif#include "sl.h"#if NSL > 0#if defined(ultrix) && defined(ULTRIX_3)#include "../data/if_sl_data.c"#endif#if defined(ultrix) && defined(ULTRIX_4)#include "../../data/if_sl_data.c"#endif#ifdef ultrix#if defined(ULTRIX_3) && defined(ULTRIX_4)#include "Error - both ULTRIX_3 and ULTRIX_4 are defined"#endif#endif/* * The following are patchable defaults for the three options * in the interface flags word. If desired, they should be set * by config file options SL_DOCOMPRESS, SL_ALLOWCOMPRESS and * SL_NOICMP. * * sl_docompress If = 1, compression for a line will default to "on" * * sl_allowcompres If = 1, compression for a line will default to "off" * but will be turned on if a compressed packet is * received. * * sl_noicmp If = 1, outbound ICMP packets will be discarded. * XXX - shouldn't have to set this but some cretin * pinging us can drive our throughput to zero (not * to mention the raft of quenches we'll get if we're * unlucky enough to have to traverse the milnet. */#ifndef SL_DOCOMPRESS#define SL_DOCOMPRESS 0#endif#ifndef SL_ALLOWCOMPRESS#define SL_ALLOWCOMPRESS 0#endif#ifndef SL_NOICMP#define SL_NOICMP 0#endifint sl_docompress = SL_DOCOMPRESS;int sl_allowcompress = SL_ALLOWCOMPRESS;int sl_noicmp = SL_NOICMP;/* Compatibility with 4.2 BSD (and variants) */#ifndef MCLBYTES#ifdef ultrix#define MCLBYTES M_CLUSTERSZ#else#define MCLBYTES CLBYTES#endif#endif/* * SLMAX is a hard limit on input packet size. To simplify the code * and improve performance, we require that packets fit in an mbuf * cluster, that there be enough extra room for the ifnet pointer that * IP input requires and, if we get a compressed packet, there's * enough extra room to expand the header into a max length tcp/ip * header (128 bytes). So, SLMAX can be at most * MCLBYTES - sizeof(struct ifnet *) - 128 * * SLMTU is a hard limit on output packet size. To insure good * interactive response, SLMTU wants to be the smallest size that * amortizes the header cost. (Remember that even with * type-of-service queuing, we have to wait for any in-progress * packet to finish. I.e., we wait, on the average, 1/2 * mtu / * cps, where cps is the line speed in characters per second. * E.g., 533ms wait for a 1024 byte MTU on a 9600 baud line. The * average compressed header size is 6-8 bytes so any MTU > 90 * bytes will give us 90% of the line bandwidth. A 100ms wait is * tolerable (500ms is not), so want an MTU around 296. (Since TCP * will send 256 byte segments (to allow for 40 byte headers), the * typical packet size on the wire will be around 260 bytes). In * 4.3tahoe+ systems, we can set an MTU in a route so we do that & * leave the interface MTU relatively high (so we don't IP fragment * when acting as a gateway to someone using a stupid MTU). * * Similar considerations apply to SLIP_HIWAT: It's the amount of * data that will be queued 'downstream' of us (i.e., in clists * waiting to be picked up by the tty output interrupt). If we * queue a lot of data downstream, it's immune to our t.o.s. queuing. * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed * telnet/ftp will see a 1 sec wait, independent of the mtu (the * wait is dependent on the ftp window size but that's typically * 1k - 4k). So, we want SLIP_HIWAT just big enough to amortize * the cost (in idle time on the wire) of the tty driver running * off the end of its clists & having to call back slstart for a * new packet. For a tty interface with any buffering at all, this * cost will be zero. Even with a totally brain dead interface (like * the one on a typical workstation), the cost will be <= 1 character * time. So, setting SLIP_HIWAT to ~100 guarantees that we'll lose * at most 1% while maintaining good interactive response. */#define BUFOFFSET (128+sizeof(struct ifnet **))#define SLMAX (MCLBYTES - BUFOFFSET)#define SLMTU 296#define SLIP_HIWAT roundup(50,CBSIZE)#define CLISTRESERVE 1024 /* Can't let clists get too low *//* * The following disgusting hack gets around the problem that IP TOS * can't be set in BSD/Sun OS yet. We want to put "interactive" * traffic on a high priority queue. To decide if traffic is * interactive, we check that a) it is TCP and b) one of it's ports * if telnet, rlogin or ftp control. */static u_short interactive_ports[8] = { 0, 513, 0, 0, 0, 21, 0, 23,};#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))#define FRAME_END 0xc0 /* Frame End */#define FRAME_ESCAPE 0xdb /* Frame Esc */#define TRANS_FRAME_END 0xdc /* transposed frame end */#define TRANS_FRAME_ESCAPE 0xdd /* transposed frame esc */#ifdef sun#define t_sc t_linep#else#define t_sc T_LINEP#endif#if defined(SL_NIT) && defined(NIT)#include "../h/time.h"#include "../net/nit.h"#include "../netinet/if_ether.h"extern struct nit_cb nitcb;int sl_donit = 0;#endif/* Sun OS3.x doesn't have an MCLGET or MCLFREE. Sun OS4.x doesn't * have an MCLFREE. The code below should work on either Sun OS * (this driver, however will *NOT* work on a stock Sun OS4 system * because of the slow, broken, worthless, System-V "streams" tty * driver). * * All BSD systems since 4.1c have both MCLGET and MCLFREE. * However 4.2bsd had a second, unused parameter to MCLGET. Some * versions of cpp may complain if you compile this routine under * a stock 4.2bsd. For reasons I have never understood, various * vendors chose to break BSD in mysterious ways (e.g., DEC's Ultrix * changed the definition of m_off to make mbuf cluster use * a factor of two more costly -- no doubt this was done to encourage * the sale of faster processors since there is no technical * justification whatsoever for the change). If you are stuck with * one of these abortions and, for reasons best known to yourself, * don't want to upgrade to the BSD network code freely available via * anonymous ftp from ucbarpa.berkeley.edu, the following macros * might give you a prototype to work from. Then again, they might * not. Good luck. */#ifdef sun#ifndef MCLGET#define MCLGET(m) { int ms = splimp(); (void)mclget(m); (void) splx(ms); }#endif#ifndef MCLFREE#define MCLFREE(p) { \ extern char *mclrefcnt; \ struct mbuf mxxx; \ mxxx.m_len = MCLBYTES; \ mxxx.m_off = (int)p - (int)xm; \ mxxx.m_cltype = 1; \ mclput(&mxxx); \ }#endif#endif#ifdef ultrix/* Ultrix 3.x on Vaxen misdefines the MCLGET macro to cause the m_len field * to be set to half of the amount actually allocated. Thus this re- * definition is necessary. */#if defined(vax) && defined(ULTRIX_3)#undef MCLGET#define MCLGET(m, p) \ KM_ALLOC((p), struct mbuf *, M_CLUSTERSZ, KM_CLUSTER, KM_NOWAIT); \ if((p)) { \ (m)->m_cltype = M_CLTYPE1; (m)->m_clptr = (caddr_t) p; \ m->m_off = (int)(p); m->m_len = M_CLUSTERSZ; \ mbstat.m_clfree++; mbstat.m_clusters++; \ }#endif defined(vax) && defined(ULTRIX_3)#ifndef MCLFREE#define MCLFREE(p) { \ KM_FREE((p), KM_CLUSTER); \ mbstat.m_clusters--; mbstat.m_clfree--; \ }#endif#endifint sloutput(), slioctl();/* * Called from boot code to establish sl interfaces. */slattach(){ register struct sl_softc *sc; register int i = 0;#if defined(ultrix) && defined(ULTRIX_4) int s;#endif if (sl_softc[0].sc_if.if_name == NULL) { for (sc = sl_softc; i < nNSL; sc++) { sc->sc_if.if_name = "sl"; sc->sc_if.if_unit = i++; sc->sc_if.if_mtu = SLMTU; sc->sc_if.if_flags = IFF_POINTOPOINT; sc->sc_if.if_ioctl = slioctl; sc->sc_if.if_output = sloutput; sc->sc_if.if_snd.ifq_maxlen = 50; sc->sc_fastq.ifq_maxlen = 32;#if defined(ultrix) && defined(ULTRIX_4) s = splnet(); /* SMP */ if_attach(&sc->sc_if); splx(s);#else if_attach(&sc->sc_if);#endif } }}static intslinit(sc) register struct sl_softc *sc;{ if (sc->sc_ep == (u_char *) 0) { struct mbuf m;#ifdef ultrix struct mbuf *p; MCLGET((&m),p);#else MCLGET((&m));#endif if (m.m_len == MCLBYTES) sc->sc_ep = mtod(&m,u_char *) + (BUFOFFSET + SLMAX); else { printf("sl%d: can't allocate buffer\n", sc - sl_softc); sc->sc_if.if_flags &= ~IFF_UP; return (0); } } sc->sc_buf = sc->sc_ep - SLMAX; sc->sc_mp = sc->sc_buf; if (sl_docompress) sc->sc_if.if_flags |= IFF_D1; else sc->sc_if.if_flags &=~ IFF_D1; if (sl_allowcompress) sc->sc_if.if_flags |= IFF_D2; else sc->sc_if.if_flags &=~ IFF_D2; if (sl_noicmp) sc->sc_if.if_flags |= IFF_D3; else sc->sc_if.if_flags &=~ IFF_D3; sl_compress_init(&sc->sc_comp); return (1);}/* * Line specific open routine. * Attach the given tty to the first available sl unit. *//* ARGSUSED */slopen(dev, tp) dev_t dev; register struct tty *tp;{ register struct sl_softc *sc; register int nsl; if (!suser()) return (EPERM);#ifdef ultrix slattach();#define SLIPDISC SLPDISC#endif if (tp->t_line == SLIPDISC) return (EBUSY); for (nsl = nNSL, sc = sl_softc; --nsl >= 0; sc++) if (sc->sc_ttyp == NULL) { if (slinit(sc) == 0) return (ENOBUFS); tp->t_sc = (caddr_t)sc; sc->sc_ttyp = tp; ttyflush(tp, FREAD | FWRITE); return (0); } return (ENXIO);}#ifdef sun/* XXX - Sun OS3 is missing these 4bsd routines. * * Mark an interface down and notify protocols of * the transition. */static voidif_down(ifp) register struct ifnet *ifp;{ register struct ifqueue *ifq = &ifp->if_snd; register struct mbuf *m, *n; ifp->if_flags &=~ IFF_UP; pfctlinput(PRC_IFDOWN, &ifp->if_addr); /* Flush the interface queue. */ n = ifq->ifq_head; while (m = n) { n = m->m_act; m_freem(m); } ifq->ifq_head = 0; ifq->ifq_tail = 0; ifq->ifq_len = 0;}static voidif_rtdelete(ifp) register struct ifnet *ifp;{ static struct rtentry route; if (ifp->if_flags & IFF_ROUTE) { route.rt_dst = ifp->if_dstaddr; route.rt_gateway = ifp->if_addr; route.rt_flags = RTF_HOST|RTF_UP; (void) rtrequest(SIOCDELRT, &route); ifp->if_flags &=~ IFF_ROUTE; }}#endif/* * Line specific close routine. * Detach the tty from the sl unit. * Mimics part of ttyclose(). */slclose(tp) struct tty *tp;{ register struct sl_softc *sc; int s; ttywflush(tp); tp->t_line = 0; s = splimp(); sc = (struct sl_softc *)tp->t_sc; if (sc != NULL) {#ifdef sun if_rtdelete(&sc->sc_if);#endif if_down(&sc->sc_if); rtpurge(&sc->sc_if); in_reminterface(&sc->sc_if); sc->sc_if.if_addrlist = NULL; sc->sc_ttyp = NULL; tp->t_sc = NULL; MCLFREE((struct mbuf *)(sc->sc_ep - (SLMAX + BUFOFFSET))); sc->sc_ep = 0; sc->sc_mp = 0; sc->sc_buf = 0; } splx(s);}/* * Line specific (tty) ioctl routine. * Provide a way to get the sl unit number. *//* ARGSUSED */sltioctl(tp, cmd, data, flag) struct tty *tp; caddr_t data;{ if (cmd == TIOCGETD) { *(int *)data = ((struct sl_softc *)tp->t_sc)->sc_if.if_unit; return (0); } return (EINVAL);}/* * Queue a packet. Start transmission if not active. */sloutput(ifp, m, dst) register struct ifnet *ifp; register struct mbuf *m; struct sockaddr *dst;{ register struct sl_softc *sc; register struct ip *ip; register struct ifqueue *ifq; int s; /* * `Cannot happen' (see slioctl). Someday we will extend * the line protocol to support other address families. */ if (dst->sa_family != AF_INET) { printf("sl%d: af%d not supported\n", ifp->if_unit, dst->sa_family); m_freem(m); return (EAFNOSUPPORT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -