On Fri, Oct 23, 2015 at 01:21:05PM +1000, David Gwynne wrote: > > > On 23 Oct 2015, at 09:00, Reyk Floeter <r...@openbsd.org> wrote: > > > > Hi, > > > > this diff allows to interconnect routing domains. > > > > It is very useful to route traffic from one routing domain to another, > > without using the pf "rtable" hack (tested in production for a long > > time). > > > > eg., > > # ifconfig vether0 10.0.1.1/24 > > # ifconfig vether1 rdomain 1 10.0.1.2/24 > > # ping 10.1.1.2 > > # route -T 1 add default 10.0.1.1 > > # ifconfig bridge0 add vether0 add em0 > > > > for hacking/testing, you can do thing like: > > # dhcpd vether0 > > # dhclient vether1 > > > > It has been discussed in much detail if this is possible with > > bridge(4). It is not. The bridge is not designed for it and explain > > on request. > > the diff implements a crossover option, but the example above doesnt use > them. does that mean you can use a bridge to build crossovers without the > extra code, or the example is wrong? >
The example is missing the relevant bit: # ifconfig vether0 10.0.1.1/24 # ifconfig vether1 rdomain 1 10.0.1.2/24 # ifconfig vether1 crossover vether0 You can use a bridge to connect multiple rdomains by attaching multiple virtual ethernet ports to it. The "crossover" is the cable, the connection between rdomains; naming is a pure bikeshed - we could also call it "cable", "connect", "plumb" or whatever. For example, if rdomain 0 is the "gateway" to the outside or the service network: bridge0 em0 vether0 rdomain 0 -> vether10 rdomain 1 vether1 rdomain 0 -> vether11 rdomain 2 vether2 rdomain 0 -> vether12 rdomain 3 Reyk > > > > OK? > > > > Reyk > > > > Index: sbin/ifconfig/ifconfig.8 > > =================================================================== > > RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v > > retrieving revision 1.257 > > diff -u -p -u -p -r1.257 ifconfig.8 > > --- sbin/ifconfig/ifconfig.8 6 Oct 2015 17:23:21 -0000 1.257 > > +++ sbin/ifconfig/ifconfig.8 22 Oct 2015 22:33:40 -0000 > > @@ -1560,6 +1560,33 @@ The accepted size of the number depends > > it is a 24-bit number for > > .Xr vxlan 4 . > > .El > > +.\" VETHER > > +.Sh VETHER > > +.nr nS 1 > > +.Bk -words > > +.Nm ifconfig > > +.Ar vether-interface > > +.Op Oo Fl Oc Ns Cm crossover Ar interface > > +.Ek > > +.nr nS 0 > > +.Pp > > +The following options are available for a > > +.Xr vether 4 > > +interface: > > +.Bl -tag -width Ds > > +.It Cm crossover Ar interface > > +Create a virtual crossover link with another > > +.Xr vether 4 > > +interface. > > +Any outgoing packets from the > > +.Ar vether-interface > > +will be received by the crossover > > +.Ar interface > > +and vice versa. > > +This link allows to interconnect two routing domains locally. > > +.It Fl crossover > > +If configured, disconnect the virtual crossover link. > > +.El > > .\" VLAN > > .Sh VLAN > > .nr nS 1 > > Index: sbin/ifconfig/ifconfig.c > > =================================================================== > > RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v > > retrieving revision 1.302 > > diff -u -p -u -p -r1.302 ifconfig.c > > --- sbin/ifconfig/ifconfig.c 3 Oct 2015 10:44:23 -0000 1.302 > > +++ sbin/ifconfig/ifconfig.c 22 Oct 2015 22:33:41 -0000 > > @@ -275,6 +275,8 @@ void setifipdst(const char *, int); > > void setifdesc(const char *, int); > > void unsetifdesc(const char *, int); > > void printifhwfeatures(const char *, int); > > +void setxover(const char *, int); > > +void unsetxover(const char *, int); > > #else > > void setignore(const char *, int); > > #endif > > @@ -490,6 +492,8 @@ const struct cmd { > > { "-descr", 1, 0, unsetifdesc }, > > { "wol", IFXF_WOL, 0, setifxflags }, > > { "-wol", -IFXF_WOL, 0, setifxflags }, > > + { "crossover", NEXTARG, 0, setxover }, > > + { "-crossover", 1, 0, unsetxover }, > > #else /* SMALL */ > > { "powersave", NEXTARG0, 0, setignore }, > > { "priority", NEXTARG, 0, setignore }, > > @@ -2917,6 +2921,7 @@ status(int link, struct sockaddr_dl *sdl > > struct ifreq ifrdesc; > > struct ifkalivereq ikardesc; > > char ifdescr[IFDESCRSIZE]; > > + char ifname[IF_NAMESIZE]; > > #endif > > uint64_t *media_list; > > int i; > > @@ -2955,6 +2960,9 @@ status(int link, struct sockaddr_dl *sdl > > (ikardesc.ikar_timeo != 0 || ikardesc.ikar_cnt != 0)) > > printf("\tkeepalive: timeout %d count %d\n", > > ikardesc.ikar_timeo, ikardesc.ikar_cnt); > > + if (ioctl(s, SIOCGXOVER, &ifrdesc) == 0 && ifrdesc.ifr_index != 0 && > > + if_indextoname(ifrdesc.ifr_index, ifname) != NULL) > > + printf("\tcrossover: %s\n", ifname); > > #endif > > vlan_status(); > > #ifndef SMALL > > @@ -5199,6 +5207,29 @@ setinstance(const char *id, int param) > > ifr.ifr_rdomainid = rdomainid; > > if (ioctl(s, SIOCSIFRDOMAIN, (caddr_t)&ifr) < 0) > > warn("SIOCSIFRDOMAIN"); > > +} > > +#endif > > + > > +#ifndef SMALL > > +void > > +setxover(const char *val, int d) > > +{ > > + strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); > > + if ((ifr.ifr_index = if_nametoindex(val)) == 0) { > > + errno = ENOENT; > > + err(1, "crossover %s", val); > > + } > > + if (ioctl(s, SIOCSXOVER, (caddr_t)&ifr) < 0) > > + warn("SIOCSXOVER"); > > +} > > + > > +void > > +unsetxover(const char *val, int d) > > +{ > > + ifr.ifr_index = 0; > > + strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); > > + if (ioctl(s, SIOCSXOVER, (caddr_t)&ifr) < 0) > > + warn("SIOCSXOVER"); > > } > > #endif > > > > Index: sys/net/if.c > > =================================================================== > > RCS file: /cvs/src/sys/net/if.c,v > > retrieving revision 1.391 > > diff -u -p -u -p -r1.391 if.c > > --- sys/net/if.c 22 Oct 2015 15:37:47 -0000 1.391 > > +++ sys/net/if.c 22 Oct 2015 22:33:42 -0000 > > @@ -1794,6 +1794,7 @@ ifioctl(struct socket *so, u_long cmd, c > > case SIOCDELMULTI: > > case SIOCSIFMEDIA: > > case SIOCSVNETID: > > + case SIOCSXOVER: > > if ((error = suser(p, 0)) != 0) > > return (error); > > /* FALLTHROUGH */ > > @@ -1804,6 +1805,7 @@ ifioctl(struct socket *so, u_long cmd, c > > case SIOCGLIFPHYTTL: > > case SIOCGIFMEDIA: > > case SIOCGVNETID: > > + case SIOCGXOVER: > > if (ifp->if_ioctl == 0) > > return (EOPNOTSUPP); > > error = (*ifp->if_ioctl)(ifp, cmd, data); > > Index: sys/net/if.h > > =================================================================== > > RCS file: /cvs/src/sys/net/if.h,v > > retrieving revision 1.169 > > diff -u -p -u -p -r1.169 if.h > > --- sys/net/if.h 5 Oct 2015 15:19:29 -0000 1.169 > > +++ sys/net/if.h 22 Oct 2015 22:33:42 -0000 > > @@ -356,6 +356,7 @@ struct ifreq { > > int ifru_metric; > > uint64_t ifru_media; > > caddr_t ifru_data; > > + unsigned int ifru_index; > > } ifr_ifru; > > #define ifr_addr ifr_ifru.ifru_addr /* address */ > > #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p > > link */ > > @@ -369,6 +370,7 @@ struct ifreq { > > #define ifr_vnetid ifr_ifru.ifru_metric /* Virtual Net Id (overload) */ > > #define ifr_ttl ifr_ifru.ifru_metric /* tunnel TTL > > (overload) */ > > #define ifr_data ifr_ifru.ifru_data /* for use by interface > > */ > > +#define ifr_index ifr_ifru.ifru_index /* interface index */ > > }; > > > > struct ifaliasreq { > > Index: sys/net/if_var.h > > =================================================================== > > RCS file: /cvs/src/sys/net/if_var.h,v > > retrieving revision 1.48 > > diff -u -p -u -p -r1.48 if_var.h > > --- sys/net/if_var.h 12 Oct 2015 13:17:58 -0000 1.48 > > +++ sys/net/if_var.h 22 Oct 2015 22:33:42 -0000 > > @@ -431,6 +431,9 @@ void if_clone_detach(struct if_clone *); > > int if_clone_create(const char *); > > int if_clone_destroy(const char *); > > > > +struct if_clone * > > + if_clone_lookup(const char *, int *); > > + > > int sysctl_mq(int *, u_int, void *, size_t *, void *, size_t, > > struct mbuf_queue *); > > > > Index: sys/net/if_vether.c > > =================================================================== > > RCS file: /cvs/src/sys/net/if_vether.c,v > > retrieving revision 1.24 > > diff -u -p -u -p -r1.24 if_vether.c > > --- sys/net/if_vether.c 23 May 2015 08:31:05 -0000 1.24 > > +++ sys/net/if_vether.c 22 Oct 2015 22:33:42 -0000 > > @@ -45,6 +45,7 @@ void vether_media_status(struct ifnet *, > > struct vether_softc { > > struct arpcom sc_ac; > > struct ifmedia sc_media; > > + unsigned int sc_crossover; > > }; > > > > struct if_clone vether_cloner = > > @@ -106,11 +107,20 @@ int > > vether_clone_destroy(struct ifnet *ifp) > > { > > struct vether_softc *sc = ifp->if_softc; > > + struct ifnet *dstifp; > > + struct vether_softc *dstsc = ifp->if_softc; > > + > > + if ((dstifp = if_get(sc->sc_crossover)) != NULL) { > > + dstsc = dstifp->if_softc; > > + dstsc->sc_crossover = 0; > > + if_put(dstifp); > > + } > > > > ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); > > ether_ifdetach(ifp); > > if_detach(ifp); > > free(sc, M_DEVBUF, sizeof(*sc)); > > + > > return (0); > > } > > > > @@ -121,12 +131,17 @@ vether_clone_destroy(struct ifnet *ifp) > > void > > vetherstart(struct ifnet *ifp) > > { > > + struct vether_softc *sc = (struct vether_softc *)ifp->if_softc; > > + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); > > + struct ifnet *dstifp; > > struct mbuf *m; > > > > + dstifp = if_get(sc->sc_crossover); > > + > > for (;;) { > > IFQ_DEQUEUE(&ifp->if_snd, m); > > if (m == NULL) > > - return; > > + break; > > > > #if NBPFILTER > 0 > > if (ifp->if_bpf) > > @@ -134,7 +149,15 @@ vetherstart(struct ifnet *ifp) > > #endif /* NBPFILTER > 0 */ > > > > ifp->if_opackets++; > > - m_freem(m); > > + if (dstifp != NULL) > > + ml_enqueue(&ml, m); > > + else > > + m_freem(m); > > + } > > + > > + if (dstifp != NULL) { > > + if_input(dstifp, &ml); > > + if_put(dstifp); > > } > > } > > > > @@ -145,7 +168,10 @@ vetherioctl(struct ifnet *ifp, u_long cm > > struct vether_softc *sc = (struct vether_softc *)ifp->if_softc; > > struct ifaddr *ifa = (struct ifaddr *)data; > > struct ifreq *ifr = (struct ifreq *)data; > > - int error = 0, link_state; > > + struct if_clone *ifc; > > + struct vether_softc *dstsc = ifp->if_softc; > > + struct ifnet *dstifp; > > + int error = 0, link_state, unit; > > > > switch (cmd) { > > case SIOCSIFADDR: > > @@ -175,6 +201,45 @@ vetherioctl(struct ifnet *ifp, u_long cm > > case SIOCGIFMEDIA: > > case SIOCSIFMEDIA: > > error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); > > + break; > > + > > + case SIOCSXOVER: > > + /* First disconnect the connected interface */ > > + if ((dstifp = if_get(sc->sc_crossover)) != NULL) { > > + dstsc = dstifp->if_softc; > > + dstsc->sc_crossover = 0; > > + if_put(dstifp); > > + dstifp = NULL; > > + } > > + > > + /* Now disconnect the local interface */ > > + if (ifr->ifr_index == 0) { > > + sc->sc_crossover = 0; > > + break; > > + } > > + > > + /* And find the new interface */ > > + if ((dstifp = if_get(ifr->ifr_index)) == NULL) { > > + error = ENOENT; > > + break; > > + } > > + > > + /* Only allow vether(4) interfaces for the crossover */ > > + if ((ifc = if_clone_lookup(dstifp->if_xname, &unit)) == NULL || > > + strcmp("vether", ifc->ifc_name) != 0) { > > + if_put(dstifp); > > + error = ENODEV; > > + break; > > + } > > + > > + sc->sc_crossover = ifr->ifr_index; > > + dstsc = dstifp->if_softc; > > + dstsc->sc_crossover = ifp->if_index; > > + if_put(dstifp); > > + break; > > + > > + case SIOCGXOVER: > > + ifr->ifr_index = sc->sc_crossover; > > break; > > > > default: > > Index: sys/sys/sockio.h > > =================================================================== > > RCS file: /cvs/src/sys/sys/sockio.h,v > > retrieving revision 1.60 > > diff -u -p -u -p -r1.60 sockio.h > > --- sys/sys/sockio.h 11 Sep 2015 13:02:28 -0000 1.60 > > +++ sys/sys/sockio.h 22 Oct 2015 22:33:42 -0000 > > @@ -194,6 +194,9 @@ > > #define SIOCSETMPWCFG _IOW('i', 173, struct ifreq) /* set mpw config > > */ > > #define SIOCGETMPWCFG _IOWR('i', 174, struct ifreq) /* get mpw config > > */ > > > > +#define SIOCSXOVER _IOW('i', 175, struct ifreq) /* set crossover if */ > > +#define SIOCGXOVER _IOWR('i', 176, struct ifreq) /* get crossover if */ > > + > > #define SIOCSVH _IOWR('i', 245, struct ifreq) /* set carp > > param */ > > #define SIOCGVH _IOWR('i', 246, struct ifreq) /* get carp > > param */ > > > > > --