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

Ben Pfaff blp at ovn.org
Wed Jul 27 20:42:19 UTC 2016


Justin, are you the best person to review this (when you're back from
vacation)?

Thanks,

Ben.

On Sun, Jul 24, 2016 at 03:01:00PM +0300, itamaro wrote:
> From: itamaro <itamar.ofeq at gmail.com>
> 
> This patch adds support for handeling a per-tunnel tunnel key in the
> ovs-vtep and vtep-ctl to support the usage of neutron L2GW as an
> inter-cloud gateway.
> 
> The Neutron spec is available here:
> https://review.openstack.org/#/c/270786/
> 
> 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. This document will also explain the logic behind the addition of the 
> new per-tunnel tunnel-key in the hardware_vtep schema.  
> 
> The introduction of the relay tunnel, does not change the current logic of 
> hardware_vtep, it does however introduce new logic related to iner-cloud
> connectivity.
> 
> 
> Network layout
> ==============
> 
>     virtual network 1                 shared  network         virtual network 2 
>     +------------+                                                  +------------+
>     |Compute Host|   VNI=1                                    VNI=2 |Compute Host|
>     |   +--+     <---------+                                +------->   +--+     |
>     |   |vm|     |         |                                |       |   |vm|     |
>     |   +--+     |         |           L3 network           |       |   +--+     |
>     +---^--------+         |                                |       +---------^--+
>         |          +-------v--------+      X     +----------v-----+           |   
>         |      +---> hardware_vtep  |      X     | hardware_vtep  |           |   
>         | VNI=1|   | logical switch |      X     | logical switch <-----+     |   
>         |      |   | (tunnel_key 1) |==<<==X=>>==| (tunnel_key 2) |     |VNI=2|   
>         |      |   |   +-+     +-+  |      X     |   +-+      +-+ |     |     |   
>         |      |   |   |-|     |-|  |      X     |   |-|      |-| |     |     |   
>     +---v------v-+ +----------------+      X     +----------------+     |     |   
>     |Compute Host| vlan2|       |vlan5           vlan9|        |vlan21  |     |   
>     |   +--+     |      |       |    relay vxlan      |        |    +---v-----v--+
>     |   |vm|     |      |       |      VNI=100        |        |    |Compute Host|
>     |   +--+     |      |       |                     |        |    |   +--+     |
>     +------------+    +-v-+   +-v-+                 +-v-+    +-v-+  |   |vm|     |
>                       |   |   |   |                 |   |    |   |  |   +--+     |
>                       |   |   |   |                 |   |    |   |  +------------+
>                       +---+   +---+                 +---+    +---+                
>                     Bare metal elements             Bare metal elements
> 
> Logical switch
> ===============
> In a cloud architecture, there is sometimes need to connect virtual machines
> and physical machines to the same L2 broadcast domain.
> A logical switch is an entity representing an l2 virtual overlay network,
> identified by a shared tunnel key. This tunnel key (VxLAN VNI) is shared among
> all overlay virtual tunnel endpoints (VTEP) of the switch.
> The logical switch binds physical ports with either identical or different
> "VLAN" tags to the "VxLAN overlay" network.
> 
> In a multi-cloud architecture, it may be useful to establish a cross-cloud 
> l2 broadcast domain. The extended hardware vtep uses a relay l2 tunnel,
> which is a tunnel with an explicit tunnel-key property. The tunnel-key propery 
> is used to map each overlay network (logical switch tunnel-key) in each cloud to
> the tunnel-key of the relay tunnel.
> 
> The mapping to a remote logical switch is done by defining the same tunnel key
> in both ends of the the relay tunnel. This tunnel key (VxLAN VNI) is a
> property of the relay tunnel itself.
> 
> To support the above tunnel behevior, a new kind of VTEP port is logic is
> introduced, defining two VTEP port groups. One group represents the existing
> VTEP ports of the local l2 overlay network, and another new group represents the
> individual l2 relay VTEPS.
> 
> Multicast and Unknown unicast traffic
> =====================================
> Currently Broadcast, Unknown unicast, and Multicast,"BUM" traffic to the overlay networks
> is handled by two replication modes:
> 
>   - "source_node" mode: The packets originated from physical port
>     are replicated on all the VTEPs ports pointed by unknown-dst, and flooded
>     to all the physical bound ports.
> 
>   - "service_node" mode: The packets originated from physical port are
>     forwarded to only a selected single service node from the unknown-dst ports
>     (the service node responsible for "BUM" propagation to the overlay network),
>     and flooded to all the physical bound ports.
> 
> In either of the replication modes BUM traffic originated from a VTEP port is
> flooded only to all physical ports.
> 
> Considering the new l2-relay VTEPs ports group, relay related BUM traffic is 
> handled as follows:
>   - BUM packets from Physical Port and from local overlay network are replicated
>     to the unknown-dst l2-relay ports. 
>        The reason is that a relay VTEP is not a part of the local managed
>        network and BUM traffic to the relay VTEPs cannot be suppressed by a
>        local service node.
>   - BUM packets from relay VTEPs are handled according to the replicating mode
>     and not forwarded/replicated to the l2-relay ports.
>        It is assumed that relay tunnels do not interconnect remote networks.
> 
> To sum it up, the role of the l2-relay is merely to connect two distinct 
> broadcast domains, it will otherwise never be used as a switching fabric among
> the different remote l2 networks.
> 
> ovs-vtep manifested changes
> ===========================
> 
> 1. The code need to distinguish between overlay (mesh) VTEPs, and relay VTEPs.
> 2. BUM traffic
>     * BUM traffic from either mesh or bare metal network is replicated on all
>       relay 'unknown-dst' VTEP.
>     * BUM traffic from relay VTEP, is handled according to the replicating mode
>       and is not forwarded/replicated to the l2-relay ports.
> 
> 
> Requested-by: "Ofer Ben-Yacov" <ofer.benyacov at gmail.com>
> Signed-off-by: "Itamar Ofek" <itamar.ofeq at gmail.com>
> ---
>  tests/vtep-ctl.at | 145 +++++++++++++++++++++++++++++++++++++++++++++++-------
>  vtep/ovs-vtep     | 102 +++++++++++++++++++++++++-------------
>  vtep/vtep-ctl.c   | 138 ++++++++++++++++++++++++++++++++++-----------------
>  3 files changed, 286 insertions(+), 99 deletions(-)
> 
> diff --git a/tests/vtep-ctl.at b/tests/vtep-ctl.at
> index f0511ad..4178309 100644
> --- a/tests/vtep-ctl.at
> +++ b/tests/vtep-ctl.at
> @@ -433,12 +433,16 @@ 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])
>  ], [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]]
>  
>  mcast-mac-local
>  
> @@ -460,11 +464,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: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])
>  ], [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]]
>  
>  mcast-mac-local
>  
> @@ -480,22 +493,28 @@ 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])
>  ], [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]]
>  
>  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])
>  ], [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 +530,16 @@ 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])
>  ], [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]]
>  
>  mcast-mac-remote
>  
> @@ -538,11 +561,14 @@ 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])
>  ], [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]]
>  
>  mcast-mac-remote
>  
> @@ -558,22 +584,28 @@ 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])
>  ], [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]]
>  
>  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])
>  ], [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 +622,19 @@ 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-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])
>  ], [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]]
>  
>  mcast-mac-local
>  
> @@ -605,6 +643,8 @@ 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]]
>  
>  mcast-mac-remote
>  
> @@ -621,7 +661,9 @@ 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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
>     [ucast-mac-local
> @@ -630,6 +672,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.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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
> @@ -651,7 +695,9 @@ 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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
>     [ucast-mac-local
> @@ -661,10 +707,13 @@ 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]]
>  
>  ], [], [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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
>     [ucast-mac-local
> @@ -673,6 +722,7 @@ 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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  VTEP_CTL_CLEANUP
> @@ -687,7 +737,10 @@ 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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
>     [ucast-mac-remote
> @@ -696,6 +749,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.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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
> @@ -717,7 +773,10 @@ 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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
>     [ucast-mac-remote
> @@ -727,10 +786,14 @@ 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]]
>  
>  ], [], [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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
>     [ucast-mac-remote
> @@ -739,6 +802,8 @@ 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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  VTEP_CTL_CLEANUP
> @@ -756,7 +821,13 @@ 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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
>     [ucast-mac-local
> @@ -765,6 +836,9 @@ 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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
> @@ -774,7 +848,10 @@ mcast-mac-remote
>    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
>  AT_CLEANUP
> @@ -793,7 +870,13 @@ 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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
>     [ucast-mac-local
> @@ -803,6 +886,9 @@ 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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
> @@ -813,6 +899,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.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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL(
> @@ -831,6 +920,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.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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  VTEP_CTL_CLEANUP
> @@ -850,7 +942,13 @@ 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])
>  ], [0], [], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-local-macs ls1])], [0],
>     [ucast-mac-local
> @@ -860,6 +958,9 @@ 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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL([list-remote-macs ls1])], [0],
> @@ -870,6 +971,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.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]]
>  
>  ], [], [VTEP_CTL_CLEANUP])
>  AT_CHECK([RUN_VTEP_CTL(
> @@ -882,6 +986,9 @@ 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]]
>  
>  ], [], [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..360f9fd 100755
> --- a/vtep/ovs-vtep
> +++ b/vtep/ovs-vtep
> @@ -120,30 +120,52 @@ 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):
> +        relay_ports, mesh_ports = list(), list()
> +        for tunnel in tunnel_list:
> +            if self.tunnels[tunnel][3]:
> +                relay_ports.append(self.tunnels[tunnel][0])
> +                continue
> +            mesh_ports.append(self.tunnels[tunnel][0])
> +        return relay_ports, mesh_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())
> +        relay_ports, mesh_ports = self.vtep_ports(self.tunnels.keys())
> +        relay_unknown, mesh_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 relay VTEP ports.
> +        # If the 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 + relay_unknown
> +        if len(mesh_unknown) > 0:
>              if self.replication_mode == "service_node":
> -                break
> +                phy_flood_ports += mesh_unknown[0]
> +            else:
> +                phy_flood_ports += mesh_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)))
> +
> +        # Traffic flowing from a mesh VTEP should not be flooded to mesh
> +        # unknown-dst ports
> +        mesh_flood_ports = phy_ports + relay_unknown
> +        for port_no in mesh_ports:
> +            ovs_ofctl("add-flow %s table=1,priority=1,in_port=%s,action=%s"
> +                      % (self.short_name, port_no, ",".join(mesh_flood_ports)))
>  
> -        ovs_ofctl("add-flow %s table=1,priority=0,action=%s"
> -                  % (self.short_name, ",".join(flood_ports)))
> +        # Traffic flowing from a relay VTEP should not be flooded to relay
> +        # unknown-dst ports
> +        relay_flood_ports = phy_ports + mesh_unknown
> +        for port_no in relay_ports:
> +            ovs_ofctl("add-flow %s table=1,priority=1,in_port=%s,action=%s"
> +                      % (self.short_name,
> +                          port_no, ",".join(relay_flood_ports)))
>  
>      def add_lbinding(self, lbinding):
>          vlog.info("adding %s binding to %s" % (lbinding, self.name))
> @@ -164,11 +186,22 @@ class Logical_Switch(object):
>          del self.ports[lbinding]
>          self.update_flood()
>  
> +    def tunnel_dict(self, entry):
> +        return {
> +                'tunnel_type': entry[2],
> +                'dest_ip': entry[3],
> +                'tunnel_key': entry[5],
> +               }
> +
>      def add_tunnel(self, tunnel, tunnel_key):
>          global tun_id
> -        vlog.info("adding tunnel %s" % tunnel)
> -        encap, ip = tunnel.split("/")
> +        if tunnel['tunnel_key']:
> +            tunnel_key = tunnel['tunnel_key']
> +        vlog.info("adding tunnel %s key %s" % (tunnel['dest_ip'],
> +                   tunnel_key))
>  
> +        encap = tunnel['tunnel_type']
> +        ip = tunnel['dest_ip']
>          if encap != "vxlan_over_ipv4":
>              vlog.warn("unsupported tunnel format %s" % encap)
>              return
> @@ -192,7 +225,7 @@ class Logical_Switch(object):
>              # 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['tunnel_key'])
>  
>          add_bfd(ip)
>  
> @@ -200,17 +233,17 @@ 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 = 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 +264,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 +278,7 @@ class Logical_Switch(object):
>      def update_remote_macs(self):
>          remote_macs = {}
>          unknown_dsts = set()
> -        tunnels = set()
> +        tunnels = {}
>          parse_ucast = True
>  
>          column = vtep_ctl("--columns=tunnel_key find logical_switch "
> @@ -264,27 +297,26 @@ 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*)( \[(.*)\])?', line)
> +            if len(entry) != 7:
>                  continue
>  
>              if parse_ucast:
> -                remote_macs[entry[1]] = entry[2]
> +                remote_macs[entry[1]] = self.tunnel_dict(entry)['tunnel_type']
>              else:
>                  if entry[1] != "unknown-dst":
>                      continue
>  
> -                unknown_dsts.add(entry[2])
> +                unknown_dsts.add(entry[3])
>  
> -            tunnels.add(entry[2])
> +            tunnels[entry[3]] = self.tunnel_dict(entry)
>  
>          old_tunnels = set(self.tunnels.keys())
> +        tunnels_keys = set(tunnels.keys())
> +        for tunnel in tunnels_keys.difference(old_tunnels):
> +            self.add_tunnel(tunnels[tunnel], tunnel_key)
>  
> -        for tunnel in tunnels.difference(old_tunnels):
> -            self.add_tunnel(tunnel, tunnel_key)
> -
> -        for tunnel in old_tunnels.difference(tunnels):
> +        for tunnel in old_tunnels.difference(tunnels_keys):
>              self.del_tunnel(tunnel)
>  
>          for mac in six.iterkeys(remote_macs):
> diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c
> index 759150f..1904a71 100644
> --- a/vtep/vtep-ctl.c
> +++ b/vtep/vtep-ctl.c
> @@ -37,6 +37,7 @@
>  #include "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]   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]   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]  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]  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\
> @@ -887,7 +888,8 @@ 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_tunnel_col_local);
>      ovsdb_idl_add_column(ctx->idl, &vteprec_tunnel_col_remote);
>  }
> @@ -1653,27 +1655,46 @@ 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;
> +    const char *mac = 0;
> +    const char *encap = 0;
> +    const char *dst_ip = 0;
> +    const char *tunnel_key = 0;
>      struct vteprec_physical_locator *ploc_cfg;
> +    ovs_be32 ip = 0;
>  
>      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];
> +    switch (ctx->argc)
> +    {
> +        case 6:
> +            tunnel_key = ctx->argv[5];
> +        case 5:
> +            if (ip_parse(ctx->argv[4],&ip)){
> +                dst_ip = ctx->argv[4];
> +                encap = ctx->argv[3];
> +                break;
> +            }
> +            tunnel_key = ctx->argv[4];
> +        case 4:
> +            if (ip_parse(ctx->argv[3],&ip)){
> +                dst_ip = ctx->argv[3];
> +                encap = "vxlan_over_ipv4";
> +            }
> +            break;
> +        default:
> +            break;
>      }
>  
>      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 segement_value = 0;
> +            ovs_scan(tunnel_key,"%ld",&segement_value);
> +            vteprec_physical_locator_set_tunnel_key(ploc_cfg,&segement_value,1);
> +        }
>          vteprec_physical_locator_set_dst_ip(ploc_cfg, dst_ip);
>          vteprec_physical_locator_set_encapsulation_type(ploc_cfg, encap);
>  
> @@ -1790,7 +1811,7 @@ 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,bool local)
>  {
>      struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
>      struct shash *mcast_shash;
> @@ -1839,6 +1860,11 @@ 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_id = 0;
> +            ovs_scan(tunnel_key,"%ld",&tunnel_id);
> +            vteprec_physical_locator_set_tunnel_key(ploc_cfg,&tunnel_id,1);
> +        }
>          vteprec_physical_locator_set_dst_ip(ploc_cfg, dst_ip);
>          vteprec_physical_locator_set_encapsulation_type(ploc_cfg, encap);
>  
> @@ -1908,25 +1934,39 @@ 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;
> -
> +    const char *mac = 0;
> +    const char *encap = 0;
> +    const char *dst_ip = 0;
> +    const char *tunnel_key = 0;
> +    ovs_be32 ip = 0;
>      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];
> +    switch (ctx->argc)
> +    {
> +        case 6:
> +            tunnel_key = ctx->argv[5];
> +        case 5:
> +            if (ip_parse(ctx->argv[4],&ip)){
> +                dst_ip = ctx->argv[4];
> +                encap = ctx->argv[3];
> +                break;
> +            }
> +            tunnel_key = ctx->argv[4];
> +        case 4:
> +            if (ip_parse(ctx->argv[3],&ip)){
> +                dst_ip = ctx->argv[3];
> +                encap = "vxlan_over_ipv4";
> +            }
> +            break;
> +        default:
> +            break;
>      }
>  
>      if (add) {
> -        add_mcast_entry(ctx, ls, mac, encap, dst_ip, local);
> +        add_mcast_entry(ctx, ls, mac, encap, dst_ip, tunnel_key, local);
>      } else {
>          del_mcast_entry(ctx, ls, mac, encap, dst_ip, local);
>      }
> @@ -2017,7 +2057,7 @@ list_macs(struct ctl_context *ctx, bool local)
>      struct svec ucast_macs;
>      struct shash *mcast_shash;
>      struct svec mcast_macs;
> -
> +    char tunnel_key[8];
>      vtep_ctl_context_populate_cache(ctx);
>      ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
>  
> @@ -2032,9 +2072,13 @@ 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],8," [%d]",(uint32_t)(*ploc_cfg->tunnel_key));
> +        entry = xasprintf("  %s -> %s/%s%s", node->name,
> +                          ploc_cfg->encapsulation_type,
> +                          ploc_cfg->dst_ip,
> +                          tunnel_key );
>          svec_add_nocopy(&ucast_macs, entry);
>      }
>      ds_put_format(&ctx->output, "ucast-mac-%s\n", local ? "local" : "remote");
> @@ -2049,9 +2093,13 @@ 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,8," [%d]",(uint32_t)(*ploc->ploc_cfg->tunnel_key));
> +            entry = xasprintf("  %s -> %s/%s%s", node->name,
>                                ploc->ploc_cfg->encapsulation_type,
> -                              ploc->ploc_cfg->dst_ip);
> +                              ploc->ploc_cfg->dst_ip,
> +                              tunnel_key);
>              svec_add_nocopy(&mcast_macs, entry);
>          }
>      }
> @@ -2508,11 +2556,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, 5, 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, 5, 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 +2568,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, 5, 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, 5, 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},
> -- 
> 1.9.1
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev




More information about the dev mailing list