Search Linux Wireless

Re: [PATCH] nl80211: add testmode dump support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For testing, I used the attached patch to hwsim, and the attached
hwsim.c file as an iw module (add hwsim.o to iw's Makefile and
recompile).

As the code is nonsensical I don't want to commit it.

johannes
---
 drivers/net/wireless/mac80211_hwsim.c |   56 ++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

--- a/drivers/net/wireless/mac80211_hwsim.c	2011-05-20 09:06:12.000000000 -0700
+++ b/drivers/net/wireless/mac80211_hwsim.c	2011-05-20 09:06:15.000000000 -0700
@@ -882,6 +882,7 @@ enum hwsim_testmode_attr {
 	__HWSIM_TM_ATTR_INVALID	= 0,
 	HWSIM_TM_ATTR_CMD	= 1,
 	HWSIM_TM_ATTR_PS	= 2,
+	HWSIM_TM_ATTR_DUMP	= 3,
 
 	/* keep last */
 	__HWSIM_TM_ATTR_AFTER_LAST,
@@ -891,6 +892,8 @@ enum hwsim_testmode_attr {
 enum hwsim_testmode_cmd {
 	HWSIM_TM_CMD_SET_PS		= 0,
 	HWSIM_TM_CMD_GET_PS		= 1,
+	HWSIM_TM_CMD_DUMP1		= 2,
+	HWSIM_TM_CMD_DUMP2		= 3,
 };
 
 static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = {
@@ -937,6 +940,58 @@ static int mac80211_hwsim_testmode_cmd(s
 	kfree_skb(skb);
 	return -ENOBUFS;
 }
+
+static int mac80211_hwsim_testmode_dump(struct ieee80211_hw *hw,
+					struct sk_buff *skb,
+					struct netlink_callback *cb,
+					void *data, int len)
+{
+	struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
+	int err, idx;
+	u32 cmd;
+
+	if (!data || !len)
+		return -EINVAL;
+
+	/*
+	 * Setup code -- get the type of command we want to do
+	 */
+	if (cb->args[2]) {
+		/* offset by 1 since commands start at 0 */
+		cmd = cb->args[2] - 1;
+	} else {
+		err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len,
+				hwsim_testmode_policy);
+		if (err)
+			return err;
+		if (!tb[HWSIM_TM_ATTR_CMD])
+			return -EINVAL;
+		cmd = nla_get_u32(tb[HWSIM_TM_ATTR_CMD]);
+		switch (cmd) {
+		case HWSIM_TM_CMD_DUMP1:
+		case HWSIM_TM_CMD_DUMP2:
+			break;
+		default:
+			return -EINVAL;
+		}
+		/* offset by 1 since commands start at 0 */
+		cb->args[2] = cmd + 1;
+	}
+
+	/* Deal with the command */
+	idx = cb->args[3];
+	if (cmd == HWSIM_TM_CMD_DUMP1 && idx >= 5)
+		return -ENOENT;
+	if (cmd == HWSIM_TM_CMD_DUMP2 && idx >= 10)
+		return -ENOENT;
+	NLA_PUT_U32(skb, HWSIM_TM_ATTR_DUMP, idx * 10);
+	idx++;
+	cb->args[3] = idx;
+
+	return 0;
+ nla_put_failure:
+	return -ENOBUFS;
+}
 #endif
 
 static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
@@ -1059,6 +1114,7 @@ static struct ieee80211_ops mac80211_hws
 	.conf_tx = mac80211_hwsim_conf_tx,
 	.get_survey = mac80211_hwsim_get_survey,
 	CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
+	CFG80211_TESTMODE_DUMP(mac80211_hwsim_testmode_dump)
 	.ampdu_action = mac80211_hwsim_ampdu_action,
 	.sw_scan_start = mac80211_hwsim_sw_scan,
 	.sw_scan_complete = mac80211_hwsim_sw_scan_complete,
#include <net/if.h>
#include <errno.h>
#include <string.h>

#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/msg.h>
#include <netlink/attr.h>

#include "nl80211.h"
#include "iw.h"

/* These enums need to be kept in sync with the kernel */
enum hwsim_testmode_attr {
	__HWSIM_TM_ATTR_INVALID	= 0,
	HWSIM_TM_ATTR_CMD	= 1,
	HWSIM_TM_ATTR_PS	= 2,
	HWSIM_TM_ATTR_DUMP	= 3,

	/* keep last */
	__HWSIM_TM_ATTR_AFTER_LAST,
	HWSIM_TM_ATTR_MAX	= __HWSIM_TM_ATTR_AFTER_LAST - 1
};

enum hwsim_testmode_cmd {
	HWSIM_TM_CMD_SET_PS		= 0,
	HWSIM_TM_CMD_GET_PS		= 1,
	HWSIM_TM_CMD_DUMP1		= 2,
	HWSIM_TM_CMD_DUMP2		= 3,
};


SECTION(hwsim);

static int print_hwsim_ps_handler(struct nl_msg *msg, void *arg)
{
	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
	struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));

	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (!attrs[NL80211_ATTR_TESTDATA])
		return NL_SKIP;

	nla_parse(tb, HWSIM_TM_ATTR_MAX, nla_data(attrs[NL80211_ATTR_TESTDATA]),
		  nla_len(attrs[NL80211_ATTR_TESTDATA]), NULL);

	printf("HWSIM PS: %d\n", nla_get_u32(tb[HWSIM_TM_ATTR_PS]));

	return NL_SKIP;
}

static int handle_hwsim_getps(struct nl80211_state *state, struct nl_cb *cb,
			      struct nl_msg *msg, int argc, char **argv)
{
	struct nlattr *tmdata;

	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
	if (!tmdata)
		goto nla_put_failure;

	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_GET_PS);

	nla_nest_end(msg, tmdata);

	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
		  print_hwsim_ps_handler, NULL);
	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(hwsim, getps, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_getps, "");

static int handle_hwsim_setps(struct nl80211_state *state, struct nl_cb *cb,
			      struct nl_msg *msg, int argc, char **argv)
{
	struct nlattr *tmdata;
	__u32 ps;
	char *end;

	if (argc != 1)
		return 1;

	ps = strtoul(argv[0], &end, 0);
	if (*end)
		return 1;

	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
	if (!tmdata)
		goto nla_put_failure;

	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_SET_PS);
	NLA_PUT_U32(msg, HWSIM_TM_ATTR_PS, ps);

	nla_nest_end(msg, tmdata);

	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
		  print_hwsim_ps_handler, NULL);
	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(hwsim, setps, "<value>", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_setps, "");

static int print_hwsim_dump_handler(struct nl_msg *msg, void *arg)
{
	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
	struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));

	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (!attrs[NL80211_ATTR_TESTDATA])
		return NL_SKIP;

	nla_parse(tb, HWSIM_TM_ATTR_MAX, nla_data(attrs[NL80211_ATTR_TESTDATA]),
		  nla_len(attrs[NL80211_ATTR_TESTDATA]), NULL);

	printf("HWSIM dump data: %d\n", nla_get_u32(tb[HWSIM_TM_ATTR_DUMP]));

	return NL_SKIP;
}

static int handle_hwsim_dump1(struct nl80211_state *state, struct nl_cb *cb,
			      struct nl_msg *msg, int argc, char **argv)
{
	struct nlattr *tmdata;

	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
	if (!tmdata)
		goto nla_put_failure;

	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_DUMP1);

	nla_nest_end(msg, tmdata);

	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
		  print_hwsim_dump_handler, NULL);
	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(hwsim, dump1, "", NL80211_CMD_TESTMODE, NLM_F_DUMP, CIB_PHY, handle_hwsim_dump1, "");

static int handle_hwsim_dump2(struct nl80211_state *state, struct nl_cb *cb,
			      struct nl_msg *msg, int argc, char **argv)
{
	struct nlattr *tmdata;

	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
	if (!tmdata)
		goto nla_put_failure;

	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_DUMP2);

	nla_nest_end(msg, tmdata);

	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
		  print_hwsim_dump_handler, NULL);
	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(hwsim, dump2, "", NL80211_CMD_TESTMODE, NLM_F_DUMP, CIB_PHY, handle_hwsim_dump2, "");

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux