tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
vether(4)
Hi List!
There was some discussion recently about introducing vether(4) in a
thread about bridging here:
http://mail-index.netbsd.org/tech-net/2016/02/10/msg005588.html
Attached is a patch which ports the OpenBSD vether(4) driver to NetBSD.
It seems to function well as an endpoint to a bridge(4) interface and is
a lot simpler than tap(4).
Commentary welcome.
Would also welcome some discussion on extending vether(4) to allow it to
be paired (like a crossover cable) to another vether or to just import
pair(4) (again from OpenBSD). The argument for extending vether is that
both code bases are very similar.
I'm hopeful that paired vether will allow me to run a DHCP server on one
vether and a DHCP client on another and they talk to each other, as they
don't over a bridge using either vether or tap(4).
Roy
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.1154
diff -u -r1.1154 files
--- sys/conf/files 12 Apr 2016 11:51:08 -0000 1.1154
+++ sys/conf/files 20 Apr 2016 20:23:20 -0000
@@ -1410,6 +1410,7 @@
defpseudodev tap: ifnet, ether, arp
defpseudo carp: ifnet, ether, arp
defpseudodev etherip: ifnet, ether, arp
+defpseudo vether: ifnet, ether
defpseudo sequencer
defpseudo clockctl
Index: sys/net/files.net
===================================================================
RCS file: /cvsroot/src/sys/net/files.net,v
retrieving revision 1.9
diff -u -r1.9 files.net
--- sys/net/files.net 5 Apr 2016 22:51:01 -0000 1.9
+++ sys/net/files.net 20 Apr 2016 20:23:20 -0000
@@ -35,6 +35,7 @@
file net/if_tokensubr.c token needs-flag
file net/if_tap.c tap
file net/if_tun.c tun
+file net/if_vether.c vether
file net/if_vlan.c vlan needs-flag
file net/if_pppoe.c pppoe needs-flag
file net/pfil.c net
Index: sys/net/if_vether.c
===================================================================
RCS file: sys/net/if_vether.c
diff -N sys/net/if_vether.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/net/if_vether.c 20 Apr 2016 20:23:20 -0000
@@ -0,0 +1,188 @@
+/* $NetBSD: $ */
+/* $OpenBSD: if_vether.c,v 1.27 2016/04/13 11:41:15 mpi Exp $ */
+
+/*
+ * Copyright (c) 2009 Theo de Raadt
+ * Copyright (c) 2016 Roy Marples
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: $");
+
+#include <sys/cprng.h>
+#include <sys/kmem.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+#include <net/bpf.h>
+
+void vetherattach(int);
+static int vether_ioctl(struct ifnet *, u_long, void *);
+static void vether_start(struct ifnet *);
+static int vether_clone_create(struct if_clone *, int);
+static int vether_clone_destroy(struct ifnet *);
+static int vether_media_change(struct ifnet *);
+static void vether_media_status(struct ifnet *, struct ifmediareq *);
+
+static void vether_stop(struct ifnet *, int);
+static int vether_init(struct ifnet *);
+
+struct vether_softc {
+ struct ethercom sc_ec;
+ struct ifmedia sc_media;
+};
+
+struct if_clone vether_cloner =
+ IF_CLONE_INITIALIZER("vether", vether_clone_create, vether_clone_destroy);
+
+static int
+vether_media_change(struct ifnet *ifp)
+{
+
+ return (0);
+}
+
+static void
+vether_media_status(struct ifnet *ifp, struct ifmediareq *imr)
+{
+
+ imr->ifm_active = IFM_ETHER | IFM_AUTO;
+ imr->ifm_status = IFM_AVALID;
+ if (ifp->if_flags & IFF_RUNNING)
+ imr->ifm_status |= IFM_ACTIVE;
+}
+
+void
+vetherattach(int nvether)
+{
+
+ if_clone_attach(&vether_cloner);
+}
+
+static int
+vether_clone_create(struct if_clone *ifc, int unit)
+{
+ struct ifnet *ifp;
+ struct vether_softc *sc;
+ uint8_t enaddr[ETHER_ADDR_LEN] =
+ { 0xf2, 0x0b, 0xa4, 0xff, 0xff, 0xff };
+
+ sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
+ ifp = &sc->sc_ec.ec_if;
+ if_initname(ifp, ifc->ifc_name, unit);
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = vether_ioctl;
+ ifp->if_start = vether_start;
+ ifp->if_stop = vether_stop;
+ ifp->if_init = vether_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_READY(&ifp->if_snd);
+
+ sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;
+
+ ifmedia_init(&sc->sc_media, 0, vether_media_change,
+ vether_media_status);
+ ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
+
+ /*
+ * In order to obtain unique initial Ethernet address on a host,
+ * do some randomisation. It's not meant for anything but avoiding
+ * hard-coding an address.
+ */
+ cprng_fast(&enaddr[3], 3);
+
+ /* Those steps are mandatory for an Ethernet driver. */
+ if_initialize(ifp);
+ ether_ifattach(ifp, enaddr);
+ if_register(ifp);
+
+ return (0);
+}
+
+static int
+vether_clone_destroy(struct ifnet *ifp)
+{
+ struct vether_softc *sc = ifp->if_softc;
+
+ ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
+ ether_ifdetach(ifp);
+ if_detach(ifp);
+ kmem_free(sc, sizeof(*sc));
+ return (0);
+}
+
+static int
+vether_init(struct ifnet *ifp)
+{
+
+ ifp->if_flags |= IFF_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_UP);
+ vether_start(ifp);
+ return (0);
+}
+
+/*
+ * The bridge has magically already done all the work for us,
+ * and we only need to discard the packets.
+ */
+static void
+vether_start(struct ifnet *ifp)
+{
+ struct mbuf *m;
+
+ for (;;) {
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ return;
+ bpf_mtap(ifp, m);
+ ifp->if_opackets++;
+ m_freem(m);
+ }
+}
+
+static void
+vether_stop(struct ifnet *ifp, __unused int disable)
+{
+
+ ifp->if_flags &= ~IFF_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+;}
+
+static int
+vether_ioctl(struct ifnet *ifp, unsigned long cmd, void *data)
+{
+ struct vether_softc *sc = (struct vether_softc *)ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error = 0;
+
+ switch (cmd) {
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ break;
+
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
+ break;
+
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ }
+ return (error);
+}
Home |
Main Index |
Thread Index |
Old Index