Skip to content
This repository has been archived by the owner on Dec 20, 2023. It is now read-only.

DeviceManager: don't listen on 11095 when ephemeral is enabled #573

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kghost
Copy link
Contributor

@kghost kghost commented Apr 30, 2020

When both device emulator and device manager running on the same
station, both of them will listen on 11095, only one of them choosing
randomly can receive packets from the socket.

Ephemeral port is introduced to solve the problem, let device manager to
choose a random port instead of 11095. But there is a bug that even with
ephemeral enabled, device manager still listening on 11095.

The patch solved the bug, and prevent device manager from listening of
11095 when ephemeral is enabled.

Change-Id: I61e1b92fd329991d5931ce8472fa91580794bbcc

When both device emulator and device manager running on the same
station, both of them will listen on 11095, only one of them choosing
randomly can receive packets from the socket.

Ephemeral port is introduced to solve the problem, let device manager to
choose a random port instead of 11095. But there is a bug that even with
ephemeral enabled, device manager still listening on 11095.

The patch solved the bug, and prevent device manager from listening of
11095 when ephemeral is enabled.

Change-Id: I61e1b92fd329991d5931ce8472fa91580794bbcc
Copy link
Contributor

@jaylogue jaylogue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behavior is by design, and changing it will break various scenarios.

@kghost
Copy link
Contributor Author

kghost commented Apr 30, 2020

So can we add another option to prevent device manager binding on 11095, so we can run device daemon and device manager simultaneously ?

@jaylogue
Copy link
Contributor

This is already possible, by instructing either the device manager or the device to bind to a different IP address.

For the mock device, and other test-app command-line tools, you can pass the --node-addr argument to give a specific IP address to bind to. (You can actually pass two --node-addr arguments, one IPv6, one IPv4, to bind to two addresses).

On the device manager side, you can instruct it to bind to specific IPv6/IPv4 addresses using the environment variables WEAVE_IPV6_LISTEN_ADDR/WEAVE_IPV4_LISTEN_ADDR.

On linux, the easiest way to run both the device manager and a device on the same system is to bind the device manager to an alternate localhost address. For IPv4, this address does not need to be configured in advance:

$ ./output/x86_64-unknown-linux-gnu/bin/mock-device

$ WEAVE_IPV4_LISTEN_ADDR=127.0.0.2 ./output/x86_64-unknown-linux-gnu/bin/weave-device-mgr
WEAVE:ML: WoBLE disabled by application
Weave Device Manager Shell

weave-device-mgr > connect 127.0.0.1
WEAVE:DM: Initiating connection to device
WEAVE:DM: Enabling UDP listen
WEAVE:ML: Listening on Weave IPv4 UDP endpoint ([127.0.0.2]:11095)
WEAVE:ML: Listening on ephemeral IPv4 UDP endpoint ([127.0.0.2]:42746)
WEAVE:ML: Listening on Weave IPv4 UDP broadcast endpoint ([255.255.255.255]:11095)
WEAVE:EM: ec id: 1, AppState: 0x50c24320
WEAVE:DM: Sending IdentifyRequest to locate device (target 1 ([127.0.0.1]:11095))
WEAVE:EM: Msg sent 0000000E:1 16 0000000000000001 0000 9869 0 MsgId:23C64567
WEAVE:EM: Msg rcvd 0000000E:2 96 0000000000000001 0000 9869 0 MsgId:65A3B3E1
WEAVE:DM: Disabling UDP listen
WEAVE:DM: Received identify response from device 1 ([127.0.0.1]:11095%lo)
WEAVE:DM: Initiating weave connection to device 1 (127.0.0.1)
WEAVE:ML: Con start AD90 0000000000000001 0001
WEAVE:ML: TCP con start AD90 127.0.0.1 11095
WEAVE:ML: TCP con complete AD90 0
WEAVE:ML: Con complete AD90
WEAVE:DM: Connected to device
Connected to device 1 at 127.0.0.1
weave-device-mgr (1 @ 127.0.0.1) >

If you want to use IPv6, you can assign temporary ULA addresses to the loopback interface:

sudo ifconfig lo add fd00:0:1:1::1/64
sudo ifconfig lo add fd00:0:1:1::2/64

$ ./output/x86_64-unknown-linux-gnu/bin/mock-device --node-addr fd00:0:1:1::1

$ WEAVE_IPV6_LISTEN_ADDR=fd00:0:1:1::2 ./output/x86_64-unknown-linux-gnu/bin/weave-device-mgr 
WEAVE:ML: WoBLE disabled by application
Weave Device Manager Shell

weave-device-mgr > connect fd00:0:1:1::1
WEAVE:DM: Initiating connection to device
WEAVE:DM: Enabling UDP listen
WEAVE:ML: Listening on Weave IPv6 UDP endpoint ([fd00:0:1:1::2]:11095%lo)
WEAVE:ML: Listening on ephemeral IPv6 UDP endpoint ([fd00:0:1:1::2]:34550%lo)
WEAVE:ML: Listening on Weave IPv6 UDP multicast endpoint ([ff02::1]:11095%lo)
WEAVE:EM: ec id: 1, AppState: 0xfb0ccae0
WEAVE:DM: Sending IdentifyRequest to locate device (target 1 ([fd00:0:1:1::1]:11095))
WEAVE:EM: Msg sent 0000000E:1 16 0000000000000001 0000 9869 0 MsgId:23C64567
WEAVE:EM: Msg rcvd 0000000E:2 96 0000000000000001 0000 9869 0 MsgId:BA2266E9
WEAVE:DM: Disabling UDP listen
WEAVE:DM: Received identify response from device 1 ([fd00:0:1:1::1]:11095%lo)
WEAVE:DM: Initiating weave connection to device 1 (fd00:0:1:1::1)
WEAVE:ML: Con start ED90 0000000000000001 0001
WEAVE:ML: TCP con start ED90 fd00:0:1:1::1 11095
WEAVE:ML: TCP con complete ED90 0
WEAVE:ML: Con complete ED90
WEAVE:DM: Connected to device
Connected to device 1 at fd00:0:1:1::1
weave-device-mgr (1 @ fd00:0:1:1::1) >

@kghost
Copy link
Contributor Author

kghost commented May 12, 2020

This method looks pretty good, I'll update docs corresponding to the setup.

@kghost kghost closed this May 12, 2020
@kghost kghost reopened this May 14, 2020
@kghost
Copy link
Contributor Author

kghost commented May 14, 2020

@jaylogue This solution is not working properly.

Once I specify any IPv4 local address, then Message layer refuse to bind any IPv6 address, so it will not be able to connect to cloud via tunnel. I got the error:

WEAVE:-: PairDeviceToAccount request failed with local error: Weave Error 4070 (0x00000FE6): No endpoint was available to send the message

The logic is here:

inline bool WeaveMessageLayer::IPv6ListenEnabled(void) const
{
// When the targeted listen feature is enabled, enable IPv6 listening when the message layer has
// been bound to a specific IPv6 listening address OR the message
// layer has not been bound to any address (IPv4 or IPv6).
//
// Otherwise, when the targeted listen feature is NOT enabled, always listen on IPv6.
//
return IsBoundToLocalIPv6Address() || !IsBoundToLocalIPv4Address();
}

If we bind to an IPv6 local address, since the bond address is not inside ULA network, so it is also not able to communicate with cloud.

I think we should continue working on solution using the different ports. I'll add an command line option to let device manager do not bind 11095. The option will be off by default to keep it compatible with current behavior.

@jaylogue
Copy link
Contributor

@kghost If you are running a simulated device that creates a tunnel you cannot force bind the device to a particular IPv4/IPv6 address. It will not be able to talk to the service correctly.

Also, if you disable listening on port 11095 in the device manager, some features will not work. If you want to run a device and the device manager on the same node, you really should be using network namespaces.

@kghost
Copy link
Contributor Author

kghost commented May 15, 2020

@jaylogue In my original setup guide, I'm suggesting using namespace or docker, but the setup procedure is a little bit tedious, and the experience is not great. For our 1P developers who have fully aware of technologies like docker or network namespaces, this is totally fine, but for our MFGN partners, it is not a simple task to setup docker or namespaces for an inexperienced developer.

Here I want to improve our user experience targeting all third party developers, and preferably one click fire and go without bunch of environment setups.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants