Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I have a little experience with C programming so I am playing around with some examples, and making my first LKM. I would like to know what’s the best method for storing data in a LKM that can be accessed/modified later by any function in that LKM later?
From the little I know it sounds like a job for a global variable. I have learned that global is bad so I wanted to check before going that route. My thought is to create a structure that will function as a row to store the required pieces of data. I would create a structure for each row I need, and add it to an array.
This way later in my LKM I can access that particular row of data, and read/modify it as needed. Of course I would have to locate the correct one in the array first so I am not sure the best approach for doing this.
Sorry if its a dumb question, but I have not finish even one of my C books yet, and none of them cover LKM development. Looks like an excuse to buy more books
I hate to disappoint you, but LKM programming is going to be a waste of your time until you are *much* *much* more competent with C. Like, forget this right now. Honestly.
However, since you said you've been playing around with some examples, I'll give you a hint: a global is fine for this purpose, but not required. Global structs are totally normal in kernel modules.
The extent of them is kind of up to you; I believe there is a "private data" pointer in (eg) the cdev and/or file_operations struct that you pass to the kernel in your module_init function; you can kalloc a block and leave a pointer to it there, since when the kernel calls the other registered functions, it will include (eg) a struct file which itself will include a pointer to the file_operations you submitted (I might have this backward; it could be struct file which has the private data field and must be submitted in your "open" function).
I am just toying with some ideas for a WAN accelerater, but to implement some of the features I needed to store the session info for each new TCP session the machine sees open. I figued the best way is to hash together the client ip:port, and the server ip:port. That should create a unique ID that would be identical on both the client accelerator, and the server accelerator. Being new to all this I am not sure if this is even a good method, but I expect it to work.
I like the hash idea because I thought it would be easier/faster to lookup a single hash field than checking souce ip:port, and dest ip:port combinations in order to find the session a particular packet belongs to.
A problem I have though is that closing the session with TCP FIN can be instigated from either the client, or the server. This could possibly break my HASH method for creating identical IDs at both client and server locations without actually passing data between the two accelerators. Because I need to know if the FIN was sent by the client or server to get the hash correct, and remove the info for the correct session once that session is closed.
For now thought I am just begining to read data in the ip packet, and tcp segment in order to sort them based on the souce either client or server. I am pretty sure I have that part work except for the session close because the TCP FIN issue. Possibly some more thinking, and Ill have a solution to that also.
I guess if you have a good idea of what you want to do and are determined enough you should be able to. If this is all kernel space activity, then you can use very large chunks of memory there with no restriction (the total limit is 896MB).
Keep in mind that struct file private_data field (a void pointer) and much luck.
I am using dev_add_pack(), and from my limited understanding it creates a called/triggered function that gets executed when a packet is received, or sent.
How can I access an array in the module from packetprocessor_func()? I need the data to be persistant from one execution of packetprocessor_func() to the next.
I think I am getting it figured out. packet_type does not have a "data" or "private_data" field, but I did find a "af_packet_priv" field and its a pointer so thats probably been renamed. Now I wonder do I need my function to accept that as a parameter too?
I start with a structure that will store the shared data, and a pointer that will point to the memmory used to store the shared data. I then use a variable to specify how many slots there are. When the module loads I vmalloc the memory, and assin it to the sessions pointer.
Then my packet_type uses that somehow... not sure if the packet type passes it as a parameter to the function or how it works at this point.
Code:
/* Structure used to store TCP session info. */
struct session {
__u32 largerIP; /* Stores the larger IP address. */
__u16 largerIPPort; /* Stores the larger IP port #. */
__u32 smallerIP; /* Stores the smaller IP address. */
__u16 smallerIPPort; /* Stores the smaller IP port #. */
__u32 local; /* Stores the local PacketProcessor IP. */
__u32 remote; /* Stores the remote PacketProcessor IP. */
__u8 state; /* Stores the TCP session state. */
};
/* Session array data. */
__u8 *sessions;
__u32 SESSIONSLOTS = 1024; /* Starting with capacity to track 1024 sessions. */
static struct packet_type pt =
{
.type = __constant_htons(ETH_P_ALL),
.func = packetprocessor_func,
.af_packet_priv = &sessions,
};
static int __init packetprocessor_init(void)
{
printk(KERN_ALERT "Loading Packet Processor...\n");
sessions = vmalloc(SESSIONSLOTS * sizeof(struct session)); /* Initialize sessions array. */
dev_add_pack(&pt);
return 0;
}
static void __exit packetprocessor_exit(void)
{
dev_remove_pack(&pt);
printk(KERN_ALERT "Unloading Packet Processor...\n");
vfree(sessions);
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.