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

-- 

Reply via email to