[ovs-dev] Subject: [PATCH] ovs-monitor-ipsec: ipsec_vxlan support and IPsec tunnel mode options support.

Muthukrishnan Thangasamy muthukrishnan.t at tataelxsi.co.in
Thu Sep 29 07:13:55 UTC 2016


>From 76e504a38a3c556884782323459cc6862a38747c Mon Sep 17 00:00:00 2001
From: Muthukrishnan T <muthukrishnan.t at tataelxsi.co.in>
Date: Thu, 29 Sep 2016 12:21:29 +0530
Subject: [PATCH] ovs-monitor-ipsec: ipsec_vxlan support and IPsec tunnel mode options support.


Description :
OpenvSwitch doesn’t have support for IPSec Tunnel interface ‘ipsec_vxlan’ for VxLAN traffic. It supports only IPSec Transport mode for IPSec tunnel interfaces (i.e.) GRE/VxLAN, doesn’t have options for IPSec Tunnel mode of operation , this patch addresses the same.

Signed-off-by: Muthukrishnan T <muthukrishnan.t at tataelxsi.co.in>
---
 NEWS                         |   3 +
 debian/ovs-monitor-ipsec     | 140 +++++++++----
 lib/dpif-netlink.c           |   2 +-
 lib/netdev-vport.c           |  39 +++-
 ofproto/ofproto-dpif-ipfix.c |   5 +
 tests/ovs-monitor-ipsec.at   | 483 +++++++++++++++++++++++++++++++++++++++++--
 vswitchd/vswitch.xml         |   6 +
 7 files changed, 615 insertions(+), 63 deletions(-)

diff --git a/NEWS b/NEWS
index bb32c47..95c7e99 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,9 @@ Post-v2.6.0
      * TLV mappings for protocols such as Geneve are now segregated on
        a per-OpenFlow bridge basis rather than globally. (The interface
        has not changed.)
+   - The ovs-monitor-ipsec daemon provides support for encrypting VxLAN Traffic.
+   - New option 'mode=tunnel/transport' added for the interface
+     ipsec_gre and ipsec_vxlan.

 v2.6.0 - xx xxx xxxx
 ---------------------
diff --git a/debian/ovs-monitor-ipsec b/debian/ovs-monitor-ipsec
index 6bc26aa..a716201 100755
--- a/debian/ovs-monitor-ipsec
+++ b/debian/ovs-monitor-ipsec
@@ -14,7 +14,7 @@
 # limitations under the License.


-# A daemon to monitor attempts to create GRE-over-IPsec tunnels.
+# A daemon to monitor attempts to create GRE-over-IPsec and VxLAN-over-IPsec tunnels.
 # Uses racoon and setkey to support the configuration.  Assumes that
 # OVS has complete control over IPsec configuration for the box.

@@ -30,6 +30,7 @@ import glob
 import os
 import subprocess
 import sys
+import socket

 import ovs.dirs
 from ovs.db import error
@@ -48,6 +49,11 @@ SETKEY = "/usr/sbin/setkey"
 IP = "/sbin/ip"
 exiting = False
 IPSEC_MARK = "1"
+# UDP ports used for VXLAN.  The source port is only fixed for
+# VXLAN-over-IPsec traffic.
+
+VXLAN_SRC_PORT = "any"
+VXLAN_DST_PORT = "4789"


 def unixctl_exit(conn, unused_argv, unused_aux):
@@ -266,7 +272,7 @@ class IPsec(object):
         self.sad_flush()
         self.spd_flush()
         self.racoon = Racoon()
-        self.entries = []
+        self.entries = {}

     def call_setkey(self, cmds):
         try:
@@ -335,35 +341,71 @@ class IPsec(object):
                            "mark", IPSEC_MARK, "mask", IPSEC_MARK,
                            "action", "block", "priority", "4294967295"])

-    def spd_add(self, local_ip, remote_ip):
-        cmds = ("spdadd %s %s gre -P out ipsec esp/transport//require;\n" %
-                    (local_ip, remote_ip))
-        cmds += ("spdadd %s %s gre -P in ipsec esp/transport//require;\n" %
-                    (remote_ip, local_ip))
-        self.call_setkey(cmds)
+    def spd_add(self, local_ip, remote_ip, tunnel_mode):
+        tunnel_type = self.entries[remote_ip]
+        cmds = ""
+        if tunnel_type == "vxlan" and tunnel_mode == "tunnel":
+            cmds = ("spdadd %s[%s] %s udp -P out ipsec esp/tunnel/%s-%s/require;\n"
+                        % (local_ip, VXLAN_SRC_PORT, remote_ip, local_ip, remote_ip))
+            cmds += ("spdadd %s %s[%s] udp -P in ipsec esp/tunnel/%s-%s/require;\n"
+                        % (remote_ip, local_ip, VXLAN_SRC_PORT, remote_ip, local_ip))
+        elif tunnel_type == "vxlan" and tunnel_mode == "transport":
+            cmds = ("spdadd %s[%s] %s udp -P out ipsec esp/transport//require;\n"
+                        % (local_ip, VXLAN_SRC_PORT, remote_ip))
+            cmds += ("spdadd %s %s[%s] udp -P in ipsec esp/transport//require;\n"
+                        % (remote_ip, local_ip, VXLAN_SRC_PORT))
+        elif tunnel_type == "gre" and tunnel_mode == "tunnel":
+            cmds = ("spdadd %s %s gre -P out ipsec esp/tunnel/%s-%s/require;\n"
+                        % (local_ip,  remote_ip, local_ip, remote_ip))
+            cmds += ("spdadd %s %s gre -P in ipsec esp/tunnel/%s-%s/require;\n"
+                        % (remote_ip, local_ip, remote_ip, local_ip))
+        elif tunnel_type == "gre" and tunnel_mode == "transport":
+            cmds = ("spdadd %s %s gre -P out ipsec esp/transport//require;\n" %
+                        (local_ip, remote_ip))
+            cmds += ("spdadd %s %s gre -P in ipsec esp/transport//require;\n" %
+                        (remote_ip, local_ip))
+    else:
+            vlog.err("Unsupported IPsec Mode %s Received" % tunnel_mode)
+        if cmds:
+            vlog.info("IPsec Policy: %s" % cmds)
+            self.call_setkey(cmds)

     def spd_del(self, local_ip, remote_ip):
-        cmds = "spddelete %s %s gre -P out;\n" % (local_ip, remote_ip)
-        cmds += "spddelete %s %s gre -P in;\n" % (remote_ip, local_ip)
-        self.call_setkey(cmds)
+        tunnel_type = self.entries[remote_ip]
+        cmds= ""
+        if tunnel_type == "vxlan":
+            cmds = ("spddelete %s %s udp -P out;\n" % (local_ip, remote_ip))
+            cmds += ("spddelete %s %s udp -P in;\n" % (remote_ip, local_ip))
+        else:
+            cmds = "spddelete %s %s gre -P out;\n" % (local_ip, remote_ip)
+            cmds += "spddelete %s %s gre -P in;\n" % (remote_ip, local_ip)
+        if cmds:
+            vlog.info(" Command:%s" % cmds)
+            self.call_setkey(cmds)

     def add_entry(self, local_ip, remote_ip, vals):
+        tunnel_type = vals["tunnel_type"]
+        tunnel_mode = vals["tunnel_mode"]
+        vlog.warn("Tunnel type in add_entry %s" % tunnel_type)
+        if tunnel_type not in ("gre", "vxlan"):
+            raise error.Error("unknown tunnel type: %s" % tunnel_type)
+
         if remote_ip in self.entries:
             raise error.Error("host %s already configured for ipsec"
                               % remote_ip)

         self.racoon.add_entry(remote_ip, vals)
-        self.spd_add(local_ip, remote_ip)
-
-        self.entries.append(remote_ip)
+        self.entries[remote_ip] = tunnel_type
+        self.spd_add(local_ip, remote_ip, tunnel_mode)

     def del_entry(self, local_ip, remote_ip):
         if remote_ip in self.entries:
             self.racoon.del_entry(remote_ip)
             self.spd_del(local_ip, remote_ip)
             self.sad_del(local_ip, remote_ip)
+
+            del self.entries[remote_ip]

-            self.entries.remove(remote_ip)


 def update_ipsec(ipsec, interfaces, new_interfaces):
@@ -398,6 +440,10 @@ def get_ssl_cert(data):

     return None

+def get_local_ip():
+    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    s.connect(("8.8.8.8", 80))
+    return s.getsockname()[0]

 def main():

@@ -453,40 +499,50 @@ def main():
         ssl_cert = get_ssl_cert(idl.tables)

         new_interfaces = {}
+        loc_ip = get_local_ip()
         for rec in six.itervalues(idl.tables["Interface"].rows):
             if rec.type == "ipsec_gre":
-                name = rec.name
-                options = rec.options
-                peer_cert_name = "ovs-%s.pem" % (options.get("remote_ip"))
-                entry = {
-                    "remote_ip": options.get("remote_ip"),
-                    "local_ip": options.get("local_ip", "0.0.0.0/0"),
-                    "certificate": options.get("certificate"),
-                    "private_key": options.get("private_key"),
-                    "use_ssl_cert": options.get("use_ssl_cert"),
-                    "peer_cert": options.get("peer_cert"),
-                    "peer_cert_file": Racoon.cert_dir + "/" + peer_cert_name,
-                    "psk": options.get("psk")}
-
-                if entry["peer_cert"] and entry["psk"]:
-                    vlog.warn("both 'peer_cert' and 'psk' defined for %s"
-                              % name)
-                    continue
-                elif not entry["peer_cert"] and not entry["psk"]:
-                    vlog.warn("no 'peer_cert' or 'psk' defined for %s" % name)
-                    continue
+                tunnel_type = "gre"
+            elif rec.type == "ipsec_vxlan":
+                tunnel_type = "vxlan"
+            else:
+                continue

+            name = rec.name
+            options = rec.options
+            peer_cert_name = "ovs-%s.pem" % (options.get("remote_ip"))
+            vlog.info("local ip received from def:get_local_ip %s" % loc_ip)
+            entry = {
+                "remote_ip": options.get("remote_ip"),
+                "local_ip": options.get("local_ip", loc_ip),
+                "certificate": options.get("certificate"),
+                "private_key": options.get("private_key"),
+                "use_ssl_cert": options.get("use_ssl_cert"),
+                "peer_cert": options.get("peer_cert"),
+                "psk": options.get("psk"),
+                "tunnel_mode": options.get("mode","transport"),
+                "peer_cert_file": Racoon.cert_dir + "/" + peer_cert_name,
+                "tunnel_type": tunnel_type }
+
+            vlog.info("IPsec mode received %s" % entry["tunnel_mode"])
+            if entry["peer_cert"] and entry["psk"]:
+                vlog.warn("both 'peer_cert' and 'psk' defined for %s"
+                        % name)
+                continue
                 # The "use_ssl_cert" option is deprecated and will
                 # likely go away in the near future.
-                if entry["use_ssl_cert"] == "true":
-                    if not ssl_cert:
-                        vlog.warn("no valid SSL entry for %s" % name)
-                        continue
+            # The "use_ssl_cert" option is deprecated and will
+            # likely go away in the near future.
+            if entry["use_ssl_cert"] == "true":
+                if not ssl_cert:
+                    vlog.warn("no valid SSL entry for %s" % name)
+                    continue
+
+                entry["certificate"] = ssl_cert[0]
+                entry["private_key"] = ssl_cert[1]

-                    entry["certificate"] = ssl_cert[0]
-                    entry["private_key"] = ssl_cert[1]

-                new_interfaces[name] = entry
+            new_interfaces[name] = entry

         if interfaces != new_interfaces:
             update_ipsec(ipsec, interfaces, new_interfaces)
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index a39faa2..67cf6e8 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -794,7 +794,7 @@ netdev_to_ovs_vport_type(const struct netdev *netdev)
         return OVS_VPORT_TYPE_GENEVE;
     } else if (strstr(type, "gre")) {
         return OVS_VPORT_TYPE_GRE;
-    } else if (!strcmp(type, "vxlan")) {
+    } else if (strstr(type, "vxlan")) {
         return OVS_VPORT_TYPE_VXLAN;
     } else if (!strcmp(type, "lisp")) {
         return OVS_VPORT_TYPE_LISP;
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 8d22cf5..f343cb4 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -108,7 +108,7 @@ netdev_vport_needs_dst_port(const struct netdev *dev)
     const char *type = netdev_get_type(dev);

     return (class->get_config == get_tunnel_config &&
-            (!strcmp("geneve", type) || !strcmp("vxlan", type) ||
+            (!strcmp("geneve", type) || strstr("vxlan", type) ||
              !strcmp("lisp", type) || !strcmp("stt", type)) );
 }

@@ -195,7 +195,7 @@ netdev_vport_construct(struct netdev *netdev_)
     /* Add a default destination port for tunnel ports if none specified. */
     if (!strcmp(type, "geneve")) {
         dev->tnl_cfg.dst_port = htons(GENEVE_DST_PORT);
-    } else if (!strcmp(type, "vxlan")) {
+    } else if (strstr(type, "vxlan")) {
         dev->tnl_cfg.dst_port = htons(VXLAN_DST_PORT);
     } else if (!strcmp(type, "lisp")) {
         dev->tnl_cfg.dst_port = htons(LISP_DST_PORT);
@@ -335,7 +335,6 @@ netdev_vport_wait(const struct netdev_class *netdev_class OVS_UNUSED)
         poll_immediate_wake();
     }
 }
-
 /* Code specific to tunnel types. */

 static ovs_be64
@@ -402,7 +401,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
     struct netdev_vport *dev = netdev_vport_cast(dev_);
     const char *name = netdev_get_name(dev_);
     const char *type = netdev_get_type(dev_);
-    bool ipsec_mech_set, needs_dst_port, has_csum;
+    bool ipsec_mech_set, needs_dst_port, has_csum , ipsec_mode_set;
     uint16_t dst_proto = 0, src_proto = 0;
     struct netdev_tunnel_config tnl_cfg;
     struct smap_node *node;
@@ -410,6 +409,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
     has_csum = strstr(type, "gre") || strstr(type, "geneve") ||
                strstr(type, "stt") || strstr(type, "vxlan");
     ipsec_mech_set = false;
+    ipsec_mode_set = false;
     memset(&tnl_cfg, 0, sizeof tnl_cfg);

     /* Add a default destination port for tunnel ports if none specified. */
@@ -417,7 +417,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
         tnl_cfg.dst_port = htons(GENEVE_DST_PORT);
     }

-    if (!strcmp(type, "vxlan")) {
+    if (strstr(type, "vxlan")) {
         tnl_cfg.dst_port = htons(VXLAN_DST_PORT);
     }

@@ -429,8 +429,12 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
         tnl_cfg.dst_port = htons(STT_DST_PORT);
     }

+    if ((strstr(type, "ipsec"))) {
+    tnl_cfg.ipsec = true;
+    ipsec_mode_set = true;
+    }
+
     needs_dst_port = netdev_vport_needs_dst_port(dev_);
-    tnl_cfg.ipsec = strstr(type, "ipsec");
     tnl_cfg.dont_fragment = true;

     SMAP_FOR_EACH (node, args) {
@@ -507,6 +511,11 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
             }
         } else if (!strcmp(node->key, "psk") && tnl_cfg.ipsec) {
             ipsec_mech_set = true;
+        } else if (!strcmp(node->key, "mode") && tnl_cfg.ipsec) {
+            if ((strcmp(node->value, "tunnel")) && (strcmp(node->value, "transport"))) {
+                ipsec_mode_set = false;
+                VLOG_WARN("IPsec mode received: '%s'",node->value);
+            }
         } else if (tnl_cfg.ipsec
                 && (!strcmp(node->key, "certificate")
                     || !strcmp(node->key, "private_key")
@@ -535,7 +544,13 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)

             free(str);
         } else {
-            VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->key);
+            if ((!strcmp(node->key, "psk")) || (!strcmp(node->key, "mode"))) {
+                VLOG_ERR("%s: IPsec argument '%s' not supported for interface type '%s'",
+                             name,node->key,type);
+                return EINVAL;
+            } else {
+                VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->key);
+            }
         }
     }

@@ -570,6 +585,11 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
                      name);
             return EINVAL;
         }
+        if (!ipsec_mode_set) {
+            VLOG_ERR("%s: IPsec mode requires an 'tunnel' or 'transport' argument",
+                     name);
+            return EINVAL;
+        }
     }

     if (!ipv6_addr_is_set(&tnl_cfg.ipv6_dst) && !tnl_cfg.ip_dst_flow) {
@@ -670,7 +690,7 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
         const char *type = netdev_get_type(dev);

         if ((!strcmp("geneve", type) && dst_port != GENEVE_DST_PORT) ||
-            (!strcmp("vxlan", type) && dst_port != VXLAN_DST_PORT) ||
+            (strstr("vxlan", type) && dst_port != VXLAN_DST_PORT) ||
             (!strcmp("lisp", type) && dst_port != LISP_DST_PORT) ||
             (!strcmp("stt", type) && dst_port != STT_DST_PORT)) {
             smap_add_format(args, "dst_port", "%d", dst_port);
@@ -900,6 +920,9 @@ netdev_vport_tunnel_register(void)
         TUNNEL_CLASS("vxlan", "vxlan_sys", netdev_vxlan_build_header,
                                            netdev_tnl_push_udp_header,
                                            netdev_vxlan_pop_header),
+        TUNNEL_CLASS("ipsec_vxlan", "vxlan_sys", netdev_vxlan_build_header,
+                                           netdev_tnl_push_udp_header,
+                                           netdev_vxlan_pop_header),
         TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL),
         TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL),
     };
diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
index abea492..aef3c1a 100644
--- a/ofproto/ofproto-dpif-ipfix.c
+++ b/ofproto/ofproto-dpif-ipfix.c
@@ -80,6 +80,7 @@ enum dpif_ipfix_tunnel_type {
     DPIF_IPFIX_TUNNEL_STT = 0x04,
     DPIF_IPFIX_TUNNEL_IPSEC_GRE = 0x05,
     DPIF_IPFIX_TUNNEL_GENEVE = 0x07,
+    DPIF_IPFIX_TUNNEL_IPSEC_VXLAN = 0x08,
     NUM_DPIF_IPFIX_TUNNEL
 };

@@ -323,6 +324,7 @@ static uint8_t tunnel_protocol[NUM_DPIF_IPFIX_TUNNEL] = {
     IPPROTO_GRE,    /* DPIF_IPFIX_TUNNEL_IPSEC_GRE */
     0          ,    /* reserved */
     IPPROTO_UDP,    /* DPIF_IPFIX_TUNNEL_GENEVE*/
+    IPPROTO_UDP,    /* DPIF_IPFIX_TUNNEL_IPSEC_VXLAN*/
 };

 OVS_PACKED(
@@ -664,6 +666,9 @@ dpif_ipfix_add_tunnel_port(struct dpif_ipfix *di, struct ofport *ofport,
     } else if (strcmp(type, "vxlan") == 0) {
         dip->tunnel_type = DPIF_IPFIX_TUNNEL_VXLAN;
         dip->tunnel_key_length = 3;
+    } else if (strcmp(type, "ipsec_vxlan") == 0) {
+        dip->tunnel_type = DPIF_IPFIX_TUNNEL_IPSEC_VXLAN;
+        dip->tunnel_key_length = 3;
     } else if (strcmp(type, "lisp") == 0) {
         dip->tunnel_type = DPIF_IPFIX_TUNNEL_LISP;
         dip->tunnel_key_length = 3;
diff --git a/tests/ovs-monitor-ipsec.at b/tests/ovs-monitor-ipsec.at
index cae2878..e2427f2 100644
--- a/tests/ovs-monitor-ipsec.at
+++ b/tests/ovs-monitor-ipsec.at
@@ -18,6 +18,7 @@ OVS_MONITOR_IPSEC_START
 AT_CHECK([ovs-vsctl \
               -- add-port br0 gre0 \
               -- set interface gre0 type=ipsec_gre \
+                                    options:local_ip=0.0.0.0 \
                                     options:remote_ip=1.2.3.4 \
                                     options:psk=swordfish])
 OVS_WAIT_UNTIL([test -f actions && grep 'spdadd 1.2.3.4' actions >/dev/null])
@@ -29,8 +30,8 @@ setkey:
 racoon: reload
 racoon: reload
 setkey:
-> spdadd 0.0.0.0/0 1.2.3.4 gre -P out ipsec esp/transport//require;
-> spdadd 1.2.3.4 0.0.0.0/0 gre -P in ipsec esp/transport//require;
+> spdadd 0.0.0.0 1.2.3.4 gre -P out ipsec esp/transport//require;
+> spdadd 1.2.3.4 0.0.0.0 gre -P in ipsec esp/transport//require;
 ])
 AT_CHECK([trim etc/racoon/psk.txt], [0], [1.2.3.4   swordfish
 ])
@@ -64,8 +65,8 @@ OVS_WAIT_UNTIL([test `wc -l < actions` -ge 17])
 AT_CHECK([sed '1,9d' actions], [0], [dnl
 racoon: reload
 setkey:
-> spddelete 0.0.0.0/0 1.2.3.4 gre -P out;
-> spddelete 1.2.3.4 0.0.0.0/0 gre -P in;
+> spddelete 0.0.0.0 1.2.3.4 gre -P out;
+> spddelete 1.2.3.4 0.0.0.0 gre -P in;
 setkey:
 > dump ;
 setkey:
@@ -100,6 +101,7 @@ AT_DATA([key.pem], [dnl
 AT_CHECK([ovs-vsctl \
               -- add-port br0 gre1 \
               -- set Interface gre1 type=ipsec_gre \
+                 options:local_ip=0.0.0.0 \
                  options:remote_ip=2.3.4.5 \
                  options:peer_cert='"-----BEGIN CERTIFICATE-----
 (not a real peer certificate)
@@ -111,8 +113,8 @@ OVS_WAIT_UNTIL([test `wc -l < actions` -ge 21])
 AT_CHECK([sed '1,17d' actions], [0], [dnl
 racoon: reload
 setkey:
-> spdadd 0.0.0.0/0 2.3.4.5 gre -P out ipsec esp/transport//require;
-> spdadd 2.3.4.5 0.0.0.0/0 gre -P in ipsec esp/transport//require;
+> spdadd 0.0.0.0 2.3.4.5 gre -P out ipsec esp/transport//require;
+> spdadd 2.3.4.5 0.0.0.0 gre -P in ipsec esp/transport//require;
 ])
 AT_CHECK([trim etc/racoon/psk.txt], [0], [])
 AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
@@ -156,8 +158,8 @@ OVS_WAIT_UNTIL([test `wc -l < actions` -ge 29])
 AT_CHECK([sed '1,21d' actions], [0], [dnl
 racoon: reload
 setkey:
-> spddelete 0.0.0.0/0 2.3.4.5 gre -P out;
-> spddelete 2.3.4.5 0.0.0.0/0 gre -P in;
+> spddelete 0.0.0.0 2.3.4.5 gre -P out;
+> spddelete 2.3.4.5 0.0.0.0 gre -P in;
 setkey:
 > dump ;
 setkey:
@@ -190,6 +192,7 @@ AT_DATA([ssl-cacert.pem], [dnl
 AT_CHECK([ovs-vsctl set-ssl /ssl-key.pem /ssl-cert.pem /ssl-cacert.pem \
               -- add-port br0 gre2 \
               -- set Interface gre2 type=ipsec_gre \
+                 options:local_ip=0.0.0.0 \
                  options:remote_ip=3.4.5.6 \
                  options:peer_cert='"-----BEGIN CERTIFICATE-----
 (not a real peer certificate)
@@ -200,8 +203,8 @@ OVS_WAIT_UNTIL([test `wc -l < actions` -ge 33])
 AT_CHECK([sed '1,29d' actions], [0], [dnl
 racoon: reload
 setkey:
-> spdadd 0.0.0.0/0 3.4.5.6 gre -P out ipsec esp/transport//require;
-> spdadd 3.4.5.6 0.0.0.0/0 gre -P in ipsec esp/transport//require;
+> spdadd 0.0.0.0 3.4.5.6 gre -P out ipsec esp/transport//require;
+> spdadd 3.4.5.6 0.0.0.0 gre -P in ipsec esp/transport//require;
 ])
 AT_CHECK([trim etc/racoon/psk.txt], [0], [])
 AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
@@ -245,8 +248,464 @@ OVS_WAIT_UNTIL([test `wc -l < actions` -ge 41])
 AT_CHECK([sed '1,33d' actions], [0], [dnl
 racoon: reload
 setkey:
-> spddelete 0.0.0.0/0 3.4.5.6 gre -P out;
-> spddelete 3.4.5.6 0.0.0.0/0 gre -P in;
+> spddelete 0.0.0.0 3.4.5.6 gre -P out;
+> spddelete 3.4.5.6 0.0.0.0 gre -P in;
+setkey:
+> dump ;
+setkey:
+> dump ;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+AT_CHECK([test ! -f etc/racoon/certs/ovs-3.4.5.6.pem])
+
+###
+### Add an ipsec_gre psk interface with mode as transport and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl set-ssl /ssl-key.pem /ssl-cert.pem /ssl-cacert.pem \
+              -- add-port br0 gre2 \
+              -- set Interface gre2 type=ipsec_gre \
+                 options:local_ip=0.0.0.0 \
+                 options:remote_ip=1.2.3.4 \
+                 options:mode=transport \
+                 options:psk=swordfish])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 45])
+AT_CHECK([sed '1,41d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spdadd 0.0.0.0 1.2.3.4 gre -P out ipsec esp/transport//require;
+> spdadd 1.2.3.4 0.0.0.0 gre -P in ipsec esp/transport//require;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [1.2.3.4   swordfish
+])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+remote 1.2.3.4 {
+        exchange_mode main;
+        nat_traversal on;
+        proposal {
+                encryption_algorithm aes;
+                hash_algorithm sha1;
+                authentication_method pre_shared_key;
+                dh_group 2;
+        }
+}
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+###
+### Delete the ipsec_gre interface and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl del-port gre2])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 53])
+AT_CHECK([sed '1,45d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spddelete 0.0.0.0 1.2.3.4 gre -P out;
+> spddelete 1.2.3.4 0.0.0.0 gre -P in;
+setkey:
+> dump ;
+setkey:
+> dump ;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+
+###
+### Add an ipsec_gre psk interface with mode as tunnel and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl set-ssl /ssl-key.pem /ssl-cert.pem /ssl-cacert.pem \
+              -- add-port br0 gre2 \
+              -- set Interface gre2 type=ipsec_gre \
+                 options:local_ip=0.0.0.0 \
+                 options:remote_ip=1.2.3.4 \
+                 options:mode=tunnel \
+                 options:psk=swordfish])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 57])
+AT_CHECK([sed '1,53d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spdadd 0.0.0.0 1.2.3.4 gre -P out ipsec esp/tunnel/0.0.0.0-1.2.3.4/require;
+> spdadd 1.2.3.4 0.0.0.0 gre -P in ipsec esp/tunnel/1.2.3.4-0.0.0.0/require;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [1.2.3.4   swordfish
+])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+remote 1.2.3.4 {
+        exchange_mode main;
+        nat_traversal on;
+        proposal {
+                encryption_algorithm aes;
+                hash_algorithm sha1;
+                authentication_method pre_shared_key;
+                dh_group 2;
+        }
+}
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+###
+### Delete the ipsec_gre interface and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl del-port gre2])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 65])
+AT_CHECK([sed '1,57d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spddelete 0.0.0.0 1.2.3.4 gre -P out;
+> spddelete 1.2.3.4 0.0.0.0 gre -P in;
+setkey:
+> dump ;
+setkey:
+> dump ;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+
+###
+### Add an ipsec_vxlan psk interface with mode as transport and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl set-ssl /ssl-key.pem /ssl-cert.pem /ssl-cacert.pem \
+              -- add-port br0 vxlan1 \
+              -- set Interface vxlan1 type=ipsec_vxlan \
+                 options:local_ip=0.0.0.0 \
+                 options:remote_ip=1.2.3.4 \
+                 options:mode=transport \
+                 options:psk=swordfish])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 69])
+AT_CHECK([sed '1,65d' actions], [0],
+[[racoon: reload
+setkey:
+> spdadd 0.0.0.0[any] 1.2.3.4 udp -P out ipsec esp/transport//require;
+> spdadd 1.2.3.4 0.0.0.0[any] udp -P in ipsec esp/transport//require;
+]])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [1.2.3.4   swordfish
+])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+remote 1.2.3.4 {
+        exchange_mode main;
+        nat_traversal on;
+        proposal {
+                encryption_algorithm aes;
+                hash_algorithm sha1;
+                authentication_method pre_shared_key;
+                dh_group 2;
+        }
+}
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+###
+### Delete the ipsec_vxlan interface and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl del-port vxlan1])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 77])
+AT_CHECK([sed '1,69d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spddelete 0.0.0.0 1.2.3.4 udp -P out;
+> spddelete 1.2.3.4 0.0.0.0 udp -P in;
+setkey:
+> dump ;
+setkey:
+> dump ;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+
+###
+### Add an ipsec_vxlan psk interface with mode as tunnel and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl set-ssl /ssl-key.pem /ssl-cert.pem /ssl-cacert.pem \
+              -- add-port br0 vxlan1 \
+              -- set Interface vxlan1 type=ipsec_vxlan \
+                 options:local_ip=0.0.0.0 \
+                 options:remote_ip=1.2.3.4 \
+                 options:mode=tunnel \
+                 options:psk=swordfish])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 81])
+AT_CHECK([sed '1,77d' actions], [0],
+[[racoon: reload
+setkey:
+> spdadd 0.0.0.0[any] 1.2.3.4 udp -P out ipsec esp/tunnel/0.0.0.0-1.2.3.4/require;
+> spdadd 1.2.3.4 0.0.0.0[any] udp -P in ipsec esp/tunnel/1.2.3.4-0.0.0.0/require;
+]])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [1.2.3.4   swordfish
+])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+remote 1.2.3.4 {
+        exchange_mode main;
+        nat_traversal on;
+        proposal {
+                encryption_algorithm aes;
+                hash_algorithm sha1;
+                authentication_method pre_shared_key;
+                dh_group 2;
+        }
+}
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+###
+### Delete the ipsec_vxlan interface and check what ovs-monitor-ipsec does
+###
+AT_CHECK([ovs-vsctl del-port vxlan1])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 89])
+AT_CHECK([sed '1,81d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spddelete 0.0.0.0 1.2.3.4 udp -P out;
+> spddelete 1.2.3.4 0.0.0.0 udp -P in;
+setkey:
+> dump ;
+setkey:
+> dump ;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+
+###
+### Add ipsec_vxlan certificate interface and check what ovs-monitor-ipsec does
+###
+AT_DATA([cert.pem], [dnl
+-----BEGIN CERTIFICATE-----
+(not a real certificate)
+-----END CERTIFICATE-----
+])
+AT_DATA([key.pem], [dnl
+-----BEGIN RSA PRIVATE KEY-----
+(not a real private key)
+-----END RSA PRIVATE KEY-----
+])
+AT_CHECK([ovs-vsctl \
+              -- add-port br0 vxlan1 \
+              -- set Interface vxlan1 type=ipsec_vxlan \
+                 options:local_ip=0.0.0.0 \
+                 options:remote_ip=2.3.4.5 \
+                 options:peer_cert='"-----BEGIN CERTIFICATE-----
+(not a real peer certificate)
+-----END CERTIFICATE-----
+"' \
+                 options:certificate='"/cert.pem"' \
+                 options:private_key='"/key.pem"'])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 93])
+AT_CHECK([sed '1,89d' actions], [0],
+[[racoon: reload
+setkey:
+> spdadd 0.0.0.0[any] 2.3.4.5 udp -P out ipsec esp/transport//require;
+> spdadd 2.3.4.5 0.0.0.0[any] udp -P in ipsec esp/transport//require;
+]])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+remote 2.3.4.5 {
+        exchange_mode main;
+        nat_traversal on;
+        ike_frag on;
+        certificate_type x509 "/cert.pem" "/key.pem";
+        my_identifier asn1dn;
+        peers_identifier asn1dn;
+        peers_certfile x509 "/etc/racoon/certs/ovs-2.3.4.5.pem";
+        verify_identifier on;
+        proposal {
+                encryption_algorithm aes;
+                hash_algorithm sha1;
+                authentication_method rsasig;
+                dh_group 2;
+        }
+}
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+AT_CHECK([cat etc/racoon/certs/ovs-2.3.4.5.pem], [0], [dnl
+-----BEGIN CERTIFICATE-----
+(not a real peer certificate)
+-----END CERTIFICATE-----
+])
+
+###
+### Delete the ipsec_vxlan certificate interface.
+###
+AT_CHECK([ovs-vsctl del-port vxlan1])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 101])
+AT_CHECK([sed '1,93d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spddelete 0.0.0.0 2.3.4.5 udp -P out;
+> spddelete 2.3.4.5 0.0.0.0 udp -P in;
+setkey:
+> dump ;
+setkey:
+> dump ;
+])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+AT_CHECK([test ! -f etc/racoon/certs/ovs-2.3.4.5.pem])
+
+###
+### Add an SSL certificate interface.
+###
+cp cert.pem ssl-cert.pem
+cp key.pem ssl-key.pem
+AT_DATA([ssl-cacert.pem], [dnl
+-----BEGIN CERTIFICATE-----
+(not a real CA certificate)
+-----END CERTIFICATE-----
+])
+AT_CHECK([ovs-vsctl set-ssl /ssl-key.pem /ssl-cert.pem /ssl-cacert.pem \
+              -- add-port br0 vxlan1 \
+              -- set Interface vxlan1 type=ipsec_vxlan \
+                 options:local_ip=0.0.0.0 \
+                 options:remote_ip=3.4.5.6 \
+                 options:peer_cert='"-----BEGIN CERTIFICATE-----
+(not a real peer certificate)
+-----END CERTIFICATE-----
+"' \
+                 options:use_ssl_cert='"true"'])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 105])
+AT_CHECK([sed '1,101d' actions], [0],
+[[racoon: reload
+setkey:
+> spdadd 0.0.0.0[any] 3.4.5.6 udp -P out ipsec esp/transport//require;
+> spdadd 3.4.5.6 0.0.0.0[any] udp -P in ipsec esp/transport//require;
+]])
+AT_CHECK([trim etc/racoon/psk.txt], [0], [])
+AT_CHECK([trim etc/racoon/racoon.conf], [0], [dnl
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon/certs";
+remote 3.4.5.6 {
+        exchange_mode main;
+        nat_traversal on;
+        ike_frag on;
+        certificate_type x509 "/ssl-cert.pem" "/ssl-key.pem";
+        my_identifier asn1dn;
+        peers_identifier asn1dn;
+        peers_certfile x509 "/etc/racoon/certs/ovs-3.4.5.6.pem";
+        verify_identifier on;
+        proposal {
+                encryption_algorithm aes;
+                hash_algorithm sha1;
+                authentication_method rsasig;
+                dh_group 2;
+        }
+}
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1, hmac_md5;
+        compression_algorithm deflate;
+}
+])
+AT_CHECK([cat etc/racoon/certs/ovs-3.4.5.6.pem], [0], [dnl
+-----BEGIN CERTIFICATE-----
+(not a real peer certificate)
+-----END CERTIFICATE-----
+])
+
+###
+### Delete the SSL certificate interface.
+###
+AT_CHECK([ovs-vsctl del-port vxlan1])
+OVS_WAIT_UNTIL([test `wc -l < actions` -ge 113])
+AT_CHECK([sed '1,105d' actions], [0], [dnl
+racoon: reload
+setkey:
+> spddelete 0.0.0.0 3.4.5.6 udp -P out;
+> spddelete 3.4.5.6 0.0.0.0 udp -P in;
 setkey:
 > dump ;
 setkey:
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index e73023d..ee80ada 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2010,6 +2010,12 @@
             IPsec tunnel.
           </dd>

+          <dt><code>ipsec_vxlan</code></dt>
+          <dd>
+            An Ethernet over RFC 7348 Virtual eXtensible Local Area Network
+            (VXLAN) over IPv4 IPsec tunnel.
+          </dd>
+
           <dt><code>vxlan</code></dt>
           <dd>
             <p>
--
2.1.4





More information about the dev mailing list