📄 network device drivers.htm
字号:
</dd><dt><tt>ARPHRD_PRONET</tt></dt><dd>PROnet token ring (not used).
</dd><dt><tt>ARPHRD_CHAOS</tt></dt><dd>ChaosNET (not used).
</dd><dt><tt>ARPHRD_IEE802</tt></dt><dd>802.2 networks notably token ring.
</dd><dt><tt>ARPHRD_ARCNET</tt></dt><dd>ARCnet interfaces.
</dd><dt><tt>ARPHRD_DLCI</tt></dt><dd>Frame Relay DLCI.
</dd></dl>
<b>Defined by Linux:</b>
<dl>
<dt><tt>ARPHRD_SLIP</tt></dt><dd>Serial Line IP protocol
</dd><dt><tt>ARPHRD_CSLIP</tt></dt><dd>SLIP with VJ header compression
</dd><dt><tt>ARPHRD_SLIP6</tt></dt><dd>6bit encoded SLIP
</dd><dt><tt>ARPHRD_CSLIP6</tt></dt><dd>6bit encoded header compressed SLIP
</dd><dt><tt>ARPHRD_ADAPT</tt></dt><dd>SLIP interface in adaptive mode
</dd><dt><tt>ARPHRD_PPP</tt></dt><dd>PPP interfaces (async and sync)
</dd><dt><tt>ARPHRD_TUNNEL</tt></dt><dd>IPIP tunnels
</dd><dt><tt>ARPHRD_TUNNEL6</tt></dt><dd>IPv6 over IP tunnels
</dd><dt><tt>ARPHRD_FRAD</tt></dt><dd>Frame Relay Access Device.
</dd><dt><tt>ARPHRD_SKIP</tt></dt><dd>SKIP encryption tunnel.
</dd><dt><tt>ARPHRD_LOOPBACK</tt></dt><dd>Loopback device.
</dd><dt><tt>ARPHRD_LOCALTLK</tt></dt><dd>Localtalk apple networking device.
</dd><dt><tt>ARPHRD_METRICOM</tt></dt><dd>Metricom Radio Network.
</dd></dl>
<p>Those interfaces marked unused are defined types but without
any current support on the existing net-tools. The Linux kernel
provides additional generic support routines for devices using
ethernet and token ring.
</p><p>The <tt>pa_addr</tt> field is used to hold the IP address when
the interface is up. Interfaces should start down with this
variable clear. <tt>pa_brdaddr</tt> is used to hold the
configured broadcast address, <tt>pa_dstaddr</tt> the target of
a point to point link and <tt>pa_mask</tt> the IP netmask of
the interface. All of these can be initialised to zero. The
<tt>pa_alen</tt> field holds the length of an address (in our
case an IP address), this should be initialised to 4.
</p><h3>Link Layer Variables</h3>
<p></p><p>The <tt>hard_header_len</tt> is the number of bytes the
device desires at the start of a network buffer it is passed.
It does not have to be the number of bytes of physical header
that will be added, although this is normal. A device can use
this to provide itself a scratchpad at the start of each
buffer.
</p><p>In the 1.2.x series kernels, the <tt>skb->data</tt> pointer
will point to the buffer start and you must avoid sending your
scratchpad yourself. This also means for devices with variable
length headers you will need to allocate <tt>max_size+1</tt>
bytes and keep a length byte at the start so you know where the
header really begins (the header should be contiguous with the
data). Linux 1.3.x makes life much simpler and ensures you will
have at least as much room as you asked free at the start of
the buffer. It is up to you to use <tt>skb_push()</tt>
appropriately as was discussed in the section on networking
buffers.
</p><p>The physical media addresses (if any) are maintained in
<tt>dev_addr</tt> and <tt>broadcast</tt> respectively. These
are byte arrays and addresses smaller than the size of the
array are stored starting from the left. The <tt>addr_len</tt>
field is used to hold the length of a hardware address. With
many media there is no hardware address, and this should be set
to zero. For some other interfaces the address must be set by a
user program. The ifconfig tool permits the setting of an
interface hardware address. In this case it need not be set
initially, but the open code should take care not to allow a
device to start transmitting without an address being set.
</p><h3>Flags</h3>
<p>A set of flags are used to maintain the interface
properties. Some of these are ``compatibility'' items and as
such not directly useful. The flags are:
</p><dl>
<dt><tt>IFF_UP</tt>
</dt><dd>The interface is currently active. In Linux, the
<tt>IFF_RUNNING</tt> and <tt>IFF_UP</tt> flags are basically
handled as a pair. They exist as two items for compatibility
reasons. When an interface is not marked as <tt>IFF_UP</tt> it
may be removed. Unlike BSD, an interface that does not have
<tt>IFF_UP</tt> set will never receive packets.
</dd><dt><tt>IFF_BROADCAST</tt>
</dt><dd>The interface has broadcast capability. There will be a
valid IP address stored in the device addresses.
</dd><dt><tt>IFF_DEBUG</tt>
</dt><dd>Available to indicate debugging is desired. Not currently
used.
</dd><dt><tt>IFF_LOOPBACK</tt>
</dt><dd>The loopback interface (lo) is the only interface that has
this flag set. Setting it on other interfaces is neither
defined nor a very good idea.
</dd><dt><tt>IFF_POINTOPOINT</tt>
</dt><dd>The interface is a point to point link (such as SLIP or
PPP). There is no broadcast capability as such. The remote
point to point address in the device structure is valid. A
point to point link has no netmask or broadcast normally, but
this can be enabled if needed.
</dd><dt><tt>IFF_NOTRAILERS</tt>
</dt><dd>More of a prehistoric than a historic compatibility flag.
Not used.
</dd><dt><tt>IFF_RUNNING</tt>
</dt><dd>See <tt>IFF_UP</tt>
</dd><dt><tt>IFF_NOARP</tt>
</dt><dd>The interface does not perform ARP queries. Such an
interface must have either a static table of address
conversions or no need to perform mappings. The NetROM
interface is a good example of this. Here all entries are hand
configured as the NetROM protocol cannot do ARP queries.
</dd><dt><tt>IFF_PROMISC</tt>
</dt><dd>The interface if it is possible will hear all packets on
the network. This is typically used for network monitoring
although it may also be used for bridging. One or two
interfaces like the AX.25 interfaces are always in promiscuous
mode.
</dd><dt><tt>IFF_ALLMULTI</tt>
</dt><dd>Receive all multicast packets. An interface that cannot
perform this operation but can receive all packets will go into
promiscuous mode when asked to perform this task.
</dd><dt><tt>IFF_MULTICAST</tt>
</dt><dd>Indicate that the interface supports multicast IP traffic.
This is not the same as supporting a physical multicast. AX.25
for example supports IP multicast using physical broadcast.
Point to point protocols such as SLIP generally support IP
multicast.
</dd></dl>
<h3>The Packet Queue</h3>
<p>Packets are queued for an interface by the kernel protocol
code. Within each device, <tt>buffs[]</tt> is an array of
packet queues for each kernel priority level. These are
maintained entirely by the kernel code, but must be initialised
by the device itself on boot up. The intialisation code used is:
</p><pre>int ct=0;
while(ct<DEV_NUMBUFFS)
{
skb_queue_head_init(&dev->buffs[ct]);
ct++;
}
</pre>
All other fields should be initialised to 0.
<p>The device gets to select the queue length it wants by
setting the field <tt>dev->tx_queue_len</tt> to the maximum
number of frames the kernel should queue for the device.
Typically this is around 100 for ethernet and 10 for serial
lines. A device can modify this dynamically, although its
effect will lag the change slightly.
</p><h3>Network Device Methods</h3>
<p>Each network device has to provide a set of actual functions
(methods) for the basic low level operations. It should also
provide a set of support functions that interface the protocol
layer to the protocol requirements of the link layer it is
providing.
</p><h3>Setup</h3>
<p>The init method is called when the device is initialised and
registered with the system. It should perform any low level
verification and checking needed, and return an error code if
the device is not present, areas cannot be registered or it is
otherwise unable to proceed. If the init method returns an
error the <tt>register_netdev()</tt> call returns the error
code and the device is not created.
</p><h3>Frame Transmission</h3>
<p>All devices must provide a transmit function. It is possible
for a device to exist that cannot transmit. In this case the
device needs a transmit function that simply frees the buffer
it is passed. The dummy device has exactly this functionality
on transmit.
</p><p>The <tt>dev->hard_start_xmit()</tt> function is called and
provides the driver with its own device pointer and network
buffer (an <tt>sk_buff</tt>) to transmit. If your device is
unable to accept the buffer, it should return 1 and set
<tt>dev->tbusy</tt> to a non-zero value. This will queue the
buffer and it may be retried again later, although there is no
guarantee that the buffer will be retried. If the protocol
layer decides to free the buffer the driver has rejected, then
it will not be offered back to the device. If the device knows
the buffer cannot be transmitted in the near future, for
example due to bad congestion, it can call
<tt>dev_kfree_skb()</tt> to dump the buffer and return 0
indicating the buffer is processed.
</p><p>If there is room the buffer should be processed. The buffer
handed down already contains all the headers, including link
layer headers, neccessary and need only be actually loaded into
the hardware for transmission. In addition, the buffer is
locked. This means that the device driver has absolute
ownership of the buffer until it chooses to relinquish it. The
contents of an <tt>sk_buff</tt> remain read-only, except that
you are guaranteed that the next/previous pointers are free so
you can use the <tt>sk_buff</tt> list primitives to build
internal chains of buffers.
</p><p>When the buffer has been loaded into the hardware, or in the
case of some DMA driven devices, when the hardware has
indicated transmission complete, the driver must release the
buffer. This is done by calling <tt>dev_kfree_skb(skb,
FREE_WRITE)</tt>. As soon as this call is made, the
<tt>sk_buff</tt> in question may spontaneously disappear and
the device driver thus should not reference it again.
</p><h3>Frame Headers</h3>
<p>It is neccessary for the high level protocols to append low
level headers to each frame before queueing it for
transmission. It is also clearly undesirable that the protocol
know in advance how to append low level headers for all
possible frame types. Thus the protocol layer calls down to the
device with a buffer that has at least
<tt>dev->hard_header_len</tt> bytes free at the start of the
buffer. It is then up to the network device to correctly call
<tt>skb_push()</tt> and to put the header on the packet in its
<tt>dev->hard_header()</tt> method. Devices with no link layer
header, such as SLIP, may have this method specified as NULL.
</p><p>The method is invoked giving the buffer concerned, the device's
own pointers, its protocol identity, pointers to the source and
destination hardware addresses, and the length of the packet to
be sent. As the routine may be called before the protocol
layers are fully assembled, it is vital that the method use the
length parameter, <b>not</b> the buffer length.
</p><p>The source address may be NULL to mean ``use the default
address of this device'', and the destination may be NULL to
mean ``unknown''. If as a result of an unknown destination the
header may not be completed, the space should be allocated and
any bytes that can be filled in should be filled in. This
facility is currently only used by IP when ARP processing must
take place. The function must then return the negative of the
bytes of header added. If the header is completely built it
must return the number of bytes of header added.
</p><p>When a header cannot be completed the protocol layers will
attempt to resolve the address neccessary. When this occurs,
the <tt>dev->rebuild_header()</tt> method is called with the
address at which the header is located, the device in question,
the destination IP address, and the network buffer pointer. If
the device is able to resolve the address by whatever means
available (normally ARP), then it fills in the physical address
and returns 1. If the header cannot be resolved, it returns 0
and the buffer will be retried the next time the protocol layer
has reason to believe resolution will be possible.
</p><h3>Reception</h3>
<p>There is no receive method in a network device, because it
is the device that invokes processing of such events. With a
typical device, an interrupt notifies the handler that a
completed packet is ready for reception. The device allocates a
buffer of suitable size with <tt>dev_alloc_skb()</tt> and
places the bytes from the hardware into the buffer. Next, the
device driver analyses the frame to decide the packet type. The
driver sets <tt>skb->dev</tt> to the device that received the
frame. It sets <tt>skb->protocol</tt> to the protocol the frame
represents so that the frame can be given to the correct
protocol layer. The link layer header pointer is stored in
<tt>skb->mac.raw</tt> and the link layer header removed with
<tt>skb_pull()</tt> so that the protocols need not be aware of
it. Finally, to keep the link and protocol isolated, the device
driver must set <tt>skb->pkt_type</tt> to one of the following:
</p><dl>
<dt><tt>PACKET_BROADCAST</tt>
</dt><dd>Link layer broadcast.
</dd><dt><tt>PACKET_MULTICAST</tt>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -