Skip to content

Commit

Permalink
ofproto-dpif: Store relevant fields for wildcarding in facet.
Browse files Browse the repository at this point in the history
Dynamically determines the flow fields that were relevant in
processing flows based on the OpenFlow flow table and switch
configuration.  The immediate use for this functionality is to
cache action translations for similar flows in facets.  This yields
a roughly 80% improvement in flow set up rates for a complicated
flow table.

More importantly, these wildcards will be used to determine what to
wildcard for the forthcoming kernel wildcard (megaflow) patches
that will allow wildcarding in the kernel, which will provide
significant flow set up improvements.

The approach to tracking fields and caching action translations in
facets was based on an impressive prototype by Ethan Jackson.

Co-authored-by: Ethan Jackson <[email protected]>
Signed-off-by: Ethan Jackson <[email protected]>
Signed-off-by: Justin Pettit <[email protected]>
  • Loading branch information
Justin Pettit and ejj committed Jun 11, 2013
1 parent 368eefa commit bcd2633
Show file tree
Hide file tree
Showing 17 changed files with 855 additions and 167 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ v1.11.0 - xx xxx xxxx
in_port to some unused value, such as OFPP_NONE.)
- ovs-dpctl:
* New debugging commands "add-flow", "mod-flow", "del-flow".
- In dpif-based bridges, cache action translations, which can improve
flow set up performance by 80% with a complicated flow table.
- New syslog format, prefixed with "ovs|", to be easier to filter.
- RHEL: Removes the default firewall rule that allowed GRE traffic to
pass through. Any users that relied on this automatic firewall hole
Expand Down
20 changes: 16 additions & 4 deletions lib/bond.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ static struct bond_entry *lookup_bond_entry(const struct bond *,
static tag_type bond_get_active_slave_tag(const struct bond *);
static struct bond_slave *choose_output_slave(const struct bond *,
const struct flow *,
struct flow_wildcards *,
uint16_t vlan, tag_type *tags);
static void bond_update_fake_slave_stats(struct bond *);

Expand Down Expand Up @@ -505,7 +506,7 @@ bond_compose_learning_packet(struct bond *bond,

memset(&flow, 0, sizeof flow);
memcpy(flow.dl_src, eth_src, ETH_ADDR_LEN);
slave = choose_output_slave(bond, &flow, vlan, &tags);
slave = choose_output_slave(bond, &flow, NULL, vlan, &tags);

packet = ofpbuf_new(0);
compose_rarp(packet, eth_src);
Expand Down Expand Up @@ -605,12 +606,17 @@ bond_check_admissibility(struct bond *bond, const void *slave_,
* packet belongs to (so for an access port it will be the access port's VLAN).
*
* Adds a tag to '*tags' that associates the flow with the returned slave.
*
* If 'wc' is non-NULL, bitwise-OR's 'wc' with the set of bits that were
* significant in the selection. At some point earlier, 'wc' should
* have been initialized (e.g., by flow_wildcards_init_catchall()).
*/
void *
bond_choose_output_slave(struct bond *bond, const struct flow *flow,
uint16_t vlan, tag_type *tags)
struct flow_wildcards *wc, uint16_t vlan,
tag_type *tags)
{
struct bond_slave *slave = choose_output_slave(bond, flow, vlan, tags);
struct bond_slave *slave = choose_output_slave(bond, flow, wc, vlan, tags);
if (slave) {
*tags |= slave->tag;
return slave->aux;
Expand Down Expand Up @@ -1349,7 +1355,7 @@ lookup_bond_entry(const struct bond *bond, const struct flow *flow,

static struct bond_slave *
choose_output_slave(const struct bond *bond, const struct flow *flow,
uint16_t vlan, tag_type *tags)
struct flow_wildcards *wc, uint16_t vlan, tag_type *tags)
{
struct bond_entry *e;

Expand All @@ -1368,8 +1374,14 @@ choose_output_slave(const struct bond *bond, const struct flow *flow,
/* Must have LACP negotiations for TCP balanced bonds. */
return NULL;
}
if (wc) {
flow_mask_hash_fields(wc, NX_HASH_FIELDS_SYMMETRIC_L4);
}
/* Fall Through. */
case BM_SLB:
if (wc) {
flow_mask_hash_fields(wc, NX_HASH_FIELDS_ETH_SRC);
}
e = lookup_bond_entry(bond, flow, vlan);
if (!e->slave || !e->slave->enabled) {
e->slave = CONTAINER_OF(hmap_random_node(&bond->slaves),
Expand Down
5 changes: 3 additions & 2 deletions lib/bond.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ enum bond_verdict {
enum bond_verdict bond_check_admissibility(struct bond *, const void *slave_,
const uint8_t eth_dst[ETH_ADDR_LEN],
tag_type *);
void *bond_choose_output_slave(struct bond *,
const struct flow *, uint16_t vlan, tag_type *);
void *bond_choose_output_slave(struct bond *, const struct flow *,
struct flow_wildcards *, uint16_t vlan,
tag_type *);

/* Rebalancing. */
void bond_account(struct bond *, const struct flow *, uint16_t vlan,
Expand Down
19 changes: 13 additions & 6 deletions lib/bundle.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,17 @@ execute_ab(const struct ofpact_bundle *bundle,
}

static uint16_t
execute_hrw(const struct ofpact_bundle *bundle, const struct flow *flow,
execute_hrw(const struct ofpact_bundle *bundle,
const struct flow *flow, struct flow_wildcards *wc,
bool (*slave_enabled)(uint16_t ofp_port, void *aux), void *aux)
{
uint32_t flow_hash, best_hash;
int best, i;

if (bundle->n_slaves > 1) {
flow_mask_hash_fields(wc, bundle->fields);
}

flow_hash = flow_hash_fields(flow, bundle->fields, bundle->basis);
best = -1;
best_hash = 0;
Expand All @@ -76,16 +81,18 @@ execute_hrw(const struct ofpact_bundle *bundle, const struct flow *flow,
return best >= 0 ? bundle->slaves[best] : OFPP_NONE;
}

/* Executes 'bundle' on 'flow'. Uses 'slave_enabled' to determine if the slave
* designated by 'ofp_port' is up. Returns the chosen slave, or OFPP_NONE if
* none of the slaves are acceptable. */
/* Executes 'bundle' on 'flow'. Sets fields in 'wc' that were used to
* calculate the result. Uses 'slave_enabled' to determine if the slave
* designated by 'ofp_port' is up. Returns the chosen slave, or
* OFPP_NONE if none of the slaves are acceptable. */
uint16_t
bundle_execute(const struct ofpact_bundle *bundle, const struct flow *flow,
bundle_execute(const struct ofpact_bundle *bundle,
const struct flow *flow, struct flow_wildcards *wc,
bool (*slave_enabled)(uint16_t ofp_port, void *aux), void *aux)
{
switch (bundle->algorithm) {
case NX_BD_ALG_HRW:
return execute_hrw(bundle, flow, slave_enabled, aux);
return execute_hrw(bundle, flow, wc, slave_enabled, aux);

case NX_BD_ALG_ACTIVE_BACKUP:
return execute_ab(bundle, slave_enabled, aux);
Expand Down
2 changes: 2 additions & 0 deletions lib/bundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

struct ds;
struct flow;
struct flow_wildcards;
struct ofpact_bundle;
struct ofpbuf;

Expand All @@ -35,6 +36,7 @@ struct ofpbuf;
* See include/openflow/nicira-ext.h for NXAST_BUNDLE specification. */

uint16_t bundle_execute(const struct ofpact_bundle *, const struct flow *,
struct flow_wildcards *wc,
bool (*slave_enabled)(uint16_t ofp_port, void *aux),
void *aux);
enum ofperr bundle_from_openflow(const struct nx_action_bundle *,
Expand Down
26 changes: 26 additions & 0 deletions lib/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,32 @@ flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis)
return jhash_bytes(&fields, sizeof fields, basis);
}

/* Masks the fields in 'wc' that are used by the flow hash 'fields'. */
void
flow_mask_hash_fields(struct flow_wildcards *wc, enum nx_hash_fields fields)
{
switch (fields) {
case NX_HASH_FIELDS_ETH_SRC:
memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
break;

case NX_HASH_FIELDS_SYMMETRIC_L4:
memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type);
memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
break;

default:
NOT_REACHED();
}
}

/* Hashes the portions of 'flow' designated by 'fields'. */
uint32_t
flow_hash_fields(const struct flow *flow, enum nx_hash_fields fields,
Expand Down
1 change: 1 addition & 0 deletions lib/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ bool flow_wildcards_equal(const struct flow_wildcards *,
const struct flow_wildcards *);
uint32_t flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis);

void flow_mask_hash_fields(struct flow_wildcards *, enum nx_hash_fields);
uint32_t flow_hash_fields(const struct flow *, enum nx_hash_fields,
uint16_t basis);
const char *flow_hash_fields_to_str(enum nx_hash_fields);
Expand Down
16 changes: 16 additions & 0 deletions lib/learn.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,22 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
fm->ofpacts_len = ofpacts->size;
}

/* Perform a bitwise-OR on 'wc''s fields that are relevant as sources in
* the learn action 'learn'. */
void
learn_mask(const struct ofpact_learn *learn, struct flow_wildcards *wc)
{
const struct ofpact_learn_spec *spec;
union mf_subvalue value;

memset(&value, 0xff, sizeof value);
for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) {
if (spec->src_type == NX_LEARN_SRC_FIELD) {
mf_write_subfield_flow(&spec->src, &value, &wc->masks);
}
}
}

static void
learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec)
{
Expand Down
2 changes: 2 additions & 0 deletions lib/learn.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

struct ds;
struct flow;
struct flow_wildcards;
struct ofpbuf;
struct ofpact_learn;
struct ofputil_flow_mod;
Expand All @@ -38,6 +39,7 @@ void learn_to_nxast(const struct ofpact_learn *, struct ofpbuf *openflow);

void learn_execute(const struct ofpact_learn *, const struct flow *,
struct ofputil_flow_mod *, struct ofpbuf *ofpacts);
void learn_mask(const struct ofpact_learn *, struct flow_wildcards *);

void learn_parse(char *, struct ofpbuf *ofpacts);
void learn_format(const struct ofpact_learn *, struct ds *);
Expand Down
7 changes: 5 additions & 2 deletions lib/multipath.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,18 @@ static uint16_t multipath_algorithm(uint32_t hash, enum nx_mp_algorithm,
unsigned int n_links, unsigned int arg);

/* Executes 'mp' based on the current contents of 'flow', writing the results
* back into 'flow'. */
* back into 'flow'. Sets fields in 'wc' that were used to calculate
* the result. */
void
multipath_execute(const struct ofpact_multipath *mp, struct flow *flow)
multipath_execute(const struct ofpact_multipath *mp, struct flow *flow,
struct flow_wildcards *wc)
{
/* Calculate value to store. */
uint32_t hash = flow_hash_fields(flow, mp->fields, mp->basis);
uint16_t link = multipath_algorithm(hash, mp->algorithm,
mp->max_link + 1, mp->arg);

flow_mask_hash_fields(wc, mp->fields);
nxm_reg_load(&mp->dst, link, flow);
}

Expand Down
4 changes: 3 additions & 1 deletion lib/multipath.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

struct ds;
struct flow;
struct flow_wildcards;
struct nx_action_multipath;
struct ofpact_multipath;
struct ofpbuf;
Expand All @@ -38,7 +39,8 @@ enum ofperr multipath_check(const struct ofpact_multipath *,
void multipath_to_nxast(const struct ofpact_multipath *,
struct ofpbuf *openflow);

void multipath_execute(const struct ofpact_multipath *, struct flow *);
void multipath_execute(const struct ofpact_multipath *, struct flow *,
struct flow_wildcards *);

void multipath_parse(struct ofpact_multipath *, const char *);
void multipath_format(const struct ofpact_multipath *, struct ds *);
Expand Down
13 changes: 11 additions & 2 deletions lib/nx-match.c
Original file line number Diff line number Diff line change
Expand Up @@ -1279,11 +1279,15 @@ nxm_reg_load_to_nxast(const struct ofpact_reg_load *load,

void
nxm_execute_reg_move(const struct ofpact_reg_move *move,
struct flow *flow)
struct flow *flow, struct flow_wildcards *wc)
{
union mf_subvalue mask_value;
union mf_value src_value;
union mf_value dst_value;

memset(&mask_value, 0xff, sizeof mask_value);
mf_write_subfield_flow(&move->src, &mask_value, &wc->masks);

mf_get_value(move->dst.field, flow, &dst_value);
mf_get_value(move->src.field, flow, &src_value);
bitwise_copy(&src_value, move->src.field->n_bytes, move->src.ofs,
Expand Down Expand Up @@ -1428,10 +1432,15 @@ nx_stack_pop(struct ofpbuf *stack)

void
nxm_execute_stack_push(const struct ofpact_stack *push,
const struct flow *flow, struct ofpbuf *stack)
const struct flow *flow, struct flow_wildcards *wc,
struct ofpbuf *stack)
{
union mf_subvalue mask_value;
union mf_subvalue dst_value;

memset(&mask_value, 0xff, sizeof mask_value);
mf_write_subfield_flow(&push->subfield, &mask_value, &wc->masks);

mf_read_subfield(&push->subfield, flow, &dst_value);
nx_stack_push(stack, &dst_value);
}
Expand Down
6 changes: 4 additions & 2 deletions lib/nx-match.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ void nxm_reg_move_to_nxast(const struct ofpact_reg_move *,
void nxm_reg_load_to_nxast(const struct ofpact_reg_load *,
struct ofpbuf *openflow);

void nxm_execute_reg_move(const struct ofpact_reg_move *, struct flow *);
void nxm_execute_reg_move(const struct ofpact_reg_move *, struct flow *,
struct flow_wildcards *);
void nxm_execute_reg_load(const struct ofpact_reg_load *, struct flow *);
void nxm_reg_load(const struct mf_subfield *, uint64_t src_data,
struct flow *);
Expand All @@ -105,7 +106,8 @@ void nxm_stack_pop_to_nxast(const struct ofpact_stack *,
struct ofpbuf *openflow);

void nxm_execute_stack_push(const struct ofpact_stack *,
const struct flow *, struct ofpbuf *);
const struct flow *, struct flow_wildcards *,
struct ofpbuf *);
void nxm_execute_stack_pop(const struct ofpact_stack *,
struct flow *, struct ofpbuf *);

Expand Down
Loading

0 comments on commit bcd2633

Please sign in to comment.