From 95ee79a8c9352237b900bf829e7cf722f3f0ec2b Mon Sep 17 00:00:00 2001 From: Hao Zheng Date: Thu, 29 Jul 2010 18:19:05 -0700 Subject: [PATCH] ovs-ofctl: Adding support for table ID. 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 54d222a47..a3466dae9 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 ac8fdb70c..598f6526f 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")) { @@ -915,6 +918,21 @@ do_dump_aggregate(int argc, char *argv[]) dump_stats_transaction(argv[1], request); } +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[]) { @@ -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); } -- 2.43.0