When developing virtual network device drivers for Linux, sometimes there is a need of redirecting packets between the real device and a virtual one.
Fortunately, the Linux kernel (version 4.14 in our case) has the right tools to do so, without any extra headache. Let’s look at redirecting incoming packets from a real network device. To do so, you don’t even have to change the sources of a real network driver itself. All you need to do is just use the mechanism of rx_handlers. To add your own handler, you need to use the following API call from your virtual driver:
int netdev_rx_handler_register (
struct net_device * dev,
rx_handler_func_t * rx_handler,
void * rx_handler_data);
The signature of a rx_handler is following: typedef rx_handler_result_t rx_handler_func_t(struct sk_buff **pskb); Here is the list of possible return codes: enum rx_handler_result { RX_HANDLER_CONSUMED, RX_HANDLER_ANOTHER, RX_HANDLER_EXACT, RX_HANDLER_PASS, }; This enum has a good amount of description in Linux sources, so we will stop in what we need – RX_HANDLER_ANOTHER. So, let’s summarize what we should do to redirect incoming packets to a different device:- Register rx_handler
- In rx_handler change dev (pointer to net_device struct) to the device we want to redirect packets to
- Return RX_HANDLER_ANOTHER to inform the kernel that we actually changed the destination device