Ankündigung

Einklappen
Keine Ankündigung bisher.

Multicast und multihome

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Multicast und multihome

    Ich habe auf meinem aktuellen Centos7 versucht, knxd (aktuelles github, commit 848a5cc6cc1f3f79116fbf61c825ca9cd47057cd) mit multicast, sowohl ip als auch server/ets_router zum Laufen zu bringen. Allerdings hat die (virtuelle) Maschine 3 Ethernet-interfaces, weil KNX auf einem sauberen VLAN laufen (eth2) soll, auf dem ansonsten kein Traffic ist.

    Tunnelmode (mit IP-router/interface) kein Problem. Ausgehende multicast-messages ebenfalls kein Problem.

    Hereinkommenden Pakete werden vom knxd nicht bemerkt (maximales logging). Nach Beseitigung der offensichtlichen Probleme (firewall, 2 Stunden, grr), Diagnose: der knxd tritt der multicast-Gruppe bei, allerdings mit dem falschen Interface:

    Code:
    % netstat -ng
    IPv6/IPv4 Group Memberships
    Interface RefCnt Group
    --------------- ------ ---------------------
    lo 1 224.0.0.1
    eth0 1 224.0.23.12
    eth0 1 224.0.0.1
    eth1 1 224.0.0.1
    eth2 1 224.0.0.1
    Hier das config file (keine command line parameter):
    Code:
    [main]
    addr = 0.0.2
    client-addrs = 0.0.5:9
    connections = server,knxd_unix
    # logfile = /var/log/knx/knxd.log
    # background = true
    cache=gc
    
    [server]
    server = ets_router
    discover = true
    debug = debug-server
    router = router
    tunnel = tunnel
    interface = eth2
    
    [debug-server]
    name = mcast:knxd
    error-level = 0x9
    trace-mask = 0xffffff
    
    [knxd_unix]
    path = /usr/local/knxd/run/knxd.socket
    Zur Behandlung des Themas ist schon reichlich code im knxd vorhanden, ich denke aber, das funktioniert (zumindest bei mir) nicht richtig.

    Hier mein vorgeschlagener Patch, mit dem das Problem beseitigt wird. Ich denke, nicht, dass das der optimale Weg ist, aber es ist recht minimalistisch. Da ja das Versenden der Pakete über multicast funktioniert, geht setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,...) offensichtlich gut. Was nicht funktioniert ist setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, ...), dabei insbesondere die Festlegung des verwendeten physischen Interfaces. Dazu gibt es zwei Möglichkeiten: Angabe der Adresse des Interfaces oder des Index (>0). Nur gibt es leider ip_mreq (alt) und ip_mreqn (neu), die dafür verwendet werden können. ip_mreqn ist bereits bei IP_MULTICAST_IF im Einsatz. Wünschenswert wäre eine Vereinheitlichung von EIBNetIPSocket::SetMulticast() und EIBNetIPSocket::SetInterface() in dieser Beziehung, aber das war mir jetzt etwas kritisch. Also merke ich mir den Interface-Index bei SetInterface() und nutze ihn im Erfolgsfall bei SetMulticast().

    Code:
    diff --git a/src/libserver/eibnetip.cpp b/src/libserver/eibnetip.cpp
    index 7139d44..480faf2 100644
    --- a/src/libserver/eibnetip.cpp
    +++ b/src/libserver/eibnetip.cpp
    @@ -74,6 +74,7 @@ EIBNetIPSocket::EIBNetIPSocket (struct sockaddr_in bindaddr, bool reuseaddr,
    t = tr;
    TRACEPRINTF (t, 0, "Open");
    multicast = false;
    + mc_ifindex = 0;
    memset (&maddr, 0, sizeof (maddr));
    memset (&sendaddr, 0, sizeof (sendaddr));
    memset (&recvaddr, 0, sizeof (recvaddr));
    @@ -201,10 +202,17 @@ EIBNetIPSocket::port ()
    bool
    EIBNetIPSocket::SetMulticast (struct ip_mreq multicastaddr)
    {
    +
    + ip_mreqn mreqn;
    +
    + mreqn.imr_multiaddr = multicastaddr.imr_multiaddr;
    + mreqn.imr_address = multicastaddr.imr_interface;
    + mreqn.imr_ifindex = mc_ifindex;
    +
    if (multicast)
    return false;
    maddr = multicastaddr;
    - if (setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &maddr, sizeof (maddr))
    + if (setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn, sizeof (mreqn))
    == -1)
    return false;
    multicast = true;
    @@ -302,8 +310,12 @@ EIBNetIPSocket::SetInterface(std::string& iface)
    if (iface.size() == 0)
    return true;
    addr.imr_ifindex = if_nametoindex(iface.c_str());
    - return
    - setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)) >= 0;
    + if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)) >= 0)
    + {
    + mc_ifindex = addr.imr_ifindex; // save for SetMulticast
    + return true;
    + }
    + return false;
    }
    
    EIBnet_SearchRequest::EIBnet_SearchRequest ()
    diff --git a/src/libserver/eibnetip.h b/src/libserver/eibnetip.h
    index b6fb92e..9bca6e5 100644
    --- a/src/libserver/eibnetip.h
    +++ b/src/libserver/eibnetip.h
    @@ -512,6 +512,8 @@ private:
    int fd;
    /** multicast in use? */
    bool multicast;
    + /** saved interface index **/
    + int mc_ifindex;
    };
    
    #endif
Lädt...
X