From f0166e5e3cdab66d5a31f796ce18e21fd3ce99dc Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 23 Jul 2009 16:56:29 +0400 Subject: ieee802154: move headers out of extra directory include/net/ieee802154/af_ieee802154.h (and others) naming seems to be too long and redundant. Drop one level of subdirectories. Signed-off-by: Dmitry Eremin-Solenikov --- net/ieee802154/netlink.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/ieee802154/netlink.c') diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 27eda9fdf3c..a615b9d1321 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -27,9 +27,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include static unsigned int ieee802154_seq_num; -- cgit v1.2.3-70-g09d2 From 8e753dd0a82bd266256c20a20b98dfa48f98d21e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Aug 2009 02:58:40 +0000 Subject: nl802154: add support for dumping WPAN interface information Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: David S. Miller --- include/linux/nl802154.h | 2 + net/ieee802154/netlink.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 2 deletions(-) (limited to 'net/ieee802154/netlink.c') diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h index 266dd96ced9..9a1af5f871a 100644 --- a/include/linux/nl802154.h +++ b/include/linux/nl802154.h @@ -111,6 +111,8 @@ enum { IEEE802154_RX_ENABLE_REQ, /* Not supported yet */ IEEE802154_RX_ENABLE_CONF, /* Not supported yet */ + IEEE802154_LIST_IFACE, + __IEEE802154_CMD_MAX, }; diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index a615b9d1321..3fe02b394ad 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -19,6 +19,7 @@ * Written by: * Sergey Lapin * Dmitry Eremin-Solenikov + * Maxim Osipov */ #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -73,7 +75,7 @@ static int ieee802154_nl_finish(struct sk_buff *msg) /* XXX: nlh is right at the start of msg */ void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); - if (!genlmsg_end(msg, hdr)) + if (genlmsg_end(msg, hdr) < 0) goto out; return genlmsg_multicast(msg, 0, ieee802154_coord_mcgrp.id, @@ -260,6 +262,35 @@ nla_put_failure: } EXPORT_SYMBOL(ieee802154_nl_scan_confirm); +static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid, + u32 seq, int flags, struct net_device *dev) +{ + void *hdr; + + pr_debug("%s\n", __func__); + + hdr = genlmsg_put(msg, 0, seq, &ieee802154_coordinator_family, flags, + IEEE802154_LIST_IFACE); + if (!hdr) + goto out; + + NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); + NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); + + NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr); + NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, + ieee802154_mlme_ops(dev)->get_short_addr(dev)); + NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID, + ieee802154_mlme_ops(dev)->get_pan_id(dev)); + return genlmsg_end(msg, hdr); + +nla_put_failure: + genlmsg_cancel(msg, hdr); +out: + return -EMSGSIZE; +} + /* Requests from userspace */ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) { @@ -272,7 +303,7 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) dev = dev_get_by_name(&init_net, name); } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) dev = dev_get_by_index(&init_net, - nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX])); + nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX])); else return NULL; @@ -466,6 +497,67 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) return ret; } +static int ieee802154_list_iface(struct sk_buff *skb, + struct genl_info *info) +{ + /* Request for interface name, index, type, IEEE address, + PAN Id, short address */ + struct sk_buff *msg; + struct net_device *dev = NULL; + int rc = -ENOBUFS; + + pr_debug("%s\n", __func__); + + dev = ieee802154_nl_get_dev(info); + if (!dev) + return -ENODEV; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + goto out_dev; + + rc = ieee802154_nl_fill_iface(msg, info->snd_pid, info->snd_seq, + 0, dev); + if (rc < 0) + goto out_free; + + dev_put(dev); + + return genlmsg_unicast(&init_net, msg, info->snd_pid); +out_free: + nlmsg_free(msg); +out_dev: + dev_put(dev); + return rc; + +} + +static int ieee802154_dump_iface(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct net *net = sock_net(skb->sk); + struct net_device *dev; + int idx; + int s_idx = cb->args[0]; + + pr_debug("%s\n", __func__); + + idx = 0; + for_each_netdev(net, dev) { + if (idx < s_idx || (dev->type != ARPHRD_IEEE802154)) + goto cont; + + if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0) + break; +cont: + idx++; + } + cb->args[0] = idx; + + return skb->len; +} + #define IEEE802154_OP(_cmd, _func) \ { \ .cmd = _cmd, \ @@ -475,12 +567,22 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) .flags = GENL_ADMIN_PERM, \ } +#define IEEE802154_DUMP(_cmd, _func, _dump) \ + { \ + .cmd = _cmd, \ + .policy = ieee802154_policy, \ + .doit = _func, \ + .dumpit = _dump, \ + } + static struct genl_ops ieee802154_coordinator_ops[] = { IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req), IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req), IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), + IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, + ieee802154_dump_iface), }; static int __init ieee802154_nl_init(void) -- cgit v1.2.3-70-g09d2 From acb8aacda3f0bc3aeb652f4365c078a2b0adb0bf Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Aug 2009 02:58:44 +0000 Subject: nl802154: support START-CONFIRM primitive Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: David S. Miller --- include/net/nl802154.h | 9 +++++++++ net/ieee802154/netlink.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'net/ieee802154/netlink.c') diff --git a/include/net/nl802154.h b/include/net/nl802154.h index 6096096f6d7..e554ecd3727 100644 --- a/include/net/nl802154.h +++ b/include/net/nl802154.h @@ -114,4 +114,13 @@ int ieee802154_nl_scan_confirm(struct net_device *dev, int ieee802154_nl_beacon_indic(struct net_device *dev, u16 panid, u16 coord_addr); +/** + * ieee802154_nl_start_confirm - Notify userland of completion of start. + * @dev: The device which was instructed to scan. + * @status: The status of the scan operation. + * + * Note: This is in section 7.1.14 of the IEEE 802.15.4 document. + */ +int ieee802154_nl_start_confirm(struct net_device *dev, u8 status); + #endif diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 3fe02b394ad..cd0567f0671 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -31,6 +31,7 @@ #include #include #include +#include #include static unsigned int ieee802154_seq_num; @@ -262,6 +263,31 @@ nla_put_failure: } EXPORT_SYMBOL(ieee802154_nl_scan_confirm); +int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) +{ + struct sk_buff *msg; + + pr_debug("%s\n", __func__); + + msg = ieee802154_nl_create(0, IEEE802154_START_CONF); + if (!msg) + return -ENOBUFS; + + NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); + NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); + NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, + dev->dev_addr); + + NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); + + return ieee802154_nl_finish(msg); + +nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(ieee802154_nl_start_confirm); + static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct net_device *dev) { @@ -462,6 +488,12 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]); coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]); + if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { + ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); + dev_put(dev); + return -EINVAL; + } + ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, bcn_ord, sf_ord, pan_coord, blx, coord_realign); -- cgit v1.2.3-70-g09d2 From 16eea493da563b5a3356a77c6d8776dffc29d3b6 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Wed, 19 Aug 2009 19:32:24 +0400 Subject: ieee802154: add support for channel pages from IEEE 802.15.4-2006 IEEE 802.15.4-2006 adds new concept: channel pages, which can contain several channels. Add support for channel pages in the API and in the fakehard driver. Signed-off-by: Dmitry Eremin-Solenikov --- drivers/ieee802154/fakehard.c | 10 ++++++---- include/linux/nl802154.h | 2 ++ include/net/ieee802154_netdev.h | 6 +++--- include/net/nl802154.h | 2 +- net/ieee802154/netlink.c | 28 +++++++++++++++++++++++++--- net/ieee802154/nl_policy.c | 1 + 6 files changed, 38 insertions(+), 11 deletions(-) (limited to 'net/ieee802154/netlink.c') diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c index 22a93bc764c..c1c9697f9fd 100644 --- a/drivers/ieee802154/fakehard.c +++ b/drivers/ieee802154/fakehard.c @@ -119,12 +119,13 @@ static u8 fake_get_bsn(struct net_device *dev) * 802.15.4-2006 document. */ static int fake_assoc_req(struct net_device *dev, - struct ieee802154_addr *addr, u8 channel, u8 cap) + struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap) { struct wpan_phy *phy = net_to_phy(dev); mutex_lock(&phy->pib_lock); phy->current_channel = channel; + phy->current_page = page; mutex_unlock(&phy->pib_lock); /* We simply emulate it here */ @@ -191,7 +192,7 @@ static int fake_disassoc_req(struct net_device *dev, * document, with 7.3.8 describing coordinator realignment. */ static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr, - u8 channel, + u8 channel, u8 page, u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx, u8 coord_realign) { @@ -199,6 +200,7 @@ static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr, mutex_lock(&phy->pib_lock); phy->current_channel = channel; + phy->current_page = page; mutex_unlock(&phy->pib_lock); /* We don't emulate beacons here at all, so START should fail */ @@ -222,11 +224,11 @@ static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr, * Note: This is in section 7.5.2.1 of the IEEE 802.15.4-2006 document. */ static int fake_scan_req(struct net_device *dev, u8 type, u32 channels, - u8 duration) + u8 page, u8 duration) { u8 edl[27] = {}; return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type, - channels, + channels, page, type == IEEE802154_MAC_SCAN_ED ? edl : NULL); } diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h index 9a1af5f871a..b7d9435d5a9 100644 --- a/include/linux/nl802154.h +++ b/include/linux/nl802154.h @@ -64,6 +64,8 @@ enum { IEEE802154_ATTR_COORD_REALIGN, IEEE802154_ATTR_SEC, + IEEE802154_ATTR_PAGE, + __IEEE802154_ATTR_MAX, }; diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index e2506af3e7c..5dc6a61952d 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h @@ -80,7 +80,7 @@ static inline int mac_cb_type(struct sk_buff *skb) struct ieee802154_mlme_ops { int (*assoc_req)(struct net_device *dev, struct ieee802154_addr *addr, - u8 channel, u8 cap); + u8 channel, u8 page, u8 cap); int (*assoc_resp)(struct net_device *dev, struct ieee802154_addr *addr, u16 short_addr, u8 status); @@ -89,10 +89,10 @@ struct ieee802154_mlme_ops { u8 reason); int (*start_req)(struct net_device *dev, struct ieee802154_addr *addr, - u8 channel, u8 bcn_ord, u8 sf_ord, + u8 channel, u8 page, u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx, u8 coord_realign); int (*scan_req)(struct net_device *dev, - u8 type, u32 channels, u8 duration); + u8 type, u32 channels, u8 page, u8 duration); /* * FIXME: these should become the part of PIB/MIB interface. diff --git a/include/net/nl802154.h b/include/net/nl802154.h index e554ecd3727..99d2ba1c7e0 100644 --- a/include/net/nl802154.h +++ b/include/net/nl802154.h @@ -95,7 +95,7 @@ int ieee802154_nl_disassoc_confirm(struct net_device *dev, * Note: This API does not permit the return of an active scan result. */ int ieee802154_nl_scan_confirm(struct net_device *dev, - u8 status, u8 scan_type, u32 unscanned, + u8 status, u8 scan_type, u32 unscanned, u8 page, u8 *edl/*, struct list_head *pan_desc_list */); /** diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index cd0567f0671..2106ecbf030 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -232,7 +232,7 @@ nla_put_failure: EXPORT_SYMBOL(ieee802154_nl_beacon_indic); int ieee802154_nl_scan_confirm(struct net_device *dev, - u8 status, u8 scan_type, u32 unscanned, + u8 status, u8 scan_type, u32 unscanned, u8 page, u8 *edl/* , struct list_head *pan_desc_list */) { struct sk_buff *msg; @@ -251,6 +251,7 @@ int ieee802154_nl_scan_confirm(struct net_device *dev, NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); NLA_PUT_U8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type); NLA_PUT_U32(msg, IEEE802154_ATTR_CHANNELS, unscanned); + NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, page); if (edl) NLA_PUT(msg, IEEE802154_ATTR_ED_LIST, 27, edl); @@ -349,6 +350,7 @@ static int ieee802154_associate_req(struct sk_buff *skb, { struct net_device *dev; struct ieee802154_addr addr; + u8 page; int ret = -EINVAL; if (!info->attrs[IEEE802154_ATTR_CHANNEL] || @@ -374,8 +376,14 @@ static int ieee802154_associate_req(struct sk_buff *skb, } addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); + if (info->attrs[IEEE802154_ATTR_PAGE]) + page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); + else + page = 0; + ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr, nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]), + page, nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY])); dev_put(dev); @@ -458,6 +466,7 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) struct ieee802154_addr addr; u8 channel, bcn_ord, sf_ord; + u8 page; int pan_coord, blx, coord_realign; int ret; @@ -488,13 +497,19 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]); coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]); + if (info->attrs[IEEE802154_ATTR_PAGE]) + page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); + else + page = 0; + + if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); dev_put(dev); return -EINVAL; } - ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, + ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, bcn_ord, sf_ord, pan_coord, blx, coord_realign); dev_put(dev); @@ -508,6 +523,7 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) u8 type; u32 channels; u8 duration; + u8 page; if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] || !info->attrs[IEEE802154_ATTR_CHANNELS] || @@ -522,7 +538,13 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]); - ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, + if (info->attrs[IEEE802154_ATTR_PAGE]) + page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); + else + page = 0; + + + ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page, duration); dev_put(dev); diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 83cb4ccef90..2363ebee02e 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c @@ -33,6 +33,7 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { [IEEE802154_ATTR_HW_ADDR] = { .type = NLA_HW_ADDR, }, [IEEE802154_ATTR_PAN_ID] = { .type = NLA_U16, }, [IEEE802154_ATTR_CHANNEL] = { .type = NLA_U8, }, + [IEEE802154_ATTR_PAGE] = { .type = NLA_U8, }, [IEEE802154_ATTR_COORD_SHORT_ADDR] = { .type = NLA_U16, }, [IEEE802154_ATTR_COORD_HW_ADDR] = { .type = NLA_HW_ADDR, }, [IEEE802154_ATTR_COORD_PAN_ID] = { .type = NLA_U16, }, -- cgit v1.2.3-70-g09d2