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