#include "compat.h"
+/* Strings to describe the manufacturer, hardware, and software. This data
+ * is queriable through the version stats message. */
+static char mfr_desc[VERSION_STR_LEN] = "Nicira Networks";
+static char hw_desc[VERSION_STR_LEN] = "Reference Linux Kernel Module";
+static char sw_desc[VERSION_STR_LEN] = VERSION;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+module_param_string(mfr_desc, mfr_desc, sizeof mfr_desc, 0444);
+module_param_string(hw_desc, hw_desc, sizeof hw_desc, 0444);
+module_param_string(sw_desc, sw_desc, sizeof sw_desc, 0444);
+#else
+MODULE_PARM(mfr_desc, "s");
+MODULE_PARM(hw_desc, "s");
+MODULE_PARM(sw_desc, "s");
+#endif
+
+
/* Number of milliseconds between runs of the maintenance thread. */
#define MAINT_SLEEP_MSECS 1000
[DP_GENL_A_DP_IDX] = { .type = NLA_U32 },
};
+static int version_stats_dump(struct datapath *dp, void *state,
+ void *body, int *body_len)
+{
+ struct ofp_version_stats *ovs = body;
+ int n_bytes = sizeof *ovs;
+
+ if (n_bytes > *body_len) {
+ return -ENOBUFS;
+ }
+ *body_len = n_bytes;
+
+ strncpy(ovs->mfr_desc, mfr_desc, sizeof ovs->mfr_desc);
+ strncpy(ovs->hw_desc, hw_desc, sizeof ovs->hw_desc);
+ strncpy(ovs->sw_desc, sw_desc, sizeof ovs->sw_desc);
+
+ return 0;
+}
+
struct flow_stats_state {
int table_idx;
struct sw_table_position position;
};
static const struct stats_type stats[] = {
+ [OFPST_VERSION] = {
+ 0,
+ 0,
+ NULL,
+ version_stats_dump,
+ NULL
+ },
[OFPST_FLOW] = {
sizeof(struct ofp_flow_stats_request),
sizeof(struct ofp_flow_stats_request),
OFP_ASSERT(sizeof(struct ofp_error_msg) == 12);
enum ofp_stats_types {
+ /* Description of this OpenFlow switch.
+ * The request body is empty.
+ * The reply body is struct ofp_version_stats. */
+ OFPST_VERSION,
+
/* Individual flow statistics.
* The request body is struct ofp_flow_stats_request.
* The reply body is an array of struct ofp_flow_stats. */
};
OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
+#define VERSION_STR_LEN 256
+/* Body of reply to OFPST_VERSION request. Each entry is a NULL-terminated
+ * ASCII string. */
+struct ofp_version_stats {
+ char mfr_desc[VERSION_STR_LEN]; /* Manufacturer description. */
+ char hw_desc[VERSION_STR_LEN]; /* Hardware description. */
+ char sw_desc[VERSION_STR_LEN]; /* Software description. */
+};
+OFP_ASSERT(sizeof(struct ofp_version_stats) == 768);
+
/* Body for ofp_stats_request of type OFPST_FLOW. */
struct ofp_flow_stats_request {
struct ofp_match match; /* Fields to match */
};
OFP_ASSERT(sizeof(struct ofp_table_stats) == 56);
-/* Statistics about a particular port. If a counter is unsupported, set
+/* Body of reply to OFPST_PORT request. If a counter is unsupported, set
* the field to all ones. */
struct ofp_port_stats {
uint16_t port_no;
ofp_print_phy_port(string, &ops->desc);
}
+static void
+ofp_version_stats_reply(struct ds *string, const void *body, size_t len,
+ int verbosity)
+{
+ const struct ofp_version_stats *vs = body;
+
+ ds_put_format(string, "Manufacturer: %s\n", vs->mfr_desc);
+ ds_put_format(string, "Hardware: %s\n", vs->hw_desc);
+ ds_put_format(string, "Software: %s\n", vs->sw_desc);
+}
+
static void
ofp_flow_stats_request(struct ds *string, const void *oh, size_t len,
int verbosity)
};
static const struct stats_type stats_types[] = {
+ [OFPST_VERSION] = {
+ "version",
+ { 0, 0, NULL },
+ { 0, SIZE_MAX, ofp_version_stats_reply },
+ },
[OFPST_FLOW] = {
"flow",
{ sizeof(struct ofp_flow_stats_request),
#define BRIDGE_PORT_NO_FLOOD 0x00000001
+extern char mfr_desc;
+extern char hw_desc;
+extern char sw_desc;
+
/* Capabilities supported by this implementation. */
#define OFP_SUPPORTED_CAPABILITIES ( OFPC_FLOW_STATS \
| OFPC_TABLE_STATS \
}
}
+static int version_stats_dump(struct datapath *dp, void *state,
+ struct buffer *buffer)
+{
+ struct ofp_version_stats *ovs = buffer_put_uninit(buffer, sizeof *ovs);
+
+ strncpy(ovs->mfr_desc, &mfr_desc, sizeof ovs->mfr_desc);
+ strncpy(ovs->hw_desc, &hw_desc, sizeof ovs->hw_desc);
+ strncpy(ovs->sw_desc, &sw_desc, sizeof ovs->sw_desc);
+
+ return 0;
+}
+
struct flow_stats_state {
int table_idx;
struct sw_table_position position;
};
static const struct stats_type stats[] = {
+ [OFPST_VERSION] = {
+ 0,
+ 0,
+ NULL,
+ version_stats_dump,
+ NULL
+ },
[OFPST_FLOW] = {
sizeof(struct ofp_flow_stats_request),
sizeof(struct ofp_flow_stats_request),
#define THIS_MODULE VLM_switch
#include "vlog.h"
+
+/* Strings to describe the manufacturer, hardware, and software. This data
+ * is queriable through the version stats message. */
+char mfr_desc[VERSION_STR_LEN] = "Nicira Networks";
+char hw_desc[VERSION_STR_LEN] = "Reference User-Space Switch";
+char sw_desc[VERSION_STR_LEN] = VERSION;
+
static void parse_options(int argc, char *argv[]);
static void usage(void) NO_RETURN;
parse_options(int argc, char *argv[])
{
enum {
- OPT_MAX_BACKOFF = UCHAR_MAX + 1
+ OPT_MAX_BACKOFF = UCHAR_MAX + 1,
+ OPT_MFR_DESC,
+ OPT_HW_DESC,
+ OPT_SW_DESC
};
static struct option long_options[] = {
{"verbose", optional_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
+ {"mfr-desc", required_argument, 0, OPT_MFR_DESC},
+ {"hw-desc", required_argument, 0, OPT_HW_DESC},
+ {"sw-desc", required_argument, 0, OPT_SW_DESC},
VCONN_SSL_LONG_OPTIONS
{0, 0, 0, 0},
};
}
break;
+ case OPT_MFR_DESC:
+ strncpy(mfr_desc, optarg, sizeof mfr_desc);
+ break;
+
+ case OPT_HW_DESC:
+ strncpy(hw_desc, optarg, sizeof hw_desc);
+ break;
+
+ case OPT_SW_DESC:
+ strncpy(sw_desc, optarg, sizeof sw_desc);
+ break;
+
case 'l':
if (listen_vconn_name) {
fatal(0, "-l or --listen may be only specified once");
#endif
"\nFor local datapaths and remote switches:\n"
" show SWITCH show information\n"
+ " dump-version SWITCH print version information\n"
" dump-tables SWITCH print table stats\n"
" dump-ports SWITCH print port statistics\n"
" dump-flows SWITCH print all flow entries\n"
}
+static void
+do_dump_version(int argc, char *argv[])
+{
+ dump_trivial_stats_transaction(argv[1], OFPST_VERSION);
+}
+
static void
do_dump_tables(int argc, char *argv[])
{
{ "help", 0, INT_MAX, do_help },
{ "monitor", 1, 1, do_monitor },
+ { "dump-version", 1, 1, do_dump_version },
{ "dump-tables", 1, 1, do_dump_tables },
{ "dump-flows", 1, 2, do_dump_flows },
{ "dump-aggregate", 1, 2, do_dump_aggregate },