Commit 9a8083d1 authored by Yizhen Fan's avatar Yizhen Fan Committed by fanyizhen1995
Browse files

ub: ubcore add tp request and response handle in netlink



driver inclusion
category: feature
bugzilla: NA
CVE: NA

--------------------------------

Ubcore add tp request and response handle in netlink.

It's possible to handle tp creation/deletion/restore request from user
layer.

Signed-off-by: default avatarGuoxin Qian <qianguoxin@huawei.com>
Signed-off-by: default avatarYizhen Fan <fanyizhen@huawei.com>
parent fd5b4070
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/netlink.h>
#include <linux/list.h>
#include "ubcore_log.h"
#include "ubcore_tp.h"
#include "ubcore_netlink.h"

#define UBCORE_NL_TYPE 24 /* same with agent netlink type */
@@ -76,6 +77,85 @@ static inline void ubcore_destroy_nl_session(struct ubcore_nl_session *s)
	kref_put(&s->kref, ubcore_free_nl_session);
}

static struct ubcore_nl_session *ubcore_find_nl_session(uint32_t nlmsg_seq)
{
	struct ubcore_nl_session *tmp, *target = NULL;
	unsigned long flags;

	spin_lock_irqsave(&g_nl_session_lock, flags);
	list_for_each_entry(tmp, &g_nl_session_list, node) {
		if (tmp->req->nlmsg_seq == nlmsg_seq) {
			target = tmp;
			kref_get(&target->kref);
			break;
		}
	}
	spin_unlock_irqrestore(&g_nl_session_lock, flags);
	return target;
}

static struct ubcore_nlmsg *ubcore_get_nlmsg_data(struct nlmsghdr *nlh)
{
	struct ubcore_nlmsg *msg;

	msg = kzalloc(nlmsg_len(nlh), GFP_KERNEL);
	if (msg == NULL)
		return NULL;

	(void)memcpy(msg, nlmsg_data(nlh), nlmsg_len(nlh));
	return msg;
}

static void ubcore_nl_handle_tp_resp(struct nlmsghdr *nlh)
{
	struct ubcore_nl_session *s;
	struct ubcore_nlmsg *resp;

	resp = ubcore_get_nlmsg_data(nlh);
	if (resp == NULL) {
		ubcore_log_err("Failed to calloc and copy response");
		return;
	}
	s = ubcore_find_nl_session(resp->nlmsg_seq);
	if (s == NULL) {
		ubcore_log_err("Failed to find nl session with seq %u", resp->nlmsg_seq);
		kfree(resp);
		return;
	}
	s->resp = resp;
	kref_put(&s->kref, ubcore_free_nl_session);
	complete(&s->comp);
}

static void ubcore_nl_handle_tp_req(struct nlmsghdr *nlh)
{
	struct ubcore_nlmsg *resp = NULL;
	struct ubcore_nlmsg *req;

	req = ubcore_get_nlmsg_data(nlh);
	if (req == NULL) {
		ubcore_log_err("Failed to calloc and copy req");
		return;
	}
	if (nlh->nlmsg_type == UBCORE_NL_CREATE_TP_REQ)
		resp = ubcore_handle_create_tp_req(req);
	else if (nlh->nlmsg_type == UBCORE_NL_DESTROY_TP_REQ)
		resp = ubcore_handle_destroy_tp_req(req);
	else if (nlh->nlmsg_type == UBCORE_NL_RESTORE_TP_REQ)
		resp = ubcore_handle_restore_tp_req(req);

	if (resp == NULL) {
		ubcore_log_err("Failed to handle tp req");
		kfree(req);
		return;
	}
	if (ubcore_nl_send(resp, ubcore_nlmsg_len(resp)) != 0)
		ubcore_log_err("Failed to send response");

	kfree(req);
	kfree(resp);
}

static void ubcore_nl_cb_func(struct sk_buff *skb)
{
	struct nlmsghdr *nlh;
@@ -87,9 +167,21 @@ static void ubcore_nl_cb_func(struct sk_buff *skb)
	}

	switch (nlh->nlmsg_type) {
	case UBCORE_NL_CREATE_TP_REQ:
	case UBCORE_NL_DESTROY_TP_REQ:
	case UBCORE_NL_RESTORE_TP_REQ:
		ubcore_nl_handle_tp_req(nlh);
		break;
	case UBCORE_NL_CREATE_TP_RESP:
	case UBCORE_NL_DESTROY_TP_RESP:
	case UBCORE_NL_QUERY_TP_RESP:
	case UBCORE_NL_RESTORE_TP_RESP:
		ubcore_nl_handle_tp_resp(nlh);
		break;
	case UBCORE_NL_SET_AGENT_PID:
		g_agent_port = nlh->nlmsg_pid;
		break;
	case UBCORE_NL_QUERY_TP_REQ:
	default:
		ubcore_log_err("Unexpected nl msg type: %d received\n", nlh->nlmsg_type);
		break;