> 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?

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