[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-vlan
Subject:    Re: [VLAN] Proposal: temporarily adopt NICE
From:       Ard van Breemen <ard () telegraafnet ! nl>
Date:       2001-10-22 9:50:27
[Download RAW message or body]

On Sat, Oct 20, 2001 at 04:03:37PM -0700, Ben Greear wrote:
> Is the NICE patch still considered stable?  Any changes since you
> sent me the 'diffie' patch?
Hi,
Sorry for the late reply... Had social things todo this weekend :(

I've attached the latest patch, that has that thing fixed of put_dev.
Annyway, this is straight from the package that I intend to upload for
debian users.

(The debian patch exist of the original patch, with seperate fixes, and
nice patch, so users have a choice, and you don't get bothered by my
bugs ;) ).
-- 
<ard@telegraafnet.nl> Telegraaf Elektronische Media  http://wwwijzer.nl
http://leerquoten.monster.org/ http://www.faqs.org/rfcs/rfc1855.html 
Let your government know you value your freedom. Sign the petition:
http://petition.eurolinux.org/

["vlan-nice.patch" (text/plain)]

diff -ruN -X exclude kernel-source-2.4.12-vanilla/net/8021q/Makefile \
                kernel-source-2.4.12/net/8021q/Makefile
--- kernel-source-2.4.12-vanilla/net/8021q/Makefile	Wed Oct 17 11:11:15 2001
+++ kernel-source-2.4.12/net/8021q/Makefile	Wed Oct 17 16:34:11 2001
@@ -9,7 +9,7 @@
 
 O_TARGET := 8021q.o
 
-obj-y := vlan.o vlanproc.o vlan_dev.o
+obj-y := vlan.o vlanproc.o vlan_dev.o vlan_nice.o
 obj-m := $(O_TARGET)
 obj-$(CONFIG_SYSCTL) += sysctl_net_vlan.o
 
diff -ruN -X exclude kernel-source-2.4.12-vanilla/net/8021q/nicext.h \
                kernel-source-2.4.12/net/8021q/nicext.h
--- kernel-source-2.4.12-vanilla/net/8021q/nicext.h	Thu Jan  1 01:00:00 1970
+++ kernel-source-2.4.12/net/8021q/nicext.h	Wed Oct 17 16:34:11 2001
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * Copyright(c) 2000-2001 Broadcom Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.          
+ *
+ * Name:        nicext.h
+ *
+ * Description: Broadcom Network Interface Card Extension (NICE) is an 
+ *              extension to Linux NET device kernel mode drivers. 
+ *              NICE is designed to provide additional functionalities, 
+ *              such as receive packet intercept. To support Broadcom NICE, 
+ *              the network device driver can be modified by adding an 
+ *              device ioctl handler and by indicating receiving packets 
+ *              to the NICE receive handler. Broadcom NICE will only be 
+ *              enabled by a NICE-aware intermediate driver, such as 
+ *              Broadcom Advanced Server Program Driver (BASP). When NICE 
+ *              is not enabled, the modified network device drivers 
+ *              functions exactly as other non-NICE aware drivers.
+ *
+ * Author:      Frankie Fan
+ *
+ * Created:     September 17, 2000
+ *
+ ****************************************************************************/
+#ifndef _nicext_h_
+#define _nicext_h_
+
+/*
+ * ioctl for NICE
+ */
+#define SIOCNICE                   	SIOCDEVPRIVATE+7
+
+/*
+ * SIOCNICE: 
+ *
+ * The following structure needs to be less than IFNAMSIZ (16 bytes) because
+ * we're overloading ifreq.ifr_ifru.
+ *
+ * If 16 bytes is not enough, we should consider relaxing this because
+ * this is no field after ifr_ifru in the ifreq structure. But we may
+ * run into future compatiability problem in case of changing struct ifreq.
+ */
+struct nice_req
+{
+    __u32 cmd;
+    
+    union
+    {
+        /* cmd = NICE_CMD_SET_RX or NICE_CMD_GET_RX */
+        struct
+        {
+            void (*nrqus1_rx)( struct sk_buff*, void* );
+            void* nrqus1_ctx;
+        } nrqu_nrqus1;
+
+        /* cmd = NICE_CMD_QUERY_SUPPORT */
+        struct
+        {
+            __u32 nrqus2_magic;
+            __u32 nrqus2_support_rx:1;
+            __u32 nrqus2_support_vlan:1;
+        } nrqu_nrqus2;
+    } nrq_nrqu;
+};
+
+#define nrq_rx           nrq_nrqu.nrqu_nrqus1.nrqus1_rx
+#define nrq_ctx          nrq_nrqu.nrqu_nrqus1.nrqus1_ctx
+#define nrq_support_rx   nrq_nrqu.nrqu_nrqus2.nrqus2_support_rx
+#define nrq_magic        nrq_nrqu.nrqu_nrqus2.nrqus2_magic
+#define nrq_support_vlan nrq_nrqu.nrqu_nrqus2.nrqus2_support_vlan
+
+/*
+ * magic constants
+ */
+#define NICE_REQUESTOR_MAGIC            0x4543494E // NICE in ascii
+#define NICE_DEVICE_MAGIC               0x4E494345 // ECIN in ascii
+
+/*
+ * command field
+ */
+#define NICE_CMD_QUERY_SUPPORT          0x00000001
+#define NICE_CMD_SET_RX                 0x00000002
+#define NICE_CMD_GET_RX                 0x00000003
+
+#endif  // _nicext_h_ 
+
diff -ruN -X exclude kernel-source-2.4.12-vanilla/net/8021q/vlan.c \
                kernel-source-2.4.12/net/8021q/vlan.c
--- kernel-source-2.4.12-vanilla/net/8021q/vlan.c	Wed Oct 17 11:11:15 2001
+++ kernel-source-2.4.12/net/8021q/vlan.c	Thu Oct 18 13:41:24 2001
@@ -34,6 +34,7 @@
 #include <linux/if_vlan.h>
 #include "vlan.h"
 #include "vlanproc.h"
+#include "vlan_nice.h"
 
 
 /* Global VLAN variables */
@@ -106,6 +107,20 @@
 }
 
 /*
+ * Cleanup of groups before exit
+ */
+
+static void vlan_group_cleanup(void) {
+	struct vlan_group* grp = NULL;
+	for (grp = p802_1Q_vlan_list; (grp != NULL);) {
+		struct vlan_group *nextgroup=grp->next;
+		nextgroup=grp->next;
+		kfree(grp);
+		grp = nextgroup;
+   }
+}
+
+/*
  *     Module 'remove' entry point.
  *     o delete /proc/net/router directory and static entries.
  */ 
@@ -115,6 +130,7 @@
 
         dev_remove_pack(&vlan_packet_type);
         vlan_proc_cleanup();
+		vlan_group_cleanup();
 
         vlan_ioctl_hook = NULL;
 }
@@ -159,6 +175,17 @@
 }/* find_802_1Q_vlan_client */
 
 
+/** Will search the vlan group table to see if there is a vlan defined
+ */
+
+int vlan_group_empty(struct vlan_group* grp) {
+	int i;
+	for(i=0;i<VLAN_GROUP_ARRAY_LEN;i++) {
+		if(grp->vlan_devices[i]) return 0;
+	}
+	return 1;
+}
+
 /** This method will explicitly do a dev_put on the device if do_dev_put
  * is TRUE.  This gets around a difficulty with reference counting, and
  * the unregister-by-name (below).  If do_locks is true, it will grab
@@ -209,7 +236,14 @@
                         else {
                                 unregister_netdevice(dev);
                         }
-
+						if(vlan_group_empty(grp)) {
+							struct net_device *real_dev;
+							real_dev=dev_get_by_index(real_dev_ifindex);
+							if(real_dev) {
+								vlan_nice_disable_rx(real_dev);
+								dev_put(real_dev);
+							}
+						}
                         MOD_DEC_USE_COUNT;
          
                 }/* if */
@@ -262,6 +296,7 @@
         struct net_device *new_dev;
         struct net_device *real_dev; /* the ethernet device */
         int malloc_size = 0;
+		int nice_supported =0; /* Is the device nice capable */
    
 #ifdef VLAN_DEBUG
         printk(VLAN_DBG __FUNCTION__ ": if_name -:%s:-  vid: %i\n",
@@ -297,6 +332,7 @@
                         if (new_dev != NULL) {
                                 /* printk(KERN_ALERT "Got a new device.."); */
             
+								nice_supported=vlan_nice_supported(real_dev);
                                 memset(new_dev, 0, malloc_size); /* zero everything \
out */  
                                 /* set us up to not use a Qdisc, as the underlying \
Hardware device @@ -361,8 +397,13 @@
                                 
                                 new_dev->type = real_dev->type; /* TODO: maybe just \
assign it to be ETHERNET? */  
-                                /* Regular ethernet + 4 bytes (18 total). */
-                                new_dev->hard_header_len = VLAN_HLEN + \
real_dev->hard_header_len; +								if(nice_supported) {
+									/* Regular ethernet, tag is done seperately */
+									new_dev->hard_header_len=real_dev->hard_header_len;
+								} else {
+									/* Regular ethernet + 4 bytes tag (18 total). */
+									new_dev->hard_header_len = VLAN_HLEN + real_dev->hard_header_len;
+								}
 
                                 new_dev->priv = kmalloc(sizeof(struct \
vlan_dev_info),  GFP_KERNEL);
@@ -379,9 +420,19 @@
 
                                 new_dev->open = vlan_dev_open;
                                 new_dev->stop = vlan_dev_stop;
-                                new_dev->hard_header = vlan_dev_hard_header;
 
-                                new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
+								if(nice_supported) {
+									/* We do not have to insert tags */
+									new_dev->hard_header=real_dev->hard_header;
+									/* We must send extra info in the skb */
+									new_dev->hard_start_xmit = vlan_nice_dev_hard_start_xmit;
+								} else {
+									/* We must insert tags */
+									new_dev->hard_header = vlan_dev_hard_header;
+									/* We must make sure it is tagged */
+									new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
+								}
+
                                 new_dev->rebuild_header = vlan_dev_rebuild_header;
                                 new_dev->hard_header_parse = \
                real_dev->hard_header_parse;
                                 new_dev->set_mac_address = vlan_dev_set_mac_address;
@@ -447,6 +498,11 @@
                                  * so hold on to the reference.
                                  */
                                 MOD_INC_USE_COUNT; /* Add was a success!! */
+								/** It is not a problem to re-enable again and again.
+								 * We must do it after MOD_INC_USE_COUNT, since only
+								 * then we are sure that our noce functions will not be removed
+								 */
+								vlan_nice_enable_rx(real_dev,grp);
 
 #ifdef VLAN_DEBUG
                                 printk(VLAN_DBG "Allocated new device successfully, \
                returning.\n");
diff -ruN -X exclude kernel-source-2.4.12-vanilla/net/8021q/vlan_nice.c \
                kernel-source-2.4.12/net/8021q/vlan_nice.c
--- kernel-source-2.4.12-vanilla/net/8021q/vlan_nice.c	Thu Jan  1 01:00:00 1970
+++ kernel-source-2.4.12/net/8021q/vlan_nice.c	Wed Oct 17 16:34:11 2001
@@ -0,0 +1,143 @@
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/in.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <net/datalink.h>
+#include <net/p8022.h>
+#include <net/arp.h>
+#include <linux/brlock.h>
+
+
+#include "vlan.h"
+#include "vlanproc.h"
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include "nicext.h"
+#include "vlan_nice.h"
+
+int vlan_nice_netif_rx(struct sk_buff *skb, struct vlan_group *grp) {
+	unsigned short vid;
+	struct net_device_stats* stats;
+	vlan_tag_t *nice_vlan;
+	struct net_device *dev;
+
+	unsigned short vlan_TCI;
+
+	/* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
+	nice_vlan=(vlan_tag_t *)&skb->cb[0];
+	if(NICE_VLAN_RXTAG!=nice_vlan->signature) {
+		/* Nope, do a plain netif_rx */
+		return netif_rx(skb);
+	}
+	/* Clear signature just in case */
+	nice_vlan->signature=0;
+	dev=skb->dev;
+	/* Yep, we got vlan */
+	vlan_TCI=nice_vlan->tag;
+	/*vlan_TCI = ntohs(vhdr->h_vlan_TCI);*/
+	vid = (vlan_TCI & 0xFFF);
+
+	/* At this moment we have to:
+	 * check if the vid is valid for this device
+	 * If it is, we do a netif_rx with the right skb->dev
+	 */
+
+#ifdef VLAN_DEBUG
+	printk(VLAN_DBG __FUNCTION__ ": skb: %p vlan_id: %hx\n",
+		   skb, vid);
+#endif
+
+	/* we have 12 bits of vlan ID. */
+	skb->dev = grp->vlan_devices[vid];
+
+	if (!skb->dev) {
+	#ifdef VLAN_DEBUG
+		printk(VLAN_DBG __FUNCTION__ ": ERROR:  No net_device for VID: %i on dev: %s \
[%i]\n", (unsigned int)(vid), dev->name, dev->ifindex); +	#endif
+		kfree_skb(skb);
+		return -1;
+	}
+
+	/* Bump the rx counters for the VLAN device. */
+	stats = vlan_dev_get_stats(skb->dev);
+	stats->rx_packets++;
+	stats->rx_bytes += skb->len;
+	return netif_rx(skb);
+}
+
+int vlan_nice_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) {
+        struct net_device_stats* stats = vlan_dev_get_stats(dev);
+		vlan_tag_t *nice_vlan;
+
+        /* Prepare vlan tag insertion by nice driver.
+         */
+                
+		nice_vlan=(vlan_tag_t *)&skb->cb[0];
+		nice_vlan->tag = VLAN_DEV_INFO(dev)->vlan_id;
+		nice_vlan->tag |= vlan_dev_get_egress_qos_mask(dev, skb);
+		nice_vlan->signature=NICE_VLAN_TXTAG;
+
+        skb->dev = VLAN_DEV_INFO(dev)->real_dev;
+        
+        dev_queue_xmit(skb);
+        stats->tx_packets++; /* for statics only */
+        stats->tx_bytes += skb->len;
+        return 0;
+}/* vlan_nice_dev_hard_start_xmit */
+
+int vlan_nice_supported(struct net_device *dev) {
+	static struct ifreq ifr;
+	static struct nice_req *nrq;
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	memset(&ifr,0,sizeof(ifr));
+	nrq=&ifr.ifr_ifru;
+	nrq->cmd=NICE_CMD_QUERY_SUPPORT;
+	if (((ioctl = dev->do_ioctl) != NULL) && (ioctl(dev, &ifr, SIOCNICE) == 0)) {
+		/* Now we have something nice? */
+		if(NICE_DEVICE_MAGIC==nrq->nrq_magic && nrq->nrq_support_rx) {
+			/* Yes. It supports _rx and vlan */
+			/* Actually the test is not complete, but the bcm5700 driver is also not complete \
*/ +			return 1;
+		}
+	}
+	printk(KERN_INFO "VLAN NICE: device %s is not NICE capable.\n",dev->name);
+	return 0;
+}
+
+int vlan_nice_enable_rx(struct net_device *dev, void *data) {
+	static struct ifreq ifr;
+	static struct nice_req *nrq;
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	memset(&ifr,0,sizeof(ifr));
+	nrq=&ifr.ifr_ifru;
+	if(!vlan_nice_supported(dev)) return 0;
+	nrq->cmd=NICE_CMD_SET_RX;
+	nrq->nrq_rx=vlan_nice_netif_rx;
+	nrq->nrq_ctx=data;
+	printk(KERN_INFO "VLAN NICE: enabling NICE on %s.\n",dev->name);
+	if (((ioctl = dev->do_ioctl) != NULL) && (ioctl(dev, &ifr, SIOCNICE) == 0)) {
+		/* Hmmm, ok.... */
+	}
+	return 0;
+}
+
+int vlan_nice_disable_rx(struct net_device *dev) {
+	static struct ifreq ifr;
+	static struct nice_req *nrq;
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	memset(&ifr,0,sizeof(ifr));
+	nrq=&ifr.ifr_ifru;
+	if(!vlan_nice_supported(dev)) return 0;
+	nrq->cmd=NICE_CMD_SET_RX;
+	nrq->nrq_rx=NULL;
+	nrq->nrq_ctx=NULL;
+	printk(KERN_INFO "VLAN NICE: disabling NICE on %s.\n",dev->name);
+	if (((ioctl = dev->do_ioctl) != NULL) && (ioctl(dev, &ifr, SIOCNICE) == 0)) {
+		/* Hmmm, ok.... */
+	}
+	return 0;
+}
+
diff -ruN -X exclude kernel-source-2.4.12-vanilla/net/8021q/vlan_nice.h \
                kernel-source-2.4.12/net/8021q/vlan_nice.h
--- kernel-source-2.4.12-vanilla/net/8021q/vlan_nice.h	Thu Jan  1 01:00:00 1970
+++ kernel-source-2.4.12/net/8021q/vlan_nice.h	Wed Oct 17 16:34:11 2001
@@ -0,0 +1,23 @@
+/******************************************************************************/
+/*                                                                            */
+/* This file is based on bcm5700.c written by Broadcom                        */
+/*                                                                            */
+/******************************************************************************/
+#include "nicext.h"
+
+#ifndef NICE_VLAN
+#define NICE_VLAN
+typedef struct {
+	unsigned short  tag;
+	unsigned short  signature;
+} vlan_tag_t;
+
+#define NICE_VLAN_TXTAG 0x5555
+#define NICE_VLAN_RXTAG 0x7777
+#define NICE_VLAN_EMPTY 0
+
+extern int vlan_nice_enable_rx(struct net_device *dev, void *data);
+extern int vlan_nice_disable_rx(struct net_device *dev);
+extern int vlan_nice_dev_hard_start_xmit(struct sk_buff *skb, struct net_device \
*dev); +
+#endif


_______________________________________________
VLAN mailing list  -  VLAN@Scry.WANfear.com
http://www.WANfear.com/mailman/listinfo/vlan
VLAN Page:  http://scry.wanfear.com/~greear/vlan.html


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic