网卡驱动程序实践

来源:互联网 发布:海湾编程软件 下载 编辑:程序博客网 时间:2024/06/05 07:39

一、虚拟网卡的实现
在linux系统中,添加一个网络设备大致需要以下步骤。
1、分配一个网络设备结构体

    /*alloc a net_device struct*/vnet_dev = alloc_netdev(0, "eth%d",ether_setup);

2、注册这个网络设备

register_netdev(vnet_dev);

这样,当安装上这个驱动程序之后,就在linux系统中有了一个ethx设备。在控制台使用

ifconfig -a

命令,就能看到这个设备。使用

ifconfig ethx up

就可以启动这个网络设备。使用

ifconfig ethx 192.168.x.x

就可以给这个设备分配ip,但是此时的设备是不能进行数据收发的。还需要对vnet_dev进行具体的设置。
首先,给vnet_dev分配一个操作结构体,

static struct net_device_ops vnet_dev_ops = {    .ndo_start_xmit = vnet_send_packet,    ......};

这里仅仅添加一个数据包的发送函数以实现一个虚拟网卡。把这个结构体赋给vnet_dev,这个成员的设置,在不同版本内核是不一样的,老的内核是设置vnet_dev->hard_start_xmit

vnet_dev->netdev_ops= &vnet_dev_ops;

给网卡设置mac地址

vnet_dev->dev_addr[0] = xxx;...vnet_dev->dev_addr[5] = xxx;

设置网卡设备的标志位

    vnet_dev->flags           |= IFF_NOARP;    vnet_dev->features        |= NETIF_F_NO_CSUM;   

vnet_send_packet的具体实现

static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev){static int cnt = 0;printk("virt_net_send_packet cnt = %d\n", ++cnt);/* 对于真实的网卡, 把skb里的数据通过网卡发送出去 */netif_stop_queue(dev); /* 停止该网卡的队列 *//* ...... */           /* 把skb的数据写入网卡 *//* 构造一个假的sk_buff,上报 */emulator_rx_packet(skb, dev);dev_kfree_skb (skb);   /* 释放skb */netif_wake_queue(dev); /* 数据全部发送出去后,唤醒网卡的队列 *//* 更新统计信息 */dev->stats.tx_packets++;dev->stats.tx_bytes += skb->len;return 0;}    static void emulator_rx_packet(struct sk_buff *skb, struct net_device *dev){/* 参考LDD3 */unsigned char *type;struct iphdr *ih;__be32 *saddr, *daddr, tmp;unsigned char   tmp_dev_addr[ETH_ALEN];struct ethhdr *ethhdr;struct sk_buff *rx_skb;// 从硬件读出/保存数据/* 对调"源/目的"的mac地址 */ethhdr = (struct ethhdr *)skb->data;memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);    memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);/* 对调"源/目的"的ip地址 */    ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));saddr = &ih->saddr;daddr = &ih->daddr;tmp = *saddr;*saddr = *daddr;*daddr = tmp;//((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) *///((u8 *)daddr)[2] ^= 1;type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr);//printk("tx package type = %02x\n", *type);// 修改类型, 原来0x8表示ping*type = 0; /* 0表示reply */ih->check = 0;         /* and rebuild the checksum (ip needs it) */ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);// 构造一个sk_buffrx_skb = dev_alloc_skb(skb->len + 2);skb_reserve(rx_skb, 2); /* align IP on 16B boundary */  memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);/* Write metadata, and then pass to the receive level */rx_skb->dev = dev;rx_skb->protocol = eth_type_trans(rx_skb, dev);rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */dev->stats.rx_packets++;dev->stats.rx_bytes += skb->len;// 提交sk_buffnetif_rx(rx_skb);}

这样,当

ifconfig ethx upifconfig ethx 192.168.x.x

后,即能ping同自己的ip地址。
但本身我自己的文件系统是通过网络挂载的,实际测试网卡驱动比较麻烦。先按当前进度,把后续实验做完,然后再抽时间重写网卡驱动

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子断奶后乳房变小怎么办 断奶了月经不来怎么办 钥匙在门上拔不出来怎么办 钥匙拔不下来了怎么办 养了几天鱼死了怎么办 乌龟的眼睛肿了怎么办 手被鱼刺扎了怎么办 被鱼刺扎手肿了怎么办 手被桂鱼扎了怎么办 三岁宝宝卡鱼刺怎么办 一岁宝宝卡鱼刺怎么办 鱼刺卡在胸口了怎么办 婴儿被鱼刺卡了怎么办 幼儿被鱼刺卡到怎么办 鱼刺被吞下去了怎么办 喉咙卡到鱼刺下不去怎么办 被小鱼刺卡了怎么办 晚上被鱼刺卡到怎么办 一个小鱼刺卡了怎么办 卡了一个小鱼刺怎么办 鱼刺卡在气管里怎么办 刺蛾幼虫 蛰了怎么办 被杨树辣子蛰了怎么办 蜇了老子蜇了怎么办 被刺蛾幼虫蛰了怎么办 孕妇被蚊虫叮咬发痒怎么办 白掌叶子尖发黄怎么办 白掌叶子卷了怎么办 白掌叶子全软了怎么办? 发财树有黄斑了怎么办 幸福树叶子蔫了怎么办 幸福树枝条塌了怎么办? 幸福树叶子嫣了怎么办 毒蚊子叮咬肿硬怎么办 被蚊子咬了很痒怎么办 蚊子咬了脚肿了怎么办 小孩被蚊子咬了怎么办 小狗老喜欢咬人怎么办 狗狗喜欢咬手怎么办 成年猫喜欢咬人怎么办 猫总喜欢咬人怎么办