Linux 虚拟网络设备驱动 (vnet)
源代码
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/ip.h>
#include <asm/system.h>
;
{
.ndo_start_xmit = virt_net_send_packet,
};
{
*type;
__be32 *saddr, *daddr, tmp;
tmp_dev_addr[ETH_ALEN];
ethhdr = ( ethhdr *)skb->data;
(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);
(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);
(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);
ih = ( iphdr *)(skb->data + ( ethhdr));
saddr = &ih->saddr;
daddr = &ih->daddr;
tmp = *saddr;
*saddr = *daddr;
*daddr = tmp;
type = skb->data + ( ethhdr) + ( iphdr);
*type = ;
ih->check = ;
ih->check = ip_fast_csum(( *)ih,ih->ihl);
rx_skb = dev_alloc_skb(skb->len + );
skb_reserve(rx_skb, );
(skb_put(rx_skb, skb->len), skb->data, skb->len);
rx_skb->dev = dev;
rx_skb->protocol = eth_type_trans(rx_skb, dev);
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
netif_rx(rx_skb);
}
{
netif_stop_queue(dev);
emulator_rx_packet(skb, dev);
dev_kfree_skb (skb);
netif_wake_queue(dev);
virt_net_dev->stats.tx_packets++;
virt_net_dev->stats.tx_bytes +=skb->len;
;
}
{
ether_setup(dev);
dev->netdev_ops= &virt_net_ops;
dev->dev_addr[] = ;
dev->dev_addr[] = ;
dev->dev_addr[] = ;
dev->dev_addr[] = ;
dev->dev_addr[] = ;
dev->dev_addr[] = ;
dev->flags |= IFF_NOARP;
dev->features |= NETIF_F_NO_CSUM;
}
__init {
ret;
virt_net_dev = alloc_netdev(, , virt_net_init);
(!virt_net_dev) {
printk();
-ENOMEM;
}
ret = register_netdev(virt_net_dev);
ret;
}
{
unregister_netdev(virt_net_dev);
free_netdev(virt_net_dev);
}
module_init(s3c_virt_net_init);
module_exit(s3c_virt_net_exit);
MODULE_LICENSE();