kernel patch
Robert Morris
rtm at cag.lcs.mit.edu
Thu Jul 8 20:06:35 EDT 1999
I've appended a short script I used to make the kernel patch and the
patch itself. I'm not sure what to do with either -- I imagine we'll
soon have a subdirectory to hold release-building goodies. The patch
works fine with vanilla Linux 2.2.10; you can experience the resulting
kernel on cone.
#!/usr/local/bin/perl -w
# Make a patch file for a Linux kernel that adds our hooks.
# The resulting output can be used thus:
# cd /usr/src/linux
# patch -p0 -b < patch-file
# Directory of patched kernel source:
my $nd = "/opt1/rtm/linux-2.2.10";
# List of files that we modified and that should be patched.
# Each must be accompanied by a file.orig.
my @files = (
"include/linux/netdevice.h",
"net/core/dev.c",
"net/sched/sch_generic.c",
"net/netsyms.c"
);
chdir($nd);
$| = 1;
my $f;
foreach $f (@files) {
print "\nIndex: $f\n";
system("diff -u ${f}.orig $f");
}
Index: include/linux/netdevice.h
--- include/linux/netdevice.h.orig Sun May 16 21:28:41 1999
+++ include/linux/netdevice.h Thu Jul 8 14:54:47 1999
@@ -349,6 +349,11 @@
extern int unregister_netdevice(struct device *dev);
extern int register_netdevice_notifier(struct notifier_block *nb);
extern int unregister_netdevice_notifier(struct notifier_block *nb);
+extern int register_net_in(struct notifier_block *nb); /* Click */
+extern int unregister_net_in(struct notifier_block *nb); /* Click */
+extern int register_net_out(struct notifier_block *nb); /* Click */
+extern int unregister_net_out(struct notifier_block *nb); /* Click */
+extern void ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */
extern int dev_new_index(void);
extern struct device *dev_get_by_index(int ifindex);
extern int dev_restart(struct device *dev);
Index: net/core/dev.c
--- net/core/dev.c.orig Thu Mar 25 12:23:34 1999
+++ net/core/dev.c Thu Jul 8 14:52:10 1999
@@ -94,6 +94,8 @@
extern int plip_init(void);
#endif
+#include <asm/irq.h>
+
NET_PROFILE_DEFINE(dev_queue_xmit)
NET_PROFILE_DEFINE(net_bh)
NET_PROFILE_DEFINE(net_bh_skb)
@@ -145,6 +147,9 @@
static struct notifier_block *netdev_chain=NULL;
+/* input packet handlers -- might steal packets from net_bh(). for Click. */
+static struct notifier_block *net_in_chain = 0;
+
/*
* Device drivers call our routines to queue packets here. We empty the
* queue in the bottom half handler.
@@ -503,6 +508,22 @@
}
/*
+ * Allow Click modules to ask to intercept input packets.
+ * Must add these to ../netsyms.c
+ */
+int
+register_net_in(struct notifier_block *nb)
+{
+ return(notifier_chain_register(&net_in_chain, nb));
+}
+
+int
+unregister_net_in(struct notifier_block *nb)
+{
+ return(notifier_chain_unregister(&net_in_chain, nb));
+}
+
+/*
* Support routine. Sends outgoing frames to any network
* taps currently in use.
*/
@@ -819,6 +840,84 @@
}
#endif
+/*
+ * Hand a packet to the ordinary Linux protocol stack.
+ * Broke this out from net_bh() so that Click can call it.
+ * Always frees the skb one way or another.
+ *
+ * skb->pkt_type needs to be set to PACKET_{BROADCAST,MULTICAST,OTHERHOST}
+ * maybe skb->mac.raw must point to ether header.
+ * skb->protocol must be set to a htons(ETHERTYPE_?).
+ * skb->data must point to the ethernet payload (e.g. the IP header).
+ * skb->nh.raw must point to the ethernet payload also.
+ */
+void
+ptype_dispatch(struct sk_buff *skb, unsigned short type)
+{
+ struct packet_type *ptype;
+ struct packet_type *pt_prev;
+
+ /*
+ * We got a packet ID. Now loop over the "known protocols"
+ * list. There are two lists. The ptype_all list of taps (normally empty)
+ * and the main protocol list which is hashed perfectly for normal protocols.
+ */
+
+ pt_prev = NULL;
+ for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
+ {
+ if (!ptype->dev || ptype->dev == skb->dev) {
+ if(pt_prev)
+ {
+ struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
+ if(skb2)
+ pt_prev->func(skb2,skb->dev, pt_prev);
+ }
+ pt_prev=ptype;
+ }
+ }
+
+ for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
+ {
+ if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
+ {
+ /*
+ * We already have a match queued. Deliver
+ * to it and then remember the new match
+ */
+ if(pt_prev)
+ {
+ struct sk_buff *skb2;
+
+ skb2=skb_clone(skb, GFP_ATOMIC);
+
+ /*
+ * Kick the protocol handler. This should be fast
+ * and efficient code.
+ */
+
+ if(skb2)
+ pt_prev->func(skb2, skb->dev, pt_prev);
+ }
+ /* Remember the current last to do */
+ pt_prev=ptype;
+ }
+ } /* End of protocol list loop */
+
+ /*
+ * Is there a last item to send to ?
+ */
+
+ if(pt_prev)
+ pt_prev->func(skb, skb->dev, pt_prev);
+ /*
+ * Has an unknown packet has been received ?
+ */
+
+ else {
+ kfree_skb(skb);
+ }
+}
/*
* When we are called the queue is ready to grab, the interrupts are
@@ -827,13 +926,13 @@
* This is run as a bottom half after an interrupt handler that does
* mark_bh(NET_BH);
*/
-
+
void net_bh(void)
{
- struct packet_type *ptype;
- struct packet_type *pt_prev;
- unsigned short type;
unsigned long start_time = jiffies;
+ unsigned short type;
+ unsigned long long c0;
+ unsigned int cli_flags;
#ifdef CONFIG_CPU_IS_SLOW
static unsigned long start_busy = 0;
static unsigned long ave_busy = 0;
@@ -932,66 +1031,16 @@
handle_bridge(skb, type);
#endif
- /*
- * We got a packet ID. Now loop over the "known protocols"
- * list. There are two lists. The ptype_all list of taps (normally empty)
- * and the main protocol list which is hashed perfectly for normal protocols.
- */
-
- pt_prev = NULL;
- for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
- {
- if (!ptype->dev || ptype->dev == skb->dev) {
- if(pt_prev)
- {
- struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
- if(skb2)
- pt_prev->func(skb2,skb->dev, pt_prev);
- }
- pt_prev=ptype;
- }
- }
-
- for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
- {
- if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
- {
- /*
- * We already have a match queued. Deliver
- * to it and then remember the new match
- */
- if(pt_prev)
- {
- struct sk_buff *skb2;
-
- skb2=skb_clone(skb, GFP_ATOMIC);
-
- /*
- * Kick the protocol handler. This should be fast
- * and efficient code.
- */
-
- if(skb2)
- pt_prev->func(skb2, skb->dev, pt_prev);
- }
- /* Remember the current last to do */
- pt_prev=ptype;
- }
- } /* End of protocol list loop */
-
- /*
- * Is there a last item to send to ?
- */
+ /* does Click want to steal this packet? */
+ if(notifier_call_chain(&net_in_chain, 0, skb) & NOTIFY_STOP_MASK)
+ continue;
+
+ /*
+ * Ordinary Linux dispatch based on packet type.
+ * Moved into a function so Click can call it.
+ */
+ ptype_dispatch(skb, type);
- if(pt_prev)
- pt_prev->func(skb, skb->dev, pt_prev);
- /*
- * Has an unknown packet has been received ?
- */
-
- else {
- kfree_skb(skb);
- }
} /* End of queue loop */
/*
@@ -1019,11 +1068,13 @@
netdev_dropping = 0;
#endif
NET_PROFILE_LEAVE(net_bh);
+
return;
net_bh_break:
mark_bh(NET_BH);
NET_PROFILE_LEAVE(net_bh);
+
return;
}
Index: net/sched/sch_generic.c
--- net/sched/sch_generic.c.orig Sun Mar 21 10:22:00 1999
+++ net/sched/sch_generic.c Thu Jul 8 14:52:29 1999
@@ -76,6 +76,24 @@
return q->q.qlen;
}
+/*
+ * Click hooks to be notified when a network device
+ * is idle and could send a packet.
+ */
+static struct notifier_block *net_out_chain = 0;
+
+int
+register_net_out(struct notifier_block *nb)
+{
+ return(notifier_chain_register(&net_out_chain, nb));
+}
+
+int
+unregister_net_out(struct notifier_block *nb)
+{
+ return(notifier_chain_unregister(&net_out_chain, nb));
+}
+
/* Scan transmission queue and kick devices.
Deficiency: slow devices (ppp) and fast ones (100Mb ethernet)
@@ -93,9 +111,14 @@
hp = &qdisc_head.forw;
while ((h = *hp) != &qdisc_head) {
int res = -1;
+ int res1 = -1;
struct Qdisc *q = (struct Qdisc*)h;
struct device *dev = q->dev;
+ /* Click */
+ if(dev->tbusy == 0)
+ res1 = notifier_call_chain(&net_out_chain, 0, dev);
+
while (!dev->tbusy && (res = qdisc_restart(dev)) < 0)
/* NOTHING */;
@@ -108,7 +131,7 @@
No problem, we will unlink it during the next round.
*/
- if (res == 0 && *hp == h) {
+ if (res1 == 0 && res == 0 && *hp == h) {
*hp = h->forw;
h->forw = NULL;
continue;
Index: net/netsyms.c
--- net/netsyms.c.orig Sat Apr 24 20:51:48 1999
+++ net/netsyms.c Thu Jul 8 14:51:52 1999
@@ -431,6 +431,13 @@
EXPORT_SYMBOL(register_netdevice_notifier);
EXPORT_SYMBOL(unregister_netdevice_notifier);
+/* Click */
+EXPORT_SYMBOL(register_net_in);
+EXPORT_SYMBOL(unregister_net_in);
+EXPORT_SYMBOL(register_net_out);
+EXPORT_SYMBOL(unregister_net_out);
+EXPORT_SYMBOL(ptype_dispatch);
+
/* support for loadable net drivers */
#ifdef CONFIG_NET
EXPORT_SYMBOL(loopback_dev);
More information about the click
mailing list