/* Most users really don't care about some of the differences between
* protocols. These abbreviations help with that. */
static const struct proto_abbrev proto_abbrevs[] = {
- { OFPUTIL_P_ANY, "any" },
- { OFPUTIL_P_OF10_ANY, "OpenFlow10" },
- { OFPUTIL_P_NXM_ANY, "NXM" },
+ { OFPUTIL_P_ANY, "any" },
+ { OFPUTIL_P_OF10_STD_ANY, "OpenFlow10" },
+ { OFPUTIL_P_OF10_NXM_ANY, "NXM" },
};
#define N_PROTO_ABBREVS ARRAY_SIZE(proto_abbrevs)
enum ofputil_protocol ofputil_flow_dump_protocols[] = {
- OFPUTIL_P_NXM,
- OFPUTIL_P_OF10,
+ OFPUTIL_P_OF10_NXM,
+ OFPUTIL_P_OF10_STD,
};
size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols);
{
switch (version) {
case OFP10_VERSION:
- return OFPUTIL_P_OF10;
+ return OFPUTIL_P_OF10_STD;
case OFP12_VERSION:
- return OFPUTIL_P_OF12;
+ return OFPUTIL_P_OF12_OXM;
case OFP11_VERSION:
default:
return 0;
ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
{
switch (protocol) {
- case OFPUTIL_P_OF10:
- case OFPUTIL_P_OF10_TID:
- case OFPUTIL_P_NXM:
- case OFPUTIL_P_NXM_TID:
+ case OFPUTIL_P_OF10_STD:
+ case OFPUTIL_P_OF10_STD_TID:
+ case OFPUTIL_P_OF10_NXM:
+ case OFPUTIL_P_OF10_NXM_TID:
return OFP10_VERSION;
- case OFPUTIL_P_OF12:
+ case OFPUTIL_P_OF12_OXM:
return OFP12_VERSION;
}
ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable)
{
switch (protocol) {
- case OFPUTIL_P_OF10:
- case OFPUTIL_P_OF10_TID:
- return enable ? OFPUTIL_P_OF10_TID : OFPUTIL_P_OF10;
+ case OFPUTIL_P_OF10_STD:
+ case OFPUTIL_P_OF10_STD_TID:
+ return enable ? OFPUTIL_P_OF10_STD_TID : OFPUTIL_P_OF10_STD;
- case OFPUTIL_P_NXM:
- case OFPUTIL_P_NXM_TID:
- return enable ? OFPUTIL_P_NXM_TID : OFPUTIL_P_NXM;
+ case OFPUTIL_P_OF10_NXM:
+ case OFPUTIL_P_OF10_NXM_TID:
+ return enable ? OFPUTIL_P_OF10_NXM_TID : OFPUTIL_P_OF10_NXM;
- case OFPUTIL_P_OF12:
- return OFPUTIL_P_OF12;
+ case OFPUTIL_P_OF12_OXM:
+ return OFPUTIL_P_OF12_OXM;
default:
NOT_REACHED();
bool tid = (cur & OFPUTIL_P_TID) != 0;
switch (new_base) {
- case OFPUTIL_P_OF10:
- case OFPUTIL_P_OF10_TID:
- return ofputil_protocol_set_tid(OFPUTIL_P_OF10, tid);
+ case OFPUTIL_P_OF10_STD:
+ case OFPUTIL_P_OF10_STD_TID:
+ return ofputil_protocol_set_tid(OFPUTIL_P_OF10_STD, tid);
- case OFPUTIL_P_NXM:
- case OFPUTIL_P_NXM_TID:
- return ofputil_protocol_set_tid(OFPUTIL_P_NXM, tid);
+ case OFPUTIL_P_OF10_NXM:
+ case OFPUTIL_P_OF10_NXM_TID:
+ return ofputil_protocol_set_tid(OFPUTIL_P_OF10_NXM, tid);
- case OFPUTIL_P_OF12:
- return ofputil_protocol_set_tid(OFPUTIL_P_OF12, tid);
+ case OFPUTIL_P_OF12_OXM:
+ return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid);
default:
NOT_REACHED();
/* Use a "switch" statement for single-bit names so that we get a compiler
* warning if we forget any. */
switch (protocol) {
- case OFPUTIL_P_NXM:
+ case OFPUTIL_P_OF10_NXM:
return "NXM-table_id";
- case OFPUTIL_P_NXM_TID:
+ case OFPUTIL_P_OF10_NXM_TID:
return "NXM+table_id";
- case OFPUTIL_P_OF10:
+ case OFPUTIL_P_OF10_STD:
return "OpenFlow10-table_id";
- case OFPUTIL_P_OF10_TID:
+ case OFPUTIL_P_OF10_STD_TID:
return "OpenFlow10+table_id";
- case OFPUTIL_P_OF12:
- return NULL;
+ case OFPUTIL_P_OF12_OXM:
+ return "OXM";
}
/* Check abbreviations. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
- /* NXM and OF1.1+ supports bitwise matching on ethernet addresses. */
+ /* NXM, OXM, and OF1.1 support bitwise matching on ethernet addresses. */
if (!eth_mask_is_exact(wc->masks.dl_src)
&& !eth_addr_is_zero(wc->masks.dl_src)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
if (!eth_mask_is_exact(wc->masks.dl_dst)
&& !eth_addr_is_zero(wc->masks.dl_dst)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* NXM and OF1.1+ support matching metadata. */
+ /* NXM, OXM, and OF1.1+ support matching metadata. */
if (wc->masks.metadata != htonll(0)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching ARP hardware addresses. */
+ /* NXM and OXM support matching ARP hardware addresses. */
if (!eth_addr_is_zero(wc->masks.arp_sha) ||
!eth_addr_is_zero(wc->masks.arp_tha)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching IPv6 traffic. */
+ /* NXM and OXM support matching IPv6 traffic. */
if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching registers. */
+ /* NXM and OXM support matching registers. */
if (!regs_fully_wildcarded(wc)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching tun_id. */
+ /* NXM and OXM support matching tun_id. */
if (wc->masks.tunnel.tun_id != htonll(0)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching fragments. */
+ /* NXM and OXM support matching fragments. */
if (wc->masks.nw_frag) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching IPv6 flow label. */
+ /* NXM and OXM support matching IPv6 flow label. */
if (wc->masks.ipv6_label) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching IP ECN bits. */
+ /* NXM and OXM support matching IP ECN bits. */
if (wc->masks.nw_tos & IP_ECN_MASK) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports matching IP TTL/hop limit. */
+ /* NXM and OXM support matching IP TTL/hop limit. */
if (wc->masks.nw_ttl) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports non-CIDR IPv4 address masks. */
+ /* NXM and OXM support non-CIDR IPv4 address masks. */
if (!ip_is_cidr(wc->masks.nw_src) || !ip_is_cidr(wc->masks.nw_dst)) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
- /* Only NXM supports bitwise matching on transport port. */
+ /* NXM and OXM support bitwise matching on transport port. */
if ((wc->masks.tp_src && wc->masks.tp_src != htons(UINT16_MAX)) ||
(wc->masks.tp_dst && wc->masks.tp_dst != htons(UINT16_MAX))) {
- return OFPUTIL_P_NXM_ANY;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
/* Other formats can express this rule. */
* connection if the switch processes the returned message correctly. (If
* '*next != want' then the caller will have to iterate.)
*
- * If 'current == want', returns NULL and stores 'current' in '*next'. */
+ * If 'current == want', or if it is not possible to transition from 'current'
+ * to 'want' (because, for example, 'current' and 'want' use different OpenFlow
+ * protocol versions), returns NULL and stores 'current' in '*next'. */
struct ofpbuf *
ofputil_encode_set_protocol(enum ofputil_protocol current,
enum ofputil_protocol want,
enum ofputil_protocol *next)
{
+ enum ofp_version cur_version, want_version;
enum ofputil_protocol cur_base, want_base;
bool cur_tid, want_tid;
+ cur_version = ofputil_protocol_to_ofp_version(current);
+ want_version = ofputil_protocol_to_ofp_version(want);
+ if (cur_version != want_version) {
+ *next = current;
+ return NULL;
+ }
+
cur_base = ofputil_protocol_to_base(current);
want_base = ofputil_protocol_to_base(want);
if (cur_base != want_base) {
*next = ofputil_protocol_set_base(current, want_base);
switch (want_base) {
- case OFPUTIL_P_NXM:
+ case OFPUTIL_P_OF10_NXM:
return ofputil_encode_nx_set_flow_format(NXFF_NXM);
- case OFPUTIL_P_OF10:
+ case OFPUTIL_P_OF10_STD:
return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW10);
- case OFPUTIL_P_OF12:
- return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW12);
+ case OFPUTIL_P_OF12_OXM:
+ /* 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_TID:
- case OFPUTIL_P_NXM_TID:
+ case OFPUTIL_P_OF10_STD_TID:
+ case OFPUTIL_P_OF10_NXM_TID:
NOT_REACHED();
}
}
{
switch (flow_format) {
case NXFF_OPENFLOW10:
- return OFPUTIL_P_OF10;
+ return OFPUTIL_P_OF10_STD;
case NXFF_NXM:
- return OFPUTIL_P_NXM;
-
- case NXFF_OPENFLOW12:
- return OFPUTIL_P_OF12;
+ return OFPUTIL_P_OF10_NXM;
default:
return 0;
return "openflow10";
case NXFF_NXM:
return "nxm";
- case NXFF_OPENFLOW12:
- return "openflow12";
default:
NOT_REACHED();
}
struct ofpbuf *msg;
switch (protocol) {
- case OFPUTIL_P_OF12: {
+ case OFPUTIL_P_OF12_OXM: {
struct ofp11_flow_mod *ofm;
msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD, OFP12_VERSION,
break;
}
- case OFPUTIL_P_OF10:
- case OFPUTIL_P_OF10_TID: {
+ case OFPUTIL_P_OF10_STD:
+ case OFPUTIL_P_OF10_STD_TID: {
struct ofp10_flow_mod *ofm;
msg = ofpraw_alloc(OFPRAW_OFPT10_FLOW_MOD, OFP10_VERSION,
break;
}
- case OFPUTIL_P_NXM:
- case OFPUTIL_P_NXM_TID: {
+ case OFPUTIL_P_OF10_NXM:
+ case OFPUTIL_P_OF10_NXM_TID: {
struct nx_flow_mod *nfm;
int match_len;
usable_protocols &= OFPUTIL_P_TID;
}
- /* Matching of the cookie is only supported through NXM. */
+ /* Matching of the cookie is only supported through NXM or OF1.1+. */
if (fm->cookie_mask != htonll(0)) {
- usable_protocols &= OFPUTIL_P_NXM_ANY;
+ usable_protocols &= OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
}
assert(usable_protocols);
enum ofpraw raw;
switch (protocol) {
- case OFPUTIL_P_OF12: {
+ case OFPUTIL_P_OF12_OXM: {
struct ofp11_flow_stats_request *ofsr;
raw = (fsr->aggregate
break;
}
- case OFPUTIL_P_OF10:
- case OFPUTIL_P_OF10_TID: {
+ case OFPUTIL_P_OF10_STD:
+ case OFPUTIL_P_OF10_STD_TID: {
struct ofp10_flow_stats_request *ofsr;
raw = (fsr->aggregate
break;
}
- case OFPUTIL_P_NXM:
- case OFPUTIL_P_NXM_TID: {
+ case OFPUTIL_P_OF10_NXM:
+ case OFPUTIL_P_OF10_NXM_TID: {
struct nx_flow_stats_request *nfsr;
int match_len;
usable_protocols = ofputil_usable_protocols(&fsr->match);
if (fsr->cookie_mask != htonll(0)) {
- usable_protocols &= OFPUTIL_P_NXM_ANY;
+ usable_protocols &= OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
}
return usable_protocols;
}
struct ofpbuf *msg;
switch (protocol) {
- case OFPUTIL_P_OF12: {
+ case OFPUTIL_P_OF12_OXM: {
struct ofp12_flow_removed *ofr;
msg = ofpraw_alloc_xid(OFPRAW_OFPT11_FLOW_REMOVED,
break;
}
- case OFPUTIL_P_OF10:
- case OFPUTIL_P_OF10_TID: {
+ case OFPUTIL_P_OF10_STD:
+ case OFPUTIL_P_OF10_STD_TID: {
struct ofp_flow_removed *ofr;
msg = ofpraw_alloc_xid(OFPRAW_OFPT10_FLOW_REMOVED, OFP10_VERSION,
break;
}
- case OFPUTIL_P_NXM:
- case OFPUTIL_P_NXM_TID: {
+ case OFPUTIL_P_OF10_NXM:
+ case OFPUTIL_P_OF10_NXM_TID: {
struct nx_flow_removed *nfr;
int match_len;
struct ofpbuf *packet;
/* Add OFPT_PACKET_IN. */
- if (protocol == OFPUTIL_P_OF12) {
+ if (protocol == OFPUTIL_P_OF12_OXM) {
struct ofp12_packet_in *opi;
struct match match;