ovn-controller: Support VXLAN enapsulation.
authorJustin Pettit <jpettit@nicira.com>
Thu, 8 Oct 2015 19:58:48 +0000 (12:58 -0700)
committerJustin Pettit <jpettit@nicira.com>
Fri, 16 Oct 2015 07:54:38 +0000 (00:54 -0700)
Signed-off-by: Justin Pettit <jpettit@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
ovn/controller/encaps.c
ovn/controller/ovn-controller.8.xml
ovn/controller/physical.c
ovn/ovn-architecture.7.xml

index c914e2a..de1aef3 100644 (file)
@@ -214,10 +214,11 @@ preferred_encap(const struct sbrec_chassis *chassis_rec)
 
     /* For hypervisors, we only support Geneve and STT encapsulations.
      * Sets are returned alphabetically, so "geneve" will be preferred
-     * over "stt". */
+     * over "stt".  For gateways, we only support VXLAN encapsulation. */
     for (i = 0; i < chassis_rec->n_encaps; i++) {
         if (!strcmp(chassis_rec->encaps[i]->type, "geneve")
-                || !strcmp(chassis_rec->encaps[i]->type, "stt")) {
+                || !strcmp(chassis_rec->encaps[i]->type, "stt")
+                || !strcmp(chassis_rec->encaps[i]->type, "vxlan")) {
             return chassis_rec->encaps[i];
         }
     }
index 3909b9d..4aaf97b 100644 (file)
 
       <dt><code>external_ids:ovn-encap-type</code></dt>
       <dd>
-        The encapsulation type that a chassis should use to connect to this
-        node.  Supported tunnel types for connecting hypervisors are
-        <code>geneve</code> and <code>stt</code>.  Gateways may use
-        <code>geneve</code>, <code>vxlan</code>, or <code>stt</code>.
+        <p>
+          The encapsulation type that a chassis should use to connect to
+          this node.  Supported tunnel types for connecting hypervisors
+          are <code>geneve</code> and <code>stt</code>.  Gateways may
+          use <code>geneve</code>, <code>vxlan</code>, or
+          <code>stt</code>.
+        </p>
+
+        <p>
+          Due to the limited amount of metadata in <code>vxlan</code>,
+          the capabilities and performance of connected gateways will be
+          reduced versus other tunnel formats.
+        </p>
       </dd>
 
       <dt><code>external_ids:ovn-encap-ip</code></dt>
index 630d420..17fa635 100644 (file)
@@ -54,7 +54,7 @@ struct chassis_tunnel {
     struct hmap_node hmap_node;
     const char *chassis_id;
     ofp_port_t ofport;
-    enum chassis_tunnel_type { GENEVE, STT } type;
+    enum chassis_tunnel_type { GENEVE, STT, VXLAN } type;
 };
 
 static struct chassis_tunnel *
@@ -120,6 +120,8 @@ put_encapsulation(enum mf_field_id mff_ovn_geneve,
         put_load(datapath->tunnel_key | (outport << 24), 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);
     } else {
         OVS_NOT_REACHED();
     }
@@ -182,6 +184,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
                     }
                 } else if (!strcmp(iface_rec->type, "stt")) {
                     tunnel_type = STT;
+                } else if (!strcmp(iface_rec->type, "vxlan")) {
+                    tunnel_type = VXLAN;
                 } else {
                     continue;
                 }
@@ -588,11 +592,14 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
     /* Table 0, priority 100.
      * ======================
      *
-     * For packets that arrive from a remote hypervisor (by matching a tunnel
-     * in_port), 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. */
-
+     * 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. */
     struct chassis_tunnel *tun;
     HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
         struct match match = MATCH_CATCHALL_INITIALIZER;
@@ -609,14 +616,53 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
             put_move(MFF_TUN_ID, 40, MFF_LOG_INPORT,   0, 15, &ofpacts);
             put_move(MFF_TUN_ID, 24, MFF_LOG_OUTPORT,  0, 16, &ofpacts);
             put_move(MFF_TUN_ID,  0, MFF_LOG_DATAPATH, 0, 24, &ofpacts);
+        } else if (tun->type == VXLAN) {
+            /* We'll handle VXLAN later. */
+            continue;
         } else {
             OVS_NOT_REACHED();
         }
+
         put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts);
 
         ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, &match, &ofpacts);
     }
 
+    /* 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.
+     *
+     * xxx Due to resubmitting to table 16, broadcasts will be re-sent to
+     * xxx all logical ports, including non-local ones which could cause
+     * xxx duplicate packets to be received by multiply-connected gateways. */
+    HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
+        if (tun->type != VXLAN) {
+            continue;
+        }
+
+        SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
+            struct match match = MATCH_CATCHALL_INITIALIZER;
+
+            if (!binding->chassis ||
+                strcmp(tun->chassis_id, binding->chassis->name)) {
+                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);
+            put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts);
+
+            ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, &match,
+                    &ofpacts);
+        }
+    }
+
     /* Table 32, Priority 0.
      * =======================
      *
index f5b8440..7b540d2 100644 (file)
 
     <dt>logical input port field</dt>
     <dd>
-      A field that denotes the logical port from which the packet
-      entered the logical datapath.
-      <!-- Keep the following in sync with MFF_LOG_INPORT in
-           ovn/controller/lflow.h. -->
-      OVN stores this in Nicira extension register number 6.  (This field is
-      passed across tunnels as part of the tunnel key.)
+      <p>
+        A field that denotes the logical port from which the packet
+        entered the logical datapath.
+        <!-- Keep the following in sync with MFF_LOG_INPORT in
+             ovn/controller/lflow.h. -->
+        OVN stores this in Nicira extension register number 6.
+      </p>
+
+      <p>
+        Geneve and STT tunnels pass this field as part of the tunnel key.
+        Although VXLAN tunnels do not explicitly carry a logical input port,
+        OVN only uses VXLAN to communicate with gateways that from OVN's
+        perspective consist of only a single logical port, so that OVN can set
+        the logical input port field to this one on ingress to the OVN logical
+        pipeline.
+      </p>
     </dd>
 
     <dt>logical output port field</dt>
     <dd>
-      A field that denotes the logical port from which the packet will
-      leave the logical datapath.  This is initialized to 0 at the
-      beginning of the logical ingress pipeline.
-      <!-- Keep the following in sync with MFF_LOG_OUTPORT in
-           ovn/controller/lflow.h. -->
-      OVN stores this in
-      Nicira extension register number 7.  (This field is passed across
-      tunnels as part of the tunnel key.)
+      <p>
+        A field that denotes the logical port from which the packet will
+        leave the logical datapath.  This is initialized to 0 at the
+        beginning of the logical ingress pipeline.
+        <!-- Keep the following in sync with MFF_LOG_OUTPORT in
+             ovn/controller/lflow.h. -->
+        OVN stores this in Nicira extension register number 7.
+      </p>
+
+      <p>
+        Geneve and STT tunnels pass this field as part of the tunnel key.
+        VXLAN tunnels do not transmit the logical output port field.
+      </p>
     </dd>
 
     <dt>conntrack zone field</dt>