8000 Iperf3 not working: unable to send cookie · Issue #22163 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Iperf3 not working: unable to send cookie #22163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
allserv opened this issue Mar 18, 2019 · 20 comments · Fixed by #29495
Closed

Iperf3 not working: unable to send cookie #22163

allserv opened this issue Mar 18, 2019 · 20 comments · Fixed by #29495
Assignees

Comments

@allserv
Copy link
allserv commented Mar 18, 2019

Home Assistant release with the issue:
hass --version
0.89.2

python3.5 --version
python 3.5.3

Last working Home Assistant release (if known):

Operating environment (Hass.io/Docker/Windows/etc.):
hassbian installation on a Raspberry Pi 2B

Component/platform:
iperf3 => https://www.home-assistant.io/components/iperf3/

Description of problem:
Unable to use iperf3 in home assistant, not data retrieved from the server.

Problem-relevant configuration.yaml entries and (fill out even if it seems unimportant):

iperf3:
  hosts:
    - host: bouygues.iperf.fr
  monitored_conditions:
    - download
    - upload

Traceback (if applicable):
== log file from /home/homeassistant/.homeassistant/home-assistant.log

2019-03-18 20:39:10 ERROR (Thread-5) [homeassistant.components.iperf3] Iperf3 error: unable to receive control message: Connection reset by peer
2019-03-18 20:39:10 ERROR (Thread-5) [homeassistant.components.iperf3] Iperf3 error: unable to send cookie to server: Broken pipe
2019-03-18 20:39:15 ERROR (Thread-2) [homeassistant.components.iperf3] Iperf3 error: unable to send control message: Broken pipe
2019-03-18 20:39:15 ERROR (Thread-2) [homeassistant.components.iperf3] Iperf3 error: unable to send cookie to server: Broken pipe
2019-03-18 20:39:25 ERROR (Thread-9) [homeassistant.components.iperf3] Iperf3 error: unable to send cookie to server: Broken pipe
2019-03-18 20:39:25 ERROR (Thread-9) [homeassistant.components.iperf3] Iperf3 error: unable to send cookie to server: Broken pipe

Additional information:

I configure logger to have more information on iperf3 components but no more details

@dooz127
Copy link
dooz127 commented Mar 22, 2019

Seeing the same issue.

Home Assistant release with the issue:
hass --version
0.90.1

python3.5 --version
python 3.7.2

Last working Home Assistant release (if known):

Operating environment (Hass.io/Docker/Windows/etc.):
homeassistant/home-assistant Docker image on a NUC

Problem-relevant configuration.yaml entries and (fill out even if it seems unimportant):
iperf3: hosts: - IPERF3_SERVER_LOCAL_IP_ADDRESS

Looks like my local iPerf server (networkstatic/iperf3 latest docker image) is receiving the request from Home Assistant's iPerf client but iperf3 entity states remain unknown and running the service throws the "unable to send cookie" error.

2019-03-22 18:33:41 stdout Server listening on 5201 2019-03-22 18:33:41 stdout ----------------------------------------------------------- 2019-03-22 18:33:41 stdout [ 5] 0.00-10.03 sec 144 MBytes 121 Mbits/sec receiver 2019-03-22 18:33:41 stdout [ 5] 0.00-10.03 sec 146 MBytes 122 Mbits/sec 0 sender 2019-03-22 18:33:41 stdout [ ID] Interval Transfer Bandwidth Retr 2019-03-22 18:33:41 stdout - - - - - - - - - - - - - - - - - - - - - - - - - 2019-03-22 18:33:41 stdout [ 5] 10.00-10.03 sec 0.00 Bytes 0.00 bits/sec 0 938 KBytes 2019-03-22 18:33:41 stdout [ 5] 9.00-10.00 sec 14.1 MBytes 118 Mbits/sec 0 938 KBytes 2019-03-22 18:33:40 stdout [ 5] 8.00-9.00 sec 15.4 MBytes 129 Mbits/sec 0 933 KBytes 2019-03-22 18:33:39 stdout [ 5] 7.00-8.00 sec 14.3 MBytes 120 Mbits/sec 0 926 KBytes 2019-03-22 18:33:38 stdout [ 5] 6.00-7.00 sec 15.1 MBytes 127 Mbits/sec 0 916 KBytes 2019-03-22 18:33:37 stdout [ 5] 5.00-6.00 sec 15.3 MBytes 128 Mbits/sec 0 908 KBytes 2019-03-22 18:33:36 stdout [ 5] 4.00-5.00 sec 15.2 MBytes 128 Mbits/sec 0 899 KBytes 2019-03-22 18:33:35 stdout [ 5] 3.00-4.00 sec 15.3 MBytes 128 Mbits/sec 0 884 KBytes 2019-03-22 18:33:34 stdout [ 5] 2.00-3.00 sec 15.4 MBytes 130 Mbits/sec 0 858 KBytes 2019-03-22 18:33:33 stdout [ 5] 1.00-2.00 sec 15.9 MBytes 134 Mbits/sec 0 740 KBytes 2019-03-22 18:33:32 stdout [ 5] 0.00-1.00 sec 9.54 MBytes 80.0 Mbits/sec 0 339 KBytes 2019-03-22 18:33:32 stdout [ ID] Interval Transfer Bandwidth Retr Cwnd

@fabaff
Copy link
Member
fabaff commented Mar 22, 2019

Are you able to use iperf3 from the commandline on that system?

I'm not.

$ iperf3 -c bouygues.iperf.fr
iperf3: error - unable to connect to server: Connection refused

@allserv
Copy link
Author
allserv commented Mar 22, 2019

I'm totally able to use iperf3 from the commandline :

 iperf3 -c bouygues.iperf.fr
Connecting to host bouygues.iperf.fr, port 5201
[  4] local 192.168.1.30 port 56350 connected to 89.84.1.222 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec   175 KBytes  1.44 Mbits/sec    0   43.8 KBytes
[  4]   1.00-2.00   sec   143 KBytes  1.17 Mbits/sec    0   49.5 KBytes
[  4]   2.00-3.00   sec   124 KBytes  1.02 Mbits/sec    0   55.1 KBytes
^C[  4]   3.00-3.60   sec  39.6 KBytes   542 Kbits/sec    0   59.4 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-3.60   sec   482 KBytes  1.10 Mbits/sec    0             sender
[  4]   0.00-3.60   sec  0.00 Bytes  0.00 bits/sec                  receiver
iperf3: interrupt - the client has terminated

I don't know if it's a noticeable point but Bouygues is my ISP

@dooz127
Copy link
dooz127 commented Mar 23, 2019

Yes, I can run iperf3 from the command line:

root@nuc:/usr/src/app/homeassistant/components/iperf3# iperf3 -c LOCAL_SERVER_IP
Connecting to host LOCAL_SERVER_IP, port 5201
[  4] local CLIENT_IP port CLIENT_PORT connected to LOCAL_SERVER_IP port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec  1.69 MBytes  14.2 Mbits/sec    0   49.5 KBytes
[  4]   1.00-2.00   sec  2.24 MBytes  18.8 Mbits/sec    0   80.6 KBytes
[  4]   2.00-3.00   sec  2.17 MBytes  18.2 Mbits/sec    0   90.5 KBytes
[  4]   3.00-4.00   sec  1.80 MBytes  15.1 Mbits/sec    0   96.2 KBytes
[  4]   4.00-5.00   sec  1.99 MBytes  16.7 Mbits/sec    0    113 KBytes
[  4]   5.00-6.00   sec  4.60 MBytes  38.6 Mbits/sec    0    163 KBytes
[  4]   6.00-7.00   sec  4.54 MBytes  38.1 Mbits/sec    0    229 KBytes
[  4]   7.00-8.00   sec  4.78 MBytes  40.1 Mbits/sec    0    266 KBytes
[  4]   8.00-9.00   sec  4.91 MBytes  41.2 Mbits/sec    0    280 KBytes
[  4]   9.00-10.00  sec  4.54 MBytes  38.0 Mbits/sec    0    368 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  33.3 MBytes  27.9 Mbits/sec    0             sender
[  4]   0.00-10.00  sec  31.2 MBytes  26.2 Mbits/sec                  receiver

iperf Done.

@dooz127
Copy link
dooz127 commented Mar 27, 2019

Got a little more output after 90.2 update.

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/app/homeassistant/components/iperf3/__init__.py", line 166, in update
    self._run_test(ATTR_UPLOAD), 'sent_Mbps', None)
  File "/usr/src/app/homeassistant/components/iperf3/__init__.py", line 174, in _run_test
    result = self._client.run()
  File "/usr/local/lib/python3.7/site-packages/iperf3/iperf3.py", line 617, in run
    return TestResult(data)
  File "/usr/local/lib/python3.7/site-packages/iperf3/iperf3.py", line 776, in __init__
    self.time = self.json['start']['timestamp']['time']
KeyError: 'timestamp'

@larserhardsen
Copy link

I have the exact same issue after upgrading from 88.2 to 90.2:
[homeassistant.components.iperf3] Iperf3 error: unable to send cookie to server: Broken pipe

Also, the iperf3 command works just fine when executed "standalone":

$ iperf3 -c 10.17.38.38
Connecting to host 10.17.38.38, port 5201
[  4] local 10.17.10.108 port 39332 connected to 10.17.38.38 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec  13.7 MBytes   115 Mbits/sec    0    748 KBytes 
...

@magenbrot
Copy link
Contributor

I have the same issue. Maybe @rohankapoorcom has more information, since this problem has appeared once the component was split up?

@kb5zuy
Copy link
kb5zuy commented Apr 6, 2019

same issue here. HA on RPi3B, python 3.5. It broke a few HA releases ago; it worked before the split up of the component. I run several RPis around the house and use iperf3 to test the home network throughput. Relevant config:

iperf3:
hosts:
- host: calendar
- host: ernest
- host: awesome
- host: baby
- host: tunnel
monitored_conditions:
- download
- upload
manual: true

Sometimes the manual test will work - I think the first time after an HA restart, but not again until another restart. The sensor values never update.

I thought it might be related to using python3.5 vs 3.6 but I have not tested that. iperf3 works fine from the command line as well.

I have seen both the "unable to send cookie" and the Keyerror: timestamp error. It seems like HA cannot start the iperf3 binary.

@rohankapoorcom
Copy link
Member

I've been looking through the code again and trying to reproduce this but I am unable to do so.

I took another look at #21138 (where the component was split up) and do not see anything different in how the library is called (and the same version of the library is used) before and after the split.

As far as I can tell, all of the syntax should be python 3.5 compliant (though the iperf3 lib specifies it's tested again 2.7 and 3.6 only).

Can you check what version of iperf3 you have installed and whether they are on this list?

I'm running iperf 3.0.11 on Ubuntu 16.04 (python 3.6.8).

@larserhardsen
Copy link

I have the issue on a Hassbian with Python 3.5.3 and iperf3 3.1.3.
Similar, the issue appears on MacOS and a docker image running on a Qnap.

@magenbrot
Copy link
Contributor
magenbrot commented Apr 8, 2019

I'm running iperf3 3.1.3 also with Python 3.5.3 in a Debian Stretch LXC Container. It works perfectly when running from command line, also when using the python3 lib as described in the quickstart part here https://github.com/thiezn/iperf3-python#quickstart

 $  root@homeassistant  ◰³ homeassistant  ~  python
Python 3.5.3 (default, Sep 27 2018, 17:25:39) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import iperf3
>>> 
>>> client = iperf3.Client()
>>> client.duration = 10
>>> client.server_hostname = '<myiperfhost>'
>>> client.port = 5201
>>> result = client.run()
>>> result.sent_Mbps
29.791971288709

Can we somehow output the command line or the way the python lib is called?

8000

@kb5zuy
Copy link
kb5zuy commented Apr 9, 2019

I did some more testing. I installed python3.6 as per http://www.knight-of-pi.org/installing-python3-6-on-a-raspberry-pi/. I installed home assistant and dependencies ( I use ansible to push the home assistant config and dependencies). I then started hass. No difference with 3.6. Same kind of behaviour. Like @magenbrot said above, can we see if the iperf3 binary is being spawned correctly?

@larserhardsen
Copy link

Tested with a brand new Hassio install, 0.92.2, on a Debian 9 server and unfortunately the issue is still there.

@zanix
Copy link
zanix commented Jul 22, 2019

Having this issue as well on 0.95.4 using the docker container.
I was able to use iperf3 directly via the command line outside of the docker container, inside of the docker container, and via python using the commands from @magenbrot

@Choo-lux
Copy link

also with lxc here, same issue

python 3.6.4
iperf 3.3 from ubuntu apt and 3.6 from source

8000

@Choo-lux
Copy link

HA installs the python wrapper and you must manually install iperf3.
Sometimes it works once from HA then the cookie error comes up.

any idea how to debug?

(homeassistant) hass@HASS:~$ pip3 show iperf3
Name: iperf3
Version: 0.1.11
Summary: Python wrapper around iperf3
Home-page: https://github.com/thiezn/iperf3-python
Author: Mathijs Mortimer
Author-email: mathijs@mortimer.nl
License: MIT
Location: /srv/homeassistant/lib/python3.6/site-packages
Requires:
(homeassistant) hass@HASS:~$ sudo apt-cache policy iperf3
iperf3:
  Installed: 3.1.3-1
  Candidate: 3.1.3-1

@dooz127
Copy link
dooz127 commented Dec 4, 2019

Looks like this is a known issue with a pending pull request in the source repository for iperf3:

esnet/iperf#818

@dooz127
Copy link
dooz127 commented Dec 4, 2019

I'm not a software developer, and I feel like Richard Hendricks in his early days at Hooli using brute force programming, but instantiating a second client for the second iperf3 test plus a 2 second delay fixed this bug for me. Hopefully someone can come up with a more elegant solution. Some additional context here:

esnet/iperf#753

And my crappy fix of init.py_:

"""Support for Iperf3 network measurement tool."""
from datetime import timedelta
from time import time, sleep # need a delay between tests
import logging

import iperf3
import voluptuous as vol

from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import (
    CONF_HOST,
    CONF_HOSTS,
    CONF_MONITORED_CONDITIONS,
    CONF_PORT,
    CONF_PROTOCOL,
    CONF_SCAN_INTERVAL,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.helpers.event import async_track_time_interval

DOMAIN = "iperf3"
DATA_UPDATED = f"{DOMAIN}_data_updated"

_LOGGER = logging.getLogger(__name__)

CONF_DURATION = "duration"
CONF_PARALLEL = "parallel"
CONF_MANUAL = "manual"

DEFAULT_DURATION = 10
DEFAULT_PORT = 5201
DEFAULT_PARALLEL = 1
DEFAULT_PROTOCOL = "tcp"
DEFAULT_INTERVAL = timedelta(minutes=60)

ATTR_DOWNLOAD = "download"
ATTR_UPLOAD = "upload"
ATTR_VERSION = "Version"
ATTR_HOST = "host"

UNIT_OF_MEASUREMENT = "Mbit/s"

SENSOR_TYPES = {
    ATTR_DOWNLOAD: [ATTR_DOWNLOAD.capitalize(), UNIT_OF_MEASUREMENT],
    ATTR_UPLOAD: [ATTR_UPLOAD.capitalize(), UNIT_OF_MEASUREMENT],
}

PROTOCOLS = ["tcp", "udp"]

HOST_CONFIG_SCHEMA = vol.Schema(
    {
        vol.Required(CONF_HOST): cv.string,
        vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
        vol.Optional(CONF_DURATION, default=DEFAULT_DURATION): vol.Range(5, 10),
        vol.Optional(CONF_PARALLEL, default=DEFAULT_PARALLEL): vol.Range(1, 20),
        vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL): vol.In(PROTOCOLS),
    }
)

CONFIG_SCHEMA = vol.Schema(
    {
        DOMAIN: vol.Schema(
            {
                vol.Required(CONF_HOSTS): vol.All(cv.ensure_list, [HOST_CONFIG_SCHEMA]),
                vol.Optional(
                    CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)
                ): vol.All(cv.ensure_list, [vol.In(list(SENSOR_TYPES))]),
                vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_INTERVAL): vol.All(
                    cv.time_period, cv.positive_timedelta
                ),
                vol.Optional(CONF_MANUAL, default=False): cv.boolean,
            }
        )
    },
    extra=vol.ALLOW_EXTRA,
)

SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_HOST, default=None): cv.string})


async def async_setup(hass, config):
    """Set up the iperf3 component."""
    hass.data[DOMAIN] = {}

    conf = config[DOMAIN]
    for host in conf[CONF_HOSTS]:
        host_name = host[CONF_HOST]

        client = iperf3.Client()
        client.duration = host[CONF_DURATION]
        client.server_hostname = host_name
        client.port = host[CONF_PORT]
        client.num_streams = host[CONF_PARALLEL]
        client.protocol = host[CONF_PROTOCOL]
        client.verbose = False

        # dumb instantiation of second client
        client2 = iperf3.Client()
        client2.duration = host[CONF_DURATION]                                           
        client2.server_hostname = host_name                                              
        client2.port = host[CONF_PORT]                                                   
        client2.num_streams = host[CONF_PARALLEL]                                        
        client2.protocol = host[CONF_PROTOCOL]                                           
        client2.verbose = False

        data = hass.data[DOMAIN][host_name] = Iperf3Data(hass, client, client2)

        if not conf[CONF_MANUAL]:
            async_track_time_interval(hass, data.update, conf[CONF_SCAN_INTERVAL])

    def update(call):
        """Service call to manually update the data."""
        called_host = call.data[ATTR_HOST]
        if called_host in hass.data[DOMAIN]:
            hass.data[DOMAIN][called_host].update()
        else:
            for iperf3_host in hass.data[DOMAIN].values():
                iperf3_host.update()

    hass.services.async_register(DOMAIN, "speedtest", update, schema=SERVICE_SCHEMA)

    hass.async_create_task(
        async_load_platform(
            hass, SENSOR_DOMAIN, DOMAIN, conf[CONF_MONITORED_CONDITIONS], config
        )
    )

    return True


class Iperf3Data:
    """Get the latest data from iperf3."""

    def __init__(self, hass, client, client2):
        """Initialize the data object."""
        self._hass = hass
        self._client = client
        self._client2 = client2
        self.data = {ATTR_DOWNLOAD: None, ATTR_UPLOAD: None, ATTR_VERSION: None}

    @property
    def protocol(self):
        """Return the protocol used for this connection."""
        return self._client.protocol

    @property
    def host(self):
        """Return the host connected to."""
        return self._client.server_hostname

    @property
    def port(self):
        """Return the port on the host connected to."""
        return self._client.port

    def update(self, now=None):
        """Get the latest data from iperf3."""
        if self.protocol == "udp":
            # UDP only have 1 way attribute
            result = self._run_test(ATTR_DOWNLOAD)
            self.data[ATTR_DOWNLOAD] = self.data[ATTR_UPLOAD] = getattr(
                result, "Mbps", None
            )
            self.data[ATTR_VERSION] = getattr(result, "version", None)
        else:
            result = self._run_test(ATTR_DOWNLOAD)
            self.data[ATTR_DOWNLOAD] = getattr(result, "received_Mbps", None)
            self.data[ATTR_VERSION] = getattr(result, "version", None)
            self.data[ATTR_UPLOAD] = getattr(
                self._run_test(ATTR_UPLOAD), "sent_Mbps", None
            )

        dispatcher_send(self._hass, DATA_UPDATED, self.host)

    def _run_test(self, test_type):
        """Run and return the iperf3 data."""
        self._client.reverse = test_type == ATTR_DOWNLOAD
        try:
            if self._client.reverse:
              result = self._client.run()
              sleep(2)
            else:
              result = self._client2.run()
        except (AttributeError, OSError, ValueError) as error:
            _LOGGER.error("Iperf3 error: %s", error)
            return None

        if result is not None and hasattr(result, "error") and result.error is not None:
            _LOGGER.error("Iperf3 error: %s", result.error)
            return None

        return result

@rohankapoorcom
Copy link
Member

Thanks for finding the problem @dooz127. I'll make a PR with the requisite changes this evening. Currently debating between storing 2 clients or just regenerating a client every time it's needed.

@rohankapoorcom rohankapoorcom self-assigned this Dec 4, 2019
@rohankapoorcom
Copy link
Member

Having thought about it a bit, I think it's cleaner to regenerate the client every time that it's needed - that means that we can avoid any of the sleeping.

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

Successfully merging a pull request may close this issue.

10 participants
0