[ovs-dev] [PATCH] add TCP passive-mode to IDL

ofer.benyacov at gmail.com ofer.benyacov at gmail.com
Wed May 18 15:29:13 UTC 2016


From: Ofer Ben-Yacov <ofer.benyacov at gmail.com>

Signed-off-by: "Ofer Ben-Yacov" <ofer.benyacov at gmail.com>

Requested-by: Ben Pfaff <blp at nicira.com>, 
Requested-by: "D M, Vikas" <vikas.d-m at hpe.com>,
Requested-by: "Kamat, Maruti Haridas" <maruti.kamat at hpe.com>,
Requested-by: "Sukhdev Kapur" <sukhdev at arista.com>,
Requested-by: "Migliaccio, Armando" <armando.migliaccio at hpe.com>

---
 python/ovs/jsonrpc.py |  2 +-
 python/ovs/stream.py  | 33 +++++++++++++++++++++++----------
 tests/ovsdb-idl.at    | 29 +++++++++++++++++++++++++++++
 tests/test-ovsdb.py   | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 100 insertions(+), 12 deletions(-)

diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py
index e3ef6db..6300c67 100644
--- a/python/ovs/jsonrpc.py
+++ b/python/ovs/jsonrpc.py
@@ -435,7 +435,7 @@ class Session(object):
                 self.reconnect.connecting(ovs.timeval.msec())
             else:
                 self.reconnect.connect_failed(ovs.timeval.msec(), error)
-        elif self.pstream is not None:
+        elif self.pstream is None:
             error, self.pstream = ovs.stream.PassiveStream.open(name)
             if not error:
                 self.reconnect.listening(ovs.timeval.msec())
diff --git a/python/ovs/stream.py b/python/ovs/stream.py
index 64d9544..97b22ac 100644
--- a/python/ovs/stream.py
+++ b/python/ovs/stream.py
@@ -269,9 +269,9 @@ class PassiveStream(object):
     @staticmethod
     def is_valid_name(name):
         """Returns True if 'name' is a passive stream name in the form
-        "TYPE:ARGS" and TYPE is a supported passive stream type (currently only
-        "punix:"), otherwise False."""
-        return name.startswith("punix:")
+        "TYPE:ARGS" and TYPE is a supported passive stream type (currently
+        "punix:" or "ptcp"), otherwise False."""
+        return name.startswith("punix:") | name.startswith("ptcp:")
 
     def __init__(self, sock, name, bind_path):
         self.name = name
@@ -282,8 +282,8 @@ class PassiveStream(object):
     def open(name):
         """Attempts to start listening for remote stream connections.  'name'
         is a connection name in the form "TYPE:ARGS", where TYPE is an passive
-        stream class's name and ARGS are stream class-specific.  Currently the
-        only supported TYPE is "punix".
+        stream class's name and ARGS are stream class-specific. Currently the
+        supported values for TYPE are "punix" and "ptcp".
 
         Returns (error, pstream): on success 'error' is 0 and 'pstream' is the
         new PassiveStream, on failure 'error' is a positive errno value and
@@ -294,10 +294,20 @@ class PassiveStream(object):
         bind_path = name[6:]
         if name.startswith("punix:"):
             bind_path = ovs.util.abs_file_name(ovs.dirs.RUNDIR, bind_path)
-        error, sock = ovs.socket_util.make_unix_socket(socket.SOCK_STREAM,
-                                                       True, bind_path, None)
-        if error:
-            return error, None
+            error, sock = ovs.socket_util.make_unix_socket(socket.SOCK_STREAM,
+                                                           True, bind_path,
+                                                           None)
+            if error:
+                return error, None
+
+        elif name.startswith("ptcp:"):
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+            remote = name.split(':')
+            sock.bind((remote[1], int(remote[2])))
+
+        else:
+            raise Exception('Unknown connection string')
 
         try:
             sock.listen(10)
@@ -328,7 +338,10 @@ class PassiveStream(object):
             try:
                 sock, addr = self.socket.accept()
                 ovs.socket_util.set_nonblocking(sock)
-                return 0, Stream(sock, "unix:%s" % addr, 0)
+                if (sock.family == socket.AF_UNIX):
+                    return 0, Stream(sock, "unix:%s" % addr, 0)
+                return 0, Stream(sock, 'ptcp:%s:%s' % (addr[0],
+                                                       str(addr[1])), 0)
             except socket.error as e:
                 error = ovs.socket_util.get_exception_errno(e)
                 if error != errno.EAGAIN:
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index 33d508c..0a0be38 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -135,6 +135,35 @@ m4_define([OVSDB_CHECK_IDL],
    OVSDB_CHECK_IDL_TCP_PY($@)
    OVSDB_CHECK_IDL_TCP6_PY($@)])
 
+# This test uses the Python IDL implementation with passive tcp
+m4_define([OVSDB_CHECK_IDL_PASSIVE_TCP_PY],
+  [AT_SETUP([$1 - Python ptcp])
+   AT_SKIP_IF([test $HAVE_PYTHON = no])
+   AT_KEYWORDS([ovsdb server idl positive Python with tcp socket $5])
+   AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
+                  [0], [stdout], [ignore])
+   # find free TCP port
+   AT_CHECK([ovsdb-server --log-file '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
+   AT_CHECK([kill `cat pid`])
+
+   # start OVSDB server in passive mode
+   AT_CHECK([ovsdb-server --log-file '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --remote=tcp:127.0.0.1:$TCP_PORT --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   AT_CHECK([$PYTHON $srcdir/test-ovsdb.py -t10 idl_passive $srcdir/idltest.ovsschema ptcp:127.0.0.1:$TCP_PORT $3],
+      [0], [stdout], [ignore], [kill `cat pid`])
+   AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
+            [0], [$4], [], [kill `cat pid`])
+   AT_CLEANUP
+   ])
+
+OVSDB_CHECK_IDL_PASSIVE_TCP_PY([simple passive idl, initially empty, select empty],
+  [],
+  [['["idltest",{"op":"select","table":"link1","where":[]}]']],
+  [[000: empty
+001: {"error":null,"result":[{"rows":[]}]}
+002: done
+]])
+
 OVSDB_CHECK_IDL([simple idl, initially empty, no ops],
   [],
   [],
diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
index 4e87dbb..42d36d4 100644
--- a/tests/test-ovsdb.py
+++ b/tests/test-ovsdb.py
@@ -487,6 +487,51 @@ def do_idl(schema_file, remote, *commands):
     print("%03d: done" % step)
 
 
+def do_idl_passive(schema_file, remote, *commands):
+    symtab = {}
+    step = 0
+    schema_helper = ovs.db.idl.SchemaHelper(schema_file)
+    schema_helper.register_all()
+    idl = ovs.db.idl.Idl(remote, schema_helper)
+
+    while idl._session.rpc is None:
+        idl.run()
+
+    rpc = idl._session.rpc
+
+    print_idl(idl, step)
+    step += 1
+
+    for command in commands:
+        json = ovs.json.from_string(command)
+        if isinstance(json, six.string_types):
+            sys.stderr.write("\"%s\": %s\n" % (command, json))
+            sys.exit(1)
+        json = substitute_uuids(json, symtab)
+        request = ovs.jsonrpc.Message.create_request("transact", json)
+        error, reply = rpc.transact_block(request)
+        if error:
+            sys.stderr.write("jsonrpc transaction failed: %s"
+                             % os.strerror(error))
+            sys.exit(1)
+        elif reply.error is not None:
+            sys.stderr.write("jsonrpc transaction failed: %s"
+                             % reply.error)
+            sys.exit(1)
+
+        sys.stdout.write("%03d: " % step)
+        sys.stdout.flush()
+        step += 1
+        if reply.result is not None:
+            parse_uuids(reply.result, symtab)
+        reply.id = None
+        sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
+        sys.stdout.flush()
+
+    idl.close()
+    print("%03d: done" % step)
+
+
 def usage():
     print("""\
 %(program_name)s: test utility for Open vSwitch database Python bindings
@@ -587,7 +632,8 @@ def main(argv):
                 "parse-column": (do_parse_column, 2),
                 "parse-table": (do_parse_table, (2, 3)),
                 "parse-schema": (do_parse_schema, 1),
-                "idl": (do_idl, (2,))}
+                "idl": (do_idl, (2,)),
+                "idl_passive": (do_idl_passive, (2,))}
 
     command_name = args[0]
     args = args[1:]
-- 
2.1.4




More information about the dev mailing list