patch-2.1.20 linux/net/core/dev.c
Next file: linux/net/core/dev_mcast.c
Previous file: linux/net/core/datagram.c
Back to the patch index
Back to the overall index
- Lines: 341
- Date:
Thu Jan 2 15:13:28 1997
- Orig file:
v2.1.19/linux/net/core/dev.c
- Orig date:
Sun Dec 22 16:37:43 1996
diff -u --recursive --new-file v2.1.19/linux/net/core/dev.c linux/net/core/dev.c
@@ -78,9 +78,7 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <net/br.h>
-#ifdef CONFIG_NET_ALIAS
#include <linux/net_alias.h>
-#endif
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
@@ -91,14 +89,30 @@
/*
* The list of devices, that are able to output.
*/
+
static struct device *dev_up_base;
/*
* The list of packet types we will receive (as opposed to discard)
* and the routines to invoke.
+ *
+ * Why 16. Because with 16 the only overlap we get on a hash of the
+ * low nibble of the protocol value is RARP/SNAP/X.25.
+ *
+ * 0800 IP
+ * 0001 802.3
+ * 0002 AX.25
+ * 0004 802.2
+ * 8035 RARP
+ * 0005 SNAP
+ * 0805 X.25
+ * 0806 ARP
+ * 8137 IPX
+ * 0009 Localtalk
+ * 86DD IPv6
*/
-struct packet_type *ptype_base[16];
+struct packet_type *ptype_base[16]; /* 16 way hashed list */
struct packet_type *ptype_all = NULL; /* Taps */
/*
@@ -243,6 +257,7 @@
/*
* Call device private open method
*/
+
if (dev->open)
ret = dev->open(dev);
@@ -259,11 +274,12 @@
*/
dev_mc_upload(dev);
notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
-#ifdef CONFIG_NET_ALIAS
- if (!net_alias_is(dev) || dev->tx_queue_len)
-#else
- if (dev->tx_queue_len)
-#endif
+ /*
+ * FIXME: This logic was wrong before. Now its
+ * obviously so. I think the change here (removing the
+ * ! on the net_alias_is) is right. ANK ??
+ */
+ if (net_alias_is(dev) || dev->tx_queue_len)
{
cli();
dev->next_up = dev_up_base;
@@ -301,6 +317,7 @@
/*
* Tell people we are going down
*/
+
notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
/*
* Flush the multicast chain
@@ -318,6 +335,10 @@
ct++;
}
+ /*
+ * The device is no longer up. Drop it from the list.
+ */
+
devp = &dev_up_base;
while (*devp)
{
@@ -348,6 +369,34 @@
}
/*
+ * Support routine. Sends outgoing frames to any network
+ * taps currently in use.
+ */
+
+static void queue_xmit_nit(struct sk_buff *skb, struct device *dev)
+{
+ struct packet_type *ptype;
+ get_fast_time(&skb->stamp);
+
+ for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next)
+ {
+ /* Never send packets back to the socket
+ * they originated from - MvS (miquels@drinkel.ow.org)
+ */
+ if ((ptype->dev == dev || !ptype->dev) &&
+ ((struct sock *)ptype->data != skb->sk))
+ {
+ struct sk_buff *skb2;
+ if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
+ break;
+ skb2->mac.raw = skb2->data;
+ skb2->nh.raw = skb2->h.raw = skb2->data + dev->hard_header_len;
+ ptype->func(skb2, skb->dev, ptype);
+ }
+ }
+}
+
+/*
* Send (or queue for sending) a packet.
*
* IMPORTANT: When this is called to resend frames. The caller MUST
@@ -403,41 +452,30 @@
list = dev->buffs + pri;
save_flags(flags);
- /* if this isn't a retransmission, use the first packet instead... */
- if (!retransmission) {
- if (skb_queue_len(list)) {
- /* avoid overrunning the device queue.. */
- if (skb_queue_len(list) > dev->tx_queue_len) {
- dev_kfree_skb(skb, FREE_WRITE);
- return;
- }
- }
- /* copy outgoing packets to any sniffer packet handlers */
- if (dev_nit) {
- struct packet_type *ptype;
-
- get_fast_time(&skb->stamp);
+ /*
+ * If this isn't a retransmission, use the first packet instead.
+ * Note: We don't do strict priority ordering here. We will in
+ * fact kick the queue that is our priority. The dev_tint reload
+ * does strict priority queueing. In effect what we are doing here
+ * is to add some random jitter to the queues and to do so by
+ * saving clocks. Doing a perfect priority queue isn't a good idea
+ * as you get some fascinating timing interactions.
+ */
- for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next)
- {
- /* Never send packets back to the socket
- * they originated from - MvS (miquels@drinkel.ow.org)
- */
- if ((ptype->dev == dev || !ptype->dev) &&
- ((struct sock *)ptype->data != skb->sk))
- {
- struct sk_buff *skb2;
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
- break;
- skb2->mac.raw = skb2->data;
- skb2->nh.raw =
- skb2->h.raw = skb2->data + dev->hard_header_len;
- ptype->func(skb2, skb->dev, ptype);
- }
- }
+ if (!retransmission)
+ {
+ /* avoid overrunning the device queue.. */
+ if (skb_queue_len(list) > dev->tx_queue_len)
+ {
+ dev_kfree_skb(skb, FREE_WRITE);
+ return;
}
+ /* copy outgoing packets to any sniffer packet handlers */
+ if (dev_nit)
+ queue_xmit_nit(skb,dev);
+
if (skb_queue_len(list)) {
cli();
__skb_queue_tail(list, skb);
@@ -461,13 +499,16 @@
restore_flags(flags);
}
+/*
+ * Entry point for transmitting frames.
+ */
+
int dev_queue_xmit(struct sk_buff *skb)
{
struct device *dev = skb->dev;
start_bh_atomic();
-
#if CONFIG_SKB_CHECK
IS_SKB(skb);
#endif
@@ -477,13 +518,23 @@
* This can cover all protocols and technically not just ARP either.
*/
- if (!skb->arp) {
- if (dev->rebuild_header) {
- if (dev->rebuild_header(skb)) {
+ if (!skb->arp)
+ {
+ /*
+ * FIXME: we should make the printk for no rebuild
+ * header a default rebuild_header routine and drop
+ * this call. Similarly we should make hard_header
+ * have a default NULL operation not check conditions.
+ */
+ if (dev->rebuild_header)
+ {
+ if (dev->rebuild_header(skb))
+ {
end_bh_atomic();
return 0;
}
- } else
+ }
+ else
printk("%s: !skb->arp & !rebuild_header!\n", dev->name);
}
@@ -495,16 +546,18 @@
*
*/
-#ifdef CONFIG_NET_ALIAS
if (net_alias_is(dev))
skb->dev = dev = net_alias_main_dev(dev);
-#endif
do_dev_queue_xmit(skb, dev, skb->priority);
end_bh_atomic();
return 0;
}
+/*
+ * Fast path for loopback frames.
+ */
+
void dev_loopback_xmit(struct sk_buff *skb)
{
struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC);
@@ -521,8 +574,7 @@
/*
* Receive a packet from a device driver and queue it for the upper
- * (protocol) levels. It always succeeds. This is the recommended
- * interface to use.
+ * (protocol) levels. It always succeeds.
*/
void netif_rx(struct sk_buff *skb)
@@ -582,7 +634,8 @@
for (dev = dev_up_base; dev != NULL; dev = dev->next_up)
{
- if (dev->flags != 0 && !dev->tbusy) {
+ if (dev->flags != 0 && !dev->tbusy)
+ {
/*
* Kick the device
*/
@@ -636,7 +689,8 @@
* disabling interrupts.
*/
- while (!skb_queue_empty(&backlog)) {
+ while (!skb_queue_empty(&backlog))
+ {
struct sk_buff * skb = backlog.next;
/*
@@ -658,8 +712,6 @@
continue;
}
-
-
#ifdef CONFIG_BRIDGE
/*
@@ -783,9 +835,7 @@
* One last output flush.
*/
-#ifdef XMIT_AFTER
dev_transmit();
-#endif
}
@@ -804,12 +854,11 @@
* aliases do not transmit (for now :) )
*/
-#ifdef CONFIG_NET_ALIAS
if (net_alias_is(dev)) {
printk("net alias %s transmits\n", dev->name);
return;
}
-#endif
+
head = dev->buffs;
save_flags(flags);
cli();
@@ -848,7 +897,7 @@
/*
* Perform a SIOCGIFCONF call. This structure will change
- * size shortly, and there is nothing I can do about it.
+ * size eventually, and there is nothing I can do about it.
* Thus we will need a 'compatibility mode'.
*/
@@ -1426,6 +1475,7 @@
extern int pt_init(void);
extern int sm_init(void);
extern int baycom_init(void);
+extern int lapbeth_init(void);
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry proc_net_dev = {
@@ -1496,6 +1546,9 @@
#endif
#if defined(CONFIG_SOUNDMODEM)
sm_init();
+#endif
+#if defined(CONFIG_LAPBETHER)
+ lapbeth_init();
#endif
/*
* SLHC if present needs attaching so other people see it
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov