diff --git a/datapath/datapath.c b/datapath/datapath.c index 649e9e1..b1957ba 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -284,6 +285,7 @@ int gen_dp_idx(void) static int new_dp(int dp_idx, const char *dp_name) { struct datapath *dp; + struct new_utsname *u; int err; rtnl_lock(); @@ -310,6 +312,10 @@ static int new_dp(int dp_idx, const char *dp_name) goto err_put; dp->dp_idx = dp_idx; + /* copied from sys_gethostname() */ + u = utsname(); + /* shouldn't need to lock b/c no userspace interactions */ + snprintf(dp->dp_desc, sizeof dp->dp_desc, "%s idx=%d", u->nodename, dp_idx); /* Setup our datapath device */ err = dp_dev_setup(dp, dp_name); @@ -1372,6 +1378,7 @@ static int desc_stats_dump(struct datapath *dp, void *state, strncpy(ods->mfr_desc, mfr_desc, sizeof ods->mfr_desc); strncpy(ods->hw_desc, hw_desc, sizeof ods->hw_desc); strncpy(ods->sw_desc, sw_desc, sizeof ods->sw_desc); + strncpy(ods->dp_desc, dp->dp_desc, sizeof ods->dp_desc); strncpy(ods->serial_num, serial_num, sizeof ods->serial_num); return 0; diff --git a/datapath/datapath.h b/datapath/datapath.h index 244078f..7ce039c 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -47,6 +47,7 @@ struct datapath { /* Data related to the "of" device of this datapath */ struct net_device *netdev; + char dp_desc[DESC_STR_LEN]; /* human readible comment to ID this DP */ /* Configuration set from controller */ uint16_t flags; diff --git a/doc/of-spec/appendix.tex b/doc/of-spec/appendix.tex index daef94b..a21b86b 100755 --- a/doc/of-spec/appendix.tex +++ b/doc/of-spec/appendix.tex @@ -187,10 +187,10 @@ In both the request and response, the \verb|type| field specifies the kind of in \input{enum/ofp_stats_types} \paragraph{Description Statistics} -Information about the switch manufacturer, hardware revision, software revision, and serial number is available from the \verb|OFPST_DESC| stats request type: +Information about the switch manufacturer, hardware revision, software revision, serial number, and a description field is available from the \verb|OFPST_DESC| stats request type: \input{struct/ofp_desc_stats} -Each entry is ASCII formatted and padded on the right with 0 bytes. \verb|DESC_STR_LEN| is \input{define/DESC_STR_LEN}and \verb|SERIAL_NUM_LEN| is \input{define/SERIAL_NUM_LEN}. +Each entry is ASCII formatted and padded on the right with 0 bytes. \verb|DESC_STR_LEN| is \input{define/DESC_STR_LEN}and \verb|SERIAL_NUM_LEN| is \input{define/SERIAL_NUM_LEN}. Note: \footnote{Added to address concerns raised in \url{https://mailman.stanford.edu/pipermail/openflow-spec/2009-September/000504.html}} the dp\_desc field is a free-form string to describe the datapath for debugging purposes, e.g., ``switch3 in room 3120''. As such, it is not guaranteed to be unique and should not be used as the primary identifier for the datapath---use the datapath\_id field from the switch features instead (\S~\ref{cts:handshake}). \paragraph{Individual Flow Statistics} Information about individual flows is requested with the \verb|OFPST_FLOW| stats request type: diff --git a/include/openflow/openflow.h b/include/openflow/openflow.h index acaff07..df77e0e 100644 --- a/include/openflow/openflow.h +++ b/include/openflow/openflow.h @@ -729,8 +729,9 @@ struct ofp_desc_stats { char hw_desc[DESC_STR_LEN]; /* Hardware description. */ char sw_desc[DESC_STR_LEN]; /* Software description. */ char serial_num[SERIAL_NUM_LEN]; /* Serial number. */ + char dp_desc[DESC_STR_LEN]; /* Human readable description of datapath. */ }; -OFP_ASSERT(sizeof(struct ofp_desc_stats) == 800); +OFP_ASSERT(sizeof(struct ofp_desc_stats) == 1056); /* Body for ofp_stats_request of type OFPST_FLOW. */ struct ofp_flow_stats_request { diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 69dd1d1..3da1bf1 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -930,6 +930,7 @@ ofp_desc_stats_reply(struct ds *string, const void *body, size_t len UNUSED, ds_put_format(string, "Manufacturer: %s\n", ods->mfr_desc); ds_put_format(string, "Hardware: %s\n", ods->hw_desc); ds_put_format(string, "Software: %s\n", ods->sw_desc); + ds_put_format(string, "Comment: %s\n", ods->dp_desc); ds_put_format(string, "Serial Num: %s\n", ods->serial_num); } diff --git a/regress/projects/black_box/regress/test_stats_desc/run.pl b/regress/projects/black_box/regress/test_stats_desc/run.pl new file mode 100755 index 0000000..9409ac9 --- /dev/null +++ b/regress/projects/black_box/regress/test_stats_desc/run.pl @@ -0,0 +1,71 @@ +#!/usr/bin/perl -w +# test_flow_stats + +use strict; +use OF::Includes; + +sub stats_desc_test { + + my ( $sock, $options_ref ) = @_; + + my $port_base = $$options_ref{'port_base'}; + + my $hdr_args = { + version => get_of_ver(), + type => $enums{'OFPT_STATS_REQUEST'}, + length => $ofp->sizeof('ofp_stats_request') , # should generate automatically! + xid => 0x00000001 + }; + + my $stats_request_args = { + header => $hdr_args, + type => $enums{'OFPST_DESC'}, + flags => 0 + }; + + my $stats_request = $ofp->pack( 'ofp_stats_request', $stats_request_args ); + + # Send 'stats_request' message + print $sock $stats_request; + + # Should add timeout here - will crash if no reply + my $recvd_mesg; + sysread( $sock, $recvd_mesg, 1512 ) || die "Failed to receive message: $!"; + + # Inspect message + my $resp_size = length($recvd_mesg); + + my $resp_header = $ofp->unpack( 'ofp_stats_reply', $recvd_mesg ); + + #print HexDump ($recvd_mesg); + print Dumper($resp_header); + + # Verify fields + verify_header( $resp_header, 'OFPT_STATS_REPLY', $resp_size ); + + # Unmarshall embedded description + my $resp_body = $ofp->unpack('ofp_desc_stats', + substr($recvd_mesg, $ofp->offsetof('ofp_stats_reply', 'body'))); + print Dumper($resp_body); + print "keys: " . join(" ",keys %$resp_body) . "\n"; + my $key; + foreach $key (sort keys %$resp_body) + { + my $val = $resp_body->{$key}; + my $len = scalar(@{$val}); + printf("key=%s ref=%s len=%d val='%s'\n", + $key, + ref($val), + $len, + pack("c*", @{$val}) + #@{$val} + ); + } + + #die("forced death"); + die("Missing dp_desc in desc_stats") unless(defined($resp_body->{"dp_desc"})); + +} + +run_black_box_test( \&stats_desc_test, \@ARGV ); + diff --git a/regress/projects/black_box/regress/tests.txt b/regress/projects/black_box/regress/tests.txt index 3533153..8c53a4c 100644 --- a/regress/projects/black_box/regress/tests.txt +++ b/regress/projects/black_box/regress/tests.txt @@ -13,6 +13,7 @@ test_flow_expired_send_flow_exp/run.pl test_miss_send_length/run.pl # Read State Tests +test_stats_desc/run.pl test_port_stats/run.pl test_flow_stats/run.pl test_flow_stats_precision/run.pl diff --git a/udatapath/datapath.c b/udatapath/datapath.c index ceac46e..1f6ccfe 100644 --- a/udatapath/datapath.c +++ b/udatapath/datapath.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "chain.h" #include "csum.h" #include "flow.h" @@ -63,6 +64,7 @@ extern char mfr_desc; extern char hw_desc; extern char sw_desc; +extern char dp_desc; extern char serial_num; /* Capabilities supported by this implementation. */ @@ -182,6 +184,16 @@ dp_new(struct datapath **dp_, uint64_t dpid) list_init(&dp->port_list); dp->flags = 0; dp->miss_send_len = OFP_DEFAULT_MISS_SEND_LEN; + + if(strlen(&dp_desc) > 0) /* use the comment, if specified */ + strncpy(dp->dp_desc, &dp_desc, sizeof dp->dp_desc); + else /* else, just use "$HOSTNAME pid=$$" */ + { + char hostnametmp[DESC_STR_LEN]; + gethostname(hostnametmp,sizeof hostnametmp); + snprintf(dp->dp_desc, sizeof dp->dp_desc,"%s pid=%u",hostnametmp, getpid()); + } + *dp_ = dp; return 0; } @@ -1176,6 +1188,7 @@ desc_stats_dump(struct datapath *dp UNUSED, void *state UNUSED, strncpy(ods->mfr_desc, &mfr_desc, sizeof ods->mfr_desc); strncpy(ods->hw_desc, &hw_desc, sizeof ods->hw_desc); strncpy(ods->sw_desc, &sw_desc, sizeof ods->sw_desc); + strncpy(ods->dp_desc, dp->dp_desc, sizeof ods->dp_desc); strncpy(ods->serial_num, &serial_num, sizeof ods->serial_num); return 0; diff --git a/udatapath/datapath.h b/udatapath/datapath.h index 136bfe4..642f270 100644 --- a/udatapath/datapath.h +++ b/udatapath/datapath.h @@ -75,6 +75,7 @@ struct datapath { /* Unique identifier for this datapath */ uint64_t id; + char dp_desc[DESC_STR_LEN]; /* human readible comment to ID this DP */ struct sw_chain *chain; /* Forwarding rules. */ diff --git a/udatapath/udatapath.c b/udatapath/udatapath.c index 1e66974..317a485 100644 --- a/udatapath/udatapath.c +++ b/udatapath/udatapath.c @@ -63,6 +63,7 @@ char mfr_desc[DESC_STR_LEN] = "Stanford University"; char hw_desc[DESC_STR_LEN] = "Reference Userspace Switch"; char sw_desc[DESC_STR_LEN] = VERSION BUILDNR; +char dp_desc[DESC_STR_LEN] = ""; char serial_num[SERIAL_NUM_LEN] = "None"; static void parse_options(int argc, char *argv[]); @@ -166,6 +167,7 @@ parse_options(int argc, char *argv[]) OPT_MFR_DESC = UCHAR_MAX + 1, OPT_HW_DESC, OPT_SW_DESC, + OPT_DP_DESC, OPT_SERIAL_NUM, OPT_BOOTSTRAP_CA_CERT, OPT_NO_LOCAL_PORT @@ -182,6 +184,7 @@ parse_options(int argc, char *argv[]) {"mfr-desc", required_argument, 0, OPT_MFR_DESC}, {"hw-desc", required_argument, 0, OPT_HW_DESC}, {"sw-desc", required_argument, 0, OPT_SW_DESC}, + {"dp_desc", required_argument, 0, OPT_DP_DESC}, {"serial_num", required_argument, 0, OPT_SERIAL_NUM}, DAEMON_LONG_OPTIONS, #ifdef HAVE_OPENSSL @@ -255,6 +258,10 @@ parse_options(int argc, char *argv[]) strncpy(sw_desc, optarg, sizeof sw_desc); break; + case OPT_DP_DESC: + strncpy(dp_desc, optarg, sizeof dp_desc); + break; + case OPT_SERIAL_NUM: strncpy(serial_num, optarg, sizeof serial_num); break; diff --git a/utilities/wireshark_dissectors/openflow/packet-openflow.c b/utilities/wireshark_dissectors/openflow/packet-openflow.c index e03f722..ef23bf5 100644 --- a/utilities/wireshark_dissectors/openflow/packet-openflow.c +++ b/utilities/wireshark_dissectors/openflow/packet-openflow.c @@ -490,6 +490,7 @@ static gint ofp_desc_stats = -1; static gint ofp_desc_stats_mfr_desc = -1; static gint ofp_desc_stats_hw_desc = -1; static gint ofp_desc_stats_sw_desc = -1; +static gint ofp_desc_stats_dp_desc = -1; static gint ofp_desc_stats_serial_num = -1; static gint ofp_flow_stats_request = -1; @@ -1487,6 +1488,9 @@ void proto_register_openflow() { &ofp_desc_stats_serial_num, { "Serial Num", "of.stats_desc_serial_num", FT_STRING, BASE_NONE, NO_STRINGS, NO_MASK, "Serial Num", HFILL } }, + { &ofp_desc_stats_dp_desc, + { "DP Desc", "of.stats_desc_dp_desc", FT_STRING, BASE_NONE, NO_STRINGS, NO_MASK, "DP Comment", HFILL } }, + /* CSM: Stats: Flow: Request */ { &ofp_flow_stats_request, { "Flow Stats Request", "of.stats_flow", FT_NONE, BASE_NONE, NO_STRINGS, NO_MASK, "Flow Statistics Request", HFILL } }, @@ -2823,6 +2827,7 @@ static void dissect_openflow_message(tvbuff_t *tvb, packet_info *pinfo, proto_tr add_child( desc_tree, ofp_desc_stats_hw_desc, tvb, &offset, DESC_STR_LEN ); add_child( desc_tree, ofp_desc_stats_sw_desc, tvb, &offset, DESC_STR_LEN ); add_child( desc_tree, ofp_desc_stats_serial_num, tvb, &offset, SERIAL_NUM_LEN ); + add_child( desc_tree, ofp_desc_stats_dp_desc, tvb, &offset, DESC_STR_LEN ); break; }