[ovs-dev] [PATCH ovn] ovn-controller: Add physical/logical translation for containers.

Gurucharan Shetty shettyg at nicira.com
Wed May 13 14:51:21 UTC 2015


When containers are running inside VMs and the openflow flows
are added in the hypervisor, the physical to logical translation
(and vice versa) needs to handle the VLAN tags that the packet
comes with.

Signed-off-by: Gurucharan Shetty <shettyg at nicira.com>
---
 ovn/controller/physical.c |   61 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c
index 593899d..71a24ac 100644
--- a/ovn/controller/physical.c
+++ b/ovn/controller/physical.c
@@ -96,9 +96,23 @@ physical_run(struct controller_ctx *ctx)
          * on a remote chassis, this is the OpenFlow port for the tunnel to
          * that chassis (and set 'local' to false).  Otherwise, if it's on the
          * chassis we're managing, this is the OpenFlow port for the vif itself
-         * (and set 'local' to true). */
-        ofp_port_t ofport = u16_to_ofp(simap_get(&lport_to_ofport,
-                                                 binding->logical_port));
+         * (and set 'local' to true). When 'parent_port' is set for a binding,
+         * it implies a container sitting inside a VM reachable via a 'tag'.
+         */
+
+        int tag = 0;
+        ofp_port_t ofport;
+        if (binding->parent_port) {
+            ofport = u16_to_ofp(simap_get(&lport_to_ofport,
+                                          binding->parent_port));
+            if (ofport) {
+                tag = *binding->tag;
+            }
+        } else {
+            ofport = u16_to_ofp(simap_get(&lport_to_ofport,
+                                          binding->logical_port));
+        }
+
         bool local = ofport != 0;
         if (!local) {
             ofport = u16_to_ofp(simap_get(&chassis_to_ofport,
@@ -122,10 +136,20 @@ physical_run(struct controller_ctx *ctx)
              *
              * For packets that arrive from a vif: set MFF_LOG_INPORT to the
              * logical input port, MFF_METADATA to the logical datapath, and
-             * resubmit into the logical pipeline starting at table 16. */
+             * resubmit into the logical pipeline starting at table 16.
+             *
+             * Containers sitting behind a vif, come with VLAN tags.
+             * Match on the tags and then strip it before resubmitting to
+             * the next tables. */
             match_init_catchall(&match);
             ofpbuf_clear(&ofpacts);
             match_set_in_port(&match, ofport);
+            if (tag) {
+                match_set_dl_vlan(&match, htons(tag));
+            } else {
+                match_set_dl_vlan(&match, htons(OFP10_VLAN_NONE));
+            }
+
 
             /* Set MFF_METADATA. */
             struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
@@ -139,6 +163,11 @@ physical_run(struct controller_ctx *ctx)
             sf->value.be32 = htonl(binding->tunnel_key);
             sf->mask.be32 = OVS_BE32_MAX;
 
+            /* Strip vlans. */
+            if (tag) {
+                ofpact_put_STRIP_VLAN(&ofpacts);
+            }
+
             /* Resubmit to first logical pipeline table. */
             struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts);
             resubmit->in_port = OFPP_IN_PORT;
@@ -149,10 +178,17 @@ physical_run(struct controller_ctx *ctx)
              * =====================
              *
              * For packets that arrive from a remote node destined to this
-             * local vif: deliver directly to the vif. */
+             * local vif: deliver directly to the vif. If the destination
+             * is a container sitting behind a vif, tag the packets. */
             match_init_catchall(&match);
             ofpbuf_clear(&ofpacts);
             match_set_tun_id(&match, htonll(binding->tunnel_key));
+            if (tag) {
+                struct ofpact_vlan_vid *vlan_vid;
+                vlan_vid = ofpact_put_SET_VLAN_VID(&ofpacts);
+                vlan_vid->vlan_vid = tag;
+                vlan_vid->push_vlan_if_needed = true;
+            }
             ofpact_put_OUTPUT(&ofpacts)->port = ofport;
             ofctrl_add_flow(0, 50, &match, &ofpacts);
         }
@@ -184,6 +220,21 @@ physical_run(struct controller_ctx *ctx)
             sf->value.be64 = htonll(binding->tunnel_key);
             sf->mask.be64 = OVS_BE64_MAX;
         }
+        if (tag) {
+            /* For containers sitting behind a local vif, tag the packets
+             * before delivering them. Since there is a possibility of
+             * packets needing to hair-pin back into the same vif from
+             * which it came, make the in_port as zero. */
+            struct ofpact_vlan_vid *vlan_vid;
+            vlan_vid = ofpact_put_SET_VLAN_VID(&ofpacts);
+            vlan_vid->vlan_vid = tag;
+            vlan_vid->push_vlan_if_needed = true;
+
+            struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
+            sf->field = mf_from_id(MFF_IN_PORT);
+            sf->value.be16 = 0;
+            sf->mask.be16 = OVS_BE16_MAX;
+        }
         ofpact_put_OUTPUT(&ofpacts)->port = ofport;
         ofctrl_add_flow(64, 50, &match, &ofpacts);
     }
-- 
1.7.9.5




More information about the dev mailing list