Index: sys/sys/sockio.h =================================================================== RCS file: /cvs/src/sys/sys/sockio.h,v retrieving revision 1.78 diff -u -p -r1.78 sockio.h --- sys/sys/sockio.h 29 Nov 2018 00:11:23 -0000 1.78 +++ sys/sys/sockio.h 8 Jan 2019 03:51:30 -0000 @@ -143,6 +143,7 @@ #define SIOCSSPPPPARAMS _IOW('i', 147, struct ifreq) /* set pppoe params */ #define SIOCGSPPPPARAMS _IOWR('i', 148, struct ifreq) /* get pppoe params */ +#define SIOCGPWE3 _IOWR('i', 152, struct ifreq) /* get MPLS PWE3 cap */ #define SIOCSETLABEL _IOW('i', 153, struct ifreq) /* set MPLS label */ #define SIOCGETLABEL _IOW('i', 154, struct ifreq) /* get MPLS label */ Index: sys/net/if.h =================================================================== RCS file: /cvs/src/sys/net/if.h,v retrieving revision 1.198 diff -u -p -r1.198 if.h --- sys/net/if.h 12 Nov 2018 23:34:48 -0000 1.198 +++ sys/net/if.h 8 Jan 2019 03:51:30 -0000 @@ -420,12 +420,16 @@ struct ifreq { #define ifr_index ifr_ifru.ifru_index /* interface index */ #define ifr_llprio ifr_ifru.ifru_metric /* link layer priority */ #define ifr_hdrprio ifr_ifru.ifru_metric /* header prio field config */ +#define ifr_pwe3 ifr_ifru.ifru_metric /* PWE3 type */ }; #define IF_HDRPRIO_MIN IFQ_MINPRIO #define IF_HDRPRIO_MAX IFQ_MAXPRIO #define IF_HDRPRIO_PACKET -1 /* use mbuf prio */ #define IF_HDRPRIO_PAYLOAD -2 /* copy payload prio */ + +#define IF_PWE3_ETHERNET 1 /* ethernet or ethernet tagged */ +#define IF_PWE3_IP 2 /* IP layer 2 */ struct ifaliasreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ Index: sys/net/if_mpw.c =================================================================== RCS file: /cvs/src/sys/net/if_mpw.c,v retrieving revision 1.24 diff -u -p -r1.24 if_mpw.c --- sys/net/if_mpw.c 19 Feb 2018 08:59:52 -0000 1.24 +++ sys/net/if_mpw.c 8 Jan 2019 03:51:30 -0000 @@ -45,15 +45,16 @@ #endif struct mpw_softc { - struct ifnet sc_if; + struct arpcom sc_ac; +#define sc_if sc_ac.ac_if - struct ifaddr sc_ifa; - struct sockaddr_mpls sc_smpls; /* Local label */ + struct ifaddr sc_ifa; + struct sockaddr_mpls sc_smpls; /* Local label */ - uint32_t sc_flags; - uint32_t sc_type; - struct shim_hdr sc_rshim; - struct sockaddr_storage sc_nexthop; + uint32_t sc_flags; + uint32_t sc_type; + struct shim_hdr sc_rshim; + struct sockaddr_storage sc_nexthop; }; void mpwattach(int); @@ -63,7 +64,6 @@ int mpw_ioctl(struct ifnet *, u_long, ca int mpw_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); void mpw_start(struct ifnet *); -int mpw_input(struct ifnet *, struct mbuf *, void *); #if NVLAN > 0 struct mbuf *mpw_vlan_handle(struct mbuf *, struct mpw_softc *); #endif /* NVLAN */ @@ -85,32 +85,25 @@ mpw_clone_create(struct if_clone *ifc, i sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = &sc->sc_if; - snprintf(ifp->if_xname, sizeof(ifp->if_xname), "mpw%d", unit); + 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_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED; ifp->if_ioctl = mpw_ioctl; ifp->if_output = mpw_output; ifp->if_start = mpw_start; - ifp->if_type = IFT_MPLSTUNNEL; - ifp->if_hdrlen = ETHER_HDR_LEN; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + ether_fakeaddr(ifp); - if_attach(ifp); - if_alloc_sadl(ifp); + if_attach(ifp); + ether_ifattach(ifp); sc->sc_ifa.ifa_ifp = ifp; sc->sc_ifa.ifa_addr = sdltosa(ifp->if_sadl); sc->sc_smpls.smpls_len = sizeof(sc->sc_smpls); sc->sc_smpls.smpls_family = AF_MPLS; - if_ih_insert(ifp, mpw_input, NULL); - -#if NBPFILTER > 0 - bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN); -#endif /* NBFILTER */ - return (0); } @@ -122,27 +115,19 @@ mpw_clone_destroy(struct ifnet *ifp) ifp->if_flags &= ~IFF_RUNNING; if (sc->sc_smpls.smpls_label) { - rt_ifa_del(&sc->sc_ifa, RTF_MPLS, + rt_ifa_del(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL, smplstosa(&sc->sc_smpls)); } - if_ih_remove(ifp, mpw_input, NULL); - + ether_ifdetach(ifp); if_detach(ifp); + free(sc, M_DEVBUF, sizeof(*sc)); return (0); } int -mpw_input(struct ifnet *ifp, struct mbuf *m, void *cookie) -{ - /* Don't have local broadcast. */ - m_freem(m); - return (1); -} - -int mpw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ifreq *ifr = (struct ifreq *) data; @@ -168,6 +153,10 @@ mpw_ioctl(struct ifnet *ifp, u_long cmd, ifp->if_flags &= ~IFF_RUNNING; break; + case SIOCGPWE3: + ifr->ifr_pwe3 = IF_PWE3_ETHERNET; + break; + case SIOCSETMPWCFG: error = suser(curproc); if (error != 0) @@ -180,7 +169,7 @@ mpw_ioctl(struct ifnet *ifp, u_long cmd, /* Teardown all configuration if got no nexthop */ sin = (struct sockaddr_in *) &imr.imr_nexthop; if (sin->sin_addr.s_addr == 0) { - if (rt_ifa_del(&sc->sc_ifa, RTF_MPLS, + if (rt_ifa_del(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL, smplstosa(&sc->sc_smpls)) == 0) sc->sc_smpls.smpls_label = 0; @@ -209,11 +198,11 @@ mpw_ioctl(struct ifnet *ifp, u_long cmd, if (sc->sc_smpls.smpls_label != imr.imr_lshim.shim_label) { if (sc->sc_smpls.smpls_label) - rt_ifa_del(&sc->sc_ifa, RTF_MPLS, + rt_ifa_del(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL, smplstosa(&sc->sc_smpls)); sc->sc_smpls.smpls_label = imr.imr_lshim.shim_label; - error = rt_ifa_add(&sc->sc_ifa, RTF_MPLS, + error = rt_ifa_add(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL, smplstosa(&sc->sc_smpls)); if (error != 0) { sc->sc_smpls.smpls_label = 0; @@ -257,19 +246,18 @@ mpw_ioctl(struct ifnet *ifp, u_long cmd, return (error); } -int -mpw_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, - struct rtentry *rt) +static void +mpw_input(struct mpw_softc *sc, struct mbuf *m) { - struct mpw_softc *sc = ifp->if_softc; struct mbuf_list ml = MBUF_LIST_INITIALIZER(); - struct ether_header *eh, ehc; + struct ifnet *ifp = &sc->sc_if; struct shim_hdr *shim; - if (sc->sc_type == IMR_TYPE_NONE) { - m_freem(m); - return (EHOSTUNREACH); - } + if (!ISSET(ifp->if_flags, IFF_RUNNING)) + goto drop; + + if (sc->sc_type == IMR_TYPE_NONE) + goto drop; if (sc->sc_flags & IMR_FLAG_CONTROLWORD) { shim = mtod(m, struct shim_hdr *); @@ -282,78 +270,37 @@ mpw_output(struct ifnet *ifp, struct mbu */ if (shim->shim_label & CW_ZERO_MASK) { ifp->if_ierrors++; - m_freem(m); - return (EINVAL); + goto drop; } /* We don't support fragmentation just yet. */ if (shim->shim_label & CW_FRAG_MASK) { ifp->if_ierrors++; - m_freem(m); - return (EINVAL); - } - } - - if (sc->sc_type == IMR_TYPE_ETHERNET_TAGGED) { - m_copydata(m, 0, sizeof(ehc), (caddr_t) &ehc); - m_adj(m, ETHER_HDR_LEN); - - /* Ethernet tagged expects at least 2 VLANs */ - if (ntohs(ehc.ether_type) != ETHERTYPE_QINQ) { - ifp->if_ierrors++; - m_freem(m); - return (EINVAL); + goto drop; } - - /* Remove dummy VLAN and update ethertype */ - if (EVL_VLANOFTAG(*mtod(m, uint16_t *)) == 0) { - m_adj(m, EVL_ENCAPLEN); - ehc.ether_type = htons(ETHERTYPE_VLAN); - } - - M_PREPEND(m, sizeof(*eh), M_NOWAIT); - if (m == NULL) - return (ENOMEM); - - eh = mtod(m, struct ether_header *); - memcpy(eh, &ehc, sizeof(*eh)); } ml_enqueue(&ml, m); if_input(ifp, &ml); - - return (0); + return; +drop: + m_freem(m); } -#if NVLAN > 0 -extern void vlan_start(struct ifqueue *); - -/* - * This routine handles VLAN tag reinsertion in packets flowing through - * the pseudowire. Also it does the necessary modifications to the VLANs - * to respect the RFC. - */ -struct mbuf * -mpw_vlan_handle(struct mbuf *m, struct mpw_softc *sc) +int +mpw_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rt) { - struct ifnet *ifp; - struct ifvlan *ifv; - - uint16_t type = ETHERTYPE_QINQ; - uint16_t tag = 0; + struct mpw_softc *sc = ifp->if_softc; - ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp != NULL && ifp->if_qstart == vlan_start && - ISSET(ifp->if_flags, IFF_RUNNING)) { - ifv = ifp->if_softc; - type = ifv->ifv_type; - tag = ifv->ifv_tag; + if (dst->sa_family == AF_LINK && + rt != NULL && ISSET(rt->rt_flags, RTF_LOCAL)) { + mpw_input(sc, m); + return (0); } - if_put(ifp); - return (vlan_inject(m, type, tag)); + return (ether_output(ifp, m, dst, rt)); } -#endif /* NVLAN */ void mpw_start(struct ifnet *ifp) @@ -396,20 +343,6 @@ mpw_start(struct ifnet *ifp) if (sc->sc_if.if_bpf) bpf_mtap(sc->sc_if.if_bpf, m, BPF_DIRECTION_OUT); #endif /* NBPFILTER */ - - if (sc->sc_type == IMR_TYPE_ETHERNET_TAGGED) { - #if NVLAN > 0 - m = mpw_vlan_handle(m, sc); - if (m == NULL) { - ifp->if_oerrors++; - continue; - } - #else - /* Ethernet tagged doesn't work without VLANs'*/ - m_freem(m); - continue; - #endif /* NVLAN */ - } if (sc->sc_flags & IMR_FLAG_CONTROLWORD) { M_PREPEND(m, sizeof(*shim), M_NOWAIT); Index: usr.sbin/ldpd/Makefile =================================================================== RCS file: /cvs/src/usr.sbin/ldpd/Makefile,v retrieving revision 1.12 diff -u -p -r1.12 Makefile --- usr.sbin/ldpd/Makefile 20 Jan 2017 12:19:18 -0000 1.12 +++ usr.sbin/ldpd/Makefile 8 Jan 2019 03:51:30 -0000 @@ -17,4 +17,6 @@ YFLAGS= LDADD+= -levent -lutil DPADD+= ${LIBEVENT} ${LIBUTIL} +DEBUG=-g + .include Index: usr.sbin/ldpd/kroute.c =================================================================== RCS file: /cvs/src/usr.sbin/ldpd/kroute.c,v retrieving revision 1.67 diff -u -p -r1.67 kroute.c --- usr.sbin/ldpd/kroute.c 3 Jan 2018 19:39:07 -0000 1.67 +++ usr.sbin/ldpd/kroute.c 8 Jan 2019 03:51:30 -0000 @@ -141,6 +141,12 @@ kif_init(void) if (fetchifs() == -1) return (-1); + if ((kr_state.ioctl_fd = socket(AF_INET, + SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { + log_warn("%s: ioctl socket", __func__); + return (-1); + } + return (0); } @@ -198,12 +204,6 @@ kr_init(int fs, unsigned int rdomain) kr_dispatch_msg, NULL); event_add(&kr_state.ev, NULL); - if ((kr_state.ioctl_fd = socket(AF_INET, - SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { - log_warn("%s: ioctl socket", __func__); - return (-1); - } - return (0); } @@ -1809,6 +1809,8 @@ kmpw_install(const char *ifname, struct struct ifreq ifr; struct ifmpwreq imr; +log_warnx("%s", __func__); + memset(&imr, 0, sizeof(imr)); switch (kpw->pw_type) { case PW_TYPE_ETHERNET: @@ -1855,6 +1857,35 @@ kmpw_uninstall(const char *ifname) ifr.ifr_data = (caddr_t) &imr; if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr)) { log_warn("ioctl SIOCSETMPWCFG"); + return (-1); + } + + return (0); +} + +int +kmpw_find(const char *ifname) +{ + struct ifreq ifr; + +log_warnx("%s", ifname); + memset(&ifr, 0, sizeof(ifr)); + if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= + sizeof(ifr.ifr_name)) { +log_warn("%u", __LINE__); + errno = ENAMETOOLONG; + return (-1); + } + + if (ioctl(kr_state.ioctl_fd, SIOCGPWE3, &ifr) == -1) +{ +log_warn("%u", __LINE__); + return (-1); +} + + if (ifr.ifr_pwe3 != IF_PWE3_ETHERNET) { +log_warn("%u", __LINE__); + errno = EPFNOSUPPORT; return (-1); } Index: usr.sbin/ldpd/l2vpn.c =================================================================== RCS file: /cvs/src/usr.sbin/ldpd/l2vpn.c,v retrieving revision 1.24 diff -u -p -r1.24 l2vpn.c --- usr.sbin/ldpd/l2vpn.c 4 Mar 2017 00:21:48 -0000 1.24 +++ usr.sbin/ldpd/l2vpn.c 8 Jan 2019 03:51:30 -0000 @@ -234,22 +234,31 @@ l2vpn_pw_reset(struct l2vpn_pw *pw) int l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) { - struct fec fec; - struct fec_node *fn; +// struct fec fec; +// struct fec_node *fn; /* check for a remote label */ if (fnh->remote_label == NO_LABEL) +{ +log_warnx("%s no label", __func__); return (0); +} /* MTUs must match */ if (pw->l2vpn->mtu != pw->remote_mtu) +{ +log_warnx("%s mtu mismatch", __func__); return (0); +} /* check pw status if applicable */ if ((pw->flags & F_PW_STATUSTLV) && pw->remote_status != PW_FORWARDING) +{ +log_warnx("%s remote status != forwarding", __func__); return (0); - +} +#if 0 /* check for a working lsp to the nexthop */ memset(&fec, 0, sizeof(fec)); switch (pw->af) { @@ -269,14 +278,21 @@ l2vpn_pw_ok(struct l2vpn_pw *pw, struct fn = (struct fec_node *)fec_find(&ft, &fec); if (fn == NULL || fn->local_label == NO_LABEL) +{ +log_warnx("%s no fec node (%d)", __func__, fn ? fn->local_label : -1); return (0); +} /* * Need to ensure that there's a label binding for all nexthops. * Otherwise, ECMP for this route could render the pseudowire unusable. */ LIST_FOREACH(fnh, &fn->nexthops, entry) if (fnh->remote_label == NO_LABEL) +{ +log_warnx("%s no remote label", __func__); return (0); +} +#endif return (1); } Index: usr.sbin/ldpd/ldpd.h =================================================================== RCS file: /cvs/src/usr.sbin/ldpd/ldpd.h,v retrieving revision 1.88 diff -u -p -r1.88 ldpd.h --- usr.sbin/ldpd/ldpd.h 8 Feb 2018 00:17:31 -0000 1.88 +++ usr.sbin/ldpd/ldpd.h 8 Jan 2019 03:51:30 -0000 @@ -564,6 +564,7 @@ void kr_change_egress_label(int, int); void kr_show_route(struct imsg *); void kr_ifinfo(char *, pid_t); struct kif *kif_findname(char *); +int kmpw_find(const char *); void kif_clear(void); int kmpw_set(struct kpw *); int kmpw_unset(struct kpw *); Index: usr.sbin/ldpd/parse.y =================================================================== RCS file: /cvs/src/usr.sbin/ldpd/parse.y,v retrieving revision 1.67 diff -u -p -r1.67 parse.y --- usr.sbin/ldpd/parse.y 1 Nov 2018 00:18:44 -0000 1.67 +++ usr.sbin/ldpd/parse.y 8 Jan 2019 03:51:30 -0000 @@ -517,7 +517,7 @@ pseudowire : PSEUDOWIRE STRING { } free($2); - if (kif->if_type != IFT_MPLSTUNNEL) { + if (kmpw_find(kif->ifname) == -1) { yyerror("unsupported interface type on " "interface %s", kif->ifname); YYERROR;