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.
* 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.
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:
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;
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
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;
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;
&actions, &actions_len);
}
- ret = dpif_flow_put(ofproto->backer->dpif, flags, subfacet->key,
- subfacet->key_len, NULL, 0,
+ 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(subfacet->backer->dpif, flags, subfacet->key,
+ subfacet->key_len, mask.data, mask.size,
actions, actions_len, stats);
if (stats) {