Modularized net bridging PATCH against pre-2.1.104-1

Adam J. Richter (adam@yggdrasil.com)
Sun, 24 May 1998 02:58:12 -0700


Here is a patch that modularizes the ethernet
bridge support in the kernel. This allows a piece of functionality
that is used only very specialized circumstances to be available
from a single kernel binary configured to support everything without
it needing to take up space or causing a confusing boot time message.
This patch includes kmod support. If you are running kmod, the bridge
module will automatically be loaded if you try to configure an
ethernet bridge.

The last time I tried the kernel bridging code (~2.1.98), the
kernel would always crash within seconds, and it would take some
time to set up a system for testing with the latest kernels, so
I don't know if this code works or not. I do know that it seems
to load and unload just fine. Anyhow, I would appreciate feedback
from anybody who is using the bridging code on whether these
modularization changes break anything. I hope you find this
software useful.

Adam J. Richter __ ______________ 4880 Stevens Creek Blvd, Suite 205
adam@yggdrasil.com \ / San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l United States of America
fax +1 408 261-6631 "Free Software For The Rest Of Us."
---------------------CUT HERE-----------------------------------

--- /tmp/linux-2.1.104pre1/./include/net/br.h Fri Apr 3 17:48:11 1998
+++ linux/./include/net/br.h Sat May 23 22:06:56 1998
@@ -298,4 +298,9 @@

extern struct br_stat br_stats;

+#ifdef CONFIG_BRIDGE_MODULE
+extern void (*handle_bridge_hook)(struct sk_buff *skb, unsigned short type);
+extern int (*br_ioctl_hook)(unsigned int, void *);
+#endif
+

--- /tmp/linux-2.1.104pre1/./net/netsyms.c Thu May 14 10:35:55 1998
+++ linux/./net/netsyms.c Sat May 23 22:40:46 1998
@@ -17,7 +17,7 @@
#include <net/neighbour.h>
#include <net/snmp.h>

-#ifdef CONFIG_BRIDGE
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <net/br.h>
#endif

@@ -200,6 +200,12 @@
EXPORT_SYMBOL(br_ioctl);
#endif

+#ifdef CONFIG_BRIDGE_MODULE
+EXPORT_SYMBOL(br_ioctl);
+EXPORT_SYMBOL(br_ioctl_hook);
+EXPORT_SYMBOL(handle_bridge_hook);
+#endif
+
#ifdef CONFIG_INET
/* Internet layer registration */
EXPORT_SYMBOL(inet_add_protocol);
@@ -218,6 +224,7 @@
EXPORT_SYMBOL(ip_fragment);
EXPORT_SYMBOL(inet_family_ops);
EXPORT_SYMBOL(in_aton);
+EXPORT_SYMBOL(in_ntoa);
EXPORT_SYMBOL(ip_mc_inc_group);
EXPORT_SYMBOL(ip_mc_dec_group);
EXPORT_SYMBOL(__ip_finish_output);
--- /tmp/linux-2.1.104pre1/./net/core/dev.c Wed May 6 10:56:06 1998
+++ linux/./net/core/dev.c Sat May 23 22:06:57 1998
@@ -94,6 +94,11 @@
NET_PROFILE_DEFINE(net_bh)
NET_PROFILE_DEFINE(net_bh_skb)

+#ifdef CONFIG_BRIDGE
+extern void handle_bridge(struct sk_buff *skb, unsigned short type);
+#elif defined(CONFIG_BRIDGE_MODULE)
+void (*handle_bridge_hook)(struct sk_buff *skb, unsigned short type) = NULL;
+#endif

const char *if_port_text[] = {
"unknown",
@@ -730,35 +735,6 @@
kfree_skb(skb);
}

-#ifdef CONFIG_BRIDGE
-static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
-{
- if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(type)))
- {
- /*
- * We pass the bridge a complete frame. This means
- * recovering the MAC header first.
- */
-
- int offset=skb->data-skb->mac.raw;
- cli();
- skb_push(skb,offset); /* Put header back on for bridge */
- if(br_receive_frame(skb))
- {
- sti();
- return;
- }
- /*
- * Pull the MAC header off for the copy going to
- * the upper layers.
- */
- skb_pull(skb,offset);
- sti();
- }
-}
-#endif
-
-
/*
* When we are called the queue is ready to grab, the interrupts are
* on and hardware can interrupt and queue to the receive queue as we
@@ -849,13 +825,15 @@
type = skb->protocol;


-#ifdef CONFIG_BRIDGE
+#if defined(CONFIG_BRIDGE)
/*
* If we are bridging then pass the frame up to the
* bridging code (if this protocol is to be bridged).
* If it is bridged then move on
*/
- handle_bridge(skb, type);
+ handle_bridge(skb, type);
+#elif defined(CONFIG_BRIDGE_MODULE)
+ if (handle_bridge_hook) (*handle_bridge_hook)(skb,type);
#endif

/*
--- /tmp/linux-2.1.104pre1/./net/ipv4/af_inet.c Thu May 14 10:26:23 1998
+++ linux/./net/ipv4/af_inet.c Sat May 23 21:55:01 1998
@@ -105,7 +105,7 @@
#ifdef CONFIG_IP_MASQUERADE
#include <net/ip_masq.h>
#endif
-#ifdef CONFIG_BRIDGE
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <net/br.h>
#endif
#ifdef CONFIG_KMOD
@@ -143,6 +143,21 @@
* Destroy an AF_INET socket
*/

+
+#ifdef CONFIG_BRIDGE_MODULE
+
+int (*br_ioctl_hook) (unsigned int cmd, void *arg) = NULL;
+
+int br_ioctl(unsigned int cmd, void *arg) {
+# ifdef CONFIG_KMOD
+ if (br_ioctl_hook == NULL)
+ request_module("bridge");
+# endif/* CONFIG_KMOD */
+ return (br_ioctl_hook == NULL) ? -ENOPKG : (*br_ioctl_hook)(cmd,arg);
+}
+#endif /* CONFIG_BRIDGE_MODULE */
+
+
static __inline__ void kill_sk_queues(struct sock *sk)
{
struct sk_buff *skb;
@@ -855,6 +870,7 @@
* There's a good 20K of config code hanging around the kernel.
*/

+
static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
@@ -915,12 +931,11 @@
return(devinet_ioctl(cmd,(void *) arg));
case SIOCGIFBR:
case SIOCSIFBR:
-#ifdef CONFIG_BRIDGE
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
return(br_ioctl(cmd,(void *) arg));
#else
return -ENOPKG;
-#endif
-
+#endif
case SIOCADDDLCI:
case SIOCDELDLCI:
#ifdef CONFIG_DLCI
--- /tmp/linux-2.1.104pre1/./net/packet/af_packet.c Fri May 8 00:08:02 1998
+++ linux/./net/packet/af_packet.c Sat May 23 21:19:13 1998
@@ -71,7 +71,7 @@
#include <net/inet_common.h>
#endif

-#ifdef CONFIG_BRIDGE
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <net/br.h>
#endif

@@ -1130,12 +1130,12 @@

case SIOCGIFBR:
case SIOCSIFBR:
-#ifdef CONFIG_BRIDGE
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
return(br_ioctl(cmd,(void *) arg));
#else
return -ENOPKG;
#endif
-
+
#ifdef CONFIG_INET
case SIOCADDRT:
case SIOCDELRT:
--- /tmp/linux-2.1.104pre1/./net/Makefile Sun Nov 30 14:00:39 1997
+++ linux/./net/Makefile Sat May 23 20:42:02 1998
@@ -58,6 +58,10 @@

ifeq ($(CONFIG_BRIDGE),y)
SUB_DIRS += bridge
+else
+ ifeq ($(CONFIG_BRIDGE),m)
+ MOD_SUB_DIRS += bridge
+ endif
endif

ifeq ($(CONFIG_IPX),y)
--- /tmp/linux-2.1.104pre1/./net/bridge/Makefile Tue Apr 28 11:10:10 1998
+++ linux/./net/bridge/Makefile Sat May 23 23:48:28 1998
@@ -8,6 +8,8 @@
# Note 2! The CFLAGS definition is now in the main makefile...

O_TARGET := bridge.o
+MOD_LIST_NAME := NET_MISC_MODULES
+
O_OBJS := br.o br_tree.o
M_OBJS := $(O_TARGET)

--- /tmp/linux-2.1.104pre1/./net/bridge/br.c Wed Apr 1 16:19:57 1998
+++ linux/./net/bridge/br.c Sat May 23 22:55:23 1998
@@ -47,7 +47,10 @@
* Put the path costs in the port info and devices.
* Put the bridge port number in the device structure for speed.
* Bridge SNMP stats.
- *
+ * Add calls to MOD_{INC,DEC}_USE_COUNT rather than leaving
+ * the module marked as "unused" (this is OK, because
+ * "rmmod -a" does not automatically remove modules marked
+ * as "unused").
*/

#include <linux/errno.h>
@@ -71,6 +74,14 @@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <net/br.h>
+#ifdef MODULE
+# include <linux/module.h>
+# include <linux/config.h>
+# ifdef CONFIG_SYSCTL
+# include <linux/sysctl.h>
+# endif
+#endif
+

#ifndef min
#define min(a, b) (((a) <= (b)) ? (a) : (b))
@@ -155,6 +166,19 @@
int max_mcast_per_period = MAX_MCAST_PER_PERIOD;
int mcast_hold_time = MCAST_HOLD_TIME;

+#ifdef MODULE
+extern void (*handle_bridge_hook)(struct sk_buff *skb, unsigned short type);
+extern int (*bridge_ioctl_hook)(unsigned int, void *);
+
+static void handle_bridge(struct sk_buff *skb, unsigned short type);
+static int br_ioctl_local(unsigned int cmd, void *arg);
+
+#ifdef CONFIG_SYSCTL
+extern ctl_table bridge_table[];
+static struct ctl_table_header *ctl_table_header;
+#endif
+#endif
+
/* JRP: next two bpdu are copied to skbuff so we need only 1 of each */
static Config_bpdu config_bpdu;
static Tcn_bpdu tcn_bpdu;
@@ -802,12 +826,35 @@
} /* (4.6.1.2.3) */
}

+
+#ifdef MODULE
+void cleanup_module(void) {
+ handle_bridge_hook = NULL;
+ br_ioctl_hook = NULL;
+#ifdef CONFIG_SYSCTL
+ if (ctl_table_header != NULL) {
+ unregister_sysctl_table(ctl_table_header);
+ }
+#endif
+}
+
+int init_module(void)
+#else
__initfunc(void br_init(void))
+#endif
{ /* (4.8.1) */
int port_no;

printk(KERN_INFO "Ethernet Bridge 005 for NET3.037 (Linux 2.1)\n");

+#ifdef MODULE
+ handle_bridge_hook = handle_bridge;
+ br_ioctl_hook = br_ioctl_local;
+# ifdef CONFIG_SYSCTL
+ ctl_table_header = register_sysctl_table(bridge_table, 0);
+# endif
+#endif
+
/*
* Form initial topology change time.
* The topology change timer is only used if this is the root bridge.
@@ -857,6 +904,9 @@
br_stats.policy = BR_ACCEPT; /* Enable bridge to accpet all protocols */
br_stats.exempt_protocols = 0;
/*start_hello_timer();*/
+#ifdef MODULE
+ return 0;
+#endif
}

static inline unsigned short make_port_id(int port_no)
@@ -1889,7 +1939,11 @@
return fdbis;
}

+#ifdef MODULE
+static int br_ioctl_local(unsigned int cmd, void *arg)
+#else
int br_ioctl(unsigned int cmd, void *arg)
+#endif
{
int err, i;
struct br_cf bcf;
@@ -2059,4 +2113,35 @@
return(1);
}
return(0);
+}
+
+#ifdef MODULE
+static
+#endif
+void
+handle_bridge(struct sk_buff *skb, unsigned short type)
+{
+
+ if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(type)))
+ {
+ /*
+ * We pass the bridge a complete frame. This means
+ * recovering the MAC header first.
+ */
+
+ int offset=skb->data-skb->mac.raw;
+ cli();
+ skb_push(skb,offset); /* Put header back on for bridge */
+ if(br_receive_frame(skb))
+ {
+ sti();
+ return;
+ }
+ /*
+ * Pull the MAC header off for the copy going to
+ * the upper layers.
+ */
+ skb_pull(skb,offset);
+ sti();
+ }
}
--- /tmp/linux-2.1.104pre1/./net/Config.in Tue Apr 28 11:10:10 1998
+++ linux/./net/Config.in Sat May 23 20:41:30 1998
@@ -37,7 +37,7 @@
# fi
tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25
tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB
- bool 'Bridging (EXPERIMENTAL)' CONFIG_BRIDGE
+ tristate 'Bridging (EXPERIMENTAL)' CONFIG_BRIDGE
bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
# if [ "$CONFIG_LLC" = "y" ]; then
# bool 'Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI
--S.pNyT/970962=_/vger.rutgers.edu--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu