From b5889101243ef5dc8d72235fcd6a4ba6193da71d Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Mon, 20 May 2013 17:48:49 -0700 Subject: [PATCH] ofproto-dpif: Use megaflows. 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 Acked-by: Ben Pfaff --- NEWS | 4 ++++ PORTING | 32 ++++++++++++++++++++------------ ofproto/ofproto-dpif.c | 21 ++++++++++++++++++--- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index fe14f262a..cd4fb05f5 100644 --- 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 ffde29637..53c19d33d 100644 --- 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: diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index a3aa59204..d881c47ec 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -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) { -- 2.20.1