[ovs-dev] [PATCH] python: Add SSL support to the python ovs client library

2016-10-04 Thread nusiddiq
From: Numan Siddique 

SSL support is added to the ovs/stream.py. pyOpenSSL library is used
to support SSL. If this library is not present, then the SSL stream
is not registered with the Stream class.

Signed-off-by: Numan Siddique 
---
 python/ovs/poller.py |  8 +
 python/ovs/stream.py | 87 ++--
 tests/ovsdb-idl.at   | 30 --
 tests/test-ovsdb.py  |  7 +
 4 files changed, 127 insertions(+), 5 deletions(-)

diff --git a/python/ovs/poller.py b/python/ovs/poller.py
index de6bf22..d7cb7d3 100644
--- a/python/ovs/poller.py
+++ b/python/ovs/poller.py
@@ -20,6 +20,11 @@ import socket
 import os
 
 try:
+from OpenSSL import SSL
+except ImportError:
+SSL = None
+
+try:
 import eventlet.patcher
 
 def _using_eventlet_green_select():
@@ -54,6 +59,9 @@ class _SelectSelect(object):
 def register(self, fd, events):
 if isinstance(fd, socket.socket):
 fd = fd.fileno()
+if SSL and isinstance(fd, SSL.Connection):
+fd = fd.fileno()
+
 assert isinstance(fd, int)
 if events & POLLIN:
 self.rlist.append(fd)
diff --git a/python/ovs/stream.py b/python/ovs/stream.py
index 97b22ac..bb813a6 100644
--- a/python/ovs/stream.py
+++ b/python/ovs/stream.py
@@ -22,6 +22,11 @@ import ovs.poller
 import ovs.socket_util
 import ovs.vlog
 
+try:
+from OpenSSL import SSL
+except ImportError:
+SSL = None
+
 vlog = ovs.vlog.Vlog("stream")
 
 
@@ -39,7 +44,7 @@ def stream_or_pstream_needs_probes(name):
 
 
 class Stream(object):
-"""Bidirectional byte stream.  Currently only Unix domain sockets
+"""Bidirectional byte stream.  Unix domain sockets, tcp and ssl
 are implemented."""
 
 # States.
@@ -54,6 +59,10 @@ class Stream(object):
 
 _SOCKET_METHODS = {}
 
+_SSL_private_key_file = None
+_SSL_certificate_file = None
+_SSL_ca_cert_file = None
+
 @staticmethod
 def register_method(method, cls):
 Stream._SOCKET_METHODS[method + ":"] = cls
@@ -68,7 +77,7 @@ class Stream(object):
 @staticmethod
 def is_valid_name(name):
 """Returns True if 'name' is a stream name in the form "TYPE:ARGS" and
-TYPE is a supported stream type (currently only "unix:" and "tcp:"),
+TYPE is a supported stream type ("unix:", "tcp:" and "ssl:"),
 otherwise False."""
 return bool(Stream._find_method(name))
 
@@ -116,7 +125,7 @@ class Stream(object):
 return error, None
 else:
 status = ovs.socket_util.check_connection_completion(sock)
-return 0, Stream(sock, name, status)
+return 0, cls(sock, name, status)
 
 @staticmethod
 def _open(suffix, dscp):
@@ -264,6 +273,18 @@ class Stream(object):
 # Don't delete the file: we might have forked.
 self.socket.close()
 
+@staticmethod
+def ssl_set_private_key_file(file_name):
+Stream._SSL_private_key_file = file_name
+
+@staticmethod
+def ssl_set_certificate_file(file_name):
+Stream._SSL_certificate_file = file_name
+
+@staticmethod
+def ssl_set_ca_cert_file(file_name):
+Stream._SSL_ca_cert_file = file_name
+
 
 class PassiveStream(object):
 @staticmethod
@@ -362,6 +383,7 @@ def usage(name):
 Active %s connection methods:
   unix:FILE   Unix domain socket named FILE
   tcp:IP:PORT TCP socket to IP with port no of PORT
+  ssl:IP:PORT SSL socket to IP with port no of PORT
 
 Passive %s connection methods:
   punix:FILE  Listen on Unix domain socket FILE""" % (name, name)
@@ -385,3 +407,62 @@ class TCPStream(Stream):
 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
 return error, sock
 Stream.register_method("tcp", TCPStream)
+
+
+class SSLStream(Stream):
+
+@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
+
+# 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.set_session_cache_mode(SSL.SESS_CACHE_OFF)
+# 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)
+
+ssl_sock = SSL.Connection(ctx, sock)
+ssl_sock.set_connect_state()
+return error, ssl_sock
+
+def connect(self):
+retval = super(SSLStream, self).connect()
+
+if retval:
+return retval
+
+# TCP Connection is successful. Now do the SSL handshake
+try:
+self.

[ovs-dev] [PATCH v3 4/4] ovn: Add tests for ovn dhcp

2015-11-20 Thread nusiddiq
Signed-off-by: Numan Siddique 
---
 tests/automake.mk |   1 +
 tests/ovn.at  | 184 +++
 tests/test-ovn-dhcp.c | 211 ++
 3 files changed, 396 insertions(+)
 create mode 100644 tests/test-ovn-dhcp.c

diff --git a/tests/automake.mk b/tests/automake.mk
index 5267be1..9c19b1e 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -305,6 +305,7 @@ tests_ovstest_SOURCES = \
tests/test-odp.c \
tests/test-ofpbuf.c \
tests/test-ovn.c \
+   tests/test-ovn-dhcp.c \
tests/test-packets.c \
tests/test-random.c \
tests/test-reconnect.c \
diff --git a/tests/ovn.at b/tests/ovn.at
index 68fcc9a..34b9913 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1104,3 +1104,187 @@ for i in 1 2 3; do
 done
 done
 AT_CLEANUP
+
+AT_SETUP([ovn dhcp -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+ovn_start
+
+# Logical network:
+#
+# Three logical switches ls1, ls2, ls3.
+# One logical router lr0 connected to ls[123],
+# with nine subnets, three per logical switch:
+#
+#lrp11 on ls1 for subnet 192.168.11.0/24
+#lrp12 on ls1 for subnet 192.168.12.0/24
+#lrp13 on ls1 for subnet 192.168.13.0/24
+#...
+#lrp33 on ls3 for subnet 192.168.33.0/24
+#
+# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
+# digits are the subnet and the last digit distinguishes the VIF.
+for i in 1 2 3; do
+ovn-nbctl lswitch-add ls$i
+for j in 1 2 3; do
+for k in 1 2 3; do
+ovn-nbctl \
+-- lport-add ls$i lp$i$j$k \
+-- lport-set-addresses lp$i$j$k "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
+done
+done
+done
+
+# Physical network:
+#
+# Three hypervisors hv[123].
+# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
+# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
+# lp?3[123] all on hv3.
+
+
+# Given the name of a logical port, prints the name of the hypervisor
+# on which it is located.
+vif_to_hv() {
+case $1 in dnl (
+?11) echo 1 ;; dnl (
+?12 | ?21 | ?22) echo 2 ;; dnl (
+?13 | ?23 | ?3?) echo 3 ;;
+esac
+}
+
+# Given the name of a logical port, prints the name of its logical router
+# port, e.g. "vif_to_lrp 123" yields 12.
+vif_to_lrp() {
+echo ${1%?}
+}
+
+# Given the name of a logical port, prints the name of its logical
+# switch, e.g. "vif_to_ls 123" yields 1.
+vif_to_ls() {
+echo ${1%??}
+}
+
+net_add n1
+for i in 1 2 3; do
+sim_add hv$i
+as hv$i
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.$i
+done
+for i in 1 2 3; do
+for j in 1 2 3; do
+for k in 1 2 3; do
+hv=`vif_to_hv $i$j$k`
+as hv$hv ovs-vsctl \
+-- add-port br-int vif$i$j$k \
+-- set Interface vif$i$j$k \
+   external-ids:iface-id=lp$i$j$k \
+   options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
+   options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
+   ofport-request=$i$j$k
+done
+done
+done
+
+# Pre-populate the hypervisors' ARP tables so that we don't lose any
+# packets for ARP resolution (native tunneling doesn't queue packets
+# for ARP resolution).
+ovn_populate_arp
+
+# Allow some time for ovn-northd and ovn-controller to catch up.
+# XXX This should be more systematic.
+sleep 1
+
+send_dhcp_packet() {
+local inport=$1 src_mac=$2 dhcp_type=$3
+local 
request=${src_mac}0800451001108011
+# udp header and dhcp header
+request+=0044004300FC
+request+=010106006359aa76${src_mac}
+# client hardware padding
+request+=
+# server hostname
+request+=
+request+=
+# boot file name
+request+=
+request+=
+request+=
+request+=
+# dhcp magic cookie
+request+=63825363
+# dhcp message type
+request+=3501${dhcp_type}ff
+shift; shift; shift; shift; shift
+hv=`vif_to_hv $inport`
+as hv$hv ovs-appctl netdev-dummy/receive vif$inport $request
+}
+
+ip_to_hex() {
+printf "%02x%02x%02x%02x" "$@"
+}
+
+run_dhcp_test() {
+local i=$1 j=$2 k=$3 set_option=$4 dhcp_type=$5
+netmask=255.255.255.0
+gw_ip=0.0.0.0
+if $set_option = 'true'; then
+netmask=255.255.252.0
+gw_ip=192.168.$i$j.254
+ovn-nbctl \
+-- lport-set-options lp$i$j$k \
+"dhcp-opt-1=$netmask" "dhcp-opt-3=$gw_ip"
+sleep 1
+fi
+
+echo $gw_ip
+  

[ovs-dev] [PATCH v4 4/4] ovn: Add tests for ovn dhcp

2015-11-24 Thread nusiddiq
Signed-off-by: Numan Siddique 
---
 tests/automake.mk |   1 +
 tests/ovn.at  | 184 
 tests/test-ovn-dhcp.c | 228 ++
 3 files changed, 413 insertions(+)
 create mode 100644 tests/test-ovn-dhcp.c

diff --git a/tests/automake.mk b/tests/automake.mk
index 5267be1..9c19b1e 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -305,6 +305,7 @@ tests_ovstest_SOURCES = \
tests/test-odp.c \
tests/test-ofpbuf.c \
tests/test-ovn.c \
+   tests/test-ovn-dhcp.c \
tests/test-packets.c \
tests/test-random.c \
tests/test-reconnect.c \
diff --git a/tests/ovn.at b/tests/ovn.at
index 68fcc9a..34b9913 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1104,3 +1104,187 @@ for i in 1 2 3; do
 done
 done
 AT_CLEANUP
+
+AT_SETUP([ovn dhcp -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+ovn_start
+
+# Logical network:
+#
+# Three logical switches ls1, ls2, ls3.
+# One logical router lr0 connected to ls[123],
+# with nine subnets, three per logical switch:
+#
+#lrp11 on ls1 for subnet 192.168.11.0/24
+#lrp12 on ls1 for subnet 192.168.12.0/24
+#lrp13 on ls1 for subnet 192.168.13.0/24
+#...
+#lrp33 on ls3 for subnet 192.168.33.0/24
+#
+# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
+# digits are the subnet and the last digit distinguishes the VIF.
+for i in 1 2 3; do
+ovn-nbctl lswitch-add ls$i
+for j in 1 2 3; do
+for k in 1 2 3; do
+ovn-nbctl \
+-- lport-add ls$i lp$i$j$k \
+-- lport-set-addresses lp$i$j$k "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
+done
+done
+done
+
+# Physical network:
+#
+# Three hypervisors hv[123].
+# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
+# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
+# lp?3[123] all on hv3.
+
+
+# Given the name of a logical port, prints the name of the hypervisor
+# on which it is located.
+vif_to_hv() {
+case $1 in dnl (
+?11) echo 1 ;; dnl (
+?12 | ?21 | ?22) echo 2 ;; dnl (
+?13 | ?23 | ?3?) echo 3 ;;
+esac
+}
+
+# Given the name of a logical port, prints the name of its logical router
+# port, e.g. "vif_to_lrp 123" yields 12.
+vif_to_lrp() {
+echo ${1%?}
+}
+
+# Given the name of a logical port, prints the name of its logical
+# switch, e.g. "vif_to_ls 123" yields 1.
+vif_to_ls() {
+echo ${1%??}
+}
+
+net_add n1
+for i in 1 2 3; do
+sim_add hv$i
+as hv$i
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.$i
+done
+for i in 1 2 3; do
+for j in 1 2 3; do
+for k in 1 2 3; do
+hv=`vif_to_hv $i$j$k`
+as hv$hv ovs-vsctl \
+-- add-port br-int vif$i$j$k \
+-- set Interface vif$i$j$k \
+   external-ids:iface-id=lp$i$j$k \
+   options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
+   options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
+   ofport-request=$i$j$k
+done
+done
+done
+
+# Pre-populate the hypervisors' ARP tables so that we don't lose any
+# packets for ARP resolution (native tunneling doesn't queue packets
+# for ARP resolution).
+ovn_populate_arp
+
+# Allow some time for ovn-northd and ovn-controller to catch up.
+# XXX This should be more systematic.
+sleep 1
+
+send_dhcp_packet() {
+local inport=$1 src_mac=$2 dhcp_type=$3
+local 
request=${src_mac}0800451001108011
+# udp header and dhcp header
+request+=0044004300FC
+request+=010106006359aa76${src_mac}
+# client hardware padding
+request+=
+# server hostname
+request+=
+request+=
+# boot file name
+request+=
+request+=
+request+=
+request+=
+# dhcp magic cookie
+request+=63825363
+# dhcp message type
+request+=3501${dhcp_type}ff
+shift; shift; shift; shift; shift
+hv=`vif_to_hv $inport`
+as hv$hv ovs-appctl netdev-dummy/receive vif$inport $request
+}
+
+ip_to_hex() {
+printf "%02x%02x%02x%02x" "$@"
+}
+
+run_dhcp_test() {
+local i=$1 j=$2 k=$3 set_option=$4 dhcp_type=$5
+netmask=255.255.255.0
+gw_ip=0.0.0.0
+if $set_option = 'true'; then
+netmask=255.255.252.0
+gw_ip=192.168.$i$j.254
+ovn-nbctl \
+-- lport-set-options lp$i$j$k \
+"dhcp-opt-1=$netmask" "dhcp-opt-3=$gw_ip"
+sleep 1
+fi
+
+echo $gw_ip
+e