From d6a1e67a8d9883087fe8712400d43b559618994f Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Sat, 16 Aug 2008 09:43:05 -0700 Subject: [PATCH] Add stats message that allows querying description of components in OpenFlow. --- datapath/datapath.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/openflow.h | 17 ++++++++++++++++- lib/ofp-print.c | 16 ++++++++++++++++ switch/datapath.c | 23 +++++++++++++++++++++++ switch/switch.c | 27 ++++++++++++++++++++++++++- utilities/dpctl.c | 8 ++++++++ 6 files changed, 131 insertions(+), 2 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 5b5967605..7c264936b 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -41,6 +41,23 @@ #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 @@ -1079,6 +1096,24 @@ static struct nla_policy dp_genl_openflow_policy[DP_GENL_A_MAX + 1] = { [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; @@ -1350,6 +1385,13 @@ struct stats_type { }; 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), diff --git a/include/openflow.h b/include/openflow.h index ba25687b5..cd216736c 100644 --- a/include/openflow.h +++ b/include/openflow.h @@ -424,6 +424,11 @@ struct ofp_error_msg { 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. */ @@ -465,6 +470,16 @@ struct ofp_stats_reply { }; 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 */ @@ -522,7 +537,7 @@ struct ofp_table_stats { }; 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; diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 01e49b78c..1f05675bb 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -557,6 +557,17 @@ ofp_print_port_status(struct ds *string, const void *oh, size_t len, 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) @@ -750,6 +761,11 @@ print_stats(struct ds *string, int type, const void *body, size_t body_len, }; 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), diff --git a/switch/datapath.c b/switch/datapath.c index 4e7b6256b..f9f4a8db8 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -56,6 +56,10 @@ #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 \ @@ -1155,6 +1159,18 @@ recv_flow(struct datapath *dp, const struct sender *sender UNUSED, } } +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; @@ -1374,6 +1390,13 @@ struct stats_type { }; 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), diff --git a/switch/switch.c b/switch/switch.c index 3a9c60426..61fbfb985 100644 --- a/switch/switch.c +++ b/switch/switch.c @@ -57,6 +57,13 @@ #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; @@ -152,7 +159,10 @@ static void 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[] = { @@ -165,6 +175,9 @@ parse_options(int argc, char *argv[]) {"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}, }; @@ -228,6 +241,18 @@ parse_options(int argc, char *argv[]) } 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"); diff --git a/utilities/dpctl.c b/utilities/dpctl.c index b074edd79..f96941236 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -186,6 +186,7 @@ usage(void) #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" @@ -388,6 +389,12 @@ do_show(int argc UNUSED, char *argv[]) } +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[]) { @@ -890,6 +897,7 @@ static struct command all_commands[] = { { "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 }, -- 2.43.0