mirror of
https://github.com/openvswitch/ovs
synced 2025-08-30 13:58:14 +00:00
ovs-dpctl: New add-flow, mod-flow, del-flow commands.
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
parent
b093fa6123
commit
186afbfef9
2
NEWS
2
NEWS
@ -10,6 +10,8 @@ post-v1.10.0
|
|||||||
1.1 and later are now implemented.
|
1.1 and later are now implemented.
|
||||||
* New "stack" extension for use in actions, to push and pop from
|
* New "stack" extension for use in actions, to push and pop from
|
||||||
NXM fields.
|
NXM fields.
|
||||||
|
- ovs-dpctl:
|
||||||
|
* New debugging commands "add-flow", "mod-flow", "del-flow".
|
||||||
|
|
||||||
|
|
||||||
v1.10.0 - xx xxx xxxx
|
v1.10.0 - xx xxx xxxx
|
||||||
|
@ -104,27 +104,54 @@ port.
|
|||||||
If one or more datapaths are specified, information on only those
|
If one or more datapaths are specified, information on only those
|
||||||
datapaths are displayed. Otherwise, \fBovs\-dpctl\fR displays information
|
datapaths are displayed. Otherwise, \fBovs\-dpctl\fR displays information
|
||||||
about all configured datapaths.
|
about all configured datapaths.
|
||||||
|
.SS "DEBUGGING COMMANDS"
|
||||||
|
The following commands are primarily useful for debugging Open
|
||||||
|
vSwitch. The flow table entries (both matches and actions) that they
|
||||||
|
work with are not OpenFlow flow entries. Instead, they are different
|
||||||
|
and considerably simpler flows maintained by the Open vSwitch kernel
|
||||||
|
module. Use \fBovs\-ofctl\fR(8), instead, to work with OpenFlow flow
|
||||||
|
entries.
|
||||||
|
.
|
||||||
|
.PP
|
||||||
|
The \fIdp\fR argument to each of these commands is optional when
|
||||||
|
exactly one datapath exists, in which case that datapath is the
|
||||||
|
default. When multiple datapaths exist, then a datapath name is
|
||||||
|
required.
|
||||||
.
|
.
|
||||||
.IP "\fBdump\-flows\fR [\fIdp\fR]"
|
.IP "\fBdump\-flows\fR [\fIdp\fR]"
|
||||||
Prints to the console all flow entries in datapath \fIdp\fR's
|
Prints to the console all flow entries in datapath \fIdp\fR's
|
||||||
flow table. If \fIdp\fR is not specified and exactly one datapath
|
flow table.
|
||||||
exists, the flows for that datapath will be printed.
|
.
|
||||||
|
.IP "\fBadd\-flow\fR [\fIdp\fR] \fIflow actions\fR"
|
||||||
|
.IQ "[\fB\-\-clear\fR] [\fB\-\-may-create\fR] [\fB\-s\fR | \fB\-\-statistics\fR] \fBmod\-flow\fR [\fIdp\fR] \fIflow actions\fR"
|
||||||
|
Adds or modifies a flow in \fIdp\fR's flow table that, when a packet
|
||||||
|
matching \fIflow\fR arrives, causes \fIactions\fR to be executed.
|
||||||
.IP
|
.IP
|
||||||
This command is primarily useful for debugging Open vSwitch. The flow
|
The \fBadd\-flow\fR command succeeds only if \fIflow\fR does not
|
||||||
table entries that it displays are not
|
already exist in \fIdp\fR. Contrariwise, \fBmod\-flow\fR without
|
||||||
OpenFlow flow entries. Instead, they are different and considerably
|
\fB\-\-may\-create\fR only modifies the actions for an existing flow.
|
||||||
simpler flows maintained by the Open vSwitch kernel module. If you wish
|
With \fB\-\-may\-create\fR, \fBmod\-flow\fR will add a new flow or
|
||||||
to see the OpenFlow flow entries, use \fBovs\-ofctl dump\-flows\fR.
|
modify an existing one.
|
||||||
|
.IP
|
||||||
|
If \fB\-s\fR or \fB\-\-statistics\fR is specified, then
|
||||||
|
\fBmod\-flows\fR prints the modified flow's statistics. A flow's
|
||||||
|
statistics are the number of packets and bytes that have passed
|
||||||
|
through the flow, the elapsed time since the flow last processed a
|
||||||
|
packet (if ever), and (for TCP flows) the union of the TCP flags
|
||||||
|
processed through the flow.
|
||||||
|
.IP
|
||||||
|
With \fB\-\-clear\fR, \fBmod\-flows\fR zeros out the flow's
|
||||||
|
statistics. The statistics printed if \fB\-s\fR or
|
||||||
|
\fB\-\-statistics\fR is also specified are those from just before
|
||||||
|
clearing the statistics.
|
||||||
|
.
|
||||||
|
.IP "[\fB\-s\fR | \fB\-\-statistics\fR] \fBdel\-flow\fR [\fIdp\fR] \fIflow\fR"
|
||||||
|
Deletes the flow from \fIdp\fR's flow table that matches \fIflow\fR.
|
||||||
|
If \fB\-s\fR or \fB\-\-statistics\fR is specified, then
|
||||||
|
\fBmod\-flows\fR prints the deleted flow's statistics.
|
||||||
.
|
.
|
||||||
.IP "\fBdel\-flows\fR [\fIdp\fR]"
|
.IP "\fBdel\-flows\fR [\fIdp\fR]"
|
||||||
Deletes all flow entries from datapath \fIdp\fR's flow table. If
|
Deletes all flow entries from datapath \fIdp\fR's flow table.
|
||||||
\fIdp\fR is not specified and exactly one datapath exists, the flows for
|
|
||||||
that datapath will be deleted.
|
|
||||||
.IP
|
|
||||||
This command is primarily useful for debugging Open vSwitch. As
|
|
||||||
discussed in \fBdump\-flows\fR, these entries are
|
|
||||||
not OpenFlow flow entries. By deleting them, the process that set them
|
|
||||||
up may be confused about their disappearance.
|
|
||||||
.
|
.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.IP "\fB\-s\fR"
|
.IP "\fB\-s\fR"
|
||||||
|
@ -51,9 +51,15 @@
|
|||||||
|
|
||||||
VLOG_DEFINE_THIS_MODULE(dpctl);
|
VLOG_DEFINE_THIS_MODULE(dpctl);
|
||||||
|
|
||||||
/* -s, --statistics: Print port statistics? */
|
/* -s, --statistics: Print port/flow statistics? */
|
||||||
static bool print_statistics;
|
static bool print_statistics;
|
||||||
|
|
||||||
|
/* --clear: Reset existing statistics to zero when modifying a flow? */
|
||||||
|
static bool zero_statistics;
|
||||||
|
|
||||||
|
/* --may-create: Allow mod-flows command to create a new flow? */
|
||||||
|
static bool may_create;
|
||||||
|
|
||||||
/* -m, --more: Output verbosity.
|
/* -m, --more: Output verbosity.
|
||||||
*
|
*
|
||||||
* So far only undocumented commands honor this option, so we don't document
|
* So far only undocumented commands honor this option, so we don't document
|
||||||
@ -79,11 +85,14 @@ static void
|
|||||||
parse_options(int argc, char *argv[])
|
parse_options(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
OPT_DUMMY = UCHAR_MAX + 1,
|
OPT_CLEAR = UCHAR_MAX + 1,
|
||||||
|
OPT_MAY_CREATE,
|
||||||
VLOG_OPTION_ENUMS
|
VLOG_OPTION_ENUMS
|
||||||
};
|
};
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"statistics", no_argument, NULL, 's'},
|
{"statistics", no_argument, NULL, 's'},
|
||||||
|
{"clear", no_argument, NULL, OPT_CLEAR},
|
||||||
|
{"may-create", no_argument, NULL, OPT_MAY_CREATE},
|
||||||
{"more", no_argument, NULL, 'm'},
|
{"more", no_argument, NULL, 'm'},
|
||||||
{"timeout", required_argument, NULL, 't'},
|
{"timeout", required_argument, NULL, 't'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
@ -107,6 +116,14 @@ parse_options(int argc, char *argv[])
|
|||||||
print_statistics = true;
|
print_statistics = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPT_CLEAR:
|
||||||
|
zero_statistics = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_MAY_CREATE:
|
||||||
|
may_create = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
verbosity++;
|
verbosity++;
|
||||||
break;
|
break;
|
||||||
@ -154,14 +171,20 @@ usage(void)
|
|||||||
" show show basic info on all datapaths\n"
|
" show show basic info on all datapaths\n"
|
||||||
" show DP... show basic info on each DP\n"
|
" show DP... show basic info on each DP\n"
|
||||||
" dump-flows DP display flows in DP\n"
|
" dump-flows DP display flows in DP\n"
|
||||||
|
" add-flow DP FLOW ACTIONS add FLOW with ACTIONS to DP\n"
|
||||||
|
" mod-flow DP FLOW ACTIONS change FLOW actions to ACTIONS in DP\n"
|
||||||
|
" del-flow DP FLOW delete FLOW from DP\n"
|
||||||
" del-flows DP delete all flows from DP\n"
|
" del-flows DP delete all flows from DP\n"
|
||||||
"Each IFACE on add-dp, add-if, and set-if may be followed by\n"
|
"Each IFACE on add-dp, add-if, and set-if may be followed by\n"
|
||||||
"comma-separated options. See ovs-dpctl(8) for syntax, or the\n"
|
"comma-separated options. See ovs-dpctl(8) for syntax, or the\n"
|
||||||
"Interface table in ovs-vswitchd.conf.db(5) for an options list.\n",
|
"Interface table in ovs-vswitchd.conf.db(5) for an options list.\n",
|
||||||
program_name, program_name);
|
program_name, program_name);
|
||||||
vlog_usage();
|
vlog_usage();
|
||||||
printf("\nOptions for show:\n"
|
printf("\nOptions for show and mod-flow:\n"
|
||||||
" -s, --statistics print port statistics\n"
|
" -s, --statistics print statistics for port or flow\n"
|
||||||
|
"\nOptions for mod-flow:\n"
|
||||||
|
" --may-create create flow if it doesn't exist\n"
|
||||||
|
" --clear reset existing stats to zero\n"
|
||||||
"\nOther options:\n"
|
"\nOther options:\n"
|
||||||
" -t, --timeout=SECS give up after SECS seconds\n"
|
" -t, --timeout=SECS give up after SECS seconds\n"
|
||||||
" -h, --help display this help message\n"
|
" -h, --help display this help message\n"
|
||||||
@ -747,6 +770,100 @@ dpctl_dump_flows(int argc, char *argv[])
|
|||||||
dpif_close(dpif);
|
dpif_close(dpif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dpctl_put_flow(int argc, char *argv[], enum dpif_flow_put_flags flags)
|
||||||
|
{
|
||||||
|
const char *key_s = argv[argc - 2];
|
||||||
|
const char *actions_s = argv[argc - 1];
|
||||||
|
struct dpif_flow_stats stats;
|
||||||
|
struct ofpbuf actions;
|
||||||
|
struct ofpbuf key;
|
||||||
|
struct dpif *dpif;
|
||||||
|
char *dp_name;
|
||||||
|
|
||||||
|
ofpbuf_init(&key, 0);
|
||||||
|
run(odp_flow_key_from_string(key_s, NULL, &key), "parsing flow key");
|
||||||
|
|
||||||
|
ofpbuf_init(&actions, 0);
|
||||||
|
run(odp_actions_from_string(actions_s, NULL, &actions), "parsing actions");
|
||||||
|
|
||||||
|
dp_name = argc == 3 ? xstrdup(argv[1]) : get_one_dp();
|
||||||
|
run(parsed_dpif_open(dp_name, false, &dpif), "opening datapath");
|
||||||
|
free(dp_name);
|
||||||
|
|
||||||
|
run(dpif_flow_put(dpif, flags,
|
||||||
|
key.data, key.size,
|
||||||
|
actions.data, actions.size,
|
||||||
|
print_statistics ? &stats : NULL),
|
||||||
|
"updating flow table");
|
||||||
|
|
||||||
|
ofpbuf_uninit(&key);
|
||||||
|
ofpbuf_uninit(&actions);
|
||||||
|
|
||||||
|
if (print_statistics) {
|
||||||
|
struct ds s;
|
||||||
|
|
||||||
|
ds_init(&s);
|
||||||
|
dpif_flow_stats_format(&stats, &s);
|
||||||
|
puts(ds_cstr(&s));
|
||||||
|
ds_destroy(&s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dpctl_add_flow(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
dpctl_put_flow(argc, argv, DPIF_FP_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dpctl_mod_flow(int argc OVS_UNUSED, char *argv[])
|
||||||
|
{
|
||||||
|
enum dpif_flow_put_flags flags;
|
||||||
|
|
||||||
|
flags = DPIF_FP_MODIFY;
|
||||||
|
if (may_create) {
|
||||||
|
flags |= DPIF_FP_CREATE;
|
||||||
|
}
|
||||||
|
if (zero_statistics) {
|
||||||
|
flags |= DPIF_FP_ZERO_STATS;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpctl_put_flow(argc, argv, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dpctl_del_flow(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *key_s = argv[argc - 1];
|
||||||
|
struct dpif_flow_stats stats;
|
||||||
|
struct ofpbuf key;
|
||||||
|
struct dpif *dpif;
|
||||||
|
char *dp_name;
|
||||||
|
|
||||||
|
ofpbuf_init(&key, 0);
|
||||||
|
run(odp_flow_key_from_string(key_s, NULL, &key), "parsing flow key");
|
||||||
|
|
||||||
|
dp_name = argc == 2 ? xstrdup(argv[1]) : get_one_dp();
|
||||||
|
run(parsed_dpif_open(dp_name, false, &dpif), "opening datapath");
|
||||||
|
free(dp_name);
|
||||||
|
|
||||||
|
run(dpif_flow_del(dpif,
|
||||||
|
key.data, key.size,
|
||||||
|
print_statistics ? &stats : NULL), "deleting flow");
|
||||||
|
|
||||||
|
ofpbuf_uninit(&key);
|
||||||
|
|
||||||
|
if (print_statistics) {
|
||||||
|
struct ds s;
|
||||||
|
|
||||||
|
ds_init(&s);
|
||||||
|
dpif_flow_stats_format(&stats, &s);
|
||||||
|
puts(ds_cstr(&s));
|
||||||
|
ds_destroy(&s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dpctl_del_flows(int argc, char *argv[])
|
dpctl_del_flows(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -1004,6 +1121,9 @@ static const struct command all_commands[] = {
|
|||||||
{ "dump-dps", 0, 0, dpctl_dump_dps },
|
{ "dump-dps", 0, 0, dpctl_dump_dps },
|
||||||
{ "show", 0, INT_MAX, dpctl_show },
|
{ "show", 0, INT_MAX, dpctl_show },
|
||||||
{ "dump-flows", 0, 1, dpctl_dump_flows },
|
{ "dump-flows", 0, 1, dpctl_dump_flows },
|
||||||
|
{ "add-flow", 2, 3, dpctl_add_flow },
|
||||||
|
{ "mod-flow", 2, 3, dpctl_mod_flow },
|
||||||
|
{ "del-flow", 1, 2, dpctl_del_flow },
|
||||||
{ "del-flows", 0, 1, dpctl_del_flows },
|
{ "del-flows", 0, 1, dpctl_del_flows },
|
||||||
{ "help", 0, INT_MAX, dpctl_help },
|
{ "help", 0, INT_MAX, dpctl_help },
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user