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; };