Get in touch:
01524 851 877
07718 896 553

FreeBSD TODO Lists

Posted on Jun 25 2009

I just spotted an email on the FreeBSD Hackers mailing list asking for small open source projects for a few students to partake in. Of more interest was one of the replies. It had a list of url’s for the FreeBSD TODO lists that I hadn’t seen before. So if anyone is looking to contribute to the FreeBSD project in any way this would be a good place to start. There are a number of different areas within which you can participate and the TODO lists are quite a nice way to break things down so people can easily spot areas where their expertise could be useful.

Anyway here is the list of url’s thanks to Joel Dahl over at FreeBSD:

Networking
IPv6
Bsnmp
Jails
USB
SMP

Hash Table Implementation

Posted on Jun 12 2009

I have been doing some more kernel module coding and have been using the linked list implementation provided by list.h quite a bit recently as I have known in advance that the lists would only ever have a small amount of entries so looping through the list would not prove to be too much of a performance penalty.

For my latest problem however I have a list that could grow a bit larger in size so I made the decision to use a hash table instead of a linked list. I searched through the kernel source naively hoping there would be a neat generic hash table implementation included.. Alas there is not.

After a bit of searching I stumbled across uthash. This is a nice hash table implementation allowing you to basically put any struct into a hash table based on using one of the fields in the struct as the id. The included macro’s allow a string or an int to be used for the id as well which is quite useful.

So far it seems quite simple to use. All the functions are included in one header file wrapped us as macro’s so it is nice and easy to integrate with any project and it doesn’t rely on much to be included externally. In my case all the functions it does need are provided by the kernel so it was very simple to integrate. I will definitely be using this again in other projects in the future.

Simple Sleeping Linux Kernel Thread

Posted on May 26 2009

I am currently implementing the timeout functionality for the NP++ kernel module. Each physical mapping has a function pointer defined in its descriptive struct (struct np_sw) as described here.

Until now this hasn’t actually been implemented but I wanted to create a kernel thread that simply sleeps for 500 milliseconds, then awakes and looks through all the physical mappings available on the system and calls their timeout function.

This is a fairly simple process but in order to achieve it we need to include a couple of new headers :

#include <linux/kthread.h>
#include <linux/delay.h>

The first of these is for the thread related functions needed and the second is to allow us to sleep the thread.

Now we have those included we need to declare a function that will be called when we start the thread as follows :

int timeout_thread(void *data)
Any kernel thread function needs ro return an int and take a void pointer as the only argument to conform with the function pointer defined the kthread_create() function in kthread.h which the kthread_run() macro is a wrapper for.

Now we need to actually create the thread. I have done this in the modules init_module() function as follows:

kthread_run(timeout_thread, NULL, "NP++ Timeout Thread");
Now this is all done we simply need to put some implementation into the timeout_thread() function to perform the sleep as follows:

while(1)
{
set_current_state(TASK_RUNNING);
//Some Code Here
set_current_state(TASK_INTERRUPTIBLE);
msleep(500);
}

This sets the state of the thread to TASK_RUNNING to tell the kernel that the thread is working. The code to call the mappings individual timeout functions will go here. Then we set the state to TASK_INTERRUPTIBLE to tell the kernel we aren’t doing anything at which point we call the msleep() function to sleep the thread for 500 milliseconds.

Compile the module and you have a nice thread that will run roughly every 500 milliseconds. If you need a longer delay that can be measured in seconds the delay.h header also defines the following function that takes the number of seconds as the only argument:

void ssleep(unsigned int seconds);

Conditional Statements Explained

Posted on Jun 11 2008

I have often used #if, #ifdef, #if defined() etc as conditional preprocessor directives but haven’t really thought in depth about the differences between them. It was only when someone asked the question in a C channel on freenode that it made me think.

A quick search of google brought me across a nice little explanation. Rather than recycling the information here is the link :

Conditional Compilation (#if, #ifdef, ..#endif)

Quite an interesting little read.

Linux XFRM Framework Selectors

Posted on Apr 17 2008

Whilst progressing some code I have been writing I was recently introduced to Linux’s XFRM (transform) framework. I had not heard of this before but it can be a very useful tool for manipulating packets.

The one big downside to XFRM is there is virtually no documentation on it yet. This can make working with it quite tricky. I am documenting what I find out from using it here in the hope that others will find it useful.

The basic idea behind XFRM is that it allows you to select a packet based on a number of factors. These are all defined in /usr/include/linux/xfrm.h in a struct named xfrm_selector as defined below :

struct xfrm_selector
{
xfrm_address_t daddr;
xfrm_address_t saddr;
__be16 dport;
__be16 dport_mask;
__be16 sport;
__be16 sport_mask;
__u16 family;
__u8 prefixlen_d;
__u8 prefixlen_s;
__u8 proto;
int ifindex;
uid_t user;
};

Creating a struct of this type and setting the fields such as the source/destination addresses, ports, address masks etc, allows a packet to be selected, based on this criteria, to allow it to be transformed. By passing this information into the kernel using a nlmsghdr struct and the addattr_l() function along with a template (struct xfmr_user_tmpl) describing what action to take on the packet we can alter certain packets however we wish.

This is proving very useful to me in some of my current work and I will continue to post anything I think might be useful to others working in the same area on this blog.

Structure Packing in GCC

Posted on Mar 26 2008

I have recently been doing a lot of coding using the NEPL NEMO Implementation as a part of a project I am working on. This has proved to be very interesting work and has brought about lots of interesting problems.

One of the most recent problems I faced involved a packet I was sending over the network using a header I had constructed using a struct as follows.

struct Nino
{
uint8_t type;
uint8_t length;
uint8_t prefix_len;
uint8_t res_l_4;
uint32_t nino_lifetime;
uint32_t reserved2;
uint8_t nino_depth;
uint8_t reserved3;
uint16_t nino_seq;
struct in6_addr _prefix_in6_addr;
};

This was the exact packet header format that I required but when I received a packet and checked it using a version of Wireshark I had modified to recognise the header format, I was getting what seemed like an erroneous 2 Bytes of data (set to 0’s) at the beginning of the in6_addr. This puzzled me for a while until I started to think about how GCC would lay out the fields in the struct. Of course GCC tries to optimise the struct for passing across the hardware and pads it if it feels it is necessary.

For my purposes this ruins the whole layout of the packet header for processing so I had a look around and found that GCC has an attribute named __packed__ that will force it not to pad the struct out. Or in the terms of the GCC Manual :

  • “a variable or structure field should have the smallest possible alignment–one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.”

This was exactly what I wanted. So by changing the struct definition from that above, to :

struct Nino
{
uint8_t type;
uint8_t length;
uint8_t prefix_len;
uint8_t res_l_4;
uint32_t nino_lifetime;
uint32_t reserved2;
uint8_t nino_depth;
uint8_t reserved3;
uint16_t nino_seq;
struct in6_addr _prefix_in6_addr;
}__attribute__((__packed__));

My code behaved exactly as I required. Problem solved. This is a handy little function of GCC especially when dealing with network packets to make sure you know exactly how the compiler is behaving and hence avoiding any unwanted surprised.

A slightly more in depth look at the packed attribute can be found here.