-Subproject commit 4cf18a517a2663e945529a16e5d18e3b676c2687
+Subproject commit 15707fb578371cdd0b7ee8c84758d78633e0177b
--- /dev/null
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#ifndef NICIRA_EXT_H
+#define NICIRA_EXT_H 1
+
+#include "openflow.h"
+
+/* The following vendor extensions, proposed by Nicira Networks, are not yet
+ * ready for standardization (and may never be), so they are not included in
+ * openflow.h. */
+
+#define NX_VENDOR_ID 0x00002320
+
+enum nicira_type {
+ /* Switch status request. The request body is an ASCII string that
+ * specifies a prefix of the key names to include in the output; if it is
+ * the null string, then all key-value pairs are included. */
+ NXT_STATUS_REQUEST,
+
+ /* Switch status reply. The reply body is an ASCII string of key-value
+ * pairs in the form "key=value\n". */
+ NXT_STATUS_REPLY
+};
+
+struct nicira_header {
+ struct ofp_header header;
+ uint32_t vendor_id; /* NX_VENDOR_ID. */
+ uint32_t subtype; /* One of NXT_* above. */
+};
+OFP_ASSERT(sizeof(struct nicira_header) == sizeof(struct ofp_vendor) + 4);
+
+#endif /* nicira-ext.h */
* The reply body is an array of struct ofp_port_stats. */
OFPST_PORT,
- /* Switch status.
- * The request body is an ASCII string that specifies a prefix of the key
- * names to include in the output; if it is the null string, then all
- * key-value pairs are included.
- * The reply body is an ASCII string of key-value pairs in the form
- * "key=value\n". */
- OFPST_SWITCH,
-
/* Vendor extension.
* The request and reply bodies begin with a 32-bit vendor ID, which takes
* the same form as in "struct ofp_vendor". The request and reply bodies
}
static void
-switch_status_reply(struct ds *string, const void *body, size_t len,
- int verbosity UNUSED)
+vendor_stat(struct ds *string, const void *body, size_t len,
+ int verbosity UNUSED)
{
- char *save_ptr = NULL;
- char *s, *line;
-
- s = xmemdup0(body, len);
- for (line = strtok_r(s, "\n\n", &save_ptr); line != NULL;
- line = strtok_r(NULL, "\n\n", &save_ptr)) {
- ds_put_printable(string, line, strlen(line));
- ds_put_char(string, '\n');
- }
- free(s);
+ ds_put_format(string, " vendor=%08"PRIx32, ntohl(*(uint32_t *) body));
+ ds_put_format(string, " %zu bytes additional data",
+ len - sizeof(uint32_t));
}
enum stats_direction {
{ 0, 0, NULL, },
{ 0, SIZE_MAX, ofp_port_stats_reply },
},
- [OFPST_SWITCH] = {
- "switch status",
- { 0, 0, NULL, },
- { 0, SIZE_MAX, switch_status_reply },
+ [OFPST_VENDOR] = {
+ "vendor-specific",
+ { sizeof(uint32_t), SIZE_MAX, vendor_stat },
+ { sizeof(uint32_t), SIZE_MAX, vendor_stat },
},
};
#include "list.h"
#include "mac-learning.h"
#include "netdev.h"
+#include "nicira-ext.h"
#include "openflow.h"
#include "packets.h"
#include "poll-loop.h"
struct rconn *rc = r->halves[HALF_REMOTE].rconn;
struct buffer *msg = r->halves[HALF_REMOTE].rxbuf;
struct switch_status_category *c;
- struct ofp_stats_request *osr;
- struct ofp_stats_reply *reply;
+ struct nicira_header *request;
+ struct nicira_header *reply;
struct status_reply sr;
- struct ofp_header *oh;
struct buffer *b;
int retval;
- oh = msg->data;
- if (oh->type != OFPT_STATS_REQUEST) {
+ if (msg->size < sizeof(struct nicira_header)) {
return false;
}
- if (msg->size < sizeof(struct ofp_stats_request)) {
- VLOG_WARN_RL(&vrl, "packet too short (%zu bytes) for stats_request",
- msg->size);
+ request = msg->data;
+ if (request->header.type != OFPT_VENDOR
+ || request->vendor_id != htonl(NX_VENDOR_ID)
+ || request->subtype != htonl(NXT_STATUS_REQUEST)) {
return false;
}
- osr = msg->data;
- if (osr->type != htons(OFPST_SWITCH)) {
- return false;
- }
-
- sr.request.string = (void *) (osr + 1);
- sr.request.length = msg->size - sizeof *osr;
+ sr.request.string = (void *) (request + 1);
+ sr.request.length = msg->size - sizeof *request;
ds_init(&sr.output);
for (c = ss->categories; c < &ss->categories[ss->n_categories]; c++) {
if (!memcmp(c->name, sr.request.string,
c->cb(&sr, c->aux);
}
}
- reply = make_openflow_xid((offsetof(struct ofp_stats_reply, body)
- + sr.output.length),
- OFPT_STATS_REPLY, osr->header.xid, &b);
- reply->type = htons(OFPST_SWITCH);
- reply->flags = 0;
- memcpy(reply->body, sr.output.string, sr.output.length);
+ reply = make_openflow_xid(sizeof *reply + sr.output.length,
+ OFPT_VENDOR, request->header.xid, &b);
+ reply->vendor_id = htonl(NX_VENDOR_ID);
+ reply->subtype = htonl(NXT_STATUS_REPLY);
+ memcpy(reply + 1, sr.output.string, sr.output.length);
retval = rconn_send(rc, b, NULL);
if (retval && retval != EAGAIN) {
VLOG_WARN("send failed (%s)", strerror(retval));
#include "command-line.h"
#include "compiler.h"
#include "dpif.h"
+#include "nicira-ext.h"
#include "ofp-print.h"
#include "openflow.h"
#include "packets.h"
static void
do_status(int argc, char *argv[])
{
- struct buffer *request;
- alloc_stats_request(0, OFPST_SWITCH, &request);
+ struct nicira_header *request, *reply;
+ struct vconn *vconn;
+ struct buffer *b;
+
+ request = make_openflow(sizeof *request, OFPT_VENDOR, &b);
+ request->vendor_id = htonl(NX_VENDOR_ID);
+ request->subtype = htonl(NXT_STATUS_REQUEST);
if (argc > 2) {
- buffer_put(request, argv[2], strlen(argv[2]));
+ buffer_put(b, argv[2], strlen(argv[2]));
}
- dump_stats_transaction(argv[1], request);
+ run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
+ run(vconn_transact(vconn, b, &b), "talking to %s", argv[1]);
+ vconn_close(vconn);
+
+ if (b->size < sizeof *reply) {
+ fatal(0, "short reply (%zu bytes)", b->size);
+ }
+ reply = b->data;
+ if (reply->header.type != OFPT_VENDOR
+ || reply->vendor_id != ntohl(NX_VENDOR_ID)
+ || reply->subtype != ntohl(NXT_STATUS_REPLY)) {
+ ofp_print(stderr, b->data, b->size, 2);
+ fatal(0, "bad reply");
+ }
+
+ fwrite(reply + 1, b->size, 1, stdout);
}
static void