- On flow entries with wildcards, match priority field when doing a "strict" delete.
authorJustin Pettit <jpettit@nicira.com>
Tue, 29 Apr 2008 22:00:28 +0000 (15:00 -0700)
committerJustin Pettit <jpettit@nicira.com>
Tue, 29 Apr 2008 22:00:28 +0000 (15:00 -0700)
- Remove group_id from flow entries.
- Show priority when print flow mod messages.

19 files changed:
datapath/chain.c
datapath/chain.h
datapath/flow.h
datapath/forward.c
datapath/table-hash.c
datapath/table-linear.c
datapath/table.h
datapath/table_t.c
include/openflow.h
lib/ofp-print.c
lib/vconn.c
switch/chain.c
switch/chain.h
switch/datapath.c
switch/switch-flow.h
switch/table-hash.c
switch/table-linear.c
switch/table.h
utilities/dpctl.c

index 6d3784cc1039a8de75cb0ecc6cc662a2f11873d5..f44fbf0903553f88eac4c7ac93d79e7fad9f61d3 100644 (file)
@@ -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
index 76692539cd96eda0ac3f0cdc5dfebbf3b9a59a00..42e2cb774730288a37318f7ebc32fcc76404364d 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef CHAIN_H
 #define CHAIN_H 1
 
+#include <linux/types.h>
+
 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 *);
index 96c72151c476efe91945f3e80ecca6eb07d1a176..a3abc848914719925901bf999e37ce8478ac2d9e 100644 (file)
@@ -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). */
index bfc5815223fca387dbecf806ba91320039ee5cf6..7ab282788abfc7d879bde685217d9b64036f19c1 100644 (file)
@@ -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;
        }
index c87048f710e99bc63ad925e6cf41897036e2cb99..04b73013f64d076d010e03d58e32d22eea0277af 100644 (file)
@@ -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)
index 1cdc04e81300d9a26813bad0aa288ba5c41bb655..1df1d831de8d9d8665efe83e3456339ef0dd72de 100644 (file)
@@ -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)
index 34028b4dae4dfc385be784ee70ecd762f18a455c..b0681b6a5ded24ed81df002e77d7c8d2ed62b1e3 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef TABLE_H
 #define TABLE_H 1
 
+#include <linux/types.h>
+
 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. */
index cb017b8e23ccc9e2f9785ce73d656b73c49b0863..3cc6a58df4e742e47690178461f2af9365773c24 100644 (file)
@@ -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;
 
index f3f533c3c1259f38f2123529170a03435ead303f..648a36073b616a7d4a28c6412444c46b32364cd5 100644 (file)
@@ -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. */
index 92eb87d82fd8ed2f81f384e8909ca49665c76c20..e846f7e942c9a84e0844fd3adc279955f02b5cd5 100644 (file)
@@ -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'
index f9c3ec00a81effbb85c151b9bcc248b1a6dd8af7..440058476a5b326eaceabfe7fe0df3a6cd5100c5 100644 (file)
@@ -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);
index 2a19df0271b4d827a32bd24516c90888573fbf85..dab4dd338f1a0f0d90c8d51cdedc965aa0d67ac3 100644 (file)
@@ -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;
index 2d751d03a5510838cbcaae33a5522b9acdb53e8d..aa8945dcb339f8759c311c529b1e92296e01f5ce 100644 (file)
@@ -34,6 +34,8 @@
 #ifndef CHAIN_H
 #define CHAIN_H 1
 
+#include <stdint.h>
+
 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 *);
index c465b76a1c955e6d9e954bc00a58fda78772a4fc..a3efa1a5c3affea90841c965e9a68ada45351539 100644 (file)
@@ -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;
     }
index 5a35c0d9c0787146588e40f7d0ac2c2982e3b9f9..40d94dd216c8d0c4b790eddb47f1eba9018efe4b 100644 (file)
@@ -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. */
index e35f9abe7ac411a17053bb461f6e68d8d8b26a93..46ab27ee9c60a75b35cf9501d962e1e83f90d1ab 100644 (file)
@@ -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)
index dc1f7e70141b21a4c811b7c04b58f7453f283475..e6c6a2ffbe45154a3a87d91b57bd0cc8af4075e0 100644 (file)
@@ -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++;
         }
index 86b46132c3035beb9307f2724f4ed6f74762ee59..15743387b56c0a992cf80e360af8de0d47c9d84d 100644 (file)
@@ -37,6 +37,8 @@
 #ifndef TABLE_H
 #define TABLE_H 1
 
+#include <stdint.h>
+
 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
index 9bc50ca0c54b395f4175473cee385f439096e1d0..f6d851d3078c4a3ce26996287cb225bf11023c51 100644 (file)
@@ -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);