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.. */ |