- Remove group_id from flow entries.
- Show priority when print flow mod messages.
* 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;
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
#ifndef CHAIN_H
#define CHAIN_H 1
+#include <linux/types.h>
+
struct sw_flow;
struct sw_flow_key;
struct datapath;
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 *);
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). */
/* 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;
} 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;
}
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;
}
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 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;
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)
#ifndef TABLE_H
#define TABLE_H 1
+#include <linux/types.h>
+
struct sw_flow;
struct sw_flow_key;
struct datapath;
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. */
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)");
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");
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;
}
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;
}
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;
}
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;
/* 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
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. */
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. */
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'
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);
* 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;
#ifndef CHAIN_H
#define CHAIN_H 1
+#include <stdint.h>
+
struct sw_flow;
struct sw_flow_key;
struct list;
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 *);
/* 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 */
} 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;
}
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. */
*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;
}
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)
}
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++;
}
#ifndef TABLE_H
#define TABLE_H 1
+#include <stdint.h>
+
struct sw_flow;
struct sw_flow_key;
struct list;
* '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
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);
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);