The following patch is just a preparation for the code that is coming to
implement the wire network interface (the VPLS datapath) to work on OpenBSD.

This code turns the mpe code that handles route and labels into some general
use functions that will be called by mpe and wire.

diff --git sys/net/if_mpe.c sys/net/if_mpe.c
index 74039dc..98d69f4 100644
--- sys/net/if_mpe.c
+++ sys/net/if_mpe.c
@@ -61,7 +61,6 @@ int   mpeioctl(struct ifnet *, u_long, caddr_t);
 void   mpestart(struct ifnet *);
 int    mpe_clone_create(struct if_clone *, int);
 int    mpe_clone_destroy(struct ifnet *);
-int    mpe_newlabel(struct ifnet *, int, struct shim_hdr *);
 
 LIST_HEAD(, mpe_softc) mpeif_list;
 struct if_clone        mpe_cloner =
@@ -319,36 +318,17 @@ mpeioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                        break;
                }
                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 (error)
-                       break;
-               ifm = ifp->if_softc;
-               if (ifm->sc_shim.shim_label) {
-                       /* remove old MPLS route */
-                       mpe_newlabel(ifp, RTM_DELETE, &ifm->sc_shim);
-               }
-               /* add new MPLS route */
-               error = mpe_newlabel(ifp, RTM_ADD, &shim);
-               if (error)
-                       break;
-               ifm->sc_shim.shim_label = shim.shim_label;
+               error = mpls_shim_set(ifp, &shim, &ifm->sc_shim);
                break;
        case SIOCSIFRDOMAIN:
                /* must readd the MPLS "route" for our label */
                ifm = ifp->if_softc;
                if (ifr->ifr_rdomainid != ifp->if_rdomain) {
-                       if (ifm->sc_shim.shim_label) {
-                               shim.shim_label = ifm->sc_shim.shim_label;
-                               error = mpe_newlabel(ifp, RTM_ADD, &shim);
-                       }
+                       shim.shim_label = ifm->sc_shim.shim_label;
+
+                       /* XXX trick mpls_shim_set() to reinstall the route */
+                       bzero(&ifm->sc_shim, sizeof(ifm->sc_shim));
+                       error = mpls_shim_set(ifp, &shim, &ifm->sc_shim);
                }
                /* return with ENOTTY so that the parent handler finishes */
                return (ENOTTY);
@@ -444,36 +424,13 @@ mpe_input6(struct mbuf *m, struct ifnet *ifp, struct 
sockaddr_mpls *smpls,
 #endif /* INET6 */
 
 int
-mpe_newlabel(struct ifnet *ifp, int cmd, struct shim_hdr *shim)
+mpe_label_exists(const struct shim_hdr *shim)
 {
-       struct rtentry *nrt;
-       struct sockaddr_mpls dst;
-       struct rt_addrinfo info;
-       int error;
-
-       bzero(&dst, sizeof(dst));
-       dst.smpls_len = sizeof(dst);
-       dst.smpls_family = AF_MPLS;
-       dst.smpls_label = shim->shim_label;
-
-       bzero(&info, sizeof(info));
-       info.rti_flags = RTF_UP | RTF_MPLS;
-       info.rti_mpls = MPLS_OP_POP;
-       info.rti_info[RTAX_DST] = smplstosa(&dst);
-       info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)ifp->if_sadl;
-
-       error = rtrequest1(cmd, &info, RTP_CONNECTED, &nrt, 0);
-       rt_missmsg(cmd, &info, error ? 0 : nrt->rt_flags, ifp, error, 0);
-       if (cmd == RTM_DELETE) {
-               if (error == 0 && nrt != NULL) {
-                       if (nrt->rt_refcnt <= 0) {
-                               nrt->rt_refcnt++;
-                               rtfree(nrt);
-                       }
-               }
-       }
-       if (cmd == RTM_ADD && error == 0 && nrt != NULL) {
-               nrt->rt_refcnt--;
-       }
-       return (error);
+       struct  mpe_softc *mpe_sc;
+
+       LIST_FOREACH(mpe_sc, &mpeif_list, sc_list)
+               if (shim->shim_label == mpe_sc->sc_shim.shim_label)
+                       return (1);
+
+       return (0);
 }
diff --git sys/netmpls/mpls.h sys/netmpls/mpls.h
index 2903aa4..0363d86 100644
--- sys/netmpls/mpls.h
+++ sys/netmpls/mpls.h
@@ -176,9 +176,13 @@ extern int         mpls_inkloop;
 void   mpls_init(void);
 void   mplsintr(void);
 
+int             mpe_label_exists(const 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 *);
+int             mpls_shim_set(struct ifnet *, struct shim_hdr *,
+                   struct shim_hdr *);
 
 int             mpls_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 void            mpls_input(struct mbuf *);
diff --git sys/netmpls/mpls_shim.c sys/netmpls/mpls_shim.c
index 203f220..3275dfb 100644
--- sys/netmpls/mpls_shim.c
+++ sys/netmpls/mpls_shim.c
@@ -30,6 +30,8 @@
  * SUCH DAMAGE.
  */
 
+#include "mpe.h"
+
 #include <sys/param.h>
 #include <sys/mbuf.h>
 #include <sys/errno.h>
@@ -37,9 +39,13 @@
 #include <sys/systm.h>
 
 #include <net/if.h>
+#include <net/route.h>
 
 #include <netmpls/mpls.h>
 
+int    mpls_shim_label_exists(const struct shim_hdr *);
+int    mpls_shim_route(struct ifnet *, int, struct shim_hdr *);
+
 struct mbuf *
 mpls_shim_pop(struct mbuf *m)
 {
@@ -96,3 +102,78 @@ mpls_shim_push(struct mbuf *m, struct rt_mpls *rt_mpls)
 
        return (mpls_shim_swap(m, rt_mpls));
 }
+
+int
+mpls_shim_label_exists(const struct shim_hdr *shim)
+{
+#if NMPE > 0
+       if (mpe_label_exists(shim))
+               return (1);
+#endif /* NMPE */
+
+       return (0);
+}
+
+int
+mpls_shim_route(struct ifnet *ifp, int cmd, struct shim_hdr *shim)
+{
+       struct rtentry *nrt;
+       struct sockaddr_mpls dst;
+       struct rt_addrinfo info;
+       int error;
+
+       bzero(&dst, sizeof(dst));
+       dst.smpls_len = sizeof(dst);
+       dst.smpls_family = AF_MPLS;
+       dst.smpls_label = shim->shim_label;
+
+       bzero(&info, sizeof(info));
+       info.rti_flags = RTF_UP | RTF_MPLS;
+       info.rti_mpls = MPLS_OP_POP;
+       info.rti_info[RTAX_DST] = smplstosa(&dst);
+       info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)ifp->if_sadl;
+
+       error = rtrequest1(cmd, &info, RTP_CONNECTED, &nrt, 0);
+       rt_missmsg(cmd, &info, error ? 0 : nrt->rt_flags, ifp, error, 0);
+       if (cmd == RTM_DELETE) {
+               if (error == 0 && nrt != NULL) {
+                       if (nrt->rt_refcnt <= 0) {
+                               nrt->rt_refcnt++;
+                               rtfree(nrt);
+                       }
+               }
+       }
+       if (cmd == RTM_ADD && error == 0 && nrt != NULL)
+               nrt->rt_refcnt--;
+
+       return (error);
+}
+
+int
+mpls_shim_set(struct ifnet *ifp, struct shim_hdr *sshim, struct shim_hdr 
*dshim)
+{
+       int     error;
+
+       if (sshim->shim_label == dshim->shim_label)
+               return (0);
+
+       /* There must be only one route to this path */
+       if (mpls_shim_label_exists(sshim))
+               return (EEXIST);
+
+       /* Remove old MPLS route */
+       if (dshim->shim_label != 0) {
+               mpls_shim_route(ifp, RTM_DELETE, dshim);
+               bzero(dshim, sizeof(*dshim));
+       }
+
+       if (sshim->shim_label == 0)
+               return (0);
+
+       /* Add new MPLS route */
+       error = mpls_shim_route(ifp, RTM_ADD, sshim);
+       if (error == 0)
+               dshim->shim_label = sshim->shim_label;
+
+       return (error);
+}

Reply via email to