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