On Wed, Aug 22, 2012 at 12:20:19AM -0300, Rafael Zalamena wrote:
> I've being working on a project that involves MPLS and OpenBSD, I
> recently started coding and I would really love to get some
> comments/advices about it.
> 
> This thread will contain code about the wire(4) pseudo device (RFC4448),
> it will be used in the future by ldpd(8) or ifconfig(8) to configure
> pseudowires (RFC4447). This device will allow us to develop VPLS support
> in LDPd later (RFC4762).
> 
> Since I'm quite new to this expect rough edges.
> 

Updated v1 patch:
* Cleaned up code - removed code at if_output() and if_start() that
didn't make sense.
* Setting and getting labels works (fixed setlabel)
* Moved wire_input() call to its propper place at ether_input()
* Creating wire and associating it with ethernet + mpe interface works -
needs custom program that calls the appropriated ioctl()


--- /dev/null   Mon Aug 27 00:22:40 2012
+++ net/if_mpe.h        Tue Aug 21 23:50:31 2012
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012 Rafael F. Zalamena <rzalam...@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct mpe_softc {
+       struct ifnet            sc_if;          /* the interface */
+       int                     sc_unit;
+       struct shim_hdr         sc_shim;
+       LIST_ENTRY(mpe_softc)   sc_list;
+};
+
+int             mpe_newlabel(struct ifnet *, int, struct shim_hdr *);
--- /dev/null   Mon Aug 27 00:30:25 2012
+++ net/if_wire.c       Mon Aug 27 00:29:49 2012
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2012 Rafael F. Zalamena <rzalam...@gmail.com>
+ * 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 ``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 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 "bpfilter.h"
+#include "vlan.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <machine/cpu.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_llc.h>
+#include <net/route.h>
+#include <net/netisr.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/if_ether.h>
+#endif
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <netmpls/mpls.h>
+
+#include <net/if_mpe.h>
+#include <net/if_wire.h>
+
+#ifdef WIRE_DEBUG
+#define        DPRINTF(fmt, args...)   printf("wire: " fmt "\n", ## args)
+#else
+#define        DPRINTF(fmt, args...)
+#endif
+
+
+void            wireattach(int);
+int             wire_clone_create(struct if_clone *, int);
+int             wire_clone_destroy(struct ifnet *);
+int             wire_ioctl(struct ifnet *, u_long, caddr_t);
+void            wire_init(struct wire_softc *);
+void            wire_stop(struct wire_softc *);
+int             wire_output(struct ifnet *, struct mbuf *,
+                       struct sockaddr *, struct rtentry *);
+void            wire_start(struct ifnet *);
+void            wire_input(struct mbuf *, struct ether_header *, struct 
wire_softc *);
+
+LIST_HEAD(, wire_softc) wire_list;
+
+struct if_clone wire_cloner =
+    IF_CLONE_INITIALIZER("wire", wire_clone_create, wire_clone_destroy);
+
+/* ARGSUSED */
+void
+wireattach(int n)
+{
+       LIST_INIT(&wire_list);
+       if_clone_attach(&wire_cloner);
+}
+
+int
+wire_clone_create(struct if_clone *ifc, int unit)
+{
+       struct wire_softc       *sc;
+       struct ifnet            *ifp;
+       int                      s;
+
+       sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO);
+       if (sc == NULL)
+               return (ENOMEM);
+
+       ifp = &sc->sc_if;
+       snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
+           ifc->ifc_name, unit);
+       ifp->if_softc = sc;
+       ifp->if_mtu = ETHERMTU;
+       ifp->if_flags = IFF_POINTOPOINT;
+       ifp->if_ioctl = wire_ioctl;
+       ifp->if_output = wire_output;
+       ifp->if_start = wire_start;
+       ifp->if_type = IFT_MPLSTUNNEL;
+       ifp->if_hdrlen = ETHER_HDR_LEN;
+       IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+       IFQ_SET_READY(&ifp->if_snd);
+
+       if_attach(ifp);
+       if_alloc_sadl(ifp);
+
+#if NBPFILTER > 0
+       bpfattach(&sc->sc_if.if_bpf, ifp,
+           DLT_EN10MB, ETHER_HDR_LEN);
+#endif
+
+       s = splnet();
+       LIST_INSERT_HEAD(&wire_list, sc, sc_list);
+       splx(s);
+
+       return (0);
+}
+
+int
+wire_clone_destroy(struct ifnet *ifp)
+{
+       struct wire_softc       *sc = ifp->if_softc;
+       int                      s;
+
+       wire_stop(sc);
+
+       s = splnet();
+       LIST_REMOVE(sc, sc_list);
+       splx(s);
+
+       if_detach(ifp);
+
+       free(sc, M_DEVBUF);
+       return (0);
+}
+
+int
+wire_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+       struct ifwreq           *req = (struct ifwreq *) data;
+       struct ifnet            *ifs, *ifm;
+       struct ifreq            *ifreq = (struct ifreq *) data;
+       struct wire_softc       *sc;
+       int                      error = 0, s;
+       struct shim_hdr          shim;
+       struct ifreq             ifreq_aux;
+
+       sc = ifp->if_softc;
+       s = splnet();
+       switch (cmd) {
+       case SIOCSETLABEL:
+               if ((error = copyin(ifreq->ifr_data, &shim, sizeof(shim))))
+                       break;
+               if (shim.shim_label > MPLS_LABEL_MAX ||
+                   shim.shim_label <= MPLS_LABEL_RESERVED_MAX) {
+                       error = EINVAL;
+                       break;
+               }
+               shim.shim_label = htonl(shim.shim_label << MPLS_LABEL_OFFSET);
+               if (sc->sc_shim.shim_label == shim.shim_label)
+                       break;
+               if (mpls_shim_label_exists(&shim)) {
+                       error = EEXIST;
+                       break;
+               }
+               if (sc->sc_shim.shim_label) {
+                       /* remove old MPLS route */
+                       mpe_newlabel(ifp, RTM_DELETE, &sc->sc_shim);
+               }
+               /* add new MPLS route */
+               error = mpe_newlabel(ifp, RTM_ADD, &shim);
+               if (error)
+                       break;
+               sc->sc_shim.shim_label = shim.shim_label;
+               break;
+
+       case SIOCGETLABEL:
+               bzero(&shim, sizeof(struct shim_hdr));
+               shim.shim_label =
+                   ((ntohl(sc->sc_shim.shim_label & MPLS_LABEL_MASK)) >>
+                       MPLS_LABEL_OFFSET);
+               error = copyout(&shim, ifreq->ifr_data, sizeof(shim));
+               break;
+
+       case SIOCWIREADD:
+               if ((error = suser(curproc, 0)) != 0)
+                       break;
+
+               /* Get mpe output interface */
+               ifs = ifunit(req->ifwr_ifsname);
+               ifm = ifunit(req->ifwr_mpename);
+               if (ifs == NULL || ifm == NULL) {
+                       error = ENOENT;
+                       break;
+               }
+               if (ifs->if_type != IFT_ETHER ||
+                   ifm->if_type != IFT_MPLS) {
+                       error = EINVAL;
+                       break;
+               }
+
+               /* Set input interface to promiscuos mode */
+               if ((ifs->if_flags & IFF_UP) == 0) {
+                       /*
+                        * Bring interface up long enough to set
+                        * promiscuous flag, then shut it down again.
+                        */
+                       strlcpy(ifreq_aux.ifr_name, req->ifwr_ifsname,
+                           IFNAMSIZ);
+                       ifs->if_flags |= IFF_UP;
+                       ifreq_aux.ifr_flags = ifs->if_flags;
+                       error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
+                           (caddr_t) &ifreq_aux);
+                       if (error != 0)
+                               break;
+
+                       error = ifpromisc(ifs, 1);
+                       if (error != 0)
+                               break;
+
+                       strlcpy(ifreq_aux.ifr_name, req->ifwr_ifsname,
+                           IFNAMSIZ);
+                       ifs->if_flags &= ~IFF_UP;
+                       ifreq_aux.ifr_flags = ifs->if_flags;
+                       error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
+                           (caddr_t) &ifreq_aux);
+                       if (error != 0) {
+                               ifpromisc(ifs, 0);
+                               break;
+                       }
+               } else {
+                       error = ifpromisc(ifs, 1);
+                       if (error != 0)
+                               break;
+               }
+
+               sc->sc_ifmpe = ifm;
+               sc->sc_ifs = ifs;
+               ifs->if_wire = (caddr_t) sc;
+               ifm->if_wire = (caddr_t) sc;
+               break;
+
+       case SIOCWIREDEL:
+               if ((error = suser(curproc, 0)) != 0)
+                       break;
+
+               ifs = ifunit(req->ifwr_ifsname);
+               ifm = ifunit(req->ifwr_mpename);
+               if (ifs == NULL || ifm == NULL) {
+                       error = ENOENT;
+                       break;
+               }
+               if (ifs->if_wire == NULL || ifm->if_wire == NULL) {
+                       error = ENXIO;
+                       break;
+               }
+               wire_stop(sc);
+               ifs->if_wire = NULL;
+               ifm->if_wire = NULL;
+               sc->sc_ifs = NULL;
+               sc->sc_ifmpe = NULL;
+               break;
+
+       case SIOCSIFFLAGS:
+               if ((ifp->if_flags & IFF_UP))
+                       wire_init(sc);
+               else
+                       wire_stop(sc);
+               break;
+
+       default:
+               error = ENOTTY;
+               break;
+       }
+       splx(s);
+       return (error);
+}
+
+void
+wire_ifdetach(struct ifnet *ifp)
+{
+       struct wire_softc       *sc;
+
+       sc = (struct wire_softc *) ifp->if_wire;
+       if (sc->sc_ifs) {
+               sc->sc_ifs->if_wire = NULL;
+               sc->sc_ifs = NULL;
+       }
+       if (sc->sc_ifmpe) {
+               sc->sc_ifmpe->if_wire = NULL;
+               sc->sc_ifmpe = NULL;
+       }
+
+       wire_stop(sc);
+       ifpromisc(ifp, 0);
+}
+
+void
+wire_init(struct wire_softc *sc)
+{
+       struct ifnet    *ifp = &sc->sc_if;
+
+       if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING)
+               return;
+
+       ifp->if_flags |= IFF_RUNNING;
+}
+
+void
+wire_stop(struct wire_softc *sc)
+{
+       struct ifnet    *ifp = &sc->sc_if;
+
+       if ((ifp->if_flags & IFF_RUNNING) == 0)
+               return;
+
+       ifp->if_flags &= ~IFF_RUNNING;
+}
+
+int
+wire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
+    struct rtentry *rt)
+{
+       if ((ifp->if_flags & IFF_RUNNING) == 0) {
+               m_freem(m);
+               return (0);
+       }
+
+       /* TODO */
+
+       m_freem(m);
+       return (EPFNOSUPPORT);
+}
+
+void
+wire_start(struct ifnet *ifp)
+{
+       struct mbuf     *m;
+       int              s;
+
+       if ((ifp->if_flags & IFF_RUNNING) == 0)
+               return;
+
+       for (;;) {
+               s = splnet();
+               IFQ_DEQUEUE(&ifp->if_snd, m);
+               splx(s);
+
+               if (m == NULL)
+                       return;
+
+               /* TODO */
+
+               m_freem(m);
+       }
+}
+
+void
+wire_input(struct mbuf *m, struct ether_header *eh, struct wire_softc *sc)
+{
+       struct ether_header     *aux;
+       struct shim_hdr          shim, *sptr;
+       int                      s;
+
+       if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
+               return;
+
+       /* Don't accept packets if there is no way to output them later */
+       if (sc->sc_ifmpe == NULL) {
+               sc->sc_if.if_ierrors++;
+               m_freem(m);
+               return;
+       }
+
+       /* Copy the encapsulated ethernet header */
+       M_PREPEND(m, sizeof(struct ether_header), M_NOWAIT);
+       if (m == NULL)
+               return;
+
+       aux = mtod(m, struct ether_header *);
+       bcopy(eh, aux, sizeof(struct ether_header));
+
+       /* Add our MPLS shim */
+       M_PREPEND(m, sizeof(struct shim_hdr), M_NOWAIT);
+       if (m == NULL)
+               return;
+
+       /* Set our protection against last time modifications and
+        * enqueue packet to ourselves, to send later through mpe(4).
+        */
+       bzero(&shim, sizeof(shim));
+       shim.shim_label |= htonl(mpls_defttl) & MPLS_TTL_MASK;
+       shim.shim_label |= sc->sc_shim.shim_label;
+
+       sptr = mtod(m, struct shim_hdr *);
+       bcopy(&shim, sptr, sizeof(struct shim_hdr));
+       s = splnet();
+       IF_ENQUEUE(&sc->sc_ifmpe->if_snd, m);
+       splx(s);
+
+       return;
+}
--- /dev/null   Mon Aug 27 00:22:43 2012
+++ net/if_wire.h       Tue Aug 21 21:10:19 2012
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 Rafael F. Zalamena <rzalam...@gmail.com>
+ * 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 ``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 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.
+ */
+
+#ifndef _NET_IF_WIRE_H_
+#define _NET_IF_WIRE_H_
+
+struct ifwreq {
+       char                             ifwr_name[IFNAMSIZ];
+       char                             ifwr_ifsname[IFNAMSIZ];
+       char                             ifwr_mpename[IFNAMSIZ];
+};
+
+struct wire_softc {
+       struct ifnet                     sc_if;         /* the interface */
+       struct ifnet                    *sc_ifmpe;      /* Interfaces to 
exchange packets */
+       struct ifnet                    *sc_ifs;
+       struct shim_hdr                  sc_shim;
+
+       LIST_ENTRY(wire_softc)           sc_list;       /* linked wire list */
+};
+
+void    wire_ifdetach(struct ifnet *);
+
+#endif /* _NET_IF_WIRE_H_ */
Index: conf/GENERIC
===================================================================
RCS file: /backup/obsd_cvs//src/sys/conf/GENERIC,v
retrieving revision 1.190
diff -u -r1.190 GENERIC
--- conf/GENERIC        23 Aug 2012 06:12:49 -0000      1.190
+++ conf/GENERIC        27 Aug 2012 03:24:30 -0000
@@ -65,6 +65,7 @@
 option         MROUTING        # Multicast router
 #option                PIM             # Protocol Independent Multicast
 option         MPLS            # Multi-Protocol Label Switching
+option         WIRE_DEBUG      # Wire debugging messages
 
 #mpath0                at root         # SCSI Multipathing
 #scsibus*      at mpath?
@@ -92,6 +93,7 @@
 # clonable devices
 pseudo-device  bpfilter        # packet filter
 pseudo-device  bridge          # network bridging support
+pseudo-device  wire            # pseudowire support
 pseudo-device  carp            # CARP protocol support
 pseudo-device  gif             # IPv[46] over IPv[46] tunnel (RFC1933)
 pseudo-device  gre             # GRE encapsulation interface
Index: conf/files
===================================================================
RCS file: /backup/obsd_cvs//src/sys/conf/files,v
retrieving revision 1.538
diff -u -r1.538 files
--- conf/files  23 Aug 2012 06:12:49 -0000      1.538
+++ conf/files  27 Aug 2012 03:24:30 -0000
@@ -518,6 +518,7 @@
 pseudo-device bpfilter: ifnet
 pseudo-device enc: ifnet
 pseudo-device bridge: ifnet, ether
+pseudo-device wire: ifnet, ether
 pseudo-device vlan: ifnet, ether
 pseudo-device carp: ifnet, ether
 pseudo-device sppp: ifnet
@@ -758,6 +759,7 @@
 file net/if_bridge.c                   bridge                  needs-count
 file net/bridgestp.c                   bridge
 file net/if_vlan.c                     vlan                    needs-count
+file net/if_wire.c                     wire                    needs-count
 file net/pipex.c                       pipex
 file net/radix.c
 file net/radix_mpath.c                 !small_kernel
Index: net/if.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/net/if.c,v
retrieving revision 1.241
diff -u -r1.241 if.c
--- net/if.c    3 Jan 2012 23:41:51 -0000       1.241
+++ net/if.c    27 Aug 2012 03:24:30 -0000
@@ -124,6 +124,10 @@
 #include <net/if_bridge.h>
 #endif
 
+#if NWIRE > 0
+#include <net/if_wire.h>
+#endif
+
 #if NCARP > 0
 #include <netinet/ip_carp.h>
 #endif
@@ -533,6 +537,10 @@
        /* Remove the interface from any bridge it is part of.  */
        if (ifp->if_bridge)
                bridge_ifdetach(ifp);
+#endif
+#if NWIRE > 0
+       if (ifp->if_wire)
+               wire_ifdetach(ifp);
 #endif
 
 #if NCARP > 0
Index: net/if.h
===================================================================
RCS file: /backup/obsd_cvs//src/sys/net/if.h,v
retrieving revision 1.132
diff -u -r1.132 if.h
--- net/if.h    21 Aug 2012 19:50:39 -0000      1.132
+++ net/if.h    27 Aug 2012 03:24:30 -0000
@@ -251,6 +251,7 @@
        int     if_pcount;              /* number of promiscuous listeners */
        caddr_t if_bpf;                 /* packet filter structure */
        caddr_t if_bridge;              /* bridge structure */
+       caddr_t if_wire;                /* wire structure */
        caddr_t if_tp;                  /* used by trunk ports */
        caddr_t if_pf_kif;              /* pf interface abstraction */
        union {
Index: net/if_ethersubr.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/net/if_ethersubr.c,v
retrieving revision 1.151
diff -u -r1.151 if_ethersubr.c
--- net/if_ethersubr.c  9 Jul 2011 00:47:18 -0000       1.151
+++ net/if_ethersubr.c  27 Aug 2012 03:24:30 -0000
@@ -500,6 +500,14 @@
                m_freem(m);
                return;
        }
+
+#if NWIRE > 0
+       if (ifp->if_wire) {
+               wire_input(m, eh, ifp->if_wire);
+               return;
+       }
+#endif
+
        if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
                if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
                        struct ifaddr *ifa;
Index: net/if_mpe.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/net/if_mpe.c,v
retrieving revision 1.27
diff -u -r1.27 if_mpe.c
--- net/if_mpe.c        14 Apr 2012 09:39:47 -0000      1.27
+++ net/if_mpe.c        27 Aug 2012 03:24:30 -0000
@@ -51,6 +51,8 @@
 
 #include <netmpls/mpls.h>
 
+#include <net/if_mpe.h>
+
 #ifdef MPLS_DEBUG
 #define DPRINTF(x)    do { if (mpedebug) printf x ; } while (0)
 #else
@@ -324,12 +326,9 @@
                shim.shim_label = htonl(shim.shim_label << MPLS_LABEL_OFFSET);
                if (ifm->sc_shim.shim_label == shim.shim_label)
                        break;
-               LIST_FOREACH(ifm, &mpeif_list, sc_list) {
-                       if (ifm != ifp->if_softc &&
-                           ifm->sc_shim.shim_label == shim.shim_label) {
-                               error = EEXIST;
-                               break;
-                       }
+               if (mpls_shim_label_exists(&shim)) {
+                       error = EEXIST;
+                       break;
                }
                if (error)
                        break;
Index: netmpls/mpls.h
===================================================================
RCS file: /backup/obsd_cvs//src/sys/netmpls/mpls.h,v
retrieving revision 1.25
diff -u -r1.25 mpls.h
--- netmpls/mpls.h      8 Sep 2010 08:00:56 -0000       1.25
+++ netmpls/mpls.h      27 Aug 2012 03:24:30 -0000
@@ -145,13 +145,6 @@
 
 #ifdef _KERNEL
 
-struct mpe_softc {
-       struct ifnet            sc_if;          /* the interface */
-       int                     sc_unit;
-       struct shim_hdr         sc_shim;
-       LIST_ENTRY(mpe_softc)   sc_list;
-};
-
 #define MPE_HDRLEN     sizeof(struct shim_hdr)
 #define MPE_MTU                1500
 #define MPE_MTU_MIN    256
@@ -175,6 +168,7 @@
 void   mpls_init(void);
 void   mplsintr(void);
 
+int             mpls_shim_label_exists(struct shim_hdr *);
 struct mbuf    *mpls_shim_pop(struct mbuf *);
 struct mbuf    *mpls_shim_swap(struct mbuf *, struct rt_mpls *);
 struct mbuf    *mpls_shim_push(struct mbuf *, struct rt_mpls *);
Index: netmpls/mpls_shim.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/netmpls/mpls_shim.c,v
retrieving revision 1.6
diff -u -r1.6 mpls_shim.c
--- netmpls/mpls_shim.c 28 Jan 2009 22:18:44 -0000      1.6
+++ netmpls/mpls_shim.c 27 Aug 2012 03:24:30 -0000
@@ -42,6 +42,30 @@
 
 #include <netmpls/mpls.h>
 
+#include <net/if_mpe.h>
+#include <net/if_wire.h>
+
+int
+mpls_shim_label_exists(struct shim_hdr *shim)
+{
+       extern LIST_HEAD(, mpe_softc)   mpeif_list;
+       extern LIST_HEAD(, wire_softc)  wire_list;
+
+       struct mpe_softc        *mpe_sc;
+       struct wire_softc       *wr_sc;
+
+       LIST_FOREACH(mpe_sc, &mpeif_list, sc_list) {
+               if (shim->shim_label == mpe_sc->sc_shim.shim_label)
+                       return (1);
+       }
+
+       LIST_FOREACH(wr_sc, &wire_list, sc_list) {
+               if (shim->shim_label == wr_sc->sc_shim.shim_label)
+                       return (1);
+       }
+       return (0);
+}
+
 struct mbuf *
 mpls_shim_pop(struct mbuf *m)
 {
Index: sys/sockio.h
===================================================================
RCS file: /backup/obsd_cvs//src/sys/sys/sockio.h,v
retrieving revision 1.49
diff -u -r1.49 sockio.h
--- sys/sockio.h        26 Nov 2011 23:38:18 -0000      1.49
+++ sys/sockio.h        27 Aug 2012 03:24:30 -0000
@@ -181,6 +181,9 @@
 #define SIOCSETKALIVE  _IOW('i', 163, struct ifkalivereq)
 #define SIOCGETKALIVE  _IOWR('i', 164, struct ifkalivereq)
 
+#define        SIOCWIREADD      _IOW('i', 165, struct ifwreq)  /* add wire ifs 
*/
+#define        SIOCWIREDEL      _IOW('i', 166, struct ifwreq)  /* del wire ifs 
*/
+
 #define        SIOCSVH         _IOWR('i', 245, struct ifreq)   /* set carp 
param */
 #define        SIOCGVH         _IOWR('i', 246, struct ifreq)   /* get carp 
param */

Reply via email to