Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add an in-kernel PPPoE (ppp over ethernet, RFC 2516) imp...



details:   https://anonhg.NetBSD.org/src/rev/1e7d56bf0325
branches:  trunk
changeset: 509198:1e7d56bf0325
user:      martin <martin%NetBSD.org@localhost>
date:      Sun Apr 29 09:50:36 2001 +0000

description:
Add an in-kernel PPPoE (ppp over ethernet, RFC 2516) implementation,
based on the existing net/if_spppsubr.c stuff.

While there are completely userland (bpf based) implementations available,
those have a vastly larger per packet overhead thus causing major CPU
overhead and higher latency. On an i386 base router, running a 486DX at 50MHz
my line (768kBit/s downstream) was limited to something (varying) between 10
and 20 kByte/s effective download rate. With this implementation I get full
bandwidth (~85kByte/s).

This is client side only. Arguably the right way to add full PPPoE support
(including server side) would be a variation of the ppp line discipline and
appropriate modifications to pppd. I promise every help I can give to anyone
doing that - but I needed this realy fast. Besids, on low memory NAT boxes
with typically a single PPPoE connection, this implementation is more
lightweight than a pppd based one, which nicely fits my needs.

diffstat:

 sys/conf/files         |    6 +-
 sys/net/Makefile       |    4 +-
 sys/net/dlt.h          |    4 +-
 sys/net/if_ethersubr.c |   30 +-
 sys/net/if_pppoe.c     |  965 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/net/if_pppoe.h     |   54 ++
 6 files changed, 1056 insertions(+), 7 deletions(-)

diffs (truncated from 1161 to 300 lines):

diff -r 0342763e4fec -r 1e7d56bf0325 sys/conf/files
--- a/sys/conf/files    Sun Apr 29 08:37:04 2001 +0000
+++ b/sys/conf/files    Sun Apr 29 09:50:36 2001 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files,v 1.434 2001/04/20 16:39:22 fredette Exp $
+#      $NetBSD: files,v 1.435 2001/04/29 09:50:36 martin Exp $
 
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
 
@@ -633,6 +633,7 @@
 defpseudo loop: ifnet
 defpseudo sl: ifnet
 defpseudo ppp: ifnet, bpf_filter
+defpseudo pppoe: ifnet, ether, sppp
 defpseudo sppp: ifnet
 defpseudo tun: ifnet
 defpseudo vlan: ifnet, ether
@@ -923,7 +924,7 @@
 file   net/if_bridge.c                 bridge                  needs-flag
 file   net/bridgestp.c                 bridge
 file   net/if_ethersubr.c              ether | fddi | netatalk | token |
-                                           wlan | vlan
+                                           wlan | vlan | pppoe
 file   net/if_faith.c                  faith                   needs-flag
 file   net/if_fddisubr.c               fddi                    needs-flag
 file   net/if_gif.c                    gif                     needs-flag
@@ -940,6 +941,7 @@
 file   net/if_tokensubr.c              token                   needs-flag
 file   net/if_tun.c                    tun                     needs-count
 file   net/if_vlan.c                   vlan                    needs-flag
+file   net/if_pppoe.c                  pppoe                   needs-count
 #file net/net_osdep.c
 file   net/pfil.c                      pfil_hooks | ipfilter
 file   net/ppp-deflate.c               ppp & ppp_deflate
diff -r 0342763e4fec -r 1e7d56bf0325 sys/net/Makefile
--- a/sys/net/Makefile  Sun Apr 29 08:37:04 2001 +0000
+++ b/sys/net/Makefile  Sun Apr 29 09:50:36 2001 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.9 2000/12/12 17:53:00 thorpej Exp $
+#      $NetBSD: Makefile,v 1.10 2001/04/29 09:50:36 martin Exp $
 
 KDIR=  /sys/net
 INCSDIR= /usr/include/net
@@ -6,7 +6,7 @@
 INCS=  bpf.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \
        if_atm.h if_dl.h if_ether.h if_fddi.h if_gif.h \
        if_gre.h if_hippi.h if_ieee80211.h if_llc.h if_media.h \
-       if_ppp.h if_pppvar.h if_slvar.h if_sppp.h if_stf.h \
+       if_ppp.h if_pppvar.h if_pppoe.h if_slvar.h if_sppp.h if_stf.h \
        if_stripvar.h if_token.h if_tun.h if_types.h if_vlanvar.h \
        netisr.h pfil.h pfkeyv2.h ppp-comp.h ppp_defs.h radix.h \
        raw_cb.h route.h slcompress.h slip.h zlib.h
diff -r 0342763e4fec -r 1e7d56bf0325 sys/net/dlt.h
--- a/sys/net/dlt.h     Sun Apr 29 08:37:04 2001 +0000
+++ b/sys/net/dlt.h     Sun Apr 29 09:50:36 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dlt.h,v 1.1 2000/12/12 17:53:00 thorpej Exp $  */
+/*     $NetBSD: dlt.h,v 1.2 2001/04/29 09:50:37 martin Exp $   */
 
 /*
  * Copyright (c) 1990, 1991, 1993
@@ -67,7 +67,7 @@
 
 /* NetBSD-specific types */
 #define        DLT_PPP_SERIAL  50      /* PPP over serial (async and sync) */
-#define        DLT_PPP_ETHER   51      /* PPP over Ethernet */
+#define        DLT_PPP_ETHER   51      /* XXX - depreceated! PPP over Ethernet; session only, w/o ether header */
 
 /*
  * NetBSD-specific generic "raw" link type.  The upper 16-bits indicate
diff -r 0342763e4fec -r 1e7d56bf0325 sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c    Sun Apr 29 08:37:04 2001 +0000
+++ b/sys/net/if_ethersubr.c    Sun Apr 29 09:50:36 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ethersubr.c,v 1.80 2001/04/27 00:14:02 marcus Exp $ */
+/*     $NetBSD: if_ethersubr.c,v 1.81 2001/04/29 09:50:37 martin Exp $ */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -73,12 +73,14 @@
 #include "opt_gateway.h"
 #include "opt_pfil_hooks.h"
 #include "vlan.h"
+#include "pppoe.h"
 #include "bridge.h"
 #include "bpfilter.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/callout.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/protosw.h>
@@ -105,6 +107,10 @@
 #include <net/if_vlanvar.h>
 #endif
 
+#if NPPPOE > 0
+#include <net/if_pppoe.h>
+#endif
+
 #if NBRIDGE > 0
 #include <net/if_bridgevar.h>
 #endif
@@ -748,6 +754,28 @@
                        m_freem(m);
                return;
 #endif /* NVLAN > 0 */
+#if NPPPOE > 0
+       case ETHERTYPE_PPPOEDISC:
+       case ETHERTYPE_PPPOE:
+               if (etype == ETHERTYPE_PPPOEDISC) 
+                       inq = &ppoediscinq;
+               else
+                       inq = &ppoeinq;
+               s = splnet();
+               if (IF_QFULL(inq)) {
+                       IF_DROP(inq);
+                       m_freem(m);
+               } else
+                       IF_ENQUEUE(inq, m);
+               splx(s);
+#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
+               if (!callout_active(&pppoe_softintr))
+                       callout_reset(&pppoe_softintr, 1, pppoe_softintr_handler, NULL);
+#else
+               softintr_schedule(pppoe_softintr);
+#endif
+               return;
+#endif /* NPPPOE > 0 */
        default:
                ; /* Nothing. */
        }
diff -r 0342763e4fec -r 1e7d56bf0325 sys/net/if_pppoe.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/net/if_pppoe.c        Sun Apr 29 09:50:36 2001 +0000
@@ -0,0 +1,965 @@
+/* $NetBSD: if_pppoe.c,v 1.1 2001/04/29 09:50:37 martin Exp $ */
+
+/*
+ * Copyright (c) 2001 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "pppoe.h"
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_ether.h>
+#include <net/if_sppp.h>
+#include <net/if_pppoe.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#if NPPPOE > 0
+
+#undef PPPOE_DEBUG             /* XXX - remove this or make it an option */
+/* #define PPPOE_DEBUG 1 */
+
+#define PPPOE_HEADERLEN        6
+#define        PPPOE_VERTYPE   0x11    /* VER=1, TYPE = 1 */
+
+#define        PPPOE_TAG_EOL           0x0000          /* end of list */
+#define        PPPOE_TAG_SNAME         0x0101          /* service name */
+#define        PPPOE_TAG_ACNAME        0x0102          /* access concentrator name */
+#define        PPPOE_TAG_HUNIQUE       0x0103          /* host unique */
+#define        PPPOE_TAG_ACCOOKIE      0x0104          /* AC cookie */
+#define        PPPOE_TAG_VENDOR        0x0105          /* vendor specific */
+#define        PPPOE_TAG_RELAYSID      0x0110          /* relay session id */
+#define        PPPOE_TAG_SNAME_ERR     0x0201          /* service name error */
+#define        PPPOE_TAG_ACSYS_ERR     0x0202          /* AC system error */
+#define        PPPOE_TAG_GENERIC_ERR   0x0203          /* gerneric error */
+
+#define PPPOE_CODE_PADI                0x09            /* Active Discovery Initiation */
+#define        PPPOE_CODE_PADO         0x07            /* Active Discovery Offer */
+#define        PPPOE_CODE_PADR         0x19            /* Active Discovery Request */
+#define        PPPOE_CODE_PADS         0x65            /* Active Discovery Session confirmation */
+#define        PPPOE_CODE_PADT         0xA7            /* Active Discovery Terminate */
+
+/* Read a 16 bit unsigned value from a buffer */
+#define PPPOE_READ_16(PTR, VAL)                                \
+               (VAL) = ((PTR)[0] << 8) | (PTR)[1];     \
+               (PTR)+=2
+
+/* Add a 16 bit unsigned value to a buffer pointed to by PTR */
+#define        PPPOE_ADD_16(PTR, VAL)                  \
+               *(PTR)++ = (VAL) / 256;         \
+               *(PTR)++ = (VAL) % 256
+
+/* Add a complete PPPoE header to the buffer pointed to by PTR */
+#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \
+               *(PTR)++ = PPPOE_VERTYPE;       \
+               *(PTR)++ = (CODE);              \
+               PPPOE_ADD_16(PTR, SESS);        \
+               PPPOE_ADD_16(PTR, LEN)
+
+struct pppoe_softc {
+       struct sppp sc_sppp;            /* contains a struct ifnet as first element */
+       struct ifnet *sc_eth_if;        /* ethernet interface we are using */
+
+#define        PPPOE_DISC_TIMEOUT      hz/5
+#define PPPOE_DISC_MAXPADI     4       /* retry PADI four times */
+#define        PPPOE_DISC_MAXPADR      2       /* retry PADR twice */
+       
+#define PPPOE_STATE_INITIAL    0
+#define PPPOE_STATE_PADI_SENT  1
+#define        PPPOE_STATE_PADR_SENT   2
+#define        PPPOE_STATE_SESSION     3
+#define        PPPOE_STATE_CLOSING     4
+       int sc_state;                   /* discovery phase or session connected */
+       struct ether_addr sc_dest;      /* hardware address of concentrator */
+       u_int16_t sc_session;           /* PPPoE session id */
+
+       char *sc_service_name;          /* if != NULL: requested name of service */
+       char *sc_concentrator_name;     /* if != NULL: requested concentrator id */
+       u_int8_t *sc_ac_cookie;         /* content of AC cookie we must echo back */
+       size_t sc_ac_cookie_len;        /* length of cookie data */
+       struct callout sc_timeout;      /* timeout while not in session state */
+       int sc_padi_retried;            /* number of PADI retries already done */
+       int sc_padr_retried;            /* number of PADR retries already done */
+};
+
+/* incoming traffic will be queued here */
+struct ifqueue ppoediscinq = { NULL };
+struct ifqueue ppoeinq = { NULL };
+
+#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
+void * pppoe_softintr = NULL;
+static void pppoe_softintr_handler(void *);
+#else
+struct callout pppoe_softintr = CALLOUT_INITIALIZER;
+void pppoe_softintr_handler(void*);
+#endif
+
+extern int sppp_ioctl(struct ifnet *ifp, unsigned long cmd, void *data);
+
+/* input routines */
+static void pppoe_input(void);
+static void pppoe_disc_input(struct mbuf *m);
+static void pppoe_dispatch_disc_pkt(u_int8_t *p, size_t size, struct ifnet *rcvif, struct ether_header *eh);
+static void pppoe_data_input(struct mbuf *m);
+
+/* management routines */
+void pppoeattach(void);
+static int pppoe_connect(struct pppoe_softc *sc);
+static int pppoe_disconnect(struct pppoe_softc *sc);
+static void pppoe_abort_connect(struct pppoe_softc *sc);
+static int pppoe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data);
+static void pppoe_tls(struct sppp *sp);
+static void pppoe_tlf(struct sppp *sp);
+static void pppoe_start(struct ifnet *ifp);
+
+/* internal timeout handling */
+static void pppoe_timeout(void*);
+
+/* sending actual protocol controll packets */
+static int pppoe_send_padi(struct pppoe_softc *sc);
+static int pppoe_send_padr(struct pppoe_softc *sc);
+static int pppoe_send_padt(struct pppoe_softc *sc);
+
+/* raw output */
+static int pppoe_output(struct pppoe_softc *sc, struct mbuf *m);
+
+/* internal helper functions */
+static struct pppoe_softc * pppoe_find_softc_by_session(u_int session, struct ifnet *rcvif);
+static struct pppoe_softc * pppoe_find_softc_by_hunique(u_int8_t *token, size_t len, struct ifnet *rcvif);



Home | Main Index | Thread Index | Old Index