X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=switch%2Ftable-hash.c;h=461a4636f12a42f64eb83adf9d3545453435100e;hb=61df6c4639fe3a8f819e9d8a35c71f947e842e1a;hp=315da5168ad773d1edce8387e51258d1afc45b05;hpb=3f0201adb5da48e98039e4a7552284b77004784a;p=sliver-openvswitch.git diff --git a/switch/table-hash.c b/switch/table-hash.c index 315da5168..461a4636f 100644 --- a/switch/table-hash.c +++ b/switch/table-hash.c @@ -31,6 +31,7 @@ * derivatives without specific, written prior permission. */ +#include #include "table.h" #include #include @@ -97,9 +98,12 @@ do_delete(struct sw_flow **bucket) *bucket = NULL; } -/* Returns number of deleted flows. */ +/* Returns number of deleted flows. We can igonre 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, int strict) + const struct sw_flow_key *key, + uint16_t priority, int strict) { struct sw_table_hash *th = (struct sw_table_hash *) swt; unsigned int count = 0; @@ -127,23 +131,20 @@ static int table_hash_delete(struct sw_table *swt, return count; } -static int table_hash_timeout(struct datapath *dp, struct sw_table *swt) +static void table_hash_timeout(struct sw_table *swt, struct list *deleted) { struct sw_table_hash *th = (struct sw_table_hash *) swt; unsigned int i; - int count = 0; for (i = 0; i <= th->bucket_mask; i++) { struct sw_flow **bucket = &th->buckets[i]; struct sw_flow *flow = *bucket; if (flow && flow_timeout(flow)) { - dp_send_flow_expired(dp, flow); - do_delete(bucket); - count++; + list_push_back(deleted, &flow->node); + *bucket = NULL; + th->n_flows--; } } - th->n_flows -= count; - return count; } static void table_hash_destroy(struct sw_table *swt) @@ -159,56 +160,36 @@ static void table_hash_destroy(struct sw_table *swt) free(th); } -struct swt_iterator_hash { - struct sw_table_hash *th; - unsigned int bucket_i; -}; - -static struct sw_flow *next_flow(struct swt_iterator_hash *ih) +static int table_hash_iterate(struct sw_table *swt, + const struct sw_flow_key *key, + struct sw_table_position *position, + int (*callback)(struct sw_flow *, void *private), + void *private) { - for (;ih->bucket_i <= ih->th->bucket_mask; ih->bucket_i++) { - struct sw_flow *f = ih->th->buckets[ih->bucket_i]; - if (f != NULL) - return f; - } - - return NULL; -} - -static int table_hash_iterator(struct sw_table *swt, - struct swt_iterator *swt_iter) -{ - struct swt_iterator_hash *ih; - - swt_iter->private = ih = malloc(sizeof *ih); + struct sw_table_hash *th = (struct sw_table_hash *) swt; - if (ih == NULL) + if (position->private[0] > th->bucket_mask) return 0; - ih->th = (struct sw_table_hash *) swt; - - ih->bucket_i = 0; - swt_iter->flow = next_flow(ih); - - return 1; -} - -static void table_hash_next(struct swt_iterator *swt_iter) -{ - struct swt_iterator_hash *ih; - - if (swt_iter->flow == NULL) - return; - - ih = (struct swt_iterator_hash *) swt_iter->private; - - ih->bucket_i++; - swt_iter->flow = next_flow(ih); -} - -static void table_hash_iterator_destroy(struct swt_iterator *swt_iter) -{ - free(swt_iter->private); + if (key->wildcards == 0) { + struct sw_flow *flow = table_hash_lookup(swt, key); + position->private[0] = -1; + return flow ? callback(flow, private) : 0; + } else { + int i; + + for (i = position->private[0]; i <= th->bucket_mask; i++) { + struct sw_flow *flow = th->buckets[i]; + if (flow && flow_matches(key, &flow->key)) { + int error = callback(flow, private); + if (error) { + position->private[0] = i + 1; + return error; + } + } + } + return 0; + } } static void table_hash_stats(struct sw_table *swt, @@ -237,6 +218,7 @@ struct sw_table *table_hash_create(unsigned int polynomial, free(th); return NULL; } + th->n_flows = 0; th->bucket_mask = n_buckets - 1; swt = &th->swt; @@ -245,9 +227,7 @@ struct sw_table *table_hash_create(unsigned int polynomial, swt->delete = table_hash_delete; swt->timeout = table_hash_timeout; swt->destroy = table_hash_destroy; - swt->iterator = table_hash_iterator; - swt->iterator_next = table_hash_next; - swt->iterator_destroy = table_hash_iterator_destroy; + swt->iterate = table_hash_iterate; swt->stats = table_hash_stats; crc32_init(&th->crc32, polynomial); @@ -286,18 +266,19 @@ static int table_hash2_insert(struct sw_table *swt, struct sw_flow *flow) } static int table_hash2_delete(struct sw_table *swt, - const struct sw_flow_key *key, int strict) + const struct sw_flow_key *key, + uint16_t priority, int strict) { struct sw_table_hash2 *t2 = (struct sw_table_hash2 *) swt; - return (table_hash_delete(t2->subtable[0], key, strict) - + table_hash_delete(t2->subtable[1], key, strict)); + return (table_hash_delete(t2->subtable[0], key, priority, strict) + + table_hash_delete(t2->subtable[1], key, priority, strict)); } -static int table_hash2_timeout(struct datapath *dp, struct sw_table *swt) +static void table_hash2_timeout(struct sw_table *swt, struct list *deleted) { struct sw_table_hash2 *t2 = (struct sw_table_hash2 *) swt; - return (table_hash_timeout(dp, t2->subtable[0]) - + table_hash_timeout(dp, t2->subtable[1])); + table_hash_timeout(t2->subtable[0], deleted); + table_hash_timeout(t2->subtable[1], deleted); } static void table_hash2_destroy(struct sw_table *swt) @@ -308,79 +289,25 @@ static void table_hash2_destroy(struct sw_table *swt) free(t2); } -struct swt_iterator_hash2 { - struct sw_table_hash2 *th2; - struct swt_iterator ih; - uint8_t table_i; -}; - -static int table_hash2_iterator(struct sw_table *swt, - struct swt_iterator *swt_iter) +static int table_hash2_iterate(struct sw_table *swt, + const struct sw_flow_key *key, + struct sw_table_position *position, + int (*callback)(struct sw_flow *, void *), + void *private) { - struct swt_iterator_hash2 *ih2; - - swt_iter->private = ih2 = malloc(sizeof *ih2); - if (ih2 == NULL) - return 0; - - ih2->th2 = (struct sw_table_hash2 *) swt; - if (!table_hash_iterator(ih2->th2->subtable[0], &ih2->ih)) { - free(ih2); - return 0; - } - - if (ih2->ih.flow != NULL) { - swt_iter->flow = ih2->ih.flow; - ih2->table_i = 0; - } else { - table_hash_iterator_destroy(&ih2->ih); - ih2->table_i = 1; - if (!table_hash_iterator(ih2->th2->subtable[1], &ih2->ih)) { - free(ih2); - return 0; - } - swt_iter->flow = ih2->ih.flow; - } - - return 1; -} - -static void table_hash2_next(struct swt_iterator *swt_iter) -{ - struct swt_iterator_hash2 *ih2; - - if (swt_iter->flow == NULL) - return; - - ih2 = (struct swt_iterator_hash2 *) swt_iter->private; - table_hash_next(&ih2->ih); + struct sw_table_hash2 *t2 = (struct sw_table_hash2 *) swt; + int i; - if (ih2->ih.flow != NULL) { - swt_iter->flow = ih2->ih.flow; - } else { - if (ih2->table_i == 0) { - table_hash_iterator_destroy(&ih2->ih); - ih2->table_i = 1; - if (!table_hash_iterator(ih2->th2->subtable[1], &ih2->ih)) { - ih2->ih.private = NULL; - swt_iter->flow = NULL; - } else { - swt_iter->flow = ih2->ih.flow; - } - } else { - swt_iter->flow = NULL; + for (i = position->private[1]; i < 2; i++) { + int error = table_hash_iterate(t2->subtable[i], key, position, + callback, private); + if (error) { + return error; } + position->private[0] = 0; + position->private[1]++; } -} - -static void table_hash2_iterator_destroy(struct swt_iterator *swt_iter) -{ - struct swt_iterator_hash2 *ih2; - - ih2 = (struct swt_iterator_hash2 *) swt_iter->private; - if (ih2->ih.private != NULL) - table_hash_iterator_destroy(&ih2->ih); - free(ih2); + return 0; } static void table_hash2_stats(struct sw_table *swt, @@ -422,12 +349,9 @@ struct sw_table *table_hash2_create(unsigned int poly0, unsigned int buckets0, swt->delete = table_hash2_delete; swt->timeout = table_hash2_timeout; swt->destroy = table_hash2_destroy; + swt->iterate = table_hash2_iterate; swt->stats = table_hash2_stats; - swt->iterator = table_hash2_iterator; - swt->iterator_next = table_hash2_next; - swt->iterator_destroy = table_hash2_iterator_destroy; - return swt; out_free_subtable0: