From: Ondrej Lichtner olichtne@redhat.com
When we reconnect to netlink we risk bringing the InterfaceManager into an inconsistent state by discarding broadcast messages from the old socket. Because of this we should call rescan_devices every time a new netlink socket is bound.
Calling this method manually in the NetTestSlave after namespace creation is therefore not necessary anymore.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Slave/InterfaceManager.py | 2 ++ lnst/Slave/NetTestSlave.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py index 62b2805..9e89f2b 100644 --- a/lnst/Slave/InterfaceManager.py +++ b/lnst/Slave/InterfaceManager.py @@ -82,6 +82,8 @@ class InterfaceManager(object): self._nl_socket = IPRSocket() self._nl_socket.bind()
+ self.rescan_devices() + def get_nl_socket(self): return self._nl_socket
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py index 1c6f47b..8695d5e 100644 --- a/lnst/Slave/NetTestSlave.py +++ b/lnst/Slave/NetTestSlave.py @@ -643,7 +643,6 @@ class SlaveMethods: self._log_ctl.set_origin_name(netns) self._log_ctl.set_connection(write_pipe)
- self._if_manager.rescan_devices() logging.debug("Created network namespace %s" % netns) return True else:
From: Ondrej Lichtner olichtne@redhat.com
The default bind() call on the IPRSocket binds us to all possible RTNL broadcast groups. This restricts those groups to just those related to link and ip address updates. This should reduce the number of messages, hopefuly lovering the changes of the socket running out of buffer space and getting closed by the kernel.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Slave/InterfaceManager.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py index 9e89f2b..e28b353 100644 --- a/lnst/Slave/InterfaceManager.py +++ b/lnst/Slave/InterfaceManager.py @@ -22,6 +22,9 @@ from lnst.Common.NetUtils import scan_netdevs from lnst.Common.ExecCmd import exec_cmd from lnst.Common.ConnectionHandler import recv_data from pyroute2 import IPRSocket +from pyroute2.netlink.rtnl import RTNLGRP_IPV4_IFADDR +from pyroute2.netlink.rtnl import RTNLGRP_IPV6_IFADDR +from pyroute2.netlink.rtnl import RTNLGRP_LINK try: from pyroute2.netlink.iproute import RTM_NEWLINK from pyroute2.netlink.iproute import RTM_DELLINK @@ -36,6 +39,8 @@ except ImportError: class IfMgrError(Exception): pass
+NL_GROUPS = RTNLGRP_IPV4_IFADDR | RTNLGRP_IPV6_IFADDR | RTNLGRP_LINK + class InterfaceManager(object): def __init__(self, server_handler): self._devices = {} #if_index to device @@ -43,7 +48,7 @@ class InterfaceManager(object): self._tmp_mapping = {} #id from the ctl to newly created device
self._nl_socket = IPRSocket() - self._nl_socket.bind() + self._nl_socket.bind(groups=NL_GROUPS)
self.rescan_devices()
@@ -80,7 +85,7 @@ class InterfaceManager(object): self._nl_socket.close() self._nl_socket = None self._nl_socket = IPRSocket() - self._nl_socket.bind() + self._nl_socket.bind(groups=NL_GROUPS)
self.rescan_devices()
From: Ondrej Lichtner olichtne@redhat.com
The ServerHandler automatically closes all sockets that are either closed from the other side or get into a broken state. This is normally fine, however in case the socket in question is the Netlink socket, the InterfaceManager doesn't get notified of this event and attempts to call on this object fail with EBADF.
This makes sure that whenever the ServerHandler closes the socket, it calls the InterfaceManager reconnect_netlink() method so that a new netlink connection is established.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Slave/NetTestSlave.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py index 8695d5e..157b651 100644 --- a/lnst/Slave/NetTestSlave.py +++ b/lnst/Slave/NetTestSlave.py @@ -842,8 +842,13 @@ class ServerHandler(ConnectionHandler): self._netns = None self._c_socket = None
+ self._if_manager = None + self._security = lnst_config.get_section_values("security")
+ def set_if_manager(self, if_manager): + self._if_manager = if_manager + def accept_connection(self): self._c_socket, addr = self._s_socket.accept() self._c_socket = (SlaveSecSocket(self._c_socket), addr[0]) @@ -880,6 +885,13 @@ class ServerHandler(ConnectionHandler): self.remove_connection(self._c_socket[0]) self._c_socket = None
+ def check_connections(self): + msgs = super(ServerHandler, self).check_connections() + if 'netlink' not in self._connection_mapping: + self._if_manager.reconnect_netlink() + self.add_connection('netlink', self._if_manager.get_nl_socket()) + return msgs + def get_messages(self): messages = self.check_connections()
@@ -963,6 +975,8 @@ class NetTestSlave: self._server_handler = ServerHandler(("", port)) self._if_manager = InterfaceManager(self._server_handler)
+ self._server_handler.set_if_manager(self._if_manager) + self._net_namespaces = {}
self._methods = SlaveMethods(self._cmd_context, log_ctl,
Fri, May 13, 2016 at 11:01:20AM IDT, olichtne@redhat.com wrote:
From: Ondrej Lichtner olichtne@redhat.com
The ServerHandler automatically closes all sockets that are either closed from the other side or get into a broken state. This is normally fine, however in case the socket in question is the Netlink socket, the InterfaceManager doesn't get notified of this event and attempts to call on this object fail with EBADF.
This makes sure that whenever the ServerHandler closes the socket, it calls the InterfaceManager reconnect_netlink() method so that a new netlink connection is established.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com
Thanks for taking care of this Ondrej. I'll test this today and report.
Fri, May 13, 2016 at 11:01:19AM IDT, olichtne@redhat.com wrote:
From: Ondrej Lichtner olichtne@redhat.com
The default bind() call on the IPRSocket binds us to all possible RTNL broadcast groups. This restricts those groups to just those related to link and ip address updates. This should reduce the number of messages, hopefuly lovering the changes of the socket running out of
"hopefully lowering the chances of ..."
buffer space and getting closed by the kernel.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com
Fri, May 13, 2016 at 11:01:20AM IDT, olichtne@redhat.com wrote:
From: Ondrej Lichtner olichtne@redhat.com
The ServerHandler automatically closes all sockets that are either closed from the other side or get into a broken state. This is normally fine, however in case the socket in question is the Netlink socket, the InterfaceManager doesn't get notified of this event and attempts to call on this object fail with EBADF.
This makes sure that whenever the ServerHandler closes the socket, it calls the InterfaceManager reconnect_netlink() method so that a new netlink connection is established.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com
I ran most of our L2 tests and I didn't get this error message anymore, so:
Tested-by: Ido Schimmel idosch@mellanox.com
Thanks!
lnst-developers@lists.fedorahosted.org