X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Ftable-hash.c;h=2951722e964b6b963e9df454e3ebb19628d08f6e;hb=faa47744f0d0ad4d1987d9722d15897d788625f4;hp=46acf80e39f256bd84a1303cb20076b11d7a5d62;hpb=9630e4100553c3531605aa44db65e9eaafe07dad;p=sliver-openvswitch.git diff --git a/datapath/table-hash.c b/datapath/table-hash.c index 46acf80e3..2951722e9 100644 --- a/datapath/table-hash.c +++ b/datapath/table-hash.c @@ -31,7 +31,8 @@ static struct sw_flow **find_bucket(struct sw_table *swt, const struct sw_flow_key *key) { struct sw_table_hash *th = (struct sw_table_hash *) swt; - unsigned int crc = crc32_calculate(&th->crc32, key, sizeof *key); + unsigned int crc = crc32_calculate(&th->crc32, key, + offsetof(struct sw_flow_key, wildcards)); return &th->buckets[crc & th->bucket_mask]; } @@ -39,7 +40,7 @@ static struct sw_flow *table_hash_lookup(struct sw_table *swt, const struct sw_flow_key *key) { struct sw_flow *flow = *find_bucket(swt, key); - return flow && !memcmp(&flow->key, key, sizeof *key) ? flow : NULL; + return flow && flow_keys_equal(&flow->key, key) ? flow : NULL; } static int table_hash_insert(struct sw_table *swt, struct sw_flow *flow) @@ -58,7 +59,7 @@ static int table_hash_insert(struct sw_table *swt, struct sw_flow *flow) retval = 1; } else { struct sw_flow *old_flow = *bucket; - if (!memcmp(&old_flow->key, &flow->key, sizeof flow->key)) { + if (flow_keys_equal(&old_flow->key, &flow->key)) { rcu_assign_pointer(*bucket, flow); flow_deferred_free(old_flow); retval = 1; @@ -69,9 +70,42 @@ static int table_hash_insert(struct sw_table *swt, struct sw_flow *flow) return retval; } +static int table_hash_modify(struct sw_table *swt, + const struct sw_flow_key *key, uint16_t priority, int strict, + const struct ofp_action_header *actions, size_t actions_len) +{ + struct sw_table_hash *th = (struct sw_table_hash *) swt; + unsigned int count = 0; + + if (key->wildcards == 0) { + struct sw_flow **bucket = find_bucket(swt, key); + struct sw_flow *flow = *bucket; + if (flow && flow_matches_desc(&flow->key, key, strict) + && (!strict || (flow->priority == priority))) { + flow_replace_acts(flow, actions, actions_len); + count = 1; + } + } else { + unsigned int i; + + for (i = 0; i <= th->bucket_mask; i++) { + struct sw_flow **bucket = &th->buckets[i]; + struct sw_flow *flow = *bucket; + if (flow && flow_matches_desc(&flow->key, key, strict) + && (!strict || (flow->priority == priority))) { + flow_replace_acts(flow, actions, actions_len); + count++; + } + } + } + return count; +} + /* Caller must update n_flows. */ -static int do_delete(struct sw_flow **bucket, struct sw_flow *flow) +static int do_delete(struct datapath *dp, struct sw_flow **bucket, + struct sw_flow *flow, enum nx_flow_end_reason reason) { + dp_send_flow_end(dp, flow, reason); rcu_assign_pointer(*bucket, NULL); flow_deferred_free(flow); return 1; @@ -80,9 +114,9 @@ static int do_delete(struct sw_flow **bucket, struct sw_flow *flow) /* Returns number of deleted flows. We can ignore the priority * argument, since all exact-match entries are the same (highest) * priority. */ -static int table_hash_delete(struct sw_table *swt, - const struct sw_flow_key *key, - uint16_t priority, int strict) +static int table_hash_delete(struct datapath *dp, struct sw_table *swt, + const struct sw_flow_key *key, uint16_t out_port, + uint16_t priority, int strict) { struct sw_table_hash *th = (struct sw_table_hash *) swt; unsigned int count = 0; @@ -90,16 +124,18 @@ static int table_hash_delete(struct sw_table *swt, if (key->wildcards == 0) { struct sw_flow **bucket = find_bucket(swt, key); struct sw_flow *flow = *bucket; - if (flow && !memcmp(&flow->key, key, sizeof *key)) - count = do_delete(bucket, flow); + if (flow && flow_keys_equal(&flow->key, key) + && flow_has_out_port(flow, out_port)) + count = do_delete(dp, bucket, flow, NXFER_DELETE); } else { unsigned int i; for (i = 0; i <= th->bucket_mask; i++) { struct sw_flow **bucket = &th->buckets[i]; struct sw_flow *flow = *bucket; - if (flow && flow_del_matches(&flow->key, key, strict)) - count += do_delete(bucket, flow); + if (flow && flow_matches_desc(&flow->key, key, strict) + && flow_has_out_port(flow, out_port)) + count = do_delete(dp, bucket, flow, NXFER_DELETE); } } th->n_flows -= count; @@ -119,8 +155,7 @@ static int table_hash_timeout(struct datapath *dp, struct sw_table *swt) if (flow) { int reason = flow_timeout(flow); if (reason >= 0) { - count += do_delete(bucket, flow); - dp_send_flow_expired(dp, flow, reason); + count += do_delete(dp, bucket, flow, reason); } } } @@ -142,7 +177,7 @@ static void table_hash_destroy(struct sw_table *swt) } static int table_hash_iterate(struct sw_table *swt, - const struct sw_flow_key *key, + const struct sw_flow_key *key, uint16_t out_port, struct sw_table_position *position, int (*callback)(struct sw_flow *, void *private), void *private) @@ -157,7 +192,7 @@ static int table_hash_iterate(struct sw_table *swt, int error; flow = table_hash_lookup(swt, key); - if (!flow) + if (!flow || !flow_has_out_port(flow, out_port)) return 0; error = callback(flow, private); @@ -169,7 +204,8 @@ static int table_hash_iterate(struct sw_table *swt, for (i = position->private[0]; i <= th->bucket_mask; i++) { struct sw_flow *flow = th->buckets[i]; - if (flow && flow_matches_1wild(&flow->key, key)) { + if (flow && flow_matches_1wild(&flow->key, key) + && flow_has_out_port(flow, out_port)) { int error = callback(flow, private); if (error) { position->private[0] = i; @@ -185,8 +221,10 @@ static void table_hash_stats(struct sw_table *swt, { struct sw_table_hash *th = (struct sw_table_hash *) swt; stats->name = "hash"; - stats->n_flows = th->n_flows; + stats->wildcards = 0; /* No wildcards are supported. */ + stats->n_flows = th->n_flows; stats->max_flows = th->bucket_mask + 1; + stats->n_lookup = swt->n_lookup; stats->n_matched = swt->n_matched; } @@ -239,7 +277,7 @@ static struct sw_flow *table_hash2_lookup(struct sw_table *swt, for (i = 0; i < 2; i++) { struct sw_flow *flow = *find_bucket(t2->subtable[i], key); - if (flow && !memcmp(&flow->key, key, sizeof *key)) + if (flow && flow_keys_equal(&flow->key, key)) return flow; } return NULL; @@ -254,13 +292,27 @@ static int table_hash2_insert(struct sw_table *swt, struct sw_flow *flow) return table_hash_insert(t2->subtable[1], flow); } -static int table_hash2_delete(struct sw_table *swt, +static int table_hash2_modify(struct sw_table *swt, + const struct sw_flow_key *key, uint16_t priority, int strict, + const struct ofp_action_header *actions, size_t actions_len) +{ + struct sw_table_hash2 *t2 = (struct sw_table_hash2 *) swt; + return (table_hash_modify(t2->subtable[0], key, priority, strict, + actions, actions_len) + + table_hash_modify(t2->subtable[1], key, priority, strict, + actions, actions_len)); +} + +static int table_hash2_delete(struct datapath *dp, struct sw_table *swt, const struct sw_flow_key *key, + uint16_t out_port, uint16_t priority, int strict) { struct sw_table_hash2 *t2 = (struct sw_table_hash2 *) swt; - return (table_hash_delete(t2->subtable[0], key, priority, strict) - + table_hash_delete(t2->subtable[1], key, priority, strict)); + return (table_hash_delete(dp, t2->subtable[0], key, out_port, + priority, strict) + + table_hash_delete(dp, t2->subtable[1], key, out_port, + priority, strict)); } static int table_hash2_timeout(struct datapath *dp, struct sw_table *swt) @@ -279,7 +331,7 @@ static void table_hash2_destroy(struct sw_table *swt) } static int table_hash2_iterate(struct sw_table *swt, - const struct sw_flow_key *key, + const struct sw_flow_key *key, uint16_t out_port, struct sw_table_position *position, int (*callback)(struct sw_flow *, void *), void *private) @@ -288,8 +340,8 @@ static int table_hash2_iterate(struct sw_table *swt, int i; for (i = position->private[1]; i < 2; i++) { - int error = table_hash_iterate(t2->subtable[i], key, position, - callback, private); + int error = table_hash_iterate(t2->subtable[i], key, out_port, + position, callback, private); if (error) { return error; } @@ -309,8 +361,10 @@ static void table_hash2_stats(struct sw_table *swt, for (i = 0; i < 2; i++) table_hash_stats(t2->subtable[i], &substats[i]); stats->name = "hash2"; - stats->n_flows = substats[0].n_flows + substats[1].n_flows; + stats->wildcards = 0; /* No wildcards are supported. */ + stats->n_flows = substats[0].n_flows + substats[1].n_flows; stats->max_flows = substats[0].max_flows + substats[1].max_flows; + stats->n_lookup = swt->n_lookup; stats->n_matched = swt->n_matched; } @@ -336,6 +390,7 @@ struct sw_table *table_hash2_create(unsigned int poly0, unsigned int buckets0, swt = &t2->swt; swt->lookup = table_hash2_lookup; swt->insert = table_hash2_insert; + swt->modify = table_hash2_modify; swt->delete = table_hash2_delete; swt->timeout = table_hash2_timeout; swt->destroy = table_hash2_destroy;