#include <sys/stat.h>
#include <sys/time.h>
+#include "byte-order.h"
+#include "classifier.h"
#include "command-line.h"
#include "compiler.h"
#include "dirs.h"
#include "dpif.h"
+#include "dynamic-string.h"
#include "netlink.h"
+#include "nx-match.h"
#include "odp-util.h"
#include "ofp-parse.h"
#include "ofp-print.h"
#include "util.h"
#include "vconn.h"
#include "vlog.h"
-#include "xtoxll.h"
-VLOG_DEFINE_THIS_MODULE(ofctl)
+VLOG_DEFINE_THIS_MODULE(ofctl);
#define MOD_PORT_CMD_UP "up"
struct vconn *vconn;
struct ofpbuf *b;
- request = make_openflow(sizeof *request, OFPT_VENDOR, &b);
- request->vendor = htonl(NX_VENDOR_ID);
- request->subtype = htonl(NXT_STATUS_REQUEST);
+ request = make_nxmsg(sizeof *request, NXT_STATUS_REQUEST, &b);
if (argc > 2) {
ofpbuf_put(b, argv[2], strlen(argv[2]));
update_openflow_length(b);
do_dump_flows(int argc, char *argv[])
{
struct ofp_flow_stats_request *req;
- uint16_t out_port;
+ struct parsed_flow pf;
struct ofpbuf *request;
req = alloc_stats_request(sizeof *req, OFPST_FLOW, &request);
- parse_ofp_str(argc > 2 ? argv[2] : "", &req->match, NULL,
- &req->table_id, &out_port, NULL, NULL, NULL, NULL);
+ parse_ofp_str(&pf, NULL, argc > 2 ? argv[2] : "");
+ flow_to_match(&pf.rule.flow, pf.rule.wc.wildcards, NXFF_OPENFLOW10,
+ &req->match);
memset(&req->pad, 0, sizeof req->pad);
- req->out_port = htons(out_port);
+ req->out_port = htons(pf.out_port);
dump_stats_transaction(argv[1], request);
}
{
struct ofp_aggregate_stats_request *req;
struct ofpbuf *request;
- uint16_t out_port;
+ struct parsed_flow pf;
req = alloc_stats_request(sizeof *req, OFPST_AGGREGATE, &request);
- parse_ofp_str(argc > 2 ? argv[2] : "", &req->match, NULL,
- &req->table_id, &out_port, NULL, NULL, NULL, NULL);
+ parse_ofp_str(&pf, NULL, argc > 2 ? argv[2] : "");
+ flow_to_match(&pf.rule.flow, pf.rule.wc.wildcards, NXFF_OPENFLOW10,
+ &req->match);
memset(&req->pad, 0, sizeof req->pad);
- req->out_port = htons(out_port);
+ req->out_port = htons(pf.out_port);
dump_stats_transaction(argv[1], request);
}
{
struct vconn *vconn;
struct ofpbuf *buffer;
- struct ofp_flow_mod *ofm;
- uint16_t priority, idle_timeout, hard_timeout;
- uint64_t cookie;
- struct ofp_match match;
-
- /* Parse and send. parse_ofp_str() will expand and reallocate the
- * data in 'buffer', so we can't keep pointers to across the
- * parse_ofp_str() call. */
- make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- parse_ofp_str(argv[2], &match, buffer,
- NULL, NULL, &priority, &idle_timeout, &hard_timeout,
- &cookie);
- ofm = buffer->data;
- ofm->match = match;
- ofm->command = htons(OFPFC_ADD);
- ofm->cookie = htonll(cookie);
- ofm->idle_timeout = htons(idle_timeout);
- ofm->hard_timeout = htons(hard_timeout);
- ofm->buffer_id = htonl(UINT32_MAX);
- ofm->priority = htons(priority);
+
+ buffer = parse_ofp_flow_mod_str(argv[2], OFPFC_ADD);
open_vconn(argv[1], &vconn);
send_openflow_buffer(vconn, buffer);
do_add_flows(int argc OVS_UNUSED, char *argv[])
{
struct vconn *vconn;
+ struct ofpbuf *b;
FILE *file;
- char line[1024];
file = fopen(argv[2], "r");
if (file == NULL) {
}
open_vconn(argv[1], &vconn);
- while (fgets(line, sizeof line, file)) {
- struct ofpbuf *buffer;
- struct ofp_flow_mod *ofm;
- uint16_t priority, idle_timeout, hard_timeout;
- uint64_t cookie;
- struct ofp_match match;
-
- char *comment;
-
- /* Delete comments. */
- comment = strchr(line, '#');
- if (comment) {
- *comment = '\0';
- }
-
- /* Drop empty lines. */
- if (line[strspn(line, " \t\n")] == '\0') {
- continue;
- }
-
- /* Parse and send. parse_ofp_str() will expand and reallocate
- * the data in 'buffer', so we can't keep pointers to across the
- * parse_ofp_str() call. */
- make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- parse_ofp_str(line, &match, buffer,
- NULL, NULL, &priority, &idle_timeout, &hard_timeout,
- &cookie);
- ofm = buffer->data;
- ofm->match = match;
- ofm->command = htons(OFPFC_ADD);
- ofm->cookie = htonll(cookie);
- ofm->idle_timeout = htons(idle_timeout);
- ofm->hard_timeout = htons(hard_timeout);
- ofm->buffer_id = htonl(UINT32_MAX);
- ofm->priority = htons(priority);
-
- send_openflow_buffer(vconn, buffer);
+ while ((b = parse_ofp_add_flow_file(file)) != NULL) {
+ send_openflow_buffer(vconn, b);
}
vconn_close(vconn);
fclose(file);
static void
do_mod_flows(int argc OVS_UNUSED, char *argv[])
{
- uint16_t priority, idle_timeout, hard_timeout;
- uint64_t cookie;
struct vconn *vconn;
struct ofpbuf *buffer;
- struct ofp_flow_mod *ofm;
- struct ofp_match match;
-
- /* Parse and send. parse_ofp_str() will expand and reallocate the
- * data in 'buffer', so we can't keep pointers to across the
- * parse_ofp_str() call. */
- make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- parse_ofp_str(argv[2], &match, buffer,
- NULL, NULL, &priority, &idle_timeout, &hard_timeout,
- &cookie);
- ofm = buffer->data;
- ofm->match = match;
- if (strict) {
- ofm->command = htons(OFPFC_MODIFY_STRICT);
- } else {
- ofm->command = htons(OFPFC_MODIFY);
- }
- ofm->idle_timeout = htons(idle_timeout);
- ofm->hard_timeout = htons(hard_timeout);
- ofm->cookie = htonll(cookie);
- ofm->buffer_id = htonl(UINT32_MAX);
- ofm->priority = htons(priority);
+ uint16_t command;
+ command = strict ? OFPFC_MODIFY_STRICT : OFPFC_MODIFY;
+ buffer = parse_ofp_flow_mod_str(argv[2], command);
open_vconn(argv[1], &vconn);
send_openflow_buffer(vconn, buffer);
vconn_close(vconn);
static void do_del_flows(int argc, char *argv[])
{
struct vconn *vconn;
- uint16_t priority;
- uint16_t out_port;
struct ofpbuf *buffer;
- struct ofp_flow_mod *ofm;
-
- /* Parse and send. */
- ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- parse_ofp_str(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL,
- &out_port, &priority, NULL, NULL, NULL);
- if (strict) {
- ofm->command = htons(OFPFC_DELETE_STRICT);
- } else {
- ofm->command = htons(OFPFC_DELETE);
- }
- ofm->idle_timeout = htons(0);
- ofm->hard_timeout = htons(0);
- ofm->buffer_id = htonl(UINT32_MAX);
- ofm->out_port = htons(out_port);
- ofm->priority = htons(priority);
+ uint16_t command;
+
+ command = strict ? OFPFC_DELETE_STRICT : OFPFC_DELETE;
+ buffer = parse_ofp_flow_mod_str(argc > 2 ? argv[2] : "", command);
open_vconn(argv[1], &vconn);
send_openflow_buffer(vconn, buffer);
struct ofpbuf *buffer;
struct vconn *vconn;
- tun_id_cookie = make_openflow(sizeof *tun_id_cookie, OFPT_VENDOR, &buffer);
-
- tun_id_cookie->vendor = htonl(NX_VENDOR_ID);
- tun_id_cookie->subtype = htonl(NXT_TUN_ID_FROM_COOKIE);
+ tun_id_cookie = make_nxmsg(sizeof *tun_id_cookie, NXT_TUN_ID_FROM_COOKIE,
+ &buffer);
tun_id_cookie->set = !strcmp(argv[2], "true");
open_vconn(argv[1], &vconn);
{
usage();
}
+\f
+/* Undocumented commands for unit testing. */
+
+static void
+do_parse_flows(int argc OVS_UNUSED, char *argv[])
+{
+ struct ofpbuf *b;
+ FILE *file;
+
+ file = fopen(argv[1], "r");
+ if (file == NULL) {
+ ovs_fatal(errno, "%s: open", argv[2]);
+ }
+
+ while ((b = parse_ofp_add_flow_file(file)) != NULL) {
+ ofp_print(stdout, b->data, b->size, 0);
+ ofpbuf_delete(b);
+ }
+ fclose(file);
+}
+
+static void
+do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+ struct ds in;
+
+ ds_init(&in);
+ while (!ds_get_line(&in, stdin)) {
+ struct ofpbuf nx_match;
+ struct cls_rule rule;
+ int match_len;
+ int error;
+ char *s;
+
+ /* Delete comments, skip blank lines. */
+ s = ds_cstr(&in);
+ if (*s == '#') {
+ puts(s);
+ continue;
+ }
+ if (strchr(s, '#')) {
+ *strchr(s, '#') = '\0';
+ }
+ if (s[strspn(s, " ")] == '\0') {
+ putchar('\n');
+ continue;
+ }
+
+ /* Convert string to nx_match. */
+ ofpbuf_init(&nx_match, 0);
+ match_len = nx_match_from_string(ds_cstr(&in), &nx_match);
+
+ /* Convert nx_match to cls_rule. */
+ error = nx_pull_match(&nx_match, match_len, 0, &rule);
+ if (!error) {
+ char *out;
+
+ /* Convert cls_rule back to nx_match. */
+ ofpbuf_uninit(&nx_match);
+ ofpbuf_init(&nx_match, 0);
+ match_len = nx_put_match(&nx_match, &rule);
+
+ /* Convert nx_match to string. */
+ out = nx_match_to_string(nx_match.data, match_len);
+ puts(out);
+ free(out);
+ } else {
+ printf("nx_pull_match() returned error %x\n", error);
+ }
+
+ ofpbuf_uninit(&nx_match);
+ }
+ ds_destroy(&in);
+}
static const struct command all_commands[] = {
{ "show", 1, 1, do_show },
{ "ping", 1, 2, do_ping },
{ "benchmark", 3, 3, do_benchmark },
{ "help", 0, INT_MAX, do_help },
+
+ /* Undocumented commands for testing. */
+ { "parse-flows", 1, 1, do_parse_flows },
+ { "parse-nx-match", 0, 0, do_parse_nx_match },
+
{ NULL, 0, 0, NULL },
};