luckfox-pico-sdk/sysdrv/drv_ko/wifi/hichannel/wal/wal_netlink.c
2023-08-08 20:36:47 +08:00

172 lines
4.9 KiB
C

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: ioctl implementatioin.
* Author: Hisilicon
* Create: 2020-09-28
*/
/*****************************************************************************
1 头文件包含
*****************************************************************************/
#include <linux/netlink.h>
#include <net/sock.h>
#include "wal_netlink.h"
#include "securec.h"
#include "oal_net.h"
#include "oal_netbuf.h"
#include "hcc_host.h"
#include "hcc_comm.h"
#include "hcc_adapt.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
/*****************************************************************************
2 枚举、结构体定义
*****************************************************************************/
typedef struct {
struct sock *netlink_sk;
hi_u32 user_pid;
}netlink_user_s;
static hi_void oal_recieve_user_msg(struct sk_buff *skb);
/*****************************************************************************
3 宏定义、全局变量
*****************************************************************************/
#define NETLINK_CHANNEL_MODEID 28
#undef NLMSG_ALIGNTO
#define NLMSG_ALIGNTO 1
static struct netlink_kernel_cfg cfg = {
.input = oal_recieve_user_msg,
};
static netlink_user_s g_netlink_user;
/*****************************************************************************
4 函数实现
*****************************************************************************/
hi_s32 oal_send_user_msg(hi_u8 *pbuf, hi_u32 len)
{
struct sk_buff *nl_skb = HI_NULL;
struct nlmsghdr *nlh = HI_NULL;
if (g_netlink_user.netlink_sk == HI_NULL) {
return HI_FAILURE;
}
if ((pbuf == HI_NULL) || (len == 0) || (len > MAX_USER_LONG_DATA_LEN)) {
oam_error_log1("send_usrmsg is fail:len:%d\n", len);
return HI_FAILURE;
}
/* 创建sk_buff 空间 */
nl_skb = nlmsg_new(len, GFP_ATOMIC);
if (nl_skb == HI_NULL) {
oam_error_log0("nlmsg_new is fail.\n");
return HI_FAILURE;
}
/* 设置netlink消息头部 */
nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_CHANNEL_MODEID, len, 0);
if (nlh == HI_NULL) {
oam_error_log0("nlmsg_put is fail.\n");
nlmsg_free(nl_skb);
return HI_FAILURE;
}
/* 拷贝数据发送 */
(hi_void)memcpy_s(nlmsg_data(nlh), nlmsg_len(nlh), pbuf, len);
hi_s32 ret = netlink_unicast(g_netlink_user.netlink_sk, nl_skb, g_netlink_user.user_pid, MSG_DONTWAIT);
if (ret == -1) {
oam_error_log0("netlink_unicast is fail.\n");
nlmsg_free(nl_skb);
return HI_FAILURE;
}
return HI_SUCCESS;
}
static hi_void oal_recieve_user_msg(struct sk_buff *skb)
{
hi_u32 payload_len;
hi_char *umsg = HI_NULL;
struct nlmsghdr *nlh = HI_NULL;
oal_netbuf_stru *netbuf = HI_NULL;
if (skb == HI_NULL) {
return;
}
if (skb->len <= nlmsg_total_size(0)) {
oam_warning_log2("oal_netlink_deinit is success\n", skb->len, nlmsg_total_size(0));
return;
}
nlh = nlmsg_hdr(skb);
umsg = NLMSG_DATA(nlh);
payload_len = nlh->nlmsg_len - NLMSG_HDRLEN; /* header len is nlmsg_total_size */
g_netlink_user.user_pid = nlh->nlmsg_pid;
if (payload_len > MAX_USER_LONG_DATA_LEN) {
oam_error_log1("payload len[%d] is fail\n", payload_len);
return;
}
hcc_type_enum type = (payload_len > MAX_USER_DATA_LEN) ? HCC_TYPE_DATA : HCC_TYPE_MSG;
netbuf = (oal_netbuf_stru *)oal_netbuf_alloc(payload_len, 0, 0);
if (netbuf == HI_NULL) {
oam_error_log0("oal_netbuf_alloc is fail\n");
return;
}
(hi_void)memcpy_s(oal_netbuf_data(netbuf), payload_len, umsg, payload_len);
oal_netbuf_len(netbuf) = payload_len;
oal_netbuf_next(netbuf) = HI_NULL;
oal_netbuf_prev(netbuf) = HI_NULL;
if (hcc_tx_data_adapt(netbuf, type, HCC_SUB_TYPE_USER_MSG) != HI_SUCCESS) {
oam_error_log0("hcc_tx_data_adapt is fail\n");
oal_netbuf_free(netbuf);
}
}
hi_s32 oal_netlink_init(hi_void)
{
if (g_netlink_user.netlink_sk != HI_NULL) {
oam_error_log0("oal_netlink_init is fail\n");
return HI_FAILURE;
}
/* create netlink socket */
g_netlink_user.netlink_sk = (struct sock *)netlink_kernel_create(&init_net, NETLINK_CHANNEL_MODEID, &cfg);
if (g_netlink_user.netlink_sk == HI_NULL) {
oam_error_log0("netlink_kernel_create is fail\n");
return HI_FAILURE;
}
oam_warning_log0("oal_netlink_init is success\n");
return HI_SUCCESS;
}
hi_s32 oal_netlink_deinit(hi_void)
{
if (g_netlink_user.netlink_sk == HI_NULL) {
printk("oal_netlink_deinit is fail\n");
return HI_FAILURE;
}
netlink_kernel_release(g_netlink_user.netlink_sk); /* release. */
g_netlink_user.netlink_sk = HI_NULL;
g_netlink_user.user_pid = 0;
oam_warning_log0("oal_netlink_deinit is success\n");
return HI_SUCCESS;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif