How is replaced struct tcp_opt in the newer kernel? - linux-kernel

I working on an old module for kernel 2.4.x and want to rewrite it for kernel 4.15.0.19.
There is a declaration which is causing an error during the compilation:
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
I checked in the newer kernel and tcp_opt struct is not defined anywhere, neither tp_pinfo union nor af_tcp.
From 2.4.x kernel, it is declared inside struct sock as follows:
union {
struct tcp_opt af_tcp;
#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE)
struct raw_opt tp_raw4;
#endif
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct raw6_opt tp_raw;
#endif /* CONFIG_IPV6 */
#if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE)
struct spx_opt af_spx;
#endif /* CONFIG_SPX */
} tp_pinfo;
What is the purpose of the first initialisation (in the beginning of the question) and how is this replaced in the newer kernels?
EDIT:
I managed to solve this using:
const struct tcp_sock *tp = tcp_sk(sk);
And then accessing the TCP Options in this way:
tp->rx_opt.rcv_tsval

Related

Specialized template accepting constructor parameter when only default constructor defined

So, I have this template class and its specialization.
#include <iostream>
using namespace std;
template<bool> struct CompileTimeChecker{
CompileTimeChecker(...); //constructor, can accept any number of parameters;
};
//specialized template definition
template<> struct CompileTimeChecker<false> {
//default constructor, body empty
};
Case 1:
In the main function I am defining a local class called ErrorA. When I create a temporary of CompileTimeChecker<false> with temporary object of ErrorA fed as an initializer, the compiler is not detecting any error.
int main()
{
class ErrorA {};
CompileTimeChecker<false>(ErrorA()); //Case 1;
CompileTimeChecker<false>(int()); //Case 2;
return 0;
}
Case 2:
Next I feed it with temporary object of type int, and suddenly the compiler recognizes the issue (there is no constructor that takes args in the specialized template CompileTimeChecker<false>)
main.cpp:30:36: error: no matching function for call to ‘CompileTimeChecker::CompileTimeChecker(int)’ CompileTimeChecker<false>(int());
main.cpp:21:23: note: candidate: constexpr CompileTimeChecker::CompileTimeChecker()
template<> struct CompileTimeChecker<false> {
^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:21:23: note: candidate expects 0 arguments, 1 provided
Why does it not recognize the issue in case 1?
CompileTimeChecker<false>(ErrorA());
does not create a temporary of type CompileTimeChecker<false>, passing a temporary ErrorA() to its constructor. Rather, it declares a function named ErrorA, taking no parameters and returning CompileTimeChecker<false> . See also: most vexing parse.
On the other hand, CompileTimeChecker<false>(int()); cannot be parsed as a declaration, so it does unambiguously create a temporary of type CompileTimeChecker<false>.
The easiest way out is to use braces in place of parens to indicate initialization:
CompileTimeChecker<false>{ErrorA{}};

error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]

I am working on a linux kernel module.
A struct tcpsp_conn is defined in the header file as follows:
struct tcpsp_conn {
...
struct timer_list timer; /* exp. timer*/
...
};
Then I declare a pointer to the structure and try to assign the function:
struct tcpsp_conn *cp;
cp->timer.function = tcpsp_conn_expire;
tcpsp_conn_expire function is defined in the same way as in the struct timer_list of the kernel:
static void tcpsp_conn_expire(unsigned long data)
I don't understand why am I getting this error:
error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
cp->timer.function = tcpsp_conn_expire;
It doesn't look to have a problem with types.
Type of your tcpsp_conn_expire function differs from the type of .function field of the timer_list structure.
In the newest kernel (since 4.15) this function-field is declared with struct timer_list * argument instead of unsigned long, as follows:
struct timer_list {
...
void (*function)(struct timer_list *);
...
};
Having such argument, you may obtain the pointer to the struct tcpsp_conn structure, into which the timer is embedded, with macro container_of.

How to attach file operations to sysfs attribute in platform driver?

I wrote a platform driver for a peripheral we developed and would like to expose some configuration options to the sysfs. I have managed to create the appropriate files using attribute structs (see below) and sysfs_create_file in the probe function, but I can't figure out how to attach the show/store functions to the structs in a platform driver.
Most resources I found online used a device_attribute struct or something similar to create their files, is that also appropriate here? Is there another way to do this for a platform driver?
My attribute struct looks like this:
struct attribute subkey_attr = {
.name = "subkeys",
.mode = S_IWUGO | S_IRUGO,
};
And I register the file using this call:
riddler_kobject = &pdev->dev.kobj;
ret_val = sysfs_create_file(riddler_kobject, &subkey_attr);
It boils down to next:
reuse existing kobject from struct device (from your struct platform_device) for sysfs_create_group() (instead of creating your own kobject)
use DEVICE_ATTR() to declare struct device_attribute instead of regular __ATTR(), which creates struct kobj_attribute.
Here is how I created sysfs attributes for my platform driver.
Create structure you'll be using as private data in show() / store() operations for your sysfs attribute (file). For example:
struct mydrv {
struct device *dev;
long myparam;
};
Allocate this structure in your driver's probe():
static int mydrv_probe(struct platform_device *pdev)
{
struct mydrv *mydrv;
mydrv = devm_kzalloc(&pdev->dev, sizeof(*mydrv), GFP_KERNEL);
mydrv->dev = &pdev->dev;
platform_set_drvdata(pdev, mydrv);
...
}
Create show() / store() functions:
static ssize_t mydrv_myparam_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mydrv *mydrv = dev_get_drvdata(dev);
int len;
len = sprintf(buf, "%d\n", mydrv->myparam);
if (len <= 0)
dev_err(dev, "mydrv: Invalid sprintf len: %d\n", len);
return len;
}
static ssize_t mydrv_myparam_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct mydrv *mydrv = dev_get_drvdata(dev);
kstrtol(buf, 10, &mydrv->myparam);
return count;
}
Create device attribute for those functions (right after those functions):
static DEVICE_ATTR(myparam, S_IRUGO | S_IWUSR, mydrv_myparam_show,
mydrv_myparam_store);
Declare attributes table (listing in fact sysfs files for you driver):
static struct attribute *mydrv_attrs[] = {
&dev_attr_myparam.attr,
NULL
};
Declare attribute group (specifying in fact sysfs directory for your driver):
static struct attribute_group mydrv_group = {
.name = "mydrv",
.attrs = mydrv_attrs,
};
static struct attribute_group *mydrv_groups[] = {
&mydrv_group,
NULL
}
which can be actually replaced with one line:
ATTRIBUTE_GROUPS(mydrv);
Create sysfs directory and files in your driver's probe() function:
static int mydrv_probe(struct platform_device *pdev)
{
int ret;
...
ret = sysfs_create_group(&pdev->dev.kobj, &mydrv_group);
if (ret) {
dev_err(&pdev->dev, "sysfs creation failed\n");
return ret;
}
...
}
Remove your sysfs files in your driver's remove() function:
static int mydrv_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &mydrv_group);
...
}
Race condition note
As #FranzForstmayr correctly pointed out, there may be race condition when adding sysfs files with sysfs_create_group() in mydrv_probe(). That's because user-space can be already notified that those files exist before mydrv_probe() called (where those files are actually being created by sysfs_create_group() function). This issue covered in details in "How to Create a sysfs File Correctly" article by Greg Kroah-Hartman.
So in our case of platform_device, instead of calling sysfs_create_group() (and its counterpart sysfs_remove_group()), you can use default attribute group. To do so, you need to assign corresponding .groups field of your struct device to your attribute groups variable:
static int mydrv_probe(struct platform_device *pdev)
{
...
pdev->dev.groups = mydrv_groups;
...
}
DISCLAIMER: I didn't test this code, though it should work, because of this code.
See [1,2,3] links for more insights on mentioned race condition.
For more examples, run next command in kernel source directory:
$ git grep -l --all-match -e platform_device -e attribute -e '\.groups =' -- drivers/
Also you can search by "default attribute" in commit messages:
$ git log --no-merges --oneline --grep="default attribute" -- drivers/
Some commits I found this way: [4,5,6,7].
References
[1] My attributes are way too racy, what should I do?
[2] PATCH: sysfs: add devm_sysfs_create_group() and friends
[3] [GIT PATCH] Driver core patches for 3.11-rc2
[4] commit 1
[5] commit 2
[6] commit 3
[7] commit 4
Not enough reputation to post a comment, but I just want to comment on the default attribute group note from the accepted answer.
My understanding is that this should not be added in the probe function, as given in the example, but instead should be set in the device struct, (or device_driver, class, or bus depending on your driver) usually defined at the end of your file.
For example:
static struct device iio_evgen_dev = {
.bus = &iio_bus_type,
.groups = iio_evgen_groups,
.release = &iio_evgen_release,
};
from this example
Strangely, according to this it doesn't work correctly when using DEVICE_INT_ATTR to create the attribute, so not sure what that's all about.
Also, I'm not 100% sure, but I think that this is invoked when the driver is loaded, not when the device is probed.
This is an addition to Sam Protsenko's and Anthony's answers
If you create device attributes via the DEVICE_ATTR macros then you have to register the attribute groups (mydrv_groups) in the .dev_groups instead of the .groups field.
static struct device iio_evgen_dev = {
.bus = &iio_bus_type,
.dev_groups = iio_evgen_groups, // .dev_groups for DEVICE_ATTR
.groups = another_attr_group, // .groups for DRIVER_ATTR
.release = &iio_evgen_release,
};
Then the attributes are automatically registered correctly without setting up anything in the probe/remove functions, as described in Greg Kroah-Hartman's article.
Assume that the module has been loaded into the kernel and the driver is registered in
/sys/bus/platform/drivers/mydrv
every device instances will be a subdirectory of the driver's folder like
/sys/bus/platform/drivers/mydrv/mydrv1
/sys/bus/platform/drivers/mydrv/mydrv2
Registering attributes in the .groups field creates the attributes in the driver folder.
Registering attributes in the .dev_groups field creates the attributes in the device's instance folder.
mydrv
├── driver_attr1
├── driver_attr2
└── mydrv1
├── device_attr1
└── device_attr2
The show/store functions of the attributes in the .groups field do not have access to the driver data set via platform_set_drvdata(pdev, mydrv).
At least not by accessing it via dev_get_drvdata(dev).
Accessing the driver data via dev_get_drvdata(dev) returns NULL and dereferencing it will result in a kernel oops.
In turn, he show/store functions of the attributes in the .dev_groups field have access to the driver data via
struct mydrv *mydrv = dev_get_drvdata(dev);

Compilation error: Redefinition of union name

I have this piece of code here and I get a GCC error: Redefinition of union semun right at the beginning of this code
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
};
This program is about communicating with mutexes. I don't think that it's about the other parts of the program because the error comes here, right at the first line of it, and this code is outside the main, at the beginning of the program so there's not any other union declaration before (and after). Thank you
Contrary to X/Open, some platforms define union semun in their headers (specifically in sys/sem.h).
You can check accordingly using appropriate platform identifier macros:
#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \
|| defined(__FreeBSD__) || ...
/* union semun is defined by including <sys/sem.h> */
#else
union semun {
// ...
};
#endif
If you have a meta-make system for your package (configure, CMake, etc.) you might check for the existence of union semun at the configure stage instead of relying on platform checks.

Preventing recursive C #include

I roughly understand the rules with what #include does with the C preprocessor, but I don't understand it completely. Right now, I have two header files, Move.h and Board.h that both typedef their respective type (Move and Board). In both header files, I need to reference the type defined in the other header file.
Right now I have #include "Move.h" in Board.h and #include "Board.h" in Move.h. When I compile though, gcc flips out and gives me a long (what looks like infinite recursive) error message flipping between Move.h and Board.h.
How do I include these files so that I'm not recursively including indefinitely?
You need to look into forward declarations, you have created an infinite loops of includes, forward declarations are the proper solution.
Here's an example:
Move.h
#ifndef MOVE_H_
#define MOVE_H_
struct board; /* forward declaration */
struct move {
struct board *m_board; /* note it's a pointer so the compiler doesn't
* need the full definition of struct board yet...
* make sure you set it to something!*/
};
#endif
Board.h
#ifndef BOARD_H_
#define BOARD_H_
#include "Move.h"
struct board {
struct move m_move; /* one of the two can be a full definition */
};
#endif
main.c
#include "Board.h"
int main() { ... }
Note: whenever you create a "Board", you will need to do something like this (there are a few ways, here's an example):
struct board *b = malloc(sizeof(struct board));
b->m_move.m_board = b; /* make the move's board point
* to the board it's associated with */
Include guards would be part of the solution to this issue.
Example from wikipedia:
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct foo {
int member;
};
#endif
http://en.wikipedia.org/wiki/Include_guard
The other part as noted by several others is forward referencing. (http://en.wikipedia.org/wiki/Forward_Reference)
You can partially declare one of the structures above the other one like so:
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct bar;
struct foo {
int member;
};
#endif
Like so:
//Board.h
#ifndef BOARD_H
#define BOARD_H
strunct move_t; //forward declaration
typedef struct move_t Move;
//...
#endif //BOARD_H
//Move.h
#ifndef MOVE_H
#define MOVE_H
#include "Move.h"
typedef struct board_t Board;
//...
#endif //MOVE_H
This way Board.h can be compiled without dependency on move.h and you can include board.h from move.h to make its content available there.
First, you seem to lack include guards in your .h files, so you're including them recursively. That is bad.
Second, you can do a forward declaration. In Move.h:
/* Include guard to make sure your header files are idempotent */
#ifndef H_MOVE_
#define H_MOVE_
#include "Board.h"
/* Now you can use struct Board */
struct Move { struct Board *board; };
#endif
In Board.h:
#ifndef H_BOARD_
#define H_BOARD_
struct Move; /* Forward declaration. YOu can use a pointer to
struct Move from now on, but the type itself is incomplete,
so you can't declare an object of the type itself. */
struct Board { struct Move *move; }; /* OK: since move is a pointer */
#endif
Note that if you need to declare struct Move and struct Board objects (rather than pointer to one of them) in both the files, this method won't work. This is because one of the types is an incomplete type at the time of parsing of one of the files (struct Move in the above example).
So, if you need to use the types in both the files, you will have to separate out the type definitions: have header files that define struct Move and struct Board, and nothing else (something like my example above), and then use another header file that references both struct Move and struct Board.
Of course, you can't have struct Move contain a struct Board and struct Board contain a struct Move at the same time—that will be infinite recursion, and the struct sizes will be infinite as well!
You need to have one of them first. Make a forward decl in one of them and have that one for for example
#ifndef move
struct move;
#endif
could be part of the board.h file.
and
#ifndef board
struct board;
#endif
could be part of the move.h file
then you could add them in either order.
edit
As was pointed out in the comments... I was assuming the use of the typedef construct as follows for the board struct
typedef struct {…} board;
since I've never seen anyone using structs in C without a typedef I made this assumption... maybe things have changed since the last time I coded in C (yikies.... it was like 15 years ago)
Circular dependencies are a pain in the ass and should be eliminated wherever feasible. In addition to the forward declaration suggestions given so far (Alok's is the best example), I'd like to throw another suggestion into the works: break the mutual dependency between Board and Move by introducing a third type (call it BoardMoveAssoc for illustration; I'm sure you can come up with a less sucky name):
#ifndef H_BOARD_MOVE_ASSOC
#define H_BOARD_MOVE_ASSOC
#include "Move.h"
#include "Board.h"
struct BoardMoveAssoc {
Move m;
Board b;
};
...
#endif
Under this scheme, Board and Move don't have to know anything about each other; any associations between the two are managed by the BoardMoveAssoc type. The exact structure will depend on how Move and Board are supposed to be related; e.g., if multiple moves are mapped to a single board, the structure may look more like
struct BoardMoveAssoc {
Move m[NUM_MOVES] // or Move *m;
Board b;
};
This way, you don't have to worry about forward declarations or incomplete types. You are introducing a third type into the mix, but I believe this will be easier to understand and maintain.
From K&R The C Programming Language (p 91 "Conditional Inclusion" in my copy), with some tweaks for you:
#if !defined (BOARD_H)
#define BOARD_H
/* contents of board.h go here */
#endif
and the same for Move.h
In this way, once a header has been included once, it will not be included again, as the 'BOARD_H' name has already been defined for the preprocessor.

Resources