[ovs-dev] [PATCH RFC ovn] Add VXLAN support for non-VTEP datapath bindings

Ihar Hrachyshka ihrachys at redhat.com
Fri Mar 20 05:07:11 UTC 2020


Hello,

this patch is not ready, sending it to collect initial feedback on the
path taken. Let me know.

Because of limited space in VXLAN VNI to pass over all three of -
datapath id, ingress port, egress port - the implementation ignores
ingress; and splits the remaining 24 bits of VNI into two chunks, 12
bits each - one for datapath and one for egress port.

Limitations: because ingress port is not passed, ACLs that rely on it
won't work with VXLAN; reduced number of networks and ports per
network (max 4096 for both).

Renamed MLF_RCV_FROM_VXLAN_BIT into MLF_RCV_FROM_VTEP_BIT to reflect
the new use case.

TODO:
* limit maximum number of networks / ports per network for vxlan
  datapaths.
* forbid acls matching against ingress port for vxlan datapaths.
* update test suite.
* update documentation.

Signed-off-by: Ihar Hrachyshka <ihrachys at redhat.com>
---
 controller/physical.c        | 81 ++++++++++++++++++++++--------------
 include/ovn/logical-fields.h | 10 ++---
 2 files changed, 55 insertions(+), 36 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index 144aeb7bd..28f639480 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -180,7 +180,8 @@ static void
 put_encapsulation(enum mf_field_id mff_ovn_geneve,
                   const struct chassis_tunnel *tun,
                   const struct sbrec_datapath_binding *datapath,
-                  uint16_t outport, struct ofpbuf *ofpacts)
+                  uint16_t outport, bool is_vtep,
+                  struct ofpbuf *ofpacts)
 {
     if (tun->type == GENEVE) {
         put_load(datapath->tunnel_key, MFF_TUN_ID, 0, 24, ofpacts);
@@ -191,7 +192,10 @@ put_encapsulation(enum mf_field_id mff_ovn_geneve,
                  MFF_TUN_ID, 0, 64, ofpacts);
         put_move(MFF_LOG_INPORT, 0, MFF_TUN_ID, 40, 15, ofpacts);
     } else if (tun->type == VXLAN) {
-        put_load(datapath->tunnel_key, MFF_TUN_ID, 0, 24, ofpacts);
+        uint64_t vni = (is_vtep?
+                        datapath->tunnel_key :
+                        datapath->tunnel_key | ((uint64_t) outport << 12));
+        put_load(vni, MFF_TUN_ID, 0, 24, ofpacts);
     } else {
         OVS_NOT_REACHED();
     }
@@ -323,8 +327,9 @@ put_remote_port_redirect_overlay(const struct
         if (!rem_tun) {
             return;
         }
-        put_encapsulation(mff_ovn_geneve, tun, binding->datapath,
-                          port_key, ofpacts_p);
+        put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key,
+                          !strcmp(binding->type, "vtep"),
+                          ofpacts_p);
         /* Output to tunnel. */
         ofpact_put_OUTPUT(ofpacts_p)->port = rem_tun->ofport;
     } else {
@@ -360,8 +365,9 @@ put_remote_port_redirect_overlay(const struct
             return;
         }
 
-        put_encapsulation(mff_ovn_geneve, tun, binding->datapath,
-                          port_key, ofpacts_p);
+        put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key,
+                          !strcmp(binding->type, "vtep"),
+                          ofpacts_p);
 
         /* Output to tunnels with active/backup */
         struct ofpact_bundle *bundle = ofpact_put_BUNDLE(ofpacts_p);
@@ -1364,7 +1370,7 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve,
 
             if (!prev || tun->type != prev->type) {
                 put_encapsulation(mff_ovn_geneve, tun, mc->datapath,
-                                  mc->tunnel_key, &remote_ofpacts);
+                                  mc->tunnel_key, true, &remote_ofpacts);
                 prev = tun;
             }
             ofpact_put_OUTPUT(&remote_ofpacts)->port = tun->ofport;
@@ -1609,11 +1615,12 @@ physical_run(struct physical_ctx *p_ctx,
      * Process packets that arrive from a remote hypervisor (by matching
      * on tunnel in_port). */
 
-    /* Add flows for Geneve and STT encapsulations.  These
-     * encapsulations have metadata about the ingress and egress logical
-     * ports.  We set MFF_LOG_DATAPATH, MFF_LOG_INPORT, and
-     * MFF_LOG_OUTPORT from the tunnel key data, then resubmit to table
-     * 33 to handle packets to the local hypervisor. */
+    /* Add flows for Geneve, STT and non-VTEP VXLAN encapsulations.  Geneve and
+     * STT encapsulations have metadata about the ingress and egress logical
+     * ports.  Non-VTEP VXLAN encapsulations have metadata about the egress
+     * logical port only. We set MFF_LOG_DATAPATH, MFF_LOG_INPORT, and
+     * MFF_LOG_OUTPORT from the tunnel key data where possible, then resubmit
+     * to table 33 to handle packets to the local hypervisor. */
     HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
         struct match match = MATCH_CATCHALL_INITIALIZER;
         match_set_in_port(&match, tun->ofport);
@@ -1642,11 +1649,7 @@ physical_run(struct physical_ctx *p_ctx,
                         &ofpacts, hc_uuid);
     }
 
-    /* Add flows for VXLAN encapsulations.  Due to the limited amount of
-     * metadata, we only support VXLAN for connections to gateways.  The
-     * VNI is used to populate MFF_LOG_DATAPATH.  The gateway's logical
-     * port is set to MFF_LOG_INPORT.  Then the packet is resubmitted to
-     * table 16 to determine the logical egress port. */
+    /* Handle VXLAN encapsulations. */
     HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
         if (tun->type != VXLAN) {
             continue;
@@ -1662,20 +1665,36 @@ physical_run(struct physical_ctx *p_ctx,
                 continue;
             }
 
-            match_set_in_port(&match, tun->ofport);
-            match_set_tun_id(&match, htonll(binding->datapath->tunnel_key));
-
-            ofpbuf_clear(&ofpacts);
-            put_move(MFF_TUN_ID, 0,  MFF_LOG_DATAPATH, 0, 24, &ofpacts);
-            put_load(binding->tunnel_key, MFF_LOG_INPORT, 0, 15, &ofpacts);
-            /* For packets received from a vxlan tunnel, set a flag to that
-             * effect. */
-            put_load(1, MFF_LOG_FLAGS, MLF_RCV_FROM_VXLAN_BIT, 1, &ofpacts);
-            put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts);
-
-            ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100,
-                            binding->header_.uuid.parts[0],
-                            &match, &ofpacts, hc_uuid);
+            if (!strcmp(binding->type, "vtep")) {
+                /* Add flows for VTEP encapsulations.  The VNI is used to
+                 * populate MFF_LOG_DATAPATH.  The gateway's logical port is
+                 * set to MFF_LOG_INPORT.  Then the packet is resubmitted to
+                 * table 8 to determine the logical egress port. */
+                match_set_in_port(&match, tun->ofport);
+                match_set_tun_id(&match,
+                                 htonll(binding->datapath->tunnel_key));
+
+                ofpbuf_clear(&ofpacts);
+                put_move(MFF_TUN_ID, 0,  MFF_LOG_DATAPATH, 0, 24, &ofpacts);
+                put_load(binding->tunnel_key, MFF_LOG_INPORT, 0, 15, &ofpacts);
+                /* For packets received from a VTEP tunnel, set a flag to that
+                 * effect. */
+                put_load(1, MFF_LOG_FLAGS, MLF_RCV_FROM_VTEP_BIT, 1, &ofpacts);
+                put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts);
+
+                ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100,
+                                binding->header_.uuid.parts[0],
+                                &match, &ofpacts, hc_uuid);
+            } else {
+                /* Add flows for non-VTEP tunnels. Split VNI into two 12-bit
+                 * sections and use them for datapath and outport IDs. */
+                put_move(MFF_TUN_ID, 12, MFF_LOG_OUTPORT,  0, 12, &ofpacts);
+                put_move(MFF_TUN_ID, 0, MFF_LOG_DATAPATH, 0, 12, &ofpacts);
+
+                put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts);
+                ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, 0,
+                                &match, &ofpacts, hc_uuid);
+            }
         }
     }
 
diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
index c7bd2dba9..c5a25b07d 100644
--- a/include/ovn/logical-fields.h
+++ b/include/ovn/logical-fields.h
@@ -51,7 +51,7 @@ void ovn_init_symtab(struct shash *symtab);
 /* MFF_LOG_FLAGS_REG bit assignments */
 enum mff_log_flags_bits {
     MLF_ALLOW_LOOPBACK_BIT = 0,
-    MLF_RCV_FROM_VXLAN_BIT = 1,
+    MLF_RCV_FROM_VTEP_BIT = 1,
     MLF_FORCE_SNAT_FOR_DNAT_BIT = 2,
     MLF_FORCE_SNAT_FOR_LB_BIT = 3,
     MLF_LOCAL_ONLY_BIT = 4,
@@ -64,11 +64,11 @@ enum mff_log_flags {
     /* Allow outputting back to inport. */
     MLF_ALLOW_LOOPBACK = (1 << MLF_ALLOW_LOOPBACK_BIT),
 
-    /* Indicate that a packet was received from a VXLAN tunnel to
+    /* Indicate that a packet was received from a VTEP tunnel to
      * compensate for the lack of egress port information available in
-     * VXLAN encapsulation.  Egress port information is available for
-     * Geneve and STT tunnel types. */
-    MLF_RCV_FROM_VXLAN = (1 << MLF_RCV_FROM_VXLAN_BIT),
+     * VTEP encapsulation.  Egress port information is available for
+     * Geneve, STT and non-VTEP VXLAN tunnel types. */
+    MLF_RCV_FROM_VXLAN = (1 << MLF_RCV_FROM_VTEP_BIT),
 
     /* Indicate that a packet needs a force SNAT in the gateway router when
      * DNAT has taken place. */
-- 
2.24.1



More information about the dev mailing list