Hi,
I already thought many times to introduce something like that. Here is a draft
for introducing the generic 6lowpan private data into each lowpan interface.
For the beginning I introduced the enum "l2_type" which contains the L2 type of
a lowpan interface.
Use cases for such feature (L2 types):
- If we do in upper layers (6LoWPAN/IPv6) a evaluation of dev->type then
the value is on all lowpan interfaces "APRHRD_6LOWPAN". If we checked on
"dev->type" and it's ARPHRD_6LOWPAN we can safe use lowpan_priv to get
6LoWPAN generic private data. With this data we can check the L2 type which
can be currently BTLE or IEEE802154. This could be useful to make different
handling in iphc compress/decompress and evaluating L2 private data of skb
control block "skb->cb".
Example (802.15.4 has different address handling functionality):
switch (lowpan_priv(dev)->l2_type) {
case LOWPAN_L2_TYPE_BTLE:
/* do EUI64 btle handling */
break;
case LOWPAN_L2_TYPE_IEEE802154:
/* do complicated short/extended address handling */
/* we can surely call skb->cb to some other private data from L2
which was set before iphc compress/decompress function call */
break;
}
The handling is currently for 802.15.4 is in generic 6lowpan code currently
not quite. This should be handled by private data. At the moment btle use
the same handling like for 802.15.4 extended address. Nevertheless is we can
cleanup some handling then in generic iphc functionality.
This also possible in layers like IPv6, just doing a check on APRHRD_6LOWPAN
before calling lowpan_priv(dev)->l2_type, then we are sure that the private
data of the interface is a 6LoWPAN interface and we can cast it to lowpan_priv.
Then we can do 6LoWPAN generic stuff OR 6lowpan specific L2 stuff.
- In Lukasz Duda RFC for introducing stateful address compression, I saw
some behaviour which such functionality is also useful. Currently we don't
have a allocated space for a 6LoWPAN generic space which is assigned to a
lowpan interface. When L2 layers (BTLE, IEEE802154) calls iphc
compress/decompress Lukasz had no change to access some room which is needed
for storing the context information into a table. The workaround for this
feature was to add allocate a static data room for the table and doing a
lookup/match of netdev name. Which a generic 6lowpan private data room per each
lowpan interface we can put this table according to the netdev private room,
which means in short: no lookup is needed anymore, just dereferencing lowpan_priv.
In upper layer like IPv6 Lukasz could use that to get the stateful context
table information as an example for doing 6LoWPAN generic stuff in upper
layers.
Note about the implementation for L2 6LoWPAN private pointer:
I stole some mechanism from wireless for that. See [0], the vif struct is part
of sdata which is also part of private data of a wireless interface (mac80211).
I hope I can just adapt this behaviour.
- Alex
[0] http://lxr.free-electrons.com/source/include/net/mac80211.h#L1366
Alexander Aring (2):
bluetooth: 6lowpan: change netdev_priv to lowpan_dev
6lowpan: add generic 6lowpan netdev private data
include/net/6lowpan.h | 18 ++++++++++++++++++
net/bluetooth/6lowpan.c | 9 ++++++---
net/ieee802154/6lowpan/6lowpan_i.h | 3 ++-
net/ieee802154/6lowpan/core.c | 5 ++++-
4 files changed, 30 insertions(+), 5 deletions(-)
--
2.5.0
On Thu, Jul 30, 2015 at 09:31:59PM +0200, Stefan Schmidt wrote:
> Hello.
>
> On 29/07/15 14:24, Alexander Aring wrote:
> >Hi,
> >
> >I already thought many times to introduce something like that. Here is a draft
> >for introducing the generic 6lowpan private data into each lowpan interface.
> >For the beginning I introduced the enum "l2_type" which contains the L2 type of
> >a lowpan interface.
> >
> >Use cases for such feature (L2 types):
> >
> > - If we do in upper layers (6LoWPAN/IPv6) a evaluation of dev->type then
> > the value is on all lowpan interfaces "APRHRD_6LOWPAN". If we checked on
> > "dev->type" and it's ARPHRD_6LOWPAN we can safe use lowpan_priv to get
> > 6LoWPAN generic private data. With this data we can check the L2 type which
> > can be currently BTLE or IEEE802154. This could be useful to make different
> > handling in iphc compress/decompress and evaluating L2 private data of skb
> > control block "skb->cb".
>
> And there is more to come. Power line, low power wifi, dect, etc. For all of
> them some 6lowpan adaptiona re on the way. Which of them really makes it to
> a full RFC is to be seen but having a L2 type here is a good idea.
In short the use case would be "casting private data corretly":
We have currently the situation that lowpan interfaces uses
ARPHRD_6LOWPAN which is correct for me.
Usually to get the netdev_priv in generic upper layers is:
switch (dev->type) {
case ARPHRD_6LOWPAN:
my_private_data_struct = netdev_priv(dev);
/* do great stuff which is ARPHRD_6LOWPAN related */
break;
case ARPHRD_FOOBAR:
my_private_data_struct = netdev_priv(dev);
/* do great stuff which is ARPHRD_FOOBAR related */
break;
case ...
...
break;
}
with the lowpan_priv struct we have a private data room for 6LoWPAN
generic layer which is allocated per interface (We don't have the option
to make such behaviour above because currently each lowpan interface do
their own link layer stuff in netdev_priv and their share the same
ARPHRD).
What we introduce now is a 6LoWPAN generic + linklayer private data room.
In case of generic 6LoWPAN handling we can do now:
switch (dev->type) {
case ARPHRD_6LOWPAN:
lowpan_data_struct = lowpan_priv(dev);
/* do great stuff which is ARPHRD_6LOWPAN related */
break;
...
}
In case of special linklayer handling (e.g. address handling in
802.15.4) we can do the following now:
switch (dev->type) {
case ARPHRD_6LOWPAN:
lowpan_data_struct = lowpan_priv(dev);
/* do great stuff which is ARPHRD_6LOWPAN related */
switch (lowpan_data_struct->ll_type)
case LOWPAN_LL_TYPE_IEEE802154:
lowpan_802154_data struct = (great cast *)lowpan_priv(dev)->priv;
/* do 802.15.4 6LoWPAN handling here */
break;
....
}
break;
...
}
So we have actually the same mechanism like "switch (dev->type)" ->
"casting private data" for "switch (lowpan_priv(dev)->ll_type)" ->
"casting 6LoWPAN LL private data".
In my opinion we definitely need such behaviour and some "net/6lowpan"
code parts looks already weird because we don't have such mechanism.
It's just some struct hierarchy where we introduce now a private data
for the ARPHRD_6LOWPAN type.
- Alex
On Thu, Jul 30, 2015 at 09:39:17PM +0200, Stefan Schmidt wrote:
> Hello.
>
> On 30/07/15 21:36, Stefan Schmidt wrote:
> >Hello.
> >
> >On 29/07/15 14:24, Alexander Aring wrote:
> >>The usually way to get the btle lowpan private data is to use the
> >>introduced lowpan_dev inline function. This patch will cleanup by using
> >>lowpan_dev consequently.
> >>
> >>Signed-off-by: Alexander Aring <[email protected]>
> >>---
> >> net/bluetooth/6lowpan.c | 2 +-
> >> 1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >>diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> >>index 2fb7b30..93c6ba0 100644
> >>--- a/net/bluetooth/6lowpan.c
> >>+++ b/net/bluetooth/6lowpan.c
> >>@@ -871,7 +871,7 @@ static int setup_netdev(struct l2cap_chan *chan,
> >>struct lowpan_dev **dev)
> >> &chan->src, chan->src_type);
> >> set_bit(__LINK_STATE_PRESENT, &netdev->state);
> >> - *dev = netdev_priv(netdev);
> >>+ *dev = lowpan_dev(netdev);
> >> (*dev)->netdev = netdev;
> >> (*dev)->hdev = chan->conn->hcon->hdev;
> >> INIT_LIST_HEAD(&(*dev)->peers);
> >
> >This patch does no longer apply. There have been 5 patches to the 6lowpan
> >file in bluetooth from Gleen. You need to rebase this one.
> >
> Looking at it in more detail its actually your own patch which makes the
> rebase necessary. The one fixing a possible race.
>
yes, I know. I will send a v2 in the next 24 hours.
- Alex
Hello.
Also needsa a rebase for net/bluetooth/6lowpan.c
Rest applies fine.
regards
Stefan Schmidt
Hello.
On 30/07/15 21:36, Stefan Schmidt wrote:
> Hello.
>
> On 29/07/15 14:24, Alexander Aring wrote:
>> The usually way to get the btle lowpan private data is to use the
>> introduced lowpan_dev inline function. This patch will cleanup by using
>> lowpan_dev consequently.
>>
>> Signed-off-by: Alexander Aring <[email protected]>
>> ---
>> net/bluetooth/6lowpan.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
>> index 2fb7b30..93c6ba0 100644
>> --- a/net/bluetooth/6lowpan.c
>> +++ b/net/bluetooth/6lowpan.c
>> @@ -871,7 +871,7 @@ static int setup_netdev(struct l2cap_chan *chan,
>> struct lowpan_dev **dev)
>> &chan->src, chan->src_type);
>> set_bit(__LINK_STATE_PRESENT, &netdev->state);
>> - *dev = netdev_priv(netdev);
>> + *dev = lowpan_dev(netdev);
>> (*dev)->netdev = netdev;
>> (*dev)->hdev = chan->conn->hcon->hdev;
>> INIT_LIST_HEAD(&(*dev)->peers);
>
> This patch does no longer apply. There have been 5 patches to the
> 6lowpan file in bluetooth from Gleen. You need to rebase this one.
>
Looking at it in more detail its actually your own patch which makes the
rebase necessary. The one fixing a possible race.
regards
Stefan Schmidt
Hello.
On 29/07/15 14:24, Alexander Aring wrote:
> The usually way to get the btle lowpan private data is to use the
> introduced lowpan_dev inline function. This patch will cleanup by using
> lowpan_dev consequently.
>
> Signed-off-by: Alexander Aring <[email protected]>
> ---
> net/bluetooth/6lowpan.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index 2fb7b30..93c6ba0 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -871,7 +871,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev)
> &chan->src, chan->src_type);
> set_bit(__LINK_STATE_PRESENT, &netdev->state);
>
> - *dev = netdev_priv(netdev);
> + *dev = lowpan_dev(netdev);
> (*dev)->netdev = netdev;
> (*dev)->hdev = chan->conn->hcon->hdev;
> INIT_LIST_HEAD(&(*dev)->peers);
This patch does no longer apply. There have been 5 patches to the
6lowpan file in bluetooth from Gleen. You need to rebase this one.
regards
Stefan Schmidt
Hello.
On 29/07/15 14:24, Alexander Aring wrote:
> Hi,
>
> I already thought many times to introduce something like that. Here is a draft
> for introducing the generic 6lowpan private data into each lowpan interface.
> For the beginning I introduced the enum "l2_type" which contains the L2 type of
> a lowpan interface.
>
> Use cases for such feature (L2 types):
>
> - If we do in upper layers (6LoWPAN/IPv6) a evaluation of dev->type then
> the value is on all lowpan interfaces "APRHRD_6LOWPAN". If we checked on
> "dev->type" and it's ARPHRD_6LOWPAN we can safe use lowpan_priv to get
> 6LoWPAN generic private data. With this data we can check the L2 type which
> can be currently BTLE or IEEE802154. This could be useful to make different
> handling in iphc compress/decompress and evaluating L2 private data of skb
> control block "skb->cb".
And there is more to come. Power line, low power wifi, dect, etc. For
all of them some 6lowpan adaptiona re on the way. Which of them really
makes it to a full RFC is to be seen but having a L2 type here is a good
idea.
>
> Example (802.15.4 has different address handling functionality):
>
> switch (lowpan_priv(dev)->l2_type) {
> case LOWPAN_L2_TYPE_BTLE:
> /* do EUI64 btle handling */
> break;
> case LOWPAN_L2_TYPE_IEEE802154:
> /* do complicated short/extended address handling */
> /* we can surely call skb->cb to some other private data from L2
> which was set before iphc compress/decompress function call */
> break;
> }
>
> The handling is currently for 802.15.4 is in generic 6lowpan code currently
> not quite. This should be handled by private data. At the moment btle use
> the same handling like for 802.15.4 extended address. Nevertheless is we can
> cleanup some handling then in generic iphc functionality.
>
> This also possible in layers like IPv6, just doing a check on APRHRD_6LOWPAN
> before calling lowpan_priv(dev)->l2_type, then we are sure that the private
> data of the interface is a 6LoWPAN interface and we can cast it to lowpan_priv.
> Then we can do 6LoWPAN generic stuff OR 6lowpan specific L2 stuff.
>
> - In Lukasz Duda RFC for introducing stateful address compression, I saw
> some behaviour which such functionality is also useful. Currently we don't
> have a allocated space for a 6LoWPAN generic space which is assigned to a
> lowpan interface. When L2 layers (BTLE, IEEE802154) calls iphc
> compress/decompress Lukasz had no change to access some room which is needed
> for storing the context information into a table. The workaround for this
> feature was to add allocate a static data room for the table and doing a
> lookup/match of netdev name. Which a generic 6lowpan private data room per each
> lowpan interface we can put this table according to the netdev private room,
> which means in short: no lookup is needed anymore, just dereferencing lowpan_priv.
>
> In upper layer like IPv6 Lukasz could use that to get the stateful context
> table information as an example for doing 6LoWPAN generic stuff in upper
> layers.
I in favor for having this. Will review the implementation in a moment.
regards
Stefan Schmidt
This patch introduced the 6lowpan netdev private data struct. We name it
lowpan_priv and it's placed at the beginning of netdev private data. All
lowpan interfaces should allocate this room at first of netdev private
data. 6LoWPAN L2 private data can be allocate by additional netdev private
data, e.g. dev->priv_size should be "sizeof(struct lowpan_priv) +
sizeof(L2_LOWPAN_PRIVATE_DATA)".
Signed-off-by: Alexander Aring <[email protected]>
---
include/net/6lowpan.h | 18 ++++++++++++++++++
net/bluetooth/6lowpan.c | 7 +++++--
net/ieee802154/6lowpan/6lowpan_i.h | 3 ++-
net/ieee802154/6lowpan/core.c | 5 ++++-
4 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index dc03d77..7fe7665 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -197,6 +197,24 @@
#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
#define LOWPAN_NHC_UDP_CS_C 0x04 /* checksum elided */
+enum lowpan_l2_types {
+ LOWPAN_L2_TYPE_BTLE,
+ LOWPAN_L2_TYPE_IEEE802154,
+};
+
+struct lowpan_priv {
+ enum lowpan_l2_types l2_type;
+
+ /* must be last */
+ u8 priv[0] __aligned(sizeof(void *));
+};
+
+static inline
+struct lowpan_priv *lowpan_priv(const struct net_device *dev)
+{
+ return ((struct lowpan_priv *)netdev_priv(dev));
+}
+
#ifdef DEBUG
/* print data in line */
static inline void raw_dump_inline(const char *caller, char *msg,
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 93c6ba0..ff14760 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -85,7 +85,7 @@ struct lowpan_dev {
static inline struct lowpan_dev *lowpan_dev(const struct net_device *netdev)
{
- return netdev_priv(netdev);
+ return (struct lowpan_dev *)lowpan_priv(netdev)->priv;
}
static inline void peer_add(struct lowpan_dev *dev, struct lowpan_peer *peer)
@@ -848,7 +848,8 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev)
struct net_device *netdev;
int err = 0;
- netdev = alloc_netdev(sizeof(struct lowpan_dev), IFACE_NAME_TEMPLATE,
+ netdev = alloc_netdev(sizeof(struct lowpan_priv) +
+ sizeof(struct lowpan_dev), IFACE_NAME_TEMPLATE,
NET_NAME_UNKNOWN, netdev_setup);
if (!netdev)
return -ENOMEM;
@@ -859,6 +860,8 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev)
SET_NETDEV_DEV(netdev, &chan->conn->hcon->hdev->dev);
SET_NETDEV_DEVTYPE(netdev, &bt_type);
+ lowpan_priv(netdev)->l2_type = LOWPAN_L2_TYPE_BTLE;
+
err = register_netdev(netdev);
if (err < 0) {
BT_INFO("register_netdev failed %d", err);
diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h
index e50f69d..0dd4e46 100644
--- a/net/ieee802154/6lowpan/6lowpan_i.h
+++ b/net/ieee802154/6lowpan/6lowpan_i.h
@@ -5,6 +5,7 @@
#include <net/ieee802154_netdev.h>
#include <net/inet_frag.h>
+#include <net/6lowpan.h>
struct lowpan_create_arg {
u16 tag;
@@ -52,7 +53,7 @@ struct lowpan_dev_info {
static inline struct
lowpan_dev_info *lowpan_dev_info(const struct net_device *dev)
{
- return netdev_priv(dev);
+ return (struct lowpan_dev_info *)lowpan_priv(dev)->priv;
}
extern struct list_head lowpan_devices;
diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index f20a387..21c9380 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -153,6 +153,8 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
list_add_tail(&entry->list, &lowpan_devices);
mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
+ lowpan_priv(dev)->l2_type = LOWPAN_L2_TYPE_IEEE802154;
+
ret = register_netdevice(dev);
if (ret >= 0) {
if (!lowpan_open_count)
@@ -193,7 +195,8 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head)
static struct rtnl_link_ops lowpan_link_ops __read_mostly = {
.kind = "lowpan",
- .priv_size = sizeof(struct lowpan_dev_info),
+ .priv_size = sizeof(struct lowpan_priv) +
+ sizeof(struct lowpan_dev_info),
.setup = lowpan_setup,
.newlink = lowpan_newlink,
.dellink = lowpan_dellink,
--
2.5.0
The usually way to get the btle lowpan private data is to use the
introduced lowpan_dev inline function. This patch will cleanup by using
lowpan_dev consequently.
Signed-off-by: Alexander Aring <[email protected]>
---
net/bluetooth/6lowpan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 2fb7b30..93c6ba0 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -871,7 +871,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev)
&chan->src, chan->src_type);
set_bit(__LINK_STATE_PRESENT, &netdev->state);
- *dev = netdev_priv(netdev);
+ *dev = lowpan_dev(netdev);
(*dev)->netdev = netdev;
(*dev)->hdev = chan->conn->hcon->hdev;
INIT_LIST_HEAD(&(*dev)->peers);
--
2.5.0