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