Commit 97c29f59 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/garz/repo/netdev-2.6/tuntap

into pobox.com:/garz/repo/net-drivers-2.6
parents 11ab9af3 7244c042
...@@ -84,6 +84,7 @@ config EQUALIZER ...@@ -84,6 +84,7 @@ config EQUALIZER
config TUN config TUN
tristate "Universal TUN/TAP device driver support" tristate "Universal TUN/TAP device driver support"
depends on NETDEVICES depends on NETDEVICES
select CRC32
---help--- ---help---
TUN/TAP provides packet reception and transmission for user space TUN/TAP provides packet reception and transmission for user space
programs. It can be viewed as a simple Point-to-Point or Ethernet programs. It can be viewed as a simple Point-to-Point or Ethernet
......
...@@ -16,11 +16,25 @@ ...@@ -16,11 +16,25 @@
*/ */
/* /*
* Changes:
*
* Mark Smith <markzzzsmith@yahoo.com.au>
* Use random_ether_addr() for tap MAC address.
*
* Harald Roelle <harald.roelle@ifi.lmu.de> 2004/04/20
* Fixes in packet dropping, queue length setting and queue wakeup.
* Increased default tx queue length.
* Added ethtool API.
* Minor cleanups
*
* Daniel Podlejski <underley@underley.eu.org> * Daniel Podlejski <underley@underley.eu.org>
* Modifications for 2.3.99-pre5 kernel. * Modifications for 2.3.99-pre5 kernel.
*/ */
#define TUN_VER "1.5" #define DRV_NAME "tun"
#define DRV_VERSION "1.6"
#define DRV_DESCRIPTION "Universal TUN/TAP device driver"
#define DRV_COPYRIGHT "(C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>"
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -31,11 +45,11 @@ ...@@ -31,11 +45,11 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/random.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/ethtool.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
...@@ -53,6 +67,7 @@ static int debug; ...@@ -53,6 +67,7 @@ static int debug;
/* Network device part of the driver */ /* Network device part of the driver */
static LIST_HEAD(tun_dev_list); static LIST_HEAD(tun_dev_list);
static struct ethtool_ops tun_ethtool_ops;
/* Net device open. */ /* Net device open. */
static int tun_net_open(struct net_device *dev) static int tun_net_open(struct net_device *dev)
...@@ -79,18 +94,24 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -79,18 +94,24 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
if (!tun->attached) if (!tun->attached)
goto drop; goto drop;
/* Queue packet */ /* Packet dropping */
if (skb_queue_len(&tun->readq) >= dev->tx_queue_len) {
if (!(tun->flags & TUN_ONE_QUEUE)) { if (!(tun->flags & TUN_ONE_QUEUE)) {
/* Normal queueing mode. /* Normal queueing mode. */
* Packet scheduler handles dropping. */ /* Packet scheduler handles dropping of further packets. */
if (skb_queue_len(&tun->readq) >= TUN_READQ_SIZE)
netif_stop_queue(dev); netif_stop_queue(dev);
/* We won't see all dropped packets individually, so overrun
* error is more appropriate. */
tun->stats.tx_fifo_errors++;
} else { } else {
/* Single queue mode. /* Single queue mode.
* Driver handles dropping itself. */ * Driver handles dropping of all packets itself. */
if (skb_queue_len(&tun->readq) >= dev->tx_queue_len)
goto drop; goto drop;
} }
}
/* Queue packet */
skb_queue_tail(&tun->readq, skb); skb_queue_tail(&tun->readq, skb);
/* Notify and wake up reader process */ /* Notify and wake up reader process */
...@@ -164,18 +185,16 @@ static void tun_net_init(struct net_device *dev) ...@@ -164,18 +185,16 @@ static void tun_net_init(struct net_device *dev)
/* Zero header length */ /* Zero header length */
dev->type = ARPHRD_NONE; dev->type = ARPHRD_NONE;
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->tx_queue_len = 10; dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */
break; break;
case TUN_TAP_DEV: case TUN_TAP_DEV:
/* Ethernet TAP Device */ /* Ethernet TAP Device */
dev->set_multicast_list = tun_net_mclist; dev->set_multicast_list = tun_net_mclist;
/* Generate random Ethernet address. */
*(u16 *)dev->dev_addr = htons(0x00FF);
get_random_bytes(dev->dev_addr + sizeof(u16), 4);
ether_setup(dev); ether_setup(dev);
random_ether_addr(dev->dev_addr);
dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */
break; break;
} }
} }
...@@ -354,7 +373,7 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv, ...@@ -354,7 +373,7 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
schedule(); schedule();
continue; continue;
} }
netif_start_queue(tun->dev); netif_wake_queue(tun->dev);
/** Decide whether to accept this packet. This code is designed to /** Decide whether to accept this packet. This code is designed to
* behave identically to an Ethernet interface. Accept the packet if * behave identically to an Ethernet interface. Accept the packet if
...@@ -418,6 +437,7 @@ static void tun_setup(struct net_device *dev) ...@@ -418,6 +437,7 @@ static void tun_setup(struct net_device *dev)
dev->hard_start_xmit = tun_net_xmit; dev->hard_start_xmit = tun_net_xmit;
dev->stop = tun_net_close; dev->stop = tun_net_close;
dev->get_stats = tun_net_stats; dev->get_stats = tun_net_stats;
dev->ethtool_ops = &tun_ethtool_ops;
dev->destructor = free_netdev; dev->destructor = free_netdev;
} }
...@@ -736,12 +756,97 @@ static struct miscdevice tun_miscdev = { ...@@ -736,12 +756,97 @@ static struct miscdevice tun_miscdev = {
.devfs_name = "net/tun", .devfs_name = "net/tun",
}; };
/* ethtool interface */
static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
cmd->supported = 0;
cmd->advertising = 0;
cmd->speed = SPEED_10;
cmd->duplex = DUPLEX_FULL;
cmd->port = PORT_TP;
cmd->phy_address = 0;
cmd->transceiver = XCVR_INTERNAL;
cmd->autoneg = AUTONEG_DISABLE;
cmd->maxtxpkt = 0;
cmd->maxrxpkt = 0;
return 0;
}
static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct tun_struct *tun = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
strcpy(info->fw_version, "N/A");
switch (tun->flags & TUN_TYPE_MASK) {
case TUN_TUN_DEV:
strcpy(info->bus_info, "tun");
break;
case TUN_TAP_DEV:
strcpy(info->bus_info, "tap");
break;
}
}
static u32 tun_get_msglevel(struct net_device *dev)
{
#ifdef TUN_DEBUG
struct tun_struct *tun = netdev_priv(dev);
return tun->debug;
#else
return -EOPNOTSUPP;
#endif
}
static void tun_set_msglevel(struct net_device *dev, u32 value)
{
#ifdef TUN_DEBUG
struct tun_struct *tun = netdev_priv(dev);
tun->debug = value;
#endif
}
static u32 tun_get_link(struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
return tun->attached;
}
static u32 tun_get_rx_csum(struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
return (tun->flags & TUN_NOCHECKSUM) == 0;
}
static int tun_set_rx_csum(struct net_device *dev, u32 data)
{
struct tun_struct *tun = netdev_priv(dev);
if (data)
tun->flags &= ~TUN_NOCHECKSUM;
else
tun->flags |= TUN_NOCHECKSUM;
return 0;
}
static struct ethtool_ops tun_ethtool_ops = {
.get_settings = tun_get_settings,
.get_drvinfo = tun_get_drvinfo,
.get_msglevel = tun_get_msglevel,
.set_msglevel = tun_set_msglevel,
.get_link = tun_get_link,
.get_rx_csum = tun_get_rx_csum,
.set_rx_csum = tun_set_rx_csum
};
int __init tun_init(void) int __init tun_init(void)
{ {
int ret = 0; int ret = 0;
printk(KERN_INFO "Universal TUN/TAP device driver %s " printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
"(C)1999-2002 Maxim Krasnyansky\n", TUN_VER); printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
ret = misc_register(&tun_miscdev); ret = misc_register(&tun_miscdev);
if (ret) if (ret)
...@@ -766,5 +871,7 @@ void tun_cleanup(void) ...@@ -766,5 +871,7 @@ void tun_cleanup(void)
module_init(tun_init); module_init(tun_init);
module_exit(tun_cleanup); module_exit(tun_cleanup);
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(TUN_MINOR); MODULE_ALIAS_MISCDEV(TUN_MINOR);
...@@ -58,7 +58,7 @@ struct tun_struct { ...@@ -58,7 +58,7 @@ struct tun_struct {
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/* Read queue size */ /* Read queue size */
#define TUN_READQ_SIZE 10 #define TUN_READQ_SIZE 500
/* TUN device flags */ /* TUN device flags */
#define TUN_TUN_DEV 0x0001 #define TUN_TUN_DEV 0x0001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment