Implementing An NP++ Mapping Module HOWTO

From Matt's Wiki

Jump to: navigation, search

This page gives an overview of how you can write your own kernel module for NP++ including a working example and a very basic Makefile.

The first thing to do is create a directory somewhere for all your source code. Create a .c file to act as the main file for your module and add something similar to the following:

#include <linux/module.h>
 
#include <linux/if.h>         /*
#include <linux/skbuff.h>      * A couple of includes needed for np-mod.h */
 
#include "sample_map.h" /* Our mapping module header file */
#include "../np-mod.h" /* Replace this path with the path to where you have the NP++ module source code installed */
 
#define DRIVER_AUTHOR "Matthew Jakeman <m.jakeman@lancaster.ac.uk>"
#define DRIVER_DESC   "NP++ Sample Mapping"
 
MODULE_LICENSE("GPL");
 
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);

This is all pretty standard module stuff. Along with this you will need two functions. One for initialising the module init_module() and one to perform clean up operations when the module is unloaded cleanup_module() as follows.

int init_module(void)
{
    return 0;
}
 
void cleanup_module(void)
{
}

Again, this is pretty standard module stuff. The next section focuses on the code for the init_module() function.

init_module() Function

The first thing we need to do is create a struct of type np_sw and initialise it. This is the NP++ switch struct that contains all the information needed by a mapping. The declaration of the struct as it appears in np-mod.h is shown below :

struct np_sw
{
    struct list_head npswl; // Used for linked list
    u_char phy_id; // ID of the mapping
    const char *desc; // Textual Description
    int (*phy_input) (struct sk_buff **, const struct net_device *); // Input Function
    struct sk_buff *(*phy_output) (const struct net_device *, struct sk_buff *); // Output function
    void (*phy_slowtimo) (void) ; // Timeout Function (Not Yet Implemented)
    /*
    * Counters
    */
    long p_sent;   //Packets Sent
    long p_recvd;  //Packets Received
    long p_in_dropped; //Incoming Packets Dropped
    long p_out_dropped; //Outgouing Pacjets Dropped
};

An example intialisation of a struct for use in a mapping module is shown below. This should be placed in the init_module() function.

 static struct np_sw sample_np_sw;

This struct should be declared globally for use later in the cleanup function.

 sample_np_sw.phy_id = NP_PHYS_SAMPLE; // Mapping ID
 sample_np_sw.desc = "Sample Mapping"; // Textual Description
 sample_np_sw.phy_input = sample_input; // Input Function
 sample_np_sw.phy_output = sample_output; // Output Function
 sample_np_sw.phy_slowtimo = NULL; // Timeout Function (Not Implemented At Present)
 sample_np_sw.p_sent = 0; // Packets Sent
 sample_np_sw.p_recvd = 0; // Packets Received
 sample_np_sw.p_in_dropped = 0; // Packets Dropped On Input
 sample_np_sw.p_out_dropped = 0; // Packets Dropped On Output

The next thing to do is call the np_mapping_add() function from the NP++ API as such.

np_mapping_add(&sample_np_sw);

This function takes care of adding the mapping into the NP++ framework.

Now we need to create the functions that we set when we initialised the np_sw struct. They should be declared in the source as follows.

int sample_input(struct sk_buff **skb, const struct net_device *netd)
{
    return 0;
}
 
struct sample_sk_buff *def_output(const struct net_device *netd, struct sk_buff *skb)
{
    return skb;
}

These functions are what can be used to perform operations on the packet either on input or output to/from the host.

The input function has two arguments a pointer to a pointer to a sk_buff struct that contains the packet. It also has a pointer to the net_device struct that describes the interface that the packet will be leaving the host on. A more detailed description of the sk_buff struct can be found here, and the net_device struct here.

The output function contains a pointer to the net_device struct describing the interface the packet was received on along with a pointer to a sk_buff struct containing the packet.

cleanup_module() function

This is relatively simple as all you need to do here is remove the mapping from the NP++ framework. There is a function provided by the API for this as follows.

np_mapping_del(&sample_np_sw);

Making The Module

Now all this is done it is time to Make the module. The makefile below can be used for this.

obj-m := sample_map.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

One important thing here is that in order to resolve some of the symbols created and exported by the main NP++ module you need to copy over the Module.symvers file from the directory in which the NP++ module was compiled into the directory you are using to compile the mapping module. This has to be done or you will get link errors about some symbols being undefined when trying to compile your new mapping module.

The full source code for the sample module and the Makefile can be found here.

Personal tools