2
votes

I'm trying to write a simple program that takes a packet from an interface and prints out its destination and source MAC addresses at the Linux Kernel level. This is my first project working with the Linux Kernel and I have been reading through a lot of source code and books to do with netdevice, loopback and skbuff. Now, from what I have learnt so far skbuff looks like where packet data is placed, but I cannot see how a network device driver takes packets from an interface and places them into an skb or how you get skb's related with a particular interface.

Could someone tell me how I look at skb's linked to a netdevice such as eth0? Is there some sort of transmit and receive ring I need to pick them up off?

Some sample code would be amazing! Failing that, if someone could point to a some source code (more than just the filename...line number and function name would be great).

Sorry if this is a vague question I have tried to research as much as I can. Thanks in advance.

2

2 Answers

1
votes

You can try using netfilter hooks.

Register your callback with nf_register_hook(), and it will be called for the given address family (e.g. AF_INET is IPv4) and type (e.g. NF_IP_LOCAL_IN for incoming packets). Your hook will also get the skb and the network device via which the packet came in or is going out.

The prototype for your callback looks something like this:

unsigned int my_hook(unsigned int hook,
                     struct sk_buff *skb,
                     const struct net_device *in,
                     const struct net_device *out,
                     int (*okfn)(struct sk_buff *));

There is an (outdated) example at http://www.sikurezza.org/ml/12_99/msg00063.html as well, but you can also dig into the kernel source, there are several examples how the network stack or iptables modules use netfilter hooks.

1
votes

Take the dame codes of one ethernet chip which PCI based as example: ./drivers/net/pci-skeleton.c. Maybe this code is old style of ethernet driver, but it's userful for study.

The packet receive flow: netdrv_rx_interrupt() --> allocate/replace sk_buff --> call netif_rx() passing the packet/sk_buff received to upper stack layer;

The packet send flow: netdrv_start_xmit();

The device init flow: one can start from init_module();

The common functions can be found in ./net/core/dev.c, such as netif_rx...;