void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
/* Initialize most of wc. */
flow_wildcards_init_catchall(wc);
#define N_PROTO_ABBREVS ARRAY_SIZE(proto_abbrevs)
enum ofputil_protocol ofputil_flow_dump_protocols[] = {
+ OFPUTIL_P_OF12_OXM,
OFPUTIL_P_OF10_NXM,
OFPUTIL_P_OF10_STD,
};
return protocols;
}
-static enum ofp_version
+static int
ofputil_version_from_string(const char *s)
{
if (!strcasecmp(s, "OpenFlow10")) {
if (!strcasecmp(s, "OpenFlow12")) {
return OFP12_VERSION;
}
- VLOG_FATAL("Unknown OpenFlow version: \"%s\"", s);
+ return 0;
}
static bool
while (s[i]) {
size_t j;
- enum ofp_version version;
+ int version;
char *key;
if (is_delimiter(s[i])) {
}
key = xmemdup0(s + i, j);
version = ofputil_version_from_string(key);
+ if (!version) {
+ VLOG_FATAL("Unknown OpenFlow version: \"%s\"", key);
+ }
free(key);
bitmap |= 1u << version;
i += j;
return bitmap;
}
+uint32_t
+ofputil_versions_from_strings(char ** const s, size_t count)
+{
+ uint32_t bitmap = 0;
+
+ while (count--) {
+ int version = ofputil_version_from_string(s[count]);
+ if (!version) {
+ VLOG_WARN("Unknown OpenFlow version: \"%s\"", s[count]);
+ } else {
+ bitmap |= 1u << version;
+ }
+ }
+
+ return bitmap;
+}
+
const char *
ofputil_version_to_string(enum ofp_version ofp_version)
{
return true;
}
+static bool
+tun_parms_fully_wildcarded(const struct flow_wildcards *wc)
+{
+ return (!wc->masks.tunnel.ip_src &&
+ !wc->masks.tunnel.ip_dst &&
+ !wc->masks.tunnel.ip_ttl &&
+ !wc->masks.tunnel.ip_tos &&
+ !wc->masks.tunnel.flags);
+}
+
/* Returns a bit-mask of ofputil_protocols that can be used for sending 'match'
* to a switch (e.g. to add or remove a flow). Only NXM can handle tunnel IDs,
* registers, or fixing the Ethernet multicast bit. Otherwise, it's better to
{
const struct flow_wildcards *wc = &match->wc;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
+
+ /* tunnel params other than tun_id can't be sent in a flow_mod */
+ if (!tun_parms_fully_wildcarded(wc)) {
+ return OFPUTIL_P_NONE;
+ }
/* NXM, OXM, and OF1.1 support bitwise matching on ethernet addresses. */
if (!eth_mask_is_exact(wc->masks.dl_src)
return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW10);
case OFPUTIL_P_OF12_OXM:
- return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW12);
+ /* There's only one OpenFlow 1.2 protocol and we already verified
+ * above that we're not trying to change versions. */
+ NOT_REACHED();
case OFPUTIL_P_OF10_STD_TID:
case OFPUTIL_P_OF10_NXM_TID:
case NXFF_NXM:
return OFPUTIL_P_OF10_NXM;
- case NXFF_OPENFLOW12:
- return OFPUTIL_P_OF12_OXM;
-
default:
return 0;
}
return "openflow10";
case NXFF_NXM:
return "nxm";
- case NXFF_OPENFLOW12:
- return "openflow12";
default:
NOT_REACHED();
}
usable_protocols &= OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
}
- assert(usable_protocols);
return usable_protocols;
}
OFPUTIL_NAMED_PORT(ALL) \
OFPUTIL_NAMED_PORT(CONTROLLER) \
OFPUTIL_NAMED_PORT(LOCAL) \
+ OFPUTIL_NAMED_PORT(ANY)
+
+/* For backwards compatibility, so that "none" is recognized as OFPP_ANY */
+#define OFPUTIL_NAMED_PORTS_WITH_NONE \
+ OFPUTIL_NAMED_PORTS \
OFPUTIL_NAMED_PORT(NONE)
/* Stores the port number represented by 's' into '*portp'. 's' may be an
};
static const struct pair pairs[] = {
#define OFPUTIL_NAMED_PORT(NAME) {#NAME, OFPP_##NAME},
- OFPUTIL_NAMED_PORTS
+ OFPUTIL_NAMED_PORTS_WITH_NONE
#undef OFPUTIL_NAMED_PORT
};
const struct pair *p;
}
case OFP10_VERSION: {
- const struct ofp10_queue_stats_request *qsr11 = ofpmsg_body(request);
- oqsr->queue_id = ntohl(qsr11->queue_id);
- oqsr->port_no = ntohs(qsr11->port_no);
+ const struct ofp10_queue_stats_request *qsr10 = ofpmsg_body(request);
+ oqsr->queue_id = ntohl(qsr10->queue_id);
+ oqsr->port_no = ntohs(qsr10->port_no);
+ /* OF 1.0 uses OFPP_ALL for OFPP_ANY */
+ if (oqsr->port_no == OFPP_ALL) {
+ oqsr->port_no = OFPP_ANY;
+ }
return 0;
}
struct ofp10_queue_stats_request *req;
request = ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST, ofp_version, 0);
req = ofpbuf_put_zeros(request, sizeof *req);
- req->port_no = htons(oqsr->port_no);
+ /* OpenFlow 1.0 needs OFPP_ALL instead of OFPP_ANY */
+ req->port_no = htons(oqsr->port_no == OFPP_ANY
+ ? OFPP_ALL : oqsr->port_no);
req->queue_id = htonl(oqsr->queue_id);
break;
}