I mean rdomain 0 below, not 1.
> On 30 Jan 2019, at 11:48, David Gwynne <da...@gwynne.id.au> wrote:
>
> mpls uses AF_MPLS routes with RTF_LOCAL set on them to know which tags
> are used as input for the mpe and mpw interfaces. setting this up
> currently goes through rt_ifa_add, but that has a couple of features
> that are undesirable for mpls.
>
> Firstly, rt_ifa_add unconditionally sets RTF_MPATH on the routes it
> adds, which means multiple mpe and mpw interfaces can "own" the same
> input tag. mpe tries to work around this by maintaining a global list of
> mpe interfaces, and iterates over them when a new label is added. That's
> ok (sort of) for mpe, but it doesnt take the tags used by mpw into
> account.
>
> Secondly, I'd like to start pulling apart the restriction on the use of
> mpls only in rdomain 1. rt_ifa_add doesn't help this situation because
> it assumes that we're adding a route inside the rdomain the interface is
> in, rather than the one it tunnels in. Changing this assumption means
> forking rt_ifa_add, and oh look, that's what I've started here.
>
> So, if I have the following:
>
> mpe2: flags=51<UP,POINTOPOINT,RUNNING> rdomain 2 mtu 1500
> index 6 priority 0 llprio 3
> mpls label 1000
> groups: mpe
> inet 192.168.0.25 --> 0.0.0.0 netmask 0xffffffff
> mpw0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
> lladdr fe:e1:ba:d0:93:1a
> index 7 priority 0 llprio 3
> encapsulation-type ethernet, control-word
> mpls label: local 16 remote 16
> neighbor: 192.168.0.27
> groups: mpw
> inet 100.64.100.2 netmask 0xffffff00 broadcast 100.64.100.255
>
> The following now does what's expected:
>
> dlg@cpe0 sys$ sudo ifconfig mpe3 create
> dlg@cpe0 sys$ sudo ifconfig mpe3 mplslabel 16
> ifconfig: SIOCSETLABEL: File exists
>
> ok?
>
> Index: net/if_mpe.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_mpe.c,v
> retrieving revision 1.76
> diff -u -p -r1.76 if_mpe.c
> --- net/if_mpe.c 30 Jan 2019 01:09:36 -0000 1.76
> +++ net/if_mpe.c 30 Jan 2019 01:40:47 -0000
> @@ -132,10 +132,8 @@ mpe_clone_destroy(struct ifnet *ifp)
>
> LIST_REMOVE(sc, sc_list);
>
> - if (sc->sc_smpls.smpls_label) {
> - rt_ifa_del(&sc->sc_ifa, RTF_MPLS,
> - smplstosa(&sc->sc_smpls));
> - }
> + if (sc->sc_smpls.smpls_label)
> + mpls_ifa_del(&sc->sc_ifa, &sc->sc_smpls);
>
> if_detach(ifp);
> free(sc, M_DEVBUF, sizeof *sc);
> @@ -331,13 +329,11 @@ mpe_ioctl(struct ifnet *ifp, u_long cmd,
> ifm = ifp->if_softc;
> if (ifm->sc_smpls.smpls_label) {
> /* remove old MPLS route */
> - rt_ifa_del(&ifm->sc_ifa, RTF_MPLS,
> - smplstosa(&ifm->sc_smpls));
> + mpls_ifa_del(&ifm->sc_ifa, &ifm->sc_smpls);
> }
> /* add new MPLS route */
> ifm->sc_smpls.smpls_label = shim.shim_label;
> - error = rt_ifa_add(&ifm->sc_ifa, RTF_MPLS|RTF_LOCAL,
> - smplstosa(&ifm->sc_smpls));
> + error = mpls_ifa_add(&ifm->sc_ifa, &ifm->sc_smpls);
> if (error) {
> ifm->sc_smpls.smpls_label = 0;
> break;
> @@ -348,10 +344,8 @@ mpe_ioctl(struct ifnet *ifp, u_long cmd,
> /* XXX does not make sense, the MPLS route is on rtable 0 */
> ifm = ifp->if_softc;
> if (ifr->ifr_rdomainid != ifp->if_rdomain) {
> - if (ifm->sc_smpls.smpls_label) {
> - rt_ifa_add(&ifm->sc_ifa, RTF_MPLS,
> - smplstosa(&ifm->sc_smpls));
> - }
> + if (ifm->sc_smpls.smpls_label)
> + mpls_ifa_add(&ifm->sc_ifa, &ifm->sc_smpls);
> }
> /* return with ENOTTY so that the parent handler finishes */
> return (ENOTTY);
> Index: net/if_mpw.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_mpw.c,v
> retrieving revision 1.31
> diff -u -p -r1.31 if_mpw.c
> --- net/if_mpw.c 30 Jan 2019 01:09:36 -0000 1.31
> +++ net/if_mpw.c 30 Jan 2019 01:40:47 -0000
> @@ -116,8 +116,7 @@ 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,
> - smplstosa(&sc->sc_smpls));
> + mpls_ifa_del(&sc->sc_ifa, &sc->sc_smpls);
> }
>
> ether_ifdetach(ifp);
> @@ -162,9 +161,8 @@ 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,
> - smplstosa(&sc->sc_smpls)) == 0)
> - sc->sc_smpls.smpls_label = 0;
> + mpls_ifa_del(&sc->sc_ifa, &sc->sc_smpls);
> + sc->sc_smpls.smpls_label = 0;
>
> memset(&sc->sc_rshim, 0, sizeof(sc->sc_rshim));
> memset(&sc->sc_nexthop, 0, sizeof(sc->sc_nexthop));
> @@ -191,12 +189,10 @@ 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,
> - smplstosa(&sc->sc_smpls));
> + mpls_ifa_del(&sc->sc_ifa, &sc->sc_smpls);
>
> sc->sc_smpls.smpls_label = imr.imr_lshim.shim_label;
> - error = rt_ifa_add(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL,
> - smplstosa(&sc->sc_smpls));
> + error = mpls_ifa_add(&sc->sc_ifa, &sc->sc_smpls);
> if (error != 0) {
> sc->sc_smpls.smpls_label = 0;
> break;
> Index: netmpls/mpls.h
> ===================================================================
> RCS file: /cvs/src/sys/netmpls/mpls.h,v
> retrieving revision 1.42
> diff -u -p -r1.42 mpls.h
> --- netmpls/mpls.h 30 Jan 2019 01:01:01 -0000 1.42
> +++ netmpls/mpls.h 30 Jan 2019 01:40:47 -0000
> @@ -177,4 +177,7 @@ int mpls_output(struct ifnet *, struct
> struct rtentry *);
> void mpls_input(struct ifnet *, struct mbuf *);
>
> +int mpls_ifa_add(struct ifaddr *, struct sockaddr_mpls *);
> +int mpls_ifa_del(struct ifaddr *, struct sockaddr_mpls *);
> +
> #endif /* _KERNEL */
> Index: netmpls/mpls_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netmpls/mpls_input.c,v
> retrieving revision 1.74
> diff -u -p -r1.74 mpls_input.c
> --- netmpls/mpls_input.c 29 Jan 2019 23:36:35 -0000 1.74
> +++ netmpls/mpls_input.c 30 Jan 2019 01:40:47 -0000
> @@ -299,6 +299,66 @@ mpls_input_local(struct rtentry *rt, str
> if_put(ifp);
> }
>
> +int
> +mpls_ifa_add(struct ifaddr *ifa, struct sockaddr_mpls *dst)
> +{
> + struct rt_addrinfo info;
> + struct sockaddr_rtlabel sa_rl;
> + unsigned int rtableid = 0;
> + struct ifnet *ifp = ifa->ifa_ifp;
> + struct rtentry *rt;
> + int error;
> +
> + memset(&info, 0, sizeof(info));
> + info.rti_ifa = ifa;
> + info.rti_flags = RTF_LOCAL | RTF_MPLS;
> + info.rti_info[RTAX_DST] = smplstosa(dst);
> + info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
> + info.rti_info[RTAX_LABEL] = rtlabel_id2sa(ifp->if_rtlabelid, &sa_rl);
> + info.rti_mpls = MPLS_OP_POP;
> +
> + error = rtrequest(RTM_ADD, &info, RTP_LOCAL, &rt, rtableid);
> + if (error == 0) {
> + /*
> + * XXX nothing in userland seems to care about MPLS routes,
> + * so don't bother sending messages like rt_ifa_add does.
> + */
> + rtfree(rt);
> + }
> +
> + return (error);
> +}
> +
> +int
> +mpls_ifa_del(struct ifaddr *ifa, struct sockaddr_mpls *dst)
> +{
> + struct rt_addrinfo info;
> + struct sockaddr_rtlabel sa_rl;
> + unsigned int rtableid = 0;
> + struct ifnet *ifp = ifa->ifa_ifp;
> + struct rtentry *rt;
> + int error;
> +
> + memset(&info, 0, sizeof(info));
> + info.rti_ifa = ifa;
> + info.rti_flags = RTF_LOCAL | RTF_MPLS;
> + info.rti_info[RTAX_DST] = smplstosa(dst);
> + info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
> + info.rti_info[RTAX_LABEL] = rtlabel_id2sa(ifp->if_rtlabelid, &sa_rl);
> + info.rti_mpls = MPLS_OP_POP;
> +
> + error = rtrequest_delete(&info, RTP_LOCAL, ifp, &rt, rtableid);
> + if (error == 0) {
> + /*
> + * XXX nothing in userland seems to care about MPLS routes,
> + * so don't bother sending messages like rt_ifa_del does.
> + */
> + rtfree(rt);
> + }
> +
> + return (error);
> +}
> +
> struct mbuf *
> mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl)
> {