ofproto-dpif: Use megaflows.
authorJustin Pettit <jpettit@nicira.com>
Tue, 21 May 2013 00:48:49 +0000 (17:48 -0700)
committerJustin Pettit <jpettit@nicira.com>
Fri, 21 Jun 2013 01:00:54 +0000 (18:00 -0700)
The commit configures the masks generated from megaflows and pushes
them through the dpif layer.

With this commit and a wildcard supporting OVS kernel module,
ovs-vswitchd's flow setup rate is very close to that of the Linux
bridge.

Signed-off-by: Justin Pettit <jpettit@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
NEWS
PORTING
ofproto/ofproto-dpif.c

diff --git a/NEWS b/NEWS
index fe14f26..cd4fb05 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
 v1.11.0 - xx xxx xxxx
 ---------------------
+    - Support for megaflows, which allows wildcarding in the kernel (and
+      any dpif implementation that supports wildcards).  Depending on
+      the flow table and switch configuration, flow set up rates are
+      close to the Linux bridge.
     - The "tutorial" directory contains a new tutorial for some advanced
       Open vSwitch features.
     - Stable bond mode has been removed.
diff --git a/PORTING b/PORTING
index ffde296..53c19d3 100644 (file)
--- a/PORTING
+++ b/PORTING
@@ -148,9 +148,9 @@ depends on a few different factors:
 
     * A dpif provider is usually easier to implement, but most
       appropriate for software switching.  It "explodes" wildcard
-      rules into exact-match entries.  This allows fast hash lookups
-      in software, but makes inefficient use of TCAMs in hardware
-      that support wildcarding.
+      rules into exact-match entries (with an optional wildcard mask).
+      This allows fast hash lookups in software, but makes
+      inefficient use of TCAMs in hardware that support wildcarding.
 
 The following sections describe how to implement each kind of port.
 
@@ -175,18 +175,26 @@ Writing a dpif Provider
 
 Open vSwitch has a built-in ofproto provider named "ofproto-dpif",
 which is built on top of a library for manipulating datapaths, called
-"dpif".  A "datapath" is a simple flow table, one that supports only
-exact-match flows, that is, flows without wildcards.  When a packet
-arrives on a network device, the datapath looks for it in this
-exact-match table.  If there is a match, then it performs the
-associated actions.  If there is no match, the datapath passes the
-packet up to ofproto-dpif, which maintains an OpenFlow flow table
-(that supports wildcards).  If the packet matches in this flow table,
-then ofproto-dpif executes its actions and inserts a new exact-match
-entry into the dpif flow table.  (Otherwise, ofproto-dpif passes the
+"dpif".  A "datapath" is a simple flow table, one that is only required
+to support exact-match flows, that is, flows without wildcards.  When a
+packet arrives on a network device, the datapath looks for it in this
+table.  If there is a match, then it performs the associated actions.
+If there is no match, the datapath passes the packet up to ofproto-dpif,
+which maintains the full OpenFlow flow table.  If the packet matches in
+this flow table, then ofproto-dpif executes its actions and inserts a
+new entry into the dpif flow table.  (Otherwise, ofproto-dpif passes the
 packet up to ofproto to send the packet to the OpenFlow controller, if
 one is configured.)
 
+When calculating the dpif flow, ofproto-dpif generates an exact-match
+flow that describes the missed packet.  It makes an effort to figure out
+what fields can be wildcarded based on the switch's configuration and
+OpenFlow flow table.  The dpif is free to ignore the suggested wildcards
+and only support the exact-match entry.  However, if the dpif supports
+wildcarding, then it can use the masks to match multiple flows with
+fewer entries and potentially significantly reduce the number of flow
+misses handled by ofproto-dpif.
+
 The "dpif" library in turn delegates much of its functionality to a
 "dpif provider".  The following diagram shows how dpif providers fit
 into the Open vSwitch architecture:
index a3aa592..d881c47 100644 (file)
@@ -3550,6 +3550,9 @@ struct flow_miss_op {
     struct xlate_out xout;
     bool xout_garbage;           /* 'xout' needs to be uninitialized? */
 
+    struct ofpbuf mask;          /* Flow mask for "put" ops. */
+    struct odputil_keybuf maskbuf;
+
     /* If this is a "put" op, then a pointer to the subfacet that should
      * be marked as uninstalled if the operation fails. */
     struct subfacet *subfacet;
@@ -3650,6 +3653,7 @@ init_flow_miss_execute_op(struct flow_miss *miss, struct ofpbuf *packet,
     op->dpif_op.u.execute.key = miss->key;
     op->dpif_op.u.execute.key_len = miss->key_len;
     op->dpif_op.u.execute.packet = packet;
+    ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
 }
 
 /* Helper for handle_flow_miss_without_facet() and
@@ -3799,14 +3803,19 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet,
 
         subfacet->path = want_path;
 
+        ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
+        odp_flow_key_from_mask(&op->mask, &facet->xout.wc.masks,
+                               &miss->flow, UINT32_MAX);
+
         op->xout_garbage = false;
         op->dpif_op.type = DPIF_OP_FLOW_PUT;
         op->subfacet = subfacet;
         put->flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
         put->key = miss->key;
         put->key_len = miss->key_len;
-        put->mask = NULL;
-        put->mask_len = 0;
+        put->mask = op->mask.data;
+        put->mask_len = op->mask.size;
+
         if (want_path == SF_FAST_PATH) {
             put->actions = facet->xout.odp_actions.data;
             put->actions_len = facet->xout.odp_actions.size;
@@ -5396,6 +5405,8 @@ subfacet_install(struct subfacet *subfacet, const struct ofpbuf *odp_actions,
     enum subfacet_path path = facet->xout.slow ? SF_SLOW_PATH : SF_FAST_PATH;
     const struct nlattr *actions = odp_actions->data;
     size_t actions_len = odp_actions->size;
+    struct odputil_keybuf maskbuf;
+    struct ofpbuf mask;
 
     uint64_t slow_path_stub[128 / 8];
     enum dpif_flow_put_flags flags;
@@ -5412,8 +5423,12 @@ subfacet_install(struct subfacet *subfacet, const struct ofpbuf *odp_actions,
                           &actions, &actions_len);
     }
 
+    ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf);
+    odp_flow_key_from_mask(&mask, &facet->xout.wc.masks,
+                           &facet->flow, UINT32_MAX);
+
     ret = dpif_flow_put(ofproto->backer->dpif, flags, subfacet->key,
-                        subfacet->key_len,  NULL, 0,
+                        subfacet->key_len,  mask.data, mask.size,
                         actions, actions_len, stats);
 
     if (stats) {