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

Reply via email to