Change the ifindex of netdev - linux

I have the following requirement. I want with a kernel module to change the ifindex of a netdev with one of my choice. I know that it acts as a key and cannot be change during runtime. Created interfaces are based on Intel e1000 driver.
In order to achieve the change the following has been thought:
unregister_netdev(dev);
//Change the dev->ifindex
//bring back network device to operational state somehow, tried register_netdev but this results in kernel panic of course
Can you please inform me if this is somehow possible? I am very new to linux kernel drivers.
Thank you!

I think I have found a trick/way to tackle this issue:
create a dummy network namespace
use dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat) to move device to this namespace
then use __dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat, int new_ifindex) to move dev to init_net with the
desired new_ifindex
delete dummy network namespace
In my kernel __dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat, int new_ifindex) does not exist but it is not though so hard to be created since it only pickups a new_ifindex in case it is not provided, or checks the provided one if it is currently used inside namespace
Not tested yet, but it will be very soon.

Related

Handling multiple i2c_clients in one driver module (with sysfs)

I want to create a kernel driver for tmp102 temperature sensors.
In one project I have only 1 sensor, in the other - 2 sensors. I want my kernel module to be able to support N sensors, not a fixed number. I have a problem with managing more than 1 struct i2c_client and creating sysfs entries for each of them. Here's how I'm doing it:
In the probe() function I get struct i2c_client* for each of the devices that I provide I2C_BOARD_INFO() for.
I then kobject_create_and_add("tmp102", kernel_kobj) to get the main directory for the modules in sysfs.
For each device I'm creating sysfs_create_group() which gets the pointer to statically created attributes. The attributes have the (*show)() and (*store)() pointers set to static functions, e.g.
static ssize_t tmp102_sysfs_thigh_get_one(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
In this function I want to read via I2C. The problem is... I don't know how to get the struct i2c_client * for the device which should be somehow linked to this sysfs entry, and the I2C address is there!
How should I properly "link" i2c_client with sysfs entries, so that I can get the I2C address inside the functions?
Ideally, I would like to have just one set of functions (one for each of the attributes). The sysfs tree should look like that:
/sysfs/kernel/tmp102
|
|-> <hex i2c address, e.g. /48>
| |
| |-> temperature
|
|
|-> /49
|
|-> temperature
I want both 'temperature' attributes to use the same function, which is able to determine the I2C address, to which it should write.
Or maybe my architecture is plain wrong? If so, how should it look like for a driver that needs to handle multiple i2c_clients?
EDIT:
I decided to use struct device_attribute instead of regular attributes. To my understanding, it is not easy to get the struct device pointer when using the regular attributes, same with struct i2c_client. They are not easily "linked" with kobjects from /sys/kernel, where I need to have my attributes for this project. device_attributes can be found in /sys/devices - I used sysfs_create_group and linked my device's kobject with the device_attribute group. I used sysfs_create_link, and linked my device's kobject with the /sys/kernel/tmp102. This way I could create a folder (link) for each of the devices, which points to the original attributes folder in /sys/devices.
First, you should know that there is already a kernel driver for the tmp102 that has a sysfs interface. Have a look at drivers/hwmon/tmp102.c.
Now, for your issue, you have a struct kobject that is passed to you sysfs callback. You can call kobj_to_dev() to get a pointer to the device. Then, for example, you could use dev_get_drvdata() to get a pointer to your own private structure that would contain a pointer to the i2c client. Don't forget to set it first with dev_set_drvdata() in your probe.
You have can find an example in drivers/rtc/rtc-ds1343.c but it is using an spi_driver.

Getting ENOTTY on ioctl for a Linux Kernel Module

I have the following chardev defined:
.h
#define MAJOR_NUM 245
#define MINOR_NUM 0
#define IOCTL_MY_DEV1 _IOW(MAJOR_NUM, 0, unsigned long)
#define IOCTL_MY_DEV2 _IOW(MAJOR_NUM, 1, unsigned long)
#define IOCTL_MY_DEV3 _IOW(MAJOR_NUM, 2, unsigned long)
module .c
static long device_ioctl(
struct file* file,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
...
}
static int device_open(struct inode* inode, struct file* file)
{
...
}
static int device_release(struct inode* inode, struct file* file)
{
...
}
struct file_operations Fops = {
.open=device_open,
.unlocked_ioctl= device_ioctl,
.release=device_release
};
static int __init my_dev_init(void)
{
register_chrdev(MAJOR_NUM, "MY_DEV", &Fops);
...
}
module_init(my_dev_init);
My user code
ioctl(fd, IOCTL_MY_DEV1, 1);
Always fails with same error: ENOTTY
Inappropriate ioctl for device
I've seen similar questions:
i.e
Linux kernel module - IOCTL usage returns ENOTTY
Linux Kernel Module/IOCTL: inappropriate ioctl for device
But their solutions didn't work for me
ENOTTY is issued by the kernel when your device driver has not registered a ioctl function to be called. I'm afraid your function is not well registered, probably because you have registered it in the .unlocked_ioctl field of the struct file_operations structure.
Probably you'll get a different result if you register it in the locked version of the function. The most probable cause is that the inode is locked for the ioctl call (as it should be, to avoid race conditions with simultaneous read or write operations to the same device)
Sorry, I have no access to the linux source tree for the proper name of the field to use, but for sure you'll be able to find it yourself.
NOTE
I observe that you have used macro _IOW, using the major number as the unique identifier. This is probably not what you want. First parameter for _IOW tries to ensure that ioctl calls get unique identifiers. There's no general way to acquire such identifiers, as this is an interface contract you create between application code and kernel code. So using the major number is bad practice, for two reasons:
Several devices (in linux, at least) can share the same major number (minor allocation in linux kernel allows this) making it possible for a clash between devices' ioctls.
In case you change the major number (you configure a kernel where that number is already allocated) you have to recompile all your user level software to cope with the new device ioctl ids (all of them change if you do this)
_IOW is a macro built a long time ago (long ago from the birth of linux kernel) that tried to solve this problem, by allowing you to select a different character for each driver (but not dependant of other kernel parameters, for the reasons pointed above) for a device having ioctl calls not clashing with another device driver's. The probability of such a clash is low, but when it happens you can lead to an incorrect machine state (you have issued a valid, working ioctl call to the wrong device)
Ancient unix (and early linux) kernels used different chars to build these calls, so, for example, tty driver used 'T' as parameter for the _IO* macros, scsi disks used 'S', etc.
I suggest you to select a random number (not appearing elsewhere in the linux kernel listings) and then use it in all your devices (probably there will be less drivers you write than drivers in the kernel) and select a different ioctl id for each ioctl call. Maintaining a local ioctl file with the registered ioctls this way is far better than trying to guess a value that works always.
Also, a look at the definition of the _IO* macros should be very illustrative :)

Linux cdev vs register_chrdev

I am reworking a driver and came across the cdev interface in LDD3. After reading http://lwn.net/Articles/195805/ I am more confused than enlightened. From the comments there
In order the device to actually appear in the file system, you have to call device_create (class, parent_dev, devno, device_name).
In order to call device_create you need to have a device class object: either use one of the existing classes, or create your own with create_class (THIS_MODULE, class_name)
I think this is for sysfs only.
So, is the new interface an attempt to change something that failed,
and is it thus recommended to continue using device_create?
If cdev is recommended how do I create the sysfs entry?
I never quite understood the benefit of having a device class, is
there a point in having one and if so how do I implement it with
cdev?
cdev is the char device representation of the kernel. The general idea is to associate cdev with a set of file_operations. These file_operations are performed on a device node, typically present under /dev. cdev_init() is used to associate/link a cdev with a set of file_operations. Finally cdev_add() is called on the device to make it live, such that, the user could access them.
Now, while this is done, it doesn't mean that the device node is created for you. This is done manually by using mknod utility(as explained in LDD3). In general, the drivers are supposed to create the device nodes. This is achieved using device_create() function. Device nodes are generally associated with a class. Thus, we need to create a class first(using class_create()) and then create device nodes using that class.
Let me explain this through an example. Consider only the init function(error handling is avoided here to maintain clarity) :
struct class *my_class;
struct cdev my_cdev[N_MINORS];
dev_t dev_num;
static int __init my_init(void)
{
int i;
dev_t curr_dev;
/* Request the kernel for N_MINOR devices */
alloc_chrdev_region(&dev_num, 0, N_MINORS, "my_driver");
/* Create a class : appears at /sys/class */
my_class = class_create(THIS_MODULE, "my_driver_class");
/* Initialize and create each of the device(cdev) */
for (i = 0; i < N_MINORS; i++) {
/* Associate the cdev with a set of file_operations */
cdev_init(&my_cdev[i], &fops);
/* Build up the current device number. To be used further */
curr_dev = MKDEV(MAJOR(dev_num), MINOR(dev_num) + i);
/* Create a device node for this device. Look, the class is
* being used here. The same class is associated with N_MINOR
* devices. Once the function returns, device nodes will be
* created as /dev/my_dev0, /dev/my_dev1,... You can also view
* the devices under /sys/class/my_driver_class.
*/
device_create(my_class, NULL, curr_dev, NULL, "my_dev%d", i);
/* Now make the device live for the users to access */
cdev_add(&my_cdev[i], curr_dev, 1);
}
return 0;
}
Now, answering to your questions one by one :
So, is the new interface an attempt to change something that failed, and is it thus recommended to continue using device_create?
This isn't a new interface. This can be said as an extension, generally used to create device nodes. It also gives us the advantage of creating sysfs attributes, which provides much flexible means to access kernel resources. The functions device_create() returns a pointer to struct device which has a very powerful meaning in the kernel. Take a look at the chapter on 'Linux Device Model' in LDD3.
If cdev is recommended how do I create the sysfs entry?
cdev and sysfs entries are independent of one another. You can create sysfs entries even without cdev. Again, look at the chapter on 'Linux Device Model' in LDD3. You may also look at this sample code for creating sysfs entries : http://lxr.free-electrons.com/source/samples/kobject/kobject-example.c
I never quite understood the benefit of having a device class, is there a point in having one and if so how do I implement it with cdev?
I hope the above code answers this question.
In general, you may not use cdev at all in your drivers. cdev is a very low level representation. Using cdev many powerful frameworks are built for the types of devices, such as, input, tty, ALSA, IIO, etc etc. All these frameworks are built upon cdev. So, you may not use cdev directly. Instead, you could register with these frameworks and access your device in a much more efficient way. Registering to these frameworks also create device nodes and sysfs entries for you.
Hope this helped.

Linux kernel device model - Which devices are following it?

My question is about linux device model. I did some digging myself in the source code and found that the device model works around many structures out of which some of them are:
struct device
struct device_driver
struct bus_type
There are more related to power management.
But when I looked into the char drivers implemented in linux kernel (or if I implement my own char driver) linux kernel is only implementing "struct device" and all other structures are just NULL. I have checked this through some debugging and with friendly neighbourhood API printk().
So my question is then why char drivers are not completely following the device model?
Also which drivers are completely following linux device model?
Linux Device Model uses kobject as it's base which act as a glue to held it together.
The structures you mentioned come at a layer above kobject.
So, we can say that kobject is something that you will (almost) never come across but is still embedded everywhere.
And char drivers are no excuse:
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
All drivers are following device model even without you know it, hence char drivers are no exception here too.
Look at implementation of cdev_add() and you will get your answer.
I suggest you go through this article and dig again inside LDM code.

Creating a device file: Linux device driver

How to create a device file when I do not know the minor and major number (i.e. by using dynamic registration) without using mknod or MAKEDEV.
Say you want to dynamically assign a major number to a char device on insertion, use:
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
From Linux Device Drivers 3rd Edition. Google it you can get the entire book for free along with tons of great source code for messing with drivers.
Also, the codes provided in the LDD3 are obsolete now. So, use this github repo to download example codes of LDD3: https://github.com/martinezjavier/ldd3

Resources