From 09c0629bb728ad342a41d844143d8e7437c925c4 Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Thu, 19 Aug 2021 14:32:42 +0100 Subject: [PATCH] Use TCP keepalives for ovsdb connections Ultimately, this is something that should be fixed in python-ovs, but setting the SO_KEEPALIVE socket option benefits the client by removing the need to send 'echo' requests, which can time out on an overloaded ovsdb-server, which causes a disconnection which then# adds even more load on the ovsdb-server as it has to send the entire db contents over the wire after the connection is restored. This patch ports the optimisation form neutron to reduce the likelyhood of a reconnection which can cause the nova compute agent to hang temporarily while the connection is reestablished. Change-Id: I984ec62730276f8ee60d71a02a98fbfc4c37f7d8 Related-Bug: #1930926 Partial-Bug: #1929446 --- vif_plug_ovs/ovsdb/impl_idl.py | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/vif_plug_ovs/ovsdb/impl_idl.py b/vif_plug_ovs/ovsdb/impl_idl.py index 6dc2ffe1..11f75ff4 100644 --- a/vif_plug_ovs/ovsdb/impl_idl.py +++ b/vif_plug_ovs/ovsdb/impl_idl.py @@ -10,7 +10,12 @@ # License for the specific language governing permissions and limitations # under the License. +import functools +import socket + from ovs.db import idl +from ovs import socket_util +from ovs import stream from ovsdbapp.backend.ovs_idl import connection from ovsdbapp.backend.ovs_idl import idlutils from ovsdbapp.backend.ovs_idl import vlog @@ -49,3 +54,43 @@ class NeutronOvsdbIdl(impl_idl.OvsdbIdl, api.ImplAPI): def has_table_column(self, table, column): return column in self._get_table_columns(table) + + +# this is derived form https://review.opendev.org/c/openstack/neutron/+/794892 +def add_keepalives(fn): + @functools.wraps(fn) + def _open(*args, **kwargs): + error, sock = fn(*args, **kwargs) + try: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + except socket.error as e: + sock.close() + return socket_util.get_exception_errno(e), None + return error, sock + return _open + + +class NoProbesMixin: + @staticmethod + def needs_probes(): + # If we are using keepalives, we can force probe_interval=0 + return False + + +class TCPStream(stream.TCPStream, NoProbesMixin): + @classmethod + @add_keepalives + def _open(cls, suffix, dscp): + return super()._open(suffix, dscp) + + +class SSLStream(stream.SSLStream, NoProbesMixin): + @classmethod + @add_keepalives + def _open(cls, suffix, dscp): + return super()._open(suffix, dscp) + + +# Overwriting globals in a library is clearly a good idea +stream.Stream.register_method("tcp", TCPStream) +stream.Stream.register_method("ssl", SSLStream)