This is file vlan-2400test10vl14-mea3.diff This is somewhat improved edition from vlan-2400test10vl14-mea.diff at ftp://zmailer.org/linux/ directory. This is INCREMENTAL VLAN support patch over linux-2.4.0-test10 plus Ben Greear's vlan-2.4.diff. - Changes done to 3c59x.c driver (my test machine has these) are "a bit" shaky -- the change_mtu() function clearly needs to poke at the card at selected moments, but it is *VERY* timing sensitive! Doing it at system startup with present code may get the system up just fine, or it may start spewing lots and lots of network card diagnostics to the console. (Doing "ifconfig vlan0123 mtu 3000" at active traffic interface is presently surefire way to cause spewage.. Ball to driver specialists.) - this VLAN code is supported in module form, baseline system is touched as little as possible. - this VLAN code does support to fairly large extent separation of REAL link-layer hard-headers, and VLAN protocol header (VLAN is a protocol defined in IEEE 802 framework, after all), but still the are some corners where DIX a.k.a. ETHERNET-II is expected. Specifically TokenRing, FDDI and 802.3 SNAPs are not (yet) fully supported in transmit path ( at vlan_dev_hard_start_xmit() to be exact.) - Interface MTU setting is supported for VLANs, and if the underlying device supports change_mtu() also, then it too will be changed. See code for a TODO work item in that. (Note: Initial activation of devices doesn't do change_mtu() call, while it propably really *should* do that.) /Matti Aarnio diff -u -r linux-2400t10vl14/drivers/net/3c59x.c linux-2400t10vl14m/drivers/net/3c59x.c --- linux-2400t10vl14/drivers/net/3c59x.c Mon Oct 16 22:58:51 2000 +++ linux-2400t10vl14m/drivers/net/3c59x.c Sat Nov 4 00:33:32 2000 @@ -663,6 +663,7 @@ has_nway:1, open:1, must_free_region:1; /* Flag: if zero, Cardbus owns the I/O region */ + int pkt_buf_sz; /* MTU + 36 ??? (MAX_HEADER ?), plus alignment */ int drv_flags; u16 status_enable; u16 intr_enable; @@ -729,6 +730,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void vortex_tx_timeout(struct net_device *dev); static void acpi_set_WOL(struct net_device *dev); +static void wait_for_completion(struct net_device *, int); /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ /* Option count limit only -- unlimited interfaces are supported. */ @@ -777,6 +779,54 @@ } } +static int vortex_set_mtu(struct net_device *dev, int mtu) +{ + struct vortex_private *vp = dev->priv; + unsigned int old_mtu = dev->mtu; + + if (mtu < 68 || mtu > 4000) + return -EINVAL; /* FIXME: MODEL SPECIFIC LIMITATIONS ??? */ + + dev->mtu = mtu; + vp->pkt_buf_sz = mtu + 36; /* FIXME: What is this MAGIC 36 ??? */ + + /* Size transition under or above the magic 1500 byte marker. */ + + if ((old_mtu <= 1500 && mtu > 1500) || + (old_mtu > 1500 && mtu <= 1500)) { + + /* FIXME: IS THIS RACE SAFE ? DEADLOCK SAFE ? */ + + unsigned long flags; + long ioaddr = dev->base_addr; + unsigned int config; + + local_irq_save(flags); + + EL3WINDOW(3); + + /* Set the full-duplex bit. */ + config = (((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | + ((dev->mtu > 1500) ? 0x40 : 0) | + ((vp->full_duplex && vp->flow_ctrl && + vp->partner_flow_ctrl) ? 0x100 : 0)); + outw(config, ioaddr + Wn3_MAC_Ctrl); + + wait_for_completion(dev, TxReset); + wait_for_completion(dev, RxReset); + + outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); + + local_irq_restore(flags); + + if (vortex_debug > 0) + printk(KERN_DEBUG "%s: vortex_set_mtu() New mtu=%d Wn3MACCtrl=%4.4x.\n", + dev->name, mtu, config); + } + return mtu; +} + + /* returns count found (>= 0), or negative on error */ static int __init vortex_eisa_init (void) { @@ -881,6 +931,7 @@ dev->base_addr = ioaddr; dev->irq = irq; dev->mtu = mtu; + vp->pkt_buf_sz = mtu + 36; /* FIXME: What is this MAGIC 36 ??? */ vp->drv_flags = vci->drv_flags; vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; vp->io_size = vci->io_size; @@ -1109,9 +1160,10 @@ dev->hard_start_xmit = vp->full_bus_master_tx ? boomerang_start_xmit : vortex_start_xmit; dev->stop = vortex_close; - dev->get_stats = vortex_get_stats; - dev->do_ioctl = vortex_ioctl; + dev->get_stats = vortex_get_stats; + dev->do_ioctl = vortex_ioctl; dev->set_multicast_list = set_rx_mode; + dev->change_mtu = vortex_set_mtu; dev->tx_timeout = vortex_tx_timeout; dev->watchdog_timeo = (watchdog * HZ) / 1000; @@ -1227,7 +1279,7 @@ /* Set the full-duplex bit. */ outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | - (dev->mtu > 1500 ? 0x40 : 0) | + ((dev->mtu > 1500) ? 0x40 : 0) | ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); @@ -1298,7 +1350,7 @@ if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ vp->cur_tx = vp->dirty_tx = 0; if (vp->drv_flags & IS_BOOMERANG) - outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ + outb(vp->pkt_buf_sz>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ /* Clear the Rx, Tx rings. */ for (i = 0; i < RX_RING_SIZE; i++) /* AKPM: this is done in vortex_open, too */ vp->rx_ring[i].status = 0; @@ -1354,14 +1406,14 @@ struct sk_buff *skb; vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1)); vp->rx_ring[i].status = 0; /* Clear complete bit. */ - vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG); - skb = dev_alloc_skb(PKT_BUF_SZ); + vp->rx_ring[i].length = cpu_to_le32(vp->pkt_buf_sz | LAST_FRAG); + skb = dev_alloc_skb(vp->pkt_buf_sz); vp->rx_skbuff[i] = skb; if (skb == NULL) break; /* Bad news! */ skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); + vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, vp->pkt_buf_sz, PCI_DMA_FROMDEVICE)); } if (i != RX_RING_SIZE) { int j; @@ -1443,12 +1495,15 @@ /* Set the full-duplex bit. */ EL3WINDOW(3); /* AKPM: this was missing from 2.3.99 3c59x.c! */ outw( (vp->full_duplex ? 0x20 : 0) | - (dev->mtu > 1500 ? 0x40 : 0) | + ((dev->mtu > 1500) ? 0x40 : 0) | ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); if (vortex_debug > 1) printk(KERN_DEBUG "Setting duplex in Wn3_MAC_Ctrl\n"); /* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */ + + wait_for_completion(dev, TxReset); + wait_for_completion(dev, RxReset); } } } @@ -1558,7 +1613,7 @@ if (vp->tx_full) netif_stop_queue (dev); if (vp->drv_flags & IS_BOOMERANG) - outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); + outb(vp->pkt_buf_sz>>8, ioaddr + TxFreeThreshold); outw(DownUnstall, ioaddr + EL3_CMD); } else { vp->stats.tx_dropped++; @@ -2053,10 +2108,19 @@ (pkt_len + 3) >> 2); } outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ + + if (skb->data[0] & 1) { + /* Destination MAC address has at its first octet + the lowest bit set -> multicast or broadcast.. */ + if (memcmp(skb->data, dev->broadcast, ETH_ALEN) != 0) + /* Multicast! */ + vp->stats.multicast++; + } + skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); dev->last_rx = jiffies; vp->stats.rx_packets++; + netif_rx(skb); /* Wait a limited time to go to next packet. */ for (i = 200; i >= 0; i--) if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) @@ -2114,7 +2178,7 @@ if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != 0) { skb->dev = dev; skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + pci_dma_sync_single(vp->pdev, dma, vp->pkt_buf_sz, PCI_DMA_FROMDEVICE); /* 'skb_put()' points to the start of sk_buff data area. */ memcpy(skb_put(skb, pkt_len), vp->rx_skbuff[entry]->tail, @@ -2125,9 +2189,18 @@ skb = vp->rx_skbuff[entry]; vp->rx_skbuff[entry] = NULL; skb_put(skb, pkt_len); - pci_unmap_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + pci_unmap_single(vp->pdev, dma, vp->pkt_buf_sz, PCI_DMA_FROMDEVICE); rx_nocopy++; } + + if (skb->data[0] & 1) { + /* Destination MAC address has at its first octet + the lowest bit set -> multicast or broadcast.. */ + if (memcmp(skb->data, dev->broadcast, ETH_ALEN) != 0) + /* Multicast! */ + vp->stats.multicast++; + } + skb->protocol = eth_type_trans(skb, dev); { /* Use hardware checksum info. */ int csum_bits = rx_status & 0xee000000; @@ -2138,9 +2211,9 @@ rx_csumhits++; } } - netif_rx(skb); dev->last_rx = jiffies; vp->stats.rx_packets++; + netif_rx(skb); } entry = (++vp->cur_rx) % RX_RING_SIZE; } @@ -2149,7 +2222,7 @@ struct sk_buff *skb; entry = vp->dirty_rx % RX_RING_SIZE; if (vp->rx_skbuff[entry] == NULL) { - skb = dev_alloc_skb(PKT_BUF_SZ); + skb = dev_alloc_skb(vp->pkt_buf_sz); if (skb == NULL) { static unsigned long last_jif; if ((jiffies - last_jif) > 10 * HZ) { @@ -2162,7 +2235,7 @@ } skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); + vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, vp->pkt_buf_sz, PCI_DMA_FROMDEVICE)); vp->rx_skbuff[entry] = skb; } vp->rx_ring[entry].status = 0; /* Clear complete bit. */ @@ -2249,7 +2322,7 @@ for (i = 0; i < RX_RING_SIZE; i++) if (vp->rx_skbuff[i]) { pci_unmap_single( vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), - PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + vp->pkt_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(vp->rx_skbuff[i]); vp->rx_skbuff[i] = 0; } @@ -2402,16 +2475,23 @@ static void set_rx_mode(struct net_device *dev) { long ioaddr = dev->base_addr; - int new_mode; + int new_mode = SetRxFilter | RxStation; + + if (dev->flags & IFF_BROADCAST) + new_mode |= RxBroadcast; if (dev->flags & IFF_PROMISC) { if (vortex_debug > 0) - printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name); - new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm; - } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { - new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast; - } else - new_mode = SetRxFilter | RxStation | RxBroadcast; + printk(KERN_NOTICE "%s: Setting promiscuous mode; cnt=%d\n", dev->name, dev->promiscuity); + new_mode |= RxProm; + } + + /* FIXME: Some of the 3c905 family cards actually have a WORKING + multicast reception filter, take it into use! */ + + if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { + new_mode |= RxMulticast; + } outw(new_mode, ioaddr + EL3_CMD); } diff -u -r linux-2400t10vl14/include/linux/if_ether.h linux-2400t10vl14m/include/linux/if_ether.h --- linux-2400t10vl14/include/linux/if_ether.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/include/linux/if_ether.h Wed Nov 1 17:35:00 2000 @@ -32,36 +32,6 @@ #define ETH_DATA_LEN 1500 /* Max. octets in payload */ #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ - -#ifdef CONFIG_VLAN_802_1Q - - -#define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */ -#define VLAN_ETH_HLEN 18 /* Total octets in header. */ -#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */ - -/* These could be bumped up by 4, but I'm not sure if all the underlying - * drivers would like it. - * UPDATE: Bumping it by 4, as per Klika's suggestion below. --BLG - * - * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan - */ -#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ - -struct vlan_ethhdr -{ - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_vlan_proto; /* Should always be 0x8100 */ - unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ - unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ -}; - - -#endif - - /* * These are the defined Ethernet Protocol ID's. */ @@ -84,7 +54,7 @@ #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ #define ETH_P_ATALK 0x809B /* Appletalk DDP */ #define ETH_P_AARP 0x80F3 /* Appletalk AARP */ -#define ETH_P_802_1Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ #define ETH_P_IPX 0x8137 /* IPX over DIX */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ @@ -124,5 +94,37 @@ unsigned char h_source[ETH_ALEN]; /* source ether addr */ unsigned short h_proto; /* packet type ID field */ }; + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + + +#define VLAN_HLEN 4 /* Total octets in header. */ + +/* These could be bumped up by 4, but I'm not sure if all the underlying + * drivers would like it. + * UPDATE: Bumping it by 4, as per Klika's suggestion below. --BLG + * + * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan + */ +#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ + +struct vlan_ethhdr +{ + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + unsigned short h_vlan_proto; /* Should always be 0x8100 */ + unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ + unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ +}; + +struct vlan_hdr +{ + unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ + unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ +}; + +#endif /* CONFIG_VLAN_8021Q(_MODULE) */ + #endif /* _LINUX_IF_ETHER_H */ diff -u -r linux-2400t10vl14/include/linux/if_vlan.h linux-2400t10vl14m/include/linux/if_vlan.h --- linux-2400t10vl14/include/linux/if_vlan.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/include/linux/if_vlan.h Wed Nov 1 17:37:25 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * VLAN An implementation of 802.1Q VLAN tagging. * * For some idea of the architecture, see the web page at (curently): @@ -52,8 +52,8 @@ /* found in vlan_dev.c */ struct net_device_stats* vlan_dev_get_stats(struct net_device* dev); int vlan_dev_rebuild_header(struct sk_buff *skb); -int vlan_dev_type_trans(struct sk_buff *skb, struct net_device *dev, - struct packet_type* ptype); +int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type* ptype); int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); diff -u -r linux-2400t10vl14/include/linux/netdevice.h linux-2400t10vl14m/include/linux/netdevice.h --- linux-2400t10vl14/include/linux/netdevice.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/include/linux/netdevice.h Wed Nov 1 17:35:06 2000 @@ -38,7 +38,7 @@ #ifdef CONFIG_NET_PROFILE #include -#if (defined(CONFIG_VLAN_802_1Q)) +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) struct vlan_dev_info; #endif @@ -76,7 +76,7 @@ */ #if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR) -#if defined(CONFIG_VLAN_802_1Q) +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define LL_MAX_HEADER 36 #else #define LL_MAX_HEADER 32 @@ -201,8 +201,11 @@ rwlock_t hh_lock; /* cached hardware header; allow for machine alignment needs. */ -#ifdef CONFIG_VLAN_802_1Q /* we need 4 extra bytes for VLAN headers */ - unsigned long hh_data[20/sizeof(unsigned long)]; +#if 0 && (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) + /* we need 4 extra bytes for VLAN headers */ + /* FIXME: DO THIS ONLY IF WE REALLY START TO DO VLAN HEADER + CACHE THING! MAKE SURE THIS WORKS WHEN sizeof(long) > 4 ! */ + unsigned long hh_data[1+16/sizeof(unsigned long)]; #else unsigned long hh_data[16/sizeof(unsigned long)]; #endif @@ -414,7 +417,7 @@ struct dst_entry *fastpath[NETDEV_FASTROUTE_HMASK+1]; #endif -#ifdef CONFIG_VLAN_802_1Q +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) /* Holds information that makes sense if this device is a VLAN device. */ struct vlan_dev_info* vlan_dev; #endif diff -u -r linux-2400t10vl14/net/8021q/Makefile linux-2400t10vl14m/net/8021q/Makefile --- linux-2400t10vl14/net/8021q/Makefile Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/Makefile Wed Nov 1 16:46:47 2000 @@ -7,18 +7,13 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -O_TARGET := 802_1Q.o +O_TARGET := 8021q.o -OBJS := vlan.o vlanproc.o vlan_dev.o +8021q_OBJS := vlan.o vlanproc.o vlan_dev.o +8021q_OBJS += sysctl_net_vlan.o -ifeq ($(CONFIG_SYSCTL),y) -OBJS += sysctl_net_vlan.o -endif - - -ifdef CONFIG_NET -O_OBJS := $(OBJS) $(OBJ2) -endif +M_OBJS := $(O_TARGET) +O_OBJS := $(8021q_OBJS) include $(TOPDIR)/Rules.make diff -u -r linux-2400t10vl14/net/8021q/sysctl_net_vlan.c linux-2400t10vl14m/net/8021q/sysctl_net_vlan.c --- linux-2400t10vl14/net/8021q/sysctl_net_vlan.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/sysctl_net_vlan.c Wed Nov 1 16:51:13 2000 @@ -6,7 +6,9 @@ * TODO: What, if anything, should this do?? */ -#ifdef CONFIG_VLAN_802_1Q +#include + +#if defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q) #include #include diff -u -r linux-2400t10vl14/net/8021q/vlan.c linux-2400t10vl14m/net/8021q/vlan.c --- linux-2400t10vl14/net/8021q/vlan.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlan.c Sat Nov 4 00:35:37 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. @@ -34,8 +34,6 @@ #include "vlanproc.h" -extern int eth_header_parse(struct sk_buff *skb, unsigned char *haddr); /* eth.c */ - extern struct Qdisc noqueue_qdisc; /* Global VLAN variables */ @@ -56,56 +54,15 @@ static struct packet_type vlan_packet_type = { - 0, /* MUTTER ntohs(ETH_P_802_1Q),*/ - NULL, - vlan_dev_type_trans, /* VLAN receive method */ - NULL, - NULL, + type: __constant_htons(ETH_P_8021Q), + dev: NULL, + func: vlan_skb_recv, /* VLAN receive method */ + data: NULL, /* Set here '(void *)1' when this code can SHARE SKBs */ + next: NULL }; /* End of global variables definitions. */ -#ifdef MODULE - -/* - * Kernel Loadable Module Entry Points - * - * Module 'insert' entry point. - * o print announcement - * o initialize static data - * o create /proc/net/vlan directory and static entries - * - * Return: 0 Ok - * < 0 error. - * Context: process - */ -int init_module (void) { - printk(VLAN_INF __FUNCTION__); - - vlan_proto_init(NULL); - return 0; -} - -/* - * Module 'remove' entry point. - * o delete /proc/net/router directory and static entries. - */ -void cleanup_module (void) { - vlan_proto_cleanup(); // TODO: Define this so modules work. Clean up ports. -} - -#else - - -/** Non-module init entry point. */ -void __init vlan_system_init(void) { - printk(VLAN_INF __FUNCTION__); - - /* protocol initialization */ - vlan_proto_init(NULL); - -} -#endif /* * Function vlan_proto_init (pro) @@ -113,7 +70,8 @@ * Initialize VLAN protocol layer, * */ -void vlan_proto_init(struct net_proto *pro) { +static int vlan_proto_init(void); +static int __init vlan_proto_init(void) { int err; printk(VLAN_INF "%s v%u.%u %s\n", @@ -123,15 +81,31 @@ err = vlan_proc_init(); if (err < 0) { printk(KERN_ERR __FUNCTION__ - "%s: can't create entry in proc filesystem!\n", VLAN_NAME); + "%s: can't create entry in proc filesystem!\n", + VLAN_NAME); + return 1; } - /* network byte order!! */ - vlan_packet_type.type = htons(ETH_P_802_1Q); dev_add_pack(&vlan_packet_type); + printk(VLAN_INF "%s Initialization complete.\n", VLAN_NAME); + return 0; } +/* + * Module 'remove' entry point. + * o delete /proc/net/router directory and static entries. + */ +static void __exit vlan_cleanup_module (void) +{ + // TODO: Define this so modules work. Clean up ports. + // vlan_proto_cleanup(); + dev_remove_pack(&vlan_packet_type); + vlan_proc_cleanup(); +} + +module_init(vlan_proto_init); +module_exit(vlan_cleanup_module); /** Will search linearly for now, based on device index. Could @@ -208,6 +182,8 @@ rtnl_lock(); unregister_netdevice(dev); rtnl_unlock(); + + MOD_DEC_USE_COUNT; }/* if */ }/* if */ @@ -263,13 +239,16 @@ struct net_device *real_dev; /* the ethernet device */ int malloc_size = 0; + MOD_INC_USE_COUNT; + #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": if_name -:%s:- vid: %i\n", eth_IF_name, VLAN_ID); #endif /* find the device relating to eth_IF_name. - * TODO: Make sure it's an ethernet device. */ + * TODO: Make sure it's an ethernet device. */ + real_dev = dev_get_by_name(eth_IF_name); if (real_dev != NULL) { @@ -305,25 +284,30 @@ new_dev->new_style = 0; /* Gotta set up the fields for the device. */ - - if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) { - /* name will look like: eth1.0005 */ - sprintf(new_dev->name, "%s.%.4i", real_dev->name, VLAN_ID); - } - else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) { - /* Put our vlan.VID in the name. Name will look like: vlan5 */ - sprintf(new_dev->name, "vlan%i", VLAN_ID); - } - else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) { - /* Put our vlan.VID in the name. Name will look like: eth0.5 */ - sprintf(new_dev->name, "%s.%i", real_dev->name, VLAN_ID); - } - else { /* (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) { */ - /* Put our vlan.VID in the name. Name will look like: vlan0005 */ - /* default case */ - sprintf(new_dev->name, "vlan%.4i", VLAN_ID); + + switch (vlan_name_type) { + case VLAN_NAME_TYPE_RAW_PLUS_VID: + /* name will look like: eth1.0005 */ + sprintf(new_dev->name, "%s.%.4i", real_dev->name, VLAN_ID); + break; + case VLAN_NAME_TYPE_PLUS_VID_NO_PAD: + /* Put our vlan.VID in the name. + Name will look like: vlan5 */ + sprintf(new_dev->name, "vlan%i", VLAN_ID); + break; + case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD: + /* Put our vlan.VID in the name. + Name will look like: eth0.5 */ + sprintf(new_dev->name, "%s.%i", real_dev->name, VLAN_ID); + break; + case VLAN_NAME_TYPE_PLUS_VID: + /* Put our vlan.VID in the name. + Name will look like: vlan0005 */ + default: + /* default case */ + sprintf(new_dev->name, "vlan%.4i", VLAN_ID); } - + #ifdef VLAN_DEBUG printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); #endif @@ -341,14 +325,16 @@ new_dev->flags = real_dev->flags; new_dev->flags &= ~IFF_UP; - /* need 4 bytes for extra VLAN header info, hope - * underlying device can handle it. */ - new_dev->mtu = real_dev->mtu; + /* need 4 bytes for extra VLAN header info, + hope the underlying device can handle it. */ + new_dev->mtu = real_dev->mtu; + new_dev->change_mtu = vlan_dev_change_mtu; new_dev->type = real_dev->type; /* TODO: is this true? */ - /* Regular ethernet + 4 bytes (18 total). */ - new_dev->hard_header_len = VLAN_ETH_HLEN; + /* Regular ethernet + 4 bytes (18 total). */ + new_dev->hard_header_len + = VLAN_HLEN + real_dev->hard_header_len; new_dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); @@ -366,11 +352,15 @@ new_dev->open = vlan_dev_open; new_dev->stop = vlan_dev_stop; new_dev->hard_header = vlan_dev_hard_header; - /*new_dev->hard_header_cache = vlan_header_cache;*/ - /*new_dev->header_cache_update = vlan_header_cache_update;*/ +#if 0 + /*new_dev->hard_header_cache = real_dev->hard_header_cache;*/ + /*new_dev->header_cache_update = real_dev->header_cache_update;*/ + new_dev->hard_header_cache = vlan_header_cache; + new_dev->header_cache_update = vlan_header_cache_update; +#endif new_dev->hard_start_xmit = vlan_dev_hard_start_xmit; new_dev->rebuild_header = vlan_dev_rebuild_header; - new_dev->hard_header_parse = eth_header_parse; /* trivial. */ + new_dev->hard_header_parse = real_dev->hard_header_parse; /* trivial. */ new_dev->set_mac_address = vlan_dev_set_mac_address; new_dev->set_multicast_list = vlan_dev_set_multicast_list; @@ -384,19 +374,19 @@ kfree(new_dev); VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev); dev_put(real_dev); + MOD_DEC_USE_COUNT; return NULL; } - else { - memset(new_dev->vlan_dev, 0, sizeof(struct vlan_dev_info)); - new_dev->vlan_dev->vlan_id = VLAN_ID; /* 1 through 0xFFF */ - /* TODO: have to be careful deleting real devices now. */ - new_dev->vlan_dev->real_dev = real_dev; + memset(new_dev->vlan_dev, 0, sizeof(struct vlan_dev_info)); + new_dev->vlan_dev->vlan_id = VLAN_ID; /* 1 through 0xFFF */ - new_dev->vlan_dev->dent = NULL; - } + /* TODO: have to be careful deleting real devices now. */ + new_dev->vlan_dev->real_dev = real_dev; + new_dev->vlan_dev->dent = NULL; - /* So, got the sucker initialized, now lets place it into our local + /* So, got the sucker initialized, + * now lets place it into our local * structure. */ @@ -411,26 +401,26 @@ grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL); VLAN_MEM_DBG("grp malloc, addr: %p size: %i\n", grp, sizeof(struct vlan_group)); - if (grp) { - printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); - memset(grp, 0, sizeof(struct vlan_group)); - grp->real_dev_ifindex = real_dev->ifindex; - grp->next = p802_1Q_vlan_list; - p802_1Q_vlan_list = grp; - } - else { + if (!grp) { kfree(new_dev->priv); VLAN_FMEM_DBG("new_dev->priv free, addr: %p\n", new_dev->priv); kfree(new_dev); VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev); dev_put(real_dev); + MOD_DEC_USE_COUNT; return NULL; } + printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); + memset(grp, 0, sizeof(struct vlan_group)); + grp->real_dev_ifindex = real_dev->ifindex; + grp->next = p802_1Q_vlan_list; + p802_1Q_vlan_list = grp; }/* if */ grp->vlan_devices[VLAN_ID] = new_dev; /* Now, add it to the global list of devices. */ + vlan_proc_add_dev(new_dev); /* create it's proc entry */ /* printk(KERN_ALERT "Registering new device."); */ /* TODO: Please check this: RTNL --Ben */ @@ -438,9 +428,8 @@ register_netdevice(new_dev); rtnl_unlock(); - vlan_proc_add_dev(new_dev); /* create it's proc entry */ - - /* NOTE: We have a reference to the real device, so hold on to the reference. + /* NOTE: We have a reference to the real + * device, so hold on to the reference. */ /* dev_put(real_dev); */ return new_dev; @@ -451,5 +440,6 @@ dev_put(real_dev); }//if we found real_dev + MOD_DEC_USE_COUNT; return NULL; }/* register (create) VLAN device */ diff -u -r linux-2400t10vl14/net/8021q/vlan.h linux-2400t10vl14m/net/8021q/vlan.h --- linux-2400t10vl14/net/8021q/vlan.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlan.h Wed Nov 1 17:37:25 2000 @@ -37,8 +37,4 @@ int unregister_802_1Q_vlan_device(const char* vlan_IF_name); struct net_device *register_802_1Q_vlan_device(const char* eth_IF_name, unsigned short VID); - -void vlan_system_init(void); -void vlan_proto_init(struct net_proto *pro); - #endif diff -u -r linux-2400t10vl14/net/8021q/vlan_dev.c linux-2400t10vl14m/net/8021q/vlan_dev.c --- linux-2400t10vl14/net/8021q/vlan_dev.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlan_dev.c Sat Nov 4 01:18:24 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. @@ -17,21 +17,22 @@ * 2 of the License, or (at your option) any later version. */ -#include /* for copy_from_user */ #include -#include -#include -#include #include #include #include +#include /* for copy_from_user */ +#include +#include +#include +#include +#include #include #include #include "vlan.h" #include "vlanproc.h" #include #include -#include struct net_device_stats* vlan_dev_get_stats(struct net_device* dev) { @@ -90,25 +91,38 @@ * SANITY NOTE: This method is called when a packet is moving up the stack * towards userland. To get here, it would have already passed * through the ethernet/eth.c eth_type_trans() method. + * SANITY NOTE 2: We are referencing to the VLAN_HDR frields, which MAY be + * stored UNALIGNED in the memory. RISC systems don't like + * such cases very much... + * */ -int vlan_dev_type_trans(struct sk_buff *skb, struct net_device *dev, - struct packet_type* ptype) { - unsigned char* rawp = NULL; - struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->mac.ethernet); - unsigned short vid = 0; +int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type* ptype) +{ + unsigned char* rawp = NULL; + struct vlan_hdr *vhdr = (struct vlan_hdr*)(skb->data); + unsigned short vid; struct net_device_stats* stats; + + unsigned short vlan_TCI; + unsigned short proto; +#if 0 /* If we want to re-check that the incoming frame was indeed of proper + type... */ + + proto = get_unaligned(((unsigned short *)skb->data)-1); /* Do we have a VLAN packet? If not, then throw it away, after printing an error. */ - if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) { - printk(VLAN_INF __FUNCTION__ ": VLAN device received NON-VLAN protocol: %hx\n", htons(veth->h_vlan_proto)); + if (proto != __constant_htons(ETH_P_8021Q)) { + printk(VLAN_INF __FUNCTION__ ": VLAN device received NON-VLAN protocol packet: %hx\n", proto); vlan_bad_proto_recvd++; kfree_skb(skb); return -EINVAL; } - else { - vid = ((unsigned short)(ntohs(veth->h_vlan_TCI)) & 0xFFF); - } +#endif + + vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); + vid = (vlan_TCI & 0xFFF); #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": skb: %p vlan_id: %hx\n", @@ -135,6 +149,11 @@ /* Bump the rx counters for the VLAN device. */ stats = (struct net_device_stats*)(skb->dev->priv); + stats->rx_packets++; + stats->rx_bytes += skb->len; + + skb_pull(skb, VLAN_HLEN); /* take off the VLAN header */ + /** Ok, lets check to make sure the device (dev) we * came in on is what this VLAN is attached to. */ @@ -146,92 +165,72 @@ stats->rx_errors++; return -1; } - + /* * Deal with ingress priority mapping. */ - skb->priority = skb->dev->vlan_dev->ingress_priority_map[(ntohs(veth->h_vlan_TCI) >> 13) & 0x7]; - + skb->priority = + skb->dev->vlan_dev->ingress_priority_map[(vlan_TCI >> 13) & 0x7]; + #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": priority: %lu for TCI: %hu (hbo)\n", - (unsigned long)(skb->priority), ntohs(veth->h_vlan_TCI)); + (unsigned long)(skb->priority), vlan_TCI); #endif - stats->rx_packets++; - stats->rx_bytes += skb->len; - - /* The underlying device SHOULD NOT PULL THE MAC BYTES OFF. - (it doesn't seem to.) - */ - skb_pull(skb, VLAN_ETH_HLEN); /* take off the VLAN header */ - - - /* VLAN and regular Ethernet headers have the addresses in the same place. - * TODO: Add code to deal with VLAN control packets?? --BLG - * Is there such a thing?? - */ - if (*(veth->h_dest) & 1) { - stats->multicast++; - if (memcmp(veth->h_dest, dev->broadcast, ETH_ALEN) == 0) - skb->pkt_type = PACKET_BROADCAST; - else - skb->pkt_type = PACKET_MULTICAST; - } - - /* - * This ALLMULTI check should be redundant by 1.4 - * so don't forget to remove it. - * - * Seems, you forgot to remove it. All silly devices - * seems to set IFF_PROMISC. - */ - - else if (dev->flags & (IFF_PROMISC/*|IFF_ALLMULTI*/)) { - if (memcmp(veth->h_dest, dev->dev_addr, ETH_ALEN) != 0) - skb->pkt_type = PACKET_OTHERHOST; - } + switch (skb->pkt_type) { + case PACKET_BROADCAST: /* Yeah, stats collect these together.. */ + // stats->broadcast ++; // no such counter :-( + case PACKET_MULTICAST: + stats->multicast ++; + break; + default: + break; + } /* Was a VLAN packet, grab the encapsulated protocol, which the layer * three protocols care about. */ - if (ntohs(veth->h_vlan_encapsulated_proto) >= 1536) { + proto = get_unaligned(&vhdr->h_vlan_encapsulated_proto); + skb->protocol = proto; + + if (ntohs(proto) >= 1536) { - skb->protocol = veth->h_vlan_encapsulated_proto; - /* place it back on the queue to be handled by true layer 3 protocols. - */ + /* place it back on the queue to be handled by true + layer 3 protocols. */ - /* See if we are configured to re-write the VLAN header to make it look like - * ethernet... - */ + /* See if we are configured to re-write the VLAN header + to make it look like ethernet... */ if (skb->dev->vlan_dev->flags & 1) { /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); - skb->mac.raw += 4; + memmove(skb->data - ETH_HLEN, + skb->data - (ETH_HLEN + VLAN_HLEN), 12); + skb->mac.raw += VLAN_HLEN; } netif_rx(skb); return 0; } rawp = skb->data; - + /* - * This is a magic hack to spot IPX packets. Older Novell breaks - * the protocol design and runs IPX over 802.3 without an 802.2 LLC - * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This - * won't work for fault tolerant netware but does for the rest. + * This is a magic hack to spot IPX packets. Older Novell breaks + * the protocol design and runs IPX over 802.3 without an 802.2 LLC + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This + * won't work for fault tolerant netware but does for the rest. */ if (*(unsigned short *)rawp == 0xFFFF) { + + /* place it back on the queue to be handled by true + layer 3 protocols. */ skb->protocol = __constant_htons(ETH_P_802_3); - /* place it back on the queue to be handled by true layer 3 protocols. - */ - /* See if we are configured to re-write the VLAN header to make it look like - * ethernet... - */ + /* See if we are configured to re-write the VLAN header + to make it look like ethernet... */ if (skb->dev->vlan_dev->flags & 1) { - /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); - skb->mac.raw += 4; + /* Lifted from Gleb's VLAN code... */ + memmove(skb->data - ETH_HLEN, + skb->data - (ETH_HLEN + VLAN_HLEN), 12); + skb->mac.raw += VLAN_HLEN; } netif_rx(skb); @@ -245,13 +244,13 @@ /* place it back on the queue to be handled by upper layer protocols. */ - /* See if we are configured to re-write the VLAN header to make it look like - * ethernet... - */ + /* See if we are configured to re-write the VLAN header to make + it look like ethernet... */ if (skb->dev->vlan_dev->flags & 1) { /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); - skb->mac.raw += 4; + memmove(skb->data - ETH_HLEN, + skb->data - (ETH_HLEN + VLAN_HLEN), 12); + skb->mac.raw += VLAN_HLEN; } netif_rx(skb); return 0; @@ -270,21 +269,19 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - struct vlan_ethhdr *veth; + struct vlan_hdr *vhdr; unsigned short veth_TCI = 0; - + int rc; + #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": skb: %p type: %hx len: %x vlan_id: %hx, daddr: %p\n", skb, type, len, dev->vlan_dev->vlan_id, daddr); #endif - veth = (struct vlan_ethhdr*)skb_push(skb, VLAN_ETH_HLEN); + vhdr = (struct vlan_hdr*) skb_push(skb, VLAN_HLEN); /* build the four bytes that make this a VLAN header. */ - /* first, the ethernet type */ - veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q); - /* Now, construct the second two bytes. This field looks something * like: * usr_priority: 3 bits (high bits) @@ -294,46 +291,32 @@ */ veth_TCI = dev->vlan_dev->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); - - veth->h_vlan_TCI = htons(veth_TCI); + + put_unaligned(htons(veth_TCI), &vhdr->h_vlan_TCI); /* Rest should be the same as a normal header. */ /* - * Set the protocol type. For a packet of type ETH_P_802_3 we put the length - * in here instead. It is up to the 802.2 layer to carry protocol information. + * Set the protocol type. + * For a packet of type ETH_P_802_3 we put the length in here instead. + * It is up to the 802.2 layer to carry protocol information. * */ if (type != ETH_P_802_3) - veth->h_vlan_encapsulated_proto = htons(type); + put_unaligned(htons(type), &vhdr->h_vlan_encapsulated_proto); else - veth->h_vlan_encapsulated_proto = htons(len); + put_unaligned(htons(len), &vhdr->h_vlan_encapsulated_proto); - /* - * Set the source hardware address. - */ - - if (saddr) - memcpy(veth->h_source, saddr, ETH_ALEN); - else - memcpy(veth->h_source, dev->dev_addr, ETH_ALEN); - - /* - * Anyway, the loopback-device should never use this function... - * This is especially true with VLAN's. --BLG - */ - - if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - memset(veth->h_dest, 0, ETH_ALEN); - return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */ - } - - if (daddr) { - memcpy(veth->h_dest, daddr, ETH_ALEN); - return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */ - } - - return -(VLAN_ETH_HLEN); /* was: dev->hard_header_len */ + + /* Now make the underlying real hard header */ + + dev = dev->vlan_dev->real_dev; + rc = dev->hard_header(skb, dev, ETH_P_8021Q, + daddr, saddr, len+VLAN_HLEN); + + if (rc < 0) rc -= VLAN_HLEN; + if (rc > 0) rc += VLAN_HLEN; + return rc; } /* vlan_hard_header, put on the VLAN hardware header */ @@ -342,8 +325,14 @@ struct net_device_stats* stats = (struct net_device_stats*)(dev->priv); struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data); - /* Handle non-VLAN frames if they are sent to us, for example by DHCP. */ - if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) { + /* Handle non-VLAN frames if they are sent to us, + for example by DHCP. */ + + /* NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING + OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ + + if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) { + /* This is not a VLAN frame...but we can fix that! */ unsigned short veth_TCI = 0; dev->vlan_dev->cnt_encap_on_xmit++; @@ -370,16 +359,17 @@ return -ENOMEM; } } - veth = (struct vlan_ethhdr*)skb_push(skb, 4); + veth = (struct vlan_ethhdr*)skb_push(skb, VLAN_HLEN); - /* Move the mac addresses to the beginning of the new header. */ - memmove(skb->data, skb->data + 4, 12); + /* Move the mac addresses to the beginning of the new header.*/ + memmove(skb->data, skb->data + VLAN_HLEN, 12); - /* first, the ethernet type */ - veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q); + /* first, the ethernet type */ + put_unaligned(__constant_htons(ETH_P_8021Q), + &veth->h_vlan_proto); - /* Now, construct the second two bytes. This field looks something - * like: + /* Now, construct the second two bytes. + * This field looks something like: * usr_priority: 3 bits (high bits) * CFI 1 bit * VLAN ID 12 bits (low bits) @@ -388,7 +378,8 @@ veth_TCI = dev->vlan_dev->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); - veth->h_vlan_TCI = htons(veth_TCI); + put_unaligned(htons(veth_TCI), &veth->h_vlan_TCI); + }/* If we needed to encapsulate the frame */ skb->dev = dev->vlan_dev->real_dev; @@ -413,7 +404,16 @@ * maybe an IFF_VLAN_CAPABLE flag for devices? */ + struct net_device *rdev = dev->vlan_dev->real_dev; + dev->mtu = new_mtu; + + /* TODO: Check what our VLAN peer devices have for MTU, + and play coherent result: (largest + VLAN_HDR) + of any of VLANs at the same physical device. */ + + if (rdev->change_mtu) + return rdev->change_mtu(rdev, new_mtu + VLAN_HLEN); return new_mtu; } @@ -464,7 +464,6 @@ return; } - /* TODO: Not to sure if the VLAN stuff works here. Need to understand * this better. --BLG */ @@ -500,57 +499,6 @@ } */ -#ifndef CONFIG_IP_ROUTER - -/* - * Copy from an ethernet device memory space to an sk_buff while - * checksumming if IP - * - * TODO: Find out who calls this: This was lifted from eth.c, and - * was called eth_copy_and_sum. --BLG - */ - -void vlan_dev_copy_and_sum(struct sk_buff *dest, unsigned char *src, - int length, int base) { - struct vlan_ethhdr* veth; - struct iphdr *iph; - int ip_length; - - veth = (struct vlan_ethhdr*)(src); - - /* This grabs the VLAN part of the header too. */ - if (veth->h_vlan_encapsulated_proto != __constant_htons(ETH_P_IP)) { - memcpy(dest->data, src, length); - return; - } - - /* - * We have to watch for padded packets. The csum doesn't include the - * padding, and there is no point in copying the padding anyway. - * We have to use the smaller of length and ip_length because it - * can happen that ip_length > length. - */ - - /* ethernet is always >= 34 */ - memcpy(dest->data, src, sizeof(struct iphdr) + VLAN_ETH_HLEN); - - length -= sizeof(struct iphdr) + VLAN_ETH_HLEN; - iph = (struct iphdr*)(src + VLAN_ETH_HLEN); - ip_length = ntohs(iph->tot_len) - sizeof(struct iphdr); - - /* Also watch out for bogons - min IP size is 8 (rfc-1042) */ - if ((ip_length <= length) && (ip_length > 7)) - length=ip_length; - - dest->csum = csum_partial_copy(src + sizeof(struct iphdr) + VLAN_ETH_HLEN, - dest->data + sizeof(struct iphdr) + VLAN_ETH_HLEN, - length, base); - dest->ip_summed=1; - -} /* vlan_copy_and_sum */ - -#endif //! CONFIG_IP_ROUTER - int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio) { @@ -634,15 +582,16 @@ int vlan_dev_set_mac_address(struct net_device *dev, void* addr) { +#ifdef VLAN_DEBUG int i; printk("%s: Setting MAC address to ", dev->name); for (i = 0; i < 6; i++) printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); printk(".\n"); printk(" Make sure the underlying device is in promiscious mode!\n"); - +#endif /* Copy the address. */ - memcpy(dev->dev_addr, addr, 6); + memcpy(dev->dev_addr, addr, dev->addr_len); return 0; } @@ -650,6 +599,7 @@ /** Taken from Gleb + Lennert's VLAN code, and modified... */ void vlan_dev_set_multicast_list(struct net_device *vlan_dev) { + struct dev_mc_list *dmi; struct net_device *real_dev; int inc; @@ -662,7 +612,7 @@ inc = vlan_dev->promiscuity - vlan_dev->vlan_dev->old_promiscuity; if (inc) { - printk(KERN_INFO "vlan: dev_set_promiscuity(master, %d)\n", inc); + printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n", vlan_dev->name, inc); dev_set_promiscuity(real_dev, inc); /* found in dev.c */ vlan_dev->vlan_dev->old_promiscuity = vlan_dev->promiscuity; } @@ -670,7 +620,7 @@ inc = vlan_dev->allmulti - vlan_dev->vlan_dev->old_allmulti; if (inc) { - printk(KERN_INFO "vlan: dev_set_allmulti(master, %d)\n", inc); + printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n", vlan_dev->name, inc); dev_set_allmulti(real_dev, inc); /* dev.c */ vlan_dev->vlan_dev->old_allmulti = vlan_dev->allmulti; } @@ -679,7 +629,8 @@ for (dmi = vlan_dev->mc_list; dmi!=NULL; dmi=dmi->next) { if (vlan_should_add_mc(dmi, vlan_dev->vlan_dev->old_mc_list)) { dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - printk(KERN_INFO "vlan: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", + printk(KERN_INFO "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", + vlan_dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], @@ -696,7 +647,8 @@ * delete it from the real list on the underlying device. */ dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", + printk(KERN_INFO "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", + vlan_dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], @@ -746,14 +698,13 @@ printk(KERN_ERR "vlan: cannot allocate memory. Multicast may not work properly from now.\n"); return; } - + + /* Copy whole structure, then make new 'next' pointer */ + + *new_dmi = *dmi; + new_dmi->next = vlan_info->old_mc_list; vlan_info->old_mc_list = new_dmi; - - new_dmi->dmi_addrlen = dmi->dmi_addrlen; - memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); - new_dmi->dmi_users = dmi->dmi_users; - new_dmi->dmi_gusers = dmi->dmi_gusers; } } @@ -762,7 +713,8 @@ while (dmi) { dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", + printk(KERN_INFO "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", + dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], @@ -773,9 +725,9 @@ } vlan_destroy_mc_list(dev->mc_list); + dev->mc_list = NULL; if (dev->vlan_dev) { vlan_destroy_mc_list(dev->vlan_dev->old_mc_list); dev->vlan_dev->old_mc_list = NULL; } - dev->mc_list = NULL; }/* vlan_flush_mc_list */ diff -u -r linux-2400t10vl14/net/8021q/vlanproc.c linux-2400t10vl14m/net/8021q/vlanproc.c --- linux-2400t10vl14/net/8021q/vlanproc.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlanproc.c Wed Nov 1 18:09:10 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* ****************************************************************************** * vlanproc.c VLAN Module. /proc filesystem interface. * @@ -90,7 +90,9 @@ int err = 0; struct vlan_ioctl_args args; +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": cmd: %x\n", cmd); +#endif /* everything here needs root permissions, except aguably the * hack ioctls for sending packets. However, I know _I_ don't @@ -129,11 +131,11 @@ case SET_NAME_TYPE_IOCTL: if ((args.u.name_type >= 0) && (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { vlan_name_type = args.u.name_type; - printk(VLAN_INF "VLAN_SET_NAME_TYPE: new type: %i\n", (int)(args.u.name_type)); + // printk(VLAN_INF "VLAN_SET_NAME_TYPE: new type: %i\n", (int)(args.u.name_type)); err = 0; } else { - printk(VLAN_INF "VLAN_SET_NAME_TYPE, type: %i is invalid.\n", (int)(args.u.name_type)); + // printk(VLAN_INF "VLAN_SET_NAME_TYPE, type: %i is invalid.\n", (int)(args.u.name_type)); err = -EINVAL; } break; @@ -233,7 +235,7 @@ * Clean up /proc/net/vlan entries */ -void vlan_proc_cleanup (void) { +void __exit vlan_proc_cleanup (void) { if (proc_vlan_conf) remove_proc_entry(name_conf, proc_vlan_dir); if (proc_vlan_dir) proc_net_remove(name_root); /* TODO: Take care of dynamically added entries?? @@ -412,13 +414,17 @@ for (grp = p802_1Q_vlan_list; grp != NULL; grp = grp->next) { /* loop through all devices for this device */ +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": found a group, addr: %p\n",grp); +#endif for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { vlandev = grp->vlan_devices[i]; if (!vlandev) continue; +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": found a vlan_dev, addr: %p\n", vlandev); +#endif if ((cnt + 100) > VLAN_PROC_BUFSZ) { if ((cnt+strlen(term_msg)) < VLAN_PROC_BUFSZ) { cnt += sprintf(buf+cnt, "%s", term_msg); @@ -430,9 +436,11 @@ ": ERROR: vlandev->vlan_dev is NULL\n"); continue; } +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": got a good vlandev, addr: %p\n", vlandev->vlan_dev); +#endif cnt += sprintf(buf + cnt, "%-15s| %d | %s\n", vlandev->name, vlandev->vlan_dev->vlan_id, vlandev->vlan_dev->real_dev->name); } @@ -566,7 +574,7 @@ * End */ -#else +#else /* No CONFIG_PROC_FS */ /* * No /proc - output stubs @@ -577,7 +585,7 @@ return 0; } -void vlan_proc_cleanup(void) +void __exit vlan_proc_cleanup(void) { return; } @@ -593,4 +601,4 @@ return 0; } -#endif +#endif /* No CONFIG_PROC_FS */ diff -u -r linux-2400t10vl14/net/Config.in linux-2400t10vl14m/net/Config.in --- linux-2400t10vl14/net/Config.in Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/Config.in Wed Nov 1 09:30:40 2000 @@ -48,7 +48,7 @@ fi fi - bool '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_802_1Q + tristate '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_8021Q fi diff -u -r linux-2400t10vl14/net/Makefile linux-2400t10vl14m/net/Makefile --- linux-2400t10vl14/net/Makefile Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/Makefile Wed Nov 1 09:26:55 2000 @@ -44,7 +44,7 @@ subdir-$(CONFIG_ATM) += atm subdir-$(CONFIG_DECNET) += decnet subdir-$(CONFIG_ECONET) += econet -subdir-$(CONFIG_VLAN_802_1Q) += 802_1Q +subdir-$(CONFIG_VLAN_8021Q) += 8021q obj-y := socket.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y)))) diff -u -r linux-2400t10vl14/net/core/dev.c linux-2400t10vl14m/net/core/dev.c --- linux-2400t10vl14/net/core/dev.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/core/dev.c Wed Nov 1 18:12:41 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * NET3 Protocol independent device support routines. * * This program is free software; you can redistribute it and/or @@ -98,8 +98,8 @@ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ #ifdef CONFIG_PLIP -#ifdef CONFIG_VLAN_802_1Q -#include "../802_1Q/vlan.h" +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#include "../8021q/vlan.h" #endif extern int plip_init(void); diff -u -r linux-2400t10vl14/net/ethernet/eth.c linux-2400t10vl14m/net/ethernet/eth.c --- linux-2400t10vl14/net/ethernet/eth.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/ethernet/eth.c Fri Nov 3 23:02:59 2000 @@ -103,7 +103,7 @@ * in here instead. It is up to the 802.2 layer to carry protocol information. */ - if(type!=ETH_P_802_3) + if (type != ETH_P_802_3) eth->h_proto = htons(type); else eth->h_proto = htons(len); @@ -129,7 +129,7 @@ if(daddr) { - memcpy(eth->h_dest,daddr,dev->addr_len); + memcpy(eth->h_dest, daddr, dev->addr_len); return dev->hard_header_len; } @@ -175,8 +175,6 @@ * assume 802.3 if the type field is short enough to be a length. * This is normal practice and works for any 'now in use' protocol. * - * NOTE: It is likely that you will want to change vlan_type_trans in - * 802_1Q/vlan.c if you change anything here. */ unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev) @@ -184,21 +182,10 @@ struct ethhdr *eth; unsigned char *rawp; - skb->mac.raw=skb->data; + eth = (struct ethhdr *)skb->data; + skb->mac.raw = skb->data; -#ifdef CONFIG_VLAN_802_1Q - /* Moving this below to be more selective. Reason is that for VLAN - * devices, we do not want to pull the header, we'll let the VLAN - * device do that instead. This makes default vlans (based on incoming - * port), much more sane! --BLG - */ - - /* skb_pull(skb,dev->hard_header_len); */ -#else skb_pull(skb,dev->hard_header_len); -#endif - - eth= skb->mac.ethernet; if(*eth->h_dest&1) { @@ -221,20 +208,6 @@ if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) skb->pkt_type=PACKET_OTHERHOST; } - -#ifdef CONFIG_VLAN_802_1Q - if (ntohs(eth->h_proto) == ETH_P_802_1Q) { - /* then we have to convert this into a VLAN looking packet. - * We'll wait to do that in the VLAN protocol handler. - * - * NOTE: We DO NOT PULL ANYTHING FROM THE SKB HERE!!! - */ - return __constant_htons(ETH_P_802_1Q); - } - else { - skb_pull(skb, dev->hard_header_len); - } -#endif if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; @@ -242,18 +215,18 @@ rawp = skb->data; /* - * This is a magic hack to spot IPX packets. Older Novell breaks - * the protocol design and runs IPX over 802.3 without an 802.2 LLC - * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This - * won't work for fault tolerant netware but does for the rest. + * This is a magic hack to spot IPX packets. Older Novell breaks + * the protocol design and runs IPX over 802.3 without an 802.2 LLC + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This + * won't work for fault tolerant netware but does for the rest. */ if (*(unsigned short *)rawp == 0xFFFF) - return htons(ETH_P_802_3); - + return __constant_htons(ETH_P_802_3); + /* * Real 802.2 LLC */ - return htons(ETH_P_802_2); + return __constant_htons(ETH_P_802_2); } int eth_header_parse(struct sk_buff *skb, unsigned char *haddr) diff -u -r linux-2400t10vl14/net/netsyms.c linux-2400t10vl14m/net/netsyms.c --- linux-2400t10vl14/net/netsyms.c Fri Oct 27 21:03:14 2000 +++ linux-2400t10vl14m/net/netsyms.c Fri Nov 3 21:24:11 2000 @@ -534,6 +534,8 @@ EXPORT_SYMBOL(qdisc_restart); EXPORT_SYMBOL(qdisc_create_dflt); EXPORT_SYMBOL(noop_qdisc); +extern struct Qdisc noqueue_qdisc; +EXPORT_SYMBOL(noqueue_qdisc); EXPORT_SYMBOL(qdisc_tree_lock); #ifdef CONFIG_NET_SCHED PSCHED_EXPORTLIST;