[ovs-dev] [PATCH] ovs-ofctl: Adding support for table ID.

Hao Zheng hzheng at nicira.com
Sat Jul 31 00:21:12 UTC 2010


Now for add-flow, add-flows, mod-flows and del-flows commands of ovs-ofctl
command, user can specify on which table these commands modify flows.  The
is accomplished by adding "table=table_id" to your flow description.
Note: currently Open vSwitch only supports up to 32 tables, so a valid
table_id should be in the range of 0 to 31.  If "table=table_id" is not
specified as part of the flow description, then these commands behave like
before.
---
 utilities/ovs-ofctl.8.in |   27 +++++++++++++---------
 utilities/ovs-ofctl.c    |   53 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 54d222a..a3466da 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -329,6 +329,22 @@ as a decimal number between 0 and 255, inclusive.
 When \fBdl_type\fR and \fBnw_proto\fR take other values, the values of
 these settings are ignored (see \fBFlow Syntax\fR above).
 .
+.IP \fBtable=\fInumber\fR
+If specified, limits the flow manipulation and flow dump commands to 
+only apply to the table with the given \fInumber\fR.  
+\fInumber\fR is a number between 0 and 31, inclusive.
+.
+If this field is not specified, for \fBadd-flow\fR, \fBadd-flows\fR, 
+\fBmod-flows\fR and \fBdel-flows\fR commands, the switch will choose
+the table for these commands to operate on; for \fBdump-flows\fR and
+\fBdump-aggregate\fR commands, statistics are gathered about flows 
+from all tables.
+.IP
+When this field is specified in \fBadd-flow\fR, \fBadd-flows\fR, 
+\fBmod-flows\fR and \fBdel-flows\fR commands, it will activate a 
+Nicira extension to OpenFlow, which as of this writing is only 
+known to be implemented by Open vSwitch.
+.
 .PP
 The following shorthand notations are also available:
 .
@@ -497,17 +513,6 @@ and \fBdel\-flows\fR commands support one additional optional field:
 \fBout_port=\fIport\fR
 If set, a matching flow must include an output action to \fIport\fR.
 .
-.PP
-The \fBdump\-flows\fR and \fBdump\-aggregate\fR commands support an
-additional optional field:
-.
-.IP \fBtable=\fInumber\fR
-If specified, limits the flows about which statistics are gathered to
-those in the table with the given \fInumber\fR.  Tables are numbered
-as shown by the \fBdump\-tables\fR command.
-.
-If this field is not specified, or if \fInumber\fR is given as
-\fB255\fR, statistics are gathered about flows from all tables.
 .
 .SS "Table Entry Output"
 .
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index ac8fdb7..0082a82 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -830,6 +830,9 @@ str_to_flow(char *string, struct ofp_match *match, struct ofpbuf *actions,
         
             if (table_idx && !strcmp(name, "table")) {
                 *table_idx = atoi(value);
+                if (*table_idx < 0 || *table_idx > 31) {
+                    ovs_fatal(0, "table %s is invalid, must be between 0 and 31", value);
+                }
             } else if (out_port && !strcmp(name, "out_port")) {
                 *out_port = atoi(value);
             } else if (priority && !strcmp(name, "priority")) {
@@ -916,6 +919,21 @@ do_dump_aggregate(int argc, char *argv[])
 }
 
 static void
+enable_flow_mod_table_id_ext(struct vconn *vconn, uint8_t enable)
+{
+    struct nxt_flow_mod_table_id *flow_mod_table_id;
+    struct ofpbuf *buffer;
+
+    flow_mod_table_id = make_openflow(sizeof *flow_mod_table_id, OFPT_VENDOR, &buffer);
+
+    flow_mod_table_id->vendor = htonl(NX_VENDOR_ID);
+    flow_mod_table_id->subtype = htonl(NXT_FLOW_MOD_TABLE_ID);
+    flow_mod_table_id->set = enable;
+
+    send_openflow_buffer(vconn, buffer);
+}
+
+static void
 do_add_flow(int argc OVS_UNUSED, char *argv[])
 {
     struct vconn *vconn;
@@ -924,12 +942,13 @@ do_add_flow(int argc OVS_UNUSED, char *argv[])
     uint16_t priority, idle_timeout, hard_timeout;
     uint64_t cookie;
     struct ofp_match match;
+    uint8_t table_idx;
 
     /* Parse and send.  str_to_flow() will expand and reallocate the data in
      * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
     make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
     str_to_flow(argv[2], &match, buffer,
-                NULL, NULL, &priority, &idle_timeout, &hard_timeout,
+                &table_idx, NULL, &priority, &idle_timeout, &hard_timeout,
                 &cookie);
     ofm = buffer->data;
     ofm->match = match;
@@ -941,6 +960,10 @@ do_add_flow(int argc OVS_UNUSED, char *argv[])
     ofm->priority = htons(priority);
 
     open_vconn(argv[1], &vconn);
+    if (table_idx != 0xff) {
+        enable_flow_mod_table_id_ext(vconn, 1);
+        ofm->command = htons(ntohs(ofm->command) | (table_idx << 8));
+    }
     send_openflow_buffer(vconn, buffer);
     vconn_close(vconn);
 }
@@ -951,6 +974,8 @@ do_add_flows(int argc OVS_UNUSED, char *argv[])
     struct vconn *vconn;
     FILE *file;
     char line[1024];
+    uint8_t table_idx;
+    int table_id_enabled = 0;
 
     file = fopen(argv[2], "r");
     if (file == NULL) {
@@ -983,7 +1008,7 @@ do_add_flows(int argc OVS_UNUSED, char *argv[])
          * call. */
         make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
         str_to_flow(line, &match, buffer,
-                    NULL, NULL, &priority, &idle_timeout, &hard_timeout,
+                    &table_idx, NULL, &priority, &idle_timeout, &hard_timeout,
                     &cookie);
         ofm = buffer->data;
         ofm->match = match;
@@ -994,6 +1019,18 @@ do_add_flows(int argc OVS_UNUSED, char *argv[])
         ofm->buffer_id = htonl(UINT32_MAX);
         ofm->priority = htons(priority);
 
+        if (table_idx != 0xff) {
+            if(!table_id_enabled) {
+                enable_flow_mod_table_id_ext(vconn, 1);
+                table_id_enabled = 1;
+            }
+            ofm->command = htons(ntohs(ofm->command) | (table_idx << 8));
+        } else {
+            if(table_id_enabled) {
+                enable_flow_mod_table_id_ext(vconn, 0);
+                table_id_enabled = 0;
+            }
+        }
         send_openflow_buffer(vconn, buffer);
     }
     vconn_close(vconn);
@@ -1009,12 +1046,13 @@ do_mod_flows(int argc OVS_UNUSED, char *argv[])
     struct ofpbuf *buffer;
     struct ofp_flow_mod *ofm;
     struct ofp_match match;
+    uint8_t table_idx;
 
     /* Parse and send.  str_to_flow() will expand and reallocate the data in
      * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
     make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
     str_to_flow(argv[2], &match, buffer,
-                NULL, NULL, &priority, &idle_timeout, &hard_timeout,
+                &table_idx, NULL, &priority, &idle_timeout, &hard_timeout,
                 &cookie);
     ofm = buffer->data;
     ofm->match = match;
@@ -1030,6 +1068,10 @@ do_mod_flows(int argc OVS_UNUSED, char *argv[])
     ofm->priority = htons(priority);
 
     open_vconn(argv[1], &vconn);
+    if (table_idx != 0xff) {
+        enable_flow_mod_table_id_ext(vconn, 1);
+        ofm->command = htons(ntohs(ofm->command) | (table_idx << 8));
+    }
     send_openflow_buffer(vconn, buffer);
     vconn_close(vconn);
 }
@@ -1041,6 +1083,7 @@ static void do_del_flows(int argc, char *argv[])
     uint16_t out_port;
     struct ofpbuf *buffer;
     struct ofp_flow_mod *ofm;
+    uint8_t table_idx;
 
     /* Parse and send. */
     ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
@@ -1058,6 +1101,10 @@ static void do_del_flows(int argc, char *argv[])
     ofm->priority = htons(priority);
 
     open_vconn(argv[1], &vconn);
+    if (table_idx != 0xff) {
+        enable_flow_mod_table_id_ext(vconn, 1);
+        ofm->command = htons(ntohs(ofm->command) | (table_idx << 8));
+    }
     send_openflow_buffer(vconn, buffer);
     vconn_close(vconn);
 }
-- 
1.7.1





More information about the dev mailing list