[新增] 华清 源码
This commit is contained in:
22
net/ex1/Makefile
Executable file
22
net/ex1/Makefile
Executable file
@ -0,0 +1,22 @@
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
|
||||
ifeq ($(ARCH),arm)
|
||||
KERNELDIR ?= /home/farsight/fs4412/linux-3.14.25-fs4412
|
||||
ROOTFS ?= /nfs/rootfs
|
||||
else
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
endif
|
||||
PWD := $(shell pwd)
|
||||
|
||||
modules:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
modules_install:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_PATH=$(ROOTFS) modules_install
|
||||
clean:
|
||||
rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versions
|
||||
else
|
||||
|
||||
obj-m := vnet.o
|
||||
|
||||
endif
|
||||
|
||||
178
net/ex1/vnet.c
Executable file
178
net/ex1/vnet.c
Executable file
@ -0,0 +1,178 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <linux/ip.h>
|
||||
|
||||
#include "vnet.h"
|
||||
|
||||
struct net_device *vnet_dev;
|
||||
|
||||
static int vnet_open(struct net_device *dev)
|
||||
{
|
||||
netif_start_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vnet_stop(struct net_device *dev)
|
||||
{
|
||||
netif_stop_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vnet_rx(struct net_device *dev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct vnet_priv *priv = netdev_priv(dev);
|
||||
|
||||
skb = dev_alloc_skb(priv->rxlen + 2);
|
||||
if (IS_ERR(skb)) {
|
||||
printk(KERN_NOTICE "vnet: low on mem - packet dropped\n");
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
skb_reserve(skb, 2);
|
||||
memcpy(skb_put(skb, priv->rxlen), priv->rxdata, priv->rxlen);
|
||||
|
||||
skb->dev = dev;
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes += priv->rxlen;
|
||||
netif_rx(skb);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void vnet_rx_int(char *buf, int len, struct net_device *dev)
|
||||
{
|
||||
struct vnet_priv *priv;
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
priv->rxlen = len;
|
||||
memcpy(priv->rxdata, buf, len);
|
||||
vnet_rx(dev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void vnet_hw_tx(char *buf, int len, struct net_device *dev)
|
||||
{
|
||||
#if DEBUG
|
||||
int i;
|
||||
#endif
|
||||
|
||||
struct iphdr *ih;
|
||||
struct net_device *dest;
|
||||
struct vnet_priv *priv;
|
||||
u32 *saddr, *daddr;
|
||||
|
||||
if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
|
||||
printk("vnet: Packet too short (%i octets)\n", len);
|
||||
return;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printk("len is %i\n", len);
|
||||
printk("data: ");
|
||||
for (i = 0; i < len; i++)
|
||||
printk(" %02x",buf[i] & 0xff);
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
ih = (struct iphdr *)(buf + sizeof(struct ethhdr));
|
||||
saddr = &ih->saddr;
|
||||
daddr = &ih->daddr;
|
||||
((u8 *)saddr)[3] = ((u8 *)saddr)[3] ^ ((u8 *)daddr)[3];
|
||||
((u8 *)daddr)[3] = ((u8 *)saddr)[3] ^ ((u8 *)daddr)[3];
|
||||
((u8 *)saddr)[3] = ((u8 *)saddr)[3] ^ ((u8 *)daddr)[3];
|
||||
|
||||
ih->check = 0;
|
||||
ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);
|
||||
|
||||
#if DEBUG
|
||||
printk("len is %i\n", len);
|
||||
printk("data: ");
|
||||
for (i = 0; i < len; i++)
|
||||
printk(" %02x",buf[i] & 0xff);
|
||||
printk("\n\n");
|
||||
#endif
|
||||
|
||||
dest = vnet_dev;
|
||||
vnet_rx_int(buf, len, dest);
|
||||
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += len;
|
||||
priv = netdev_priv(dev);
|
||||
dev_kfree_skb(priv->txskb);
|
||||
}
|
||||
|
||||
static netdev_tx_t vnet_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
int len;
|
||||
char *data, shortpkt[ETH_ZLEN];
|
||||
struct vnet_priv *priv = netdev_priv(dev);
|
||||
|
||||
data = skb->data;
|
||||
len = skb->len;
|
||||
if (len < ETH_ZLEN) {
|
||||
memset(shortpkt, 0, ETH_ZLEN);
|
||||
memcpy(shortpkt, skb->data, skb->len);
|
||||
len = ETH_ZLEN;
|
||||
data = shortpkt;
|
||||
}
|
||||
dev->trans_start = jiffies;
|
||||
priv->txskb = skb;
|
||||
vnet_hw_tx(data, len, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops vnet_ops = {
|
||||
.ndo_open = vnet_open,
|
||||
.ndo_stop = vnet_stop,
|
||||
.ndo_start_xmit = vnet_tx,
|
||||
};
|
||||
|
||||
|
||||
static int __init vnet_init(void)
|
||||
{
|
||||
int status;
|
||||
struct vnet_priv *priv;
|
||||
|
||||
vnet_dev = alloc_etherdev(sizeof(struct vnet_priv));
|
||||
if (IS_ERR(vnet_dev))
|
||||
return -ENOMEM;
|
||||
|
||||
ether_setup(vnet_dev);
|
||||
vnet_dev->netdev_ops = &vnet_ops;
|
||||
vnet_dev->flags |= IFF_NOARP;
|
||||
priv = netdev_priv(vnet_dev);
|
||||
memset(priv, 0, sizeof(struct vnet_priv));
|
||||
|
||||
status = register_netdev(vnet_dev);
|
||||
if (status) {
|
||||
free_netdev(vnet_dev);
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit vnet_exit(void)
|
||||
{
|
||||
|
||||
unregister_netdev(vnet_dev);
|
||||
free_netdev(vnet_dev);
|
||||
}
|
||||
|
||||
module_init(vnet_init);
|
||||
module_exit(vnet_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Kevin Jiang <jiangxg@farsight.com.cn>");
|
||||
MODULE_DESCRIPTION("Virtual ethernet driver");
|
||||
12
net/ex1/vnet.h
Executable file
12
net/ex1/vnet.h
Executable file
@ -0,0 +1,12 @@
|
||||
#ifndef __VNET_H__
|
||||
#define __VNET_H__
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
struct vnet_priv {
|
||||
struct sk_buff *txskb;
|
||||
int rxlen;
|
||||
unsigned char rxdata[ETH_DATA_LEN];
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user