#include "command-line.h"
#include "compiler.h"
#include "dirs.h"
-#include "dpif.h"
+#include "dynamic-string.h"
+#include "netdev.h"
#include "netlink.h"
-#include "odp-util.h"
#include "ofp-parse.h"
#include "ofp-print.h"
#include "ofp-util.h"
#include "util.h"
#include "vconn.h"
#include "vlog.h"
+#include "xfif.h"
+#include "xflow-util.h"
#include "xtoxll.h"
VLOG_DEFINE_THIS_MODULE(ofctl)
open_vconn__(const char *name, const char *default_suffix,
struct vconn **vconnp)
{
- struct dpif *dpif;
+ struct xfif *xfif;
struct stat s;
char *bridge_path, *datapath_name, *datapath_type;
bridge_path = xasprintf("%s/%s.%s", ovs_rundir, name, default_suffix);
- dp_parse_name(name, &datapath_name, &datapath_type);
+ xf_parse_name(name, &datapath_name, &datapath_type);
if (strstr(name, ":")) {
run(vconn_open_block(name, OFP_VERSION, vconnp),
open_vconn_socket(name, vconnp);
} else if (!stat(bridge_path, &s) && S_ISSOCK(s.st_mode)) {
open_vconn_socket(bridge_path, vconnp);
- } else if (!dpif_open(datapath_name, datapath_type, &dpif)) {
- char dpif_name[IF_NAMESIZE + 1];
+ } else if (!xfif_open(datapath_name, datapath_type, &xfif)) {
+ char xfif_name[IF_NAMESIZE + 1];
char *socket_name;
- run(dpif_port_get_name(dpif, ODPP_LOCAL, dpif_name, sizeof dpif_name),
- "obtaining name of %s", dpif_name);
- dpif_close(dpif);
- if (strcmp(dpif_name, name)) {
- VLOG_INFO("datapath %s is named %s", name, dpif_name);
+ run(xfif_port_get_name(xfif, XFLOWP_LOCAL, xfif_name, sizeof xfif_name),
+ "obtaining name of %s", xfif_name);
+ xfif_close(xfif);
+ if (strcmp(xfif_name, name)) {
+ VLOG_INFO("datapath %s is named %s", name, xfif_name);
}
socket_name = xasprintf("%s/%s.%s",
- ovs_rundir, dpif_name, default_suffix);
+ ovs_rundir, xfif_name, default_suffix);
if (stat(socket_name, &s)) {
ovs_fatal(errno, "cannot connect to %s: stat failed on %s",
name, socket_name);
dump_stats_transaction(argv[1], request);
}
+static void
+enable_flow_mod_table_id_ext(struct vconn *vconn, bool enable)
+{
+ send_openflow_buffer(vconn, make_nxt_flow_mod_table_id(enable));
+}
+
static void
do_queue_stats(int argc, char *argv[])
{
uint16_t priority, idle_timeout, hard_timeout;
uint64_t cookie;
struct ofp_match match;
+ uint8_t table_idx;
/* 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,
+ &table_idx, NULL, &priority, &idle_timeout, &hard_timeout,
&cookie);
ofm = buffer->data;
ofm->match = match;
ofm->priority = htons(priority);
open_vconn(argv[1], &vconn);
+ if (table_idx != 0xff) {
+ enable_flow_mod_table_id_ext(vconn, 1);
+ ofm->command = htons(ntohs(ofm->command) | (table_idx << 8));
+ }
send_openflow_buffer(vconn, buffer);
vconn_close(vconn);
}
struct vconn *vconn;
struct ofpbuf *b;
FILE *file;
+ bool table_id_enabled = false;
+ uint8_t table_idx;
file = fopen(argv[2], "r");
if (file == NULL) {
}
open_vconn(argv[1], &vconn);
- while ((b = parse_ofp_add_flow_file(file)) != NULL) {
+ while ((b = parse_ofp_add_flow_file(file, &table_idx)) != NULL) {
+ if ((table_idx != 0xff) != table_id_enabled) {
+ table_id_enabled = table_idx != 0xff;
+ enable_flow_mod_table_id_ext(vconn, table_id_enabled);
+ }
send_openflow_buffer(vconn, b);
}
vconn_close(vconn);
struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
struct ofp_match match;
+ uint8_t table_idx;
/* 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,
+ &table_idx, NULL, &priority, &idle_timeout, &hard_timeout,
&cookie);
ofm = buffer->data;
ofm->match = match;
ofm->priority = htons(priority);
open_vconn(argv[1], &vconn);
+ if (table_idx != 0xff) {
+ enable_flow_mod_table_id_ext(vconn, 1);
+ ofm->command = htons(ntohs(ofm->command) | (table_idx << 8));
+ }
send_openflow_buffer(vconn, buffer);
vconn_close(vconn);
}
uint16_t out_port;
struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
+ uint8_t table_idx;
/* Parse and send. */
ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- parse_ofp_str(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL,
+ parse_ofp_str(argc > 2 ? argv[2] : "", &ofm->match, NULL, &table_idx,
&out_port, &priority, NULL, NULL, NULL);
if (strict) {
ofm->command = htons(OFPFC_DELETE_STRICT);
ofm->priority = htons(priority);
open_vconn(argv[1], &vconn);
+ if (table_idx != 0xff) {
+ enable_flow_mod_table_id_ext(vconn, 1);
+ ofm->command = htons(ntohs(ofm->command) | (table_idx << 8));
+ }
send_openflow_buffer(vconn, buffer);
vconn_close(vconn);
}
count * message_size / (duration / 1000.0));
}
+/* This command is really only useful for testing the flow parser (ofp_parse),
+ * so it is undocumented. */
+static void
+do_parse_flows(int argc OVS_UNUSED, char *argv[])
+{
+ uint8_t table_idx;
+ 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, &table_idx)) != NULL) {
+ ofp_print(stdout, b->data, b->size, 0);
+ ofpbuf_delete(b);
+ }
+ fclose(file);
+}
+
static void
do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
{ "probe", 1, 1, do_probe },
{ "ping", 1, 2, do_ping },
{ "benchmark", 3, 3, do_benchmark },
+ { "parse-flows", 1, 1, do_parse_flows },
{ "help", 0, INT_MAX, do_help },
{ NULL, 0, 0, NULL },
};