aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2015-09-18 05:30:42 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-09-22 05:51:20 -0400
commit838b83d63d2909f9136f3030dc4fffa8230c31da (patch)
tree7efa76e2b2a2df882e4ad941ef01806ad0664e94
parenta1da67b8117ddbe88c770b48b5b1527393b8c9c0 (diff)
ieee802154: introduce wpan_dev_header_ops
The current header_ops callback structure of net device are used mostly from 802.15.4 upper-layers. Because this callback structure is a very generic one, which is also used by e.g. DGRAM AF_PACKET sockets, we can't make this callback structure 802.15.4 specific which is currently is. I saw the smallest "constraint" for calling this callback with dev_hard_header/dev_parse_header by AF_PACKET which assign a 8 byte array for address void pointers. Currently 802.15.4 specific protocols like af802154 and 6LoWPAN will assign the "struct ieee802154_addr" as these parameters which is greater than 8 bytes. The current callback implementation for header_ops.create assumes always a complete "struct ieee802154_addr" which AF_PACKET can't never handled and is greater than 8 bytes. For that reason we introduce now a "generic" create/parse header_ops callback which allows handling with intra-pan extended addresses only. This allows a small use-case with AF_PACKET to send "somehow" a valid dataframe over DGRAM. To keeping the current dev_hard_header behaviour we introduce a similar callback structure "wpan_dev_header_ops" which contains 802.15.4 specific upper-layer header creation functionality, which can be called by wpan_dev_hard_header. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/cfg802154.h33
-rw-r--r--include/net/ieee802154_netdev.h9
-rw-r--r--net/ieee802154/6lowpan/tx.c8
-rw-r--r--net/ieee802154/socket.c4
-rw-r--r--net/mac802154/iface.c91
5 files changed, 118 insertions, 27 deletions
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 76b1ffaea863..242273ccf34b 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -167,6 +167,26 @@ struct wpan_phy {
167 char priv[0] __aligned(NETDEV_ALIGN); 167 char priv[0] __aligned(NETDEV_ALIGN);
168}; 168};
169 169
170struct ieee802154_addr {
171 u8 mode;
172 __le16 pan_id;
173 union {
174 __le16 short_addr;
175 __le64 extended_addr;
176 };
177};
178
179struct wpan_dev_header_ops {
180 /* TODO create callback currently assumes ieee802154_mac_cb inside
181 * skb->cb. This should be changed to give these information as
182 * parameter.
183 */
184 int (*create)(struct sk_buff *skb, struct net_device *dev,
185 const struct ieee802154_addr *daddr,
186 const struct ieee802154_addr *saddr,
187 unsigned int len);
188};
189
170struct wpan_dev { 190struct wpan_dev {
171 struct wpan_phy *wpan_phy; 191 struct wpan_phy *wpan_phy;
172 int iftype; 192 int iftype;
@@ -175,6 +195,8 @@ struct wpan_dev {
175 struct list_head list; 195 struct list_head list;
176 struct net_device *netdev; 196 struct net_device *netdev;
177 197
198 const struct wpan_dev_header_ops *header_ops;
199
178 /* lowpan interface, set when the wpan_dev belongs to one lowpan_dev */ 200 /* lowpan interface, set when the wpan_dev belongs to one lowpan_dev */
179 struct net_device *lowpan_dev; 201 struct net_device *lowpan_dev;
180 202
@@ -205,6 +227,17 @@ struct wpan_dev {
205 227
206#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) 228#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
207 229
230static inline int
231wpan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
232 const struct ieee802154_addr *daddr,
233 const struct ieee802154_addr *saddr,
234 unsigned int len)
235{
236 struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
237
238 return wpan_dev->header_ops->create(skb, dev, daddr, saddr, len);
239}
240
208struct wpan_phy * 241struct wpan_phy *
209wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size); 242wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size);
210static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev) 243static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 95a71bc113b3..aebb9d8d7a11 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -50,15 +50,6 @@ struct ieee802154_sechdr {
50 }; 50 };
51}; 51};
52 52
53struct ieee802154_addr {
54 u8 mode;
55 __le16 pan_id;
56 union {
57 __le16 short_addr;
58 __le64 extended_addr;
59 };
60};
61
62struct ieee802154_hdr_fc { 53struct ieee802154_hdr_fc {
63#if defined(__LITTLE_ENDIAN_BITFIELD) 54#if defined(__LITTLE_ENDIAN_BITFIELD)
64 u16 type:3, 55 u16 type:3,
diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
index 54939d031ea5..6067e064a3fe 100644
--- a/net/ieee802154/6lowpan/tx.c
+++ b/net/ieee802154/6lowpan/tx.c
@@ -87,8 +87,8 @@ lowpan_alloc_frag(struct sk_buff *skb, int size,
87 skb_reset_network_header(frag); 87 skb_reset_network_header(frag);
88 *mac_cb(frag) = *mac_cb(skb); 88 *mac_cb(frag) = *mac_cb(skb);
89 89
90 rc = dev_hard_header(frag, wdev, 0, &master_hdr->dest, 90 rc = wpan_dev_hard_header(frag, wdev, &master_hdr->dest,
91 &master_hdr->source, size); 91 &master_hdr->source, size);
92 if (rc < 0) { 92 if (rc < 0) {
93 kfree_skb(frag); 93 kfree_skb(frag);
94 return ERR_PTR(rc); 94 return ERR_PTR(rc);
@@ -228,8 +228,8 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *ldev,
228 cb->ackreq = wpan_dev->ackreq; 228 cb->ackreq = wpan_dev->ackreq;
229 } 229 }
230 230
231 return dev_hard_header(skb, lowpan_dev_info(ldev)->wdev, ETH_P_IPV6, 231 return wpan_dev_hard_header(skb, lowpan_dev_info(ldev)->wdev, &da, &sa,
232 (void *)&da, (void *)&sa, 0); 232 0);
233} 233}
234 234
235netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev) 235netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
index b6eacf30ee7a..be77f211ce87 100644
--- a/net/ieee802154/socket.c
+++ b/net/ieee802154/socket.c
@@ -676,8 +676,8 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
676 cb->seclevel = ro->seclevel; 676 cb->seclevel = ro->seclevel;
677 cb->seclevel_override = ro->seclevel_override; 677 cb->seclevel_override = ro->seclevel_override;
678 678
679 err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr, 679 err = wpan_dev_hard_header(skb, dev, &dst_addr,
680 ro->bound ? &ro->src_addr : NULL, size); 680 ro->bound ? &ro->src_addr : NULL, size);
681 if (err < 0) 681 if (err < 0)
682 goto out_skb; 682 goto out_skb;
683 683
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index ed26952f9e14..8afe26d72971 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -367,12 +367,11 @@ static int mac802154_set_header_security(struct ieee802154_sub_if_data *sdata,
367 return 0; 367 return 0;
368} 368}
369 369
370static int mac802154_header_create(struct sk_buff *skb, 370static int ieee802154_header_create(struct sk_buff *skb,
371 struct net_device *dev, 371 struct net_device *dev,
372 unsigned short type, 372 const struct ieee802154_addr *daddr,
373 const void *daddr, 373 const struct ieee802154_addr *saddr,
374 const void *saddr, 374 unsigned len)
375 unsigned len)
376{ 375{
377 struct ieee802154_hdr hdr; 376 struct ieee802154_hdr hdr;
378 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 377 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
@@ -423,24 +422,91 @@ static int mac802154_header_create(struct sk_buff *skb,
423 return hlen; 422 return hlen;
424} 423}
425 424
425static const struct wpan_dev_header_ops ieee802154_header_ops = {
426 .create = ieee802154_header_create,
427};
428
429/* This header create functionality assumes a 8 byte array for
430 * source and destination pointer at maximum. To adapt this for
431 * the 802.15.4 dataframe header we use extended address handling
432 * here only and intra pan connection. fc fields are mostly fallback
433 * handling. For provide dev_hard_header for dgram sockets.
434 */
435static int mac802154_header_create(struct sk_buff *skb,
436 struct net_device *dev,
437 unsigned short type,
438 const void *daddr,
439 const void *saddr,
440 unsigned len)
441{
442 struct ieee802154_hdr hdr;
443 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
444 struct wpan_dev *wpan_dev = &sdata->wpan_dev;
445 struct ieee802154_mac_cb cb = { };
446 int hlen;
447
448 if (!daddr)
449 return -EINVAL;
450
451 memset(&hdr.fc, 0, sizeof(hdr.fc));
452 hdr.fc.type = IEEE802154_FC_TYPE_DATA;
453 hdr.fc.ack_request = wpan_dev->ackreq;
454 hdr.seq = atomic_inc_return(&dev->ieee802154_ptr->dsn) & 0xFF;
455
456 /* TODO currently a workaround to give zero cb block to set
457 * security parameters defaults according MIB.
458 */
459 if (mac802154_set_header_security(sdata, &hdr, &cb) < 0)
460 return -EINVAL;
461
462 hdr.dest.pan_id = wpan_dev->pan_id;
463 hdr.dest.mode = IEEE802154_ADDR_LONG;
464 memcpy(&hdr.dest.extended_addr, daddr, IEEE802154_EXTENDED_ADDR_LEN);
465
466 hdr.source.pan_id = hdr.dest.pan_id;
467 hdr.source.mode = IEEE802154_ADDR_LONG;
468
469 if (!saddr)
470 hdr.source.extended_addr = wpan_dev->extended_addr;
471 else
472 memcpy(&hdr.source.extended_addr, saddr,
473 IEEE802154_EXTENDED_ADDR_LEN);
474
475 hlen = ieee802154_hdr_push(skb, &hdr);
476 if (hlen < 0)
477 return -EINVAL;
478
479 skb_reset_mac_header(skb);
480 skb->mac_len = hlen;
481
482 if (len > ieee802154_max_payload(&hdr))
483 return -EMSGSIZE;
484
485 return hlen;
486}
487
426static int 488static int
427mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) 489mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
428{ 490{
429 struct ieee802154_hdr hdr; 491 struct ieee802154_hdr hdr;
430 struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
431 492
432 if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) { 493 if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
433 pr_debug("malformed packet\n"); 494 pr_debug("malformed packet\n");
434 return 0; 495 return 0;
435 } 496 }
436 497
437 *addr = hdr.source; 498 if (hdr.source.mode == IEEE802154_ADDR_LONG) {
438 return sizeof(*addr); 499 memcpy(haddr, &hdr.source.extended_addr,
500 IEEE802154_EXTENDED_ADDR_LEN);
501 return IEEE802154_EXTENDED_ADDR_LEN;
502 }
503
504 return 0;
439} 505}
440 506
441static struct header_ops mac802154_header_ops = { 507static const struct header_ops mac802154_header_ops = {
442 .create = mac802154_header_create, 508 .create = mac802154_header_create,
443 .parse = mac802154_header_parse, 509 .parse = mac802154_header_parse,
444}; 510};
445 511
446static const struct net_device_ops mac802154_wpan_ops = { 512static const struct net_device_ops mac802154_wpan_ops = {
@@ -513,6 +579,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
513 sdata->dev->netdev_ops = &mac802154_wpan_ops; 579 sdata->dev->netdev_ops = &mac802154_wpan_ops;
514 sdata->dev->ml_priv = &mac802154_mlme_wpan; 580 sdata->dev->ml_priv = &mac802154_mlme_wpan;
515 wpan_dev->promiscuous_mode = false; 581 wpan_dev->promiscuous_mode = false;
582 wpan_dev->header_ops = &ieee802154_header_ops;
516 583
517 mutex_init(&sdata->sec_mtx); 584 mutex_init(&sdata->sec_mtx);
518 585