}
static void
-dump_stats_transaction__(struct vconn *vconn, struct ofpbuf *request)
+dump_stats_transaction(struct vconn *vconn, struct ofpbuf *request)
{
const struct ofp_header *request_oh = request->data;
ovs_be32 send_xid = request_oh->xid;
}
static void
-dump_stats_transaction(const char *vconn_name, struct ofpbuf *request)
+dump_trivial_stats_transaction(const char *vconn_name, enum ofpraw raw)
{
+ struct ofpbuf *request;
struct vconn *vconn;
open_vconn(vconn_name, &vconn);
- dump_stats_transaction__(vconn, request);
+ request = ofpraw_alloc(raw, vconn_get_version(vconn), 0);
+ dump_stats_transaction(vconn, request);
vconn_close(vconn);
}
-static void
-dump_trivial_stats_transaction(const char *vconn_name, enum ofpraw raw)
-{
- struct ofpbuf *request;
-
- request = ofpraw_alloc(raw, OFP10_VERSION, 0);
- dump_stats_transaction(vconn_name, request);
-}
-
/* Sends 'request', which should be a request that only has a reply if an error
* occurs, and waits for it to succeed or fail. If an error does occur, prints
* it and exits with an error.
static uint16_t
str_to_port_no(const char *vconn_name, const char *port_name)
{
- unsigned int port_no;
-
- if (str_to_uint(port_name, 10, &port_no)) {
+ uint16_t port_no = ofputil_port_from_string(port_name);
+ if (port_no) {
return port_no;
} else {
struct ofputil_phy_port pp;
struct vconn *vconn;
vconn = prepare_dump_flows(argc, argv, aggregate, &request);
- dump_stats_transaction__(vconn, request);
+ dump_stats_transaction(vconn, request);
vconn_close(vconn);
}
{
const struct ofputil_flow_stats *afs = afs_;
const struct ofputil_flow_stats *bfs = bfs_;
- const struct cls_rule *a = &afs->rule;
- const struct cls_rule *b = &bfs->rule;
+ const struct match *a = &afs->match;
+ const struct match *b = &bfs->match;
const struct sort_criterion *sc;
for (sc = criteria; sc < &criteria[n_criteria]; sc++) {
int ret;
if (!f) {
- ret = a->priority < b->priority ? -1 : a->priority > b->priority;
+ unsigned int a_pri = afs->priority;
+ unsigned int b_pri = bfs->priority;
+ ret = a_pri < b_pri ? -1 : a_pri > b_pri;
} else {
bool ina, inb;
{
struct ofp10_queue_stats_request *req;
struct ofpbuf *request;
+ struct vconn *vconn;
- request = ofpraw_alloc(OFPRAW_OFPST_QUEUE_REQUEST, OFP10_VERSION, 0);
+ open_vconn(argv[1], &vconn);
+ request = ofpraw_alloc(OFPRAW_OFPST_QUEUE_REQUEST,
+ vconn_get_version(vconn), 0);
req = ofpbuf_put_zeros(request, sizeof *req);
if (argc > 2 && argv[2][0] && strcasecmp(argv[2], "all")) {
memset(req->pad, 0, sizeof req->pad);
- dump_stats_transaction(argv[1], request);
+ dump_stats_transaction(vconn, request);
+ vconn_close(vconn);
}
static enum ofputil_protocol
set_packet_in_format(struct vconn *vconn,
enum nx_packet_in_format packet_in_format)
{
- struct ofpbuf *spif = ofputil_make_set_packet_in_format(packet_in_format);
+ struct ofpbuf *spif;
+
+ spif = ofputil_make_set_packet_in_format(vconn_get_version(vconn),
+ packet_in_format);
transact_noreply(vconn, spif);
VLOG_DBG("%s: using user-specified packet in format %s",
vconn_get_name(vconn),
return;
}
- msg = ofputil_encode_barrier_request();
+ msg = ofputil_encode_barrier_request(vconn_get_version(aux->vconn));
error = vconn_send_block(aux->vconn, msg);
if (error) {
ofpbuf_delete(msg);
msg = ofpbuf_new(0);
ofputil_append_flow_monitor_request(&fmr, msg);
- dump_stats_transaction__(vconn, msg);
+ dump_stats_transaction(vconn, msg);
} else {
ovs_fatal(0, "%s: unsupported \"monitor\" argument", arg);
}
} else {
struct ofpbuf *spif, *reply;
- spif = ofputil_make_set_packet_in_format(NXPIF_NXM);
+ spif = ofputil_make_set_packet_in_format(vconn_get_version(vconn),
+ NXPIF_NXM);
run(vconn_transact_noreply(vconn, spif, &reply),
"talking to %s", vconn_get_name(vconn));
if (reply) {
static void
ofctl_dump_ports(int argc, char *argv[])
{
- struct ofp10_port_stats_request *req;
struct ofpbuf *request;
+ struct vconn *vconn;
uint16_t port;
- request = ofpraw_alloc(OFPRAW_OFPST_PORT_REQUEST, OFP10_VERSION, 0);
- req = ofpbuf_put_zeros(request, sizeof *req);
+ open_vconn(argv[1], &vconn);
port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_NONE;
- req->port_no = htons(port);
- dump_stats_transaction(argv[1], request);
+ request = ofputil_encode_dump_ports_request(vconn_get_version(vconn), port);
+ dump_stats_transaction(vconn, request);
+ vconn_close(vconn);
}
static void
struct vconn *vconn;
struct ofpbuf *reply;
- request = make_echo_request();
open_vconn(argv[1], &vconn);
+ request = make_echo_request(vconn_get_version(vconn));
run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]);
if (reply->size != sizeof(struct ofp_header)) {
ovs_fatal(0, "reply does not match request");
static void
ofctl_packet_out(int argc, char *argv[])
{
+ enum ofputil_protocol protocol;
struct ofputil_packet_out po;
struct ofpbuf ofpacts;
struct vconn *vconn;
parse_ofpacts(argv[3], &ofpacts);
po.buffer_id = UINT32_MAX;
- po.in_port = (!strcasecmp(argv[2], "none") ? OFPP_NONE
- : !strcasecmp(argv[2], "local") ? OFPP_LOCAL
- : str_to_port_no(argv[1], argv[2]));
+ po.in_port = str_to_port_no(argv[1], argv[2]);
po.ofpacts = ofpacts.data;
po.ofpacts_len = ofpacts.size;
- open_vconn(argv[1], &vconn);
+ protocol = open_vconn(argv[1], &vconn);
for (i = 4; i < argc; i++) {
struct ofpbuf *packet, *opo;
const char *error_msg;
po.packet = packet->data;
po.packet_len = packet->size;
- opo = ofputil_encode_packet_out(&po);
+ opo = ofputil_encode_packet_out(&po, protocol);
transact_noreply(vconn, opo);
ofpbuf_delete(packet);
}
if (fte) {
fte_version_free(fte->versions[0]);
fte_version_free(fte->versions[1]);
+ cls_rule_destroy(&fte->rule);
free(fte);
}
}
*
* Takes ownership of 'version'. */
static void
-fte_insert(struct classifier *cls, const struct cls_rule *rule,
- struct fte_version *version, int index)
+fte_insert(struct classifier *cls, const struct match *match,
+ unsigned int priority, struct fte_version *version, int index)
{
struct fte *old, *fte;
fte = xzalloc(sizeof *fte);
- fte->rule = *rule;
+ cls_rule_init(&fte->rule, match, priority);
fte->versions[index] = version;
old = fte_from_cls_rule(classifier_replace(cls, &fte->rule));
if (old) {
fte_version_free(old->versions[index]);
fte->versions[!index] = old->versions[!index];
+ cls_rule_destroy(&old->rule);
free(old);
}
}
version->ofpacts = fm.ofpacts;
version->ofpacts_len = fm.ofpacts_len;
- usable_protocols &= ofputil_usable_protocols(&fm.cr);
+ usable_protocols &= ofputil_usable_protocols(&fm.match);
- fte_insert(cls, &fm.cr, version, index);
+ fte_insert(cls, &fm.match, fm.priority, version, index);
}
ds_destroy(&s);
ovs_be32 send_xid;
fsr.aggregate = false;
- cls_rule_init_catchall(&fsr.match, 0);
+ match_init_catchall(&fsr.match);
fsr.out_port = OFPP_NONE;
fsr.table_id = 0xff;
fsr.cookie = fsr.cookie_mask = htonll(0);
version->ofpacts_len = fs.ofpacts_len;
version->ofpacts = xmemdup(fs.ofpacts, fs.ofpacts_len);
- fte_insert(cls, &fs.rule, version, index);
+ fte_insert(cls, &fs.match, fs.priority, version, index);
}
ofpbuf_uninit(&ofpacts);
}
struct ofputil_flow_mod fm;
struct ofpbuf *ofm;
- fm.cr = fte->rule;
+ minimatch_expand(&fte->rule.match, &fm.match);
+ fm.priority = fte->rule.priority;
fm.cookie = htonll(0);
fm.cookie_mask = htonll(0);
fm.new_cookie = version->cookie;
ds_init(&in);
while (!ds_get_test_line(&in, stdin)) {
struct ofpbuf nx_match;
- struct cls_rule rule;
+ struct match match;
ovs_be64 cookie, cookie_mask;
enum ofperr error;
int match_len;
/* Convert string to nx_match. */
ofpbuf_init(&nx_match, 0);
- match_len = nx_match_from_string(ds_cstr(&in), &nx_match);
+ if (oxm) {
+ match_len = oxm_match_from_string(ds_cstr(&in), &nx_match);
+ } else {
+ match_len = nx_match_from_string(ds_cstr(&in), &nx_match);
+ }
- /* Convert nx_match to cls_rule. */
+ /* Convert nx_match to match. */
if (strict) {
- error = nx_pull_match(&nx_match, match_len, 0, &rule,
- &cookie, &cookie_mask);
+ if (oxm) {
+ error = oxm_pull_match(&nx_match, &match);
+ } else {
+ error = nx_pull_match(&nx_match, match_len, &match,
+ &cookie, &cookie_mask);
+ }
} else {
- error = nx_pull_match_loose(&nx_match, match_len, 0, &rule,
- &cookie, &cookie_mask);
+ if (oxm) {
+ error = oxm_pull_match_loose(&nx_match, &match);
+ } else {
+ error = nx_pull_match_loose(&nx_match, match_len, &match,
+ &cookie, &cookie_mask);
+ }
}
+
if (!error) {
char *out;
- /* Convert cls_rule back to nx_match. */
+ /* Convert match back to nx_match. */
ofpbuf_uninit(&nx_match);
ofpbuf_init(&nx_match, 0);
- match_len = nx_put_match(&nx_match, oxm, &rule,
- cookie, cookie_mask);
+ if (oxm) {
+ match_len = oxm_put_match(&nx_match, &match);
+ out = oxm_match_to_string(nx_match.data, match_len);
+ } else {
+ match_len = nx_put_match(&nx_match, &match,
+ cookie, cookie_mask);
+ out = nx_match_to_string(nx_match.data, match_len);
+ }
- /* Convert nx_match to string. */
- out = nx_match_to_string(nx_match.data, match_len);
puts(out);
free(out);
} else {
/* "parse-ofp10-match": reads a series of ofp10_match specifications as hex
* bytes from stdin, converts them to cls_rules, prints them as strings on
* stdout, and then converts them back to hex bytes and prints any differences
- * from the input. */
+ * from the input.
+ *
+ * The input hex bytes may contain "x"s to represent "don't-cares", bytes whose
+ * values are ignored in the input and will be set to zero when OVS converts
+ * them back to hex bytes. ovs-ofctl actually sets "x"s to random bits when
+ * it does the conversion to hex, to ensure that in fact they are ignored. */
static void
ofctl_parse_ofp10_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
+ struct ds expout;
struct ds in;
ds_init(&in);
+ ds_init(&expout);
while (!ds_get_preprocessed_line(&in, stdin)) {
- struct ofpbuf match_in;
+ struct ofpbuf match_in, match_expout;
struct ofp10_match match_out;
struct ofp10_match match_normal;
- struct cls_rule rule;
+ struct match match;
+ char *p;
+
+ /* Parse hex bytes to use for expected output. */
+ ds_clear(&expout);
+ ds_put_cstr(&expout, ds_cstr(&in));
+ for (p = ds_cstr(&expout); *p; p++) {
+ if (*p == 'x') {
+ *p = '0';
+ }
+ }
+ ofpbuf_init(&match_expout, 0);
+ if (ofpbuf_put_hex(&match_expout, ds_cstr(&expout), NULL)[0] != '\0') {
+ ovs_fatal(0, "Trailing garbage in hex data");
+ }
+ if (match_expout.size != sizeof(struct ofp10_match)) {
+ ovs_fatal(0, "Input is %zu bytes, expected %zu",
+ match_expout.size, sizeof(struct ofp10_match));
+ }
- /* Parse hex bytes. */
+ /* Parse hex bytes for input. */
+ for (p = ds_cstr(&in); *p; p++) {
+ if (*p == 'x') {
+ *p = "0123456789abcdef"[random_uint32() & 0xf];
+ }
+ }
ofpbuf_init(&match_in, 0);
if (ofpbuf_put_hex(&match_in, ds_cstr(&in), NULL)[0] != '\0') {
ovs_fatal(0, "Trailing garbage in hex data");
}
/* Convert to cls_rule and print. */
- ofputil_cls_rule_from_ofp10_match(match_in.data, OFP_DEFAULT_PRIORITY,
- &rule);
- cls_rule_print(&rule);
+ ofputil_match_from_ofp10_match(match_in.data, &match);
+ match_print(&match);
/* Convert back to ofp10_match and print differences from input. */
- ofputil_cls_rule_to_ofp10_match(&rule, &match_out);
- print_differences("", match_in.data, match_in.size,
+ ofputil_match_to_ofp10_match(&match, &match_out);
+ print_differences("", match_expout.data, match_expout.size,
&match_out, sizeof match_out);
/* Normalize, then convert and compare again. */
- ofputil_normalize_rule(&rule);
- ofputil_cls_rule_to_ofp10_match(&rule, &match_normal);
+ ofputil_normalize_match(&match);
+ ofputil_match_to_ofp10_match(&match, &match_normal);
print_differences("normal: ", &match_out, sizeof match_out,
&match_normal, sizeof match_normal);
putchar('\n');
ofpbuf_uninit(&match_in);
+ ofpbuf_uninit(&match_expout);
}
ds_destroy(&in);
+ ds_destroy(&expout);
}
/* "parse-ofp11-match": reads a series of ofp11_match specifications as hex
- * bytes from stdin, converts them to cls_rules, prints them as strings on
- * stdout, and then converts them back to hex bytes and prints any differences
- * from the input. */
+ * bytes from stdin, converts them to "struct match"es, prints them as strings
+ * on stdout, and then converts them back to hex bytes and prints any
+ * differences from the input. */
static void
ofctl_parse_ofp11_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
while (!ds_get_preprocessed_line(&in, stdin)) {
struct ofpbuf match_in;
struct ofp11_match match_out;
- struct cls_rule rule;
+ struct match match;
enum ofperr error;
/* Parse hex bytes. */
match_in.size, sizeof(struct ofp11_match));
}
- /* Convert to cls_rule. */
- error = ofputil_cls_rule_from_ofp11_match(match_in.data,
- OFP_DEFAULT_PRIORITY, &rule);
+ /* Convert to match. */
+ error = ofputil_match_from_ofp11_match(match_in.data, &match);
if (error) {
printf("bad ofp11_match: %s\n\n", ofperr_get_name(error));
ofpbuf_uninit(&match_in);
continue;
}
- /* Print cls_rule. */
- cls_rule_print(&rule);
+ /* Print match. */
+ match_print(&match);
/* Convert back to ofp11_match and print differences from input. */
- ofputil_cls_rule_to_ofp11_match(&rule, &match_out);
+ ofputil_match_to_ofp11_match(&match, &match_out);
print_differences("", match_in.data, match_in.size,
&match_out, sizeof match_out);
static void
ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
{
- struct cls_rule rule;
+ struct match match;
char *string_s;
struct ofputil_flow_mod fm;
struct ofpbuf nxm;
- struct cls_rule nxm_rule;
+ struct match nxm_match;
int nxm_match_len;
char *nxm_s;
- struct ofp10_match of10_match;
- struct cls_rule of10_rule;
+ struct ofp10_match of10_raw;
+ struct match of10_match;
- struct ofp11_match of11_match;
- struct cls_rule of11_rule;
+ struct ofp11_match of11_raw;
+ struct match of11_match;
enum ofperr error;
- cls_rule_init_catchall(&rule, OFP_DEFAULT_PRIORITY);
- rule.flow.vlan_tci = htons(strtoul(argv[1], NULL, 16));
- rule.wc.vlan_tci_mask = htons(strtoul(argv[2], NULL, 16));
+ match_init_catchall(&match);
+ match.flow.vlan_tci = htons(strtoul(argv[1], NULL, 16));
+ match.wc.masks.vlan_tci = htons(strtoul(argv[2], NULL, 16));
/* Convert to and from string. */
- string_s = cls_rule_to_string(&rule);
+ string_s = match_to_string(&match, OFP_DEFAULT_PRIORITY);
printf("%s -> ", string_s);
fflush(stdout);
parse_ofp_str(&fm, -1, string_s, false);
printf("%04"PRIx16"/%04"PRIx16"\n",
- ntohs(fm.cr.flow.vlan_tci),
- ntohs(fm.cr.wc.vlan_tci_mask));
+ ntohs(fm.match.flow.vlan_tci),
+ ntohs(fm.match.wc.masks.vlan_tci));
+ free(string_s);
/* Convert to and from NXM. */
ofpbuf_init(&nxm, 0);
- nxm_match_len = nx_put_match(&nxm, false, &rule, htonll(0), htonll(0));
+ nxm_match_len = nx_put_match(&nxm, &match, htonll(0), htonll(0));
nxm_s = nx_match_to_string(nxm.data, nxm_match_len);
- error = nx_pull_match(&nxm, nxm_match_len, 0, &nxm_rule, NULL, NULL);
+ error = nx_pull_match(&nxm, nxm_match_len, &nxm_match, NULL, NULL);
printf("NXM: %s -> ", nxm_s);
if (error) {
printf("%s\n", ofperr_to_string(error));
} else {
printf("%04"PRIx16"/%04"PRIx16"\n",
- ntohs(nxm_rule.flow.vlan_tci),
- ntohs(nxm_rule.wc.vlan_tci_mask));
+ ntohs(nxm_match.flow.vlan_tci),
+ ntohs(nxm_match.wc.masks.vlan_tci));
}
free(nxm_s);
ofpbuf_uninit(&nxm);
/* Convert to and from OXM. */
ofpbuf_init(&nxm, 0);
- nxm_match_len = nx_put_match(&nxm, true, &rule, htonll(0), htonll(0));
- nxm_s = nx_match_to_string(nxm.data, nxm_match_len);
- error = nx_pull_match(&nxm, nxm_match_len, 0, &nxm_rule, NULL, NULL);
+ nxm_match_len = oxm_put_match(&nxm, &match);
+ nxm_s = oxm_match_to_string(nxm.data, nxm_match_len);
+ error = oxm_pull_match(&nxm, &nxm_match);
printf("OXM: %s -> ", nxm_s);
if (error) {
printf("%s\n", ofperr_to_string(error));
} else {
- uint16_t vid = ntohs(nxm_rule.flow.vlan_tci) &
+ uint16_t vid = ntohs(nxm_match.flow.vlan_tci) &
(VLAN_VID_MASK | VLAN_CFI);
- uint16_t mask = ntohs(nxm_rule.wc.vlan_tci_mask) &
+ uint16_t mask = ntohs(nxm_match.wc.masks.vlan_tci) &
(VLAN_VID_MASK | VLAN_CFI);
printf("%04"PRIx16"/%04"PRIx16",", vid, mask);
- if (vid && vlan_tci_to_pcp(nxm_rule.wc.vlan_tci_mask)) {
- printf("%02"PRIx8"\n", vlan_tci_to_pcp(nxm_rule.flow.vlan_tci));
+ if (vid && vlan_tci_to_pcp(nxm_match.wc.masks.vlan_tci)) {
+ printf("%02"PRIx8"\n", vlan_tci_to_pcp(nxm_match.flow.vlan_tci));
} else {
printf("--\n");
}
ofpbuf_uninit(&nxm);
/* Convert to and from OpenFlow 1.0. */
- ofputil_cls_rule_to_ofp10_match(&rule, &of10_match);
- ofputil_cls_rule_from_ofp10_match(&of10_match, 0, &of10_rule);
+ ofputil_match_to_ofp10_match(&match, &of10_raw);
+ ofputil_match_from_ofp10_match(&of10_raw, &of10_match);
printf("OF1.0: %04"PRIx16"/%d,%02"PRIx8"/%d -> %04"PRIx16"/%04"PRIx16"\n",
- ntohs(of10_match.dl_vlan),
- (of10_match.wildcards & htonl(OFPFW10_DL_VLAN)) != 0,
- of10_match.dl_vlan_pcp,
- (of10_match.wildcards & htonl(OFPFW10_DL_VLAN_PCP)) != 0,
- ntohs(of10_rule.flow.vlan_tci),
- ntohs(of10_rule.wc.vlan_tci_mask));
+ ntohs(of10_raw.dl_vlan),
+ (of10_raw.wildcards & htonl(OFPFW10_DL_VLAN)) != 0,
+ of10_raw.dl_vlan_pcp,
+ (of10_raw.wildcards & htonl(OFPFW10_DL_VLAN_PCP)) != 0,
+ ntohs(of10_match.flow.vlan_tci),
+ ntohs(of10_match.wc.masks.vlan_tci));
/* Convert to and from OpenFlow 1.1. */
- ofputil_cls_rule_to_ofp11_match(&rule, &of11_match);
- ofputil_cls_rule_from_ofp11_match(&of11_match, 0, &of11_rule);
+ ofputil_match_to_ofp11_match(&match, &of11_raw);
+ ofputil_match_from_ofp11_match(&of11_raw, &of11_match);
printf("OF1.1: %04"PRIx16"/%d,%02"PRIx8"/%d -> %04"PRIx16"/%04"PRIx16"\n",
- ntohs(of11_match.dl_vlan),
- (of11_match.wildcards & htonl(OFPFW11_DL_VLAN)) != 0,
- of11_match.dl_vlan_pcp,
- (of11_match.wildcards & htonl(OFPFW11_DL_VLAN_PCP)) != 0,
- ntohs(of11_rule.flow.vlan_tci),
- ntohs(of11_rule.wc.vlan_tci_mask));
+ ntohs(of11_raw.dl_vlan),
+ (of11_raw.wildcards & htonl(OFPFW11_DL_VLAN)) != 0,
+ of11_raw.dl_vlan_pcp,
+ (of11_raw.wildcards & htonl(OFPFW11_DL_VLAN_PCP)) != 0,
+ ntohs(of11_match.flow.vlan_tci),
+ ntohs(of11_match.wc.masks.vlan_tci));
}
/* "print-error ENUM": Prints the type and code of ENUM for every OpenFlow
}
for (version = 0; version <= UINT8_MAX; version++) {
- const struct ofperr_domain *domain;
-
- domain = ofperr_domain_from_version(version);
- if (!domain) {
+ const char *name = ofperr_domain_get_name(version);
+ if (!name) {
continue;
}
-
printf("%s: %d,%d\n",
- ofperr_domain_get_name(domain),
- ofperr_get_type(error, domain),
- ofperr_get_code(error, domain));
+ ofperr_domain_get_name(version),
+ ofperr_get_type(error, version),
+ ofperr_get_code(error, version));
}
}