a network driver framework
Download
Skip this Video
Download Presentation
A network driver ‘framework’

Loading in 2 Seconds...

play fullscreen
1 / 30

A network driver ‘framework’ - PowerPoint PPT Presentation


  • 111 Views
  • Uploaded on

A network driver ‘framework’. We construct a ‘skeleton’ module showing just the essential pieces of a Linux network device driver. Overview. user space kernel space. Linux operating system Kernel. standard runtime libraries. networking subsystem.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'A network driver ‘framework’' - virgo


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
a network driver framework

A network driver ‘framework’

We construct a ‘skeleton’ module showing just the essential pieces of a Linux network device driver

overview
Overview

user space kernel space

Linux

operating system

Kernel

standard

runtime

libraries

networking subsystem

device driver module

application

program

hardware

source code layout
Source-code layout

netframe.c

#include

#include

typedef struct {

/* driver’s private data */

} MY_DRIVERDATA;

char modname[ ] = “netframe”;

struct net_device *netdev;

my_open()

my_stop()

The network driver’s

“payload” functions

my_hard_start_xmit()

my_isr()

my_get_info()

The mandatory module-

administration functions

my_init

my_exit

module init
module_init()
  • This function will execute when the driver is installed in the kernel (‘/sbin/insmod’)
  • Its role is to allocate and partially initialize a ‘struct net_device’ object for our network interface controller (i.e., hardware device), then “register” that object with the kernel
  • For ethernet NICs there exists a kernel helper-function that drivers can utilize
the key statements
The ‘key’ statements…

typedef struct { /* the driver’s private data */ } MY_DRIVERDATA;

struct net_device *netdev;

static int __init my_init( void )

{

netdev = alloc_etherdev( sizeof( MY_DRIVERDATA ) );

if ( !netdev ) return –ENOMEM;

netdev->open = my_open;

netdev->stop = my_stop;

netdev->hard_start_xmit = my_hard_start_xmit;

return register_netdev( netdev );

}

module exit
module_exit()
  • This function will execute when the driver is removed from the kernel (‘/sbin/rmmod’)
  • Its role is to “unregister” the ‘net_device’ structure and free the memory that was allocated during the module’s initialization
the key statements1
The ‘key’ statements…

struct net_device *netdev;

static void __exit my_exit( void )

{

unregister_netdev( netdev );

free_netdev( netdev );

}

slide8
open()
  • The kernel will call this function when the system administrator “configures” the NIC (e.g., with the ‘/sbin/ifconfig’ command) to assign an IP-address to the interface and and bring it UP
  • Thus the role of ‘open()’ would be to reset the hardware to a known working state and initiate packet-queueing by the kernel
the key statements2
The ‘key’ statements…

int my_open( struct net_device *dev )

{

/* initialize any remaining ‘private’ data */

/* prepare the hardware for operation */

/* install an Interrupt Service Routine */

/* enable the NIC to generate interrupts */

netif_start_queue( netdev );

return 0; //SUCCESS

}

slide10
stop()
  • The kernel will call this function when the NIC is brought DOWN (i.e., to turn off its transmission and reception of packets)
  • This could occur because of a command (such as ‘/sbin/ifconfig’) executed by the System Administrator, or because a user is removing the driver-module from the kernel (with the ‘/sbin/rmmod’ command)
the key statements3
The ‘key’ statements…

int my_stop( struct net_device *dev )

{

netif_stop_queue( netdev );

/* kill any previously scheduled ‘tasklets’ (or other deferred work) */

/* turn off the NIC’s transmit and receive engines */

/* disable the NIC’s ability to generate interrupts */

/* delete the NIC’s Interrupt Service Routine */

return 0; //SUCCESS

}

hard start xmit
hard_start_xmit()
  • The kernel will call this function whenever it has data that it wants the NIC to transmit
  • The kernel will supply the address for a socket-buffer (‘struct sk_buff’) that holds the packet-data that is to be transmitted
  • So this function’s duties are: to initiate transmission, update relevant statistics, and then release that ‘sk_buff’ structure
the key statements4
The ‘key’ statements…

int my_hard_start_xmit( struct sk_buff *skb, struct net_device *dev )

{

/* code goes here to initiate transmission by the hardware */

dev->trans_start = jiffies;

dev->stats.tx_packets += 1;

dev->stats.tx_bytes += skb->len;

dev_kfree_skb( skb );

return 0; //SUCCESS

}

what about reception
What about reception?
  • The NIC hardware receives data-packets asynchronously – not at a time of its own choosing – and we don’t want our system to be ‘stalled’ doing ‘busy-waiting’
  • Thus an interrupt handler is normally used to detect and arrange for received packets to be validated and dispatched to upper layers in the kernel’s network subsystem
simulating an interrupt
Simulating an interrupt
  • Our network device-driver ‘framework’ was only designed for demonstration purposes; it does not work with any actual hardware
  • But we can use a ‘software interrupt’ that will trigger the execution of our ISR
  • To implement this scheme, we’ll need to employ an otherwise unused IRQ-number, along with its associated ‘Interrupt-ID’
advanced programmable interrupt controller
Advanced Programmable Interrupt Controller

Multi-CORE CPU

CPU

0

CPU

1

I/O

APIC

IRQ0

IRQ1

IRQ2

IRQ3

IRQ23

LOCAL

APIC

LOCAL

APIC

The I/O APIC component is programmable – its 24 inputs can be

assigned to interrupt ID-numbers in the range 0x20..0xFF (lower

numbers are reserved by Intel for the CPU’s exception-vectors)

The I/O-APIC’s 24 Redirection Table registers determine these assignments

slide17
Two-dozen IRQs
  • The I/O APIC in our classroom machines supports 24 Interrupt-Request input-lines
  • Its 24 programmable registers determine how interrupt-signals get routed to CPUs

Redirection-table

slide18
Redirection Table Entry

63 56 55 48 32

destination

extended

destination

reserved

31 16 15 14 13 12 11 10 9 8 7 0

reserved

M

A

S

K

E

/

L

R

I

R

R

H

/

L

S

T

A

T

U

S

L

/

P

delivery

mode

interrupt

vector

ID

000 = Fixed

001 = Lowest Priority

010 = SMI

011 = (reserved)

100 = NMI

101 = INIT

110 = (reserved)

111 = ExtINT

Trigger-Mode (1=Edge-triggered, 0=Level-triggered)

Remote IRR (for Level-Triggered only)

0 = Reset when EOI received from Local-APIC

1 = Set when Local-APICs accept Level-Interrupt

sent by IO-APIC

Interrupt Input-pin Polarity (1=Active-High, 0=Active-Low)

Destination-Mode (1=Logical, 0=Physical)

Delivery-Status (1=Pending, 0=Idle)

our ioapic c module
Our ‘ioapic.c’ module
  • Last semester we created a module that will show us which IRQ-numbers are not currently being used by our system, and the Interrupt-IDs those IRQ-signals were assigned to by Linux during ‘startup’

Timeout for an in-class demonstration

my isr
my_isr()
  • We created a “dummy” Interrupt Service Routine for our ‘netframe.c’ demo-module

#define IRQ 4 // temporarily unused (normally for serial-UART

#define intID 0x49 // our I/O-APIC has assigned this ID to to IRQ 4

irqreturn_t my_isr( int irq, void *my_netdev_addr )

{

struct net_device *dev = (struct net_device *)my_netdev_addr;

MY_DRIVERDATA *priv = dev->priv;

// we do processing of the received packet in our “bottom half”

tasklet_schedule( &priv->my_rxtasklet );

return IRQ_HANDLED;

}

installing and removing an isr
Installing and removing an ISR

option-flags

name for display

entry-point for interrupt-handler

ISR data-argument

IRQ’s signal-number

if ( request_irq( IRQ, my_isr, IRQF_SHARED, dev->name, dev ) < 0 )

return –EBUSY;

This statement would go in the driver’s ‘open()’ function…

…and this statement would go in the driver’s ‘stop()’ function

free_irq( IRQ, dev );

Here ‘dev’ is the address of the interface’s ‘struct net_device’ object

processing a received packet
Processing a received packet
  • When the NIC notifies our driver that it has received a new ethernet-packet, our driver must allocate a socket-buffer structure for the received data, initialize the ‘sk_buff’ with that data and supporting parameters, then pass that socket-buffer upward to the kernel’s network subsystem for delivery to the appropriate application-program that is listening for it
the key statements5
The ‘key’ statements…

void my_rxhandler( unsigned long data )

{

struct net_device *dev = (struct net_device *)data;

struct sk_buff *skb;

int rxbytes = 60; // just an artificial value here

skb = dev_alloc_skb( rxbytes + 2 );

skb->dev = dev;

skb->protocol = eth_type_trans( skb, dev );

skb->ip_summed = CHECKSUM_NONE;

dev->stats.rx_packets += 1;

dev->stats.rx_bytes += rxbytes;

netif_rx( skb );

}

triggering the interrupt
Triggering the interrupt…
  • We allow a user to trigger execution of our interrupt-handler (for testing purposes), by reading from a pseudo-file that our driver creates during module-initialization, whose ‘get_info()’ function includes execution of a software-interrupt instruction: ‘int $0x49’
  • This inline assembly language instruction is produced via the GNU ‘asm’ construct
using the asm construct
Using the ‘asm-construct’

#define intID 0x49

asm(“ int %0 “ : : “i” (intID) );

parameter-value (symbolic)

statement keyword

parameter type (“i” = immediate data)

assembly language opcode

parameter indicator

This example shows how a symbolic constant’s value, defined in the high-level

C programming language using a ‘#define’ preprocessor directive, is able to be

referenced by an “inline” assembly language statement within a C code-module

testing our framework
Testing our ‘framework’
  • You can download, compile, and install our ‘netframe.c’ network driver module
  • It doesn’t do anything with real hardware, but it does illustrate essential interactions of a network device driver with the Linux operating system’s networking subsystem
in class exercise 1
In-class exercise #1
  • Use the ‘/sbin/ifconfig’ command to assign an IP-address to the ‘struct net_device’ object that our framework-module creates
  • You can discover the interface’s name by using our earlier ‘netdevs.c’ module
  • You should use a ‘private’ IP-address
  • EXAMPLE (for station ‘hrn23501’):

$ sudo /sbin/ifconfig eth1 192.168.86.1 up

in class exercise 2
In-class exercise #2
  • Use ‘ifconfig’ to confirm the IP-address, the IRQ, and the interface’s status:

$ /sbin/ifconfig eth1

  • Use ‘ifconfig’ to examine the interface’s statistics (packets transmitted/received)
in class exercise 3
In-class exercise #3
  • Use the ‘cat’ command to simulate an interrupt from your device’s interface
  • Verify that your interrupt-handler did get executed, by looking at the statistics, and by displaying the output of a pseudo-file Linux creates (named ‘/proc/interrupts’)

$ cat /proc/interrupts

in class exercise 4
In-class exercise #4
  • Try removing the ‘netframe.ko’ module (with the ‘/sbin/rmmod’ command), then use the ‘dmesg’ command to see your system’s log-file messages
ad