[ovs-dev] [PATCH V4 1/1] ovs-vtep: vtep-ctl and ovs-vtep support of adding explicit tunnel key

itamaro itamar.ofeq at gmail.com
Mon Aug 29 16:16:05 UTC 2016


From: itamarofek <itamar.ofeq at gmail.com>

This patch adds support for handeling a per-tunnel tunnel key in the
ovs-vtep and vtep-ctl.

The aim of this patch is to support the usage of hardware vtep switch as
an inter-cloud gateway, which is used to connect two separated l2 broadcast
domains

Requested-by: "Ofer Ben-Yacov" <ofer.benyacov at gmail.com>
Signed-off-by: "Itamar Ofek" <itamar.ofeq at gmail.com>
Co-authored-by: "Darrell Ball" <dlu998 at gmail.com>
---
 tests/vtep-ctl.at   | 217 +++++++++++++++++++++++++++++++++++++++++++++++-----
 vtep/ovs-vtep       | 122 ++++++++++++++++++-----------
 vtep/vtep-ctl.c     | 203 +++++++++++++++++++++++++++++++++---------------
 vtep/vtep.ovsschema |   9 ++-
 vtep/vtep.xml       |  12 +++
 5 files changed, 438 insertions(+), 125 deletions(-)

diff --git a/tests/vtep-ctl.at b/tests/vtep-ctl.at
index f0511ad..35a0359 100644
--- a/tests/vtep-ctl.at
+++ b/tests/vtep-ctl.at
@@ -433,12 +433,20 @@ AT_CHECK([RUN_VTEP_CTL(
 CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-local ls1 00:11:22:33:44:55 10.0.0.10],
-   [add-ucast-local ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11])
+   [add-ucast-local ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
+   [add-ucast-local ls1 00:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-local ls1 00:11:22:33:55:77 vxlan_over_ipv4 10.0.0.13 200],
+   [add-ucast-local ls1 00:11:22:33:55:88 10.0.0.14 300 level0],
+   [add-ucast-local ls1 00:11:22:33:55:99 vxlan_over_ipv4 10.0.0.15 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
   00:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   00:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.12 100
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
+  00:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.14 300 level0
+  00:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.15 400 level1
 
 mcast-mac-local
 
@@ -460,11 +468,26 @@ AT_CHECK([RUN_VTEP_CTL(
 CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-local ls1 00:11:22:33:44:55 10.0.0.10],
-   [add-ucast-local ls1 00:11:22:33:44:55 10.0.0.11])
+   [add-ucast-local ls1 00:11:22:33:44:55 10.0.0.11],
+   [add-ucast-local ls1 00:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-local ls1 00:11:22:33:55:66 10.0.0.13 200],
+   [add-ucast-local ls1 00:11:22:33:55:77 10.0.0.14 300],
+   [add-ucast-local ls1 00:11:22:33:55:77 10.0.0.15],
+   [add-ucast-local ls1 00:11:22:33:55:88 10.0.0.16],
+   [add-ucast-local ls1 00:11:22:33:55:88 10.0.0.17 400],
+   [add-ucast-local ls1 00:11:22:33:55:99 10.0.0.18 500 level0],
+   [add-ucast-local ls1 00:11:22:33:55:99 10.0.0.19 600 level1],
+   [add-ucast-local ls1 00:11:22:33:56:11 10.0.0.20 700 level1],
+   [add-ucast-local ls1 00:11:22:33:56:11 10.0.0.21])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
   00:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.13 200
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15
+  00:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.17 400
+  00:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.19 600 level1
+  00:11:22:33:56:11 -> vxlan_over_ipv4/10.0.0.21
 
 mcast-mac-local
 
@@ -480,22 +503,34 @@ AT_CHECK([RUN_VTEP_CTL(
 CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-local ls1 00:11:22:33:44:55 10.0.0.10],
-   [add-ucast-local ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11])
+   [add-ucast-local ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
+   [add-ucast-local ls1 00:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-local ls1 00:11:22:33:55:77 vxlan_over_ipv4 10.0.0.13 200],
+   [add-ucast-local ls1 00:11:22:33:55:88 10.0.0.14 300 level0],
+   [add-ucast-local ls1 00:11:22:33:55:99 vxlan_over_ipv4 10.0.0.15 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
   00:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   00:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.12 100
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
+  00:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.14 300 level0
+  00:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.15 400 level1
 
 mcast-mac-local
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL(
-   [del-ucast-local ls1 00:11:22:33:44:55])
+   [del-ucast-local ls1 00:11:22:33:44:55],
+   [del-ucast-local ls1 00:11:22:33:55:66],
+   [del-ucast-local ls1 00:11:22:33:55:88],
+   [del-ucast-local ls1 00:11:22:33:55:99])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
   00:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
 
 mcast-mac-local
 
@@ -511,12 +546,20 @@ AT_CHECK([RUN_VTEP_CTL(
 CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-remote ls1 00:11:22:33:44:55 10.0.0.10],
-   [add-ucast-remote ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11])
+   [add-ucast-remote ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
+   [add-ucast-remote ls1 00:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-remote ls1 00:11:22:33:55:77 10.0.0.13 200],
+   [add-ucast-remote ls1 00:11:22:33:55:88 10.0.0.14 300 level0],
+   [add-ucast-remote ls1 00:11:22:33:55:99 vxlan_over_ipv4 10.0.0.15 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
   00:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   00:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.12 100
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
+  00:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.14 300 level0
+  00:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.15 400 level1
 
 mcast-mac-remote
 
@@ -538,11 +581,20 @@ AT_CHECK([RUN_VTEP_CTL(
 CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-remote ls1 00:11:22:33:44:55 10.0.0.10],
-   [add-ucast-remote ls1 00:11:22:33:44:55 10.0.0.11])
+   [add-ucast-remote ls1 00:11:22:33:44:55 10.0.0.11],
+   [add-ucast-remote ls1 00:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-remote ls1 00:11:22:33:55:66 10.0.0.13 200],
+   [add-ucast-remote ls1 00:11:22:33:55:99 10.0.0.18 500 level0],
+   [add-ucast-remote ls1 00:11:22:33:55:99 10.0.0.19 600 level1],
+   [add-ucast-remote ls1 00:11:22:33:56:11 10.0.0.20 700 level1],
+   [add-ucast-remote ls1 00:11:22:33:56:11 10.0.0.21])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
   00:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.13 200
+  00:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.19 600 level1
+  00:11:22:33:56:11 -> vxlan_over_ipv4/10.0.0.21
 
 mcast-mac-remote
 
@@ -558,22 +610,34 @@ AT_CHECK([RUN_VTEP_CTL(
 CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-remote ls1 00:11:22:33:44:55 10.0.0.10],
-   [add-ucast-remote ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11])
+   [add-ucast-remote ls1 00:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
+   [add-ucast-remote ls1 00:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-remote ls1 00:11:22:33:55:77 vxlan_over_ipv4 10.0.0.13 200],
+   [add-ucast-remote ls1 00:11:22:33:55:88 10.0.0.14 300 level0],
+   [add-ucast-remote ls1 00:11:22:33:55:99 vxlan_over_ipv4 10.0.0.15 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
   00:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   00:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.12 100
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
+  00:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.14 300 level0
+  00:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.15 400 level1
 
 mcast-mac-remote
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL(
-   [del-ucast-remote ls1 00:11:22:33:44:55])
+   [del-ucast-remote ls1 00:11:22:33:44:55],
+   [del-ucast-remote ls1 00:11:22:33:55:66],
+   [del-ucast-remote ls1 00:11:22:33:55:88],
+   [del-ucast-remote ls1 00:11:22:33:55:99])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
   00:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
 
 mcast-mac-remote
 
@@ -590,13 +654,25 @@ CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-local ls1 00:11:22:33:44:55 10.0.0.10],
    [add-ucast-local ls1 00:11:22:33:44:66 10.0.0.11],
+   [add-ucast-local ls1 00:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-local ls1 00:11:22:33:55:77 vxlan_over_ipv4 10.0.0.13 200],
+   [add-ucast-local ls1 00:11:22:33:55:88 10.0.0.14 300 level0],
+   [add-ucast-local ls1 00:11:22:33:55:99 vxlan_over_ipv4 10.0.0.15 400 level1],
    [add-ucast-remote ls1 02:11:22:33:44:55 10.0.0.10],
-   [add-ucast-remote ls1 02:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11])
+   [add-ucast-remote ls1 02:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
+   [add-ucast-remote ls1 02:11:22:33:55:66 10.0.0.12 100],
+   [add-ucast-remote ls1 02:11:22:33:55:77 vxlan_over_ipv4 10.0.0.13 200],
+   [add-ucast-remote ls1 02:11:22:33:55:88 10.0.0.14 300 level0],
+   [add-ucast-remote ls1 02:11:22:33:55:99 vxlan_over_ipv4 10.0.0.15 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
   00:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   00:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  00:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.12 100
+  00:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
+  00:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.14 300 level0
+  00:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.15 400 level1
 
 mcast-mac-local
 
@@ -605,6 +681,10 @@ AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
   02:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   02:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  02:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.12 100
+  02:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.13 200
+  02:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.14 300 level0
+  02:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.15 400 level1
 
 mcast-mac-remote
 
@@ -621,7 +701,11 @@ CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.10],
    [add-mcast-local ls1 01:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
-   [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.12])
+   [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.12],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.13 100],
+   [add-mcast-local ls1 01:11:22:33:55:77 vxlan_over_ipv4 10.0.0.14 200],
+   [add-mcast-local ls1 01:11:22:33:55:88 10.0.0.15 300 level0],
+   [add-mcast-local ls1 01:11:22:33:55:99 vxlan_over_ipv4 10.0.0.16 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
@@ -630,6 +714,10 @@ mcast-mac-local
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.13 100
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.14 200
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.15 300 level0
+  01:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.16 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
@@ -651,7 +739,11 @@ AT_CHECK([RUN_VTEP_CTL(
    [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.10],
    [add-mcast-local ls1 01:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
    [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.12],
-   [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.13])
+   [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.13],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-local ls1 01:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 200],
+   [add-mcast-local ls1 01:11:22:33:55:88 10.0.0.16 300 level0],
+   [add-mcast-local ls1 01:11:22:33:55:99 vxlan_over_ipv4 10.0.0.17 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
@@ -661,10 +753,16 @@ mcast-mac-local
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.13
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 200
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.16 300 level0
+  01:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.17 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL(
-   [del-mcast-local ls1 01:11:22:33:44:55 10.0.0.12])
+   [del-mcast-local ls1 01:11:22:33:44:55 10.0.0.12],
+   [del-mcast-local ls1 01:11:22:33:55:66 10.0.0.14],
+   [del-mcast-local ls1 01:11:22:33:55:88 10.0.0.16])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
@@ -673,6 +771,8 @@ mcast-mac-local
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.13
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 200
+  01:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.17 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 VTEP_CTL_CLEANUP
@@ -687,7 +787,12 @@ CHECK_LSWITCHES([ls1])
 AT_CHECK([RUN_VTEP_CTL(
    [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.10],
    [add-mcast-remote ls1 01:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
-   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12])
+   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12],
+   [add-mcast-remote ls1 01:11:22:33:55:66 10.0.0.13 100],
+   [add-mcast-remote ls1 01:11:22:33:55:77 vxlan_over_ipv4 10.0.0.14 300],
+   [add-mcast-remote ls1 01:11:22:33:55:66 10.0.0.15 200],
+   [add-mcast-remote ls1 01:11:22:33:55:88 10.0.0.16 300 level0],
+   [add-mcast-remote ls1 01:11:22:33:55:99 vxlan_over_ipv4 10.0.0.17 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
@@ -696,6 +801,11 @@ mcast-mac-remote
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.13 100
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.15 200
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.14 300
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.16 300 level0
+  01:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.17 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
@@ -717,7 +827,12 @@ AT_CHECK([RUN_VTEP_CTL(
    [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.10],
    [add-mcast-remote ls1 01:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
    [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12],
-   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.13])
+   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.13],
+   [add-mcast-remote ls1 01:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-remote ls1 01:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 300],
+   [add-mcast-remote ls1 01:11:22:33:55:66 10.0.0.16 200],
+   [add-mcast-remote ls1 01:11:22:33:55:88 10.0.0.17 300 level0],
+   [add-mcast-remote ls1 01:11:22:33:55:99 vxlan_over_ipv4 10.0.0.18 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
@@ -727,10 +842,17 @@ mcast-mac-remote
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.13
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.17 300 level0
+  01:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.18 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL(
-   [del-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12])
+   [del-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12],
+   [del-mcast-remote ls1 01:11:22:33:55:66 10.0.0.14],
+   [del-mcast-remote ls1 01:11:22:33:55:88 10.0.0.17])		
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
@@ -739,6 +861,9 @@ mcast-mac-remote
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.13
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  01:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.18 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 VTEP_CTL_CLEANUP
@@ -756,7 +881,15 @@ AT_CHECK([RUN_VTEP_CTL(
    [add-mcast-local ls1 01:11:22:33:44:55 10.0.0.12],
    [add-mcast-remote ls1 03:11:22:33:44:55 10.0.0.10],
    [add-mcast-remote ls1 03:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
-   [add-mcast-remote ls1 03:11:22:33:44:55 10.0.0.12])
+   [add-mcast-remote ls1 03:11:22:33:44:55 10.0.0.12],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-local ls1 01:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 300],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.16 200],
+   [add-mcast-remote ls1 03:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-remote ls1 03:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 300],
+   [add-mcast-remote ls1 03:11:22:33:55:66 10.0.0.16 200],
+   [add-mcast-local ls1 01:11:22:33:55:88 10.0.0.17 300 level0],
+   [add-mcast-remote ls1 01:11:22:33:55:99 vxlan_over_ipv4 10.0.0.18 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
@@ -765,15 +898,23 @@ mcast-mac-local
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.17 300 level0
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
    [ucast-mac-remote
 
 mcast-mac-remote
+  01:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.18 400 level1
   03:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   03:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   03:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  03:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
 
 ], [], [VTEP_CTL_CLEANUP])
 VTEP_CTL_CLEANUP
@@ -793,7 +934,15 @@ AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-remote ls1 00:11:22:33:44:55 10.0.0.10],
    [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.10],
    [add-mcast-remote ls1 01:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
-   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12])
+   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-local ls1 01:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 300],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.16 200],
+   [add-mcast-remote ls1 03:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-remote ls1 03:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 300],
+   [add-mcast-remote ls1 03:11:22:33:55:66 10.0.0.16 200],
+   [add-mcast-local ls1 01:11:22:33:55:88 10.0.0.17 300 level0],
+   [add-mcast-remote ls1 03:11:22:33:55:99 vxlan_over_ipv4 10.0.0.18 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
@@ -803,6 +952,10 @@ mcast-mac-local
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.17 300 level0
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
@@ -813,6 +966,10 @@ mcast-mac-remote
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  03:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  03:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.18 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL(
@@ -831,6 +988,10 @@ mcast-mac-remote
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  03:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  03:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.18 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 VTEP_CTL_CLEANUP
@@ -850,7 +1011,15 @@ AT_CHECK([RUN_VTEP_CTL(
    [add-ucast-remote ls1 00:11:22:33:44:55 10.0.0.10],
    [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.10],
    [add-mcast-remote ls1 01:11:22:33:44:66 vxlan_over_ipv4 10.0.0.11],
-   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12])
+   [add-mcast-remote ls1 01:11:22:33:44:55 10.0.0.12],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-local ls1 01:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 300],
+   [add-mcast-local ls1 01:11:22:33:55:66 10.0.0.16 200],
+   [add-mcast-remote ls1 03:11:22:33:55:66 10.0.0.14 100],
+   [add-mcast-remote ls1 03:11:22:33:55:77 vxlan_over_ipv4 10.0.0.15 300],
+   [add-mcast-remote ls1 03:11:22:33:55:66 10.0.0.16 200],
+   [add-mcast-local ls1 01:11:22:33:55:88 10.0.0.17 300 level0],
+   [add-mcast-remote ls1 03:11:22:33:55:99 vxlan_over_ipv4 10.0.0.18 400 level1])
 ], [0], [], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
    [ucast-mac-local
@@ -860,6 +1029,10 @@ mcast-mac-local
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.17 300 level0
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
@@ -870,6 +1043,10 @@ mcast-mac-remote
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  03:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  03:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  03:11:22:33:55:99 -> vxlan_over_ipv4/10.0.0.18 400 level1
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL(
@@ -882,6 +1059,10 @@ mcast-mac-local
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.10
   01:11:22:33:44:55 -> vxlan_over_ipv4/10.0.0.12
   01:11:22:33:44:66 -> vxlan_over_ipv4/10.0.0.11
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.14 100
+  01:11:22:33:55:66 -> vxlan_over_ipv4/10.0.0.16 200
+  01:11:22:33:55:77 -> vxlan_over_ipv4/10.0.0.15 300
+  01:11:22:33:55:88 -> vxlan_over_ipv4/10.0.0.17 300 level0
 
 ], [], [VTEP_CTL_CLEANUP])
 AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
diff --git a/vtep/ovs-vtep b/vtep/ovs-vtep
index b32a82a..dfb94e6 100755
--- a/vtep/ovs-vtep
+++ b/vtep/ovs-vtep
@@ -33,6 +33,12 @@ import six
 
 
 VERSION = "0.99"
+MACS_MAC_INDEX = 1
+MACS_ENCAP_INDEX = 2
+MACS_DEST_IP_INDEX = 3
+MACS_KEY_INDEX = 4
+MACS_LEVEL_INDEX = 5
+MACS_NUM_OF_FIELDS = 7
 
 root_prefix = ""
 
@@ -120,30 +126,54 @@ class Logical_Switch(object):
         for port_no, tun_name, remote_ip in six.itervalues(self.tunnels):
             del_bfd(remote_ip)
 
-    def update_flood(self):
-        flood_ports = list(self.ports.values())
+    def vtep_ports(self, tunnel_list):
+        level0_ports = []
+        level1_ports = []
+        for tunnel in tunnel_list:
+            if self.tunnels[tunnel][4] is 'level1':
+                level1_ports.append(self.tunnels[tunnel][0])
+            else:
+                level0_ports.append(self.tunnels[tunnel][0])
+        return level1_ports, level0_ports
 
-        # Traffic flowing from one 'unknown-dst' should not be flooded to
-        # port belonging to another 'unknown-dst'.
-        for tunnel in self.unknown_dsts:
-            port_no = self.tunnels[tunnel][0]
-            ovs_ofctl("add-flow %s table=1,priority=1,in_port=%s,action=%s"
-                      % (self.short_name, port_no, ",".join(flood_ports)))
+    def update_flood(self):
+        phy_ports = list(self.ports.values())
+        level1_ports, level0_ports = self.vtep_ports(self.tunnels.keys())
+        level1_unknown, level0_unknown = self.vtep_ports(self.unknown_dsts)
 
         # Traffic coming from a VTEP physical port should always be flooded to
         # all the other physical ports that belong to that VTEP device and
-        # this logical switch.  If the replication mode is service node then
+        # this logical switch and all level1 VTEP ports.
+        # If the level0 replication mode is service node then
         # send to one unknown_dst node (the first one here); else we assume the
         # replication mode is source node and we send the packet to all
         # unknown_dst nodes.
-        for tunnel in self.unknown_dsts:
-            port_no = self.tunnels[tunnel][0]
-            flood_ports.append(port_no)
+
+        phy_flood_ports = phy_ports + level1_unknown
+        if len(level0_unknown) > 0:
             if self.replication_mode == "service_node":
-                break
+                phy_flood_ports += level0_unknown[0]
+            else:
+                phy_flood_ports += level0_unknown
+        for port_no in phy_ports:
+            ovs_ofctl("add-flow %s table=1,priority=1,in_port=%s,action=%s"
+                      % (self.short_name, port_no, ",".join(phy_flood_ports)))
 
-        ovs_ofctl("add-flow %s table=1,priority=0,action=%s"
-                  % (self.short_name, ",".join(flood_ports)))
+        # Traffic flowing from a level0 VTEP should not be flooded to level0
+        # unknown-dst ports
+        level0_flood_ports = phy_ports + level1_unknown
+        for port_no in level0_ports:
+            ovs_ofctl("add-flow %s table=1,priority=1,in_port=%s,action=%s"
+                      % (self.short_name, port_no,
+                         ",".join(level0_flood_ports)))
+
+        # Traffic flowing from a level1 VTEP should not be flooded to level1
+        # unknown-dst ports
+        level1_flood_ports = phy_ports + level0_unknown
+        for port_no in level1_ports:
+            ovs_ofctl("add-flow %s table=1,priority=1,in_port=%s,action=%s"
+                      % (self.short_name,
+                          port_no, ",".join(level1_flood_ports)))
 
     def add_lbinding(self, lbinding):
         vlog.info("adding %s binding to %s" % (lbinding, self.name))
@@ -164,14 +194,12 @@ class Logical_Switch(object):
         del self.ports[lbinding]
         self.update_flood()
 
-    def add_tunnel(self, tunnel, tunnel_key):
+    def add_tunnel(self, ip, tunnel_key, tunnel_level):
         global tun_id
-        vlog.info("adding tunnel %s" % tunnel)
-        encap, ip = tunnel.split("/")
 
-        if encap != "vxlan_over_ipv4":
-            vlog.warn("unsupported tunnel format %s" % encap)
-            return
+        vlog.info("adding tunnel: ip %s key %s %s" %
+                  (ip, tunnel_key,
+                   'level1' if tunnel_level is 'level1' else 'level0'))
 
         tun_id += 1
         tun_name = "vx" + str(tun_id)
@@ -185,14 +213,14 @@ class Logical_Switch(object):
             if port_no != "-1":
                 break
             elif i == 9:
-                vlog.warn("couldn't create tunnel %s" % tunnel)
+                vlog.warn("couldn't create tunnel %s" % ip)
                 ovs_vsctl("del-port %s %s" % (self.short_name, tun_name))
                 return
 
             # Give the system a moment to allocate the port number
             time.sleep(0.5)
 
-        self.tunnels[tunnel] = (port_no, tun_name, ip)
+        self.tunnels[ip] = (port_no, tun_name, ip, tunnel_key, tunnel_level)
 
         add_bfd(ip)
 
@@ -200,17 +228,18 @@ class Logical_Switch(object):
                   "actions=resubmit(,1)"
                   % (self.short_name, port_no))
 
-    def del_tunnel(self, tunnel):
-        vlog.info("removing tunnel %s" % tunnel)
+    def del_tunnel(self, tunnel_ip):
+        vlog.info("removing tunnel %s" % tunnel_ip)
 
-        port_no, tun_name, remote_ip = self.tunnels[tunnel]
+        (port_no, tun_name,
+        remote_ip, tunnel_key, tunnel_level) = self.tunnels[tunnel_ip]
         ovs_ofctl("del-flows %s table=0,in_port=%s"
                   % (self.short_name, port_no))
         ovs_vsctl("del-port %s %s" % (self.short_name, tun_name))
 
         del_bfd(remote_ip)
 
-        del self.tunnels[tunnel]
+        del self.tunnels[tunnel_ip]
 
     def update_local_macs(self):
         flows = ovs_ofctl("dump-flows %s cookie=0x5000/-1,table=1"
@@ -231,8 +260,8 @@ class Logical_Switch(object):
 
         self.local_macs = macs
 
-    def add_remote_mac(self, mac, tunnel):
-        port_no = self.tunnels.get(tunnel, (0, ""))[0]
+    def add_remote_mac(self, mac, tunnel_ip):
+        port_no = self.tunnels.get(tunnel_ip, (0, ""))[0]
         if not port_no:
             return
 
@@ -245,7 +274,8 @@ class Logical_Switch(object):
     def update_remote_macs(self):
         remote_macs = {}
         unknown_dsts = set()
-        tunnels = set()
+        # A map of tunnel ip address to tunnel key and tunnel level
+        tunnels = {}
         parse_ucast = True
 
         column = vtep_ctl("--columns=tunnel_key find logical_switch "
@@ -264,28 +294,32 @@ class Logical_Switch(object):
             if (line.find("mcast-mac-remote") != -1):
                 parse_ucast = False
                 continue
-
-            entry = re.split(r'  (.*) -> (.*)', line)
-            if len(entry) != 4:
+            entry = re.split(r'  (.*) -> ([^/]*)/(\S*)\s?(\d+)?\s?(.*)?',
+                             line)
+            if len(entry) != MACS_NUM_OF_FIELDS:
                 continue
 
             if parse_ucast:
-                remote_macs[entry[1]] = entry[2]
+                remote_macs[entry[MACS_MAC_INDEX]] = entry[MACS_ENCAP_INDEX]
             else:
-                if entry[1] != "unknown-dst":
+                if entry[MACS_MAC_INDEX] != "unknown-dst":
                     continue
 
-                unknown_dsts.add(entry[2])
-
-            tunnels.add(entry[2])
+                unknown_dsts.add(entry[MACS_DEST_IP_INDEX])
 
-        old_tunnels = set(self.tunnels.keys())
-
-        for tunnel in tunnels.difference(old_tunnels):
-            self.add_tunnel(tunnel, tunnel_key)
+            tunnels[entry[MACS_DEST_IP_INDEX]] = (entry[MACS_KEY_INDEX],
+                                                  entry[MACS_LEVEL_INDEX])
+        old_tunnel_ips = set(self.tunnels.keys())
+        tunnel_ips = set(tunnels.keys())
+        for tunnel_ip in tunnel_ips.difference(old_tunnel_ips):
+            if tunnels[tunnel_ip][0]:
+                tunnel_scope_key = tunnels[tunnel_ip][0]
+            else:
+                tunnel_scope_key = tunnel_key
+            self.add_tunnel(tunnel_ip, tunnel_scope_key, tunnels[tunnel_ip][1])
 
-        for tunnel in old_tunnels.difference(tunnels):
-            self.del_tunnel(tunnel)
+        for tunnel_ip in old_tunnel_ips.difference(tunnel_ips):
+            self.del_tunnel(tunnel_ip)
 
         for mac in six.iterkeys(remote_macs):
             if (self.remote_macs.get(mac) != remote_macs[mac]):
diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c
index 245ba0d..88b8823 100644
--- a/vtep/vtep-ctl.c
+++ b/vtep/vtep-ctl.c
@@ -37,6 +37,7 @@
 #include "openvswitch/json.h"
 #include "ovsdb-data.h"
 #include "ovsdb-idl.h"
+#include "lib/packets.h"
 #include "poll-loop.h"
 #include "process.h"
 #include "stream.h"
@@ -345,18 +346,18 @@ Logical Router commands:\n\
   lr-exists LR                exit 2 if LR does not exist\n\
 \n\
 MAC binding commands:\n\
-  add-ucast-local LS MAC [ENCAP] IP   add ucast local entry in LS\n\
-  del-ucast-local LS MAC              del ucast local entry from LS\n\
-  add-mcast-local LS MAC [ENCAP] IP   add mcast local entry in LS\n\
-  del-mcast-local LS MAC [ENCAP] IP   del mcast local entry from LS\n\
-  clear-local-macs LS                 clear local mac entries\n\
-  list-local-macs LS                  list local mac entries\n\
-  add-ucast-remote LS MAC [ENCAP] IP  add ucast remote entry in LS\n\
-  del-ucast-remote LS MAC             del ucast remote entry from LS\n\
-  add-mcast-remote LS MAC [ENCAP] IP  add mcast remote entry in LS\n\
-  del-mcast-remote LS MAC [ENCAP] IP  del mcast remote entry from LS\n\
-  clear-remote-macs LS                clear remote mac entries\n\
-  list-remote-macs LS                 list remote mac entries\n\
+  add-ucast-local LS MAC [ENCAP] IP [KEY [LEVEL]]  add ucast local entry in LS\n\
+  del-ucast-local LS MAC                           del ucast local entry from LS\n\
+  add-mcast-local LS MAC [ENCAP] IP [KEY [LEVEL]]  add mcast local entry in LS\n\
+  del-mcast-local LS MAC [ENCAP] IP                del mcast local entry from LS\n\
+  clear-local-macs LS                              clear local mac entries\n\
+  list-local-macs LS                               list local mac entries\n\
+  add-ucast-remote LS MAC [ENCAP] IP [KEY [LEVEL]] add ucast remote entry in LS\n\
+  del-ucast-remote LS MAC                          del ucast remote entry from LS\n\
+  add-mcast-remote LS MAC [ENCAP] IP [KEY [LEVEL]] add mcast remote entry in LS\n\
+  del-mcast-remote LS MAC [ENCAP] IP               del mcast remote entry from LS\n\
+  clear-remote-macs LS                             clear remote mac entries\n\
+  list-remote-macs LS                              list remote mac entries\n\
 \n\
 %s\
 \n\
@@ -451,6 +452,14 @@ struct vtep_ctl_context {
                              * struct vtep_ctl_lrouter. */
 };
 
+struct add_mac_args {
+    const char *mac;
+    const char *encap;
+    const char *dst_ip;
+    const char *tunnel_key;
+    const char *tunnel_level;
+};
+
 /* Casts 'base' into 'struct vtep_ctl_context'. */
 static struct vtep_ctl_context *
 vtep_ctl_context_cast(struct ctl_context *base)
@@ -887,7 +896,10 @@ pre_get_info(struct ctl_context *ctx)
                          &vteprec_physical_locator_col_dst_ip);
     ovsdb_idl_add_column(ctx->idl,
                          &vteprec_physical_locator_col_encapsulation_type);
-
+    ovsdb_idl_add_column(ctx->idl,
+                         &vteprec_physical_locator_col_tunnel_key);
+    ovsdb_idl_add_column(ctx->idl,
+                         &vteprec_physical_locator_col_tunnel_level);
     ovsdb_idl_add_column(ctx->idl, &vteprec_tunnel_col_local);
     ovsdb_idl_add_column(ctx->idl, &vteprec_tunnel_col_remote);
 }
@@ -1648,34 +1660,75 @@ cmd_lr_exists(struct ctl_context *ctx)
     }
 }
 
+inline void
+parse_add_mac_args(struct ctl_context *ctx, struct add_mac_args* args)
+{
+    ovs_be32 ip = 0;
+    if (ctx->argc < 4 ) {
+      ctl_fatal("invalid argument set only %d args supplied",ctx->argc);
+  
+    }
+    int index = 2;
+    args->mac = ctx->argv[index];
+    /* check 3rd argument if its ip assume vxlan_over_ipv4
+     * else take the encapsulation from supplied argument
+     */
+    if (!ip_parse(ctx->argv[++index], &ip)) {
+        args->encap = ctx->argv[index++];
+    } else {
+        args->encap = "vxlan_over_ipv4";
+    }
+    args->dst_ip = ctx->argv[index];
+    /* if no more arguments supplied prsing is done
+     */
+    if (ctx->argc == ++index) {
+        return;
+    }
+    /* check for optional tunnel_key
+     */
+    args->tunnel_key = ctx->argv[index];
+    if (ctx->argc == ++index) {
+        return;
+    }
+    /* tunnel level can be given only if tunnel key is provided
+     */
+    args->tunnel_level = ctx->argv[index];
+    if (ctx->argc == ++index) {
+        return;
+    }
+    ctl_fatal("Unexpected number of argument %d", index);
+}
+
 static void
 add_ucast_entry(struct ctl_context *ctx, bool local)
 {
     struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
     struct vtep_ctl_lswitch *ls;
-    const char *mac;
-    const char *encap;
-    const char *dst_ip;
+    struct add_mac_args args;
+    memset(&args,0,sizeof(args));
+    int64_t tunnel_scope_key = 0;
+
     struct vteprec_physical_locator *ploc_cfg;
 
     vtep_ctl_context_populate_cache(ctx);
 
     ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
-    mac = ctx->argv[2];
-
-    if (ctx->argc == 4) {
-        encap = "vxlan_over_ipv4";
-        dst_ip = ctx->argv[3];
-    } else {
-        encap = ctx->argv[3];
-        dst_ip = ctx->argv[4];
-    }
-
-    ploc_cfg = find_ploc(vtepctl_ctx, encap, dst_ip);
+    parse_add_mac_args(ctx,&args);
+    ploc_cfg = find_ploc(vtepctl_ctx, args.encap, args.dst_ip);
     if (!ploc_cfg) {
         ploc_cfg = vteprec_physical_locator_insert(ctx->txn);
-        vteprec_physical_locator_set_dst_ip(ploc_cfg, dst_ip);
-        vteprec_physical_locator_set_encapsulation_type(ploc_cfg, encap);
+        if (args.tunnel_key) {
+            ovs_scan(args.tunnel_key,"%ld",&tunnel_scope_key);
+            vteprec_physical_locator_set_tunnel_key(ploc_cfg,
+                                                    &tunnel_scope_key,1);
+            if (args.tunnel_level){
+                vteprec_physical_locator_set_tunnel_level(ploc_cfg,
+                                                          args.tunnel_level);
+            }
+
+        }
+        vteprec_physical_locator_set_dst_ip(ploc_cfg,args.dst_ip);
+        vteprec_physical_locator_set_encapsulation_type(ploc_cfg, args.encap);
 
         add_ploc_to_cache(vtepctl_ctx, ploc_cfg);
     }
@@ -1683,23 +1736,23 @@ add_ucast_entry(struct ctl_context *ctx, bool local)
     if (local) {
         struct vteprec_ucast_macs_local *ucast_cfg;
 
-        ucast_cfg = shash_find_data(&ls->ucast_local, mac);
+        ucast_cfg = shash_find_data(&ls->ucast_local, args.mac);
         if (!ucast_cfg) {
             ucast_cfg = vteprec_ucast_macs_local_insert(ctx->txn);
-            vteprec_ucast_macs_local_set_MAC(ucast_cfg, mac);
+            vteprec_ucast_macs_local_set_MAC(ucast_cfg, args.mac);
             vteprec_ucast_macs_local_set_logical_switch(ucast_cfg, ls->ls_cfg);
-            shash_add(&ls->ucast_local, mac, ucast_cfg);
+            shash_add(&ls->ucast_local, args.mac, ucast_cfg);
         }
         vteprec_ucast_macs_local_set_locator(ucast_cfg, ploc_cfg);
     } else {
         struct vteprec_ucast_macs_remote *ucast_cfg;
 
-        ucast_cfg = shash_find_data(&ls->ucast_remote, mac);
+        ucast_cfg = shash_find_data(&ls->ucast_remote, args.mac);
         if (!ucast_cfg) {
             ucast_cfg = vteprec_ucast_macs_remote_insert(ctx->txn);
-            vteprec_ucast_macs_remote_set_MAC(ucast_cfg, mac);
+            vteprec_ucast_macs_remote_set_MAC(ucast_cfg, args.mac);
             vteprec_ucast_macs_remote_set_logical_switch(ucast_cfg, ls->ls_cfg);
-            shash_add(&ls->ucast_remote, mac, ucast_cfg);
+            shash_add(&ls->ucast_remote, args.mac, ucast_cfg);
         }
         vteprec_ucast_macs_remote_set_locator(ucast_cfg, ploc_cfg);
     }
@@ -1790,7 +1843,8 @@ commit_mcast_entries(struct vtep_ctl_mcast_mac *mcast_mac)
 static void
 add_mcast_entry(struct ctl_context *ctx,
                 struct vtep_ctl_lswitch *ls, const char *mac,
-                const char *encap, const char *dst_ip, bool local)
+                const char *encap, const char *dst_ip, const char* tunnel_key,
+                const char* tunnel_scope, bool local)
 {
     struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
     struct shash *mcast_shash;
@@ -1839,6 +1893,16 @@ add_mcast_entry(struct ctl_context *ctx,
     ploc_cfg = find_ploc(vtepctl_ctx, encap, dst_ip);
     if (!ploc_cfg) {
         ploc_cfg = vteprec_physical_locator_insert(ctx->txn);
+        if (tunnel_key) {
+            int64_t tunnel_scope_key = 0;
+            ovs_scan(tunnel_key,"%ld",&tunnel_scope_key);
+            vteprec_physical_locator_set_tunnel_key(ploc_cfg,
+                                                    &tunnel_scope_key,1);
+            if (tunnel_scope){
+                vteprec_physical_locator_set_tunnel_level(ploc_cfg,
+                                                          tunnel_scope);
+            }
+        }
         vteprec_physical_locator_set_dst_ip(ploc_cfg, dst_ip);
         vteprec_physical_locator_set_encapsulation_type(ploc_cfg, encap);
 
@@ -1908,27 +1972,18 @@ add_del_mcast_entry(struct ctl_context *ctx, bool add, bool local)
 {
     struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
     struct vtep_ctl_lswitch *ls;
-    const char *mac;
-    const char *encap;
-    const char *dst_ip;
+    struct add_mac_args args;
+    memset(&args,0,sizeof(args));
+    
 
     vtep_ctl_context_populate_cache(ctx);
 
     ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
-    mac = ctx->argv[2];
-
-    if (ctx->argc == 4) {
-        encap = "vxlan_over_ipv4";
-        dst_ip = ctx->argv[3];
-    } else {
-        encap = ctx->argv[3];
-        dst_ip = ctx->argv[4];
-    }
-
+    parse_add_mac_args(ctx,&args);
     if (add) {
-        add_mcast_entry(ctx, ls, mac, encap, dst_ip, local);
+        add_mcast_entry(ctx, ls, args.mac, args.encap, args.dst_ip, args.tunnel_key,args.tunnel_level, local);
     } else {
-        del_mcast_entry(ctx, ls, mac, encap, dst_ip, local);
+        del_mcast_entry(ctx, ls, args.mac, args.encap, args.dst_ip, local);
     }
 
     vtep_ctl_context_invalidate_cache(ctx);
@@ -2017,7 +2072,8 @@ list_macs(struct ctl_context *ctx, bool local)
     struct svec ucast_macs;
     struct shash *mcast_shash;
     struct svec mcast_macs;
-
+    char tunnel_key[10];
+    char tunnel_level[10];
     vtep_ctl_context_populate_cache(ctx);
     ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
 
@@ -2032,9 +2088,21 @@ list_macs(struct ctl_context *ctx, bool local)
         char *entry;
 
         ploc_cfg = local ? ucast_local->locator : ucast_remote->locator;
-
-        entry = xasprintf("  %s -> %s/%s", node->name,
-                          ploc_cfg->encapsulation_type, ploc_cfg->dst_ip);
+        tunnel_key[0] = '\0';
+        if (ploc_cfg->tunnel_key) {
+            snprintf(&tunnel_key[0], 10, " %d",
+                     (uint32_t)(*ploc_cfg->tunnel_key));
+        }
+        if (ploc_cfg->tunnel_level) {
+            snprintf(tunnel_level, 10, " %s", ploc_cfg->tunnel_level);
+        } else {
+            tunnel_level[0] = '\0';
+        }
+        entry = xasprintf("  %s -> %s/%s%s%s", node->name,
+                          ploc_cfg->encapsulation_type,
+                          ploc_cfg->dst_ip,
+                          tunnel_key,
+                          tunnel_level);
         svec_add_nocopy(&ucast_macs, entry);
     }
     ds_put_format(&ctx->output, "ucast-mac-%s\n", local ? "local" : "remote");
@@ -2049,9 +2117,22 @@ list_macs(struct ctl_context *ctx, bool local)
         char *entry;
 
         LIST_FOR_EACH (ploc, locators_node, &mcast_mac->locators) {
-            entry = xasprintf("  %s -> %s/%s", node->name,
+            tunnel_key[0] = '\0';
+            if (ploc->ploc_cfg->tunnel_key) {
+                snprintf(tunnel_key, 10, " %d",
+                         (uint32_t)(*ploc->ploc_cfg->tunnel_key));
+            }
+            if (ploc->ploc_cfg->tunnel_level) {
+                snprintf(tunnel_level, 10, " %s",
+                         ploc->ploc_cfg->tunnel_level);
+            } else {
+                tunnel_level[0] = '\0';
+            }
+            entry = xasprintf("  %s -> %s/%s%s%s", node->name,
                               ploc->ploc_cfg->encapsulation_type,
-                              ploc->ploc_cfg->dst_ip);
+                              ploc->ploc_cfg->dst_ip,
+                              tunnel_key,
+                              tunnel_level);
             svec_add_nocopy(&mcast_macs, entry);
         }
     }
@@ -2508,11 +2589,11 @@ static const struct ctl_command_syntax vtep_commands[] = {
     {"lr-exists", 1, 1, NULL, pre_get_info, cmd_lr_exists, NULL, "", RO},
 
     /* MAC binding commands. */
-    {"add-ucast-local", 3, 4, NULL, pre_get_info, cmd_add_ucast_local, NULL,
+    {"add-ucast-local", 3, 6, NULL, pre_get_info, cmd_add_ucast_local, NULL,
      "", RW},
     {"del-ucast-local", 2, 2, NULL, pre_get_info, cmd_del_ucast_local, NULL,
      "", RW},
-    {"add-mcast-local", 3, 4, NULL, pre_get_info, cmd_add_mcast_local, NULL,
+    {"add-mcast-local", 3, 6, NULL, pre_get_info, cmd_add_mcast_local, NULL,
      "", RW},
     {"del-mcast-local", 3, 4, NULL, pre_get_info, cmd_del_mcast_local, NULL,
      "", RW},
@@ -2520,11 +2601,11 @@ static const struct ctl_command_syntax vtep_commands[] = {
      "", RO},
     {"list-local-macs", 1, 1, NULL, pre_get_info, cmd_list_local_macs, NULL,
      "", RO},
-    {"add-ucast-remote", 3, 4, NULL, pre_get_info, cmd_add_ucast_remote, NULL,
+    {"add-ucast-remote", 3, 6, NULL, pre_get_info, cmd_add_ucast_remote, NULL,
      "", RW},
     {"del-ucast-remote", 2, 2, NULL, pre_get_info, cmd_del_ucast_remote, NULL,
      "", RW},
-    {"add-mcast-remote", 3, 4, NULL, pre_get_info, cmd_add_mcast_remote, NULL,
+    {"add-mcast-remote", 3, 6, NULL, pre_get_info, cmd_add_mcast_remote, NULL,
      "", RW},
     {"del-mcast-remote", 3, 4, NULL, pre_get_info, cmd_del_mcast_remote, NULL,
      "", RW},
diff --git a/vtep/vtep.ovsschema b/vtep/vtep.ovsschema
index 3a24318..35c3fd2 100644
--- a/vtep/vtep.ovsschema
+++ b/vtep/vtep.ovsschema
@@ -1,6 +1,6 @@
 {
   "name": "hardware_vtep",
-  "cksum": "353943336 11434",
+  "cksum": "2728111540 11603",
   "tables": {
     "Global": {
       "columns": {
@@ -209,7 +209,12 @@
               "type": "string"}},
           "mutable": false},
         "dst_ip": {"type": "string", "mutable": false},
-        "tunnel_key": {"type": {"key": "integer", "min": 0, "max": 1}}},
+        "tunnel_key": {"type": {"key": "integer", "min": 0, "max": 1}},
+        "tunnel_level": {
+          "type": {
+           "key": {
+            "enum": ["set", ["level0", "level1"]],
+            "type": "string"},"min": 0, "max": 1}}},
       "indexes": [["encapsulation_type", "dst_ip", "tunnel_key"]]},
     "ACL_entry": {
       "columns": {
diff --git a/vtep/vtep.xml b/vtep/vtep.xml
index 62075ca..0d255e7 100644
--- a/vtep/vtep.xml
+++ b/vtep/vtep.xml
@@ -1174,6 +1174,18 @@
       </p>
     </column>
 
+    <column name="tunnel_level">
+      <p>
+        For <code>vxlan_over_ipv4</code> encapsulation, represents the
+        hierarchy level of the <ref table="Physical_Locator"/>.
+        Broadcast, unknown unicast and multicast (BUM) traffic received
+        at one level is never sent to another <ref table="Physical_Locator"/>
+        of the same level.  The only valid values supported are level0 and
+        level1; this column is optional and the default value if not
+        configured is level0.
+      </p>
+    </column>
+
   </table>
   <table name="ACL_entry">
     <p>
-- 
1.9.1




More information about the dev mailing list