All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation
@ 2015-08-20 16:47 Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 01/16] ieee802154: 6lowpan: change dev vars to wdev and ldev Alexander Aring
                   ` (16 more replies)
  0 siblings, 17 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

Hi,

this patch series contains a rework of 802.15.4 6LoWPAN receive handling.
We need to check on some things before which never checked before, like
is 802.15.4 dataframe, if we can access skb->data[0] (could be that skb->len
is 0 then), etc.

Also various bug fixes like the masking for fragmentation dispatch value which
is currently wrong. Also we should again check the dispatch value after successful
reassembly a fragment, we currently assume always a iphc header there. This is wrong
it could also be a non-compressed header. This can occur if the compressed header is
larger than lower interface MTU size, we doesn't react on this while transmit which
is another issue. Nevertheless we also don't reach this case at worst-case compression
currently.

I introduced a complete new handling for the dispatch values based on mac80211
receive handling mechanism.

- Alex

changes since v2:
 - I know there is some patch on net-next which occurs in merge conflicts, I
   will wait until this patch is in bluetooth-next before sending as PATCH.
 - fix the "ieee820154: 6lowpan: dispatch evaluation rework" by also doing
   dispatch evaluation on FRAG1. Also we do now FRAG1 uncompression (if iphc)
   on-the-fly. This is currently solved by doing special lltype handling
   in generic 6LoWPAN. Maybe we can introduce some "payload_len" parameter
   to the uncompression functions, to avoid the use of skb->cb.
   The complete patch looks different now, I fixup also some other patches into
   this patch.
   Also add skb_unshare on dispatches where we manipulate the skb data.
   Change address handling for fragmentation for parse again skb_mac_header instead
   using skb->cb which was filled from lower layer.
 - replace the removal of wdev running patch "ieee802154: 6lowpan: change if
   lowpan dev is running".
 - add lowpan_dff dispatch.
 - change reserved dispatch values to use ranges.
 - add "ieee802154: 6lowpan: register packet layer while open".
 - add "ieee802154: 6lowpan: remove check on null".
 - change order at "ieee802154: 6lowpan: trivial checks at" to check on
   "wdev->type != ARPHRD_IEEE802154" at first.
 - change "ieee802154: 6lowpan: check on valid 802.15.4 frame", we don't need
   to check on addr none. Dataframes which belongs to a "node" type should always
   have source and destination addresses. This need to be handled in the lower layers.
 - add "ieee802154: 6lowpan: remove tx full-size" which removes a ugly workaround
   to calculate the full size of iphc packet. We don't need it since we use FRAG1
   uncompression on the fly. Also change this behaviour for transmit and remove
   the ugly workaround functions.

Alexander Aring (16):
  ieee802154: 6lowpan: change dev vars to wdev and ldev
  ieee802154: 6lowpan: register packet layer while open
  ieee802154: 6lowpan: remove check on null
  ieee802154: 6lowpan: remove set to zero
  ieee802154: 6lowpan: remove EXPORT_SYMBOL
  ieee802154: 6lowpan: change if lowpan dev is running
  ieee802154: 6lowpan: cleanup pull of iphc bytes
  ieee802154: 6lowpan: trivial checks at first
  ieee802154: 6lowpan: earlier skb->dev switch
  ieee820154: 6lowpan: dispatch evaluation rework
  ieee802154: 6lowpan: add generic lowpan header check
  ieee802154: 6lowpan: add handler for all dispatch values
  ieee802154: 6lowpan: add check for reserved dispatch
  ieee802154: 6lowpan: check on valid 802.15.4 frame
  ieee802154: 6lowpan: remove packet type to host
  ieee802154: 6lowpan: remove tx full-size calc workaround

 include/linux/ieee802154.h          |  25 +++
 include/net/6lowpan.h               | 144 +++------------
 include/net/mac802154.h             |  15 ++
 net/6lowpan/iphc.c                  |  13 +-
 net/6lowpan/nhc_udp.c               |  13 +-
 net/ieee802154/6lowpan/6lowpan_i.h  |  14 +-
 net/ieee802154/6lowpan/core.c       | 115 ++++++------
 net/ieee802154/6lowpan/reassembly.c | 141 ++++++++++-----
 net/ieee802154/6lowpan/rx.c         | 350 ++++++++++++++++++++++++++++--------
 net/ieee802154/6lowpan/tx.c         |  51 +++---
 10 files changed, 559 insertions(+), 322 deletions(-)

-- 
2.5.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 01/16] ieee802154: 6lowpan: change dev vars to wdev and ldev
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open Alexander Aring
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

Inside the IEEE 802.15.4 6LoWPAN subsystem we use two interfaces which
are wpan and lowpan interfaces. Instead of using always the variable
name "dev" for both we rename the "dev" variable to wdev which means the
wpan net_device and ldev which means a lowpan net_device. This avoids
confusing and always looking back to see which net_device is meant by
the variable name "dev".

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/6lowpan_i.h  |  2 +-
 net/ieee802154/6lowpan/core.c       | 89 ++++++++++++++++++-------------------
 net/ieee802154/6lowpan/reassembly.c | 14 +++---
 net/ieee802154/6lowpan/rx.c         | 22 ++++-----
 net/ieee802154/6lowpan/tx.c         | 39 ++++++++--------
 5 files changed, 82 insertions(+), 84 deletions(-)

diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h
index ea339fa..9aa7b62 100644
--- a/net/ieee802154/6lowpan/6lowpan_i.h
+++ b/net/ieee802154/6lowpan/6lowpan_i.h
@@ -40,7 +40,7 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a)
 
 /* private device info */
 struct lowpan_dev_info {
-	struct net_device	*real_dev; /* real WPAN device ptr */
+	struct net_device	*wdev; /* wpan device ptr */
 	u16			fragment_tag;
 };
 
diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index 27c25ad..3cc76f0 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -61,7 +61,7 @@ static struct header_ops lowpan_header_ops = {
 static struct lock_class_key lowpan_tx_busylock;
 static struct lock_class_key lowpan_netdev_xmit_lock_key;
 
-static void lowpan_set_lockdep_class_one(struct net_device *dev,
+static void lowpan_set_lockdep_class_one(struct net_device *ldev,
 					 struct netdev_queue *txq,
 					 void *_unused)
 {
@@ -69,10 +69,10 @@ static void lowpan_set_lockdep_class_one(struct net_device *dev,
 			  &lowpan_netdev_xmit_lock_key);
 }
 
-static int lowpan_dev_init(struct net_device *dev)
+static int lowpan_dev_init(struct net_device *ldev)
 {
-	netdev_for_each_tx_queue(dev, lowpan_set_lockdep_class_one, NULL);
-	dev->qdisc_tx_busylock = &lowpan_tx_busylock;
+	netdev_for_each_tx_queue(ldev, lowpan_set_lockdep_class_one, NULL);
+	ldev->qdisc_tx_busylock = &lowpan_tx_busylock;
 	return 0;
 }
 
@@ -81,23 +81,23 @@ static const struct net_device_ops lowpan_netdev_ops = {
 	.ndo_start_xmit		= lowpan_xmit,
 };
 
-static void lowpan_setup(struct net_device *dev)
+static void lowpan_setup(struct net_device *ldev)
 {
-	dev->addr_len		= IEEE802154_ADDR_LEN;
-	memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
-	dev->type		= ARPHRD_6LOWPAN;
+	ldev->addr_len		= IEEE802154_ADDR_LEN;
+	memset(ldev->broadcast, 0xff, IEEE802154_ADDR_LEN);
+	ldev->type		= ARPHRD_6LOWPAN;
 	/* Frame Control + Sequence Number + Address fields + Security Header */
-	dev->hard_header_len	= 2 + 1 + 20 + 14;
-	dev->needed_tailroom	= 2; /* FCS */
-	dev->mtu		= IPV6_MIN_MTU;
-	dev->tx_queue_len	= 0;
-	dev->flags		= IFF_BROADCAST | IFF_MULTICAST;
-	dev->watchdog_timeo	= 0;
-
-	dev->netdev_ops		= &lowpan_netdev_ops;
-	dev->header_ops		= &lowpan_header_ops;
-	dev->destructor		= free_netdev;
-	dev->features		|= NETIF_F_NETNS_LOCAL;
+	ldev->hard_header_len	= 2 + 1 + 20 + 14;
+	ldev->needed_tailroom	= 2; /* FCS */
+	ldev->mtu		= IPV6_MIN_MTU;
+	ldev->tx_queue_len	= 0;
+	ldev->flags		= IFF_BROADCAST | IFF_MULTICAST;
+	ldev->watchdog_timeo	= 0;
+
+	ldev->netdev_ops	= &lowpan_netdev_ops;
+	ldev->header_ops	= &lowpan_header_ops;
+	ldev->destructor	= free_netdev;
+	ldev->features		|= NETIF_F_NETNS_LOCAL;
 }
 
 static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -109,10 +109,10 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
 	return 0;
 }
 
-static int lowpan_newlink(struct net *src_net, struct net_device *dev,
+static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
 			  struct nlattr *tb[], struct nlattr *data[])
 {
-	struct net_device *real_dev;
+	struct net_device *wdev;
 	int ret;
 
 	ASSERT_RTNL();
@@ -120,35 +120,35 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 	pr_debug("adding new link\n");
 
 	if (!tb[IFLA_LINK] ||
-	    !net_eq(dev_net(dev), &init_net))
+	    !net_eq(dev_net(ldev), &init_net))
 		return -EINVAL;
-	/* find and hold real wpan device */
-	real_dev = dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK]));
-	if (!real_dev)
+	/* find and hold wpan device */
+	wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK]));
+	if (!wdev)
 		return -ENODEV;
-	if (real_dev->type != ARPHRD_IEEE802154) {
-		dev_put(real_dev);
+	if (wdev->type != ARPHRD_IEEE802154) {
+		dev_put(wdev);
 		return -EINVAL;
 	}
 
-	if (real_dev->ieee802154_ptr->lowpan_dev) {
-		dev_put(real_dev);
+	if (wdev->ieee802154_ptr->lowpan_dev) {
+		dev_put(wdev);
 		return -EBUSY;
 	}
 
-	lowpan_dev_info(dev)->real_dev = real_dev;
+	lowpan_dev_info(ldev)->wdev = wdev;
 	/* Set the lowpan hardware address to the wpan hardware address. */
-	memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
+	memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN);
 
-	lowpan_netdev_setup(dev, LOWPAN_LLTYPE_IEEE802154);
+	lowpan_netdev_setup(ldev, LOWPAN_LLTYPE_IEEE802154);
 
-	ret = register_netdevice(dev);
+	ret = register_netdevice(ldev);
 	if (ret < 0) {
-		dev_put(real_dev);
+		dev_put(wdev);
 		return ret;
 	}
 
-	real_dev->ieee802154_ptr->lowpan_dev = dev;
+	wdev->ieee802154_ptr->lowpan_dev = ldev;
 	if (!open_count)
 		lowpan_rx_init();
 
@@ -157,10 +157,9 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 	return 0;
 }
 
-static void lowpan_dellink(struct net_device *dev, struct list_head *head)
+static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
 {
-	struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
-	struct net_device *real_dev = lowpan_dev->real_dev;
+	struct net_device *wdev = lowpan_dev_info(ldev)->wdev;
 
 	ASSERT_RTNL();
 
@@ -169,9 +168,9 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head)
 	if (!open_count)
 		lowpan_rx_exit();
 
-	real_dev->ieee802154_ptr->lowpan_dev = NULL;
-	unregister_netdevice(dev);
-	dev_put(real_dev);
+	wdev->ieee802154_ptr->lowpan_dev = NULL;
+	unregister_netdevice(ldev);
+	dev_put(wdev);
 }
 
 static struct rtnl_link_ops lowpan_link_ops __read_mostly = {
@@ -196,9 +195,9 @@ static inline void lowpan_netlink_fini(void)
 static int lowpan_device_event(struct notifier_block *unused,
 			       unsigned long event, void *ptr)
 {
-	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct net_device *wdev = netdev_notifier_info_to_dev(ptr);
 
-	if (dev->type != ARPHRD_IEEE802154)
+	if (wdev->type != ARPHRD_IEEE802154)
 		goto out;
 
 	switch (event) {
@@ -207,8 +206,8 @@ static int lowpan_device_event(struct notifier_block *unused,
 		 * also delete possible lowpan interfaces which belongs
 		 * to the wpan interface.
 		 */
-		if (dev->ieee802154_ptr && dev->ieee802154_ptr->lowpan_dev)
-			lowpan_dellink(dev->ieee802154_ptr->lowpan_dev, NULL);
+		if (wdev->ieee802154_ptr && wdev->ieee802154_ptr->lowpan_dev)
+			lowpan_dellink(wdev->ieee802154_ptr->lowpan_dev, NULL);
 		break;
 	default:
 		break;
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index 214d44a..60d6df7 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -46,7 +46,7 @@ static struct lowpan_frag_info *lowpan_cb(struct sk_buff *skb)
 static struct inet_frags lowpan_frags;
 
 static int lowpan_frag_reasm(struct lowpan_frag_queue *fq,
-			     struct sk_buff *prev, struct net_device *dev);
+			     struct sk_buff *prev, struct net_device *ldev);
 
 static unsigned int lowpan_hash_frag(u16 tag, u16 d_size,
 				     const struct ieee802154_addr *saddr,
@@ -141,7 +141,7 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
 			     struct sk_buff *skb, const u8 frag_type)
 {
 	struct sk_buff *prev, *next;
-	struct net_device *dev;
+	struct net_device *ldev;
 	int end, offset;
 
 	if (fq->q.flags & INET_FRAG_COMPLETE)
@@ -195,8 +195,8 @@ found:
 	else
 		fq->q.fragments = skb;
 
-	dev = skb->dev;
-	if (dev)
+	ldev = skb->dev;
+	if (ldev)
 		skb->dev = NULL;
 
 	fq->q.stamp = skb->tstamp;
@@ -215,7 +215,7 @@ found:
 		unsigned long orefdst = skb->_skb_refdst;
 
 		skb->_skb_refdst = 0UL;
-		res = lowpan_frag_reasm(fq, prev, dev);
+		res = lowpan_frag_reasm(fq, prev, ldev);
 		skb->_skb_refdst = orefdst;
 		return res;
 	}
@@ -235,7 +235,7 @@ err:
  *	the last and the first frames arrived and all the bits are here.
  */
 static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *prev,
-			     struct net_device *dev)
+			     struct net_device *ldev)
 {
 	struct sk_buff *fp, *head = fq->q.fragments;
 	int sum_truesize;
@@ -313,7 +313,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *prev,
 	sub_frag_mem_limit(fq->q.net, sum_truesize);
 
 	head->next = NULL;
-	head->dev = dev;
+	head->dev = ldev;
 	head->tstamp = fq->q.stamp;
 
 	fq->q.fragments = NULL;
diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index 12e1020..b1442f3 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -16,9 +16,9 @@
 #include "6lowpan_i.h"
 
 static int lowpan_give_skb_to_device(struct sk_buff *skb,
-				     struct net_device *dev)
+				     struct net_device *wdev)
 {
-	skb->dev = dev->ieee802154_ptr->lowpan_dev;
+	skb->dev = wdev->ieee802154_ptr->lowpan_dev;
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->pkt_type = PACKET_HOST;
 
@@ -61,21 +61,21 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 					IEEE802154_ADDR_LEN, iphc0, iphc1);
 }
 
-static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
-		      struct packet_type *pt, struct net_device *orig_dev)
+static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
+		      struct packet_type *pt, struct net_device *orig_wdev)
 {
 	struct ieee802154_hdr hdr;
 	int ret;
 
-	if (dev->type != ARPHRD_IEEE802154 ||
-	    !dev->ieee802154_ptr->lowpan_dev)
+	if (wdev->type != ARPHRD_IEEE802154 ||
+	    !wdev->ieee802154_ptr->lowpan_dev)
 		goto drop;
 
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (!skb)
 		goto drop;
 
-	if (!netif_running(dev))
+	if (!netif_running(wdev))
 		goto drop_skb;
 
 	if (skb->pkt_type == PACKET_OTHERHOST)
@@ -88,7 +88,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
 		/* Pull off the 1-byte of 6lowpan header. */
 		skb_pull(skb, 1);
-		return lowpan_give_skb_to_device(skb, dev);
+		return lowpan_give_skb_to_device(skb, wdev);
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
@@ -96,7 +96,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 			if (ret < 0)
 				goto drop_skb;
 
-			return lowpan_give_skb_to_device(skb, dev);
+			return lowpan_give_skb_to_device(skb, wdev);
 		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
 			if (ret == 1) {
@@ -104,7 +104,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 				if (ret < 0)
 					goto drop_skb;
 
-				return lowpan_give_skb_to_device(skb, dev);
+				return lowpan_give_skb_to_device(skb, wdev);
 			} else if (ret == -1) {
 				return NET_RX_DROP;
 			} else {
@@ -117,7 +117,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 				if (ret < 0)
 					goto drop_skb;
 
-				return lowpan_give_skb_to_device(skb, dev);
+				return lowpan_give_skb_to_device(skb, wdev);
 			} else if (ret == -1) {
 				return NET_RX_DROP;
 			} else {
diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
index f6263fc..9a2147e 100644
--- a/net/ieee802154/6lowpan/tx.c
+++ b/net/ieee802154/6lowpan/tx.c
@@ -36,7 +36,7 @@ lowpan_addr_info *lowpan_skb_priv(const struct sk_buff *skb)
 			sizeof(struct lowpan_addr_info));
 }
 
-int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
+int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev,
 			 unsigned short type, const void *_daddr,
 			 const void *_saddr, unsigned int len)
 {
@@ -51,7 +51,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
 		return 0;
 
 	if (!saddr)
-		saddr = dev->dev_addr;
+		saddr = ldev->dev_addr;
 
 	raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8);
 	raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8);
@@ -73,22 +73,21 @@ static struct sk_buff*
 lowpan_alloc_frag(struct sk_buff *skb, int size,
 		  const struct ieee802154_hdr *master_hdr)
 {
-	struct net_device *real_dev = lowpan_dev_info(skb->dev)->real_dev;
+	struct net_device *wdev = lowpan_dev_info(skb->dev)->wdev;
 	struct sk_buff *frag;
 	int rc;
 
-	frag = alloc_skb(real_dev->hard_header_len +
-			 real_dev->needed_tailroom + size,
+	frag = alloc_skb(wdev->hard_header_len + wdev->needed_tailroom + size,
 			 GFP_ATOMIC);
 
 	if (likely(frag)) {
-		frag->dev = real_dev;
+		frag->dev = wdev;
 		frag->priority = skb->priority;
-		skb_reserve(frag, real_dev->hard_header_len);
+		skb_reserve(frag, wdev->hard_header_len);
 		skb_reset_network_header(frag);
 		*mac_cb(frag) = *mac_cb(skb);
 
-		rc = dev_hard_header(frag, real_dev, 0, &master_hdr->dest,
+		rc = dev_hard_header(frag, wdev, 0, &master_hdr->dest,
 				     &master_hdr->source, size);
 		if (rc < 0) {
 			kfree_skb(frag);
@@ -123,7 +122,7 @@ lowpan_xmit_fragment(struct sk_buff *skb, const struct ieee802154_hdr *wpan_hdr,
 }
 
 static int
-lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *dev,
+lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev,
 		       const struct ieee802154_hdr *wpan_hdr)
 {
 	u16 dgram_size, dgram_offset;
@@ -134,8 +133,8 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *dev,
 
 	dgram_size = lowpan_uncompress_size(skb, &dgram_offset) -
 		     skb->mac_len;
-	frag_tag = htons(lowpan_dev_info(dev)->fragment_tag);
-	lowpan_dev_info(dev)->fragment_tag++;
+	frag_tag = htons(lowpan_dev_info(ldev)->fragment_tag);
+	lowpan_dev_info(ldev)->fragment_tag++;
 
 	frag_hdr[0] = LOWPAN_DISPATCH_FRAG1 | ((dgram_size >> 8) & 0x07);
 	frag_hdr[1] = dgram_size & 0xff;
@@ -188,9 +187,9 @@ err:
 	return rc;
 }
 
-static int lowpan_header(struct sk_buff *skb, struct net_device *dev)
+static int lowpan_header(struct sk_buff *skb, struct net_device *ldev)
 {
-	struct wpan_dev *wpan_dev = lowpan_dev_info(dev)->real_dev->ieee802154_ptr;
+	struct wpan_dev *wpan_dev = lowpan_dev_info(ldev)->wdev->ieee802154_ptr;
 	struct ieee802154_addr sa, da;
 	struct ieee802154_mac_cb *cb = mac_cb_init(skb);
 	struct lowpan_addr_info info;
@@ -202,7 +201,7 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *dev)
 	daddr = &info.daddr.u.extended_addr;
 	saddr = &info.saddr.u.extended_addr;
 
-	lowpan_header_compress(skb, dev, ETH_P_IPV6, daddr, saddr, skb->len);
+	lowpan_header_compress(skb, ldev, ETH_P_IPV6, daddr, saddr, skb->len);
 
 	cb->type = IEEE802154_FC_TYPE_DATA;
 
@@ -227,11 +226,11 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *dev)
 		cb->ackreq = wpan_dev->ackreq;
 	}
 
-	return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
-			ETH_P_IPV6, (void *)&da, (void *)&sa, 0);
+	return dev_hard_header(skb, lowpan_dev_info(ldev)->wdev, ETH_P_IPV6,
+			       (void *)&da, (void *)&sa, 0);
 }
 
-netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
+netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
 {
 	struct ieee802154_hdr wpan_hdr;
 	int max_single, ret;
@@ -245,7 +244,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (!skb)
 		return NET_XMIT_DROP;
 
-	ret = lowpan_header(skb, dev);
+	ret = lowpan_header(skb, ldev);
 	if (ret < 0) {
 		kfree_skb(skb);
 		return NET_XMIT_DROP;
@@ -259,13 +258,13 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
 	max_single = ieee802154_max_payload(&wpan_hdr);
 
 	if (skb_tail_pointer(skb) - skb_network_header(skb) <= max_single) {
-		skb->dev = lowpan_dev_info(dev)->real_dev;
+		skb->dev = lowpan_dev_info(ldev)->wdev;
 		return dev_queue_xmit(skb);
 	} else {
 		netdev_tx_t rc;
 
 		pr_debug("frame is too big, fragmentation is needed\n");
-		rc = lowpan_xmit_fragmented(skb, dev, &wpan_hdr);
+		rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr);
 
 		return rc < 0 ? NET_XMIT_DROP : rc;
 	}
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 01/16] ieee802154: 6lowpan: change dev vars to wdev and ldev Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-30 21:48   ` Stefan Schmidt
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 03/16] ieee802154: 6lowpan: remove check on null Alexander Aring
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch moves the open count handling while doing open of a lowpan
interface. We need the packet handler register at first when one lowpan
interface is up.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/core.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index 3cc76f0..8e9da1d 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -76,9 +76,27 @@ static int lowpan_dev_init(struct net_device *ldev)
 	return 0;
 }
 
+static int lowpan_open(struct net_device *dev)
+{
+	if (!open_count)
+		lowpan_rx_init();
+	open_count++;
+	return 0;
+}
+
+static int lowpan_stop(struct net_device *dev)
+{
+	open_count--;
+	if (!open_count)
+		lowpan_rx_exit();
+	return 0;
+}
+
 static const struct net_device_ops lowpan_netdev_ops = {
 	.ndo_init		= lowpan_dev_init,
 	.ndo_start_xmit		= lowpan_xmit,
+	.ndo_open		= lowpan_open,
+	.ndo_stop		= lowpan_stop,
 };
 
 static void lowpan_setup(struct net_device *ldev)
@@ -149,11 +167,6 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
 	}
 
 	wdev->ieee802154_ptr->lowpan_dev = ldev;
-	if (!open_count)
-		lowpan_rx_init();
-
-	open_count++;
-
 	return 0;
 }
 
@@ -163,11 +176,6 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
 
 	ASSERT_RTNL();
 
-	open_count--;
-
-	if (!open_count)
-		lowpan_rx_exit();
-
 	wdev->ieee802154_ptr->lowpan_dev = NULL;
 	unregister_netdevice(ldev);
 	dev_put(wdev);
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 03/16] ieee802154: 6lowpan: remove check on null
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 01/16] ieee802154: 6lowpan: change dev vars to wdev and ldev Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-30 21:49   ` Stefan Schmidt
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 04/16] ieee802154: 6lowpan: remove set to zero Alexander Aring
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch removes one check on null which should be already done by
checking before for ARPHRD_IEEE802154. All ARPHRD_IEEE802154 and
ARPHRD_IEEE802154_MONITOR should have wdev->ieee802154_ptr, where
ARPHRD_IEEE802154 is currently a node interface only.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index 8e9da1d..6607bb4 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -214,7 +214,7 @@ static int lowpan_device_event(struct notifier_block *unused,
 		 * also delete possible lowpan interfaces which belongs
 		 * to the wpan interface.
 		 */
-		if (wdev->ieee802154_ptr && wdev->ieee802154_ptr->lowpan_dev)
+		if (wdev->ieee802154_ptr->lowpan_dev)
 			lowpan_dellink(wdev->ieee802154_ptr->lowpan_dev, NULL);
 		break;
 	default:
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 04/16] ieee802154: 6lowpan: remove set to zero
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (2 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 03/16] ieee802154: 6lowpan: remove check on null Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 05/16] ieee802154: 6lowpan: remove EXPORT_SYMBOL Alexander Aring
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

Internal mechanism by calling netdev_alloc which use kzalloc already
sets these variables to zero. This patch cleanup the setup of net_device.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/core.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index 6607bb4..215d673 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -108,9 +108,7 @@ static void lowpan_setup(struct net_device *ldev)
 	ldev->hard_header_len	= 2 + 1 + 20 + 14;
 	ldev->needed_tailroom	= 2; /* FCS */
 	ldev->mtu		= IPV6_MIN_MTU;
-	ldev->tx_queue_len	= 0;
 	ldev->flags		= IFF_BROADCAST | IFF_MULTICAST;
-	ldev->watchdog_timeo	= 0;
 
 	ldev->netdev_ops	= &lowpan_netdev_ops;
 	ldev->header_ops	= &lowpan_header_ops;
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 05/16] ieee802154: 6lowpan: remove EXPORT_SYMBOL
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (3 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 04/16] ieee802154: 6lowpan: remove set to zero Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 06/16] ieee802154: 6lowpan: change if lowpan dev is running Alexander Aring
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This function is used internally inside of ieee802154 6lowpan module
only and not outside of any other module. We don't need to export this
function then.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/reassembly.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index 60d6df7..0fc3350 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -387,7 +387,6 @@ err:
 	kfree_skb(skb);
 	return -1;
 }
-EXPORT_SYMBOL(lowpan_frag_rcv);
 
 #ifdef CONFIG_SYSCTL
 static int zero;
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 06/16] ieee802154: 6lowpan: change if lowpan dev is running
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (4 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 05/16] ieee802154: 6lowpan: remove EXPORT_SYMBOL Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-30 21:51   ` Stefan Schmidt
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 07/16] ieee802154: 6lowpan: cleanup pull of iphc bytes Alexander Aring
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

We don't need to check if the wpan interface is running because the
lowpan_rcv is the packet layer receive handler for the wpan interface.

Instead doing a check if wpan interface is running we should check if
the lowpan interface is running before starting 6lowpan adaptation layer.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index b1442f3..c529d9f 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -65,19 +65,20 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
 		      struct packet_type *pt, struct net_device *orig_wdev)
 {
 	struct ieee802154_hdr hdr;
+	struct net_device *ldev;
 	int ret;
 
-	if (wdev->type != ARPHRD_IEEE802154 ||
-	    !wdev->ieee802154_ptr->lowpan_dev)
+	if (wdev->type != ARPHRD_IEEE802154)
+		goto drop;
+
+	ldev = wdev->ieee802154_ptr->lowpan_dev;
+	if (!ldev || !netif_running(ldev))
 		goto drop;
 
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (!skb)
 		goto drop;
 
-	if (!netif_running(wdev))
-		goto drop_skb;
-
 	if (skb->pkt_type == PACKET_OTHERHOST)
 		goto drop_skb;
 
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 07/16] ieee802154: 6lowpan: cleanup pull of iphc bytes
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (5 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 06/16] ieee802154: 6lowpan: change if lowpan dev is running Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 08/16] ieee802154: 6lowpan: trivial checks at first Alexander Aring
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch cleanups the pull of the iphc bytes. We don't need to check
if the skb->len contains two bytes, this will be checked by
lowpan_fetch_skb_u8.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index c529d9f..4ddf694 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -33,14 +33,9 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 	void *sap, *dap;
 
 	raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
-	/* at least two bytes will be used for the encoding */
-	if (skb->len < 2)
-		return -EINVAL;
-
-	if (lowpan_fetch_skb_u8(skb, &iphc0))
-		return -EINVAL;
 
-	if (lowpan_fetch_skb_u8(skb, &iphc1))
+	if (lowpan_fetch_skb_u8(skb, &iphc0) ||
+	    lowpan_fetch_skb_u8(skb, &iphc1))
 		return -EINVAL;
 
 	ieee802154_addr_to_sa(&sa, &hdr->source);
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 08/16] ieee802154: 6lowpan: trivial checks at first
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (6 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 07/16] ieee802154: 6lowpan: cleanup pull of iphc bytes Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 09/16] ieee802154: 6lowpan: earlier skb->dev switch Alexander Aring
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch moves some trivial checks at first before calling
skb_share_check which could do some memcpy if the buffer is shared.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index 4ddf694..74d8fec 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -63,7 +63,8 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
 	struct net_device *ldev;
 	int ret;
 
-	if (wdev->type != ARPHRD_IEEE802154)
+	if (wdev->type != ARPHRD_IEEE802154 ||
+	    skb->pkt_type == PACKET_OTHERHOST)
 		goto drop;
 
 	ldev = wdev->ieee802154_ptr->lowpan_dev;
@@ -74,9 +75,6 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
 	if (!skb)
 		goto drop;
 
-	if (skb->pkt_type == PACKET_OTHERHOST)
-		goto drop_skb;
-
 	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
 		goto drop_skb;
 
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 09/16] ieee802154: 6lowpan: earlier skb->dev switch
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (7 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 08/16] ieee802154: 6lowpan: trivial checks at first Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-30 21:54   ` Stefan Schmidt
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework Alexander Aring
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

We should change the skb->dev pointer earlier to the lowpan interface
Sometimes we call iphc_decompress which also use some netdev printout
functionality. This patch will change that the correct interface will be
displayed in this case, which should be the lowpan interface.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index 74d8fec..f9cb70b 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -18,7 +18,6 @@
 static int lowpan_give_skb_to_device(struct sk_buff *skb,
 				     struct net_device *wdev)
 {
-	skb->dev = wdev->ieee802154_ptr->lowpan_dev;
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->pkt_type = PACKET_HOST;
 
@@ -71,9 +70,11 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
 	if (!ldev || !netif_running(ldev))
 		goto drop;
 
+	/* Replacing skb->dev and followed rx handlers will manipulate skb. */
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (!skb)
 		goto drop;
+	skb->dev = ldev;
 
 	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
 		goto drop_skb;
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (8 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 09/16] ieee802154: 6lowpan: earlier skb->dev switch Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-27 17:53   ` Alexander Aring
  2015-08-31  9:28   ` Stefan Schmidt
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 11/16] ieee802154: 6lowpan: add generic lowpan header check Alexander Aring
                   ` (6 subsequent siblings)
  16 siblings, 2 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch complete reworks the evaluation of 6lowpan dispatch value by
introducing a receive handler mechanism for each dispatch value.

A list of changes:

 - Doing uncompression on-the-fly when FRAG1 is received, this require
   some special handling for 802.15.4 lltype in generic 6lowpan branch
   for setting the payload length correct.
 - Fix dispatch mask for fragmentation.
 - Add IPv6 dispatch evaluation for FRAG1.
 - Add skb_unshare for dispatch which might manipulate the skb data
   buffer.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 include/net/6lowpan.h               |  31 ++++--
 net/6lowpan/iphc.c                  |  13 ++-
 net/6lowpan/nhc_udp.c               |  13 ++-
 net/ieee802154/6lowpan/6lowpan_i.h  |  12 +++
 net/ieee802154/6lowpan/reassembly.c | 126 +++++++++++++++++-------
 net/ieee802154/6lowpan/rx.c         | 188 ++++++++++++++++++++++++------------
 6 files changed, 278 insertions(+), 105 deletions(-)

diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index a2f59ec..3509841 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -126,13 +126,19 @@
 	 (((a)[6]) == 0xFF) &&	\
 	 (((a)[7]) == 0xFF))
 
-#define LOWPAN_DISPATCH_IPV6	0x41 /* 01000001 = 65 */
-#define LOWPAN_DISPATCH_HC1	0x42 /* 01000010 = 66 */
-#define LOWPAN_DISPATCH_IPHC	0x60 /* 011xxxxx = ... */
-#define LOWPAN_DISPATCH_FRAG1	0xc0 /* 11000xxx */
-#define LOWPAN_DISPATCH_FRAGN	0xe0 /* 11100xxx */
+#define LOWPAN_DISPATCH_IPV6		0x41 /* 01000001 = 65 */
+#define LOWPAN_DISPATCH_IPHC		0x60 /* 011xxxxx = ... */
+#define LOWPAN_DISPATCH_IPHC_MASK	0xe0
 
-#define LOWPAN_DISPATCH_MASK	0xf8 /* 11111000 */
+static inline bool lowpan_is_ipv6(u8 dispatch)
+{
+	return dispatch == LOWPAN_DISPATCH_IPV6;
+}
+
+static inline bool lowpan_is_iphc(u8 dispatch)
+{
+	return (dispatch & LOWPAN_DISPATCH_IPHC_MASK) == LOWPAN_DISPATCH_IPHC;
+}
 
 #define LOWPAN_FRAG_TIMEOUT	(HZ * 60)	/* time-out 60 sec */
 
@@ -218,6 +224,19 @@ struct lowpan_priv *lowpan_priv(const struct net_device *dev)
 	return netdev_priv(dev);
 }
 
+struct lowpan_802154_cb {
+	u16 d_tag;
+	unsigned int d_size;
+	u8 d_offset;
+};
+
+static inline
+struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(struct lowpan_802154_cb) > sizeof(skb->cb));
+	return (struct lowpan_802154_cb *)skb->cb;
+}
+
 #ifdef DEBUG
 /* print data in line */
 static inline void raw_dump_inline(const char *caller, char *msg,
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 1e0071f..78c8a49 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -366,7 +366,18 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
 			return err;
 	}
 
-	hdr.payload_len = htons(skb->len);
+	switch (lowpan_priv(dev)->lltype) {
+	case LOWPAN_LLTYPE_IEEE802154:
+		if (lowpan_802154_cb(skb)->d_size)
+			hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size -
+						sizeof(struct ipv6hdr));
+		else
+			hdr.payload_len = htons(skb->len);
+		break;
+	default:
+		hdr.payload_len = htons(skb->len);
+		break;
+	}
 
 	pr_debug("skb headroom size = %d, data length = %d\n",
 		 skb_headroom(skb), skb->len);
diff --git a/net/6lowpan/nhc_udp.c b/net/6lowpan/nhc_udp.c
index c6bcaeb..72d0b57 100644
--- a/net/6lowpan/nhc_udp.c
+++ b/net/6lowpan/nhc_udp.c
@@ -71,7 +71,18 @@ static int udp_uncompress(struct sk_buff *skb, size_t needed)
 	 * here, we obtain the hint from the remaining size of the
 	 * frame
 	 */
-	uh.len = htons(skb->len + sizeof(struct udphdr));
+	switch (lowpan_priv(skb->dev)->lltype) {
+	case LOWPAN_LLTYPE_IEEE802154:
+		if (lowpan_802154_cb(skb)->d_size)
+			uh.len = htons(lowpan_802154_cb(skb)->d_size -
+				       sizeof(struct ipv6hdr));
+		else
+			uh.len = htons(skb->len + sizeof(struct udphdr));
+		break;
+	default:
+		uh.len = htons(skb->len + sizeof(struct udphdr));
+		break;
+	}
 	pr_debug("uncompressed UDP length: src = %d", ntohs(uh.len));
 
 	/* replace the compressed UDP head by the uncompressed UDP
diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h
index 9aa7b62..b4e17a7 100644
--- a/net/ieee802154/6lowpan/6lowpan_i.h
+++ b/net/ieee802154/6lowpan/6lowpan_i.h
@@ -7,6 +7,15 @@
 #include <net/inet_frag.h>
 #include <net/6lowpan.h>
 
+typedef unsigned __bitwise__ lowpan_rx_result;
+#define RX_CONTINUE		((__force lowpan_rx_result) 0u)
+#define RX_DROP_UNUSABLE	((__force lowpan_rx_result) 1u)
+#define RX_DROP			((__force lowpan_rx_result) 2u)
+#define RX_QUEUED		((__force lowpan_rx_result) 3u)
+
+#define LOWPAN_DISPATCH_FRAG1           0xc0
+#define LOWPAN_DISPATCH_FRAGN           0xe0
+
 struct lowpan_create_arg {
 	u16 tag;
 	u16 d_size;
@@ -62,4 +71,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
 			 const void *_saddr, unsigned int len);
 netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev);
 
+int lowpan_iphc_decompress(struct sk_buff *skb);
+lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb);
+
 #endif /* __IEEE802154_6LOWPAN_I_H__ */
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index 0fc3350..fadd985 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -32,17 +32,6 @@
 
 static const char lowpan_frags_cache_name[] = "lowpan-frags";
 
-struct lowpan_frag_info {
-	u16 d_tag;
-	u16 d_size;
-	u8 d_offset;
-};
-
-static struct lowpan_frag_info *lowpan_cb(struct sk_buff *skb)
-{
-	return (struct lowpan_frag_info *)skb->cb;
-}
-
 static struct inet_frags lowpan_frags;
 
 static int lowpan_frag_reasm(struct lowpan_frag_queue *fq,
@@ -111,7 +100,7 @@ out:
 }
 
 static inline struct lowpan_frag_queue *
-fq_find(struct net *net, const struct lowpan_frag_info *frag_info,
+fq_find(struct net *net, const struct lowpan_802154_cb *cb,
 	const struct ieee802154_addr *src,
 	const struct ieee802154_addr *dst)
 {
@@ -121,12 +110,12 @@ fq_find(struct net *net, const struct lowpan_frag_info *frag_info,
 	struct netns_ieee802154_lowpan *ieee802154_lowpan =
 		net_ieee802154_lowpan(net);
 
-	arg.tag = frag_info->d_tag;
-	arg.d_size = frag_info->d_size;
+	arg.tag = cb->d_tag;
+	arg.d_size = cb->d_size;
 	arg.src = src;
 	arg.dst = dst;
 
-	hash = lowpan_hash_frag(frag_info->d_tag, frag_info->d_size, src, dst);
+	hash = lowpan_hash_frag(cb->d_tag, cb->d_size, src, dst);
 
 	q = inet_frag_find(&ieee802154_lowpan->frags,
 			   &lowpan_frags, &arg, hash);
@@ -138,7 +127,7 @@ fq_find(struct net *net, const struct lowpan_frag_info *frag_info,
 }
 
 static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
-			     struct sk_buff *skb, const u8 frag_type)
+			     struct sk_buff *skb, u8 frag_type)
 {
 	struct sk_buff *prev, *next;
 	struct net_device *ldev;
@@ -147,8 +136,8 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
 	if (fq->q.flags & INET_FRAG_COMPLETE)
 		goto err;
 
-	offset = lowpan_cb(skb)->d_offset << 3;
-	end = lowpan_cb(skb)->d_size;
+	offset = lowpan_802154_cb(skb)->d_offset << 3;
+	end = lowpan_802154_cb(skb)->d_size;
 
 	/* Is this the final fragment? */
 	if (offset + skb->len == end) {
@@ -174,13 +163,16 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
 	 * this fragment, right?
 	 */
 	prev = fq->q.fragments_tail;
-	if (!prev || lowpan_cb(prev)->d_offset < lowpan_cb(skb)->d_offset) {
+	if (!prev ||
+	    lowpan_802154_cb(prev)->d_offset <
+	    lowpan_802154_cb(skb)->d_offset) {
 		next = NULL;
 		goto found;
 	}
 	prev = NULL;
 	for (next = fq->q.fragments; next != NULL; next = next->next) {
-		if (lowpan_cb(next)->d_offset >= lowpan_cb(skb)->d_offset)
+		if (lowpan_802154_cb(next)->d_offset >=
+		    lowpan_802154_cb(skb)->d_offset)
 			break;	/* bingo! */
 		prev = next;
 	}
@@ -201,8 +193,7 @@ found:
 
 	fq->q.stamp = skb->tstamp;
 	if (frag_type == LOWPAN_DISPATCH_FRAG1) {
-		/* Calculate uncomp. 6lowpan header to estimate full size */
-		fq->q.meat += lowpan_uncompress_size(skb, NULL);
+		fq->q.meat += skb->len;
 		fq->q.flags |= INET_FRAG_FIRST_IN;
 	} else {
 		fq->q.meat += skb->len;
@@ -325,8 +316,59 @@ out_oom:
 	return -1;
 }
 
-static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
-				struct lowpan_frag_info *frag_info)
+int lowpan_frag_rx_handlers_result(struct sk_buff *skb, lowpan_rx_result res)
+{
+	switch (res) {
+	case RX_QUEUED:
+		return NET_RX_SUCCESS;
+	case RX_CONTINUE:
+		/* nobody cared about this packet */
+		net_warn_ratelimited("%s: received unknown dispatch\n",
+				     __func__);
+
+		/* fall-through */
+	default:
+		/* all others failure */
+		return NET_RX_DROP;
+	}
+}
+
+static lowpan_rx_result lowpan_frag_rx_h_iphc(struct sk_buff *skb)
+{
+	int ret;
+
+	if (!lowpan_is_iphc(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	ret = lowpan_iphc_decompress(skb);
+	if (ret < 0)
+		return RX_DROP;
+
+	return RX_QUEUED;
+}
+
+static int lowpan_invoke_frag_rx_handlers(struct sk_buff *skb)
+{
+	lowpan_rx_result res;
+
+#define CALL_RXH(rxh)			\
+	do {				\
+		res = rxh(skb);	\
+		if (res != RX_CONTINUE)	\
+			goto rxh_next;	\
+	} while (0)
+
+	/* likely at first */
+	CALL_RXH(lowpan_frag_rx_h_iphc);
+	CALL_RXH(lowpan_rx_h_ipv6);
+
+rxh_next:
+	return lowpan_frag_rx_handlers_result(skb, res);
+#undef CALL_RXH
+}
+
+static int lowpan_get_cb(struct sk_buff *skb, u8 frag_type,
+			 struct lowpan_802154_cb *cb)
 {
 	bool fail;
 	u8 pattern = 0, low = 0;
@@ -334,15 +376,19 @@ static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
 
 	fail = lowpan_fetch_skb(skb, &pattern, 1);
 	fail |= lowpan_fetch_skb(skb, &low, 1);
-	frag_info->d_size = (pattern & 7) << 8 | low;
+	cb->d_size = (pattern & 7) << 8 | low;
 	fail |= lowpan_fetch_skb(skb, &d_tag, 2);
-	frag_info->d_tag = ntohs(d_tag);
+	cb->d_tag = ntohs(d_tag);
 
 	if (frag_type == LOWPAN_DISPATCH_FRAGN) {
-		fail |= lowpan_fetch_skb(skb, &frag_info->d_offset, 1);
+		fail |= lowpan_fetch_skb(skb, &cb->d_offset, 1);
 	} else {
 		skb_reset_network_header(skb);
-		frag_info->d_offset = 0;
+		cb->d_offset = 0;
+		/* check if datagram_size has ipv6hdr on FRAG1 */
+		fail |= cb->d_size < sizeof(struct ipv6hdr);
+		/* check if we can dereference the dispatch value */
+		fail |= !skb->len;
 	}
 
 	if (unlikely(fail))
@@ -351,27 +397,35 @@ static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
 	return 0;
 }
 
-int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
+int lowpan_frag_rcv(struct sk_buff *skb, u8 frag_type)
 {
 	struct lowpan_frag_queue *fq;
 	struct net *net = dev_net(skb->dev);
-	struct lowpan_frag_info *frag_info = lowpan_cb(skb);
-	struct ieee802154_addr source, dest;
+	struct lowpan_802154_cb *cb = lowpan_802154_cb(skb);
+	struct ieee802154_hdr hdr;
 	int err;
 
-	source = mac_cb(skb)->source;
-	dest = mac_cb(skb)->dest;
+	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
+		goto err;
 
-	err = lowpan_get_frag_info(skb, frag_type, frag_info);
+	err = lowpan_get_cb(skb, frag_type, cb);
 	if (err < 0)
 		goto err;
 
-	if (frag_info->d_size > IPV6_MIN_MTU) {
+	if (frag_type == LOWPAN_DISPATCH_FRAG1) {
+		lowpan_rx_result res;
+
+		res = lowpan_invoke_frag_rx_handlers(skb);
+		if (res == NET_RX_DROP)
+			goto err;
+	}
+
+	if (cb->d_size > IPV6_MIN_MTU) {
 		net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n");
 		goto err;
 	}
 
-	fq = fq_find(net, frag_info, &source, &dest);
+	fq = fq_find(net, cb, &hdr.source, &hdr.dest);
 	if (fq != NULL) {
 		int ret;
 
diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index f9cb70b..2adc92a 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -15,8 +15,9 @@
 
 #include "6lowpan_i.h"
 
-static int lowpan_give_skb_to_device(struct sk_buff *skb,
-				     struct net_device *wdev)
+#define LOWPAN_DISPATCH_FRAG_MASK	0xf8
+
+static int lowpan_give_skb_to_device(struct sk_buff *skb)
 {
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->pkt_type = PACKET_HOST;
@@ -24,21 +25,77 @@ static int lowpan_give_skb_to_device(struct sk_buff *skb,
 	return netif_rx(skb);
 }
 
-static int
-iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
+int lowpan_rx_handlers_result(struct sk_buff *skb, lowpan_rx_result res)
+{
+	switch (res) {
+	case RX_CONTINUE:
+		/* nobody cared about this packet */
+		net_warn_ratelimited("%s: received unknown dispatch\n",
+				     __func__);
+
+		/* fall-through */
+	case RX_DROP_UNUSABLE:
+		kfree_skb(skb);
+
+		/* fall-through */
+	case RX_DROP:
+		return NET_RX_DROP;
+	case RX_QUEUED:
+		return lowpan_give_skb_to_device(skb);
+	default:
+		break;
+	}
+
+	return NET_RX_DROP;
+}
+
+static inline bool lowpan_is_frag1(u8 dispatch)
+{
+	return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAG1;
+}
+
+static inline bool lowpan_is_fragn(u8 dispatch)
+{
+	return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAGN;
+}
+
+static lowpan_rx_result lowpan_rx_h_frag(struct sk_buff *skb)
+{
+	int ret;
+
+	if (!(lowpan_is_frag1(*skb_network_header(skb)) ||
+	      lowpan_is_fragn(*skb_network_header(skb))))
+		return RX_CONTINUE;
+
+	ret = lowpan_frag_rcv(skb, *skb_network_header(skb) &
+			      LOWPAN_DISPATCH_FRAG_MASK);
+	if (ret == 1)
+		return RX_QUEUED;
+
+	/* Packet is freed by lowpan_frag_rcv on error or put into the frag
+	 * bucket.
+	 */
+	return RX_DROP;
+}
+
+int lowpan_iphc_decompress(struct sk_buff *skb)
 {
-	u8 iphc0, iphc1;
 	struct ieee802154_addr_sa sa, da;
+	struct ieee802154_hdr hdr;
+	u8 iphc0, iphc1;
 	void *sap, *dap;
 
+	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
+		return -EINVAL;
+
 	raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
 
 	if (lowpan_fetch_skb_u8(skb, &iphc0) ||
 	    lowpan_fetch_skb_u8(skb, &iphc1))
 		return -EINVAL;
 
-	ieee802154_addr_to_sa(&sa, &hdr->source);
-	ieee802154_addr_to_sa(&da, &hdr->dest);
+	ieee802154_addr_to_sa(&sa, &hdr.source);
+	ieee802154_addr_to_sa(&da, &hdr.dest);
 
 	if (sa.addr_type == IEEE802154_ADDR_SHORT)
 		sap = &sa.short_addr;
@@ -55,78 +112,87 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 					IEEE802154_ADDR_LEN, iphc0, iphc1);
 }
 
+static lowpan_rx_result lowpan_rx_h_iphc(struct sk_buff *skb)
+{
+	int ret;
+
+	if (!lowpan_is_iphc(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	/* Setting datagram_offset to zero indicates non frag handling
+	 * while doing lowpan_header_decompress.
+	 */
+	lowpan_802154_cb(skb)->d_size = 0;
+
+	ret = lowpan_iphc_decompress(skb);
+	if (ret < 0)
+		return RX_DROP_UNUSABLE;
+
+	return RX_QUEUED;
+}
+
+lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb)
+{
+	if (!lowpan_is_ipv6(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	/* Pull off the 1-byte of 6lowpan header. */
+	skb_pull(skb, 1);
+	return RX_QUEUED;
+}
+
+static int lowpan_invoke_rx_handlers(struct sk_buff *skb)
+{
+	lowpan_rx_result res;
+
+#define CALL_RXH(rxh)			\
+	do {				\
+		res = rxh(skb);	\
+		if (res != RX_CONTINUE)	\
+			goto rxh_next;	\
+	} while (0)
+
+	/* likely at first */
+	CALL_RXH(lowpan_rx_h_iphc);
+	CALL_RXH(lowpan_rx_h_frag);
+	CALL_RXH(lowpan_rx_h_ipv6);
+
+rxh_next:
+	return lowpan_rx_handlers_result(skb, res);
+#undef CALL_RXH
+}
+
 static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
 		      struct packet_type *pt, struct net_device *orig_wdev)
 {
-	struct ieee802154_hdr hdr;
 	struct net_device *ldev;
-	int ret;
 
 	if (wdev->type != ARPHRD_IEEE802154 ||
 	    skb->pkt_type == PACKET_OTHERHOST)
-		goto drop;
+		return NET_RX_DROP;
 
 	ldev = wdev->ieee802154_ptr->lowpan_dev;
 	if (!ldev || !netif_running(ldev))
-		goto drop;
+		return NET_RX_DROP;
 
 	/* Replacing skb->dev and followed rx handlers will manipulate skb. */
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (!skb)
-		goto drop;
+		return NET_RX_DROP;
 	skb->dev = ldev;
 
-	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
-		goto drop_skb;
-
-	/* check that it's our buffer */
-	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
-		/* Pull off the 1-byte of 6lowpan header. */
-		skb_pull(skb, 1);
-		return lowpan_give_skb_to_device(skb, wdev);
-	} else {
-		switch (skb->data[0] & 0xe0) {
-		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
-			ret = iphc_decompress(skb, &hdr);
-			if (ret < 0)
-				goto drop_skb;
-
-			return lowpan_give_skb_to_device(skb, wdev);
-		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
-			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
-			if (ret == 1) {
-				ret = iphc_decompress(skb, &hdr);
-				if (ret < 0)
-					goto drop_skb;
-
-				return lowpan_give_skb_to_device(skb, wdev);
-			} else if (ret == -1) {
-				return NET_RX_DROP;
-			} else {
-				return NET_RX_SUCCESS;
-			}
-		case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
-			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
-			if (ret == 1) {
-				ret = iphc_decompress(skb, &hdr);
-				if (ret < 0)
-					goto drop_skb;
-
-				return lowpan_give_skb_to_device(skb, wdev);
-			} else if (ret == -1) {
-				return NET_RX_DROP;
-			} else {
-				return NET_RX_SUCCESS;
-			}
-		default:
-			break;
-		}
+	/* When receive frag1 it's likely that we manipulate the buffer.
+	 * When recevie iphc we manipulate the data buffer. So we need
+	 * to unshare the buffer.
+	 */
+	if (lowpan_is_frag1(*skb_network_header(skb)) ||
+	    lowpan_is_iphc(*skb_network_header(skb))) {
+		skb = skb_unshare(skb, GFP_ATOMIC);
+		if (!skb)
+			return RX_DROP;
 	}
 
-drop_skb:
-	kfree_skb(skb);
-drop:
-	return NET_RX_DROP;
+	return lowpan_invoke_rx_handlers(skb);
 }
 
 static struct packet_type lowpan_packet_type = {
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 11/16] ieee802154: 6lowpan: add generic lowpan header check
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (9 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 12/16] ieee802154: 6lowpan: add handler for all dispatch values Alexander Aring
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch introduce an earlier check if a 6LoWPAN frame can be valid.
This contains at first for checking if the header contains a dispatch
byte and isn't the nalp dispatch value, which means it isn't a 6LoWPAN
packet. Also we add a check if we can derference the dispatch value by
checking if skb->len is unequal zero.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index 2adc92a..c13763e 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -15,8 +15,11 @@
 
 #include "6lowpan_i.h"
 
+#define LOWPAN_DISPATCH_FIRST		0xc0
 #define LOWPAN_DISPATCH_FRAG_MASK	0xf8
 
+#define LOWPAN_DISPATCH_NALP		0x00
+
 static int lowpan_give_skb_to_device(struct sk_buff *skb)
 {
 	skb->protocol = htons(ETH_P_IPV6);
@@ -162,13 +165,36 @@ rxh_next:
 #undef CALL_RXH
 }
 
+static inline bool lowpan_is_nalp(u8 dispatch)
+{
+	return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_NALP;
+}
+
+/* lowpan_rx_h_check checks on generic 6LoWPAN requirements
+ * in MAC and 6LoWPAN header.
+ *
+ * Don't manipulate the skb here, it could be shared buffer.
+ */
+static inline bool lowpan_rx_h_check(struct sk_buff *skb)
+{
+	/* check if we can dereference the dispatch */
+	if (unlikely(!skb->len))
+		return false;
+
+	if (lowpan_is_nalp(*skb_network_header(skb)))
+		return false;
+
+	return true;
+}
+
 static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
 		      struct packet_type *pt, struct net_device *orig_wdev)
 {
 	struct net_device *ldev;
 
 	if (wdev->type != ARPHRD_IEEE802154 ||
-	    skb->pkt_type == PACKET_OTHERHOST)
+	    skb->pkt_type == PACKET_OTHERHOST ||
+	    !lowpan_rx_h_check(skb))
 		return NET_RX_DROP;
 
 	ldev = wdev->ieee802154_ptr->lowpan_dev;
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 12/16] ieee802154: 6lowpan: add handler for all dispatch values
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (10 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 11/16] ieee802154: 6lowpan: add generic lowpan header check Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch Alexander Aring
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch adds dummy handlers for all known IEEE 802.15.4 dispatch
values which prints a warning that we don't support these dispatches
right now. Also we add a warning to the RX_CONTINUE case inside of
lowpan_rx_handlers_result which should now never happend.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 90 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index c13763e..d309d91 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -19,6 +19,11 @@
 #define LOWPAN_DISPATCH_FRAG_MASK	0xf8
 
 #define LOWPAN_DISPATCH_NALP		0x00
+#define LOWPAN_DISPATCH_ESC		0x7f
+#define LOWPAN_DISPATCH_HC1		0x42
+#define LOWPAN_DISPATCH_DFF		0x43
+#define LOWPAN_DISPATCH_BC0		0x50
+#define LOWPAN_DISPATCH_MESH		0x80
 
 static int lowpan_give_skb_to_device(struct sk_buff *skb)
 {
@@ -144,6 +149,86 @@ lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb)
 	return RX_QUEUED;
 }
 
+static inline bool lowpan_is_esc(u8 dispatch)
+{
+	return dispatch == LOWPAN_DISPATCH_ESC;
+}
+
+static lowpan_rx_result lowpan_rx_h_esc(struct sk_buff *skb)
+{
+	if (!lowpan_is_esc(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	net_warn_ratelimited("%s: %s\n", skb->dev->name,
+			     "6LoWPAN ESC not supported\n");
+
+	return RX_DROP_UNUSABLE;
+}
+
+static inline bool lowpan_is_hc1(u8 dispatch)
+{
+	return dispatch == LOWPAN_DISPATCH_HC1;
+}
+
+static lowpan_rx_result lowpan_rx_h_hc1(struct sk_buff *skb)
+{
+	if (!lowpan_is_hc1(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	net_warn_ratelimited("%s: %s\n", skb->dev->name,
+			     "6LoWPAN HC1 not supported\n");
+
+	return RX_DROP_UNUSABLE;
+}
+
+static inline bool lowpan_is_dff(u8 dispatch)
+{
+	return dispatch == LOWPAN_DISPATCH_DFF;
+}
+
+static lowpan_rx_result lowpan_rx_h_dff(struct sk_buff *skb)
+{
+	if (!lowpan_is_dff(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	net_warn_ratelimited("%s: %s\n", skb->dev->name,
+			     "6LoWPAN DFF not supported\n");
+
+	return RX_DROP_UNUSABLE;
+}
+
+static inline bool lowpan_is_bc0(u8 dispatch)
+{
+	return dispatch == LOWPAN_DISPATCH_BC0;
+}
+
+static lowpan_rx_result lowpan_rx_h_bc0(struct sk_buff *skb)
+{
+	if (!lowpan_is_bc0(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	net_warn_ratelimited("%s: %s\n", skb->dev->name,
+			     "6LoWPAN BC0 not supported\n");
+
+	return RX_DROP_UNUSABLE;
+}
+
+static inline bool lowpan_is_mesh(u8 dispatch)
+{
+	return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_MESH;
+}
+
+static lowpan_rx_result lowpan_rx_h_mesh(struct sk_buff *skb)
+{
+	if (!lowpan_is_mesh(*skb_network_header(skb)))
+		return RX_CONTINUE;
+
+	net_warn_ratelimited("%s: %s\n", skb->dev->name,
+			     "6LoWPAN MESH not supported\n");
+
+	return RX_DROP_UNUSABLE;
+}
+
 static int lowpan_invoke_rx_handlers(struct sk_buff *skb)
 {
 	lowpan_rx_result res;
@@ -159,6 +244,11 @@ static int lowpan_invoke_rx_handlers(struct sk_buff *skb)
 	CALL_RXH(lowpan_rx_h_iphc);
 	CALL_RXH(lowpan_rx_h_frag);
 	CALL_RXH(lowpan_rx_h_ipv6);
+	CALL_RXH(lowpan_rx_h_esc);
+	CALL_RXH(lowpan_rx_h_hc1);
+	CALL_RXH(lowpan_rx_h_dff);
+	CALL_RXH(lowpan_rx_h_bc0);
+	CALL_RXH(lowpan_rx_h_mesh);
 
 rxh_next:
 	return lowpan_rx_handlers_result(skb, res);
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (11 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 12/16] ieee802154: 6lowpan: add handler for all dispatch values Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-30 22:00   ` Stefan Schmidt
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 14/16] ieee802154: 6lowpan: check on valid 802.15.4 frame Alexander Aring
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch adds checks for reserved dispatch value. When we have a
reserved dispatch value we should drop the skb immediately.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index d309d91..f98ebf5 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -260,6 +260,17 @@ static inline bool lowpan_is_nalp(u8 dispatch)
 	return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_NALP;
 }
 
+/* Lookup for reserved dispatch values at:
+ * https://www.iana.org/assignments/_6lowpan-parameters/_6lowpan-parameters.xhtml#_6lowpan-parameters-1
+ */
+static inline bool lowpan_is_reserved(u8 dispatch)
+{
+	return ((dispatch >= 0x44 && dispatch <= 0x4F) ||
+		(dispatch >= 0x51 && dispatch <= 0x5F) ||
+		(dispatch >= 0xc8 && dispatch <= 0xdf) ||
+		(dispatch >= 0xe8 && dispatch <= 0xff));
+}
+
 /* lowpan_rx_h_check checks on generic 6LoWPAN requirements
  * in MAC and 6LoWPAN header.
  *
@@ -271,7 +282,8 @@ static inline bool lowpan_rx_h_check(struct sk_buff *skb)
 	if (unlikely(!skb->len))
 		return false;
 
-	if (lowpan_is_nalp(*skb_network_header(skb)))
+	if (lowpan_is_nalp(*skb_network_header(skb)) ||
+	    lowpan_is_reserved(*skb_network_header(skb)))
 		return false;
 
 	return true;
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 14/16] ieee802154: 6lowpan: check on valid 802.15.4 frame
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (12 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-30 22:03   ` Stefan Schmidt
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 15/16] ieee802154: 6lowpan: remove packet type to host Alexander Aring
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch adds frame control checks to check if the received frame is
something which could contain a 6LoWPAN packet.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 include/linux/ieee802154.h  | 25 +++++++++++++++++++++++++
 include/net/mac802154.h     | 15 +++++++++++++++
 net/ieee802154/6lowpan/rx.c |  8 ++++++++
 3 files changed, 48 insertions(+)

diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
index 1dc1f4e..db01492 100644
--- a/include/linux/ieee802154.h
+++ b/include/linux/ieee802154.h
@@ -205,6 +205,31 @@ enum {
 	IEEE802154_SCAN_IN_PROGRESS = 0xfc,
 };
 
+/* frame control handling */
+#define IEEE802154_FCTL_FTYPE		0x0003
+#define IEEE802154_FCTL_INTRA_PAN	0x0040
+
+#define IEEE802154_FTYPE_DATA		0x0001
+
+/*
+ * ieee802154_is_data - check if type is IEEE802154_FTYPE_DATA
+ * @fc: frame control bytes in little-endian byteorder
+ */
+static inline int ieee802154_is_data(__le16 fc)
+{
+	return (fc & cpu_to_le16(IEEE802154_FCTL_FTYPE)) ==
+		cpu_to_le16(IEEE802154_FTYPE_DATA);
+}
+
+/**
+ * ieee802154_is_intra_pan - check if intra pan id communication
+ * @fc: frame control bytes in little-endian byteorder
+ */
+static inline bool ieee802154_is_intra_pan(__le16 fc)
+{
+	return fc & cpu_to_le16(IEEE802154_FCTL_INTRA_PAN);
+}
+
 /**
  * ieee802154_is_valid_psdu_len - check if psdu len is valid
  * available lengths:
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index b7f9961..32bd7c0 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -250,6 +250,21 @@ struct ieee802154_ops {
 };
 
 /**
+ * ieee802154_get_fc_from_skb - get the frame control field from an skb
+ * @skb: skb where the frame control field will be get from
+ */
+static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb)
+{
+	/* return some invalid fc on failure */
+	if (unlikely(skb->mac_len < 2)) {
+		WARN_ON(1);
+		return cpu_to_le16(0);
+	}
+
+	return (__force __le16)__get_unaligned_memmove16(skb_mac_header(skb));
+}
+
+/**
  * ieee802154_be64_to_le64 - copies and convert be64 to le64
  * @le64_dst: le64 destination pointer
  * @be64_src: be64 source pointer
diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index f98ebf5..5be996a 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -11,6 +11,7 @@
 #include <linux/if_arp.h>
 
 #include <net/6lowpan.h>
+#include <net/mac802154.h>
 #include <net/ieee802154_netdev.h>
 
 #include "6lowpan_i.h"
@@ -278,6 +279,13 @@ static inline bool lowpan_is_reserved(u8 dispatch)
  */
 static inline bool lowpan_rx_h_check(struct sk_buff *skb)
 {
+	__le16 fc = ieee802154_get_fc_from_skb(skb);
+
+	/* check on ieee802154 conform 6LoWPAN header */
+	if (!ieee802154_is_data(fc) ||
+	    !ieee802154_is_intra_pan(fc))
+		return false;
+
 	/* check if we can dereference the dispatch */
 	if (unlikely(!skb->len))
 		return false;
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 15/16] ieee802154: 6lowpan: remove packet type to host
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (13 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 14/16] ieee802154: 6lowpan: check on valid 802.15.4 frame Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 16/16] ieee802154: 6lowpan: remove tx full-size calc workaround Alexander Aring
  2015-08-30 21:45 ` [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Stefan Schmidt
  16 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch remove the packet_type to host and leave the mac pkt_type.
By running 'grep -r "pkt_type" net/ipv6', the IPv6 stack will evaluate
this value for PACKET_BROADCAST. Instead of overwriting this value we
will leave the mac value there which is broadcasts if the mac frame was
a broadcast frame.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan/rx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index 5be996a..1a9c6ed 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -29,7 +29,6 @@
 static int lowpan_give_skb_to_device(struct sk_buff *skb)
 {
 	skb->protocol = htons(ETH_P_IPV6);
-	skb->pkt_type = PACKET_HOST;
 
 	return netif_rx(skb);
 }
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFCv2 bluetooth-next 16/16] ieee802154: 6lowpan: remove tx full-size calc workaround
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (14 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 15/16] ieee802154: 6lowpan: remove packet type to host Alexander Aring
@ 2015-08-20 16:47 ` Alexander Aring
  2015-08-30 22:06   ` Stefan Schmidt
  2015-08-30 21:45 ` [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Stefan Schmidt
  16 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-08-20 16:47 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

This patch removes a workaround for datagram_size calculation while
doing fragmentation on transmit.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 include/net/6lowpan.h       | 113 --------------------------------------------
 net/ieee802154/6lowpan/tx.c |  18 ++++---
 2 files changed, 11 insertions(+), 120 deletions(-)

diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index 3509841..eeae5eb 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -299,119 +299,6 @@ static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
 	*hc_ptr += len;
 }
 
-static inline u8 lowpan_addr_mode_size(const u8 addr_mode)
-{
-	static const u8 addr_sizes[] = {
-		[LOWPAN_IPHC_ADDR_00] = 16,
-		[LOWPAN_IPHC_ADDR_01] = 8,
-		[LOWPAN_IPHC_ADDR_02] = 2,
-		[LOWPAN_IPHC_ADDR_03] = 0,
-	};
-	return addr_sizes[addr_mode];
-}
-
-static inline u8 lowpan_next_hdr_size(const u8 h_enc, u16 *uncomp_header)
-{
-	u8 ret = 1;
-
-	if ((h_enc & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
-		*uncomp_header += sizeof(struct udphdr);
-
-		switch (h_enc & LOWPAN_NHC_UDP_CS_P_11) {
-		case LOWPAN_NHC_UDP_CS_P_00:
-			ret += 4;
-			break;
-		case LOWPAN_NHC_UDP_CS_P_01:
-		case LOWPAN_NHC_UDP_CS_P_10:
-			ret += 3;
-			break;
-		case LOWPAN_NHC_UDP_CS_P_11:
-			ret++;
-			break;
-		default:
-			break;
-		}
-
-		if (!(h_enc & LOWPAN_NHC_UDP_CS_C))
-			ret += 2;
-	}
-
-	return ret;
-}
-
-/**
- *	lowpan_uncompress_size - returns skb->len size with uncompressed header
- *	@skb: sk_buff with 6lowpan header inside
- *	@datagram_offset: optional to get the datagram_offset value
- *
- *	Returns the skb->len with uncompressed header
- */
-static inline u16
-lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
-{
-	u16 ret = 2, uncomp_header = sizeof(struct ipv6hdr);
-	u8 iphc0, iphc1, h_enc;
-
-	iphc0 = skb_network_header(skb)[0];
-	iphc1 = skb_network_header(skb)[1];
-
-	switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
-	case 0:
-		ret += 4;
-		break;
-	case 1:
-		ret += 3;
-		break;
-	case 2:
-		ret++;
-		break;
-	default:
-		break;
-	}
-
-	if (!(iphc0 & LOWPAN_IPHC_NH_C))
-		ret++;
-
-	if (!(iphc0 & 0x03))
-		ret++;
-
-	ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_SAM) >>
-				     LOWPAN_IPHC_SAM_BIT);
-
-	if (iphc1 & LOWPAN_IPHC_M) {
-		switch ((iphc1 & LOWPAN_IPHC_DAM_11) >>
-			LOWPAN_IPHC_DAM_BIT) {
-		case LOWPAN_IPHC_DAM_00:
-			ret += 16;
-			break;
-		case LOWPAN_IPHC_DAM_01:
-			ret += 6;
-			break;
-		case LOWPAN_IPHC_DAM_10:
-			ret += 4;
-			break;
-		case LOWPAN_IPHC_DAM_11:
-			ret++;
-			break;
-		default:
-			break;
-		}
-	} else {
-		ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_DAM_11) >>
-					     LOWPAN_IPHC_DAM_BIT);
-	}
-
-	if (iphc0 & LOWPAN_IPHC_NH_C) {
-		h_enc = skb_network_header(skb)[ret];
-		ret += lowpan_next_hdr_size(h_enc, &uncomp_header);
-	}
-
-	if (dgram_offset)
-		*dgram_offset = uncomp_header;
-
-	return skb->len + uncomp_header - ret;
-}
-
 void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype);
 
 int
diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
index 9a2147e..4115335 100644
--- a/net/ieee802154/6lowpan/tx.c
+++ b/net/ieee802154/6lowpan/tx.c
@@ -123,16 +123,14 @@ lowpan_xmit_fragment(struct sk_buff *skb, const struct ieee802154_hdr *wpan_hdr,
 
 static int
 lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev,
-		       const struct ieee802154_hdr *wpan_hdr)
+		       const struct ieee802154_hdr *wpan_hdr, u16 dgram_size,
+		       u16 dgram_offset)
 {
-	u16 dgram_size, dgram_offset;
 	__be16 frag_tag;
 	u8 frag_hdr[5];
 	int frag_cap, frag_len, payload_cap, rc;
 	int skb_unprocessed, skb_offset;
 
-	dgram_size = lowpan_uncompress_size(skb, &dgram_offset) -
-		     skb->mac_len;
 	frag_tag = htons(lowpan_dev_info(ldev)->fragment_tag);
 	lowpan_dev_info(ldev)->fragment_tag++;
 
@@ -187,7 +185,8 @@ err:
 	return rc;
 }
 
-static int lowpan_header(struct sk_buff *skb, struct net_device *ldev)
+static int lowpan_header(struct sk_buff *skb, struct net_device *ldev,
+			 u16 *dgram_size, u16 *dgram_offset)
 {
 	struct wpan_dev *wpan_dev = lowpan_dev_info(ldev)->wdev->ieee802154_ptr;
 	struct ieee802154_addr sa, da;
@@ -201,7 +200,10 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *ldev)
 	daddr = &info.daddr.u.extended_addr;
 	saddr = &info.saddr.u.extended_addr;
 
+	*dgram_size = skb->len;
 	lowpan_header_compress(skb, ldev, ETH_P_IPV6, daddr, saddr, skb->len);
+	/* dgram_size = (saved bytes after compression) + lowpan header size */
+	*dgram_offset = (*dgram_size - skb->len) + skb_network_header_len(skb);
 
 	cb->type = IEEE802154_FC_TYPE_DATA;
 
@@ -234,6 +236,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
 {
 	struct ieee802154_hdr wpan_hdr;
 	int max_single, ret;
+	u16 dgram_size, dgram_offset;
 
 	pr_debug("package xmit\n");
 
@@ -244,7 +247,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
 	if (!skb)
 		return NET_XMIT_DROP;
 
-	ret = lowpan_header(skb, ldev);
+	ret = lowpan_header(skb, ldev, &dgram_size, &dgram_offset);
 	if (ret < 0) {
 		kfree_skb(skb);
 		return NET_XMIT_DROP;
@@ -264,7 +267,8 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
 		netdev_tx_t rc;
 
 		pr_debug("frame is too big, fragmentation is needed\n");
-		rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr);
+		rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr, dgram_size,
+					    dgram_offset);
 
 		return rc < 0 ? NET_XMIT_DROP : rc;
 	}
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework Alexander Aring
@ 2015-08-27 17:53   ` Alexander Aring
  2015-08-31  9:28   ` Stefan Schmidt
  1 sibling, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-08-27 17:53 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel

On Thu, Aug 20, 2015 at 06:47:39PM +0200, Alexander Aring wrote:
...
>  
>  	fq->q.stamp = skb->tstamp;
>  	if (frag_type == LOWPAN_DISPATCH_FRAG1) {
> -		/* Calculate uncomp. 6lowpan header to estimate full size */
> -		fq->q.meat += lowpan_uncompress_size(skb, NULL);
> +		fq->q.meat += skb->len;
>  		fq->q.flags |= INET_FRAG_FIRST_IN;
>  	} else {
>  		fq->q.meat += skb->len;

removed the else branch and move "fq->q.meat += skb->len;" out of any
branches, we do "fq->q.meat += skb->len;" always.

> @@ -325,8 +316,59 @@ out_oom:
>  	return -1;
>  }
>  
...
>  
> -	if (frag_info->d_size > IPV6_MIN_MTU) {
> +	if (frag_type == LOWPAN_DISPATCH_FRAG1) {
> +		lowpan_rx_result res;

changed to "int res".

> +
> +		res = lowpan_invoke_frag_rx_handlers(skb);
> +		if (res == NET_RX_DROP)
> +			goto err;
> +	}
> +
> +	if (cb->d_size > IPV6_MIN_MTU) {
>  		net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n");
>  		goto err;
>  	}
>  
> -	fq = fq_find(net, frag_info, &source, &dest);
> +	fq = fq_find(net, cb, &hdr.source, &hdr.dest);
>  	if (fq != NULL) {
>  		int ret;
>  

- Alex

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation
  2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
                   ` (15 preceding siblings ...)
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 16/16] ieee802154: 6lowpan: remove tx full-size calc workaround Alexander Aring
@ 2015-08-30 21:45 ` Stefan Schmidt
  16 siblings, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 21:45 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> Hi,
>
> this patch series contains a rework of 802.15.4 6LoWPAN receive handling.
> We need to check on some things before which never checked before, like
> is 802.15.4 dataframe, if we can access skb->data[0] (could be that skb->len
> is 0 then), etc.
>
> Also various bug fixes like the masking for fragmentation dispatch value which
> is currently wrong. Also we should again check the dispatch value after successful
> reassembly a fragment, we currently assume always a iphc header there. This is wrong
> it could also be a non-compressed header. This can occur if the compressed header is
> larger than lower interface MTU size, we doesn't react on this while transmit which
> is another issue. Nevertheless we also don't reach this case at worst-case compression
> currently.
>
> I introduced a complete new handling for the dispatch values based on mac80211
> receive handling mechanism.

Tested-by: Stefan Schmidt <stefan@osg.samsung.com>

for the whole series as my testing showed no problems.

Going through the patches now reviewing. Skipping all that already have 
my reviewed by tag from the last round.

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open Alexander Aring
@ 2015-08-30 21:48   ` Stefan Schmidt
  2015-09-01  7:38     ` Alexander Aring
  0 siblings, 1 reply; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 21:48 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> This patch moves the open count handling while doing open of a lowpan
> interface. We need the packet handler register at first when one lowpan
> interface is up.
The code itself looks fine, but I have trouble to gte the why from your 
commit message. Why is this change needed?

> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   net/ieee802154/6lowpan/core.c | 28 ++++++++++++++++++----------
>   1 file changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
> index 3cc76f0..8e9da1d 100644
> --- a/net/ieee802154/6lowpan/core.c
> +++ b/net/ieee802154/6lowpan/core.c
> @@ -76,9 +76,27 @@ static int lowpan_dev_init(struct net_device *ldev)
>   	return 0;
>   }
>   
> +static int lowpan_open(struct net_device *dev)
> +{
> +	if (!open_count)
> +		lowpan_rx_init();
> +	open_count++;
> +	return 0;
> +}
> +
> +static int lowpan_stop(struct net_device *dev)
> +{
> +	open_count--;
> +	if (!open_count)
> +		lowpan_rx_exit();
> +	return 0;
> +}
> +
>   static const struct net_device_ops lowpan_netdev_ops = {
>   	.ndo_init		= lowpan_dev_init,
>   	.ndo_start_xmit		= lowpan_xmit,
> +	.ndo_open		= lowpan_open,
> +	.ndo_stop		= lowpan_stop,
>   };
>   
>   static void lowpan_setup(struct net_device *ldev)
> @@ -149,11 +167,6 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
>   	}
>   
>   	wdev->ieee802154_ptr->lowpan_dev = ldev;
> -	if (!open_count)
> -		lowpan_rx_init();
> -
> -	open_count++;
> -
>   	return 0;
>   }
>   
> @@ -163,11 +176,6 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
>   
>   	ASSERT_RTNL();
>   
> -	open_count--;
> -
> -	if (!open_count)
> -		lowpan_rx_exit();
> -
>   	wdev->ieee802154_ptr->lowpan_dev = NULL;
>   	unregister_netdevice(ldev);
>   	dev_put(wdev);

Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 03/16] ieee802154: 6lowpan: remove check on null
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 03/16] ieee802154: 6lowpan: remove check on null Alexander Aring
@ 2015-08-30 21:49   ` Stefan Schmidt
  2015-09-01  7:52     ` Stefan Schmidt
  0 siblings, 1 reply; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 21:49 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> This patch removes one check on null which should be already done by
> checking before for ARPHRD_IEEE802154. All ARPHRD_IEEE802154 and
> ARPHRD_IEEE802154_MONITOR should have wdev->ieee802154_ptr, where
> ARPHRD_IEEE802154 is currently a node interface only.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   net/ieee802154/6lowpan/core.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
> index 8e9da1d..6607bb4 100644
> --- a/net/ieee802154/6lowpan/core.c
> +++ b/net/ieee802154/6lowpan/core.c
> @@ -214,7 +214,7 @@ static int lowpan_device_event(struct notifier_block *unused,
>   		 * also delete possible lowpan interfaces which belongs
>   		 * to the wpan interface.
>   		 */
> -		if (wdev->ieee802154_ptr && wdev->ieee802154_ptr->lowpan_dev)
> +		if (wdev->ieee802154_ptr->lowpan_dev)
>   			lowpan_dellink(wdev->ieee802154_ptr->lowpan_dev, NULL);
>   		break;
>   	default:

Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 06/16] ieee802154: 6lowpan: change if lowpan dev is running
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 06/16] ieee802154: 6lowpan: change if lowpan dev is running Alexander Aring
@ 2015-08-30 21:51   ` Stefan Schmidt
  2015-09-01  7:53     ` Stefan Schmidt
  0 siblings, 1 reply; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 21:51 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> We don't need to check if the wpan interface is running because the
> lowpan_rcv is the packet layer receive handler for the wpan interface.
>
> Instead doing a check if wpan interface is running we should check if
> the lowpan interface is running before starting 6lowpan adaptation layer.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   net/ieee802154/6lowpan/rx.c | 11 ++++++-----
>   1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
> index b1442f3..c529d9f 100644
> --- a/net/ieee802154/6lowpan/rx.c
> +++ b/net/ieee802154/6lowpan/rx.c
> @@ -65,19 +65,20 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
>   		      struct packet_type *pt, struct net_device *orig_wdev)
>   {
>   	struct ieee802154_hdr hdr;
> +	struct net_device *ldev;
>   	int ret;
>   
> -	if (wdev->type != ARPHRD_IEEE802154 ||
> -	    !wdev->ieee802154_ptr->lowpan_dev)
> +	if (wdev->type != ARPHRD_IEEE802154)
> +		goto drop;
> +
> +	ldev = wdev->ieee802154_ptr->lowpan_dev;
> +	if (!ldev || !netif_running(ldev))
>   		goto drop;
>   
>   	skb = skb_share_check(skb, GFP_ATOMIC);
>   	if (!skb)
>   		goto drop;
>   
> -	if (!netif_running(wdev))
> -		goto drop_skb;
> -
>   	if (skb->pkt_type == PACKET_OTHERHOST)
>   		goto drop_skb;
>   

Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 09/16] ieee802154: 6lowpan: earlier skb->dev switch
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 09/16] ieee802154: 6lowpan: earlier skb->dev switch Alexander Aring
@ 2015-08-30 21:54   ` Stefan Schmidt
  2015-09-01  7:53     ` Stefan Schmidt
  0 siblings, 1 reply; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 21:54 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> We should change the skb->dev pointer earlier to the lowpan interface
> Sometimes we call iphc_decompress which also use some netdev printout
> functionality. This patch will change that the correct interface will be
> displayed in this case, which should be the lowpan interface.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   net/ieee802154/6lowpan/rx.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
> index 74d8fec..f9cb70b 100644
> --- a/net/ieee802154/6lowpan/rx.c
> +++ b/net/ieee802154/6lowpan/rx.c
> @@ -18,7 +18,6 @@
>   static int lowpan_give_skb_to_device(struct sk_buff *skb,
>   				     struct net_device *wdev)
>   {
> -	skb->dev = wdev->ieee802154_ptr->lowpan_dev;
>   	skb->protocol = htons(ETH_P_IPV6);
>   	skb->pkt_type = PACKET_HOST;
>   
> @@ -71,9 +70,11 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
>   	if (!ldev || !netif_running(ldev))
>   		goto drop;
>   
> +	/* Replacing skb->dev and followed rx handlers will manipulate skb. */
>   	skb = skb_share_check(skb, GFP_ATOMIC);
>   	if (!skb)
>   		goto drop;
> +	skb->dev = ldev;
>   
>   	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
>   		goto drop_skb;

Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch Alexander Aring
@ 2015-08-30 22:00   ` Stefan Schmidt
  2015-09-01  7:39     ` Alexander Aring
  2015-09-01  7:56     ` Stefan Schmidt
  0 siblings, 2 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 22:00 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> This patch adds checks for reserved dispatch value. When we have a
> reserved dispatch value we should drop the skb immediately.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   net/ieee802154/6lowpan/rx.c | 14 +++++++++++++-
>   1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
> index d309d91..f98ebf5 100644
> --- a/net/ieee802154/6lowpan/rx.c
> +++ b/net/ieee802154/6lowpan/rx.c
> @@ -260,6 +260,17 @@ static inline bool lowpan_is_nalp(u8 dispatch)
>   	return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_NALP;
>   }
>   
> +/* Lookup for reserved dispatch values at:
> + * https://www.iana.org/assignments/_6lowpan-parameters/_6lowpan-parameters.xhtml#_6lowpan-parameters-1
It might be worth noting down the update date here as well. The do not 
seem to have a version I can find easily so the update date might be a 
good idea to help helping looking at it to decide if we should update 
our code.

> + */
> +static inline bool lowpan_is_reserved(u8 dispatch)
> +{
> +	return ((dispatch >= 0x44 && dispatch <= 0x4F) ||
> +		(dispatch >= 0x51 && dispatch <= 0x5F) ||
> +		(dispatch >= 0xc8 && dispatch <= 0xdf) ||
> +		(dispatch >= 0xe8 && dispatch <= 0xff));
> +}
> +
>   /* lowpan_rx_h_check checks on generic 6LoWPAN requirements
>    * in MAC and 6LoWPAN header.
>    *
> @@ -271,7 +282,8 @@ static inline bool lowpan_rx_h_check(struct sk_buff *skb)
>   	if (unlikely(!skb->len))
>   		return false;
>   
> -	if (lowpan_is_nalp(*skb_network_header(skb)))
> +	if (lowpan_is_nalp(*skb_network_header(skb)) ||
> +	    lowpan_is_reserved(*skb_network_header(skb)))
>   		return false;
>   
>   	return true;

Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 14/16] ieee802154: 6lowpan: check on valid 802.15.4 frame
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 14/16] ieee802154: 6lowpan: check on valid 802.15.4 frame Alexander Aring
@ 2015-08-30 22:03   ` Stefan Schmidt
  2015-09-01  7:57     ` Stefan Schmidt
  0 siblings, 1 reply; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 22:03 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> This patch adds frame control checks to check if the received frame is
> something which could contain a 6LoWPAN packet.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   include/linux/ieee802154.h  | 25 +++++++++++++++++++++++++
>   include/net/mac802154.h     | 15 +++++++++++++++
>   net/ieee802154/6lowpan/rx.c |  8 ++++++++
>   3 files changed, 48 insertions(+)
>
> diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
> index 1dc1f4e..db01492 100644
> --- a/include/linux/ieee802154.h
> +++ b/include/linux/ieee802154.h
> @@ -205,6 +205,31 @@ enum {
>   	IEEE802154_SCAN_IN_PROGRESS = 0xfc,
>   };
>   
> +/* frame control handling */
> +#define IEEE802154_FCTL_FTYPE		0x0003
> +#define IEEE802154_FCTL_INTRA_PAN	0x0040
> +
> +#define IEEE802154_FTYPE_DATA		0x0001
> +
> +/*
> + * ieee802154_is_data - check if type is IEEE802154_FTYPE_DATA
> + * @fc: frame control bytes in little-endian byteorder
> + */
> +static inline int ieee802154_is_data(__le16 fc)
> +{
> +	return (fc & cpu_to_le16(IEEE802154_FCTL_FTYPE)) ==
> +		cpu_to_le16(IEEE802154_FTYPE_DATA);
> +}
> +
> +/**
> + * ieee802154_is_intra_pan - check if intra pan id communication
> + * @fc: frame control bytes in little-endian byteorder
> + */
> +static inline bool ieee802154_is_intra_pan(__le16 fc)
> +{
> +	return fc & cpu_to_le16(IEEE802154_FCTL_INTRA_PAN);
> +}
> +
>   /**
>    * ieee802154_is_valid_psdu_len - check if psdu len is valid
>    * available lengths:
> diff --git a/include/net/mac802154.h b/include/net/mac802154.h
> index b7f9961..32bd7c0 100644
> --- a/include/net/mac802154.h
> +++ b/include/net/mac802154.h
> @@ -250,6 +250,21 @@ struct ieee802154_ops {
>   };
>   
>   /**
> + * ieee802154_get_fc_from_skb - get the frame control field from an skb
> + * @skb: skb where the frame control field will be get from
> + */
> +static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb)
> +{
> +	/* return some invalid fc on failure */
> +	if (unlikely(skb->mac_len < 2)) {
> +		WARN_ON(1);
> +		return cpu_to_le16(0);
> +	}
> +
> +	return (__force __le16)__get_unaligned_memmove16(skb_mac_header(skb));
> +}
> +
> +/**
>    * ieee802154_be64_to_le64 - copies and convert be64 to le64
>    * @le64_dst: le64 destination pointer
>    * @be64_src: be64 source pointer
> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
> index f98ebf5..5be996a 100644
> --- a/net/ieee802154/6lowpan/rx.c
> +++ b/net/ieee802154/6lowpan/rx.c
> @@ -11,6 +11,7 @@
>   #include <linux/if_arp.h>
>   
>   #include <net/6lowpan.h>
> +#include <net/mac802154.h>
>   #include <net/ieee802154_netdev.h>
>   
>   #include "6lowpan_i.h"
> @@ -278,6 +279,13 @@ static inline bool lowpan_is_reserved(u8 dispatch)
>    */
>   static inline bool lowpan_rx_h_check(struct sk_buff *skb)
>   {
> +	__le16 fc = ieee802154_get_fc_from_skb(skb);
> +
> +	/* check on ieee802154 conform 6LoWPAN header */
> +	if (!ieee802154_is_data(fc) ||
> +	    !ieee802154_is_intra_pan(fc))
> +		return false;
> +
>   	/* check if we can dereference the dispatch */
>   	if (unlikely(!skb->len))
>   		return false;

Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 16/16] ieee802154: 6lowpan: remove tx full-size calc workaround
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 16/16] ieee802154: 6lowpan: remove tx full-size calc workaround Alexander Aring
@ 2015-08-30 22:06   ` Stefan Schmidt
  2015-09-01  7:57     ` Stefan Schmidt
  0 siblings, 1 reply; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-30 22:06 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> This patch removes a workaround for datagram_size calculation while
> doing fragmentation on transmit.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   include/net/6lowpan.h       | 113 --------------------------------------------
>   net/ieee802154/6lowpan/tx.c |  18 ++++---
>   2 files changed, 11 insertions(+), 120 deletions(-)
>
> diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
> index 3509841..eeae5eb 100644
> --- a/include/net/6lowpan.h
> +++ b/include/net/6lowpan.h
> @@ -299,119 +299,6 @@ static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
>   	*hc_ptr += len;
>   }
>   
> -static inline u8 lowpan_addr_mode_size(const u8 addr_mode)
> -{
> -	static const u8 addr_sizes[] = {
> -		[LOWPAN_IPHC_ADDR_00] = 16,
> -		[LOWPAN_IPHC_ADDR_01] = 8,
> -		[LOWPAN_IPHC_ADDR_02] = 2,
> -		[LOWPAN_IPHC_ADDR_03] = 0,
> -	};
> -	return addr_sizes[addr_mode];
> -}
> -
> -static inline u8 lowpan_next_hdr_size(const u8 h_enc, u16 *uncomp_header)
> -{
> -	u8 ret = 1;
> -
> -	if ((h_enc & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
> -		*uncomp_header += sizeof(struct udphdr);
> -
> -		switch (h_enc & LOWPAN_NHC_UDP_CS_P_11) {
> -		case LOWPAN_NHC_UDP_CS_P_00:
> -			ret += 4;
> -			break;
> -		case LOWPAN_NHC_UDP_CS_P_01:
> -		case LOWPAN_NHC_UDP_CS_P_10:
> -			ret += 3;
> -			break;
> -		case LOWPAN_NHC_UDP_CS_P_11:
> -			ret++;
> -			break;
> -		default:
> -			break;
> -		}
> -
> -		if (!(h_enc & LOWPAN_NHC_UDP_CS_C))
> -			ret += 2;
> -	}
> -
> -	return ret;
> -}
> -
> -/**
> - *	lowpan_uncompress_size - returns skb->len size with uncompressed header
> - *	@skb: sk_buff with 6lowpan header inside
> - *	@datagram_offset: optional to get the datagram_offset value
> - *
> - *	Returns the skb->len with uncompressed header
> - */
> -static inline u16
> -lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
> -{
> -	u16 ret = 2, uncomp_header = sizeof(struct ipv6hdr);
> -	u8 iphc0, iphc1, h_enc;
> -
> -	iphc0 = skb_network_header(skb)[0];
> -	iphc1 = skb_network_header(skb)[1];
> -
> -	switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
> -	case 0:
> -		ret += 4;
> -		break;
> -	case 1:
> -		ret += 3;
> -		break;
> -	case 2:
> -		ret++;
> -		break;
> -	default:
> -		break;
> -	}
> -
> -	if (!(iphc0 & LOWPAN_IPHC_NH_C))
> -		ret++;
> -
> -	if (!(iphc0 & 0x03))
> -		ret++;
> -
> -	ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_SAM) >>
> -				     LOWPAN_IPHC_SAM_BIT);
> -
> -	if (iphc1 & LOWPAN_IPHC_M) {
> -		switch ((iphc1 & LOWPAN_IPHC_DAM_11) >>
> -			LOWPAN_IPHC_DAM_BIT) {
> -		case LOWPAN_IPHC_DAM_00:
> -			ret += 16;
> -			break;
> -		case LOWPAN_IPHC_DAM_01:
> -			ret += 6;
> -			break;
> -		case LOWPAN_IPHC_DAM_10:
> -			ret += 4;
> -			break;
> -		case LOWPAN_IPHC_DAM_11:
> -			ret++;
> -			break;
> -		default:
> -			break;
> -		}
> -	} else {
> -		ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_DAM_11) >>
> -					     LOWPAN_IPHC_DAM_BIT);
> -	}
> -
> -	if (iphc0 & LOWPAN_IPHC_NH_C) {
> -		h_enc = skb_network_header(skb)[ret];
> -		ret += lowpan_next_hdr_size(h_enc, &uncomp_header);
> -	}
> -
> -	if (dgram_offset)
> -		*dgram_offset = uncomp_header;
> -
> -	return skb->len + uncomp_header - ret;
> -}
> -
>   void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype);
>   
>   int
> diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
> index 9a2147e..4115335 100644
> --- a/net/ieee802154/6lowpan/tx.c
> +++ b/net/ieee802154/6lowpan/tx.c
> @@ -123,16 +123,14 @@ lowpan_xmit_fragment(struct sk_buff *skb, const struct ieee802154_hdr *wpan_hdr,
>   
>   static int
>   lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev,
> -		       const struct ieee802154_hdr *wpan_hdr)
> +		       const struct ieee802154_hdr *wpan_hdr, u16 dgram_size,
> +		       u16 dgram_offset)
>   {
> -	u16 dgram_size, dgram_offset;
>   	__be16 frag_tag;
>   	u8 frag_hdr[5];
>   	int frag_cap, frag_len, payload_cap, rc;
>   	int skb_unprocessed, skb_offset;
>   
> -	dgram_size = lowpan_uncompress_size(skb, &dgram_offset) -
> -		     skb->mac_len;
>   	frag_tag = htons(lowpan_dev_info(ldev)->fragment_tag);
>   	lowpan_dev_info(ldev)->fragment_tag++;
>   
> @@ -187,7 +185,8 @@ err:
>   	return rc;
>   }
>   
> -static int lowpan_header(struct sk_buff *skb, struct net_device *ldev)
> +static int lowpan_header(struct sk_buff *skb, struct net_device *ldev,
> +			 u16 *dgram_size, u16 *dgram_offset)
>   {
>   	struct wpan_dev *wpan_dev = lowpan_dev_info(ldev)->wdev->ieee802154_ptr;
>   	struct ieee802154_addr sa, da;
> @@ -201,7 +200,10 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *ldev)
>   	daddr = &info.daddr.u.extended_addr;
>   	saddr = &info.saddr.u.extended_addr;
>   
> +	*dgram_size = skb->len;
>   	lowpan_header_compress(skb, ldev, ETH_P_IPV6, daddr, saddr, skb->len);
> +	/* dgram_size = (saved bytes after compression) + lowpan header size */
> +	*dgram_offset = (*dgram_size - skb->len) + skb_network_header_len(skb);
>   
>   	cb->type = IEEE802154_FC_TYPE_DATA;
>   
> @@ -234,6 +236,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
>   {
>   	struct ieee802154_hdr wpan_hdr;
>   	int max_single, ret;
> +	u16 dgram_size, dgram_offset;
>   
>   	pr_debug("package xmit\n");
>   
> @@ -244,7 +247,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
>   	if (!skb)
>   		return NET_XMIT_DROP;
>   
> -	ret = lowpan_header(skb, ldev);
> +	ret = lowpan_header(skb, ldev, &dgram_size, &dgram_offset);
>   	if (ret < 0) {
>   		kfree_skb(skb);
>   		return NET_XMIT_DROP;
> @@ -264,7 +267,8 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
>   		netdev_tx_t rc;
>   
>   		pr_debug("frame is too big, fragmentation is needed\n");
> -		rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr);
> +		rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr, dgram_size,
> +					    dgram_offset);
>   
>   		return rc < 0 ? NET_XMIT_DROP : rc;
>   	}

Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework
  2015-08-20 16:47 ` [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework Alexander Aring
  2015-08-27 17:53   ` Alexander Aring
@ 2015-08-31  9:28   ` Stefan Schmidt
  2015-09-01  7:43     ` Alexander Aring
  1 sibling, 1 reply; 37+ messages in thread
From: Stefan Schmidt @ 2015-08-31  9:28 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 20/08/15 18:47, Alexander Aring wrote:
> This patch complete reworks the evaluation of 6lowpan dispatch value by
> introducing a receive handler mechanism for each dispatch value.
>
> A list of changes:
>
>   - Doing uncompression on-the-fly when FRAG1 is received, this require
>     some special handling for 802.15.4 lltype in generic 6lowpan branch
>     for setting the payload length correct.
>   - Fix dispatch mask for fragmentation.
>   - Add IPv6 dispatch evaluation for FRAG1.
>   - Add skb_unshare for dispatch which might manipulate the skb data
>     buffer.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> ---
>   include/net/6lowpan.h               |  31 ++++--

Not sure if you might want to include Jukka here for the shared header 
part with BT.
>   net/6lowpan/iphc.c                  |  13 ++-
>   net/6lowpan/nhc_udp.c               |  13 ++-
>   net/ieee802154/6lowpan/6lowpan_i.h  |  12 +++
>   net/ieee802154/6lowpan/reassembly.c | 126 +++++++++++++++++-------
>   net/ieee802154/6lowpan/rx.c         | 188 ++++++++++++++++++++++++------------
>   6 files changed, 278 insertions(+), 105 deletions(-)
>
> diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
> index a2f59ec..3509841 100644
> --- a/include/net/6lowpan.h
> +++ b/include/net/6lowpan.h
> @@ -126,13 +126,19 @@
>   	 (((a)[6]) == 0xFF) &&	\
>   	 (((a)[7]) == 0xFF))
>   
> -#define LOWPAN_DISPATCH_IPV6	0x41 /* 01000001 = 65 */
> -#define LOWPAN_DISPATCH_HC1	0x42 /* 01000010 = 66 */
> -#define LOWPAN_DISPATCH_IPHC	0x60 /* 011xxxxx = ... */
> -#define LOWPAN_DISPATCH_FRAG1	0xc0 /* 11000xxx */
> -#define LOWPAN_DISPATCH_FRAGN	0xe0 /* 11100xxx */
> +#define LOWPAN_DISPATCH_IPV6		0x41 /* 01000001 = 65 */
> +#define LOWPAN_DISPATCH_IPHC		0x60 /* 011xxxxx = ... */
> +#define LOWPAN_DISPATCH_IPHC_MASK	0xe0
>   
> -#define LOWPAN_DISPATCH_MASK	0xf8 /* 11111000 */
> +static inline bool lowpan_is_ipv6(u8 dispatch)
> +{
> +	return dispatch == LOWPAN_DISPATCH_IPV6;
> +}
> +
> +static inline bool lowpan_is_iphc(u8 dispatch)
> +{
> +	return (dispatch & LOWPAN_DISPATCH_IPHC_MASK) == LOWPAN_DISPATCH_IPHC;
> +}
>   
>   #define LOWPAN_FRAG_TIMEOUT	(HZ * 60)	/* time-out 60 sec */
>   
> @@ -218,6 +224,19 @@ struct lowpan_priv *lowpan_priv(const struct net_device *dev)
>   	return netdev_priv(dev);
>   }
>   
> +struct lowpan_802154_cb {
> +	u16 d_tag;
> +	unsigned int d_size;
> +	u8 d_offset;
> +};
> +
> +static inline
> +struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb)
> +{
> +	BUILD_BUG_ON(sizeof(struct lowpan_802154_cb) > sizeof(skb->cb));
> +	return (struct lowpan_802154_cb *)skb->cb;
> +}
> +
>   #ifdef DEBUG
>   /* print data in line */
>   static inline void raw_dump_inline(const char *caller, char *msg,
> diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
> index 1e0071f..78c8a49 100644
> --- a/net/6lowpan/iphc.c
> +++ b/net/6lowpan/iphc.c
> @@ -366,7 +366,18 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
>   			return err;
>   	}
>   
> -	hdr.payload_len = htons(skb->len);
> +	switch (lowpan_priv(dev)->lltype) {
> +	case LOWPAN_LLTYPE_IEEE802154:
> +		if (lowpan_802154_cb(skb)->d_size)
> +			hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size -
> +						sizeof(struct ipv6hdr));
> +		else
> +			hdr.payload_len = htons(skb->len);
> +		break;
> +	default:
> +		hdr.payload_len = htons(skb->len);

The default and else block being the same here I think that can be 
simplified.
> +		break;
> +	}
>   
>   	pr_debug("skb headroom size = %d, data length = %d\n",
>   		 skb_headroom(skb), skb->len);
> diff --git a/net/6lowpan/nhc_udp.c b/net/6lowpan/nhc_udp.c
> index c6bcaeb..72d0b57 100644
> --- a/net/6lowpan/nhc_udp.c
> +++ b/net/6lowpan/nhc_udp.c
> @@ -71,7 +71,18 @@ static int udp_uncompress(struct sk_buff *skb, size_t needed)
>   	 * here, we obtain the hint from the remaining size of the
>   	 * frame
>   	 */
> -	uh.len = htons(skb->len + sizeof(struct udphdr));
> +	switch (lowpan_priv(skb->dev)->lltype) {
> +	case LOWPAN_LLTYPE_IEEE802154:
> +		if (lowpan_802154_cb(skb)->d_size)
> +			uh.len = htons(lowpan_802154_cb(skb)->d_size -
> +				       sizeof(struct ipv6hdr));
> +		else
> +			uh.len = htons(skb->len + sizeof(struct udphdr));
> +		break;
> +	default:
> +		uh.len = htons(skb->len + sizeof(struct udphdr));
> +		break;
> +	}

Else branch and default case same again.
>   	pr_debug("uncompressed UDP length: src = %d", ntohs(uh.len));
>   
>   	/* replace the compressed UDP head by the uncompressed UDP
> diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h
> index 9aa7b62..b4e17a7 100644
> --- a/net/ieee802154/6lowpan/6lowpan_i.h
> +++ b/net/ieee802154/6lowpan/6lowpan_i.h
> @@ -7,6 +7,15 @@
>   #include <net/inet_frag.h>
>   #include <net/6lowpan.h>
>   
> +typedef unsigned __bitwise__ lowpan_rx_result;
> +#define RX_CONTINUE		((__force lowpan_rx_result) 0u)
> +#define RX_DROP_UNUSABLE	((__force lowpan_rx_result) 1u)
> +#define RX_DROP			((__force lowpan_rx_result) 2u)
> +#define RX_QUEUED		((__force lowpan_rx_result) 3u)
> +
> +#define LOWPAN_DISPATCH_FRAG1           0xc0
> +#define LOWPAN_DISPATCH_FRAGN           0xe0
> +
>   struct lowpan_create_arg {
>   	u16 tag;
>   	u16 d_size;
> @@ -62,4 +71,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
>   			 const void *_saddr, unsigned int len);
>   netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev);
>   
> +int lowpan_iphc_decompress(struct sk_buff *skb);
> +lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb);
> +
>   #endif /* __IEEE802154_6LOWPAN_I_H__ */
> diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
> index 0fc3350..fadd985 100644
> --- a/net/ieee802154/6lowpan/reassembly.c
> +++ b/net/ieee802154/6lowpan/reassembly.c
> @@ -32,17 +32,6 @@
>   
>   static const char lowpan_frags_cache_name[] = "lowpan-frags";
>   
> -struct lowpan_frag_info {
> -	u16 d_tag;
> -	u16 d_size;
> -	u8 d_offset;
> -};
> -
> -static struct lowpan_frag_info *lowpan_cb(struct sk_buff *skb)
> -{
> -	return (struct lowpan_frag_info *)skb->cb;
> -}
> -
>   static struct inet_frags lowpan_frags;
>   
>   static int lowpan_frag_reasm(struct lowpan_frag_queue *fq,
> @@ -111,7 +100,7 @@ out:
>   }
>   
>   static inline struct lowpan_frag_queue *
> -fq_find(struct net *net, const struct lowpan_frag_info *frag_info,
> +fq_find(struct net *net, const struct lowpan_802154_cb *cb,
>   	const struct ieee802154_addr *src,
>   	const struct ieee802154_addr *dst)
>   {
> @@ -121,12 +110,12 @@ fq_find(struct net *net, const struct lowpan_frag_info *frag_info,
>   	struct netns_ieee802154_lowpan *ieee802154_lowpan =
>   		net_ieee802154_lowpan(net);
>   
> -	arg.tag = frag_info->d_tag;
> -	arg.d_size = frag_info->d_size;
> +	arg.tag = cb->d_tag;
> +	arg.d_size = cb->d_size;
>   	arg.src = src;
>   	arg.dst = dst;
>   
> -	hash = lowpan_hash_frag(frag_info->d_tag, frag_info->d_size, src, dst);
> +	hash = lowpan_hash_frag(cb->d_tag, cb->d_size, src, dst);
>   
>   	q = inet_frag_find(&ieee802154_lowpan->frags,
>   			   &lowpan_frags, &arg, hash);
> @@ -138,7 +127,7 @@ fq_find(struct net *net, const struct lowpan_frag_info *frag_info,
>   }
>   
>   static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
> -			     struct sk_buff *skb, const u8 frag_type)
> +			     struct sk_buff *skb, u8 frag_type)
>   {
>   	struct sk_buff *prev, *next;
>   	struct net_device *ldev;
> @@ -147,8 +136,8 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
>   	if (fq->q.flags & INET_FRAG_COMPLETE)
>   		goto err;
>   
> -	offset = lowpan_cb(skb)->d_offset << 3;
> -	end = lowpan_cb(skb)->d_size;
> +	offset = lowpan_802154_cb(skb)->d_offset << 3;
> +	end = lowpan_802154_cb(skb)->d_size;
>   
>   	/* Is this the final fragment? */
>   	if (offset + skb->len == end) {
> @@ -174,13 +163,16 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
>   	 * this fragment, right?
>   	 */
>   	prev = fq->q.fragments_tail;
> -	if (!prev || lowpan_cb(prev)->d_offset < lowpan_cb(skb)->d_offset) {
> +	if (!prev ||
> +	    lowpan_802154_cb(prev)->d_offset <
> +	    lowpan_802154_cb(skb)->d_offset) {
>   		next = NULL;
>   		goto found;
>   	}
>   	prev = NULL;
>   	for (next = fq->q.fragments; next != NULL; next = next->next) {
> -		if (lowpan_cb(next)->d_offset >= lowpan_cb(skb)->d_offset)
> +		if (lowpan_802154_cb(next)->d_offset >=
> +		    lowpan_802154_cb(skb)->d_offset)
>   			break;	/* bingo! */
>   		prev = next;
>   	}
> @@ -201,8 +193,7 @@ found:
>   
>   	fq->q.stamp = skb->tstamp;
>   	if (frag_type == LOWPAN_DISPATCH_FRAG1) {
> -		/* Calculate uncomp. 6lowpan header to estimate full size */
> -		fq->q.meat += lowpan_uncompress_size(skb, NULL);
> +		fq->q.meat += skb->len;
>   		fq->q.flags |= INET_FRAG_FIRST_IN;
>   	} else {
>   		fq->q.meat += skb->len;

You mentioned this one yourself already as fixed.
> @@ -325,8 +316,59 @@ out_oom:
>   	return -1;
>   }
>   
> -static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
> -				struct lowpan_frag_info *frag_info)
> +int lowpan_frag_rx_handlers_result(struct sk_buff *skb, lowpan_rx_result res)
> +{
> +	switch (res) {
> +	case RX_QUEUED:
> +		return NET_RX_SUCCESS;
> +	case RX_CONTINUE:
> +		/* nobody cared about this packet */
> +		net_warn_ratelimited("%s: received unknown dispatch\n",
> +				     __func__);
> +
> +		/* fall-through */
> +	default:
> +		/* all others failure */
> +		return NET_RX_DROP;
> +	}
> +}
> +
> +static lowpan_rx_result lowpan_frag_rx_h_iphc(struct sk_buff *skb)
> +{
> +	int ret;
> +
> +	if (!lowpan_is_iphc(*skb_network_header(skb)))
> +		return RX_CONTINUE;
> +
> +	ret = lowpan_iphc_decompress(skb);
> +	if (ret < 0)
> +		return RX_DROP;
> +
> +	return RX_QUEUED;
> +}
> +
> +static int lowpan_invoke_frag_rx_handlers(struct sk_buff *skb)
> +{
> +	lowpan_rx_result res;
> +
> +#define CALL_RXH(rxh)			\
> +	do {				\
> +		res = rxh(skb);	\
> +		if (res != RX_CONTINUE)	\
> +			goto rxh_next;	\
> +	} while (0)
> +
> +	/* likely at first */
> +	CALL_RXH(lowpan_frag_rx_h_iphc);
> +	CALL_RXH(lowpan_rx_h_ipv6);
> +
> +rxh_next:
> +	return lowpan_frag_rx_handlers_result(skb, res);
> +#undef CALL_RXH
> +}
> +
> +static int lowpan_get_cb(struct sk_buff *skb, u8 frag_type,
> +			 struct lowpan_802154_cb *cb)
>   {
>   	bool fail;
>   	u8 pattern = 0, low = 0;
> @@ -334,15 +376,19 @@ static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
>   
>   	fail = lowpan_fetch_skb(skb, &pattern, 1);
>   	fail |= lowpan_fetch_skb(skb, &low, 1);
> -	frag_info->d_size = (pattern & 7) << 8 | low;
> +	cb->d_size = (pattern & 7) << 8 | low;

Magic numbers. Yeah,. I know they have been there before.
>   	fail |= lowpan_fetch_skb(skb, &d_tag, 2);
> -	frag_info->d_tag = ntohs(d_tag);
> +	cb->d_tag = ntohs(d_tag);
>   
>   	if (frag_type == LOWPAN_DISPATCH_FRAGN) {
> -		fail |= lowpan_fetch_skb(skb, &frag_info->d_offset, 1);
> +		fail |= lowpan_fetch_skb(skb, &cb->d_offset, 1);
>   	} else {
>   		skb_reset_network_header(skb);
> -		frag_info->d_offset = 0;
> +		cb->d_offset = 0;
> +		/* check if datagram_size has ipv6hdr on FRAG1 */
> +		fail |= cb->d_size < sizeof(struct ipv6hdr);
> +		/* check if we can dereference the dispatch value */
> +		fail |= !skb->len;
>   	}
>   
>   	if (unlikely(fail))
> @@ -351,27 +397,35 @@ static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
>   	return 0;
>   }
>   
> -int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
> +int lowpan_frag_rcv(struct sk_buff *skb, u8 frag_type)
>   {
>   	struct lowpan_frag_queue *fq;
>   	struct net *net = dev_net(skb->dev);
> -	struct lowpan_frag_info *frag_info = lowpan_cb(skb);
> -	struct ieee802154_addr source, dest;
> +	struct lowpan_802154_cb *cb = lowpan_802154_cb(skb);
> +	struct ieee802154_hdr hdr;
>   	int err;
>   
> -	source = mac_cb(skb)->source;
> -	dest = mac_cb(skb)->dest;
> +	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
> +		goto err;
>   
> -	err = lowpan_get_frag_info(skb, frag_type, frag_info);
> +	err = lowpan_get_cb(skb, frag_type, cb);
>   	if (err < 0)
>   		goto err;
>   
> -	if (frag_info->d_size > IPV6_MIN_MTU) {
> +	if (frag_type == LOWPAN_DISPATCH_FRAG1) {
> +		lowpan_rx_result res;
> +
> +		res = lowpan_invoke_frag_rx_handlers(skb);
> +		if (res == NET_RX_DROP)
> +			goto err;
> +	}
> +
> +	if (cb->d_size > IPV6_MIN_MTU) {
>   		net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n");
>   		goto err;
>   	}
>   
> -	fq = fq_find(net, frag_info, &source, &dest);
> +	fq = fq_find(net, cb, &hdr.source, &hdr.dest);
>   	if (fq != NULL) {
>   		int ret;
>   
> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
> index f9cb70b..2adc92a 100644
> --- a/net/ieee802154/6lowpan/rx.c
> +++ b/net/ieee802154/6lowpan/rx.c
> @@ -15,8 +15,9 @@
>   
>   #include "6lowpan_i.h"
>   
> -static int lowpan_give_skb_to_device(struct sk_buff *skb,
> -				     struct net_device *wdev)
> +#define LOWPAN_DISPATCH_FRAG_MASK	0xf8
> +
> +static int lowpan_give_skb_to_device(struct sk_buff *skb)
>   {
>   	skb->protocol = htons(ETH_P_IPV6);
>   	skb->pkt_type = PACKET_HOST;
> @@ -24,21 +25,77 @@ static int lowpan_give_skb_to_device(struct sk_buff *skb,
>   	return netif_rx(skb);
>   }
>   
> -static int
> -iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
> +int lowpan_rx_handlers_result(struct sk_buff *skb, lowpan_rx_result res)
> +{
> +	switch (res) {
> +	case RX_CONTINUE:
> +		/* nobody cared about this packet */
> +		net_warn_ratelimited("%s: received unknown dispatch\n",
> +				     __func__);
> +
> +		/* fall-through */
> +	case RX_DROP_UNUSABLE:
> +		kfree_skb(skb);
> +
> +		/* fall-through */
> +	case RX_DROP:
> +		return NET_RX_DROP;
> +	case RX_QUEUED:
> +		return lowpan_give_skb_to_device(skb);
> +	default:
> +		break;
> +	}
> +
> +	return NET_RX_DROP;
> +}
> +
> +static inline bool lowpan_is_frag1(u8 dispatch)
> +{
> +	return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAG1;
> +}
> +
> +static inline bool lowpan_is_fragn(u8 dispatch)
> +{
> +	return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAGN;
> +}
> +
> +static lowpan_rx_result lowpan_rx_h_frag(struct sk_buff *skb)
> +{
> +	int ret;
> +
> +	if (!(lowpan_is_frag1(*skb_network_header(skb)) ||
> +	      lowpan_is_fragn(*skb_network_header(skb))))
> +		return RX_CONTINUE;
> +
> +	ret = lowpan_frag_rcv(skb, *skb_network_header(skb) &
> +			      LOWPAN_DISPATCH_FRAG_MASK);
> +	if (ret == 1)
> +		return RX_QUEUED;
> +
> +	/* Packet is freed by lowpan_frag_rcv on error or put into the frag
> +	 * bucket.
> +	 */
> +	return RX_DROP;
> +}
> +
> +int lowpan_iphc_decompress(struct sk_buff *skb)
>   {
> -	u8 iphc0, iphc1;
>   	struct ieee802154_addr_sa sa, da;
> +	struct ieee802154_hdr hdr;
> +	u8 iphc0, iphc1;
>   	void *sap, *dap;
>   
> +	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
> +		return -EINVAL;
> +
>   	raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
>   
>   	if (lowpan_fetch_skb_u8(skb, &iphc0) ||
>   	    lowpan_fetch_skb_u8(skb, &iphc1))
>   		return -EINVAL;
>   
> -	ieee802154_addr_to_sa(&sa, &hdr->source);
> -	ieee802154_addr_to_sa(&da, &hdr->dest);
> +	ieee802154_addr_to_sa(&sa, &hdr.source);
> +	ieee802154_addr_to_sa(&da, &hdr.dest);
>   
>   	if (sa.addr_type == IEEE802154_ADDR_SHORT)
>   		sap = &sa.short_addr;
> @@ -55,78 +112,87 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
>   					IEEE802154_ADDR_LEN, iphc0, iphc1);
>   }
>   
> +static lowpan_rx_result lowpan_rx_h_iphc(struct sk_buff *skb)
> +{
> +	int ret;
> +
> +	if (!lowpan_is_iphc(*skb_network_header(skb)))
> +		return RX_CONTINUE;
> +
> +	/* Setting datagram_offset to zero indicates non frag handling
> +	 * while doing lowpan_header_decompress.
> +	 */
> +	lowpan_802154_cb(skb)->d_size = 0;
> +
> +	ret = lowpan_iphc_decompress(skb);
> +	if (ret < 0)
> +		return RX_DROP_UNUSABLE;
> +
> +	return RX_QUEUED;
> +}
> +
> +lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb)
> +{
> +	if (!lowpan_is_ipv6(*skb_network_header(skb)))
> +		return RX_CONTINUE;
> +
> +	/* Pull off the 1-byte of 6lowpan header. */
> +	skb_pull(skb, 1);
> +	return RX_QUEUED;
> +}
> +
> +static int lowpan_invoke_rx_handlers(struct sk_buff *skb)
> +{
> +	lowpan_rx_result res;
> +
> +#define CALL_RXH(rxh)			\
> +	do {				\
> +		res = rxh(skb);	\
> +		if (res != RX_CONTINUE)	\
> +			goto rxh_next;	\
> +	} while (0)
> +
> +	/* likely at first */
> +	CALL_RXH(lowpan_rx_h_iphc);
> +	CALL_RXH(lowpan_rx_h_frag);
> +	CALL_RXH(lowpan_rx_h_ipv6);
> +
> +rxh_next:
> +	return lowpan_rx_handlers_result(skb, res);
> +#undef CALL_RXH
> +}
> +
>   static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
>   		      struct packet_type *pt, struct net_device *orig_wdev)
>   {
> -	struct ieee802154_hdr hdr;
>   	struct net_device *ldev;
> -	int ret;
>   
>   	if (wdev->type != ARPHRD_IEEE802154 ||
>   	    skb->pkt_type == PACKET_OTHERHOST)
> -		goto drop;
> +		return NET_RX_DROP;
>   
>   	ldev = wdev->ieee802154_ptr->lowpan_dev;
>   	if (!ldev || !netif_running(ldev))
> -		goto drop;
> +		return NET_RX_DROP;
>   
>   	/* Replacing skb->dev and followed rx handlers will manipulate skb. */
>   	skb = skb_share_check(skb, GFP_ATOMIC);
>   	if (!skb)
> -		goto drop;
> +		return NET_RX_DROP;
>   	skb->dev = ldev;
>   
> -	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
> -		goto drop_skb;
> -
> -	/* check that it's our buffer */
> -	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
> -		/* Pull off the 1-byte of 6lowpan header. */
> -		skb_pull(skb, 1);
> -		return lowpan_give_skb_to_device(skb, wdev);
> -	} else {
> -		switch (skb->data[0] & 0xe0) {
> -		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
> -			ret = iphc_decompress(skb, &hdr);
> -			if (ret < 0)
> -				goto drop_skb;
> -
> -			return lowpan_give_skb_to_device(skb, wdev);
> -		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
> -			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
> -			if (ret == 1) {
> -				ret = iphc_decompress(skb, &hdr);
> -				if (ret < 0)
> -					goto drop_skb;
> -
> -				return lowpan_give_skb_to_device(skb, wdev);
> -			} else if (ret == -1) {
> -				return NET_RX_DROP;
> -			} else {
> -				return NET_RX_SUCCESS;
> -			}
> -		case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
> -			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
> -			if (ret == 1) {
> -				ret = iphc_decompress(skb, &hdr);
> -				if (ret < 0)
> -					goto drop_skb;
> -
> -				return lowpan_give_skb_to_device(skb, wdev);
> -			} else if (ret == -1) {
> -				return NET_RX_DROP;
> -			} else {
> -				return NET_RX_SUCCESS;
> -			}
> -		default:
> -			break;
> -		}
> +	/* When receive frag1 it's likely that we manipulate the buffer.
> +	 * When recevie iphc we manipulate the data buffer. So we need
> +	 * to unshare the buffer.
> +	 */
> +	if (lowpan_is_frag1(*skb_network_header(skb)) ||
> +	    lowpan_is_iphc(*skb_network_header(skb))) {
> +		skb = skb_unshare(skb, GFP_ATOMIC);
> +		if (!skb)
> +			return RX_DROP;
>   	}
>   
> -drop_skb:
> -	kfree_skb(skb);
> -drop:
> -	return NET_RX_DROP;
> +	return lowpan_invoke_rx_handlers(skb);
>   }
>   
>   static struct packet_type lowpan_packet_type = {

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open
  2015-08-30 21:48   ` Stefan Schmidt
@ 2015-09-01  7:38     ` Alexander Aring
  2015-09-01  7:45       ` Stefan Schmidt
  0 siblings, 1 reply; 37+ messages in thread
From: Alexander Aring @ 2015-09-01  7:38 UTC (permalink / raw)
  To: Stefan Schmidt; +Cc: linux-wpan, kernel

On Sun, Aug 30, 2015 at 11:48:28PM +0200, Stefan Schmidt wrote:
> Hello.
> 
> On 20/08/15 18:47, Alexander Aring wrote:
> >This patch moves the open count handling while doing open of a lowpan
> >interface. We need the packet handler register at first when one lowpan
> >interface is up.
> The code itself looks fine, but I have trouble to gte the why from your
> commit message. Why is this change needed?
> 

It's a slightly improvement. There exists a small case when ALL lowpan
interfaces are down and the ieee802154_6lowpan module still receives
frames. We don't need to receive frames when all lowpan interfaces are
down. This will end always in the upcomming (!netif_running(ldev))
condition.

Does it sounds useful?

> >Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> >---
> >  net/ieee802154/6lowpan/core.c | 28 ++++++++++++++++++----------
> >  1 file changed, 18 insertions(+), 10 deletions(-)
> >
> >diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
> >index 3cc76f0..8e9da1d 100644
> >--- a/net/ieee802154/6lowpan/core.c
> >+++ b/net/ieee802154/6lowpan/core.c
> >@@ -76,9 +76,27 @@ static int lowpan_dev_init(struct net_device *ldev)
> >  	return 0;
> >  }
> >+static int lowpan_open(struct net_device *dev)
> >+{
> >+	if (!open_count)
> >+		lowpan_rx_init();
> >+	open_count++;
> >+	return 0;
> >+}
> >+
> >+static int lowpan_stop(struct net_device *dev)
> >+{
> >+	open_count--;
> >+	if (!open_count)
> >+		lowpan_rx_exit();
> >+	return 0;
> >+}
> >+
> >  static const struct net_device_ops lowpan_netdev_ops = {
> >  	.ndo_init		= lowpan_dev_init,
> >  	.ndo_start_xmit		= lowpan_xmit,
> >+	.ndo_open		= lowpan_open,
> >+	.ndo_stop		= lowpan_stop,
> >  };
> >  static void lowpan_setup(struct net_device *ldev)
> >@@ -149,11 +167,6 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
> >  	}
> >  	wdev->ieee802154_ptr->lowpan_dev = ldev;
> >-	if (!open_count)
> >-		lowpan_rx_init();
> >-
> >-	open_count++;
> >-
> >  	return 0;
> >  }
> >@@ -163,11 +176,6 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
> >  	ASSERT_RTNL();
> >-	open_count--;
> >-
> >-	if (!open_count)
> >-		lowpan_rx_exit();
> >-
> >  	wdev->ieee802154_ptr->lowpan_dev = NULL;
> >  	unregister_netdevice(ldev);
> >  	dev_put(wdev);
> 
> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
> 

Why is this a SOB?

- Alex

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch
  2015-08-30 22:00   ` Stefan Schmidt
@ 2015-09-01  7:39     ` Alexander Aring
  2015-09-01  7:56     ` Stefan Schmidt
  1 sibling, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-09-01  7:39 UTC (permalink / raw)
  To: Stefan Schmidt; +Cc: linux-wpan, kernel

On Mon, Aug 31, 2015 at 12:00:54AM +0200, Stefan Schmidt wrote:
> Hello.
> 
> On 20/08/15 18:47, Alexander Aring wrote:
> >This patch adds checks for reserved dispatch value. When we have a
> >reserved dispatch value we should drop the skb immediately.
> >
> >Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> >---
> >  net/ieee802154/6lowpan/rx.c | 14 +++++++++++++-
> >  1 file changed, 13 insertions(+), 1 deletion(-)
> >
> >diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
> >index d309d91..f98ebf5 100644
> >--- a/net/ieee802154/6lowpan/rx.c
> >+++ b/net/ieee802154/6lowpan/rx.c
> >@@ -260,6 +260,17 @@ static inline bool lowpan_is_nalp(u8 dispatch)
> >  	return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_NALP;
> >  }
> >+/* Lookup for reserved dispatch values at:
> >+ * https://www.iana.org/assignments/_6lowpan-parameters/_6lowpan-parameters.xhtml#_6lowpan-parameters-1
> It might be worth noting down the update date here as well. The do not seem
> to have a version I can find easily so the update date might be a good idea
> to help helping looking at it to decide if we should update our code.
> 

ok.

- Alex

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework
  2015-08-31  9:28   ` Stefan Schmidt
@ 2015-09-01  7:43     ` Alexander Aring
  0 siblings, 0 replies; 37+ messages in thread
From: Alexander Aring @ 2015-09-01  7:43 UTC (permalink / raw)
  To: Stefan Schmidt; +Cc: linux-wpan, kernel

On Mon, Aug 31, 2015 at 11:28:45AM +0200, Stefan Schmidt wrote:
> Hello.
> 
> On 20/08/15 18:47, Alexander Aring wrote:
> >This patch complete reworks the evaluation of 6lowpan dispatch value by
> >introducing a receive handler mechanism for each dispatch value.
> >
> >A list of changes:
> >
> >  - Doing uncompression on-the-fly when FRAG1 is received, this require
> >    some special handling for 802.15.4 lltype in generic 6lowpan branch
> >    for setting the payload length correct.
> >  - Fix dispatch mask for fragmentation.
> >  - Add IPv6 dispatch evaluation for FRAG1.
> >  - Add skb_unshare for dispatch which might manipulate the skb data
> >    buffer.
> >
> >Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> >---
> >  include/net/6lowpan.h               |  31 ++++--
> 
> Not sure if you might want to include Jukka here for the shared header part
> with BT.

Yes, I will do that when sending PATCH. Maybe I should also split this
patch, but I think it's fine. Very small changes.

> >  net/6lowpan/iphc.c                  |  13 ++-
> >  net/6lowpan/nhc_udp.c               |  13 ++-
> >  net/ieee802154/6lowpan/6lowpan_i.h  |  12 +++
> >  net/ieee802154/6lowpan/reassembly.c | 126 +++++++++++++++++-------
> >  net/ieee802154/6lowpan/rx.c         | 188 ++++++++++++++++++++++++------------
> >  6 files changed, 278 insertions(+), 105 deletions(-)
> >
> >diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
> >index a2f59ec..3509841 100644
> >--- a/include/net/6lowpan.h
> >+++ b/include/net/6lowpan.h
> >@@ -126,13 +126,19 @@
> >  	 (((a)[6]) == 0xFF) &&	\
> >  	 (((a)[7]) == 0xFF))
> >-#define LOWPAN_DISPATCH_IPV6	0x41 /* 01000001 = 65 */
> >-#define LOWPAN_DISPATCH_HC1	0x42 /* 01000010 = 66 */
> >-#define LOWPAN_DISPATCH_IPHC	0x60 /* 011xxxxx = ... */
> >-#define LOWPAN_DISPATCH_FRAG1	0xc0 /* 11000xxx */
> >-#define LOWPAN_DISPATCH_FRAGN	0xe0 /* 11100xxx */
> >+#define LOWPAN_DISPATCH_IPV6		0x41 /* 01000001 = 65 */
> >+#define LOWPAN_DISPATCH_IPHC		0x60 /* 011xxxxx = ... */
> >+#define LOWPAN_DISPATCH_IPHC_MASK	0xe0
> >-#define LOWPAN_DISPATCH_MASK	0xf8 /* 11111000 */
> >+static inline bool lowpan_is_ipv6(u8 dispatch)
> >+{
> >+	return dispatch == LOWPAN_DISPATCH_IPV6;
> >+}
> >+
> >+static inline bool lowpan_is_iphc(u8 dispatch)
> >+{
> >+	return (dispatch & LOWPAN_DISPATCH_IPHC_MASK) == LOWPAN_DISPATCH_IPHC;
> >+}
> >  #define LOWPAN_FRAG_TIMEOUT	(HZ * 60)	/* time-out 60 sec */
> >@@ -218,6 +224,19 @@ struct lowpan_priv *lowpan_priv(const struct net_device *dev)
> >  	return netdev_priv(dev);
> >  }
> >+struct lowpan_802154_cb {
> >+	u16 d_tag;
> >+	unsigned int d_size;
> >+	u8 d_offset;
> >+};
> >+
> >+static inline
> >+struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb)
> >+{
> >+	BUILD_BUG_ON(sizeof(struct lowpan_802154_cb) > sizeof(skb->cb));
> >+	return (struct lowpan_802154_cb *)skb->cb;
> >+}
> >+
> >  #ifdef DEBUG
> >  /* print data in line */
> >  static inline void raw_dump_inline(const char *caller, char *msg,
> >diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
> >index 1e0071f..78c8a49 100644
> >--- a/net/6lowpan/iphc.c
> >+++ b/net/6lowpan/iphc.c
> >@@ -366,7 +366,18 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
> >  			return err;
> >  	}
> >-	hdr.payload_len = htons(skb->len);
> >+	switch (lowpan_priv(dev)->lltype) {
> >+	case LOWPAN_LLTYPE_IEEE802154:
> >+		if (lowpan_802154_cb(skb)->d_size)
> >+			hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size -
> >+						sizeof(struct ipv6hdr));
> >+		else
> >+			hdr.payload_len = htons(skb->len);
> >+		break;
> >+	default:
> >+		hdr.payload_len = htons(skb->len);
> 
> The default and else block being the same here I think that can be
> simplified.
> >+		break;
> >+	}
> >  	pr_debug("skb headroom size = %d, data length = %d\n",
> >  		 skb_headroom(skb), skb->len);
> >diff --git a/net/6lowpan/nhc_udp.c b/net/6lowpan/nhc_udp.c
> >index c6bcaeb..72d0b57 100644
> >--- a/net/6lowpan/nhc_udp.c
> >+++ b/net/6lowpan/nhc_udp.c
> >@@ -71,7 +71,18 @@ static int udp_uncompress(struct sk_buff *skb, size_t needed)
> >  	 * here, we obtain the hint from the remaining size of the
> >  	 * frame
> >  	 */
> >-	uh.len = htons(skb->len + sizeof(struct udphdr));
> >+	switch (lowpan_priv(skb->dev)->lltype) {
> >+	case LOWPAN_LLTYPE_IEEE802154:
> >+		if (lowpan_802154_cb(skb)->d_size)
> >+			uh.len = htons(lowpan_802154_cb(skb)->d_size -
> >+				       sizeof(struct ipv6hdr));
> >+		else
> >+			uh.len = htons(skb->len + sizeof(struct udphdr));
> >+		break;
> >+	default:
> >+		uh.len = htons(skb->len + sizeof(struct udphdr));
> >+		break;
> >+	}
> 
> Else branch and default case same again.

I see no optimiziation here, what we could do would be a set of "uh.len"
like default case and then overwrite it -> but this confuse other
programmers.

> >  	pr_debug("uncompressed UDP length: src = %d", ntohs(uh.len));
> >  	/* replace the compressed UDP head by the uncompressed UDP
> >diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h
> >index 9aa7b62..b4e17a7 100644
> >--- a/net/ieee802154/6lowpan/6lowpan_i.h
> >+++ b/net/ieee802154/6lowpan/6lowpan_i.h
> >@@ -7,6 +7,15 @@
> >  #include <net/inet_frag.h>
> >  #include <net/6lowpan.h>
> >+typedef unsigned __bitwise__ lowpan_rx_result;
> >+#define RX_CONTINUE		((__force lowpan_rx_result) 0u)
> >+#define RX_DROP_UNUSABLE	((__force lowpan_rx_result) 1u)
> >+#define RX_DROP			((__force lowpan_rx_result) 2u)
> >+#define RX_QUEUED		((__force lowpan_rx_result) 3u)
> >+
> >+#define LOWPAN_DISPATCH_FRAG1           0xc0
> >+#define LOWPAN_DISPATCH_FRAGN           0xe0
> >+
> >  struct lowpan_create_arg {
> >  	u16 tag;
> >  	u16 d_size;
> >@@ -62,4 +71,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
> >  			 const void *_saddr, unsigned int len);
> >  netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev);
> >+int lowpan_iphc_decompress(struct sk_buff *skb);
> >+lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb);
> >+
...
> >+}
> >+
> >+static int lowpan_get_cb(struct sk_buff *skb, u8 frag_type,
> >+			 struct lowpan_802154_cb *cb)
> >  {
> >  	bool fail;
> >  	u8 pattern = 0, low = 0;
> >@@ -334,15 +376,19 @@ static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
> >  	fail = lowpan_fetch_skb(skb, &pattern, 1);
> >  	fail |= lowpan_fetch_skb(skb, &low, 1);
> >-	frag_info->d_size = (pattern & 7) << 8 | low;
> >+	cb->d_size = (pattern & 7) << 8 | low;
> 
> Magic numbers. Yeah,. I know they have been there before.

ok. Will introduce some define above this function.

- Alex

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open
  2015-09-01  7:38     ` Alexander Aring
@ 2015-09-01  7:45       ` Stefan Schmidt
  0 siblings, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-09-01  7:45 UTC (permalink / raw)
  To: Alexander Aring; +Cc: linux-wpan, kernel

Hello.

On 01/09/15 09:38, Alexander Aring wrote:
> On Sun, Aug 30, 2015 at 11:48:28PM +0200, Stefan Schmidt wrote:
>> Hello.
>>
>> On 20/08/15 18:47, Alexander Aring wrote:
>>> This patch moves the open count handling while doing open of a lowpan
>>> interface. We need the packet handler register at first when one lowpan
>>> interface is up.
>> The code itself looks fine, but I have trouble to gte the why from your
>> commit message. Why is this change needed?
>>
> It's a slightly improvement. There exists a small case when ALL lowpan
> interfaces are down and the ieee802154_6lowpan module still receives
> frames. We don't need to receive frames when all lowpan interfaces are
> down. This will end always in the upcomming (!netif_running(ldev))
> condition.
>
> Does it sounds useful?

Yes, having this explanation in the commit message would be good.
>>> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>>> ---
>>>   net/ieee802154/6lowpan/core.c | 28 ++++++++++++++++++----------
>>>   1 file changed, 18 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
>>> index 3cc76f0..8e9da1d 100644
>>> --- a/net/ieee802154/6lowpan/core.c
>>> +++ b/net/ieee802154/6lowpan/core.c
>>> @@ -76,9 +76,27 @@ static int lowpan_dev_init(struct net_device *ldev)
>>>   	return 0;
>>>   }
>>> +static int lowpan_open(struct net_device *dev)
>>> +{
>>> +	if (!open_count)
>>> +		lowpan_rx_init();
>>> +	open_count++;
>>> +	return 0;
>>> +}
>>> +
>>> +static int lowpan_stop(struct net_device *dev)
>>> +{
>>> +	open_count--;
>>> +	if (!open_count)
>>> +		lowpan_rx_exit();
>>> +	return 0;
>>> +}
>>> +
>>>   static const struct net_device_ops lowpan_netdev_ops = {
>>>   	.ndo_init		= lowpan_dev_init,
>>>   	.ndo_start_xmit		= lowpan_xmit,
>>> +	.ndo_open		= lowpan_open,
>>> +	.ndo_stop		= lowpan_stop,
>>>   };
>>>   static void lowpan_setup(struct net_device *ldev)
>>> @@ -149,11 +167,6 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
>>>   	}
>>>   	wdev->ieee802154_ptr->lowpan_dev = ldev;
>>> -	if (!open_count)
>>> -		lowpan_rx_init();
>>> -
>>> -	open_count++;
>>> -
>>>   	return 0;
>>>   }
>>> @@ -163,11 +176,6 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
>>>   	ASSERT_RTNL();
>>> -	open_count--;
>>> -
>>> -	if (!open_count)
>>> -		lowpan_rx_exit();
>>> -
>>>   	wdev->ieee802154_ptr->lowpan_dev = NULL;
>>>   	unregister_netdevice(ldev);
>>>   	dev_put(wdev);
>> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
>>
> Why is this a SOB?

Because it was late and I screwed up. :( Sorry.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 03/16] ieee802154: 6lowpan: remove check on null
  2015-08-30 21:49   ` Stefan Schmidt
@ 2015-09-01  7:52     ` Stefan Schmidt
  0 siblings, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-09-01  7:52 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 30/08/15 23:49, Stefan Schmidt wrote:
> Hello.
>
> On 20/08/15 18:47, Alexander Aring wrote:
>> This patch removes one check on null which should be already done by
>> checking before for ARPHRD_IEEE802154. All ARPHRD_IEEE802154 and
>> ARPHRD_IEEE802154_MONITOR should have wdev->ieee802154_ptr, where
>> ARPHRD_IEEE802154 is currently a node interface only.
>>
>> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>> ---
>>   net/ieee802154/6lowpan/core.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/net/ieee802154/6lowpan/core.c 
>> b/net/ieee802154/6lowpan/core.c
>> index 8e9da1d..6607bb4 100644
>> --- a/net/ieee802154/6lowpan/core.c
>> +++ b/net/ieee802154/6lowpan/core.c
>> @@ -214,7 +214,7 @@ static int lowpan_device_event(struct 
>> notifier_block *unused,
>>            * also delete possible lowpan interfaces which belongs
>>            * to the wpan interface.
>>            */
>> -        if (wdev->ieee802154_ptr && wdev->ieee802154_ptr->lowpan_dev)
>> +        if (wdev->ieee802154_ptr->lowpan_dev)
>> lowpan_dellink(wdev->ieee802154_ptr->lowpan_dev, NULL);
>>           break;
>>       default:
>
> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

This should also have been

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 06/16] ieee802154: 6lowpan: change if lowpan dev is running
  2015-08-30 21:51   ` Stefan Schmidt
@ 2015-09-01  7:53     ` Stefan Schmidt
  0 siblings, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-09-01  7:53 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 30/08/15 23:51, Stefan Schmidt wrote:
> Hello.
>
> On 20/08/15 18:47, Alexander Aring wrote:
>> We don't need to check if the wpan interface is running because the
>> lowpan_rcv is the packet layer receive handler for the wpan interface.
>>
>> Instead doing a check if wpan interface is running we should check if
>> the lowpan interface is running before starting 6lowpan adaptation 
>> layer.
>>
>> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>> ---
>>   net/ieee802154/6lowpan/rx.c | 11 ++++++-----
>>   1 file changed, 6 insertions(+), 5 deletions(-)
>>
>> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
>> index b1442f3..c529d9f 100644
>> --- a/net/ieee802154/6lowpan/rx.c
>> +++ b/net/ieee802154/6lowpan/rx.c
>> @@ -65,19 +65,20 @@ static int lowpan_rcv(struct sk_buff *skb, struct 
>> net_device *wdev,
>>                 struct packet_type *pt, struct net_device *orig_wdev)
>>   {
>>       struct ieee802154_hdr hdr;
>> +    struct net_device *ldev;
>>       int ret;
>>   -    if (wdev->type != ARPHRD_IEEE802154 ||
>> -        !wdev->ieee802154_ptr->lowpan_dev)
>> +    if (wdev->type != ARPHRD_IEEE802154)
>> +        goto drop;
>> +
>> +    ldev = wdev->ieee802154_ptr->lowpan_dev;
>> +    if (!ldev || !netif_running(ldev))
>>           goto drop;
>>         skb = skb_share_check(skb, GFP_ATOMIC);
>>       if (!skb)
>>           goto drop;
>>   -    if (!netif_running(wdev))
>> -        goto drop_skb;
>> -
>>       if (skb->pkt_type == PACKET_OTHERHOST)
>>           goto drop_skb;
>
> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
>

This should also have been

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 09/16] ieee802154: 6lowpan: earlier skb->dev switch
  2015-08-30 21:54   ` Stefan Schmidt
@ 2015-09-01  7:53     ` Stefan Schmidt
  0 siblings, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-09-01  7:53 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 30/08/15 23:54, Stefan Schmidt wrote:
> Hello.
>
> On 20/08/15 18:47, Alexander Aring wrote:
>> We should change the skb->dev pointer earlier to the lowpan interface
>> Sometimes we call iphc_decompress which also use some netdev printout
>> functionality. This patch will change that the correct interface will be
>> displayed in this case, which should be the lowpan interface.
>>
>> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>> ---
>>   net/ieee802154/6lowpan/rx.c | 3 ++-
>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
>> index 74d8fec..f9cb70b 100644
>> --- a/net/ieee802154/6lowpan/rx.c
>> +++ b/net/ieee802154/6lowpan/rx.c
>> @@ -18,7 +18,6 @@
>>   static int lowpan_give_skb_to_device(struct sk_buff *skb,
>>                        struct net_device *wdev)
>>   {
>> -    skb->dev = wdev->ieee802154_ptr->lowpan_dev;
>>       skb->protocol = htons(ETH_P_IPV6);
>>       skb->pkt_type = PACKET_HOST;
>>   @@ -71,9 +70,11 @@ static int lowpan_rcv(struct sk_buff *skb, 
>> struct net_device *wdev,
>>       if (!ldev || !netif_running(ldev))
>>           goto drop;
>>   +    /* Replacing skb->dev and followed rx handlers will manipulate 
>> skb. */
>>       skb = skb_share_check(skb, GFP_ATOMIC);
>>       if (!skb)
>>           goto drop;
>> +    skb->dev = ldev;
>>         if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
>>           goto drop_skb;
>
> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
>

This should also have been

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch
  2015-08-30 22:00   ` Stefan Schmidt
  2015-09-01  7:39     ` Alexander Aring
@ 2015-09-01  7:56     ` Stefan Schmidt
  1 sibling, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-09-01  7:56 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 31/08/15 00:00, Stefan Schmidt wrote:
> Hello.
>
> On 20/08/15 18:47, Alexander Aring wrote:
>> This patch adds checks for reserved dispatch value. When we have a
>> reserved dispatch value we should drop the skb immediately.
>>
>> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>> ---
>>   net/ieee802154/6lowpan/rx.c | 14 +++++++++++++-
>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
>> index d309d91..f98ebf5 100644
>> --- a/net/ieee802154/6lowpan/rx.c
>> +++ b/net/ieee802154/6lowpan/rx.c
>> @@ -260,6 +260,17 @@ static inline bool lowpan_is_nalp(u8 dispatch)
>>       return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_NALP;
>>   }
>>   +/* Lookup for reserved dispatch values at:
>> + * 
>> https://www.iana.org/assignments/_6lowpan-parameters/_6lowpan-parameters.xhtml#_6lowpan-parameters-1
> It might be worth noting down the update date here as well. The do not 
> seem to have a version I can find easily so the update date might be a 
> good idea to help helping looking at it to decide if we should update 
> our code.
>
>> + */
>> +static inline bool lowpan_is_reserved(u8 dispatch)
>> +{
>> +    return ((dispatch >= 0x44 && dispatch <= 0x4F) ||
>> +        (dispatch >= 0x51 && dispatch <= 0x5F) ||
>> +        (dispatch >= 0xc8 && dispatch <= 0xdf) ||
>> +        (dispatch >= 0xe8 && dispatch <= 0xff));
>> +}
>> +
>>   /* lowpan_rx_h_check checks on generic 6LoWPAN requirements
>>    * in MAC and 6LoWPAN header.
>>    *
>> @@ -271,7 +282,8 @@ static inline bool lowpan_rx_h_check(struct 
>> sk_buff *skb)
>>       if (unlikely(!skb->len))
>>           return false;
>>   -    if (lowpan_is_nalp(*skb_network_header(skb)))
>> +    if (lowpan_is_nalp(*skb_network_header(skb)) ||
>> +        lowpan_is_reserved(*skb_network_header(skb)))
>>           return false;
>>         return true;
>
> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
>

This should also have been

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 14/16] ieee802154: 6lowpan: check on valid 802.15.4 frame
  2015-08-30 22:03   ` Stefan Schmidt
@ 2015-09-01  7:57     ` Stefan Schmidt
  0 siblings, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-09-01  7:57 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 31/08/15 00:03, Stefan Schmidt wrote:
> Hello.
>
> On 20/08/15 18:47, Alexander Aring wrote:
>> This patch adds frame control checks to check if the received frame is
>> something which could contain a 6LoWPAN packet.
>>
>> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>> ---
>>   include/linux/ieee802154.h  | 25 +++++++++++++++++++++++++
>>   include/net/mac802154.h     | 15 +++++++++++++++
>>   net/ieee802154/6lowpan/rx.c |  8 ++++++++
>>   3 files changed, 48 insertions(+)
>>
>> diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
>> index 1dc1f4e..db01492 100644
>> --- a/include/linux/ieee802154.h
>> +++ b/include/linux/ieee802154.h
>> @@ -205,6 +205,31 @@ enum {
>>       IEEE802154_SCAN_IN_PROGRESS = 0xfc,
>>   };
>>   +/* frame control handling */
>> +#define IEEE802154_FCTL_FTYPE        0x0003
>> +#define IEEE802154_FCTL_INTRA_PAN    0x0040
>> +
>> +#define IEEE802154_FTYPE_DATA        0x0001
>> +
>> +/*
>> + * ieee802154_is_data - check if type is IEEE802154_FTYPE_DATA
>> + * @fc: frame control bytes in little-endian byteorder
>> + */
>> +static inline int ieee802154_is_data(__le16 fc)
>> +{
>> +    return (fc & cpu_to_le16(IEEE802154_FCTL_FTYPE)) ==
>> +        cpu_to_le16(IEEE802154_FTYPE_DATA);
>> +}
>> +
>> +/**
>> + * ieee802154_is_intra_pan - check if intra pan id communication
>> + * @fc: frame control bytes in little-endian byteorder
>> + */
>> +static inline bool ieee802154_is_intra_pan(__le16 fc)
>> +{
>> +    return fc & cpu_to_le16(IEEE802154_FCTL_INTRA_PAN);
>> +}
>> +
>>   /**
>>    * ieee802154_is_valid_psdu_len - check if psdu len is valid
>>    * available lengths:
>> diff --git a/include/net/mac802154.h b/include/net/mac802154.h
>> index b7f9961..32bd7c0 100644
>> --- a/include/net/mac802154.h
>> +++ b/include/net/mac802154.h
>> @@ -250,6 +250,21 @@ struct ieee802154_ops {
>>   };
>>     /**
>> + * ieee802154_get_fc_from_skb - get the frame control field from an skb
>> + * @skb: skb where the frame control field will be get from
>> + */
>> +static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff 
>> *skb)
>> +{
>> +    /* return some invalid fc on failure */
>> +    if (unlikely(skb->mac_len < 2)) {
>> +        WARN_ON(1);
>> +        return cpu_to_le16(0);
>> +    }
>> +
>> +    return (__force 
>> __le16)__get_unaligned_memmove16(skb_mac_header(skb));
>> +}
>> +
>> +/**
>>    * ieee802154_be64_to_le64 - copies and convert be64 to le64
>>    * @le64_dst: le64 destination pointer
>>    * @be64_src: be64 source pointer
>> diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
>> index f98ebf5..5be996a 100644
>> --- a/net/ieee802154/6lowpan/rx.c
>> +++ b/net/ieee802154/6lowpan/rx.c
>> @@ -11,6 +11,7 @@
>>   #include <linux/if_arp.h>
>>     #include <net/6lowpan.h>
>> +#include <net/mac802154.h>
>>   #include <net/ieee802154_netdev.h>
>>     #include "6lowpan_i.h"
>> @@ -278,6 +279,13 @@ static inline bool lowpan_is_reserved(u8 dispatch)
>>    */
>>   static inline bool lowpan_rx_h_check(struct sk_buff *skb)
>>   {
>> +    __le16 fc = ieee802154_get_fc_from_skb(skb);
>> +
>> +    /* check on ieee802154 conform 6LoWPAN header */
>> +    if (!ieee802154_is_data(fc) ||
>> +        !ieee802154_is_intra_pan(fc))
>> +        return false;
>> +
>>       /* check if we can dereference the dispatch */
>>       if (unlikely(!skb->len))
>>           return false;
>
> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
>

This should also have been

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFCv2 bluetooth-next 16/16] ieee802154: 6lowpan: remove tx full-size calc workaround
  2015-08-30 22:06   ` Stefan Schmidt
@ 2015-09-01  7:57     ` Stefan Schmidt
  0 siblings, 0 replies; 37+ messages in thread
From: Stefan Schmidt @ 2015-09-01  7:57 UTC (permalink / raw)
  To: Alexander Aring, linux-wpan; +Cc: kernel

Hello.

On 31/08/15 00:06, Stefan Schmidt wrote:
> Hello.
>
> On 20/08/15 18:47, Alexander Aring wrote:
>> This patch removes a workaround for datagram_size calculation while
>> doing fragmentation on transmit.
>>
>> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>> ---
>>   include/net/6lowpan.h       | 113 
>> --------------------------------------------
>>   net/ieee802154/6lowpan/tx.c |  18 ++++---
>>   2 files changed, 11 insertions(+), 120 deletions(-)
>>
>> diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
>> index 3509841..eeae5eb 100644
>> --- a/include/net/6lowpan.h
>> +++ b/include/net/6lowpan.h
>> @@ -299,119 +299,6 @@ static inline void lowpan_push_hc_data(u8 
>> **hc_ptr, const void *data,
>>       *hc_ptr += len;
>>   }
>>   -static inline u8 lowpan_addr_mode_size(const u8 addr_mode)
>> -{
>> -    static const u8 addr_sizes[] = {
>> -        [LOWPAN_IPHC_ADDR_00] = 16,
>> -        [LOWPAN_IPHC_ADDR_01] = 8,
>> -        [LOWPAN_IPHC_ADDR_02] = 2,
>> -        [LOWPAN_IPHC_ADDR_03] = 0,
>> -    };
>> -    return addr_sizes[addr_mode];
>> -}
>> -
>> -static inline u8 lowpan_next_hdr_size(const u8 h_enc, u16 
>> *uncomp_header)
>> -{
>> -    u8 ret = 1;
>> -
>> -    if ((h_enc & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
>> -        *uncomp_header += sizeof(struct udphdr);
>> -
>> -        switch (h_enc & LOWPAN_NHC_UDP_CS_P_11) {
>> -        case LOWPAN_NHC_UDP_CS_P_00:
>> -            ret += 4;
>> -            break;
>> -        case LOWPAN_NHC_UDP_CS_P_01:
>> -        case LOWPAN_NHC_UDP_CS_P_10:
>> -            ret += 3;
>> -            break;
>> -        case LOWPAN_NHC_UDP_CS_P_11:
>> -            ret++;
>> -            break;
>> -        default:
>> -            break;
>> -        }
>> -
>> -        if (!(h_enc & LOWPAN_NHC_UDP_CS_C))
>> -            ret += 2;
>> -    }
>> -
>> -    return ret;
>> -}
>> -
>> -/**
>> - *    lowpan_uncompress_size - returns skb->len size with 
>> uncompressed header
>> - *    @skb: sk_buff with 6lowpan header inside
>> - *    @datagram_offset: optional to get the datagram_offset value
>> - *
>> - *    Returns the skb->len with uncompressed header
>> - */
>> -static inline u16
>> -lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
>> -{
>> -    u16 ret = 2, uncomp_header = sizeof(struct ipv6hdr);
>> -    u8 iphc0, iphc1, h_enc;
>> -
>> -    iphc0 = skb_network_header(skb)[0];
>> -    iphc1 = skb_network_header(skb)[1];
>> -
>> -    switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
>> -    case 0:
>> -        ret += 4;
>> -        break;
>> -    case 1:
>> -        ret += 3;
>> -        break;
>> -    case 2:
>> -        ret++;
>> -        break;
>> -    default:
>> -        break;
>> -    }
>> -
>> -    if (!(iphc0 & LOWPAN_IPHC_NH_C))
>> -        ret++;
>> -
>> -    if (!(iphc0 & 0x03))
>> -        ret++;
>> -
>> -    ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_SAM) >>
>> -                     LOWPAN_IPHC_SAM_BIT);
>> -
>> -    if (iphc1 & LOWPAN_IPHC_M) {
>> -        switch ((iphc1 & LOWPAN_IPHC_DAM_11) >>
>> -            LOWPAN_IPHC_DAM_BIT) {
>> -        case LOWPAN_IPHC_DAM_00:
>> -            ret += 16;
>> -            break;
>> -        case LOWPAN_IPHC_DAM_01:
>> -            ret += 6;
>> -            break;
>> -        case LOWPAN_IPHC_DAM_10:
>> -            ret += 4;
>> -            break;
>> -        case LOWPAN_IPHC_DAM_11:
>> -            ret++;
>> -            break;
>> -        default:
>> -            break;
>> -        }
>> -    } else {
>> -        ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_DAM_11) >>
>> -                         LOWPAN_IPHC_DAM_BIT);
>> -    }
>> -
>> -    if (iphc0 & LOWPAN_IPHC_NH_C) {
>> -        h_enc = skb_network_header(skb)[ret];
>> -        ret += lowpan_next_hdr_size(h_enc, &uncomp_header);
>> -    }
>> -
>> -    if (dgram_offset)
>> -        *dgram_offset = uncomp_header;
>> -
>> -    return skb->len + uncomp_header - ret;
>> -}
>> -
>>   void lowpan_netdev_setup(struct net_device *dev, enum 
>> lowpan_lltypes lltype);
>>     int
>> diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
>> index 9a2147e..4115335 100644
>> --- a/net/ieee802154/6lowpan/tx.c
>> +++ b/net/ieee802154/6lowpan/tx.c
>> @@ -123,16 +123,14 @@ lowpan_xmit_fragment(struct sk_buff *skb, const 
>> struct ieee802154_hdr *wpan_hdr,
>>     static int
>>   lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev,
>> -               const struct ieee802154_hdr *wpan_hdr)
>> +               const struct ieee802154_hdr *wpan_hdr, u16 dgram_size,
>> +               u16 dgram_offset)
>>   {
>> -    u16 dgram_size, dgram_offset;
>>       __be16 frag_tag;
>>       u8 frag_hdr[5];
>>       int frag_cap, frag_len, payload_cap, rc;
>>       int skb_unprocessed, skb_offset;
>>   -    dgram_size = lowpan_uncompress_size(skb, &dgram_offset) -
>> -             skb->mac_len;
>>       frag_tag = htons(lowpan_dev_info(ldev)->fragment_tag);
>>       lowpan_dev_info(ldev)->fragment_tag++;
>>   @@ -187,7 +185,8 @@ err:
>>       return rc;
>>   }
>>   -static int lowpan_header(struct sk_buff *skb, struct net_device 
>> *ldev)
>> +static int lowpan_header(struct sk_buff *skb, struct net_device *ldev,
>> +             u16 *dgram_size, u16 *dgram_offset)
>>   {
>>       struct wpan_dev *wpan_dev = 
>> lowpan_dev_info(ldev)->wdev->ieee802154_ptr;
>>       struct ieee802154_addr sa, da;
>> @@ -201,7 +200,10 @@ static int lowpan_header(struct sk_buff *skb, 
>> struct net_device *ldev)
>>       daddr = &info.daddr.u.extended_addr;
>>       saddr = &info.saddr.u.extended_addr;
>>   +    *dgram_size = skb->len;
>>       lowpan_header_compress(skb, ldev, ETH_P_IPV6, daddr, saddr, 
>> skb->len);
>> +    /* dgram_size = (saved bytes after compression) + lowpan header 
>> size */
>> +    *dgram_offset = (*dgram_size - skb->len) + 
>> skb_network_header_len(skb);
>>         cb->type = IEEE802154_FC_TYPE_DATA;
>>   @@ -234,6 +236,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, 
>> struct net_device *ldev)
>>   {
>>       struct ieee802154_hdr wpan_hdr;
>>       int max_single, ret;
>> +    u16 dgram_size, dgram_offset;
>>         pr_debug("package xmit\n");
>>   @@ -244,7 +247,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, 
>> struct net_device *ldev)
>>       if (!skb)
>>           return NET_XMIT_DROP;
>>   -    ret = lowpan_header(skb, ldev);
>> +    ret = lowpan_header(skb, ldev, &dgram_size, &dgram_offset);
>>       if (ret < 0) {
>>           kfree_skb(skb);
>>           return NET_XMIT_DROP;
>> @@ -264,7 +267,8 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, 
>> struct net_device *ldev)
>>           netdev_tx_t rc;
>>             pr_debug("frame is too big, fragmentation is needed\n");
>> -        rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr);
>> +        rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr, dgram_size,
>> +                        dgram_offset);
>>             return rc < 0 ? NET_XMIT_DROP : rc;
>>       }
>
> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
>

This should also have been

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>

regards
Stefan Schmidt

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2015-09-01  7:57 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-20 16:47 [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 01/16] ieee802154: 6lowpan: change dev vars to wdev and ldev Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 02/16] ieee802154: 6lowpan: register packet layer while open Alexander Aring
2015-08-30 21:48   ` Stefan Schmidt
2015-09-01  7:38     ` Alexander Aring
2015-09-01  7:45       ` Stefan Schmidt
2015-08-20 16:47 ` [RFCv2 bluetooth-next 03/16] ieee802154: 6lowpan: remove check on null Alexander Aring
2015-08-30 21:49   ` Stefan Schmidt
2015-09-01  7:52     ` Stefan Schmidt
2015-08-20 16:47 ` [RFCv2 bluetooth-next 04/16] ieee802154: 6lowpan: remove set to zero Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 05/16] ieee802154: 6lowpan: remove EXPORT_SYMBOL Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 06/16] ieee802154: 6lowpan: change if lowpan dev is running Alexander Aring
2015-08-30 21:51   ` Stefan Schmidt
2015-09-01  7:53     ` Stefan Schmidt
2015-08-20 16:47 ` [RFCv2 bluetooth-next 07/16] ieee802154: 6lowpan: cleanup pull of iphc bytes Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 08/16] ieee802154: 6lowpan: trivial checks at first Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 09/16] ieee802154: 6lowpan: earlier skb->dev switch Alexander Aring
2015-08-30 21:54   ` Stefan Schmidt
2015-09-01  7:53     ` Stefan Schmidt
2015-08-20 16:47 ` [RFCv2 bluetooth-next 10/16] ieee820154: 6lowpan: dispatch evaluation rework Alexander Aring
2015-08-27 17:53   ` Alexander Aring
2015-08-31  9:28   ` Stefan Schmidt
2015-09-01  7:43     ` Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 11/16] ieee802154: 6lowpan: add generic lowpan header check Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 12/16] ieee802154: 6lowpan: add handler for all dispatch values Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 13/16] ieee802154: 6lowpan: add check for reserved dispatch Alexander Aring
2015-08-30 22:00   ` Stefan Schmidt
2015-09-01  7:39     ` Alexander Aring
2015-09-01  7:56     ` Stefan Schmidt
2015-08-20 16:47 ` [RFCv2 bluetooth-next 14/16] ieee802154: 6lowpan: check on valid 802.15.4 frame Alexander Aring
2015-08-30 22:03   ` Stefan Schmidt
2015-09-01  7:57     ` Stefan Schmidt
2015-08-20 16:47 ` [RFCv2 bluetooth-next 15/16] ieee802154: 6lowpan: remove packet type to host Alexander Aring
2015-08-20 16:47 ` [RFCv2 bluetooth-next 16/16] ieee802154: 6lowpan: remove tx full-size calc workaround Alexander Aring
2015-08-30 22:06   ` Stefan Schmidt
2015-09-01  7:57     ` Stefan Schmidt
2015-08-30 21:45 ` [RFCv2 bluetooth-next 00/16] ieee802154: 6lowpan: cleanup and rework dispatch evaluation Stefan Schmidt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.