Guide to Implementing Packet-Transmit Capability with Intel 82573L NIC, Slides of Computer Applications

A step-by-step guide on implementing a packet-transmit capability with the intel 82573l network interface controller using linux kernel. It covers topics such as writing a 'write()' routine, using kzalloc() function, handling transmit-descriptors, and configuring the nic. Students and professionals interested in network driver development can benefit from this document.

Typology: Slides

2012/2013

Uploaded on 04/17/2013

pamelaaaa
pamelaaaa 🇮🇳

4.5

(12)

103 documents

1 / 23

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Our ‘xmit1000.c’ driver
Implementing a ‘packet-transmit’
capability with the Intel 82573L
network interface controller
Docsity.com
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17

Partial preview of the text

Download Guide to Implementing Packet-Transmit Capability with Intel 82573L NIC and more Slides Computer Applications in PDF only on Docsity!

Our ‘xmit1000.c’ driver

Implementing a ‘packet-transmit’

capability with the Intel 82573L

network interface controller

Remenber ‘echo’ and ‘cat’?

• Your device-driver module (named ‘uart.c’)

was supposed to allow two programs that

are running on a pair of adjacent PCs to

communicate via a “null-modem” cable

$ echo Hello > /dev/uart $ _ $ cat /dev/uart Hello _

Transmitting… Receiving…

This function will program the actual data-transfer

Driver’s components

write

my_fops

my_write()

module_init() module_exit()

This function will allow us to inspect the transmit-descriptors

This function will detect and configure the hardware, define page-mappings, allocate and initialize the descriptors, start the ‘transmit’ engine, create the pseudo-file and register ‘my_fops’

This function will do needed ‘cleanup’ when it’s time to unload our driver – turn off the ‘transmit’ engine, free the memory, delete page-table entries, the pseudo-file, and the ‘my_fops’

‘struct’ holds one function-pointer

my_get_info()

Kzalloc()

• Linux kernels since 2.6.13 offer this convenient

function for allocating pre-zeroed kernel memory

• It has the same syntax as the ‘kmalloc()’ function

(described in our texts), but adds the after-effect

of zeroing out the newly-allocated memory-area

• Thus it does two logically distinct actions (often

coupled anyway) within a single function-call

void kmem = kmalloc ( region_size, GFP_KERNEL ); memset ( kmem, 0x00, region_size ); / can be replaced with */ void *kmem = kzalloc ( region_size, GFP_KERNEL );

Our Tx-Descriptor ring

descriptor 0

Our ‘reusable’ transmit-buffer (1536 bytes)

descriptor 1 descriptor 2 descriptor 3 descriptor 4 descriptor 5 descriptor 6 descriptor 7 one packet-buffer Array of 8 transmit-descriptors

TAIL HEAD

After writing the data into our packet-buffer, and writing its length to the the current TAIL descriptor, our driver will advance the TAIL index; the NIC responds by reading the current HEAD descriptor, fetching its data, then advancing the HEAD index as it sends our data out over the wire.

‘/proc/xmit1000’

• This pseudo-file can be examined anytime

to find out what values (if any) the NIC has

‘written back’ into the transmit-descriptors

(i.e., the descriptor-status information) and

current values in registers TDH and TDT:

$ cat /proc/xmit

Configuration registers

TIPG

TCTL

TDBAL

TDBAH

TDLEN

TDH

TDT

TXDCTL

CTRL

CTRL_EXT

Device Control Extended Device Control

Transmit Inter-Packet Gap

Transmit Control

Transmit Descriptor-queue Base-Address (LOW)

Transmit Descriptor-queue Base-Address (HIGH)

Transmit Descriptor-queue Length

Transmit Descriptor-queue HEAD

Transmit Descriptor-queue TAIL

Transmit Descriptor-queue Control

The ‘initialization’ sequence

• Detect the network interface controller

• Obtain its i/o-memory address and size

• Remap the i/o-memory into kernel-space

• Allocate memory for buffer and descriptors

• Initialize the array of transmit-descriptors

• Reset the NIC and configure its operations

• Create the ‘/proc/xmit1000’ pseudo-file

• Register our ‘write()’ driver-method

Our ‘write()’ algorithm

• Get index of the current TAIL descriptor

• Confine the amount of user-data

• Copy user-data into the packet-buffer

• Setup the packet’s Ethernet Header

• Setup packet-length in the TAIL descriptor

• Now hand over this descriptor to the NIC

(by advancing the value in register TDT)

• Tell the kernel how many bytes were sent

Recall Tx-Descriptor Layout

special

0x

0x

0x

0xC

CMD

Buffer-Address high (bits 63..32)

Buffer-Address low (bits 31..0)

31 0

CSO Packet Length (in bytes)

CSS reserved=0 status

Buffer-Address = the packet-buffer’s 64-bit address in physical memory Packet-Length = number of bytes in the data-packet to be transmitted CMD = Command-field CSO/CSS = Checksum Offset/Start (in bytes) STA = Status-field

Transmit IPG (0x0410)

82573L

IPG

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

R =

IPG After Deferral (Recommended value = 7)

IPG Part 1 (Recommended value = 8)

IPG Back-To-Back (Recommended value = 8)

IPG = Inter-Packet Gap

This register controls the Inter-Packet Gap timer for the Ethernet controller.

Note that the recommended TIPG register-value to achieve IEEE 802. compliant minimum transfer IPG values in full- and half-duplex operations would be 00702008 (hexadecimal), equal to (7<<20) | (8<<10) | (8<<0).

Transmit Control (0x0400)

R

=

R

=

R

=

MULR TXCSCMT UNORTX RTLC R

=

SW XOFF

COLD (upper 6-bits) (COLLISION DISTANCE)

COLD (lower 4-bits) (COLLISION DISTANCE)^0 ASDV

I L O S

S

L

U

TBI mode

P S P

0 0 R =

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

R =

E N

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16

SPEED

CT (COLLISION THRESHOLD)

EN = Transmit Enable SWXOFF = Software XOFF Transmission PSP = Pad Short Packets RLTC = Retransmit on Late Collision CT = Collision Threshold (=0xF) UNORTX = Underrun No Re-Transmit COLD = Collision Distance (=0x3F) TXCSCMT = TxDescriptor Minimum Threshold MULR = Multiple Request Support

82573L

An ‘e1000.c’ anomaly?

• The official Linux kernel is delivered with a

device-driver supporting Intel’s ‘Pro/1000’

gigabit ethernet controllers (several)

• Often this driver will get loaded by default

during the system’s startup procedures

• But it will interfere with your own driver if

you try to write a substitute for ‘e1000.ko’

• So you will want to remove it with ‘ rmmod ’

Side-effect of ‘rmmod’

• We’ve observed an unexpected side-effect

of ‘unloading’ the ‘e1000.ko’ device-driver

• The PCI Configuration Space’s command

register gets modified in a way that keeps

the NIC from working with your own driver

• Specifically, the Bus Mastering capability

gets disabled (by clearing bit #2 in the PCI

Configuration Space’s word at address 4)