calimero-project / calimero-core

Core library for KNX network access and management
Other
128 stars 65 forks source link

Multiple networkinterfaces on windows #35

Closed tuxedo0801 closed 8 years ago

tuxedo0801 commented 8 years ago

I have a nasty problem with one of my customer's installations. The symptoms:

I think I found the root-cause: The customer is having multiple network interfaces:

from "ipconfig /all":

Ethernet-Adapter LAN-Verbindung:

   Verbindungsspezifisches DNS-Suffix: fritz.box
   Beschreibung. . . . . . . . . . . : NVIDIA nForce-Netzwerkcontroller
   Physische Adresse . . . . . . . . : 00-xx-xx-xx-xx-xx
   DHCP aktiviert. . . . . . . . . . : Ja
   Autokonfiguration aktiviert . . . : Ja
   Verbindungslokale IPv6-Adresse  . : fe80::190f:efaa:1122:19ea%3(Bevorzugt)
   IPv4-Adresse  . . . . . . . . . . : 192.168.0.21(Bevorzugt)
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Lease erhalten. . . . . . . . . . : Sonntag, 15. Mai 2016 15:08:56
   Lease läuft ab. . . . . . . . . . : Freitag, 27. Mai 2016 20:39:38
   Standardgateway . . . . . . . . . : 192.168.0.1
   DHCP-Server . . . . . . . . . . . : 192.168.0.1
   DHCPv6-IAID . . . . . . . . . . . : 123456789
   DHCPv6-Client-DUID. . . . . . . . : 00-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx

   DNS-Server  . . . . . . . . . . . : 192.168.0.1
   NetBIOS über TCP/IP . . . . . . . : Aktiviert

Ethernet-Adapter VirtualBox Host-Only Network:

   Verbindungsspezifisches DNS-Suffix:
   Beschreibung. . . . . . . . . . . : VirtualBox Host-Only Ethernet Adapter
   Physische Adresse . . . . . . . . : 0a-00-27-00-00-00
   DHCP aktiviert. . . . . . . . . . : Nein
   Autokonfiguration aktiviert . . . : Ja
   Verbindungslokale IPv6-Adresse  . : fe80::3883:d613:4325:7239%23(Bevorzugt)
   IPv4-Adresse  . . . . . . . . . . : 192.168.56.1(Bevorzugt)
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Standardgateway . . . . . . . . . :
   DHCPv6-IAID . . . . . . . . . . . : 123456789
   DHCPv6-Client-DUID. . . . . . . . : 00-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx

   DNS-Server  . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   NetBIOS über TCP/IP . . . . . . . : Aktiviert

Ethernet-Adapter VMware Network Adapter VMnet1:

   Verbindungsspezifisches DNS-Suffix:
   Beschreibung. . . . . . . . . . . : VMware Virtual Ethernet Adapter for VMnet
1
   Physische Adresse . . . . . . . . : 00-xx-xx-xx-xx-xx
   DHCP aktiviert. . . . . . . . . . : Nein
   Autokonfiguration aktiviert . . . : Ja
   Verbindungslokale IPv6-Adresse  . : fe80::11bf:1254:55fc:b215%34(Bevorzugt)
   IPv4-Adresse  . . . . . . . . . . : 192.168.146.1(Bevorzugt)
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Standardgateway . . . . . . . . . :
   DHCPv6-IAID . . . . . . . . . . . : 123456789
   DHCPv6-Client-DUID. . . . . . . . : 00-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx

   DNS-Server  . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   NetBIOS über TCP/IP . . . . . . . : Aktiviert

Ethernet-Adapter VMware Network Adapter VMnet8:

   Verbindungsspezifisches DNS-Suffix:
   Beschreibung. . . . . . . . . . . : VMware Virtual Ethernet Adapter for VMnet
8
   Physische Adresse . . . . . . . . : 00-50-56-C0-00-08
   DHCP aktiviert. . . . . . . . . . : Nein
   Autokonfiguration aktiviert . . . : Ja
   Verbindungslokale IPv6-Adresse  . : fe80::7d3b:45c1:5ae7:c409%36(Bevorzugt)
   IPv4-Adresse  . . . . . . . . . . : 192.168.147.1(Bevorzugt)
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Standardgateway . . . . . . . . . :
   DHCPv6-IAID . . . . . . . . . . . : 123456789
   DHCPv6-Client-DUID. . . . . . . . : 00-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx

   DNS-Server  . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   NetBIOS über TCP/IP . . . . . . . : Aktiviert

Tunneladapter isatap.{3E9932FB-2FC6-433F-B439-EC4FE3CB33F1}:

   Medienstatus. . . . . . . . . . . : Medium getrennt
   Verbindungsspezifisches DNS-Suffix:
   Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter
   Physische Adresse . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP aktiviert. . . . . . . . . . : Nein
   Autokonfiguration aktiviert . . . : Ja

Tunneladapter isatap.{7A34D7A2-017E-462E-9968-062C9115542B}:

   Medienstatus. . . . . . . . . . . : Medium getrennt
   Verbindungsspezifisches DNS-Suffix:
   Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #2
   Physische Adresse . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP aktiviert. . . . . . . . . . : Nein
   Autokonfiguration aktiviert . . . : Ja

Tunneladapter isatap.{976BC5B1-6D33-451F-863B-C0F145636BDC}:

   Medienstatus. . . . . . . . . . . : Medium getrennt
   Verbindungsspezifisches DNS-Suffix:
   Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #3
   Physische Adresse . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP aktiviert. . . . . . . . . . : Nein
   Autokonfiguration aktiviert . . . : Ja

Tunneladapter isatap.fritz.box:

   Medienstatus. . . . . . . . . . . : Medium getrennt
   Verbindungsspezifisches DNS-Suffix: fritz.box
   Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #4
   Physische Adresse . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP aktiviert. . . . . . . . . . : Nein
   Autokonfiguration aktiviert . . . : Ja

from "route print":

===========================================================================
Schnittstellenliste
  3...00 xx xx xx xx xx ......NVIDIA nForce-Netzwerkcontroller
 23...0a 00 27 00 00 00 ......VirtualBox Host-Only Ethernet Adapter
 34...00 50 56 c0 00 01 ......VMware Virtual Ethernet Adapter for VMnet1
 36...00 50 56 c0 00 08 ......VMware Virtual Ethernet Adapter for VMnet8
  1...........................Software Loopback Interface 1
  4...00 00 00 00 00 00 00 e0 Microsoft-ISATAP-Adapter
 24...00 00 00 00 00 00 00 e0 Microsoft-ISATAP-Adapter #2
 35...00 00 00 00 00 00 00 e0 Microsoft-ISATAP-Adapter #3
 37...00 00 00 00 00 00 00 e0 Microsoft-ISATAP-Adapter #4
===========================================================================

IPv4-Routentabelle
===========================================================================
Aktive Routen:
     Netzwerkziel    Netzwerkmaske          Gateway    Schnittstelle Metrik
          0.0.0.0          0.0.0.0      192.168.0.1     192.168.0.21     10
        127.0.0.0        255.0.0.0   Auf Verbindung         127.0.0.1    306
        127.0.0.1  255.255.255.255   Auf Verbindung         127.0.0.1    306
  127.255.255.255  255.255.255.255   Auf Verbindung         127.0.0.1    306
      192.168.0.0    255.255.255.0   Auf Verbindung      192.168.0.21    266
     192.168.0.21  255.255.255.255   Auf Verbindung      192.168.0.21    266
    192.168.0.255  255.255.255.255   Auf Verbindung      192.168.0.21    266
     192.168.56.0    255.255.255.0   Auf Verbindung      192.168.56.1    266
     192.168.56.1  255.255.255.255   Auf Verbindung      192.168.56.1    266
   192.168.56.255  255.255.255.255   Auf Verbindung      192.168.56.1    266
    192.168.146.0    255.255.255.0   Auf Verbindung     192.168.146.1    276
    192.168.146.1  255.255.255.255   Auf Verbindung     192.168.146.1    276
  192.168.146.255  255.255.255.255   Auf Verbindung     192.168.146.1    276
    192.168.147.0    255.255.255.0   Auf Verbindung     192.168.147.1    276
    192.168.147.1  255.255.255.255   Auf Verbindung     192.168.147.1    276
  192.168.147.255  255.255.255.255   Auf Verbindung     192.168.147.1    276
        224.0.0.0        240.0.0.0   Auf Verbindung         127.0.0.1    306
        224.0.0.0        240.0.0.0   Auf Verbindung      192.168.56.1    266
        224.0.0.0        240.0.0.0   Auf Verbindung      192.168.0.21    266
        224.0.0.0        240.0.0.0   Auf Verbindung     192.168.146.1    276
        224.0.0.0        240.0.0.0   Auf Verbindung     192.168.147.1    276
  255.255.255.255  255.255.255.255   Auf Verbindung         127.0.0.1    306
  255.255.255.255  255.255.255.255   Auf Verbindung      192.168.56.1    266
  255.255.255.255  255.255.255.255   Auf Verbindung      192.168.0.21    266
  255.255.255.255  255.255.255.255   Auf Verbindung     192.168.146.1    276
  255.255.255.255  255.255.255.255   Auf Verbindung     192.168.147.1    276
===========================================================================
Ständige Routen:
  Keine

The network he is using (=has access to the KNX routing/tunneling interface) is the "NVIDIA nForce-Netzwerkcontroller" with 192.168.0.x IP address range.

If I check the routing table for 224-Multicast addresses, I see that

a) 192.168.56.1 and 192.168.0.21 have the same metric: 266 b) 192.168.56.1 is listed BEFORE the correct network 192.168.0.21

Investigation is still in progress, but my current guess is: calimero is using - due to the same metrik - the 192.168.56.1 network interface instead of 192.168.0.21.

Question is:

bmalinowsky commented 8 years ago

Investigation is still in progress, but my current guess is: calimero is using - due to the same metrik - the 192.168.56.1 network interface instead of 192.168.0.21.

By default, the default network interface is used (not the route metric for mcasts)

Is there a way to tell calimero which networkinterface is the rigth one?

If you create a network link, you can specify the local socket (tunneling) or the network interface (routing) you want to use. This does not work? From what I see it would surprise me if, e.g., tunneling datagrams sent from local socket 192.168.0.21 don't use the nforce interface.

Is calimero able to detect the right networkinterface automatically?

In theory yes, but since that would stop to work reliably if you have several devices or some "interesting" network setup, it doesn't do that.

Or is this in any case a weird setup and user has to fix the metric by himself?!

I would only change the system route metrics if there is a general problem with multicasts, as it affects every program. Or, e.g., if he specifically wants to always route any 224.x.x.x over a single interface only.

tuxedo0801 commented 8 years ago

By default, the default network interface is used (not the route metric for mcasts)

The question is: Which one is the default network interface? If I do not specify a network interface explicitly, I guess it depends on the routing table. That's what my experience + google tells me. Please correct me (with details) if I'm wrong.

If you create a network link, you can specify the local socket (tunneling) or the network interface (routing) you want to use.

I just use routing... And there I didn't specify any networkinterface yet. On systems with less network-interfaces and with systems with optimal metric, this works.

Have to test what happens if I specify the right interface. Should work, I guess.

In theory yes, but since that would stop to work reliably if you have several devices or some "interesting" network setup, it doesn't do that.

How about the discovery? If I enumerate over all network interfaces and do an discovery on each, this might bring up the correct knx routing/tunneling device + network interface. --> have to test this.

bmalinowsky commented 8 years ago

That's what my experience + google tells me. Please correct me (with details) if I'm wrong.

It's been years since i did kernel/nw stuff on windows, so my guess is as good as yours. It might as well be that on windows -- as you pointed out -- the top-most entry is used in case of ambiguity. Easy to verify, switch the entries. It's just something i would not rely on, or wonder if that stops working.

I just use routing... And there I didn't specify any networkinterface yet

the local socket/netif parameters are exactly for multi-host systems.

How about the discovery? If I enumerate over all network interfaces and do an discovery on each, this might bring up the correct knx routing/tunneling device + network interface. --> have to test this.

I thought you used that anyway, it's the standard way to discover devices ... discovery checks all active network interfaces by default, you don't need to enumerate.

tuxedo0801 commented 8 years ago

So, finally to come to an conclusion:

There are two options:

1) let the user of the application select the network interface 2) use discovery to configure/set the knx interface

Right now, my application lets the user just choose between routing (with no nw-if and hardcoded mc-adr), tunneling (with input field for knx interface's IP) and TPUART.

So I will add the auto-discovery ...

tuxedo0801 commented 8 years ago

I tried to use the Discoverer-class. Works great. My IP Router is discovered without any issues.

BUT... What do I do with these informations?! How can I use on of the SearchResponses to establish a working KNX connection?! I get the type of the device, as well as t it's IP and what not, but I don't get any hint on which network interface the device was found. So even if I parse the search response for the type to know which kind of connection I could open, I have no clue on which network interface this has to be done.

Is there some code that you can point me on that shows something in this direction?!

tuxedo0801 commented 8 years ago

Tried the following workaround:

iterate myself over the network interfaces (to know on which interfaces a device has been discovered, so that I can open a connection on the proper interface) and called discoverer.startSearch(myNetworkInterface, 20, true) ... Result:

Discoverer.java line 570 throws an KNXException, telling me:

failed to create socket in myhost/127.0.1.1:0, Die angeforderte Adresse kann nicht zugewiesen werden

If I have a look at the startSearch() implementation which iterates internally over the network interfaces, interface-adresses like localhost are skipped.

So,

  1. letting the Discoverer iterate over the interfaces does not give me any hint on which interfaces the device has been discovered and I haven't found a way to use the SearchResponse to establish a KNX connection via the corresponding network interface
  2. iterating myself over the network interfaces does also not work, because localhost addresses are not excluded by discoverer in this case. So search does simply not work for all interfaces.

:-(

bmalinowsky commented 8 years ago

You can try if the vm argument java.net.preferIPv4Stack=true makes a difference

failed to create socket in myhost/127.0.1.1:0

from your setup i don't see a reason why you would want to use a loopback address

interface-adresses like localhost are skipped

and where exactly do you see that? discoverer does the opposite

  1. [...]

?

[edit: spaces]

tuxedo0801 commented 8 years ago

Could you please give an answer/recommendation to this:

I tried to use the Discoverer-class. Works great. My IP Router is discovered without any issues.

BUT... What do I do with these informations?! How can I use on of the SearchResponses to establish a working KNX connection?! I get the type of the device, as well as t it's IP and what not, but I don't get any hint on which network interface the device was found. So even if I parse the search response for the type to know which kind of connection I could open, I have no clue on which network interface this has to be done.

Is there some code that you can point me on that shows something in this direction?!

??

Regarding my experiments with the mentioned workaround (due to the problem that I do not get any networkinterface information from the SearchResponse) :

I will try preferIPv4Stack, but I fear that this does not solve the issue, as the error is about ipv4 and not ipv6.

from your setup i don't see a reason why you would want to use a loopback address

If I create the discoverer like this

Discoverer discoverer = new Discoverer(0, false);
discoverer.startSearch(myNetworkInterface, 20, true)

my host name (not "localhost", but "myhost") is choosen automatically. And this resolves (on my linux developer system, which also has multiple network interfaces) to 127.0.1.1 ...

If course I can use another constructor and give a valid IP address for each discovery on each network interface. But that makes things more complicated.

So final question is:

How to use the Discoverer to find out

and where exactly do you see that?

Sorry, misinterpretation from my side. Just ignore it.

bmalinowsky commented 8 years ago

Do subnet matching (using netmask / cidr notation) for the relevant interfaces. Or, in j8, calimero uses a slightly different api which actually returns the outgoing ip/netif (note that there could be more than one result). Just patch your lib ...

I do not get any networkinterface information from the SearchResponse

A search response contains the information as listed in the knx spec, that's why.

I will try preferIPv4Stack, but I fear that this does not solve the issue, as the error is about ipv4 and not ipv6.

There are certain problems in java on windows platforms, if interfaces use ip4v but also have ipv6 addresses. One is that setting the network interface might fail ...

(I tested on a win7 host, and included win7 in a workaround ... maybe that exact problem hit you, 946a40cdeb)

How to use the Discoverer to find out

  • any knx interface/router/...

run default search, which will use all interfaces applicable at the start time of the discovery

  • and on which network interface it is reachable...

See first part; as there could be more than one netif, the decision is up to you which one you want to select.

tuxedo0801 commented 8 years ago

Final answer/solution (at least for me):

My code iterates over all network interfaces. if iface is down or loopback, it's skipped. It then iterates over all ipv4 adresses (ipv6 is skipped) of each interface and creates a Discoverer object:

Discoverer d = new Discoverer(interfaceAddr.getAddress(), 0, 0, false, false);

and starts discovery

d.startSearch(ni, 5, true);

If a result is found that indicates an IP router, the current networkinterfaces and the device's multicastaddress is used to create the matching KNXNetworkLinkIP instance.

Works for me ...