Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Цилюрик О.И. Модули ядра Linux
Назад Внешние интерфейсы модуля Вперед

Драйверы: сетевой интерфейс

Примеры этого раздела заимствованы из [6] и находятся в архиве net.tgz.

lab1_network.c :

	#include <linux/module.h> 
	#include <linux/netdevice.h>
	#include <linux/init.h> 
	
	static struct net_device *dev; 
	
	static int my_open( struct net_device *dev ) { 
	   printk( KERN_INFO "Hit: my_open(%s)\n", dev->name ); 
	   /* start up the transmission queue */ 
	   netif_start_queue( dev ); 
	   return 0; 
	} 
	
	static int my_close( struct net_device *dev ) { 
	   printk( KERN_INFO "Hit: my_close(%s)\n", dev->name ); 
	   /* shutdown the transmission queue */ 
	   netif_stop_queue( dev ); 
	   return 0; 
	} 
	
	/* Note this method is only needed on some; without it 
	   module will fail upon removal or use. At any rate there is a memory 
	   leak whenever you try to send a packet through in any case*/ 
	static int stub_start_xmit( struct sk_buff *skb, struct net_device *dev ) { 
	   dev_kfree_skb( skb ); 
	   return 0; 
	} 
	
	#ifdef HAVE_NET_DEVICE_OPS 
	static struct net_device_ops ndo = { 
	   .ndo_open = my_open, 
	   .ndo_stop = my_close, 
	   .ndo_start_xmit = stub_start_xmit, 
	}; 
	#endif 
	
	static void my_setup( struct net_device *dev ) { 
	   int j; 
	   printk( KERN_INFO "my_setup(%s)\n", dev->name ); 
	   /* Fill in the MAC address with a phoney */ 
	   for( j = 0; j < ETH_ALEN; ++j ) { 
	      dev->dev_addr[ j ] = (char)j; 
	   } 
	   ether_setup( dev ); 
	#ifdef HAVE_NET_DEVICE_OPS 
	   dev->netdev_ops = &ndo; 
	#else 
	   dev->open = my_open; 
	   dev->stop = my_close; 
	   dev->hard_start_xmit = stub_start_xmit; 
	#endif 
	} 
	
	static int __init my_init( void ) { 
	   printk( KERN_INFO "Loading stub network module:...." ); 
	   dev = alloc_netdev( 0, "mynet%d", my_setup ); 
	   if( register_netdev( dev ) ) { 
	      printk( KERN_INFO " Failed to register\n" ); 
	      free_netdev( dev ); 
	      return -1; 
	   } 
	   printk( KERN_INFO "Succeeded in loading %s!\n\n", dev_name( &dev->dev ) ); 
	   return 0; 
	} 
	
	static void __exit my_exit( void ) { 
	   printk( KERN_INFO "Unloading stub network module\n\n" ); 
	   unregister_netdev( dev ); 
	   free_netdev( dev ); 
	} 
	
	module_init( my_init ); 
	module_exit( my_exit ); 
	
	MODULE_AUTHOR( "Bill Shubert" ); 
	MODULE_AUTHOR( "Jerry Cooperstein" ); 
	MODULE_AUTHOR( "Tatsuo Kawasaki" ); 
	MODULE_DESCRIPTION( "LDD:1.0 s_24/lab1_network.c" ); 
	MODULE_LICENSE( "GPL v2" );

Это сетевое устройство уже можно установить:

$ sudo ifconfig mynet0

mynet0: error fetching interface information: Device not found

$ sudo insmod lab1_network.ko

$ lsmod | head -n2

	Module                  Size  Used by 
	lab1_network            1172  0 

$ dmesg | tail -n6

	Loading stub network module:.... 
	my_setup() 
	Succeeded in loading mynet0! 
	Hit: my_open(mynet0) 
	mynet0: no IPv6 routers present 

И теперь мы можем с ним немного поработать:

$ sudo ifconfig mynet0

	mynet0    Link encap:Ethernet HWaddr 00:01:02:03:04:05  
	          BROADCAST MULTICAST MTU:1500  Metric:1 
	          RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
	          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 
	          collisions:0 txqueuelen:1000 
	          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b) 

$ sudo ifconfig mynet0 up 192.168.1.200

$ sudo ifconfig mynet0

	mynet0    Link encap:Ethernet HWaddr 00:01:02:03:04:05
	          inet addr:192.168.1.200 Bcast:192.168.1.255  Mask:255.255.255.0 
	          inet6 addr: fe80::201:2ff:fe03:405/64 Scope:Link 
	          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1 
	          RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
	          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 
	          collisions:0 txqueuelen:1000
	          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b) 

$ ping 192.168.1.200

	PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data. 
	64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.056 ms 
	64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.051 ms 
	64 bytes from 192.168.1.200: icmp_seq=3 ttl=64 time=0.055 ms 
	64 bytes from 192.168.1.200: icmp_seq=4 ttl=64 time=0.052 ms 
	64 bytes from 192.168.1.200: icmp_seq=5 ttl=64 time=0.054 ms 
	64 bytes from 192.168.1.200: icmp_seq=6 ttl=64 time=0.052 ms 
	^C 
	--- 192.168.1.200 ping statistics --- 
	6 packets transmitted, 6 received, 0% packet loss, time 5440ms 
	rtt min/avg/max/mdev = 0.051/0.053/0.056/0.006 ms 

Удаляем сетевой интерфейс:

$ sudo rmmod lab1_network

$ dmesg | tail -n3

	Unloading stub network module 
	Hit: my_close(mynet0) 

$ sudo ifconfig mynet0

mynet0: error fetching interface information: Device not found

Как уже отмечалось выше, основу структуры описания сетевого интерфейса составляет структура struct net_device, описанная в <linux/netdevice.h>. Это очень крупная структура, содержащая не только описание аппаратных средств, но и конфигурационные параметры сетевого интерфейса по отношению к выше лежащим протоколам, например:

	struct net_device { 
	  char  name[ IFNAMSIZ ] ; 
	...
	   unsigned long  mem_end;   /* shared mem end     */ 
	   unsigned long  mem_start; /* shared mem start   */ 
	   unsigned long  base_addr; /* device I/O address */ 
	   unsigned int   irq;       /* device IRQ number  */ 
	...
	   unsigned       mtu;       /* interface MTU value     */ 
	   unsigned short type;      /* interface hardware type */ 
	...
	   /* Interface address info. */ 
	   unsigned char  perm_addr[ MAX_ADDR_LEN ]; /* permanent hw address    */ 
	   unsigned char  addr_len;                 /* hardware address length */ 
	...
	}

- где поле type, например, определяет тип аппаратного адаптера с точки зрения ARP-механизма разрешения MAC адресов (<linux/if_arp.h>):

	...
	#define ARPHRD_ETHER       1    /* Ethernet 10Mbps           */
	...
	#define ARPHRD_IEEE802     6    /* IEEE 802.2 Ethernet/TR/TB */ 
	#define ARPHRD_ARCNET      7    /* ARCnet                    */ 
	...
	#define ARPHRD_IEEE1394   24    /* IEEE 1394 IPv4 - RFC 2734 */
	...
	#define ARPHRD_IEEE80211 801    /* IEEE 802.11               */

Детальный разбор огромного числа полей struct net_device (этой и любой другой сопутствующей) или их возможных значений — бессмысленный, хотя бы потому, что эта структура радикально изменяется от подверсии к подверсии ядра; такой разбор должен проводиться «по месту».

Все структуры, описывающие доступные сетевые интерфейсы в системе, увязаны в связный список. Следующий пример диагностирует такой список:

lab1_devices.c :

	#include <linux/module.h> 
	#include <linux/init.h> 
	#include <linux/netdevice.h>
	
	static int __init my_init( void ) { 
	   struct net_device *dev; 
	   printk( KERN_INFO "Hello: module loaded at 0x%p\n", my_init ); 
	   dev = first_net_device( &init_net ); 
	   printk( KERN_INFO "Hello: dev_base address=0x%p\n", dev ); 
	   while ( dev ) { 
	      printk( KERN_INFO 
	              "name = %6s irq=%4d trans_start=%12lu last_rx=%12lu\n", 
	              dev->name, dev->irq, dev->trans_start, dev->last_rx ); 
	      dev = next_net_device( dev ); 
	   } 
	   return 0; 
	} 
	static void __exit my_exit( void ) { 
	   printk( KERN_INFO "Module Unloading\n" ); 
	} 
	
	module_init( my_init ); 
	module_exit( my_exit ); 
	
	MODULE_AUTHOR( "Jerry Cooperstein" ); 
	MODULE_DESCRIPTION( "LDD:1.0 s_25/lab1_devices.c" ); 
	MODULE_LICENSE( "GPL v2" ); 

Выполнение (предварительно для убедительности загрузим ранее созданный модуль lab1_network.ko):

$ sudo insmod lab1_network.ko

$ sudo insmod lab1_devices.ko

$ dmesg | tail -n8

	Hello: module loaded at 0xf8853000
	Hello: dev_base address=0xf719c400
	name =     lo  irq=   0  trans_start=           0  last_rx=           0 
	name =   eth0  irq=  16  trans_start=  4294693516  last_rx=           0 
	name =  wlan0  irq=   0  trans_start=  4294693412  last_rx=           0 
	name =   pan0  irq=   0  trans_start=           0  last_rx=           0 
	name = cipsec0 irq=   0  trans_start=     2459232  last_rx=           0 
	name = mynet0  irq=   0  trans_start=           0  last_rx=           0 

Предыдущий раздел: Оглавление Следующий раздел:
Сеть   Путь пакета сквозь стек протоколов