From owner-freebsd-bugs@FreeBSD.ORG Thu Jun 20 05:20:01 2013 Return-Path: Delivered-To: freebsd-bugs@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 6B02A9D3 for ; Thu, 20 Jun 2013 05:20:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 4CA4A19FE for ; Thu, 20 Jun 2013 05:20:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.7/8.14.7) with ESMTP id r5K5K186090953 for ; Thu, 20 Jun 2013 05:20:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.7/8.14.7/Submit) id r5K5K1VZ090952; Thu, 20 Jun 2013 05:20:01 GMT (envelope-from gnats) Date: Thu, 20 Jun 2013 05:20:01 GMT Message-Id: <201306200520.r5K5K1VZ090952@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: "Henning Matyschok" Subject: Re: kern/179473: Source code contribution of implementation about virtual ethernet interface X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: Henning Matyschok List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 Jun 2013 05:20:01 -0000 The following reply was made to PR kern/179473; it has been noted by GNATS. From: "Henning Matyschok" To: bug-followup@freebsd.org, henning.matyschok@stud.fh-flensburg.de Cc: Subject: Re: kern/179473: Source code contribution of implementation about virtual ethernet interface Date: Thu, 20 Jun 2013 05:21:20 -0000 ------------PSPBI3LkwZ7miaxwqpbSiu Content-Type: text/plain; charset=us-ascii; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit I apologize for my inexperiences of using the pr system and wrong spelling. After code review, an hour ago, I've realized that there exists a similar implementation of a virtual Ethernet interface by OpenBSD project since 2009. In avoidance of misunderstoodings, I've change namespace of source code entirely and added copyright information on top of file. ------------PSPBI3LkwZ7miaxwqpbSiu Content-Disposition: attachment; filename=if_vether.c.txt Content-Type: text/plain; name="if_vether.c.txt" Content-Transfer-Encoding: 7bit /*- * Copyright (c) 2013 Henning Matyschok * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * Copyright (c) 2009 Theo de Raadt * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const uint8_t ether_bcast_lla[ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* * Declaration of reduced struct bridge_softc is needed to identify * bridge(4) describing ifnet structure on the fly, when frame * originates from ng_ether(4). * * See net/if_bridge.c and net/if_var.h for further * details. */ struct bridge_softc { struct ifnet *sc_ifp; }; #define VETHERNAME "vether" struct vether_softc { struct ifnet *sc_ifp; /* It will be a network interface. */ LIST_ENTRY(vether_softc) vether_list; struct mtx sc_mtx; #define VETHER_LOCK_INIT(sc) mtx_init(&(sc)->sc_mtx, "vether softc", \ NULL, MTX_DEF) #define VETHER_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx) #define VETHER_LOCK(sc) mtx_lock(&(sc)->sc_mtx) #define VETHER_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) #define VETHER_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) /* Fake information about used transmission media. */ struct ifmedia sc_ifm; int sc_status; }; static LIST_HEAD(, vether_softc) vether_list; static struct mtx vether_mtx; static MALLOC_DEFINE(M_VETHER, VETHERNAME, "Virtual ethernet interface"); /* Ifc cloner specific subr. */ static int vether_clone_create(struct if_clone *, int, caddr_t); static void vether_clone_destroy(struct ifnet *); IFC_SIMPLE_DECLARE(vether, 0); /* Interface specific methods. */ static void vether_init(void *); static void vether_start(struct ifnet *); static void vether_stop(struct ifnet *, int); static int vether_media_change(struct ifnet *); static void vether_media_status(struct ifnet *, struct ifmediareq *); static int vether_ioctl(struct ifnet *, u_long, caddr_t); /* * Module event handler. */ static int vether_mod_event(module_t mod, int event, void *data) { int error = 0; switch (event) { case MOD_LOAD: mtx_init(&vether_mtx, "if_vether", NULL, MTX_DEF); if_clone_attach(&vether_cloner); break; case MOD_UNLOAD: if_clone_detach(&vether_cloner); mtx_destroy(&vether_mtx); break; default: error = EOPNOTSUPP; } return(error); } static moduledata_t vether_mod = { "if_vether", vether_mod_event, 0 }; DECLARE_MODULE(if_vether, vether_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); /* * Instantiates vether interface. */ static int vether_clone_create(struct if_clone *ifc, int unit, caddr_t data) { struct vether_softc *sc; struct ifnet *ifp; uint32_t randval; uint8_t lla[ETHER_ADDR_LEN]; sc = malloc(sizeof(struct vether_softc), M_VETHER, M_WAITOK|M_ZERO); ifp = sc->sc_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { free(sc, M_VETHER); return(ENOSPC); } VETHER_LOCK_INIT(sc); ifp->if_softc = sc; if_initname(ifp, ifc->ifc_name, unit); /* Generates lla with randomized value. */ lla[0] = 0x0; randval = arc4random(); memcpy(&lla[1], &randval, sizeof(uint32_t)); lla[5] = (uint8_t)unit; /* Interface major number */ ether_ifattach(ifp, lla); ifp->if_init = vether_init; ifp->if_ioctl = vether_ioctl; ifp->if_start = vether_start; ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_JUMBO_MTU; ifp->if_capenable = IFCAP_VLAN_MTU | IFCAP_JUMBO_MTU; ifp->if_flags = (IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST); ifp->if_snd.ifq_maxlen = ifqmaxlen; ifmedia_init(&sc->sc_ifm, 0, vether_media_change, vether_media_status); ifmedia_add(&sc->sc_ifm, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_ifm, IFM_ETHER | IFM_AUTO); sc->sc_status = IFM_AVALID; ifp->if_baudrate = 0; mtx_lock(&vether_mtx); LIST_INSERT_HEAD(&vether_list, sc, vether_list); mtx_unlock(&vether_mtx); ifp->if_drv_flags |= IFF_DRV_RUNNING; return(0); } /* * Destroys vether interface. */ static void vether_clone_destroy(struct ifnet *ifp) { struct vether_softc *sc; sc = ifp->if_softc; mtx_lock(&vether_mtx); vether_stop(ifp, 1); ifp->if_flags &= ~IFF_UP; LIST_REMOVE(sc, vether_list); ether_ifdetach(ifp); VETHER_LOCK_DESTROY(sc); mtx_unlock(&vether_mtx); free(sc, M_VETHER); } /* * Initializes vether interface. */ static void vether_init(void *xsc) { struct vether_softc *sc; struct ifnet *ifp; sc = (struct vether_softc *)xsc; ifp = sc->sc_ifp; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { return; } VETHER_LOCK(sc); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; VETHER_UNLOCK(sc); } /* * Stops vether interface. */ static void vether_stop(struct ifnet *ifp, int disable) { struct vether_softc *sc; sc = ifp->if_softc; VETHER_LOCK_ASSERT(sc); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { return; } ifp->if_drv_flags &= ~IFF_DRV_RUNNING; } /* * Dispatches transmissions of queued frames to bridge(4) or to * itself when bridge(4) forwarded frames to this interface. */ static void vether_start(struct ifnet *ifp) { struct mbuf *m; struct bridge_softc *sc; ifp->if_drv_flags |= IFF_DRV_OACTIVE; for (;;) { IFQ_DEQUEUE(&ifp->if_snd, m); if (m == NULL) { break; } if (ifp->if_bridge) { sc = ifp->if_bridge; if (m->m_pkthdr.rcvif == NULL) { m->m_pkthdr.rcvif = ifp; ETHER_BPF_MTAP(ifp, m); ifp->if_obytes += m->m_pkthdr.len; ifp->if_opackets++; (sc->sc_ifp->if_transmit)(sc->sc_ifp, m); } else if (m->m_pkthdr.rcvif == ifp) { m_freem(m); } else { (ifp->if_input)(ifp, m); } } else { m_freem(m); } } ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } static int vether_media_change(struct ifnet *ifp) { return(0); } static void vether_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) { ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; ifmr->ifm_active = IFM_ETHER | IFM_AUTO; } /* * Handles ioctl requests. Media types can't changed, * this is a virtual ethernet interface. */ static int vether_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct vether_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; int error = 0; VETHER_LOCK(sc); switch (cmd) { case SIOCSIFMTU: if (ifr->ifr_mtu > ETHER_MAX_LEN_JUMBO) { error = EINVAL; } else { ifp->if_mtu = ifr->ifr_mtu; } break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifm, cmd); break; case SIOCSIFFLAGS: case SIOCADDMULTI: case SIOCDELMULTI: break; case SIOCSIFPHYS: error = EOPNOTSUPP; break; default: error = ether_ioctl(ifp, cmd, data); break; } VETHER_UNLOCK(sc); return(error); } ------------PSPBI3LkwZ7miaxwqpbSiu--