1.函数功能
获取net->gen->ptr[id]数组中的指针,该指针指向各个模块储存在命名空间中的私有数据结构体,里面存放了各个模块的一些私有信息。
2.函数源码
文件路径:include/net/netns/generic.h
struct net_generic {
union {
struct {
unsigned int len;
struct rcu_head rcu;
} s;
DECLARE_FLEX_ARRAY(void *, ptr);
};
};
static inline void *net_generic(const struct net *net, unsigned int id)
{
struct net_generic *ng;
void *ptr;
rcu_read_lock();
ng = rcu_dereference(net->gen);
ptr = ng->ptr[id];
rcu_read_unlock();
return ptr;
}
3.函数分析
文件路径:include/net/net_namespace.h
struct net {
...
struct net_generic __rcu *gen;
...
}
文件路径:include/uapi/linux/stddef.h
/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */
#define __DECLARE_FLEX_ARRAY(T, member) \
T member[0]
文件路径:include/linux/stddef.h
#define DECLARE_FLEX_ARRAY(TYPE, NAME) \
__DECLARE_FLEX_ARRAY(TYPE, NAME)
文件路径:include/net/netns/generic.h
struct net_generic {
union {
struct {
unsigned int len;
struct rcu_head rcu;
} s;
//这里我理解为是一个指针数组 void* ptr[];
//在网络子系统中存储某个模块的私有数据
DECLARE_FLEX_ARRAY(void *, ptr);
};
};
static inline void *net_generic(const struct net *net, unsigned int id)
{
struct net_generic *ng;
void *ptr;
rcu_read_lock();
//将net结构体的gen成员传给ng
ng = rcu_dereference(net->gen);
//ng->ptr是一个void* ptr[];通过id获取对应的指针
ptr = ng->ptr[id];
rcu_read_unlock();
//返回某个模块在网络命名空间中存储的私有数据的指针
return ptr;
}
4.函数调用
文件路径:net/mptcp/ctrl.c
static int mptcp_pernet_id;
#ifdef CONFIG_SYSCTL
static int mptcp_pm_type_max = __MPTCP_PM_TYPE_MAX;
#endif
//mptcp存储到net命名空间的私有数据结构
struct mptcp_pernet {
#ifdef CONFIG_SYSCTL
struct ctl_table_header *ctl_table_hdr;
#endif
unsigned int add_addr_timeout;
unsigned int stale_loss_cnt;
u8 mptcp_enabled;
u8 checksum_enabled;
u8 allow_join_initial_addr_port;
u8 pm_type;
char scheduler[MPTCP_SCHED_NAME_MAX];
};
static struct mptcp_pernet *mptcp_get_pernet(const struct net *net)
{
//net_generic函数返回的是void *类型的指针
//这里通过类型转换在mptcp_get_pernet函数返回成mptcp存储到net命名空间的私有数据结构指针
return net_generic(net, mptcp_pernet_id);
}
//下面这些都是利用了mptcp_get_pernet函数获取到私有数据结构里的信息
int mptcp_is_enabled(const struct net *net)
{
return mptcp_get_pernet(net)->mptcp_enabled;
}
unsigned int mptcp_get_add_addr_timeout(const struct net *net)
{
return mptcp_get_pernet(net)->add_addr_timeout;
}
int mptcp_is_checksum_enabled(const struct net *net)
{
return mptcp_get_pernet(net)->checksum_enabled;
}
int mptcp_allow_join_id0(const struct net *net)
{
return mptcp_get_pernet(net)->allow_join_initial_addr_port;
}
(net, mptcp_pernet_id);
}
int mptcp_is_enabled(const struct net *net)
{
return mptcp_get_pernet(net)->mptcp_enabled;
}
unsigned int mptcp_get_add_addr_timeout(const struct net *net)
{
return mptcp_get_pernet(net)->add_addr_timeout;
}
int mptcp_is_checksum_enabled(const struct net *net)
{
return mptcp_get_pernet(net)->checksum_enabled;
}
int mptcp_allow_join_id0(const struct net *net)
{
return mptcp_get_pernet(net)->allow_join_initial_addr_port;
}