netlink接口

1、netlink及相关接口说明

        说到驱动和应用层进行数据通信,很多人就会想到使用传统的ioctl,诚然,很多时候应用层调用驱动进行参数配置和参数获取使用的也正是ioctl的方式,但这种方式有一种局限性,那就是只适合于数据量较小且操作不频繁的情况。否则,频繁操作io将大大影响设备的性能,甚至造成设备宕机。

        最近在做一个关于wifi诊断需求时,需要记录wifi连接过程中的控制帧和管理帧,以及STA断开及断开原因。由于wifi驱动不断在进行数据帧和控制帧的交互,如果直接在驱动中操作io写文件,wifi性能将收到很大影响。后来相到了使用netlink进行数据传输,将数据传输到应用层进行log的记录。

        下面简单介绍下linux下netlink相关的接口,由于我使用的内核版本是linux-lsk-v4.1.25,接口主要介绍该版本接口,代码实例中会进行版本兼容,需要连接其他版本的请自行跟读相关版本源码。

1.1、netlink_kernel_create接口

 H Code \kernel-4.14\include\linux\netlink.h

1
2
3
4
5

static inline struct sock *
netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
{
    return __netlink_kernel_create(net, unit, THIS_MODULE, cfg);
}

__netlink_kernel_create的实现在/kernel-4.14/net/netlink/af_netlink.c

netlink_kernel_create接口的返回值是一个socket描述符,类似于socket编程中返回的socket,主要用于msg 发送时的参入参数,便于与应用层套接字接口建立连接。

struct sock定义在/kernel-4.14/include/net/sock.h

第一个参数(struct net *)是一个网络的namespace,在不同的名字空间里面可以有自己的转发信息库,有自己的一套net_device等等,默认情况下都是使用init_net这个全局变量。

第二个参数(int unit)实际上是当前使用的协议号,由于Netlink本身是linux的一个部分,linux内核中的很多和应用层的交互也使用过netlink(比如防火墙iptables)。

                                 目前部分协议号(0~22)实际已经被占用,我们只能从之后的协议号中挑选,否则将造成协议冲突。

 H Code \kernel-4.14\include\uapi\linux\netlink.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#define NETLINK_ROUTE       0   /* Routing/device hook              */
#define NETLINK_UNUSED      1   /* Unused number                */
#define NETLINK_USERSOCK    2   /* Reserved for user mode socket protocols  */
#define NETLINK_FIREWALL    3   /* Unused number, formerly ip_queue     */
#define NETLINK_SOCK_DIAG   4   /* socket monitoring                */
#define NETLINK_NFLOG       5   /* netfilter/iptables ULOG */
#define NETLINK_XFRM        6   /* ipsec */
#define NETLINK_SELINUX     7   /* SELinux event notifications */
#define NETLINK_ISCSI       8   /* Open-iSCSI */
#define NETLINK_AUDIT       9   /* auditing */
#define NETLINK_FIB_LOOKUP  10
#define NETLINK_CONNECTOR   11
#define NETLINK_NETFILTER   12  /* netfilter subsystem */
#define NETLINK_IP6_FW      13
#define NETLINK_DNRTMSG     14  /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT  15  /* Kernel messages to userspace */
#define NETLINK_GENERIC     16
/* leave room for NETLINK_DM (DM Events) */
#define NETLINK_SCSITRANSPORT   18  /* SCSI Transports */
#define NETLINK_ECRYPTFS    19
#define NETLINK_RDMA        20
#define NETLINK_CRYPTO      21  /* Crypto layer */
#define NETLINK_SMC     22  /* SMC monitoring */

#define NETLINK_INET_DIAG   NETLINK_SOCK_DIAG

#define MAX_LINKS 32

struct sockaddr_nl {
    __kernel_sa_family_t    nl_family;  /* AF_NETLINK   */
    unsigned short  nl_pad;     /* zero     */
    __u32       nl_pid;     /* port ID  */
        __u32       nl_groups;  /* multicast groups mask */
};

struct nlmsghdr {
    __u32       nlmsg_len;  /* Length of message including header */
    __u16       nlmsg_type; /* Message content */
    __u16       nlmsg_flags;    /* Additional flags */
    __u32       nlmsg_seq;  /* Sequence number */
    __u32       nlmsg_pid;  /* Sending process port ID */
};

第三个参数(struct netlink_kernel_cfg *cfg)是关于netlink的相关参数的封装,之前的版本中该结构体实际上是分成好几个参数实现的,具体见之后的实例。该结构体如下,我们主要关注其中注释部分。

 H Code \kernel-4.14\include\linux\netlink.h

1
2
3
4
5
6
7
8
9
10

/* optional Netlink kernel configuration parameters */
struct netlink_kernel_cfg {
    unsigned int    groups;  //多播组,一般多播的时候设置成1,单播设置成0
    unsigned int    flags;
    void        (*input)(struct sk_buff *skb);  //回调函数,内核收到应用层发过来的msg时会调用此函数
    struct mutex    *cb_mutex;
    int     (*bind)(struct net *net, int group);
    void        (*unbind)(struct net *net, int group);
    bool        (*compare)(struct net *net, struct sock *sk);
};

struct sk_buff 定义在/kernel-4.14/include/linux/skbuff.h

1.2、netlink_unicast接口

extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock);

ssk:    sock结构体指针,netlink_kernel_create返回的套接字描述符

skb:    skb存放消息,它的data字段指向要发送的 netlink消息结构,而skb的控制块保存了消息的地址信息,前面的宏NETLINK_CB(skb)就用于方便设置该控制块

portid: 端口id,与应用层对应,一般是应用层对应的进程的进程pid

nonblock:表示该函数是否为非阻塞,如果为1,该函数将在没有接收缓存可利用时立即返回,而如果为0,该函数在没有接收缓存可利 用时睡眠

1.3、netlink_broadcast接口

extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 portid, __u32 group, gfp_t allocation);

ssk:    sock结构体指针,netlink_kernel_create返回的套接字描述符

skb:    skb存放消息,它的data字段指向要发送的 netlink消息结构,而skb的控制块保存了消息的地址信息,前面的宏NETLINK_CB(skb)就用于方便设置该控制块

portid: 端口id,一般是应用层对应的进程的进程pid

group:  netlink多播组

allocation: 内核内存分配类型,一般地为GFP_ATOMIC或 GFP_KERNEL,GFP_ATOMIC用于原子的上下文(即不可以睡眠),而GFP_KERNEL用于非原子上下文

返回: 发送数据的长度

注:由于协议号需要调用netlink_kernel_create后方可注册到内核,因此使用时应提供机制保证驱动在应用层之前先启动

      否则会出现报错:当前协议不支持。

==========================================================================================

协议族:

 H Code /kernel-4.14/include/linux/socket.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

/* Supported address families. */
#define AF_UNSPEC   0
#define AF_UNIX     1   /* Unix domain sockets      */
#define AF_LOCAL    1   /* POSIX name for AF_UNIX   */
#define AF_INET     2   /* Internet IP Protocol     */
#define AF_AX25     3   /* Amateur Radio AX.25      */
#define AF_IPX      4   /* Novell IPX           */
#define AF_APPLETALK    5   /* AppleTalk DDP        */
#define AF_NETROM   6   /* Amateur Radio NET/ROM    */
#define AF_BRIDGE   7   /* Multiprotocol bridge     */
#define AF_ATMPVC   8   /* ATM PVCs         */
#define AF_X25      9   /* Reserved for X.25 project    */
#define AF_INET6    10  /* IP version 6         */
#define AF_ROSE     11  /* Amateur Radio X.25 PLP   */
#define AF_DECnet   12  /* Reserved for DECnet project  */
#define AF_NETBEUI  13  /* Reserved for 802.2LLC project*/
#define AF_SECURITY 14  /* Security callback pseudo AF */
#define AF_KEY      15      /* PF_KEY key management API */
#define AF_NETLINK  16
#define AF_ROUTE    AF_NETLINK /* Alias to emulate 4.4BSD */
#define AF_PACKET   17  /* Packet family        */
#define AF_ASH      18  /* Ash              */
#define AF_ECONET   19  /* Acorn Econet         */
#define AF_ATMSVC   20  /* ATM SVCs         */
#define AF_RDS      21  /* RDS sockets          */
#define AF_SNA      22  /* Linux SNA Project (nutters!) */
#define AF_IRDA     23  /* IRDA sockets         */
#define AF_PPPOX    24  /* PPPoX sockets        */
#define AF_WANPIPE  25  /* Wanpipe API Sockets */
#define AF_LLC      26  /* Linux LLC            */
#define AF_IB       27  /* Native InfiniBand address    */
#define AF_MPLS     28  /* MPLS */
#define AF_CAN      29  /* Controller Area Network      */
#define AF_TIPC     30  /* TIPC sockets         */
#define AF_BLUETOOTH    31  /* Bluetooth sockets        */
#define AF_IUCV     32  /* IUCV sockets         */
#define AF_RXRPC    33  /* RxRPC sockets        */
#define AF_ISDN     34  /* mISDN sockets        */
#define AF_PHONET   35  /* Phonet sockets       */
#define AF_IEEE802154   36  /* IEEE802154 sockets       */
#define AF_CAIF     37  /* CAIF sockets         */
#define AF_ALG      38  /* Algorithm sockets        */
#define AF_NFC      39  /* NFC sockets          */
#define AF_VSOCK    40  /* vSockets         */
#define AF_KCM      41  /* Kernel Connection Multiplexor*/
#define AF_QIPCRTR  42  /* Qualcomm IPC Router          */
#define AF_SMC      43  /* smc sockets: reserve number for
                 * PF_SMC protocol family that
                 * reuses AF_INET address family
                 */

#define AF_MAX      44  /* For now.. */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值