From owner-freebsd-bugs Sun May 17 11:04:15 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id LAA20373 for freebsd-bugs-outgoing; Sun, 17 May 1998 11:04:15 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id LAA20359 for ; Sun, 17 May 1998 11:04:11 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id LAA17063; Sun, 17 May 1998 11:00:02 -0700 (PDT) Received: from iconmail.bellatlantic.net (iconmail.bellatlantic.net [199.173.162.30]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id LAA20179 for ; Sun, 17 May 1998 11:02:50 -0700 (PDT) (envelope-from babkin@bellatlantic.net) Received: from bird (client-151-200-127-235.bellatlantic.net [151.200.127.235]) by iconmail.bellatlantic.net (IConNet Sendmail) with SMTP id OAA14915 for ; Sun, 17 May 1998 14:00:08 -0400 (EDT) Message-Id: <355F25FA.41C67EA6@bellatlantic.net> Date: Sun, 17 May 1998 14:01:30 -0400 From: Sergey Babkin To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: kern/6668: loe Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 6668 >Category: kern >Synopsis: New Loopback Ethernet driver >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun May 17 11:00:00 PDT 1998 >Last-Modified: >Originator: Sergey Babkin >Organization: None >Release: FreeBSD current >Environment: FreeBSD-current. Tested with 3.0-980222-SNAP. >Description: New Loopback Ethernet driver >How-To-Repeat: >Fix: *** /dev/MAKEDEV 1998/04/12 06:24:00 1.1 --- /dev/MAKEDEV 1998/05/17 17:04:44 *************** *** 1148,1153 **** --- 1148,1162 ---- umask 77 ;; + # use as MAKEDEV loeN to create N entries + loe*) + chr=98 + units=`expr $i : 'loe\(.*\)'` + eval `echo ${chr} ${units} | awk ' { c=$1; n=$2 } END { + for (i = 0; i < n; i++) + printf("mknod loe%d c %d %d;", i, c, i); }'` + ;; + *) echo $i - no such device name ;; *** /dev/null Sun May 17 12:41:06 1998 --- /sys/net/if_loe.c Sun May 17 13:01:08 1998 *************** *** 0 **** --- 1,774 ---- + /* + * Copyright (c) 1996-1998 + * Sergey A. Babkin. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Loopback Ethernet-simulating interface + * + * Sergey A. Babkin (sab123@hotmail.com, babkin@bellatlantic.net) + * + */ + + #include "loe.h" + #if NLOE > 0 + + #include "opt_atalk.h" + #include "opt_inet.h" + #include "opt_ipx.h" + #include "opt_devfs.h" + + #include "bpfilter.h" + + #include + #if defined(__FreeBSD__) + #include + #include + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + #include + #include + #if defined(__NetBSD__) + #include + #endif + + #include + #include + #include + + #ifdef INET + #include + #include + #include + #include + #include + #endif + + #ifdef IPX + #include + #include + #endif + + #ifdef NS + #include + #include + #endif + + #ifdef ISO + #include + #include + #endif + + #ifdef NETATALK + #include + #include + #endif NETATALK + + #if NBPFILTER > 0 + #include + #include + #endif + + #if defined(__FreeBSD__) + #include + #endif + + #ifdef DEVFS + #include + #endif + + /* Exported variables */ + u_long loe_unit; + + static int loeioctl __P((struct ifnet * ifp, int, caddr_t)); + static void loestart __P((struct ifnet *ifp)); + static void loeread __P((struct ifnet *ifp, struct mbuf *m)); + + static char driver_name[]="loe"; + + static d_open_t loecopen; + static d_close_t loecclose; + static d_read_t loecread; + static d_write_t loecwrite; + static d_poll_t loecpoll; + static d_ioctl_t loecioctl; + + #define CDEV_MAJOR 98 + static struct cdevsw loe_cdevsw = { + loecopen, loecclose, loecread, loecwrite, + loecioctl, nullstop, noreset, nodevtotty, + loecpoll, nommap, NULL, driver_name, + NULL, -1 + }; + + static void loeattach __P((void *)); + PSEUDO_SET(loeattach, if_loe); + + struct arpcom loearp[NLOE]; + + struct loeinfo { + struct ifqueue q; /* read queue */ + struct selinfo si; + char isopen; /* open flag */ + char wantread; + char wantselect; + char fionbio; + }; + + static struct loeinfo loeinfo[NLOE]; + + #define ETHER_ADDR_LEN 6 + #define ETHER_MAX_LEN 1518 + + static void + loeattach(dummy) + void *dummy; + { + struct ifaddr *ifa; + struct ifnet *ifp; + struct sockaddr_dl *sdl; + u_short *p; + int i; + static char ethaddr[ETHER_ADDR_LEN]={0,0,0,0,0,0}; + dev_t dev; + + for(i=0; iif_softc = &loearp[i]; + ifp->if_unit = i; + ifp->if_name = "loe"; + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_RUNNING ; + ifp->if_output = ether_output; + ifp->if_start = loestart; + ifp->if_ioctl = loeioctl; + ifp->if_watchdog = 0; + + /* fill the arpcom Ethernet address */ + ethaddr[5]=i+1; + bcopy(ethaddr, &loearp[i].ac_enaddr, ETHER_ADDR_LEN); + + if_attach(ifp); + ether_ifattach(ifp); + + #if NBPFILTER > 0 + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); + #endif + + dev=makedev(CDEV_MAJOR,0); + cdevsw_add(&dev, &loe_cdevsw, NULL); + #ifdef DEVFS + devfs_add_devswf(&sio_cdevsw, i, DV_CHR, UID_ROOT, GID_WHEEL, 0666, + "loe%d",i); + #endif + + loeinfo[i].isopen=0; + loeinfo[i].wantread=0; + loeinfo[i].wantselect=0; + loeinfo[i].fionbio=0; + loeinfo[i].q.ifq_head=NULL; + loeinfo[i].q.ifq_tail=NULL; + loeinfo[i].q.ifq_len=0; + loeinfo[i].q.ifq_maxlen=IFQ_MAXLEN; + loeinfo[i].q.ifq_drops=0; + } + } + + static void + loestart(ifp) + struct ifnet *ifp; + { + register struct mbuf *m; + struct ether_header *eh; + int unit = (struct arpcom *)ifp->if_softc - loearp; + int i; + int s; + + s=splimp(); + + /* Sneak a peek at the next packet */ + m = ifp->if_snd.ifq_head; + if (m == 0) { + splx(s); + return; + } + + IF_DEQUEUE(&ifp->if_snd, m); + eh = mtod(m, struct ether_header *); + + if(eh->ether_dhost[0] & 1) { /* broadcast or multicast, + Ethernet has reverse bit order */ + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: multicast %x:%x:%x:%x:%x:%x ->", unit, + eh->ether_shost[0], + eh->ether_shost[1], + eh->ether_shost[2], + eh->ether_shost[3], + eh->ether_shost[4], + eh->ether_shost[5]); + printf("%x:%x:%x:%x:%x:%x\n", + eh->ether_dhost[0], + eh->ether_dhost[1], + eh->ether_dhost[2], + eh->ether_dhost[3], + eh->ether_dhost[4], + eh->ether_dhost[5]); + } + + for(i=0; iif_flags & IFF_DEBUG) { + printf("loe%d: unicast %x:%x:%x:%x:%x:%x ->", unit, + eh->ether_shost[0], + eh->ether_shost[1], + eh->ether_shost[2], + eh->ether_shost[3], + eh->ether_shost[4], + eh->ether_shost[5]); + printf("%x:%x:%x:%x:%x:%x [%d]\n", + eh->ether_dhost[0], + eh->ether_dhost[1], + eh->ether_dhost[2], + eh->ether_dhost[3], + eh->ether_dhost[4], + eh->ether_dhost[5], + eh->ether_dhost[5]-1); + } + + if(eh->ether_dhost[5]>0 && eh->ether_dhost[5]<=NLOE) { /* our address */ + loeread(&loearp[eh->ether_dhost[5]-1].ac_if, m); + } + /* honor the promiscuous interfaces */ + for(i=0; iether_dhost[5]-1) { + #if NBPFILTER > 0 + /* normally interface goes promisc only for BPF */ + /* but passing packet honestly leads to duplicate */ + /* response from IP layer */ + if (loearp[i].ac_if.if_bpf) { + bpf_mtap(&loearp[i].ac_if, m); + } else { + loeread(&loearp[i].ac_if, m); + } + #else + loeread(&loearp[i].ac_if, m); + #endif + } + } + } + + m_freem(m); + splx(s); + } + + static void + loeread(ifp,m) + struct ifnet *ifp; + struct mbuf *m; + { + struct mbuf *n, *c; + struct mbuf *n2; + struct ether_header *eh; + int len; + int unit = (struct arpcom *)ifp->if_softc - loearp; + + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: receiving a packet, isopen=%d\n",unit, + loeinfo[unit].isopen); + } + + n=m_copypacket(m,M_NOWAIT); + + if(n==0) + return; + + eh = mtod(n, struct ether_header *); + + ++ifp->if_ipackets; + n->m_pkthdr.rcvif = ifp; + + /* compute the length */ + for(len=0, c=n; c!=0; c=c->m_next) + len += c->m_len; + + n->m_pkthdr.len = len; + + #if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_mtap(ifp, n); + } + #endif + + /* remove link-layer address */ + + n->m_pkthdr.len -= sizeof(struct ether_header); + n->m_len -= sizeof(struct ether_header); + n->m_data += sizeof(struct ether_header); + + ether_input(ifp, eh, n); + + if(loeinfo[unit].isopen) { + if(IF_QFULL(&loeinfo[unit].q)) + return; + n2=m_copypacket(m,M_NOWAIT); + if(n2==0) + return; + + IF_ENQUEUE(&loeinfo[unit].q, n2); + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: enqueued a packet\n",unit); + } + + if(loeinfo[unit].wantread) { + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: woke up a reader\n",unit); + } + loeinfo[unit].wantread=0; + wakeup(&loeinfo[unit].wantread); + } + if(loeinfo[unit].wantselect) { + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: woke up a select\n",unit); + } + loeinfo[unit].wantselect=0; + selwakeup(&loeinfo[unit].si); + } + } + } + + /* + * Look familiar? + */ + static int + loeioctl(ifp, cmd, data) + register struct ifnet *ifp; + int cmd; + caddr_t data; + { + register struct ifaddr *ifa = (struct ifaddr *) data; + struct ifreq *ifr = (struct ifreq *) data; + int s, error = 0; + int unit = ifp->if_unit; + struct arpcom *ac=ifp->if_softc; + + switch (cmd) { + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP | IFF_RUNNING; + + switch (ifa->ifa_addr->sa_family) { + #ifdef INET + case AF_INET: + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCSIFADDR INET\n",unit); + + arp_ifinit((struct arpcom *)ifp, ifa); + break; + #endif + #ifdef IPX + case AF_IPX: + { + register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); + + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCSIFADDR IPX\n",unit); + + if (ipx_nullhost(*ina)) + ina->x_host = + *(union ipx_host *) (ac->ac_enaddr); + else { + bcopy((caddr_t) ina->x_host.c_host, + (caddr_t) ac->ac_enaddr, + sizeof(ac->ac_enaddr)); + } + break; + } + #endif + #ifdef NS + case AF_NS: + { + register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); + + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCSIFADDR NS\n",unit); + + if (ns_nullhost(*ina)) + ina->x_host = + *(union ns_host *) (ac->ac_enaddr); + else { + bcopy((caddr_t) ina->x_host.c_host, + (caddr_t) ac->ac_enaddr, + sizeof(ac->ac_enaddr)); + } + break; + } + #endif + default: + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCSIFADDR 0x%x\n",unit, + ifa->ifa_addr->sa_family); + + break; + } + break; + case SIOCGIFADDR: + { + struct sockaddr *sa; + + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCGIFADDR\n",unit); + + sa = (struct sockaddr *) & ifr->ifr_data; + bcopy((caddr_t) ac->ac_enaddr, + (caddr_t) sa->sa_data, ETHER_ADDR_LEN); + } + break; + case SIOCSIFFLAGS: + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCSIFFLAGS\n",unit); + + break; + #ifdef notdef + case SIOCGHWADDR: + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCGHWADDR\n",unit); + + bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data, + sizeof(sc->sc_addr)); + break; + #endif + case SIOCSIFMTU: + + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl SIOCSIFMTU\n",unit); + + /* + * Set the interface MTU. + */ + if (ifr->ifr_mtu > ETHERMTU) { + error = EINVAL; + } else { + ifp->if_mtu = ifr->ifr_mtu; + } + break; + case SIOCADDMULTI: + case SIOCDELMULTI: + /* Now this driver has no support for programmable + * multicast filters. If some day it will gain this + * support this part of code must be extended. + */ + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl ADD/DELMULTI\n",unit); + + error=0; + break; + default: + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: ioctl 0x%x\n",unit,cmd); + + error = EINVAL; + } + + return (error); + } + + static int + loecopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; + { + int mynor=minor(dev); + struct ifnet *ifp; + + ifp = &loearp[mynor].ac_if; + + if(mynorif_flags & IFF_DEBUG) { + printf("loe%d: open, isopen=%d\n",mynor, loeinfo[mynor].isopen); + } + return 0; + } else { + return ENODEV; + } + } + + static int + loecclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; + { + struct mbuf *m; + int mynor=minor(dev); + struct ifnet *ifp; + int s; + + ifp = &loearp[mynor].ac_if; + + if(mynorif_flags & IFF_DEBUG) { + printf("loe%d: close, isopen=%d\n",mynor, loeinfo[mynor].isopen); + } + return 0; + } else { + return ENODEV; + } + } + + static int + loecread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; + { + struct mbuf *m, *n; + int mynor=minor(dev); + int s; + int error; + struct ifnet *ifp; + + ifp = &loearp[mynor].ac_if; + + #if 0 + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: read, isopen=%d\n",mynor, loeinfo[mynor].isopen); + } + #endif + + if(uio->uio_resid < ETHER_MAX_LEN) + return ENOSPC; + + s=splimp(); + while( loeinfo[mynor].q.ifq_head==0 ) { + if(loeinfo[mynor].fionbio) { + splx(s); + return EAGAIN; + } + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: sleeping on read\n",mynor); + } + loeinfo[mynor].wantread=1; + error=tsleep(&loeinfo[mynor].wantread, (PZERO+1)|PCATCH, "loecread", 0); + if(error) { + splx(s); + return EINTR; + } + } + + IF_DEQUEUE(&loeinfo[mynor].q, m); + + for(n=m, error=0; n!=0 && n->m_len!=0 && !error; n=n->m_next) { + error=uiomove(mtod(n, char *), n->m_len, uio); + } + + if(error) { + /* return mbuf back */ + IF_PREPEND(&loeinfo[mynor].q, m); + + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: error %d during reading %d bytes\n",mynor, + error, m->m_pkthdr.len); + } + splx(s); + return error; + } + #if 0 + if(ifp->if_flags & IFF_DEBUG) { + int c; + struct mbuf *mb; + + for(mb=mmbfree, c=0 ; mb!=0; mb=mb->m_next) + c++; + printf("loe%d: before freeing: %d mbufs free\n",mynor, + c); + for(mb=m, c=0 ; mb!=0; mb=mb->m_next) + c++; + printf("loe%d: before freeing: %d mbufs in packet being freed\n",mynor, + c); + } + #endif + m_freem(m); + #if 0 + if(ifp->if_flags & IFF_DEBUG) { + int c; + struct mbuf *mb; + + for(mb=mmbfree, c=0 ; mb!=0; mb=mb->m_next) + c++; + + printf("loe%d: after freeing: %d mbufs free\n",mynor, + c); + } + #endif + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: read a packet\n",mynor); + } + + splx(s); + return 0; + } + + static int + loecwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; + { + struct mbuf *m; + int mynor=minor(dev); + int s; + int error; + struct ifnet *ifp; + static char buf[ETHER_MAX_LEN]; + int len; + + ifp = &loearp[mynor].ac_if; + + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: write, isopen=%d\n",mynor, loeinfo[mynor].isopen); + } + + if( (len=uio->uio_resid) > ETHER_MAX_LEN) + return ENOSPC; + + s=splimp(); + while(( m=m_gethdr(M_WAIT, MT_HEADER) )==0) { + if(loeinfo[mynor].fionbio) { + splx(s); + return EAGAIN; + } + if(ifp->if_flags & IFF_DEBUG) { + printf("loe%d: waiting for mbuf\n",mynor); + } + error=tsleep(&lbolt, (PZERO+1)|PCATCH, "loeget", 0); + if(error) { + splx(s); + return EINTR; + } + } + + m->m_pkthdr.rcvif=0; + m->m_pkthdr.len=len; + error=uiomove(buf, len, uio); + + if(error) { + m_freem(m); + splx(s); + return error; + } + + m->m_len=min(MHLEN,len); /* prepare for m_copyback() */ + m_copyback(m, 0, len, buf); + + IF_ENQUEUE(&ifp->if_snd, m); + splx(s); + + loestart(ifp); + + return 0; + } + + static int + loecpoll(dev, events, p) + dev_t dev; + int events; + struct proc *p; + { + int mynor=minor(dev); + struct ifnet *ifp; + int revents=0; + + #define POLL_FREAD (POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND) + #define POLL_FWRITE (POLLOUT|POLLWRNORM|POLLWRBAND) + + ifp = &loearp[mynor].ac_if; + + if(events & POLL_FWRITE) + revents |= (events & POLL_FWRITE); + + if(events & POLL_FREAD) { + if(loeinfo[mynor].q.ifq_head!=0) { + return revents | (events & POLL_FREAD); + } else { + loeinfo[mynor].wantselect=1; + selrecord(p, &loeinfo[mynor].si); + } + } + return revents; + } + + static int + loecioctl(dev, cmd, arg, flag, p) + dev_t dev; + int cmd; + caddr_t arg; + int flag; + struct proc *p; + { + int mynor=minor(dev); + struct ifnet *ifp; + struct ifreq *ifr = (struct ifreq *) arg; + + ifp = &loearp[mynor].ac_if; + + switch(cmd) { + case FIONBIO: + loeinfo[mynor].fionbio=(int)arg; + break; + case FIOASYNC: + break; + case SIOCGIFADDR: + { + struct sockaddr *sa; + + if(ifp->if_flags & IFF_DEBUG) + printf("loe%d: character ioctl SIOCGIFADDR\n",mynor); + + sa = (struct sockaddr *) & ifr->ifr_data; + bcopy((caddr_t) loearp[mynor].ac_enaddr, + (caddr_t) sa->sa_data, ETHER_ADDR_LEN); + } + break; + default: + return ENODEV; + } + return 0; + } + + #endif /* NLOE > 0 */ *** /dev/null Sun May 17 12:41:06 1998 --- /usr/share/man/man4/loe.4 Sun May 17 13:39:47 1998 *************** *** 0 **** --- 1,70 ---- + .\" Copyright (c) 1983, 1991, 1993 + .\" The Regents of the University of California. 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. + .\" 3. All advertising materials mentioning features or use of this software + .\" must display the following acknowledgement: + .\" This product includes software developed by the University of + .\" California, Berkeley and its contributors. + .\" 4. Neither the name of the University nor the names of its contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + .\" + .\" @(#)lo.4 8.1 (Berkeley) 6/5/93 + .\" $Id: lo.4,v 1.5 1997/02/22 13:24:37 peter Exp $ + .\" + .Dd May 17, 1998 + .Dt LOE 4 + .Os FreeBSD + .Sh NAME + .Nm loe + .Nd software loopback network interface with Ethernet emulation + .Sh SYNOPSIS + .Sy pseudo-device loe N + .Sh DESCRIPTION + The + .Nm loe + interface is a software loopback mechanism which may be + used for network support in emulators, software testing, and/or local + communication. + All the configured interfaces are connected to the same virtual + Ethernet segment. For any use at least two interfaces must be + configured. + The loe driver has both network and character interfaces. The character + interface is intended to be used in emulators, the network interface + is intended to be used by the FreeBSD network protocols. The character + and network interfaces with the same number are connected to the same + virtual Ethernet card and must not be used both at the same time. + .Sh FILES + .Bl -tag -width /dev/loe? -compact + .It Pa /dev/loe? + character interfaces + .Sh SEE ALSO + .Xr lo 4 , + .Xr inet 4 , + .Xr intro 4 + .Sh HISTORY + The + .Nm loe + device suport appeared in the + .Nm pcemu 1.92 + PC emulator. *** /sys/conf/files 1998/04/19 12:28:44 1.1 --- /sys/conf/files 1998/04/28 13:24:24 *************** *** 203,208 **** --- 203,209 ---- net/if_disc.c optional disc net/if_ethersubr.c optional ether net/if_fddisubr.c optional fddi + net/if_loe.c optional loe net/if_loop.c optional loop net/if_media.c standard net/if_mib.c standard *** /sys/i386/conf/LINT 1998/05/17 17:46:03 1.1 --- /sys/i386/conf/LINT 1998/05/17 17:48:40 *************** *** 363,368 **** --- 363,370 ---- # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) + # The `loe' pseudodevice simulates a number of Ethernet interfaces + # connected to a common virtual network segment. # # The PPP_BSDCOMP option enables support for compress(1) style entire # packet compression, the PPP_DEFLATE is for zlib/gzip style compression. *************** *** 379,384 **** --- 381,387 ---- pseudo-device tun 1 #Tunnel driver (user process ppp(8)) pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol + pseudo-device loe 4 #Loopback Ethernet options PPP_BSDCOMP #PPP BSD-compress support options PPP_DEFLATE #PPP zlib/deflate/gzip support options PPP_FILTER #enable bpf filtering (needs bpfilter) >Audit-Trail: >Unformatted: X-send-pr-version: 3.2 To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message