[Linux]virtual_net驱动

[Linux]virtual_net驱动

个人博客https://aeneag.xyz/

艾恩凝

2021/7/3

introduction

网卡驱动程序,主要了解网卡驱动程序工作流程

framework

vnet1PNG.PNG

flow

vnet2.PNG

code

  1/*
  2* @author aen
  3* @date 2021/7/3
  4*/ 
  5#include <linux/module.h>
  6#include <linux/errno.h>
  7#include <linux/netdevice.h>
  8#include <linux/etherdevice.h>
  9#include <linux/kernel.h>
 10#include <linux/types.h>
 11#include <linux/fcntl.h>
 12#include <linux/interrupt.h>
 13#include <linux/ioport.h>
 14#include <linux/in.h>
 15#include <linux/skbuff.h>
 16#include <linux/slab.h>
 17#include <linux/spinlock.h>
 18#include <linux/string.h>
 19#include <linux/init.h>
 20#include <linux/bitops.h>
 21#include <linux/delay.h>
 22#include <linux/ip.h>
 23
 24#include <asm/system.h>
 25#include <asm/io.h>
 26#include <asm/irq.h>
 27
 28static struct net_device *vnet_dev;
 29static void emulator_rx_packet(struct sk_buff *skb, struct net_device *dev)
 30{
 31	/* 参考LDD3 */
 32	unsigned char *type;
 33	struct iphdr *ih;
 34	__be32 *saddr, *daddr, tmp;
 35	unsigned char	tmp_dev_addr[ETH_ALEN];
 36	struct ethhdr *ethhdr;
 37
 38	struct sk_buff *rx_skb;
 39
 40	// 从硬件读出/保存数据
 41	/* 对调"源/目的"的mac地址 */
 42	ethhdr = (struct ethhdr *)skb->data;
 43	memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);
 44	memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);
 45	memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);
 46
 47	/* 对调"源/目的"的ip地址 */  
 48	ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
 49	saddr = &ih->saddr;
 50	daddr = &ih->daddr;
 51
 52	tmp = *saddr;
 53	*saddr = *daddr;
 54	*daddr = tmp;
 55
 56	//((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
 57	//((u8 *)daddr)[2] ^= 1;
 58	type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr);
 59	//printk("tx package type = %02x\n", *type);
 60	// 修改类型, 原来0x8表示ping
 61	*type = 0; /* 0表示reply */
 62
 63	ih->check = 0;		   /* and rebuild the checksum (ip needs it) */
 64	ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);
 65
 66	// 构造一个sk_buff
 67	rx_skb = dev_alloc_skb(skb->len + 2);
 68	skb_reserve(rx_skb, 2); /* align IP on 16B boundary */
 69	memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);
 70
 71	/* Write metadata, and then pass to the receive level */
 72	rx_skb->dev = dev;
 73	rx_skb->protocol = eth_type_trans(rx_skb, dev);
 74	rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
 75	dev->stats.rx_packets++;
 76	dev->stats.rx_bytes += skb->len;
 77
 78	// 提交sk_buff
 79	netif_rx(rx_skb);
 80}
 81
 82static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev){
 83	static int cnt = 0;
 84	printk("virt_net_send_packet cnt = %d\n", ++cnt);
 85	/* 对于真实的网卡, 把skb里的数据通过网卡发送出去 */
 86	netif_stop_queue(dev); /* 停止该网卡的队列 */
 87    /* ...... */           /* 把skb的数据写入网卡 */
 88
 89	/* 构造一个假的sk_buff,上报 */
 90	emulator_rx_packet(skb, dev);
 91
 92	dev_kfree_skb (skb);   /* 释放skb */
 93	netif_wake_queue(dev); /* 数据全部发送出去后,唤醒网卡的队列 */
 94
 95
 96	dev->stats.tx_packets++;
 97	dev->stats.tx_bytes += skb->len;
 98	return 0;
 99}
100
101static int virt_net_init(void)
102{
103	/* 1. distributing net_device struct */
104	vnet_dev = alloc_netdev(0, "vnet%d", ether_setup);;  /* alloc_etherdev */
105
106	/* 2. setting */
107	vnet_dev->hard_start_xmit = virt_net_send_packet;
108	/* mac address*/
109    vnet_dev->dev_addr[0] = 0x08;
110    vnet_dev->dev_addr[1] = 0x89;
111    vnet_dev->dev_addr[2] = 0x89;
112    vnet_dev->dev_addr[3] = 0x89;
113    vnet_dev->dev_addr[4] = 0x89;
114    vnet_dev->dev_addr[5] = 0x11;
115
116	vnet_dev->flags           |= IFF_NOARP;
117	vnet_dev->features        |= NETIF_F_NO_CSUM;
118
119 	/* 3. register */ 
120	register_netdev(vnet_dev);
121
122	return 0;
123}
124
125static void virt_net_exit(void)
126{
127	unregister_netdev(vnet_dev);
128	free_netdev(vnet_dev);
129}
130
131module_init(virt_net_init);
132module_exit(virt_net_exit);
133
134MODULE_AUTHOR("https://aeneag.xyz"); 
135MODULE_VERSION("0.1");
136MODULE_DESCRIPTION("S3C2440 Vnet driver");
137MODULE_LICENSE("GPL");

end

网卡 驱动算是 除了字符设备 块设备 另一块 网络驱动。主要搞搞流程理解理解内核中的驱动

艾恩凝

写于大连

2021/7/3

catalogue

[Linux]驱动系列目录


    


公众号'艾恩凝'
个人公众号
个人微信
个人微信
    吾心信其可行,
          则移山填海之难,
                  终有成功之日!
                                  ——孙文
    评论
    0 评论
avatar

取消