From f11e795a0f099a02f9ee2c2a08268ddf0bd6eb0e Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 5 Dec 2004 04:15:16 +0000 Subject: [PATCH] Make ppp a cloning device. Based on the work of Quentin Garnier. --- sys/net/if_ppp.c | 179 ++++++++++++++++++++++++++++++++------------ sys/net/if_pppvar.h | 4 +- 2 files changed, 132 insertions(+), 51 deletions(-) diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index 7378a39aff65..367da8c73875 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ppp.c,v 1.90 2004/07/03 18:11:33 dyoung Exp $ */ +/* $NetBSD: if_ppp.c,v 1.91 2004/12/05 04:15:16 christos Exp $ */ /* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */ /* @@ -102,7 +102,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.90 2004/07/03 18:11:33 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.91 2004/12/05 04:15:16 christos Exp $"); #include "ppp.h" @@ -202,7 +202,17 @@ void pppintr(void *); #define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */ #define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */ -struct ppp_softc ppp_softc[NPPP]; +static int ppp_clone_create(struct if_clone *, int); +static int ppp_clone_destroy(struct ifnet *); + +static struct ppp_softc *ppp_create(const char *, int); + +static LIST_HEAD(, ppp_softc) ppp_softc_list; + +struct if_clone ppp_cloner = + IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy); + +static struct simplelock ppp_list_mutex = SIMPLELOCK_INITIALIZER; #ifdef PPP_COMPRESS /* @@ -232,35 +242,104 @@ struct compressor *ppp_compressors[PPP_COMPRESSORS_MAX] = { void pppattach() { - struct ppp_softc *sc; - int i = 0; + LIST_INIT(&ppp_softc_list); + if_clone_attach(&ppp_cloner); +} - for (sc = ppp_softc; i < NPPP; sc++) { - sc->sc_unit = i; /* XXX */ - snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), "ppp%d", i++); - callout_init(&sc->sc_timo_ch); - sc->sc_if.if_softc = sc; - 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_dlt = DLT_NULL; - sc->sc_if.if_ioctl = pppsioctl; - sc->sc_if.if_output = pppoutput; -#ifdef ALTQ - sc->sc_if.if_start = ppp_ifstart; -#endif - IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN); - sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; - sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; - sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; - IFQ_SET_READY(&sc->sc_if.if_snd); - if_attach(&sc->sc_if); - if_alloc_sadl(&sc->sc_if); -#if NBPFILTER > 0 - bpfattach(&sc->sc_if, DLT_NULL, 0); +static struct ppp_softc * +ppp_create(const char *name, int unit) +{ + struct ppp_softc *sc, *sci, *scl = NULL; + + MALLOC(sc, struct ppp_softc *, sizeof(*sc), M_DEVBUF, M_WAIT|M_ZERO); + + simple_lock(&ppp_list_mutex); + if (unit == -1) { + int i = 0; + LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) { + scl = sci; + if (i < sci->sc_unit) { + unit = i; + break; + } else { +#ifdef DIAGNOSTIC + KASSERT(i == sci->sc_unit); #endif + i++; + } + } + if (unit == -1) + unit = i; + } else { + LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) { + scl = sci; + if (unit < sci->sc_unit) + break; + else if (unit == sci->sc_unit) { + FREE(sc, M_DEVBUF); + return NULL; + } + } } + + if (sci != NULL) + LIST_INSERT_BEFORE(sci, sc, sc_iflist); + else if (scl != NULL) + LIST_INSERT_AFTER(scl, sc, sc_iflist); + else + LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_iflist); + + simple_unlock(&ppp_list_mutex); + + (void)snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), "%s%d", + name, sc->sc_unit = unit); + callout_init(&sc->sc_timo_ch); + sc->sc_if.if_softc = sc; + 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_dlt = DLT_NULL; + sc->sc_if.if_ioctl = pppsioctl; + sc->sc_if.if_output = pppoutput; +#ifdef ALTQ + sc->sc_if.if_start = ppp_ifstart; +#endif + IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN); + sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; + sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; + sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; + IFQ_SET_READY(&sc->sc_if.if_snd); + if_attach(&sc->sc_if); + if_alloc_sadl(&sc->sc_if); +#if NBPFILTER > 0 + bpfattach(&sc->sc_if, DLT_NULL, 0); +#endif + return sc; +} + +static int +ppp_clone_create(struct if_clone *ifc, int unit) +{ + return ppp_create(ifc->ifc_name, unit) == NULL ? EEXIST : 0; +} + +static int +ppp_clone_destroy(struct ifnet *ifp) +{ + struct ppp_softc *sc = (struct ppp_softc *)ifp->if_softc; + + if (sc->sc_devp != NULL) + return EBUSY; /* Not removing it */ + + simple_lock(&ppp_list_mutex); + LIST_REMOVE(sc, sc_iflist); + simple_unlock(&ppp_list_mutex); + + if_detach(ifp); + + FREE(sc, M_DEVBUF); + return 0; } /* @@ -270,32 +349,36 @@ struct ppp_softc * pppalloc(pid) pid_t pid; { - int nppp, i; - struct ppp_softc *sc; + struct ppp_softc *sc = NULL, *scf; + int i; - for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) - if (sc->sc_xfer == pid) { - sc->sc_xfer = 0; - return sc; + simple_lock(&ppp_list_mutex); + for (scf = LIST_FIRST(&ppp_softc_list); scf != NULL; + scf = LIST_NEXT(scf, sc_iflist)) { + if (scf->sc_xfer == pid) { + scf->sc_xfer = 0; + simple_unlock(&ppp_list_mutex); + return scf; } - for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) - if (sc->sc_devp == NULL) - break; - if (nppp >= NPPP) - return NULL; + if (scf->sc_devp == NULL && sc == NULL) + sc = scf; + } + simple_lock(&ppp_list_mutex); + + if (sc == NULL) + sc = ppp_create(ppp_cloner.ifc_name, -1); #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS sc->sc_si = softintr_establish(IPL_SOFTNET, pppintr, sc); if (sc->sc_si == NULL) { - printf("ppp%d: unable to establish softintr\n", sc->sc_unit); + printf("%s: unable to establish softintr\n", sc->sc_if.if_xname); return (NULL); } #endif - sc->sc_flags = 0; sc->sc_mru = PPP_MRU; sc->sc_relinq = NULL; - memset((char *)&sc->sc_stats, 0, sizeof(sc->sc_stats)); + (void)memset(&sc->sc_stats, 0, sizeof(sc->sc_stats)); #ifdef VJC MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress), M_DEVBUF, M_NOWAIT); @@ -390,6 +473,7 @@ pppdealloc(sc) sc->sc_comp = 0; } #endif + (void)ppp_clone_destroy(&sc->sc_if); } /* @@ -410,7 +494,6 @@ pppioctl(sc, cmd, data, flag, p) struct npioctl *npi; time_t t; #ifdef PPP_FILTER -/*###413 [cc] warning: `bp' might be used uninitialized in this function%%%*/ struct bpf_program *bp, *nbp; struct bpf_insn *newcode, *oldcode; int newcodelen; @@ -425,7 +508,7 @@ pppioctl(sc, cmd, data, flag, p) break; case PPPIOCGUNIT: - *(int *)data = sc->sc_unit; /* XXX */ + *(int *)data = sc->sc_unit; break; case PPPIOCGFLAGS: @@ -1202,12 +1285,10 @@ void pppnetisr(void) { struct ppp_softc *sc; - int i; - for (i = 0; i < NPPP; i++) { - sc = &ppp_softc[i]; + for (sc = LIST_FIRST(&ppp_softc_list); scf != NULL; + sc = LIST_NEXT(sc, sc_iflist)) pppintr(sc); - } } #endif diff --git a/sys/net/if_pppvar.h b/sys/net/if_pppvar.h index 7bb238da7c34..0272ba70fc96 100644 --- a/sys/net/if_pppvar.h +++ b/sys/net/if_pppvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_pppvar.h,v 1.18 2003/09/01 16:51:27 christos Exp $ */ +/* $NetBSD: if_pppvar.h,v 1.19 2004/12/05 04:15:16 christos Exp $ */ /* Id: if_pppvar.h,v 1.3 1996/07/01 01:04:37 paulus Exp */ /* @@ -143,10 +143,10 @@ struct ppp_softc { u_int16_t sc_outfcs; /* FCS so far for output packet */ u_char sc_rawin_start; /* current char start */ struct ppp_rawin sc_rawin; /* chars as received */ + LIST_ENTRY(ppp_softc) sc_iflist; }; #ifdef _KERNEL -extern struct ppp_softc ppp_softc[]; struct ppp_softc *pppalloc __P((pid_t)); void pppdealloc __P((struct ppp_softc *));