- ovs-dpctl:
- Support requesting the port number with the "port_no" option in
the "add-if" command.
+ - ovs-appctl:
+ - New "dpif/dump-dps", "dpif/show", and "dpif/dump-flows" command
+ that mimic the equivalent ovs-dpctl commands.
- ovs-pki: The "online PKI" features have been removed, along with
the ovs-pki-cgi program that facilitated it, because of some
alarmist insecurity claims. We do not believe that these claims
lib/stress-unixctl.man \
lib/vlog-unixctl.man \
lib/vlog.man \
+ ofproto/ofproto-dpif-unixctl.man \
ofproto/ofproto-unixctl.man \
ovsdb/remote-active.man \
ovsdb/remote-passive.man
lib/stress-unixctl.man:
lib/vlog-unixctl.man:
lib/vlog.man:
+ofproto/ofproto-dpif-unixctl.man:
ofproto/ofproto-unixctl.man:
ovsdb/remote-active.man:
ovsdb/remote-passive.man:
ofproto/pinsched.c \
ofproto/pinsched.h
-MAN_FRAGMENTS += ofproto/ofproto-unixctl.man
+MAN_FRAGMENTS += ofproto/ofproto-unixctl.man ofproto/ofproto-dpif-unixctl.man
--- /dev/null
+.SS "DATAPATH COMMANDS"
+These commands manage logical datapaths. They are are similar to the
+equivalent \fBovs\-dpctl\fR commands.
+.
+.IP "\fBdpif/dump\-dps\fR"
+Prints the name of each configured datapath on a separate line.
+.
+.IP "\fBdpif/show\fR [\fIdp\fR...]"
+Prints a summary of configured datapaths, including statistics and a
+list of connected ports. The port information includes the OpenFlow
+port number, datapath port number, and the type. (The local port is
+identified as OpenFlow port 65534.)
+.IP
+If one or more datapaths are specified, information on only those
+datapaths are displayed. Otherwise, information about all configured
+datapaths are shown.
+.
+.IP "\fBdpif/dump\-flows \fIdp\fR"
+Prints to the console all flow entries in datapath \fIdp\fR's
+flow table.
+.IP
+This command is primarily useful for debugging Open vSwitch. The flow
+table entries that it displays are not OpenFlow flow entries. Instead,
+they are different and considerably simpler flows maintained by the
+datapath module. If you wish to see the OpenFlow flow entries, use
+\fBovs\-ofctl dump\-flows\fR.
+.
+.IP "\fBdpif/del\-flows \fIdp\fR"
+Deletes all flow entries from datapath \fIdp\fR's flow table and
+underlying datapath implementation (e.g., kernel datapath module).
+.IP
+This command is primarily useful for debugging Open vSwitch. As
+discussed in \fBdpif/dump\-flows\fR, these entries are
+not OpenFlow flow entries.
#include "ofproto-dpif-sflow.h"
#include "poll-loop.h"
#include "simap.h"
+#include "smap.h"
#include "timer.h"
#include "unaligned.h"
#include "unixctl.h"
ds_destroy(&reply);
}
+/* Store the current ofprotos in 'ofproto_shash'. Returns a sorted list
+ * of the 'ofproto_shash' nodes. It is the responsibility of the caller
+ * to destroy 'ofproto_shash' and free the returned value. */
+static const struct shash_node **
+get_ofprotos(struct shash *ofproto_shash)
+{
+ const struct ofproto_dpif *ofproto;
+
+ HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+ char *name = xasprintf("%s@%s", ofproto->up.type, ofproto->up.name);
+ shash_add_nocopy(ofproto_shash, name, ofproto);
+ }
+
+ return shash_sort(ofproto_shash);
+}
+
+static void
+ofproto_unixctl_dpif_dump_dps(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED,
+ void *aux OVS_UNUSED)
+{
+ struct ds ds = DS_EMPTY_INITIALIZER;
+ struct shash ofproto_shash;
+ const struct shash_node **sorted_ofprotos;
+ int i;
+
+ shash_init(&ofproto_shash);
+ sorted_ofprotos = get_ofprotos(&ofproto_shash);
+ for (i = 0; i < shash_count(&ofproto_shash); i++) {
+ const struct shash_node *node = sorted_ofprotos[i];
+ ds_put_format(&ds, "%s\n", node->name);
+ }
+
+ shash_destroy(&ofproto_shash);
+ free(sorted_ofprotos);
+
+ unixctl_command_reply(conn, ds_cstr(&ds));
+ ds_destroy(&ds);
+}
+
+static void
+show_dp_format(const struct ofproto_dpif *ofproto, struct ds *ds)
+{
+ struct dpif_dp_stats s;
+ const struct shash_node **ports;
+ int i;
+
+ dpif_get_dp_stats(ofproto->dpif, &s);
+
+ ds_put_format(ds, "%s@%s:\n", ofproto->up.type, ofproto->up.name);
+ ds_put_format(ds,
+ "\tlookups: hit:%"PRIu64" missed:%"PRIu64" lost:%"PRIu64"\n",
+ s.n_hit, s.n_missed, s.n_lost);
+ ds_put_format(ds, "\tflows: %"PRIu64"\n", s.n_flows);
+
+ ports = shash_sort(&ofproto->up.port_by_name);
+ for (i = 0; i < shash_count(&ofproto->up.port_by_name); i++) {
+ const struct shash_node *node = ports[i];
+ struct ofport *ofport = node->data;
+ const char *name = netdev_get_name(ofport->netdev);
+ const char *type = netdev_get_type(ofport->netdev);
+
+ ds_put_format(ds, "\t%s %u/%u:", name, ofport->ofp_port,
+ ofp_port_to_odp_port(ofproto, ofport->ofp_port));
+ if (strcmp(type, "system")) {
+ struct netdev *netdev;
+ int error;
+
+ ds_put_format(ds, " (%s", type);
+
+ error = netdev_open(name, type, &netdev);
+ if (!error) {
+ struct smap config;
+
+ smap_init(&config);
+ error = netdev_get_config(netdev, &config);
+ if (!error) {
+ const struct smap_node **nodes;
+ size_t i;
+
+ nodes = smap_sort(&config);
+ for (i = 0; i < smap_count(&config); i++) {
+ const struct smap_node *node = nodes[i];
+ ds_put_format(ds, "%c %s=%s", i ? ',' : ':',
+ node->key, node->value);
+ }
+ free(nodes);
+ }
+ smap_destroy(&config);
+
+ netdev_close(netdev);
+ }
+ ds_put_char(ds, ')');
+ }
+ ds_put_char(ds, '\n');
+ }
+ free(ports);
+}
+
+static void
+ofproto_unixctl_dpif_show(struct unixctl_conn *conn, int argc,
+ const char *argv[], void *aux OVS_UNUSED)
+{
+ struct ds ds = DS_EMPTY_INITIALIZER;
+ const struct ofproto_dpif *ofproto;
+
+ if (argc > 1) {
+ int i;
+ for (i = 1; i < argc; i++) {
+ ofproto = ofproto_dpif_lookup(argv[i]);
+ if (!ofproto) {
+ ds_put_format(&ds, "Unknown bridge %s (use dpif/dump-dps "
+ "for help)", argv[i]);
+ unixctl_command_reply_error(conn, ds_cstr(&ds));
+ return;
+ }
+ show_dp_format(ofproto, &ds);
+ }
+ } else {
+ struct shash ofproto_shash;
+ const struct shash_node **sorted_ofprotos;
+ int i;
+
+ shash_init(&ofproto_shash);
+ sorted_ofprotos = get_ofprotos(&ofproto_shash);
+ for (i = 0; i < shash_count(&ofproto_shash); i++) {
+ const struct shash_node *node = sorted_ofprotos[i];
+ show_dp_format(node->data, &ds);
+ }
+
+ shash_destroy(&ofproto_shash);
+ free(sorted_ofprotos);
+ }
+
+ unixctl_command_reply(conn, ds_cstr(&ds));
+ ds_destroy(&ds);
+}
+
+static void
+ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn,
+ int argc OVS_UNUSED, const char *argv[],
+ void *aux OVS_UNUSED)
+{
+ struct ds ds = DS_EMPTY_INITIALIZER;
+ const struct ofproto_dpif *ofproto;
+ struct subfacet *subfacet;
+
+ ofproto = ofproto_dpif_lookup(argv[1]);
+ if (!ofproto) {
+ unixctl_command_reply_error(conn, "no such bridge");
+ return;
+ }
+
+ HMAP_FOR_EACH (subfacet, hmap_node, &ofproto->subfacets) {
+ struct odputil_keybuf keybuf;
+ struct ofpbuf key;
+
+ subfacet_get_key(subfacet, &keybuf, &key);
+ odp_flow_key_format(key.data, key.size, &ds);
+
+ ds_put_format(&ds, ", packets:%"PRIu64", bytes:%"PRIu64", used:",
+ subfacet->dp_packet_count, subfacet->dp_byte_count);
+ if (subfacet->used) {
+ ds_put_format(&ds, "%.3fs",
+ (time_msec() - subfacet->used) / 1000.0);
+ } else {
+ ds_put_format(&ds, "never");
+ }
+ if (subfacet->facet->tcp_flags) {
+ ds_put_cstr(&ds, ", flags:");
+ packet_format_tcp_flags(&ds, subfacet->facet->tcp_flags);
+ }
+
+ ds_put_cstr(&ds, ", actions:");
+ format_odp_actions(&ds, subfacet->actions, subfacet->actions_len);
+ ds_put_char(&ds, '\n');
+ }
+
+ unixctl_command_reply(conn, ds_cstr(&ds));
+ ds_destroy(&ds);
+}
+
+static void
+ofproto_unixctl_dpif_del_flows(struct unixctl_conn *conn,
+ int argc OVS_UNUSED, const char *argv[],
+ void *aux OVS_UNUSED)
+{
+ struct ds ds = DS_EMPTY_INITIALIZER;
+ struct ofproto_dpif *ofproto;
+
+ ofproto = ofproto_dpif_lookup(argv[1]);
+ if (!ofproto) {
+ unixctl_command_reply_error(conn, "no such bridge");
+ return;
+ }
+
+ flush(&ofproto->up);
+
+ unixctl_command_reply(conn, ds_cstr(&ds));
+ ds_destroy(&ds);
+}
+
static void
ofproto_dpif_unixctl_init(void)
{
ofproto_dpif_unclog, NULL);
unixctl_command_register("ofproto/self-check", "[bridge]", 0, 1,
ofproto_dpif_self_check, NULL);
+ unixctl_command_register("dpif/dump-dps", "", 0, 0,
+ ofproto_unixctl_dpif_dump_dps, NULL);
+ unixctl_command_register("dpif/show", "[bridge]", 0, INT_MAX,
+ ofproto_unixctl_dpif_show, NULL);
+ unixctl_command_register("dpif/dump-flows", "bridge", 1, 1,
+ ofproto_unixctl_dpif_dump_flows, NULL);
+ unixctl_command_register("dpif/del-flows", "bridge", 1, 1,
+ ofproto_unixctl_dpif_del_flows, NULL);
}
\f
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
])
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/dump-dps])
+OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl dpif/dump-dps], [0], [dnl
+dummy@br0
+dummy@br1
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/show])
+OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl dpif/show], [0], [dnl
+dummy@br0:
+ lookups: hit:0 missed:0 lost:0
+ flows: 0
+ br0 65534/100: (dummy)
+ p1 1/1: (dummy)
+ p2 2/2: (dummy)
+dummy@br1:
+ lookups: hit:0 missed:0 lost:0
+ flows: 0
+ br1 65534/101: (dummy)
+ p3 3/3: (dummy)
+])
+
+AT_CHECK([ovs-appctl dpif/show br0], [0], [dnl
+dummy@br0:
+ lookups: hit:0 missed:0 lost:0
+ flows: 0
+ br0 65534/100: (dummy)
+ p1 1/1: (dummy)
+ p2 2/2: (dummy)
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/dump-flows])
+OVS_VSWITCHD_START([add-br br1 -- \
+ set bridge br1 datapath-type=dummy fail-mode=secure])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
+in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:drop
+in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0), packets:0, bytes:0, used:0.0s, actions:drop
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
+in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:drop
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - ovs-appctl dpif/del-flows])
+OVS_VSWITCHD_START([add-br br1 -- \
+ set bridge br1 datapath-type=dummy fail-mode=secure])
+ADD_OF_PORTS([br0], [1], [2])
+ADD_OF_PORTS([br1], [3])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'], [0], [success
+])
+AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
+in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:drop
+in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0), packets:0, bytes:0, used:0.0s, actions:drop
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
+in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:drop
+])
+
+AT_CHECK([ovs-appctl dpif/del-flows br0])
+AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
+])
+
+AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
+in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:0.0s, actions:drop
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
m4_define([STRIP_XIDS], [[sed 's/ (xid=0x[0-9a-fA-F]*)//']])
m4_define([STRIP_DURATION], [[sed 's/\bduration=[0-9.]*s/duration=?s/']])
+m4_define([STRIP_USED], [[sed 's/used:[0-9]\.[0-9]*/used:0.0/']])
m4_define([TESTABLE_LOG], [-vPATTERN:ANY:'%c|%p|%m'])
# OVS_VSWITCHD_START([vsctl-args], [vsctl-output])
This command is primarily useful for debugging Open vSwitch. The flow
table entries that it displays are not
OpenFlow flow entries. Instead, they are different and considerably
-simpler flows maintained by the Open vSwitch kernel module.
+simpler flows maintained by the Open vSwitch kernel module. If you wish
+to see the OpenFlow flow entries, use \fBovs\-ofctl dump\-flows\fR.
.IP "\fBdel\-flows \fIdp\fR"
Deletes all flow entries from datapath \fIdp\fR's flow table.
.IP
then displays detailed information about all interfaces with CFM
enabled.
.
+.so ofproto/ofproto-dpif-unixctl.man
.so ofproto/ofproto-unixctl.man
.so lib/vlog-unixctl.man
.so lib/memory-unixctl.man