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. 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 */