From ee63f1244f8f3fa03c4c460fd98a6b5799085317 Mon Sep 17 00:00:00 2001 From: Open vSwitch CI Date: Nov 10 2021 14:22:14 +0000 Subject: Import openvswitch2.16-2.16.0-30 from Fast DataPath --- diff --git a/SOURCES/openvswitch-2.16.0.patch b/SOURCES/openvswitch-2.16.0.patch index bb19a71..3eecc53 100644 --- a/SOURCES/openvswitch-2.16.0.patch +++ b/SOURCES/openvswitch-2.16.0.patch @@ -1,20 +1,22 @@ diff --git a/.ci/linux-prepare.sh b/.ci/linux-prepare.sh -index c55125cf78..e4d2a187e0 100755 +index c55125cf78..360c0a68ea 100755 --- a/.ci/linux-prepare.sh +++ b/.ci/linux-prepare.sh -@@ -22,7 +22,6 @@ cd .. +@@ -21,8 +21,7 @@ make -j4 HAVE_LLVM= HAVE_SQLITE= install + cd .. pip3 install --disable-pip-version-check --user \ - flake8 hacking sphinx pyOpenSSL wheel setuptools +- flake8 hacking sphinx pyOpenSSL wheel setuptools -pip3 install --user --upgrade docutils ++ flake8 hacking sphinx wheel setuptools pip3 install --user 'meson==0.47.1' if [ "$M32" ]; then diff --git a/.cirrus.yml b/.cirrus.yml -index 358f2ba256..480fea2421 100644 +index 358f2ba256..a7ae793bc4 100644 --- a/.cirrus.yml +++ b/.cirrus.yml -@@ -5,7 +5,7 @@ freebsd_build_task: +@@ -5,11 +5,11 @@ freebsd_build_task: image_family: freebsd-12-2-snap image_family: freebsd-11-4-snap cpu: 4 @@ -23,6 +25,11 @@ index 358f2ba256..480fea2421 100644 env: DEPENDENCIES: automake libtool gmake gcc wget openssl python3 +- PY_DEPS: sphinx|openssl ++ PY_DEPS: sphinx + matrix: + COMPILER: gcc + COMPILER: clang diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index e2350c6d9d..7434ad18ec 100644 --- a/.github/workflows/build-and-test.yml @@ -45,13 +52,28 @@ index e2350c6d9d..7434ad18ec 100644 - name: install dependencies run: brew install automake libtool - name: prepare +diff --git a/.travis.yml b/.travis.yml +index 51d0511080..c7aeede06e 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -17,7 +17,6 @@ addons: + - libjemalloc-dev + - libnuma-dev + - libpcap-dev +- - python3-openssl + - python3-pip + - python3-sphinx + - libelf-dev diff --git a/NEWS b/NEWS -index 559a51ba3f..7a6de3da82 100644 +index 559a51ba3f..139c24a4f8 100644 --- a/NEWS +++ b/NEWS -@@ -1,3 +1,10 @@ +@@ -1,3 +1,13 @@ +v2.16.2 - xx xxx xxxx +--------------------- ++ - Python: ++ * For SSL support, the use of the pyOpenSSL library has been replaced ++ with the native 'ssl' module. + +v2.16.1 - 21 Oct 2021 +--------------------- @@ -3720,6 +3742,271 @@ index 626ae8fc44..3318a3b6f8 100644 else: return "%(dst)s = %(src)s;" % args +diff --git a/python/ovs/poller.py b/python/ovs/poller.py +index 3624ec8655..157719c3a4 100644 +--- a/python/ovs/poller.py ++++ b/python/ovs/poller.py +@@ -26,9 +26,9 @@ if sys.platform == "win32": + import ovs.winutils as winutils + + try: +- from OpenSSL import SSL ++ import ssl + except ImportError: +- SSL = None ++ ssl = None + + try: + from eventlet import patcher as eventlet_patcher +@@ -73,7 +73,7 @@ class _SelectSelect(object): + def register(self, fd, events): + if isinstance(fd, socket.socket): + fd = fd.fileno() +- if SSL and isinstance(fd, SSL.Connection): ++ if ssl and isinstance(fd, ssl.SSLSocket): + fd = fd.fileno() + + if sys.platform != 'win32': +diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py +index 3faa64e9d7..651012bf06 100644 +--- a/python/ovs/socket_util.py ++++ b/python/ovs/socket_util.py +@@ -222,8 +222,7 @@ def inet_parse_active(target, default_port): + return (host_name, port) + + +-def inet_open_active(style, target, default_port, dscp): +- address = inet_parse_active(target, default_port) ++def inet_create_socket_active(style, address): + try: + is_addr_inet = is_valid_ipv4_address(address[0]) + if is_addr_inet: +@@ -235,23 +234,32 @@ def inet_open_active(style, target, default_port, dscp): + except socket.error as e: + return get_exception_errno(e), None + ++ return family, sock ++ ++ ++def inet_connect_active(sock, address, family, dscp): + try: + set_nonblocking(sock) + set_dscp(sock, family, dscp) +- try: +- sock.connect(address) +- except socket.error as e: +- error = get_exception_errno(e) +- if sys.platform == 'win32' and error == errno.WSAEWOULDBLOCK: +- # WSAEWOULDBLOCK would be the equivalent on Windows +- # for EINPROGRESS on Unix. +- error = errno.EINPROGRESS +- if error != errno.EINPROGRESS: +- raise +- return 0, sock ++ error = sock.connect_ex(address) ++ if error not in (0, errno.EINPROGRESS, errno.EWOULDBLOCK): ++ sock.close() ++ return error ++ return 0 + except socket.error as e: + sock.close() +- return get_exception_errno(e), None ++ return get_exception_errno(e) ++ ++ ++def inet_open_active(style, target, default_port, dscp): ++ address = inet_parse_active(target, default_port) ++ family, sock = inet_create_socket_active(style, address) ++ if sock is None: ++ return family, sock ++ error = inet_connect_active(sock, address, family, dscp) ++ if error: ++ return error, None ++ return 0, sock + + + def get_exception_errno(e): +diff --git a/python/ovs/stream.py b/python/ovs/stream.py +index f5a520862c..ac5b0fd0c6 100644 +--- a/python/ovs/stream.py ++++ b/python/ovs/stream.py +@@ -22,9 +22,9 @@ import ovs.socket_util + import ovs.vlog + + try: +- from OpenSSL import SSL ++ import ssl + except ImportError: +- SSL = None ++ ssl = None + + if sys.platform == 'win32': + import ovs.winutils as winutils +@@ -322,6 +322,12 @@ class Stream(object): + The recv function will not block waiting for data to arrive. If no + data have been received, it returns (errno.EAGAIN, "") immediately.""" + ++ try: ++ return self._recv(n) ++ except socket.error as e: ++ return (ovs.socket_util.get_exception_errno(e), "") ++ ++ def _recv(self, n): + retval = self.connect() + if retval != 0: + return (retval, "") +@@ -331,10 +337,7 @@ class Stream(object): + if sys.platform == 'win32' and self.socket is None: + return self.__recv_windows(n) + +- try: +- return (0, self.socket.recv(n)) +- except socket.error as e: +- return (ovs.socket_util.get_exception_errno(e), "") ++ return (0, self.socket.recv(n)) + + def __recv_windows(self, n): + if self._read_pending: +@@ -396,6 +399,12 @@ class Stream(object): + Will not block. If no bytes can be immediately accepted for + transmission, returns -errno.EAGAIN immediately.""" + ++ try: ++ return self._send(buf) ++ except socket.error as e: ++ return -ovs.socket_util.get_exception_errno(e) ++ ++ def _send(self, buf): + retval = self.connect() + if retval != 0: + return -retval +@@ -409,10 +418,7 @@ class Stream(object): + if sys.platform == 'win32' and self.socket is None: + return self.__send_windows(buf) + +- try: +- return self.socket.send(buf) +- except socket.error as e: +- return -ovs.socket_util.get_exception_errno(e) ++ return self.socket.send(buf) + + def __send_windows(self, buf): + if self._write_pending: +@@ -769,35 +775,42 @@ class SSLStream(Stream): + def check_connection_completion(sock): + try: + return Stream.check_connection_completion(sock) +- except SSL.SysCallError as e: ++ except ssl.SSLSyscallError as e: + return ovs.socket_util.get_exception_errno(e) + + @staticmethod + def needs_probes(): + return True + +- @staticmethod +- def verify_cb(conn, cert, errnum, depth, ok): +- return ok +- + @staticmethod + def _open(suffix, dscp): +- error, sock = TCPStream._open(suffix, dscp) +- if error: +- return error, None ++ address = ovs.socket_util.inet_parse_active(suffix, 0) ++ family, sock = ovs.socket_util.inet_create_socket_active( ++ socket.SOCK_STREAM, address) ++ if sock is None: ++ return family, sock + + # Create an SSL context +- ctx = SSL.Context(SSL.SSLv23_METHOD) +- ctx.set_verify(SSL.VERIFY_PEER, SSLStream.verify_cb) +- ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) ++ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) ++ ctx.verify_mode = ssl.CERT_REQUIRED ++ ctx.options |= ssl.OP_NO_SSLv2 ++ ctx.options |= ssl.OP_NO_SSLv3 + # If the client has not set the SSL configuration files + # exception would be raised. +- ctx.use_privatekey_file(Stream._SSL_private_key_file) +- ctx.use_certificate_file(Stream._SSL_certificate_file) + ctx.load_verify_locations(Stream._SSL_ca_cert_file) ++ ctx.load_cert_chain(Stream._SSL_certificate_file, ++ Stream._SSL_private_key_file) ++ ssl_sock = ctx.wrap_socket(sock, do_handshake_on_connect=False) + +- ssl_sock = SSL.Connection(ctx, sock) +- ssl_sock.set_connect_state() ++ # Connect ++ error = ovs.socket_util.inet_connect_active(ssl_sock, address, family, ++ dscp) ++ if not error: ++ try: ++ ssl_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) ++ except socket.error as e: ++ ssl_sock.close() ++ return ovs.socket_util.get_exception_errno(e), None + return error, ssl_sock + + def connect(self): +@@ -809,40 +822,44 @@ class SSLStream(Stream): + # TCP Connection is successful. Now do the SSL handshake + try: + self.socket.do_handshake() +- except SSL.WantReadError: ++ except ssl.SSLWantReadError: + return errno.EAGAIN +- except SSL.SysCallError as e: ++ except ssl.SSLSyscallError as e: + return ovs.socket_util.get_exception_errno(e) + + return 0 + + def recv(self, n): + try: +- return super(SSLStream, self).recv(n) +- except SSL.WantReadError: ++ return super(SSLStream, self)._recv(n) ++ except ssl.SSLWantReadError: + return (errno.EAGAIN, "") +- except SSL.SysCallError as e: ++ except ssl.SSLSyscallError as e: + return (ovs.socket_util.get_exception_errno(e), "") +- except SSL.ZeroReturnError: ++ except ssl.SSLZeroReturnError: + return (0, "") ++ except socket.error as e: ++ return (ovs.socket_util.get_exception_errno(e), "") + + def send(self, buf): + try: +- return super(SSLStream, self).send(buf) +- except SSL.WantWriteError: ++ return super(SSLStream, self)._send(buf) ++ except ssl.SSLWantWriteError: + return -errno.EAGAIN +- except SSL.SysCallError as e: ++ except ssl.SSLSyscallError as e: ++ return -ovs.socket_util.get_exception_errno(e) ++ except socket.error as e: + return -ovs.socket_util.get_exception_errno(e) + + def close(self): + if self.socket: + try: +- self.socket.shutdown() +- except SSL.Error: ++ self.socket.shutdown(socket.SHUT_RDWR) ++ except socket.error: + pass + return super(SSLStream, self).close() + + +-if SSL: ++if ssl: + # Register SSL only if the OpenSSL module is available + Stream.register_method("ssl", SSLStream) diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 956a69e1fa..1dad6f62c6 100644 --- a/tests/ofproto-dpif.at @@ -3821,6 +4108,19 @@ index 8cd2a26cb3..25c6acdac6 100644 OK]]) OVSDB_CHECK_NEGATIVE([generate and apply diff with map -- size error], +diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at +index 1386f13770..cd28a587c6 100644 +--- a/tests/ovsdb-idl.at ++++ b/tests/ovsdb-idl.at +@@ -225,7 +225,7 @@ m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PY], + m4_define([OVSDB_CHECK_IDL_SSL_PY], + [AT_SETUP([$1 - Python3 - SSL]) + AT_SKIP_IF([test "$HAVE_OPENSSL" = no]) +- $PYTHON3 -c "import OpenSSL.SSL" ++ $PYTHON3 -c "import ssl" + SSL_PRESENT=$? + AT_SKIP_IF([test $SSL_PRESENT != 0]) + AT_KEYWORDS([ovsdb server idl positive Python with ssl socket $5]) diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at index ac243d6a79..2b742f78b0 100644 --- a/tests/ovsdb-server.at diff --git a/SPECS/openvswitch2.16.spec b/SPECS/openvswitch2.16.spec index 33af697..2bc08fb 100644 --- a/SPECS/openvswitch2.16.spec +++ b/SPECS/openvswitch2.16.spec @@ -57,7 +57,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.16.0 -Release: 28%{?dist} +Release: 30%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -699,6 +699,60 @@ exit 0 %endif %changelog +* Wed Nov 10 2021 Timothy Redaelli - 2.16.0-30 +- python: Replace pyOpenSSL with ssl. [RH git: 0cd5867531] (#1988429) + Currently, pyOpenSSL is half-deprecated upstream and so it's removed on + some distributions (for example on CentOS Stream 9, + https://issues.redhat.com/browse/CS-336), but since OVS only + supports Python 3 it's possible to replace pyOpenSSL with "import ssl" + included in base Python 3. + + Stream recv and send had to be splitted as _recv and _send, since SSLError + is a subclass of socket.error and so it was not possible to except for + SSLWantReadError and SSLWantWriteError in recv and send of SSLStream. + + TCPstream._open cannot be used in SSLStream, since Python ssl module + requires the SSL socket to be created before connecting it, so + SSLStream._open needs to create the socket, create SSL socket and then + connect the SSL socket. + + Reported-by: Timothy Redaelli + Reported-at: https://bugzilla.redhat.com/1988429 + Signed-off-by: Timothy Redaelli + Acked-by: Terry Wilson + Tested-by: Terry Wilson + Signed-off-by: Ilya Maximets + Signed-off-by: Timothy Redaelli + + +* Wed Nov 10 2021 Timothy Redaelli - 2.16.0-29 +- python: socket-util: Split inet_open_active function and use connect_ex. [RH git: 2e704b371c] + In an upcoming patch, PyOpenSSL will be replaced with Python ssl module, + but in order to do an async connection with Python ssl module the ssl + socket must be created when the socket is created, but before the + socket is connected. + + So, inet_open_active function is splitted in 3 parts: + - inet_create_socket_active: creates the socket and returns the family and + the socket, or (error, None) if some error needs to be returned. + - inet_connect_active: connect the socket and returns the errno (it + returns 0 if errno is EINPROGRESS or EWOULDBLOCK). + + connect is replaced by connect_ex, since Python suggest to use it for + asynchronous connects and it's also cleaner since inet_connect_active + returns errno that connect_ex already returns, moreover due to a Python + limitation connect cannot not be used with ssl module. + + inet_open_active function is changed in order to use the new functions + inet_create_socket_active and inet_connect_active. + + Signed-off-by: Timothy Redaelli + Acked-by: Terry Wilson + Tested-by: Terry Wilson + Signed-off-by: Ilya Maximets + Signed-off-by: Timothy Redaelli + + * Wed Nov 10 2021 Timothy Redaelli - 2.16.0-28 - redhat: remove mlx4 support [RH git: 4c846afd24] (#1998122) Resolves: #1998122