[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1322663157-4022-1-git-send-email-alex.bluesman.smirnov@gmail.com>
Date: Wed, 30 Nov 2011 17:25:57 +0300
From: Alexander Smirnov <alex.bluesman.smirnov@...il.com>
To: dbaryshkov@...il.com
Cc: linux-zigbee-devel@...ts.sourceforge.net, netdev@...r.kernel.org,
davem@...emloft.net,
Alexander Smirnov <alex.bluesman.smirnov@...il.com>
Subject: [PATCH 08/12] [MAC802154] mac802154: MAC commands support
Support for MAC layer commands. Currently association and
disassociation are implemented only.
Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov@...il.com>
---
net/mac802154/Makefile | 2 +-
net/mac802154/mac_cmd.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 301 insertions(+), 1 deletions(-)
create mode 100644 net/mac802154/mac_cmd.c
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
index 875feb2..50e2569 100644
--- a/net/mac802154/Makefile
+++ b/net/mac802154/Makefile
@@ -1,2 +1,2 @@
obj-$(CONFIG_MAC802154) += mac802154.o
-mac802154-objs := ieee802154_dev.o rx.o tx.o mib.o
+mac802154-objs := ieee802154_dev.o rx.o tx.o mib.o mac_cmd.o
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
new file mode 100644
index 0000000..0013358
--- /dev/null
+++ b/net/mac802154/mac_cmd.c
@@ -0,0 +1,300 @@
+/*
+ * MAC commands interface
+ *
+ * Copyright 2007, 2008 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Sergey Lapin <slapin@...fans.org>
+ * Dmitry Eremin-Solenikov <dbaryshkov@...il.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <net/af_ieee802154.h>
+#include <net/mac802154.h>
+#include <net/ieee802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/nl802154.h>
+
+#include "mac802154.h"
+#include "mib.h"
+
+static int mac802154_cmd_assoc_req(struct sk_buff *skb)
+{
+ u8 cap;
+
+ if (skb->len != 2)
+ return -EINVAL;
+
+ if (skb->pkt_type != PACKET_HOST)
+ return 0;
+
+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
+ mac_cb(skb)->sa.pan_id != IEEE802154_PANID_BROADCAST)
+ return -EINVAL;
+
+ /*
+ * FIXME: check that we allow incoming ASSOC requests
+ * by consulting MIB
+ */
+
+ cap = skb->data[1];
+
+ return ieee802154_nl_assoc_indic(skb->dev, &mac_cb(skb)->sa, cap);
+}
+
+static int mac802154_cmd_assoc_resp(struct sk_buff *skb)
+{
+ u8 status;
+ u16 short_addr;
+
+ if (skb->len != 4)
+ return -EINVAL;
+
+ if (skb->pkt_type != PACKET_HOST)
+ return 0;
+
+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
+ mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
+ !(mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN))
+ return -EINVAL;
+
+ /* FIXME: check that we requested association ? */
+
+ status = skb->data[3];
+ short_addr = skb->data[1] | (skb->data[2] << 8);
+ pr_info("Received ASSOC-RESP status %x, addr %hx\n", status,
+ short_addr);
+ if (status) {
+ mac802154_dev_set_short_addr(skb->dev,
+ IEEE802154_ADDR_BROADCAST);
+ mac802154_dev_set_pan_id(skb->dev,
+ IEEE802154_PANID_BROADCAST);
+ } else
+ mac802154_dev_set_short_addr(skb->dev, short_addr);
+
+ return ieee802154_nl_assoc_confirm(skb->dev, short_addr, status);
+}
+
+static int mac802154_cmd_disassoc_notify(struct sk_buff *skb)
+{
+ u8 reason;
+
+ if (skb->len != 2)
+ return -EINVAL;
+
+ if (skb->pkt_type != PACKET_HOST)
+ return 0;
+
+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
+ (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_LONG &&
+ mac_cb(skb)->da.addr_type != IEEE802154_ADDR_SHORT) ||
+ mac_cb(skb)->sa.pan_id != mac_cb(skb)->da.pan_id)
+ return -EINVAL;
+
+ reason = skb->data[1];
+
+ /* FIXME: checks if this was our coordinator and the disassoc us */
+ /* FIXME: if we device, one should receive ->da and not ->sa */
+ /* FIXME: the status should also help */
+
+ return ieee802154_nl_disassoc_indic(skb->dev, &mac_cb(skb)->sa,
+ reason);
+}
+
+int mac802154_process_cmd(struct net_device *dev, struct sk_buff *skb)
+{
+ u8 cmd;
+
+ if (skb->len < 1) {
+ pr_warning("Uncomplete command frame!\n");
+ goto drop;
+ }
+
+ cmd = *(skb->data);
+ pr_debug("(%s): command %02x on device %s\n",
+ __func__, cmd, dev->name);
+
+ switch (cmd) {
+ case IEEE802154_CMD_ASSOCIATION_REQ:
+ mac802154_cmd_assoc_req(skb);
+ break;
+ case IEEE802154_CMD_ASSOCIATION_RESP:
+ mac802154_cmd_assoc_resp(skb);
+ break;
+ case IEEE802154_CMD_DISASSOCIATION_NOTIFY:
+ mac802154_cmd_disassoc_notify(skb);
+ break;
+ case IEEE802154_CMD_BEACON_REQ:
+ default:
+ pr_debug("(%s): frame type is not supported yet\n", __func__);
+ goto drop;
+ }
+
+
+ kfree_skb(skb);
+ return NET_RX_SUCCESS;
+
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+
+static int mac802154_send_cmd(struct net_device *dev,
+ struct ieee802154_addr *addr, struct ieee802154_addr *saddr,
+ const u8 *buf, int len)
+{
+ struct sk_buff *skb;
+ int err;
+ int hlen = LL_RESERVED_SPACE(dev), tlen = dev->needed_tailroom;
+
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+ skb = alloc_skb(hlen + tlen + len, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_reserve(skb, hlen);
+
+ skb_reset_network_header(skb);
+
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_MAC_CMD | MAC_CB_FLAG_ACKREQ;
+ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+ err = dev_hard_header(skb, dev, ETH_P_IEEE802154, addr, saddr, len);
+ if (err < 0) {
+ kfree_skb(skb);
+ return err;
+ }
+
+ skb_reset_mac_header(skb);
+ memcpy(skb_put(skb, len), buf, len);
+
+ skb->dev = dev;
+ skb->protocol = htons(ETH_P_IEEE802154);
+
+ return dev_queue_xmit(skb);
+}
+
+static int mac802154_mlme_assoc_req(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
+{
+ struct ieee802154_addr saddr;
+ u8 buf[2];
+ int pos = 0;
+
+ saddr.addr_type = IEEE802154_ADDR_LONG;
+ saddr.pan_id = IEEE802154_PANID_BROADCAST;
+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
+
+
+ /* FIXME: set PIB/MIB info */
+ mac802154_dev_set_pan_id(dev, addr->pan_id);
+ mac802154_dev_set_page_channel(dev, page, channel);
+ mac802154_dev_set_ieee_addr(dev);
+
+ buf[pos++] = IEEE802154_CMD_ASSOCIATION_REQ;
+ buf[pos++] = cap;
+
+ return mac802154_send_cmd(dev, addr, &saddr, buf, pos);
+}
+
+static int mac802154_mlme_assoc_resp(struct net_device *dev,
+ struct ieee802154_addr *addr, u16 short_addr, u8 status)
+{
+ struct ieee802154_addr saddr;
+ u8 buf[4];
+ int pos = 0;
+
+ saddr.addr_type = IEEE802154_ADDR_LONG;
+ saddr.pan_id = addr->pan_id;
+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
+
+ buf[pos++] = IEEE802154_CMD_ASSOCIATION_RESP;
+ buf[pos++] = short_addr;
+ buf[pos++] = short_addr >> 8;
+ buf[pos++] = status;
+
+ return mac802154_send_cmd(dev, addr, &saddr, buf, pos);
+}
+
+static int mac802154_mlme_disassoc_req(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 reason)
+{
+ struct ieee802154_addr saddr;
+ u8 buf[2];
+ int pos = 0;
+ int ret;
+
+ saddr.addr_type = IEEE802154_ADDR_LONG;
+ saddr.pan_id = addr->pan_id;
+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
+
+ buf[pos++] = IEEE802154_CMD_DISASSOCIATION_NOTIFY;
+ buf[pos++] = reason;
+
+ ret = mac802154_send_cmd(dev, addr, &saddr, buf, pos);
+
+ /* FIXME: this should be after the ack receved */
+ mac802154_dev_set_pan_id(dev, 0xffff);
+ mac802154_dev_set_short_addr(dev, 0xffff);
+ ieee802154_nl_disassoc_confirm(dev, 0x00);
+
+ return ret;
+}
+
+static int mac802154_mlme_start_req(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u8 channel, u8 page,
+ u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
+ u8 coord_realign)
+{
+ BUG_ON(addr->addr_type != IEEE802154_ADDR_SHORT);
+
+ mac802154_dev_set_pan_id(dev, addr->pan_id);
+ mac802154_dev_set_short_addr(dev, addr->short_addr);
+ mac802154_dev_set_ieee_addr(dev);
+ mac802154_dev_set_page_channel(dev, page, channel);
+
+ /*
+ * FIXME: add validation for unused parameters to be sane
+ * for SoftMAC
+ */
+
+ if (pan_coord)
+ dev->priv_flags |= IFF_IEEE802154_COORD;
+ else
+ dev->priv_flags &= ~IFF_IEEE802154_COORD;
+
+ mac802154_dev_set_pan_coord(dev);
+ ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
+
+ return 0;
+}
+
+struct ieee802154_mlme_ops mac802154_mlme_wpan = {
+ .assoc_req = mac802154_mlme_assoc_req,
+ .assoc_resp = mac802154_mlme_assoc_resp,
+ .disassoc_req = mac802154_mlme_disassoc_req,
+ .start_req = mac802154_mlme_start_req,
+
+ .wpan_ops.get_phy = mac802154_get_phy,
+
+ .get_pan_id = mac802154_dev_get_pan_id,
+ .get_short_addr = mac802154_dev_get_short_addr,
+ .get_dsn = mac802154_dev_get_dsn,
+ .get_bsn = mac802154_dev_get_bsn,
+};
--
1.7.2.3
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists