From d1d2f3f3211e123c6080fa51f127419ccb2441c5 Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Tue, 29 Apr 2008 15:00:28 -0700 Subject: [PATCH] - On flow entries with wildcards, match priority field when doing a "strict" delete. - Remove group_id from flow entries. - Show priority when print flow mod messages. --- datapath/chain.c | 6 +++--- datapath/chain.h | 4 +++- datapath/flow.h | 1 - datapath/forward.c | 5 ++--- datapath/table-hash.c | 14 +++++++++----- datapath/table-linear.c | 5 +++-- datapath/table.h | 8 +++++--- datapath/table_t.c | 12 ++++++------ include/openflow.h | 5 ++--- lib/ofp-print.c | 6 ++++-- lib/vconn.c | 1 - switch/chain.c | 5 +++-- switch/chain.h | 4 +++- switch/datapath.c | 6 +++--- switch/switch-flow.h | 1 - switch/table-hash.c | 14 +++++++++----- switch/table-linear.c | 6 ++++-- switch/table.h | 4 +++- utilities/dpctl.c | 2 -- 19 files changed, 62 insertions(+), 47 deletions(-) diff --git a/datapath/chain.c b/datapath/chain.c index 6d3784cc1..f44fbf090 100644 --- a/datapath/chain.c +++ b/datapath/chain.c @@ -94,7 +94,8 @@ int chain_insert(struct sw_chain *chain, struct sw_flow *flow) * wildcards. Relatively cheap for fully specified keys. * * The caller need not hold any locks. */ -int chain_delete(struct sw_chain *chain, const struct sw_flow_key *key, int strict) +int chain_delete(struct sw_chain *chain, const struct sw_flow_key *key, + uint16_t priority, int strict) { int count = 0; int i; @@ -102,12 +103,11 @@ int chain_delete(struct sw_chain *chain, const struct sw_flow_key *key, int stri for (i = 0; i < chain->n_tables; i++) { struct sw_table *t = chain->tables[i]; rcu_read_lock(); - count += t->delete(t, key, strict); + count += t->delete(t, key, priority, strict); rcu_read_unlock(); } return count; - } /* Performs timeout processing on all the tables in 'chain'. Returns the diff --git a/datapath/chain.h b/datapath/chain.h index 76692539c..42e2cb774 100644 --- a/datapath/chain.h +++ b/datapath/chain.h @@ -1,6 +1,8 @@ #ifndef CHAIN_H #define CHAIN_H 1 +#include + struct sw_flow; struct sw_flow_key; struct datapath; @@ -21,7 +23,7 @@ struct sw_chain { struct sw_chain *chain_create(struct datapath *); struct sw_flow *chain_lookup(struct sw_chain *, const struct sw_flow_key *); int chain_insert(struct sw_chain *, struct sw_flow *); -int chain_delete(struct sw_chain *, const struct sw_flow_key *, int); +int chain_delete(struct sw_chain *, const struct sw_flow_key *, uint16_t, int); int chain_timeout(struct sw_chain *); void chain_destroy(struct sw_chain *); void chain_print_stats(struct sw_chain *); diff --git a/datapath/flow.h b/datapath/flow.h index 96c72151c..a3abc8489 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -65,7 +65,6 @@ static inline void check_key_align(void) struct sw_flow { struct sw_flow_key key; - uint32_t group_id; /* Flow group ID (for QoS). */ uint16_t max_idle; /* Idle time before discarding (seconds). */ uint16_t priority; /* Only used on entries with wildcards. */ unsigned long timeout; /* Expiration time (in jiffies). */ diff --git a/datapath/forward.c b/datapath/forward.c index bfc581522..7ab282788 100644 --- a/datapath/forward.c +++ b/datapath/forward.c @@ -378,7 +378,6 @@ add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm) /* Fill out flow. */ flow_extract_match(&flow->key, &ofm->match); - flow->group_id = ntohl(ofm->group_id); flow->max_idle = ntohs(ofm->max_idle); flow->priority = ntohs(ofm->priority); flow->timeout = jiffies + flow->max_idle * HZ; @@ -428,11 +427,11 @@ recv_flow(struct sw_chain *chain, const struct sender *sender, const void *msg) } else if (command == OFPFC_DELETE) { struct sw_flow_key key; flow_extract_match(&key, &ofm->match); - return chain_delete(chain, &key, 0) ? 0 : -ESRCH; + return chain_delete(chain, &key, 0, 0) ? 0 : -ESRCH; } else if (command == OFPFC_DELETE_STRICT) { struct sw_flow_key key; flow_extract_match(&key, &ofm->match); - return chain_delete(chain, &key, 1) ? 0 : -ESRCH; + return chain_delete(chain, &key, ntohs(ofm->priority), 1) ? 0 : -ESRCH; } else { return -ENOTSUPP; } diff --git a/datapath/table-hash.c b/datapath/table-hash.c index c87048f71..04b73013f 100644 --- a/datapath/table-hash.c +++ b/datapath/table-hash.c @@ -85,9 +85,12 @@ static int do_delete(struct sw_flow **bucket, struct sw_flow *flow) return 0; } -/* Returns number of deleted flows. */ +/* 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, 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; @@ -250,11 +253,12 @@ 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) diff --git a/datapath/table-linear.c b/datapath/table-linear.c index 1cdc04e81..1df1d831d 100644 --- a/datapath/table-linear.c +++ b/datapath/table-linear.c @@ -90,7 +90,7 @@ static int do_delete(struct sw_table *swt, struct sw_flow *flow) } static int table_linear_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_linear *tl = (struct sw_table_linear *) swt; struct list_head *pos, *n; @@ -98,7 +98,8 @@ static int table_linear_delete(struct sw_table *swt, list_for_each_safe_rcu (pos, n, &tl->flows) { struct sw_flow *flow = list_entry(pos, struct sw_flow, node); - if (flow_del_matches(&flow->key, key, strict)) + if (flow_del_matches(&flow->key, key, strict) + && (strict && (flow->priority == priority))) count += do_delete(swt, flow); } if (count) diff --git a/datapath/table.h b/datapath/table.h index 34028b4da..b0681b6a5 100644 --- a/datapath/table.h +++ b/datapath/table.h @@ -4,6 +4,8 @@ #ifndef TABLE_H #define TABLE_H 1 +#include + struct sw_flow; struct sw_flow_key; struct datapath; @@ -45,10 +47,10 @@ struct sw_table { int (*insert)(struct sw_table *table, struct sw_flow *flow); /* Deletes from 'table' any and all flows that match 'key' from - * 'table'. If 'strict' set, wildcards must match. Returns the - * number of flows that were deleted. */ + * 'table'. If 'strict' set, wildcards and priority must match. + * Returns the number of flows that were deleted. */ int (*delete)(struct sw_table *table, const struct sw_flow_key *key, - int strict); + uint16_t priority, int strict); /* Performs timeout processing on all the flow entries in 'table'. * Returns the number of flow entries deleted through expiration. */ diff --git a/datapath/table_t.c b/datapath/table_t.c index cb017b8e2..3cc6a58df 100644 --- a/datapath/table_t.c +++ b/datapath/table_t.c @@ -72,7 +72,7 @@ simple_insert_delete(struct sw_table *swt, uint16_t wildcards) if (swt->lookup(swt, &b_flow->key)) unit_fail("lookup should not succeed (1)"); - swt->delete(swt, &a_flow->key, 0); + swt->delete(swt, &a_flow->key, 0, 0); if (swt->lookup(swt, &a_flow->key)) unit_fail("lookup should not succeed (3)"); @@ -358,7 +358,7 @@ delete_flows(struct sw_table *swt, struct list_head *keys, list_for_each_entry_safe (pos, next, keys, node) { if (del_all == 1 || i % 3 == 0) { - n_del = swt->delete(swt, &pos->key, 0); + n_del = swt->delete(swt, &pos->key, 0, 0); if (n_del > 1) { unit_fail("%d flows deleted for one entry", n_del); unit_fail("\tfuture 'errors' could just be product duplicate flow_key_entries"); @@ -494,7 +494,7 @@ iterator_test(struct sw_table *swt, int n_flows, uint16_t wildcards) iterator_test_destr: allocated->key.wildcards = OFPFW_ALL; - swt->delete(swt, &allocated->key, 0); + swt->delete(swt, &allocated->key, 0, 0); vfree(allocated); return success; } @@ -587,7 +587,7 @@ add_test(struct sw_table *swt, uint16_t wildcards) add_test_destr: allocated->key.wildcards = OFPFW_ALL; - swt->delete(swt, &allocated->key, 0); + swt->delete(swt, &allocated->key, 0, 0); vfree(allocated); return success; } @@ -689,7 +689,7 @@ delete_test(struct sw_table *swt, uint16_t wildcards) delete_test_destr: allocated->key.wildcards = OFPFW_ALL; - swt->delete(swt, &allocated->key, 0); + swt->delete(swt, &allocated->key, 0, 0); vfree(allocated); return success; } @@ -760,7 +760,7 @@ complex_add_delete_test(struct sw_table *swt, int n_flows, int i, uint16_t wildc complex_test_destr: allocated->key.wildcards = OFPFW_ALL; - swt->delete(swt, &allocated->key, 0); + swt->delete(swt, &allocated->key, 0, 0); vfree(allocated); return success; diff --git a/include/openflow.h b/include/openflow.h index f3f533c3c..648a36073 100644 --- a/include/openflow.h +++ b/include/openflow.h @@ -50,7 +50,7 @@ /* The most significant bit being set in the version field indicates an * experimental OpenFlow version. */ -#define OFP_VERSION 0x81 +#define OFP_VERSION 0x82 #define OFP_MAX_TABLE_NAME_LEN 32 #define OFP_MAX_PORT_NAME_LEN 16 @@ -281,7 +281,7 @@ struct ofp_packet_out { enum ofp_flow_mod_command { OFPFC_ADD, /* New flow. */ OFPFC_DELETE, /* Delete all matching flows. */ - OFPFC_DELETE_STRICT /* Strictly match wildcards. */ + OFPFC_DELETE_STRICT /* Strictly match wildcards and priority. */ }; /* Flow wildcards. */ @@ -341,7 +341,6 @@ struct ofp_flow_mod { uint16_t command; /* One of OFPFC_*. */ uint16_t max_idle; /* Idle time before discarding (seconds). */ uint32_t buffer_id; /* Buffered packet to apply to (or -1). */ - uint32_t group_id; /* Flow group ID (for QoS). */ uint16_t priority; /* Priority level of flow entry. */ uint8_t pad[2]; /* Align to 32-bits. */ uint32_t reserved; /* Reserved for future use. */ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 92eb87d82..e846f7e94 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -390,8 +390,10 @@ ofp_print_flow_mod(struct ds *string, const void *oh, size_t len, const struct ofp_flow_mod *ofm = oh; ofp_print_match(string, &ofm->match); - ds_put_format(string, " cmd:%d idle:%d buf:%#x grp:%d\n", ntohs(ofm->command), - ntohs(ofm->max_idle), ntohl(ofm->buffer_id), ntohl(ofm->group_id)); + ds_put_format(string, " cmd:%d idle:%d pri:%d buf:%#x\n", + ntohs(ofm->command), ntohs(ofm->max_idle), + ofm->match.wildcards ? ntohs(ofm->priority) : (uint16_t)-1, + ntohl(ofm->buffer_id)); } /* Pretty-print the OFPT_FLOW_EXPIRED packet of 'len' bytes at 'oh' to 'string' diff --git a/lib/vconn.c b/lib/vconn.c index f9c3ec00a..440058476 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -394,7 +394,6 @@ make_add_simple_flow(const struct flow *flow, ofm->command = htons(OFPFC_ADD); ofm->max_idle = htons(60); ofm->buffer_id = htonl(buffer_id); - ofm->group_id = htonl(0); ofm->actions[0].type = htons(OFPAT_OUTPUT); ofm->actions[0].arg.output.max_len = htons(0); ofm->actions[0].arg.output.port = htons(out_port); diff --git a/switch/chain.c b/switch/chain.c index 2a19df027..dab4dd338 100644 --- a/switch/chain.c +++ b/switch/chain.c @@ -120,14 +120,15 @@ chain_insert(struct sw_chain *chain, struct sw_flow *flow) * iterating through the entire contents of each table for keys that contain * wildcards. Relatively cheap for fully specified keys. */ int -chain_delete(struct sw_chain *chain, const struct sw_flow_key *key, int strict) +chain_delete(struct sw_chain *chain, const struct sw_flow_key *key, + uint16_t priority, int strict) { int count = 0; int i; for (i = 0; i < chain->n_tables; i++) { struct sw_table *t = chain->tables[i]; - count += t->delete(t, key, strict); + count += t->delete(t, key, priority, strict); } return count; diff --git a/switch/chain.h b/switch/chain.h index 2d751d03a..aa8945dcb 100644 --- a/switch/chain.h +++ b/switch/chain.h @@ -34,6 +34,8 @@ #ifndef CHAIN_H #define CHAIN_H 1 +#include + struct sw_flow; struct sw_flow_key; struct list; @@ -53,7 +55,7 @@ struct sw_chain { struct sw_chain *chain_create(void); struct sw_flow *chain_lookup(struct sw_chain *, const struct sw_flow_key *); int chain_insert(struct sw_chain *, struct sw_flow *); -int chain_delete(struct sw_chain *, const struct sw_flow_key *, int); +int chain_delete(struct sw_chain *, const struct sw_flow_key *, uint16_t, int); void chain_timeout(struct sw_chain *, struct list *deleted); void chain_destroy(struct sw_chain *); void chain_print_stats(struct sw_chain *); diff --git a/switch/datapath.c b/switch/datapath.c index c465b76a1..a3efa1a5c 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -1060,7 +1060,6 @@ add_flow(struct datapath *dp, const struct ofp_flow_mod *ofm) /* Fill out flow. */ flow_extract_match(&flow->key, &ofm->match); - flow->group_id = ntohl(ofm->group_id); flow->max_idle = ntohs(ofm->max_idle); flow->priority = ntohs(ofm->priority); flow->timeout = time(0) + flow->max_idle; /* FIXME */ @@ -1110,11 +1109,12 @@ recv_flow(struct datapath *dp, const struct sender *sender UNUSED, } else if (command == OFPFC_DELETE) { struct sw_flow_key key; flow_extract_match(&key, &ofm->match); - return chain_delete(dp->chain, &key, 0) ? 0 : -ESRCH; + return chain_delete(dp->chain, &key, 0, 0) ? 0 : -ESRCH; } else if (command == OFPFC_DELETE_STRICT) { struct sw_flow_key key; flow_extract_match(&key, &ofm->match); - return chain_delete(dp->chain, &key, 1) ? 0 : -ESRCH; + return chain_delete(dp->chain, &key, + ntohs(ofm->priority), 1) ? 0 : -ESRCH; } else { return -ENODEV; } diff --git a/switch/switch-flow.h b/switch/switch-flow.h index 5a35c0d9c..40d94dd21 100644 --- a/switch/switch-flow.h +++ b/switch/switch-flow.h @@ -52,7 +52,6 @@ struct sw_flow_key { struct sw_flow { struct sw_flow_key key; - uint32_t group_id; /* Flow group ID (for QoS). */ uint16_t max_idle; /* Idle time before discarding (seconds). */ uint16_t priority; /* Only used on entries with wildcards. */ time_t created; /* When the flow was created. */ diff --git a/switch/table-hash.c b/switch/table-hash.c index e35f9abe7..46ab27ee9 100644 --- a/switch/table-hash.c +++ b/switch/table-hash.c @@ -97,9 +97,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; @@ -283,11 +286,12 @@ 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 void table_hash2_timeout(struct sw_table *swt, struct list *deleted) diff --git a/switch/table-linear.c b/switch/table-linear.c index dc1f7e701..e6c6a2ffb 100644 --- a/switch/table-linear.c +++ b/switch/table-linear.c @@ -100,14 +100,16 @@ do_delete(struct sw_flow *flow) } static int table_linear_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_linear *tl = (struct sw_table_linear *) swt; struct sw_flow *flow, *n; unsigned int count = 0; LIST_FOR_EACH_SAFE (flow, n, struct sw_flow, node, &tl->flows) { - if (flow_del_matches(&flow->key, key, strict)) { + if (flow_del_matches(&flow->key, key, strict) + && (strict && (flow->priority == priority))) { do_delete(flow); count++; } diff --git a/switch/table.h b/switch/table.h index 86b46132c..15743387b 100644 --- a/switch/table.h +++ b/switch/table.h @@ -37,6 +37,8 @@ #ifndef TABLE_H #define TABLE_H 1 +#include + struct sw_flow; struct sw_flow_key; struct list; @@ -75,7 +77,7 @@ struct sw_table { * 'table'. If 'strict' set, wildcards must match. Returns the * number of flows that were deleted. */ int (*delete)(struct sw_table *table, const struct sw_flow_key *key, - int strict); + uint16_t priority, int strict); /* Performs timeout processing on all the flow entries in 'table'. * Appends all the flow entries removed from 'table' to 'deleted' for the diff --git a/utilities/dpctl.c b/utilities/dpctl.c index 9bc50ca0c..f6d851d30 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -642,7 +642,6 @@ static void do_add_flows(int argc, char *argv[]) ofm->command = htons(OFPFC_ADD); ofm->max_idle = htons(50); ofm->buffer_id = htonl(UINT32_MAX); - ofm->group_id = htonl(0); ofm->priority = htons(priority); ofm->reserved = htonl(0); @@ -668,7 +667,6 @@ static void do_del_flows(int argc, char *argv[]) ofm->command = htons(OFPFC_DELETE); ofm->max_idle = htons(0); ofm->buffer_id = htonl(UINT32_MAX); - ofm->group_id = htonl(0); ofm->priority = htons(0); ofm->reserved = htonl(0); str_to_flow(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL, NULL); -- 2.43.0