This new diff aims to simplify the mpe(4) device and also to improve
the old code that handled the installation of MPLS interface routes.

I followed what mpi@ said:

On Tue, Sep 30, 2014 at 11:00:25AM +0200, Martin Pieuchot wrote:
> Hello Rafael,
> 
> On 14/09/14(Sun) 23:49, Rafael Zalamena wrote:
> > 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.
> 
> Would it be possible to use  the new rt_ifa_add() and rt_ifa_del() instead of
> keeping what is basically a copy of the old rtinit()?
> 
> In your case you want to use the lladdr's ifa and you can check for
> RTF_MPLS in the flags to add the corresponding MPLS_OP_POP value.
> 
> --- patch snipped ---

Code change:
 * Moved label address from softc to lladdr ifa
 * Changed rt_ifa_add to default RTF_MPLS routes to do a POP and only
use rdomain 0 (MPLS only works on domain 0, and it doesn't make sense
other actions when creating MPLS route to an interface)
 * Removed old code that installed mpe MPLS routes
 * Conflicting labels verification is now done by routing (see rt_ifa_add())

This was tested in the setup described in:
http://2011.eurobsdcon.org/papers/jeker/MPLS.pdf

Here is the diff:
diff --git sys/net/if_mpe.c sys/net/if_mpe.c
index 74039dc..8580ef3 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 =
@@ -84,13 +83,19 @@ mpe_clone_create(struct if_clone *ifc, int unit)
 {
        struct ifnet            *ifp;
        struct mpe_softc        *mpeif;
+       struct sockaddr_mpls    *smpls;
        int                      s;
 
        if ((mpeif = malloc(sizeof(*mpeif),
            M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
                return (ENOMEM);
 
-       mpeif->sc_shim.shim_label = 0;
+       smpls = malloc(sizeof(*smpls), M_IFADDR, M_NOWAIT | M_ZERO);
+       if (smpls == NULL) {
+               free(mpeif, M_DEVBUF, 0);
+               return (ENOMEM);
+       }
+
        mpeif->sc_unit = unit;
        ifp = &mpeif->sc_if;
        snprintf(ifp->if_xname, sizeof ifp->if_xname, "mpe%d", unit);
@@ -110,6 +115,10 @@ mpe_clone_create(struct if_clone *ifc, int unit)
        bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
 #endif
 
+       smpls->smpls_family = AF_MPLS;
+       smpls->smpls_len = sizeof(*smpls);
+       ifp->if_lladdr->ifa_dstaddr = smplstosa(smpls);
+
        s = splnet();
        LIST_INSERT_HEAD(&mpeif_list, mpeif, sc_list);
        splx(s);
@@ -127,6 +136,7 @@ mpe_clone_destroy(struct ifnet *ifp)
        LIST_REMOVE(mpeif, sc_list);
        splx(s);
 
+       free(ifp->if_lladdr->ifa_dstaddr, M_IFADDR, 0);
        if_detach(ifp);
        free(mpeif, M_DEVBUF, 0);
        return (0);
@@ -278,7 +288,7 @@ int
 mpeioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
        int                      error;
-       struct mpe_softc        *ifm;
+       struct sockaddr_mpls    *smpls;
        struct ifreq            *ifr;
        struct shim_hdr          shim;
 
@@ -303,14 +313,13 @@ mpeioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                        ifp->if_mtu = ifr->ifr_mtu;
                break;
        case SIOCGETLABEL:
-               ifm = ifp->if_softc;
+               smpls = satosmpls(ifp->if_lladdr->ifa_dstaddr);
                shim.shim_label =
-                   ((ntohl(ifm->sc_shim.shim_label & MPLS_LABEL_MASK)) >>
+                   ((ntohl(smpls->smpls_label & MPLS_LABEL_MASK)) >>
                    MPLS_LABEL_OFFSET);
                error = copyout(&shim, ifr->ifr_data, sizeof(shim));
                break;
        case SIOCSETLABEL:
-               ifm = ifp->if_softc;
                if ((error = copyin(ifr->ifr_data, &shim, sizeof(shim))))
                        break;
                if (shim.shim_label > MPLS_LABEL_MAX ||
@@ -319,36 +328,29 @@ 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)
+
+               smpls = satosmpls(ifp->if_lladdr->ifa_dstaddr);
+               if (smpls->smpls_label == shim.shim_label)
                        break;
-               ifm = ifp->if_softc;
-               if (ifm->sc_shim.shim_label) {
-                       /* remove old MPLS route */
-                       mpe_newlabel(ifp, RTM_DELETE, &ifm->sc_shim);
+               if (smpls->smpls_label) {
+                       rt_ifa_del(ifp->if_lladdr, RTF_MPLS | RTF_UP,
+                           smplstosa(smpls));
+                       smpls->smpls_label = 0;
                }
-               /* add new MPLS route */
-               error = mpe_newlabel(ifp, RTM_ADD, &shim);
-               if (error)
-                       break;
-               ifm->sc_shim.shim_label = shim.shim_label;
+
+               smpls->smpls_label = shim.shim_label;
+               error = rt_ifa_add(ifp->if_lladdr, RTF_MPLS | RTF_UP,
+                   smplstosa(smpls));
+               if (error != 0)
+                       smpls->smpls_label = 0;
                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);
-                       }
+                       smpls = satosmpls(ifp->if_lladdr->ifa_dstaddr);
+                       if (smpls->smpls_label)
+                               rt_ifa_add(ifp->if_lladdr, RTF_MPLS | RTF_UP,
+                                   smplstosa(smpls));
                }
                /* return with ENOTTY so that the parent handler finishes */
                return (ENOTTY);
@@ -442,38 +444,3 @@ mpe_input6(struct mbuf *m, struct ifnet *ifp, struct 
sockaddr_mpls *smpls,
        splx(s);
 }
 #endif /* INET6 */
-
-int
-mpe_newlabel(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);
-}
diff --git sys/net/route.c sys/net/route.c
index 4ac1bd1..9559d89 100644
--- sys/net/route.c
+++ sys/net/route.c
@@ -1100,6 +1100,11 @@ rt_ifa_add(struct ifaddr *ifa, int flags, struct 
sockaddr *dst)
        info.rti_info[RTAX_LABEL] =
            rtlabel_id2sa(ifa->ifa_ifp->if_rtlabelid, &sa_rl);
 
+       if ((flags & RTF_MPLS) == RTF_MPLS) {
+               info.rti_mpls = MPLS_OP_POP;
+               rtableid = 0;
+       }
+
        if ((flags & RTF_HOST) == 0)
                info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
 
diff --git sys/netmpls/mpls.h sys/netmpls/mpls.h
index 2903aa4..b9085b0 100644
--- sys/netmpls/mpls.h
+++ sys/netmpls/mpls.h
@@ -149,7 +149,6 @@ extern      struct domain mplsdomain;
 struct mpe_softc {
        struct ifnet            sc_if;          /* the interface */
        int                     sc_unit;
-       struct shim_hdr         sc_shim;
        LIST_ENTRY(mpe_softc)   sc_list;
 };
 

Reply via email to