aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac802154/rx.c
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2014-10-27 12:13:32 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-10-27 13:07:42 -0400
commit2a9820c9e20a7889bf464e1edff5f75d685a8214 (patch)
treeda13a692aa54e96256161b43c75f605832261e98 /net/mac802154/rx.c
parentc730c90316aa5753c6b2d3d5af40085c220e3a91 (diff)
mac802154: rx: move receive handling into rx.c
This patch removes all relevant receiving functions inclusive frame parsing into rx file. Like mac80211 we should implement the complete receive handling and parsing in this file. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/mac802154/rx.c')
-rw-r--r--net/mac802154/rx.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index c4df3210c5e6..d8498c5fc297 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -24,9 +24,223 @@
24 24
25#include <net/mac802154.h> 25#include <net/mac802154.h>
26#include <net/ieee802154_netdev.h> 26#include <net/ieee802154_netdev.h>
27#include <net/rtnetlink.h>
28#include <linux/nl802154.h>
27 29
28#include "ieee802154_i.h" 30#include "ieee802154_i.h"
29 31
32static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
33{
34 return netif_receive_skb(skb);
35}
36
37static int
38mac802154_subif_frame(struct ieee802154_sub_if_data *sdata, struct sk_buff *skb,
39 const struct ieee802154_hdr *hdr)
40{
41 __le16 span, sshort;
42 int rc;
43
44 pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
45
46 spin_lock_bh(&sdata->mib_lock);
47
48 span = sdata->pan_id;
49 sshort = sdata->short_addr;
50
51 switch (mac_cb(skb)->dest.mode) {
52 case IEEE802154_ADDR_NONE:
53 if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
54 /* FIXME: check if we are PAN coordinator */
55 skb->pkt_type = PACKET_OTHERHOST;
56 else
57 /* ACK comes with both addresses empty */
58 skb->pkt_type = PACKET_HOST;
59 break;
60 case IEEE802154_ADDR_LONG:
61 if (mac_cb(skb)->dest.pan_id != span &&
62 mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
63 skb->pkt_type = PACKET_OTHERHOST;
64 else if (mac_cb(skb)->dest.extended_addr == sdata->extended_addr)
65 skb->pkt_type = PACKET_HOST;
66 else
67 skb->pkt_type = PACKET_OTHERHOST;
68 break;
69 case IEEE802154_ADDR_SHORT:
70 if (mac_cb(skb)->dest.pan_id != span &&
71 mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
72 skb->pkt_type = PACKET_OTHERHOST;
73 else if (mac_cb(skb)->dest.short_addr == sshort)
74 skb->pkt_type = PACKET_HOST;
75 else if (mac_cb(skb)->dest.short_addr ==
76 cpu_to_le16(IEEE802154_ADDR_BROADCAST))
77 skb->pkt_type = PACKET_BROADCAST;
78 else
79 skb->pkt_type = PACKET_OTHERHOST;
80 break;
81 default:
82 spin_unlock_bh(&sdata->mib_lock);
83 pr_debug("invalid dest mode\n");
84 kfree_skb(skb);
85 return NET_RX_DROP;
86 }
87
88 spin_unlock_bh(&sdata->mib_lock);
89
90 skb->dev = sdata->dev;
91
92 rc = mac802154_llsec_decrypt(&sdata->sec, skb);
93 if (rc) {
94 pr_debug("decryption failed: %i\n", rc);
95 goto fail;
96 }
97
98 sdata->dev->stats.rx_packets++;
99 sdata->dev->stats.rx_bytes += skb->len;
100
101 switch (mac_cb(skb)->type) {
102 case IEEE802154_FC_TYPE_DATA:
103 return mac802154_process_data(sdata->dev, skb);
104 default:
105 pr_warn("ieee802154: bad frame received (type = %d)\n",
106 mac_cb(skb)->type);
107 goto fail;
108 }
109
110fail:
111 kfree_skb(skb);
112 return NET_RX_DROP;
113}
114
115static void mac802154_print_addr(const char *name,
116 const struct ieee802154_addr *addr)
117{
118 if (addr->mode == IEEE802154_ADDR_NONE)
119 pr_debug("%s not present\n", name);
120
121 pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id));
122 if (addr->mode == IEEE802154_ADDR_SHORT) {
123 pr_debug("%s is short: %04x\n", name,
124 le16_to_cpu(addr->short_addr));
125 } else {
126 u64 hw = swab64((__force u64)addr->extended_addr);
127
128 pr_debug("%s is hardware: %8phC\n", name, &hw);
129 }
130}
131
132static int mac802154_parse_frame_start(struct sk_buff *skb,
133 struct ieee802154_hdr *hdr)
134{
135 int hlen;
136 struct ieee802154_mac_cb *cb = mac_cb_init(skb);
137
138 hlen = ieee802154_hdr_pull(skb, hdr);
139 if (hlen < 0)
140 return -EINVAL;
141
142 skb->mac_len = hlen;
143
144 pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc),
145 hdr->seq);
146
147 cb->type = hdr->fc.type;
148 cb->ackreq = hdr->fc.ack_request;
149 cb->secen = hdr->fc.security_enabled;
150
151 mac802154_print_addr("destination", &hdr->dest);
152 mac802154_print_addr("source", &hdr->source);
153
154 cb->source = hdr->source;
155 cb->dest = hdr->dest;
156
157 if (hdr->fc.security_enabled) {
158 u64 key;
159
160 pr_debug("seclevel %i\n", hdr->sec.level);
161
162 switch (hdr->sec.key_id_mode) {
163 case IEEE802154_SCF_KEY_IMPLICIT:
164 pr_debug("implicit key\n");
165 break;
166
167 case IEEE802154_SCF_KEY_INDEX:
168 pr_debug("key %02x\n", hdr->sec.key_id);
169 break;
170
171 case IEEE802154_SCF_KEY_SHORT_INDEX:
172 pr_debug("key %04x:%04x %02x\n",
173 le32_to_cpu(hdr->sec.short_src) >> 16,
174 le32_to_cpu(hdr->sec.short_src) & 0xffff,
175 hdr->sec.key_id);
176 break;
177
178 case IEEE802154_SCF_KEY_HW_INDEX:
179 key = swab64((__force u64)hdr->sec.extended_src);
180 pr_debug("key source %8phC %02x\n", &key,
181 hdr->sec.key_id);
182 break;
183 }
184 }
185
186 return 0;
187}
188
189static void
190mac802154_wpans_rx(struct ieee802154_local *local, struct sk_buff *skb)
191{
192 int ret;
193 struct ieee802154_sub_if_data *sdata;
194 struct ieee802154_hdr hdr;
195
196 ret = mac802154_parse_frame_start(skb, &hdr);
197 if (ret) {
198 pr_debug("got invalid frame\n");
199 kfree_skb(skb);
200 return;
201 }
202
203 rcu_read_lock();
204 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
205 if (sdata->type != IEEE802154_DEV_WPAN ||
206 !netif_running(sdata->dev))
207 continue;
208
209 mac802154_subif_frame(sdata, skb, &hdr);
210 skb = NULL;
211 break;
212 }
213 rcu_read_unlock();
214
215 if (skb)
216 kfree_skb(skb);
217}
218
219void mac802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
220{
221 struct sk_buff *skb2;
222 struct ieee802154_sub_if_data *sdata;
223 u16 crc = crc_ccitt(0, skb->data, skb->len);
224 u8 *data;
225
226 rcu_read_lock();
227 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
228 if (sdata->type != IEEE802154_DEV_MONITOR ||
229 !netif_running(sdata->dev))
230 continue;
231
232 skb2 = skb_clone(skb, GFP_ATOMIC);
233 skb2->dev = sdata->dev;
234 skb2->pkt_type = PACKET_HOST;
235 data = skb_put(skb2, 2);
236 data[0] = crc & 0xff;
237 data[1] = crc >> 8;
238
239 netif_rx_ni(skb2);
240 }
241 rcu_read_unlock();
242}
243
30static void 244static void
31mac802154_subif_rx(struct ieee802154_hw *hw, struct sk_buff *skb) 245mac802154_subif_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
32{ 246{