📄 network_device_drivers.html
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head> <title></title> <link rel="stylesheet" media="screen" type="text/css" href="./style.css" /> <link rel="stylesheet" media="screen" type="text/css" href="./design.css" /> <link rel="stylesheet" media="print" type="text/css" href="./print.css" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><a href=start.html>start</a></br><div class="toc"><div class="tocheader toctoggle" id="toc__header">Table of Contents</div><div id="toc__inside"><ul class="toc"><li class="clear"><ul class="toc"><li class="level2"><div class="li"><span class="li"><a href="#network_device_drivers" class="toc">Network Device Drivers</a></span></div><ul class="toc"><li class="level3"><div class="li"><span class="li"><a href="#the_big_picture" class="toc">The Big Picture</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#the_net_device_structure" class="toc">The Net Device structure</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#outline_of_a_simple_network_device_driver" class="toc">Outline of a Simple Network Device Driver</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#incoming_network_data" class="toc">Incoming Network data</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#outgoing_network_data" class="toc">Outgoing Network data</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#opening_a_network_device" class="toc">Opening a Network Device</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#closing_a_network_device" class="toc">Closing a Network Device</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#media_interface" class="toc">Media Interface</a></span></div></li></ul></li></ul></li></ul></div></div><h2><a name="network_device_drivers" id="network_device_drivers">Network Device Drivers</a></h2><div class="level2"><p>The main objective of a network device driver is to allow data to flow to and from the network hardware device. The Network stack handles the generation and reception of network packets. The network device driver, primarily, transfers these packets to and from the network hardware.</p></div><!-- SECTION [1-319] --><h3><a name="the_big_picture" id="the_big_picture">The Big Picture</a></h3><div class="level3"><p>A Network device driver will describe or define the network device to the network interface layer. This gives the system the ability to identify packets arriving from the hardware and route internal packets destined for the network attached to the hardware. In defining the hardware the device driver will also configure some functions to be used to set up the device and send / receive data to and from the hardware.</p></div><!-- SECTION [320-766] --><h3><a name="the_net_device_structure" id="the_net_device_structure">The Net Device structure</a></h3><div class="level3"><p>The network device structure is the master structure used to define the network device.</p><p>After detecting the network device the network device driver needs to set up this structure to allow the network interface code to define the device in the network system architecture.</p><p>A typical structure is established with a call to <strong>alloc_etherdev(sizeof(struct net_local))</strong>. This will set up the ethernet <strong>name</strong> of the device (<strong>eth%d</strong>). An ethernet name consists of a generic name followed by a number. Each time a new device of a given generic name is discovered the number is incremented. This allows devices such as <strong>eth0</strong> <strong>eth1</strong> and <strong>eth2</strong> to be defined.</p><p>The following is a subset of the functions that need to be defined for a simple network device.</p><pre class="code c"> dev->open = net_open; dev->stop = net_close; dev->hard_start_xmit = net_send_packet; dev->get_stats = net_get_stats; dev->set_multicast_list = &set_multicast_list; dev->tx_timeout = &net_tx_timeout; dev->watchdog_timeo = MY_TX_TIMEOUT; </pre></div><!-- SECTION [767-2022] --><h3><a name="outline_of_a_simple_network_device_driver" id="outline_of_a_simple_network_device_driver">Outline of a Simple Network Device Driver</a></h3><div class="level3"><p>A simple network device driver performs as follows</p><ul><li class="level1"><div class="li"> Detect the arrival of network packets from the hardware device</div></li><li class="level1"><div class="li"> Detct the availabliity of a packet to send to the hardware from the</div></li></ul><p>network stack.</p><ul><li class="level1"><div class="li"> Detect the requirement of the network interface to start (or open ) an</div></li></ul><p>interface on a selected hardware device.</p><ul><li class="level1"><div class="li"> Set up a network device structure for use by the network interface layer.</div></li><li class="level1"><div class="li"> Handle any modifications required to the packet header for data to be</div></li></ul><p>sent on the hardware device</p><ul><li class="level1"><div class="li"> Manage traffic on the device, telling the Network interface to start and</div></li></ul><p>stop sending packets, as hardware transmit buffers fill and empty.</p><ul><li class="level1"><div class="li"> Collect network statistics data from the device.</div></li></ul><p>More sophisticated drivers ( for more sophisticated devices) also manage hardware buffers and DMA based data tranfers.</p></div><!-- SECTION [2023-2898] --><h3><a name="incoming_network_data" id="incoming_network_data">Incoming Network data</a></h3><div class="level3"><p> Network device drivers deal with a network data structure called a <strong>skbuf</strong> (see <strong>linux/include/linux/skbuff.h</strong>) .</p><p>These structures are used to contain network data and header information ( as well as lots of other details ).</p><p>A data packet arriving from a network device is placed into a <strong>skbuf</strong> and then passed into the system network interface.</p><p> The following code sequence shows this process in action it is taken from <strong>linux/drivers/net/isa-skeleton.c</strong> . This code is normally part of the interrupt service routine for an incoming network packet.</p><pre class="code c"> <span class="kw4">struct</span> sk_buff *skb; <span class="kw4">int</span> status <span class="kw4">int</span> pkt_len <span class="co1">// ioaddr is the address of the network device</span> status = inw<span class="br0">(</span>ioaddr<span class="br0">)</span>; pkt_len = inw<span class="br0">(</span>ioaddr<span class="br0">)</span>; <span class="co1">// get a skb</span> skb = dev_alloc_skb<span class="br0">(</span>pkt_len<span class="br0">)</span>; <span class="co1">// define the device that got the packet.</span> skb->dev = dev; <span class="co1">// copy data from the device to the skb-&gt;data segment</span> memcpy<span class="br0">(</span>skb_put<span class="br0">(</span>skb,pkt_len<span class="br0">)</span>, <span class="br0">(</span><span class="kw4">void</span>*<span class="br0">)</span>dev->rmem_start, <span class="co1">// give it to the network layer</span> netif_rx<span class="br0">(</span>skb<span class="br0">)</span>; <span class="co1">// handle the accounts</span> dev->last_rx = jiffies; lp->stats.<span class="me1">rx_packets</span>++; lp->stats.<span class="me1">rx_bytes</span> += pkt_len; </pre><p>More sophisticated drivers will preallocate the skbuf structures as part of a DMA area for incoming data and will then pass these preallocated buffers into the system network stack.</p></div><!-- SECTION [2899-4271] --><h3><a name="outgoing_network_data" id="outgoing_network_data">Outgoing Network data</a></h3><div class="level3"><p>Once a network device has been opened it has been registered with the kernel as a possible destination for outbound network packets. This normally means that the device has been given a network address and that it can start sending data.</p><p>The system network stack will identify data destined to this particular device driver and then issue a call to the <strong>hard_start_xmit</strong> that was registered during the hardware device setup. This function has the responsibility of sending the data packet to the device.</p><p>The data is in the form of a <strong>skbuf</strong> structure and the hardware device is defined in terms of a <strong>net_device</strong> structure.</p><p>A code sample shows this in action</p><pre class="code c"> <span class="kw4">static</span> <span class="kw4">int</span> net_send_packet<span class="br0">(</span><span class="kw4">struct</span> sk_buff *skb, <span class="kw4">struct</span> net_device *dev<span class="br0">)</span><span class="br0">{</span> <span class="kw4">struct</span> net_local *np = netdev_priv<span class="br0">(</span>dev<span class="br0">)</span>; <span class="kw4">int</span> ioaddr = dev->base_addr; <span class="kw4">short</span> length = skb->len; hardware_send_packet<span class="br0">(</span>ioaddr, buf, length<span class="br0">)</span>; np->stats.<span class="me1">tx_bytes</span> += skb->len; dev->trans_start = jiffies; <span class="coMULTI">/* You might need to clean up and record Tx statistics here. */</span> <span class="kw1">if</span> <span class="br0">(</span>inw<span class="br0">(</span>ioaddr<span class="br0">)</span> == <span class="coMULTI">/*RU*/</span><span class="nu0">81</span><span class="br0">)</span> np->stats.<span class="me1">tx_aborted_errors</span>++; dev_kfree_skb <span class="br0">(</span>skb<span class="br0">)</span>; <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">}</span> </pre></div><!-- SECTION [4272-5523] --><h3><a name="opening_a_network_device" id="opening_a_network_device">Opening a Network Device</a></h3><div class="level3"><p> This function handles the process of setting up the hardware to send and receive network packets.</p><p>This function is normally invoked in response to the <strong>ifconfig eth0 up</strong> user function.</p><p>In its simplest form it will kick off the device interrupts and start the network transmit queue. After this function any network packets directed to the hardware will start to arrive. Any incoming packets will also be sent into the system network interface subsystem.</p><pre class="code c"><span class="kw4">static</span> <span class="kw4">int</span>net_open<span class="br0">(</span><span class="kw4">struct</span> net_device *dev<span class="br0">)</span><span class="br0">{</span> <span class="kw4">struct</span> net_local *np = netdev_priv<span class="br0">(</span>dev<span class="br0">)</span>; <span class="kw4">int</span> ioaddr = dev->base_addr; <span class="co1">// get the device interrupt service routine set up</span> <span class="kw1">if</span> <span class="br0">(</span>request_irq<span class="br0">(</span>dev->irq, &net_interrupt, <span class="nu0">0</span>, cardname, dev<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> -EAGAIN; <span class="br0">}</span> <span class="coMULTI">/* Reset the hardware here. Don't forget to set the station address. */</span> chipset_init<span class="br0">(</span>dev, <span class="nu0">1</span><span class="br0">)</span>; outb<span class="br0">(</span>0x00, ioaddr<span class="br0">)</span>; <span class="co1">//record the open time</span> np->open_time = jiffies; <span class="coMULTI">/* We are now ready to accept transmit requeusts from * the queueing layer of the networking. */</span> netif_start_queue<span class="br0">(</span>dev<span class="br0">)</span>; <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">}</span></pre></div><!-- SECTION [5524-6723] --><h3><a name="closing_a_network_device" id="closing_a_network_device">Closing a Network Device</a></h3><div class="level3"><p> This function handles the process of shutting down the hardware and turning off the system network packet queue to the device.</p><p>This function is normally invoked in response to the **ifconfig eth0 down* user function.</p><p>In its simplest form it will turn off the device interrupts and stop the network transmit queue.</p><p>A simple example shows this in action.</p><pre class="code c"> <span class="kw4">static</span> <span class="kw4">int</span>net_close<span class="br0">(</span><span class="kw4">struct</span> net_device *dev<span class="br0">)</span><span class="br0">{</span> <span class="kw4">struct</span> net_local *np = netdev_priv<span class="br0">(</span>dev<span class="br0">)</span>; <span class="kw4">int</span> ioaddr = dev->base_addr; netif_stop_queue<span class="br0">(</span>dev<span class="br0">)</span>; outw<span class="br0">(</span>0x00, ioaddr<span class="nu0">+0</span><span class="br0">)</span>; <span class="coMULTI">/* Release the physical interrupt line. */</span> free_irq<span class="br0">(</span>dev->irq, dev<span class="br0">)</span>; <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">}</span></pre></div><!-- SECTION [6724-7432] --><h3><a name="media_interface" id="media_interface">Media Interface</a></h3><div class="level3"><p> A hardware network driver also often has the repsonsibility of managing the media interface device. This will handle the rate and type of communications the network device can manage. Normally a separate interrupt structure is established for the media interface. </p></div><!-- SECTION [7433-] --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -