The following reply was made to PR kern/179473; it has been noted by GNATS.

From: "Henning Matyschok" <henning.matysc...@stud.fh-flensburg.de>
To: bug-follo...@freebsd.org, henning.matysc...@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 <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/libkern.h>
 #include <sys/socket.h> 
 #include <sys/sockio.h>
  
 #include <net/if.h>
 #include <net/if_clone.h>
 #include <net/if_media.h>
 #include <net/if_types.h>
 #include <net/netisr.h>
 #include <net/if_var.h>
 #include <net/ethernet.h>
 #include <net/if_bridgevar.h>
 #include <net/if_vlan_var.h>
 #include <net/if_dl.h>
 #include <net/if_arp.h>
 #include <net/bpf.h>
  
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 #include <netinet/ip_carp.h>
  
 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--
 
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to