2016-08-04 13:09:29

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv2 linux-wpan/radvd for-upstream 0/2] radvd: upstream patches

Hi,

this patch series has some overdue updates for radvd upstream version.
It doesn't contain rework of 6CO handling, since we don't have a stable
UAPI to provide stateful compression to userspace.

Anyway radvd has actually 6CO handling which is ?broken? don't know what
it should do at the moment. 6CO without stateful compression setting
makes no sense for me. If you like to use 6CO over debugfs use
linux-wpan/radvd "6lowpan" branch.

---

I will update the "6lowpan" branch also with Patch 2/2 which adds support
to get address length via sysfs. This patch will prepare correct handling
for the new BTLE 6LoWPAN handling to use the correct address and
address length (not 8 bytes, with U/L bit).

If everything seems fine I will send a pull-request for radvd github
repository. Please reply if this "hopefully final version" is okay for
all 6LoWPAN people. Then I will try to get this upstream, at last the
radvd maintainer need to apply this patch series if this looks okay
for him.

- Alex

changes since v2:

I need to correct me here, I think the buggy btle 6lowpan implementation
addr_len == 8 and U/L will work. This is because the U/L bit is part of
interface device address and radvd will use them. But anyway it's wrong
and the next step will be to fix BTLE 6LoWPAN mainline.

- change device address length UAPI to netlink
- correct commit message in PATCH 1/2 - remove the part that all 6LoWPAN
types has the same device address length.

Alexander Aring (2):
device-linux: replace ARPHRD_IEEE802154 to ARPHRD_6LOWPAN
device-linux: get address length via netlink

device-linux.c | 27 ++++++++++++++++++++-----
netlink.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
netlink.h | 1 +
3 files changed, 87 insertions(+), 5 deletions(-)

--
2.9.2



2016-08-04 13:16:38

by Alexander Aring

[permalink] [raw]
Subject: Re: [PATCHv2 linux-wpan/radvd for-upstream 2/2] device-linux: get address length via netlink


Hi,

On 08/04/2016 03:09 PM, Alexander Aring wrote:
> This patch adds a mechanism to get the device address length via
> netlink. This is necessary for device type 6LoWPAN which can have
> different device address lengths.
> ---
> device-linux.c | 16 +++++++++++++--
> netlink.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> netlink.h | 1 +
> 3 files changed, 79 insertions(+), 2 deletions(-)
>
> diff --git a/device-linux.c b/device-linux.c
> index 7301927..1ccb207 100644
> --- a/device-linux.c
> +++ b/device-linux.c
> @@ -17,6 +17,7 @@
> #include "radvd.h"
> #include "defaults.h"
> #include "pathnames.h"
> +#include "netlink.h"
>
> #ifndef IPV6_ADDR_LINKLOCAL
> #define IPV6_ADDR_LINKLOCAL 0x0020U
> @@ -84,8 +85,19 @@ int update_device_info(int sock, struct Interface *iface)
> break;
> #endif /* ARPHDR_ARCNET */
> case ARPHRD_6LOWPAN:
> - iface->sllao.if_hwaddr_len = 64;
> - iface->sllao.if_prefix_len = 64;
> +#ifdef HAVE_NETLINK
> + /* hwaddr length differs on some L2 type lets detect them */
> + iface->sllao.if_hwaddr_len = netlink_get_device_addr_len(iface);
> + if (iface->sllao.if_hwaddr_len != -1) {
> + iface->sllao.if_hwaddr_len *= 8;
> + iface->sllao.if_prefix_len = 64;
> + } else {
> + iface->sllao.if_prefix_len = -1;
> + }
> +#else
> + iface->sllao.if_hwaddr_len = -1;
> + iface->sllao.if_prefix_len = -1;
> +#endif
> break;
> default:
> iface->sllao.if_hwaddr_len = -1;
> diff --git a/netlink.c b/netlink.c
> index 80d2254..d07a0b8 100644
> --- a/netlink.c
> +++ b/netlink.c
> @@ -32,6 +32,70 @@
> #define SOL_NETLINK 270
> #endif
>
> +struct iplink_req {
> + struct nlmsghdr n;
> + struct ifinfomsg i;
> + char buf[1024];
> +};
> +
> +int netlink_get_device_addr_len(struct Interface *iface)
> +{
> + struct iplink_req req = {};
> + struct iovec iov = { &req, sizeof(req) };
> + struct sockaddr_nl sa = {};
> + struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
> + int sock, len, addr_len = -1;
> + unsigned short type;
> + char answer[32768];
> + struct rtattr *tb;
> +
> + /* nl_pid (for linux kernel) and nl_groups (unicast) should be zero */
> + sa.nl_family = AF_NETLINK;
> + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
> + req.n.nlmsg_flags = NLM_F_REQUEST;
> + req.n.nlmsg_type = RTM_GETLINK;
> + req.i.ifi_index = iface->props.if_index;
> +
> + sock = netlink_socket();
> + if (sock == -1)
> + return -1;
> +
> + len = sendmsg(sock, &msg, 0);
> + if (len == -1) {
> + flog(LOG_ERR, "netlink: sendmsg for addr_len failed: %s", strerror(errno));
> + close(sock);

need to be removed.

> + goto out;
> + }
> +
> + iov.iov_base = answer;
> + iov.iov_len = sizeof(answer);
> + len = recvmsg(sock, &msg, 0);
> + if (len == -1) {
> + flog(LOG_ERR, "netlink: recvmsg for addr_len failed: %s", strerror(errno));
> + close(sock);

same here.

> + goto out;
> + }
> +
> + if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
> + goto out;
> + len -= NLMSG_LENGTH(sizeof(struct ifinfomsg));
> +
> + tb = (struct rtattr *)(answer + NLMSG_LENGTH(sizeof(struct ifinfomsg)));
> + while (RTA_OK(tb, len)) {
> + type = tb->rta_type & ~NLA_F_NESTED;
> + if (type == IFLA_ADDRESS) {
> + addr_len = RTA_PAYLOAD(tb);
> + break;
> + }
> + tb = RTA_NEXT(tb, len);
> + }
> +
> +out:
> + close(sock);

will be done here.

I will fix that before sending the pull-request if everything else is
fine enough. :-)

- Alex


2016-08-04 13:09:30

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv2 linux-wpan/radvd for-upstream 0/2] radvd: upstream patches

Hi,

this patch series has some overdue updates for radvd upstream version.
It doesn't contain rework of 6CO handling, since we don't have a stable
UAPI to provide stateful compression to userspace.

Anyway radvd has actually 6CO handling which is ?broken? don't know what
it should do at the moment. 6CO without stateful compression setting
makes no sense for me. If you like to use 6CO over debugfs use
linux-wpan/radvd "6lowpan" branch.

---

I will update the "6lowpan" branch also with Patch 2/2 which adds support
to get address length via sysfs. This patch will prepare correct handling
for the new BTLE 6LoWPAN handling to use the correct address and
address length (not 8 bytes, with U/L bit).

If everything seems fine I will send a pull-request for radvd github
repository. Please reply if this "hopefully final version" is okay for
all 6LoWPAN people. Then I will try to get this upstream, at last the
radvd maintainer need to apply this patch series if this looks okay
for him.

- Alex

changes since v2:

I need to correct me here, I think the buggy btle 6lowpan implementation
addr_len == 8 and U/L will work. This is because the U/L bit is part of
interface device address and radvd will use them. But anyway it's wrong
and the next step will be to fix BTLE 6LoWPAN mainline.

- change device address length UAPI to netlink
- correct commit message in PATCH 1/2 - remove the part that all 6LoWPAN
types has the same device address length.

Alexander Aring (2):
device-linux: replace ARPHRD_IEEE802154 to ARPHRD_6LOWPAN
device-linux: get address length via netlink

device-linux.c | 27 ++++++++++++++++++++-----
netlink.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
netlink.h | 1 +
3 files changed, 87 insertions(+), 5 deletions(-)

--
2.9.2


2016-08-04 13:09:32

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv2 linux-wpan/radvd for-upstream 2/2] device-linux: get address length via netlink

This patch adds a mechanism to get the device address length via
netlink. This is necessary for device type 6LoWPAN which can have
different device address lengths.
---
device-linux.c | 16 +++++++++++++--
netlink.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
netlink.h | 1 +
3 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/device-linux.c b/device-linux.c
index 7301927..1ccb207 100644
--- a/device-linux.c
+++ b/device-linux.c
@@ -17,6 +17,7 @@
#include "radvd.h"
#include "defaults.h"
#include "pathnames.h"
+#include "netlink.h"

#ifndef IPV6_ADDR_LINKLOCAL
#define IPV6_ADDR_LINKLOCAL 0x0020U
@@ -84,8 +85,19 @@ int update_device_info(int sock, struct Interface *iface)
break;
#endif /* ARPHDR_ARCNET */
case ARPHRD_6LOWPAN:
- iface->sllao.if_hwaddr_len = 64;
- iface->sllao.if_prefix_len = 64;
+#ifdef HAVE_NETLINK
+ /* hwaddr length differs on some L2 type lets detect them */
+ iface->sllao.if_hwaddr_len = netlink_get_device_addr_len(iface);
+ if (iface->sllao.if_hwaddr_len != -1) {
+ iface->sllao.if_hwaddr_len *= 8;
+ iface->sllao.if_prefix_len = 64;
+ } else {
+ iface->sllao.if_prefix_len = -1;
+ }
+#else
+ iface->sllao.if_hwaddr_len = -1;
+ iface->sllao.if_prefix_len = -1;
+#endif
break;
default:
iface->sllao.if_hwaddr_len = -1;
diff --git a/netlink.c b/netlink.c
index 80d2254..d07a0b8 100644
--- a/netlink.c
+++ b/netlink.c
@@ -32,6 +32,70 @@
#define SOL_NETLINK 270
#endif

+struct iplink_req {
+ struct nlmsghdr n;
+ struct ifinfomsg i;
+ char buf[1024];
+};
+
+int netlink_get_device_addr_len(struct Interface *iface)
+{
+ struct iplink_req req = {};
+ struct iovec iov = { &req, sizeof(req) };
+ struct sockaddr_nl sa = {};
+ struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
+ int sock, len, addr_len = -1;
+ unsigned short type;
+ char answer[32768];
+ struct rtattr *tb;
+
+ /* nl_pid (for linux kernel) and nl_groups (unicast) should be zero */
+ sa.nl_family = AF_NETLINK;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_GETLINK;
+ req.i.ifi_index = iface->props.if_index;
+
+ sock = netlink_socket();
+ if (sock == -1)
+ return -1;
+
+ len = sendmsg(sock, &msg, 0);
+ if (len == -1) {
+ flog(LOG_ERR, "netlink: sendmsg for addr_len failed: %s", strerror(errno));
+ close(sock);
+ goto out;
+ }
+
+ iov.iov_base = answer;
+ iov.iov_len = sizeof(answer);
+ len = recvmsg(sock, &msg, 0);
+ if (len == -1) {
+ flog(LOG_ERR, "netlink: recvmsg for addr_len failed: %s", strerror(errno));
+ close(sock);
+ goto out;
+ }
+
+ if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
+ goto out;
+ len -= NLMSG_LENGTH(sizeof(struct ifinfomsg));
+
+ tb = (struct rtattr *)(answer + NLMSG_LENGTH(sizeof(struct ifinfomsg)));
+ while (RTA_OK(tb, len)) {
+ type = tb->rta_type & ~NLA_F_NESTED;
+ if (type == IFLA_ADDRESS) {
+ addr_len = RTA_PAYLOAD(tb);
+ break;
+ }
+ tb = RTA_NEXT(tb, len);
+ }
+
+out:
+ close(sock);
+
+ return addr_len;
+}
+
void process_netlink_msg(int sock, struct Interface * ifaces)
{
char buf[4096];
diff --git a/netlink.h b/netlink.h
index e2b706e..c693a10 100644
--- a/netlink.h
+++ b/netlink.h
@@ -17,5 +17,6 @@

#include "radvd.h"

+int netlink_get_device_addr_len(struct Interface *iface);
void process_netlink_msg(int sock, struct Interface * ifaces);
int netlink_socket(void);
--
2.9.2


2016-08-04 13:09:31

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv2 linux-wpan/radvd for-upstream 1/2] device-linux: replace ARPHRD_IEEE802154 to ARPHRD_6LOWPAN

This patch changes the ARPHRD_IEEE802154 to ARPHRD_6LOWPAN. The IEEE
802.15.4 6lowpan module changed the ARPHRD_IEEE802154 type to
ARPHRD_6LOWPAN which is the device type for all 6LoWPAN interface
adaptations.

There is no backward compatibility for 802.15.4 6LoWPAN before we
changed the ARPHRD. Anyway if somebody wants that it should be patched
manually. When the ARPHRD was ARPHRD_IEEE802154 the 802.15.4 6lowpan was
anyway in a somehow unusable state.
---
device-linux.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/device-linux.c b/device-linux.c
index de83f2e..7301927 100644
--- a/device-linux.c
+++ b/device-linux.c
@@ -22,6 +22,10 @@
#define IPV6_ADDR_LINKLOCAL 0x0020U
#endif

+#ifndef ARPHRD_6LOWPAN
+#define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */
+#endif
+
static char const *hwstr(unsigned short sa_family);

/*
@@ -79,12 +83,10 @@ int update_device_info(int sock, struct Interface *iface)
iface->sllao.if_maxmtu = -1;
break;
#endif /* ARPHDR_ARCNET */
-#ifdef ARPHRD_IEEE802154
- case ARPHRD_IEEE802154:
+ case ARPHRD_6LOWPAN:
iface->sllao.if_hwaddr_len = 64;
iface->sllao.if_prefix_len = 64;
break;
-#endif
default:
iface->sllao.if_hwaddr_len = -1;
iface->sllao.if_prefix_len = -1;
@@ -382,6 +384,9 @@ static char const *hwstr(unsigned short sa_family)
rc = "ARPHRD_IEEE802154_PHY";
break;
#endif
+ case ARPHRD_6LOWPAN:
+ rc = "ARPHRD_6LOWPAN";
+ break;
case ARPHRD_VOID:
rc = "ARPHRD_VOID";
break;
--
2.9.2