Signed-off-by: Ben Pfaff <[email protected]>
---
lib/meta-flow.c | 122 ++++++++++++++++++++++++++----------------------
lib/meta-flow.h | 13 +++++-
lib/nx-match.c | 125 ++++++++++++++++++++++++++++----------------------
lib/nx-match.h | 2 +-
lib/ofp-actions.c | 7 +--
lib/ofp-util.c | 9 ++--
lib/ofp-util.h | 2 +
tests/ovs-ofctl.at | 6 +--
utilities/ovs-ofctl.c | 26 +++++++----
9 files changed, 178 insertions(+), 134 deletions(-)
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 6ef564e..5803ded 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
false,
NXM_NX_DP_HASH, "NXM_NX_DP_HASH",
- NXM_NX_DP_HASH, "NXM_NX_DP_HASH",
+ NXM_NX_DP_HASH, "NXM_NX_DP_HASH", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -71,7 +71,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
false,
NXM_NX_RECIRC_ID, "NXM_NX_RECIRC_ID",
- NXM_NX_RECIRC_ID, "NXM_NX_RECIRC_ID",
+ NXM_NX_RECIRC_ID, "NXM_NX_RECIRC_ID", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -83,7 +83,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_NX_TUN_ID, "NXM_NX_TUN_ID",
- OXM_OF_TUNNEL_ID, "OXM_OF_TUNNEL_ID",
+ OXM_OF_TUNNEL_ID, "OXM_OF_TUNNEL_ID", OFP13_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
FLOW_U32OFS(tunnel.tun_id),
@@ -95,7 +95,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_NX_TUN_IPV4_SRC, "NXM_NX_TUN_IPV4_SRC",
- NXM_NX_TUN_IPV4_SRC, "NXM_NX_TUN_IPV4_SRC",
+ NXM_NX_TUN_IPV4_SRC, "NXM_NX_TUN_IPV4_SRC", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
FLOW_U32OFS(tunnel.ip_src),
@@ -107,7 +107,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_NX_TUN_IPV4_DST, "NXM_NX_TUN_IPV4_DST",
- NXM_NX_TUN_IPV4_DST, "NXM_NX_TUN_IPV4_DST",
+ NXM_NX_TUN_IPV4_DST, "NXM_NX_TUN_IPV4_DST", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
FLOW_U32OFS(tunnel.ip_dst),
@@ -119,7 +119,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
false,
0, NULL,
- 0, NULL,
+ 0, NULL, 0,
OFPUTIL_P_NONE,
OFPUTIL_P_NONE,
-1,
@@ -131,7 +131,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
false,
0, NULL,
- 0, NULL,
+ 0, NULL, 0,
OFPUTIL_P_NONE,
OFPUTIL_P_NONE,
-1,
@@ -143,7 +143,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
false,
0, NULL,
- 0, NULL,
+ 0, NULL, 0,
OFPUTIL_P_NONE,
OFPUTIL_P_NONE,
-1,
@@ -155,7 +155,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
OXM_OF_METADATA, "OXM_OF_METADATA",
- OXM_OF_METADATA, "OXM_OF_METADATA",
+ OXM_OF_METADATA, "OXM_OF_METADATA", OFP12_VERSION,
OFPUTIL_P_NXM_OF11_UP,
OFPUTIL_P_NXM_OF11_UP,
-1,
@@ -167,7 +167,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_OF_IN_PORT, "NXM_OF_IN_PORT",
- NXM_OF_IN_PORT, "NXM_OF_IN_PORT",
+ NXM_OF_IN_PORT, "NXM_OF_IN_PORT", 0,
OFPUTIL_P_ANY, /* OF11+ via mapping to 32 bits. */
OFPUTIL_P_NONE,
-1,
@@ -179,7 +179,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
OXM_OF_IN_PORT, "OXM_OF_IN_PORT",
- OXM_OF_IN_PORT, "OXM_OF_IN_PORT",
+ OXM_OF_IN_PORT, "OXM_OF_IN_PORT", OFP12_VERSION,
OFPUTIL_P_OF11_UP,
OFPUTIL_P_NONE,
-1,
@@ -191,7 +191,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
false,
0, NULL,
- 0, NULL,
+ 0, NULL, 0,
OFPUTIL_P_NONE,
OFPUTIL_P_NONE,
-1,
@@ -203,7 +203,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK",
- NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK",
+ NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -218,7 +218,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE, \
true, \
NXM_NX_REG(IDX), "NXM_NX_REG" #IDX, \
- NXM_NX_REG(IDX), "NXM_NX_REG" #IDX, \
+ NXM_NX_REG(IDX), "NXM_NX_REG" #IDX, 0, \
OFPUTIL_P_NXM_OXM_ANY, \
OFPUTIL_P_NXM_OXM_ANY, \
-1, \
@@ -263,7 +263,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_OF_ETH_SRC, "NXM_OF_ETH_SRC",
- OXM_OF_ETH_SRC, "OXM_OF_ETH_SRC",
+ OXM_OF_ETH_SRC, "OXM_OF_ETH_SRC", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OF11_UP, /* Bitwise masking only with NXM and OF11+! */
-1,
@@ -275,7 +275,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_OF_ETH_DST, "NXM_OF_ETH_DST",
- OXM_OF_ETH_DST, "OXM_OF_ETH_DST",
+ OXM_OF_ETH_DST, "OXM_OF_ETH_DST", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OF11_UP, /* Bitwise masking only with NXM and OF11+! */
-1,
@@ -287,7 +287,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
false,
NXM_OF_ETH_TYPE, "NXM_OF_ETH_TYPE",
- OXM_OF_ETH_TYPE, "OXM_OF_ETH_TYPE",
+ OXM_OF_ETH_TYPE, "OXM_OF_ETH_TYPE", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NONE,
-1,
@@ -301,7 +301,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI",
- NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI",
+ NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI", 0,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -313,7 +313,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
0, NULL,
- 0, NULL,
+ 0, NULL, 0,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -325,7 +325,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID",
- OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID",
+ OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -337,7 +337,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_NONE,
true,
0, NULL,
- 0, NULL,
+ 0, NULL, 0,
OFPUTIL_P_ANY, /* Will be mapped to NXM and OXM. */
OFPUTIL_P_NONE,
-1,
@@ -349,7 +349,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_VLAN_VID,
true,
OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP",
- OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP",
+ OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP", OFP12_VERSION,
OFPUTIL_P_ANY, /* Will be mapped to OF10 and NXM. */
OFPUTIL_P_NONE,
-1,
@@ -366,7 +366,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_MPLS,
true,
OXM_OF_MPLS_LABEL, "OXM_OF_MPLS_LABEL",
- OXM_OF_MPLS_LABEL, "OXM_OF_MPLS_LABEL",
+ OXM_OF_MPLS_LABEL, "OXM_OF_MPLS_LABEL", OFP12_VERSION,
OFPUTIL_P_NXM_OF11_UP,
OFPUTIL_P_NONE,
-1,
@@ -378,7 +378,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_MPLS,
true,
OXM_OF_MPLS_TC, "OXM_OF_MPLS_TC",
- OXM_OF_MPLS_TC, "OXM_OF_MPLS_TC",
+ OXM_OF_MPLS_TC, "OXM_OF_MPLS_TC", OFP12_VERSION,
OFPUTIL_P_NXM_OF11_UP,
OFPUTIL_P_NONE,
-1,
@@ -390,7 +390,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_MPLS,
false,
OXM_OF_MPLS_BOS, "OXM_OF_MPLS_BOS",
- OXM_OF_MPLS_BOS, "OXM_OF_MPLS_BOS",
+ OXM_OF_MPLS_BOS, "OXM_OF_MPLS_BOS", OFP13_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NONE,
-1,
@@ -408,7 +408,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IPV4,
true,
NXM_OF_IP_SRC, "NXM_OF_IP_SRC",
- OXM_OF_IPV4_SRC, "OXM_OF_IPV4_SRC",
+ OXM_OF_IPV4_SRC, "OXM_OF_IPV4_SRC", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OF11_UP,
FLOW_U32OFS(nw_src),
@@ -420,7 +420,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IPV4,
true,
NXM_OF_IP_DST, "NXM_OF_IP_DST",
- OXM_OF_IPV4_DST, "OXM_OF_IPV4_DST",
+ OXM_OF_IPV4_DST, "OXM_OF_IPV4_DST", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OF11_UP,
FLOW_U32OFS(nw_dst),
@@ -434,7 +434,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IPV6,
true,
NXM_NX_IPV6_SRC, "NXM_NX_IPV6_SRC",
- OXM_OF_IPV6_SRC, "OXM_OF_IPV6_SRC",
+ OXM_OF_IPV6_SRC, "OXM_OF_IPV6_SRC", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
FLOW_U32OFS(ipv6_src),
@@ -446,7 +446,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IPV6,
true,
NXM_NX_IPV6_DST, "NXM_NX_IPV6_DST",
- OXM_OF_IPV6_DST, "OXM_OF_IPV6_DST",
+ OXM_OF_IPV6_DST, "OXM_OF_IPV6_DST", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
FLOW_U32OFS(ipv6_dst),
@@ -459,7 +459,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IPV6,
false,
NXM_NX_IPV6_LABEL, "NXM_NX_IPV6_LABEL",
- OXM_OF_IPV6_FLABEL, "OXM_OF_IPV6_FLABEL",
+ OXM_OF_IPV6_FLABEL, "OXM_OF_IPV6_FLABEL", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -473,7 +473,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IP_ANY,
false,
NXM_OF_IP_PROTO, "NXM_OF_IP_PROTO",
- OXM_OF_IP_PROTO, "OXM_OF_IP_PROTO",
+ OXM_OF_IP_PROTO, "OXM_OF_IP_PROTO", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NONE,
-1,
@@ -485,7 +485,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IP_ANY,
true,
NXM_OF_IP_TOS, "NXM_OF_IP_TOS",
- NXM_OF_IP_TOS, "NXM_OF_IP_TOS",
+ NXM_OF_IP_TOS, "NXM_OF_IP_TOS", 0,
OFPUTIL_P_ANY, /* Will be shifted for OXM. */
OFPUTIL_P_NONE,
-1,
@@ -497,7 +497,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IP_ANY,
true,
OXM_OF_IP_DSCP, "OXM_OF_IP_DSCP",
- OXM_OF_IP_DSCP, "OXM_OF_IP_DSCP",
+ OXM_OF_IP_DSCP, "OXM_OF_IP_DSCP", OFP12_VERSION,
OFPUTIL_P_ANY, /* Will be shifted for non-OXM. */
OFPUTIL_P_NONE,
-1,
@@ -509,7 +509,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IP_ANY,
true,
NXM_NX_IP_ECN, "NXM_NX_IP_ECN",
- OXM_OF_IP_ECN, "OXM_OF_IP_ECN",
+ OXM_OF_IP_ECN, "OXM_OF_IP_ECN", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NONE,
-1,
@@ -521,7 +521,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IP_ANY,
true,
NXM_NX_IP_TTL, "NXM_NX_IP_TTL",
- NXM_NX_IP_TTL, "NXM_NX_IP_TTL",
+ NXM_NX_IP_TTL, "NXM_NX_IP_TTL", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NONE,
-1,
@@ -533,7 +533,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_IP_ANY,
false,
NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG",
- NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG",
+ NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -547,7 +547,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ARP,
true,
NXM_OF_ARP_OP, "NXM_OF_ARP_OP",
- OXM_OF_ARP_OP, "OXM_OF_ARP_OP",
+ OXM_OF_ARP_OP, "OXM_OF_ARP_OP", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NONE,
-1,
@@ -559,7 +559,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ARP,
true,
NXM_OF_ARP_SPA, "NXM_OF_ARP_SPA",
- OXM_OF_ARP_SPA, "OXM_OF_ARP_SPA",
+ OXM_OF_ARP_SPA, "OXM_OF_ARP_SPA", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OF11_UP,
-1,
@@ -571,7 +571,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ARP,
true,
NXM_OF_ARP_TPA, "NXM_OF_ARP_TPA",
- OXM_OF_ARP_TPA, "OXM_OF_ARP_TPA",
+ OXM_OF_ARP_TPA, "OXM_OF_ARP_TPA", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OF11_UP,
-1,
@@ -583,7 +583,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ARP,
true,
NXM_NX_ARP_SHA, "NXM_NX_ARP_SHA",
- OXM_OF_ARP_SHA, "OXM_OF_ARP_SHA",
+ OXM_OF_ARP_SHA, "OXM_OF_ARP_SHA", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -595,7 +595,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ARP,
true,
NXM_NX_ARP_THA, "NXM_NX_ARP_THA",
- OXM_OF_ARP_THA, "OXM_OF_ARP_THA",
+ OXM_OF_ARP_THA, "OXM_OF_ARP_THA", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -613,7 +613,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_TCP,
true,
NXM_OF_TCP_SRC, "NXM_OF_TCP_SRC",
- OXM_OF_TCP_SRC, "OXM_OF_TCP_SRC",
+ OXM_OF_TCP_SRC, "OXM_OF_TCP_SRC", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -625,7 +625,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_TCP,
true,
NXM_OF_TCP_DST, "NXM_OF_TCP_DST",
- OXM_OF_TCP_DST, "OXM_OF_TCP_DST",
+ OXM_OF_TCP_DST, "OXM_OF_TCP_DST", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -637,7 +637,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_TCP,
false,
NXM_NX_TCP_FLAGS, "NXM_NX_TCP_FLAGS",
- NXM_NX_TCP_FLAGS, "NXM_NX_TCP_FLAGS",
+ NXM_NX_TCP_FLAGS, "NXM_NX_TCP_FLAGS", 0,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -651,7 +651,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_UDP,
true,
NXM_OF_UDP_SRC, "NXM_OF_UDP_SRC",
- OXM_OF_UDP_SRC, "OXM_OF_UDP_SRC",
+ OXM_OF_UDP_SRC, "OXM_OF_UDP_SRC", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -663,7 +663,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_UDP,
true,
NXM_OF_UDP_DST, "NXM_OF_UDP_DST",
- OXM_OF_UDP_DST, "OXM_OF_UDP_DST",
+ OXM_OF_UDP_DST, "OXM_OF_UDP_DST", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -677,7 +677,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_SCTP,
true,
OXM_OF_SCTP_SRC, "OXM_OF_SCTP_SRC",
- OXM_OF_SCTP_SRC, "OXM_OF_SCTP_SRC",
+ OXM_OF_SCTP_SRC, "OXM_OF_SCTP_SRC", OFP12_VERSION,
OFPUTIL_P_NXM_OF11_UP,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -689,7 +689,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_SCTP,
true,
OXM_OF_SCTP_DST, "OXM_OF_SCTP_DST",
- OXM_OF_SCTP_DST, "OXM_OF_SCTP_DST",
+ OXM_OF_SCTP_DST, "OXM_OF_SCTP_DST", OFP12_VERSION,
OFPUTIL_P_NXM_OF11_UP,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -703,7 +703,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ICMPV4,
false,
NXM_OF_ICMP_TYPE, "NXM_OF_ICMP_TYPE",
- OXM_OF_ICMPV4_TYPE, "OXM_OF_ICMPV4_TYPE",
+ OXM_OF_ICMPV4_TYPE, "OXM_OF_ICMPV4_TYPE", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NONE,
-1,
@@ -715,7 +715,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ICMPV4,
false,
NXM_OF_ICMP_CODE, "NXM_OF_ICMP_CODE",
- OXM_OF_ICMPV4_CODE, "OXM_OF_ICMPV4_CODE",
+ OXM_OF_ICMPV4_CODE, "OXM_OF_ICMPV4_CODE", OFP12_VERSION,
OFPUTIL_P_ANY,
OFPUTIL_P_NONE,
-1,
@@ -729,7 +729,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ICMPV6,
false,
NXM_NX_ICMPV6_TYPE, "NXM_NX_ICMPV6_TYPE",
- OXM_OF_ICMPV6_TYPE, "OXM_OF_ICMPV6_TYPE",
+ OXM_OF_ICMPV6_TYPE, "OXM_OF_ICMPV6_TYPE", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NONE,
-1,
@@ -741,7 +741,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ICMPV6,
false,
NXM_NX_ICMPV6_CODE, "NXM_NX_ICMPV6_CODE",
- OXM_OF_ICMPV6_CODE, "OXM_OF_ICMPV6_CODE",
+ OXM_OF_ICMPV6_CODE, "OXM_OF_ICMPV6_CODE", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NONE,
-1,
@@ -759,7 +759,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ND,
false,
NXM_NX_ND_TARGET, "NXM_NX_ND_TARGET",
- OXM_OF_IPV6_ND_TARGET, "OXM_OF_IPV6_ND_TARGET",
+ OXM_OF_IPV6_ND_TARGET, "OXM_OF_IPV6_ND_TARGET", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -771,7 +771,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ND_SOLICIT,
false,
NXM_NX_ND_SLL, "NXM_NX_ND_SLL",
- OXM_OF_IPV6_ND_SLL, "OXM_OF_IPV6_ND_SLL",
+ OXM_OF_IPV6_ND_SLL, "OXM_OF_IPV6_ND_SLL", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -783,7 +783,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
MFP_ND_ADVERT,
false,
NXM_NX_ND_TLL, "NXM_NX_ND_TLL",
- OXM_OF_IPV6_ND_TLL, "OXM_OF_IPV6_ND_TLL",
+ OXM_OF_IPV6_ND_TLL, "OXM_OF_IPV6_ND_TLL", OFP12_VERSION,
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NXM_OXM_ANY,
-1,
@@ -894,6 +894,16 @@ mf_from_nxm_header__(uint32_t header)
return NULL;
}
+uint32_t
+mf_oxm_header(enum mf_field_id id, enum ofp_version oxm_version)
+{
+ const struct mf_field *field = mf_from_id(id);
+
+ return (oxm_version >= field->oxm_version
+ ? field->oxm_header
+ : field->nxm_header);
+}
+
/* Returns true if 'wc' wildcards all the bits in field 'mf', false if 'wc'
* specifies at least one bit in the field.
*
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
index d02d320..7a4b8dc 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -276,6 +276,11 @@ struct mf_field {
*
* - NXM and OXM both define such a field: nxm_header and oxm_header will
* both be nonzero and different, similarly for nxm_name and oxm_name.
+ * In this case, 'oxm_version' is significant: if it is greater than
+ * OFP12_VERSION, then only that version of OpenFlow introduced this
+ * OXM header, so ovs-vswitchd should send 'nxm_header' instead with
+ * earlier protocol versions to avoid confusing controllers that were
+ * using a previous Open vSwitch extension.
*
* - Only NXM or only OXM defines such a field: nxm_header and oxm_header
* will both have the same value (either an OXM_* or NXM_* value) and
@@ -285,11 +290,14 @@ struct mf_field {
* NXM formatted match, since it will be an NXM_* constant when possible
* for compatibility with OpenFlow implementations that expect that, with
* OXM_* constants used for fields that OXM adds. Conversely, 'oxm_header'
- * is the header to use when outputting an OXM formatted match. */
+ * is the header to use when outputting an OXM formatted match to an
+ * OpenFlow connection of version 'oxm_version' or above (and otherwise
+ * 'nxm_header'). */
uint32_t nxm_header; /* An NXM_* (or OXM_*) constant. */
const char *nxm_name; /* The nxm_header constant's name. */
uint32_t oxm_header; /* An OXM_* (or NXM_*) constant. */
const char *oxm_name; /* The oxm_header constant's name */
+ enum ofp_version oxm_version; /* OpenFlow version that added oxm_header. */
/* Usable protocols.
* NXM and OXM are extensible, allowing later extensions to be sent in
@@ -352,6 +360,9 @@ mf_from_id(enum mf_field_id id)
return &mf_fields[id];
}
+/* NXM and OXM protocol headers. */
+uint32_t mf_oxm_header(enum mf_field_id, enum ofp_version oxm_version);
+
/* Inspecting wildcarded bits. */
bool mf_is_all_wild(const struct mf_field *, const struct flow_wildcards *);
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 957c82b..295eec0 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -499,19 +499,19 @@ nxm_put_frag(struct ofpbuf *b, const struct match *match)
/* Appends to 'b' a set of OXM or NXM matches for the IPv4 or IPv6 fields in
* 'match'. */
static void
-nxm_put_ip(struct ofpbuf *b, const struct match *match, bool oxm)
+nxm_put_ip(struct ofpbuf *b, const struct match *match, enum ofp_version oxm)
{
const struct flow *flow = &match->flow;
if (flow->dl_type == htons(ETH_TYPE_IP)) {
- nxm_put_32m(b, oxm ? OXM_OF_IPV4_SRC : NXM_OF_IP_SRC,
+ nxm_put_32m(b, mf_oxm_header(MFF_IPV4_SRC, oxm),
flow->nw_src, match->wc.masks.nw_src);
- nxm_put_32m(b, oxm ? OXM_OF_IPV4_DST : NXM_OF_IP_DST,
+ nxm_put_32m(b, mf_oxm_header(MFF_IPV4_DST, oxm),
flow->nw_dst, match->wc.masks.nw_dst);
} else {
- nxm_put_ipv6(b, oxm ? OXM_OF_IPV6_SRC : NXM_NX_IPV6_SRC,
+ nxm_put_ipv6(b, mf_oxm_header(MFF_IPV6_SRC, oxm),
&flow->ipv6_src, &match->wc.masks.ipv6_src);
- nxm_put_ipv6(b, oxm ? OXM_OF_IPV6_DST : NXM_NX_IPV6_DST,
+ nxm_put_ipv6(b, mf_oxm_header(MFF_IPV6_DST, oxm),
&flow->ipv6_dst, &match->wc.masks.ipv6_dst);
}
@@ -519,74 +519,74 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match,
bool oxm)
if (match->wc.masks.nw_tos & IP_DSCP_MASK) {
if (oxm) {
- nxm_put_8(b, OXM_OF_IP_DSCP, flow->nw_tos >> 2);
+ nxm_put_8(b, mf_oxm_header(MFF_IP_DSCP_SHIFTED, oxm),
+ flow->nw_tos >> 2);
} else {
- nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
+ nxm_put_8(b, mf_oxm_header(MFF_IP_DSCP, oxm),
+ flow->nw_tos & IP_DSCP_MASK);
}
}
if (match->wc.masks.nw_tos & IP_ECN_MASK) {
- nxm_put_8(b, oxm ? OXM_OF_IP_ECN : NXM_NX_IP_ECN,
+ nxm_put_8(b, mf_oxm_header(MFF_IP_ECN, oxm),
flow->nw_tos & IP_ECN_MASK);
}
if (!oxm && match->wc.masks.nw_ttl) {
- nxm_put_8(b, NXM_NX_IP_TTL, flow->nw_ttl);
+ nxm_put_8(b, mf_oxm_header(MFF_IP_TTL, oxm), flow->nw_ttl);
}
- nxm_put_32m(b, oxm ? OXM_OF_IPV6_FLABEL : NXM_NX_IPV6_LABEL,
+ nxm_put_32m(b, mf_oxm_header(MFF_IPV6_LABEL, oxm),
flow->ipv6_label, match->wc.masks.ipv6_label);
if (match->wc.masks.nw_proto) {
- nxm_put_8(b, oxm ? OXM_OF_IP_PROTO : NXM_OF_IP_PROTO, flow->nw_proto);
+ nxm_put_8(b, mf_oxm_header(MFF_IP_PROTO, oxm), flow->nw_proto);
if (flow->nw_proto == IPPROTO_TCP) {
- nxm_put_16m(b, oxm ? OXM_OF_TCP_SRC : NXM_OF_TCP_SRC,
+ nxm_put_16m(b, mf_oxm_header(MFF_TCP_SRC, oxm),
flow->tp_src, match->wc.masks.tp_src);
- nxm_put_16m(b, oxm ? OXM_OF_TCP_DST : NXM_OF_TCP_DST,
+ nxm_put_16m(b, mf_oxm_header(MFF_TCP_DST, oxm),
flow->tp_dst, match->wc.masks.tp_dst);
- nxm_put_16m(b, NXM_NX_TCP_FLAGS,
+ nxm_put_16m(b, mf_oxm_header(MFF_TCP_FLAGS, oxm),
flow->tcp_flags, match->wc.masks.tcp_flags);
} else if (flow->nw_proto == IPPROTO_UDP) {
- nxm_put_16m(b, oxm ? OXM_OF_UDP_SRC : NXM_OF_UDP_SRC,
+ nxm_put_16m(b, mf_oxm_header(MFF_UDP_SRC, oxm),
flow->tp_src, match->wc.masks.tp_src);
- nxm_put_16m(b, oxm ? OXM_OF_UDP_DST : NXM_OF_UDP_DST,
+ nxm_put_16m(b, mf_oxm_header(MFF_UDP_DST, oxm),
flow->tp_dst, match->wc.masks.tp_dst);
} else if (flow->nw_proto == IPPROTO_SCTP) {
- nxm_put_16m(b, OXM_OF_SCTP_SRC, flow->tp_src,
+ nxm_put_16m(b, mf_oxm_header(MFF_SCTP_SRC, oxm), flow->tp_src,
match->wc.masks.tp_src);
- nxm_put_16m(b, OXM_OF_SCTP_DST, flow->tp_dst,
+ nxm_put_16m(b, mf_oxm_header(MFF_SCTP_DST, oxm), flow->tp_dst,
match->wc.masks.tp_dst);
} else if (is_icmpv4(flow)) {
if (match->wc.masks.tp_src) {
- nxm_put_8(b, oxm ? OXM_OF_ICMPV4_TYPE : NXM_OF_ICMP_TYPE,
+ nxm_put_8(b, mf_oxm_header(MFF_ICMPV4_TYPE, oxm),
ntohs(flow->tp_src));
}
if (match->wc.masks.tp_dst) {
- nxm_put_8(b, oxm ? OXM_OF_ICMPV4_CODE : NXM_OF_ICMP_CODE,
+ nxm_put_8(b, mf_oxm_header(MFF_ICMPV4_CODE, oxm),
ntohs(flow->tp_dst));
}
} else if (is_icmpv6(flow)) {
if (match->wc.masks.tp_src) {
- nxm_put_8(b, oxm ? OXM_OF_ICMPV6_TYPE : NXM_NX_ICMPV6_TYPE,
+ nxm_put_8(b, mf_oxm_header(MFF_ICMPV6_TYPE, oxm),
ntohs(flow->tp_src));
}
if (match->wc.masks.tp_dst) {
- nxm_put_8(b, oxm ? OXM_OF_ICMPV6_CODE : NXM_NX_ICMPV6_CODE,
+ nxm_put_8(b, mf_oxm_header(MFF_ICMPV6_CODE, oxm),
ntohs(flow->tp_dst));
}
if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
- nxm_put_ipv6(b, oxm ? OXM_OF_IPV6_ND_TARGET : NXM_NX_ND_TARGET,
+ nxm_put_ipv6(b, mf_oxm_header(MFF_ND_TARGET, oxm),
&flow->nd_target, &match->wc.masks.nd_target);
if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
- uint32_t field = oxm ? OXM_OF_IPV6_ND_SLL : NXM_NX_ND_SLL;
- nxm_put_eth_masked(b, field,
+ nxm_put_eth_masked(b, mf_oxm_header(MFF_ND_SLL, oxm),
flow->arp_sha, match->wc.masks.arp_sha);
}
if (flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
- uint32_t field = oxm ? OXM_OF_IPV6_ND_TLL : NXM_NX_ND_TLL;
- nxm_put_eth_masked(b, field,
+ nxm_put_eth_masked(b, mf_oxm_header(MFF_ND_TLL, oxm),
flow->arp_tha, match->wc.masks.arp_tha);
}
}
@@ -598,6 +598,9 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match,
bool oxm)
* Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
* Otherwise, 'cookie_mask' should be zero.
*
+ * Specify 'oxm' as 0 to express the match in NXM format; otherwise, specify
+ * 'oxm' as the OpenFlow version number for the OXM format to use.
+ *
* This function can cause 'b''s data to be reallocated.
*
* Returns the number of bytes appended to 'b', excluding padding.
@@ -605,7 +608,7 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match,
bool oxm)
* If 'match' is a catch-all rule that matches every packet, then this function
* appends nothing to 'b' and returns 0. */
static int
-nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match,
+nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
ovs_be64 cookie, ovs_be64 cookie_mask)
{
const struct flow *flow = &match->flow;
@@ -632,18 +635,20 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match
*match,
if (match->wc.masks.in_port.ofp_port) {
ofp_port_t in_port = flow->in_port.ofp_port;
if (oxm) {
- nxm_put_32(b, OXM_OF_IN_PORT, ofputil_port_to_ofp11(in_port));
+ nxm_put_32(b, mf_oxm_header(MFF_IN_PORT_OXM, oxm),
+ ofputil_port_to_ofp11(in_port));
} else {
- nxm_put_16(b, NXM_OF_IN_PORT, htons(ofp_to_u16(in_port)));
+ nxm_put_16(b, mf_oxm_header(MFF_IN_PORT, oxm),
+ htons(ofp_to_u16(in_port)));
}
}
/* Ethernet. */
- nxm_put_eth_masked(b, oxm ? OXM_OF_ETH_SRC : NXM_OF_ETH_SRC,
+ nxm_put_eth_masked(b, mf_oxm_header(MFF_ETH_SRC, oxm),
flow->dl_src, match->wc.masks.dl_src);
- nxm_put_eth_masked(b, oxm ? OXM_OF_ETH_DST : NXM_OF_ETH_DST,
+ nxm_put_eth_masked(b, mf_oxm_header(MFF_ETH_DST, oxm),
flow->dl_dst, match->wc.masks.dl_dst);
- nxm_put_16m(b, oxm ? OXM_OF_ETH_TYPE : NXM_OF_ETH_TYPE,
+ nxm_put_16m(b, mf_oxm_header(MFF_ETH_TYPE, oxm),
ofputil_dl_type_to_openflow(flow->dl_type),
match->wc.masks.dl_type);
@@ -654,32 +659,35 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match
*match,
ovs_be16 mask = match->wc.masks.vlan_tci & VID_CFI_MASK;
if (mask == htons(VLAN_VID_MASK | VLAN_CFI)) {
- nxm_put_16(b, OXM_OF_VLAN_VID, vid);
+ nxm_put_16(b, mf_oxm_header(MFF_VLAN_VID, oxm), vid);
} else if (mask) {
- nxm_put_16m(b, OXM_OF_VLAN_VID, vid, mask);
+ nxm_put_16m(b, mf_oxm_header(MFF_VLAN_VID, oxm), vid, mask);
}
if (vid && vlan_tci_to_pcp(match->wc.masks.vlan_tci)) {
- nxm_put_8(b, OXM_OF_VLAN_PCP, vlan_tci_to_pcp(flow->vlan_tci));
+ nxm_put_8(b, mf_oxm_header(MFF_VLAN_PCP, oxm),
+ vlan_tci_to_pcp(flow->vlan_tci));
}
} else {
- nxm_put_16m(b, NXM_OF_VLAN_TCI, flow->vlan_tci,
+ nxm_put_16m(b, mf_oxm_header(MFF_VLAN_TCI, oxm), flow->vlan_tci,
match->wc.masks.vlan_tci);
}
/* MPLS. */
if (eth_type_mpls(flow->dl_type)) {
if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
- nxm_put_8(b, OXM_OF_MPLS_TC, mpls_lse_to_tc(flow->mpls_lse[0]));
+ nxm_put_8(b, mf_oxm_header(MFF_MPLS_TC, oxm),
+ mpls_lse_to_tc(flow->mpls_lse[0]));
}
if (match->wc.masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
- nxm_put_8(b, OXM_OF_MPLS_BOS, mpls_lse_to_bos(flow->mpls_lse[0]));
+ nxm_put_8(b, mf_oxm_header(MFF_MPLS_BOS, oxm),
+ mpls_lse_to_bos(flow->mpls_lse[0]));
}
if (match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
- nxm_put_32(b, OXM_OF_MPLS_LABEL,
+ nxm_put_32(b, mf_oxm_header(MFF_MPLS_LABEL, oxm),
htonl(mpls_lse_to_label(flow->mpls_lse[0])));
}
}
@@ -691,41 +699,42 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match
*match,
flow->dl_type == htons(ETH_TYPE_RARP)) {
/* ARP. */
if (match->wc.masks.nw_proto) {
- nxm_put_16(b, oxm ? OXM_OF_ARP_OP : NXM_OF_ARP_OP,
+ nxm_put_16(b, mf_oxm_header(MFF_ARP_OP, oxm),
htons(flow->nw_proto));
}
- nxm_put_32m(b, oxm ? OXM_OF_ARP_SPA : NXM_OF_ARP_SPA,
+ nxm_put_32m(b, mf_oxm_header(MFF_ARP_SPA, oxm),
flow->nw_src, match->wc.masks.nw_src);
- nxm_put_32m(b, oxm ? OXM_OF_ARP_TPA : NXM_OF_ARP_TPA,
+ nxm_put_32m(b, mf_oxm_header(MFF_ARP_TPA, oxm),
flow->nw_dst, match->wc.masks.nw_dst);
- nxm_put_eth_masked(b, oxm ? OXM_OF_ARP_SHA : NXM_NX_ARP_SHA,
+ nxm_put_eth_masked(b, mf_oxm_header(MFF_ARP_SHA, oxm),
flow->arp_sha, match->wc.masks.arp_sha);
- nxm_put_eth_masked(b, oxm ? OXM_OF_ARP_THA : NXM_NX_ARP_THA,
+ nxm_put_eth_masked(b, mf_oxm_header(MFF_ARP_THA, oxm),
flow->arp_tha, match->wc.masks.arp_tha);
}
/* Tunnel ID. */
- nxm_put_64m(b, oxm ? OXM_OF_TUNNEL_ID : NXM_NX_TUN_ID,
+ nxm_put_64m(b, mf_oxm_header(MFF_TUN_ID, oxm),
flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id);
/* Other tunnel metadata. */
- nxm_put_32m(b, NXM_NX_TUN_IPV4_SRC,
+ nxm_put_32m(b, mf_oxm_header(MFF_TUN_SRC, oxm),
flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src);
- nxm_put_32m(b, NXM_NX_TUN_IPV4_DST,
+ nxm_put_32m(b, mf_oxm_header(MFF_TUN_DST, oxm),
flow->tunnel.ip_dst, match->wc.masks.tunnel.ip_dst);
/* Registers. */
for (i = 0; i < FLOW_N_REGS; i++) {
- nxm_put_32m(b, NXM_NX_REG(i),
+ nxm_put_32m(b, mf_oxm_header(MFF_REG0 + i, oxm),
htonl(flow->regs[i]), htonl(match->wc.masks.regs[i]));
}
/* Mark. */
- nxm_put_32m(b, NXM_NX_PKT_MARK, htonl(flow->pkt_mark),
+ nxm_put_32m(b, mf_oxm_header(MFF_PKT_MARK, oxm), htonl(flow->pkt_mark),
htonl(match->wc.masks.pkt_mark));
/* OpenFlow 1.1+ Metadata. */
- nxm_put_64m(b, OXM_OF_METADATA, flow->metadata, match->wc.masks.metadata);
+ nxm_put_64m(b, mf_oxm_header(MFF_METADATA, oxm),
+ flow->metadata, match->wc.masks.metadata);
/* Cookie. */
nxm_put_64m(b, NXM_NX_COOKIE, cookie, cookie_mask);
@@ -748,23 +757,26 @@ int
nx_put_match(struct ofpbuf *b, const struct match *match,
ovs_be64 cookie, ovs_be64 cookie_mask)
{
- int match_len = nx_put_raw(b, false, match, cookie, cookie_mask);
+ int match_len = nx_put_raw(b, 0, match, cookie, cookie_mask);
ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
return match_len;
}
-
-/* Appends to 'b' an struct ofp11_match_header followed by the oxm format that
+/* Appends to 'b' an struct ofp11_match_header followed by the OXM format that
* expresses 'cr', plus enough zero bytes to pad the data appended out to a
* multiple of 8.
*
+ * OXM differs slightly among versions of OpenFlow. Specify the OpenFlow
+ * version in use as 'version'.
+ *
* This function can cause 'b''s data to be reallocated.
*
* Returns the number of bytes appended to 'b', excluding the padding. Never
* returns zero. */
int
-oxm_put_match(struct ofpbuf *b, const struct match *match)
+oxm_put_match(struct ofpbuf *b, const struct match *match,
+ enum ofp_version version)
{
int match_len;
struct ofp11_match_header *omh;
@@ -772,7 +784,8 @@ oxm_put_match(struct ofpbuf *b, const struct match *match)
ovs_be64 cookie = htonll(0), cookie_mask = htonll(0);
ofpbuf_put_uninit(b, sizeof *omh);
- match_len = nx_put_raw(b, true, match, cookie, cookie_mask) + sizeof *omh;
+ match_len = (nx_put_raw(b, version, match, cookie, cookie_mask)
+ + sizeof *omh);
ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
omh = ofpbuf_at(b, start_len, sizeof *omh);
diff --git a/lib/nx-match.h b/lib/nx-match.h
index edd7948..077f299 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -52,7 +52,7 @@ enum ofperr oxm_pull_match(struct ofpbuf *, struct match *);
enum ofperr oxm_pull_match_loose(struct ofpbuf *, struct match *);
int nx_put_match(struct ofpbuf *, const struct match *,
ovs_be64 cookie, ovs_be64 cookie_mask);
-int oxm_put_match(struct ofpbuf *, const struct match *);
+int oxm_put_match(struct ofpbuf *, const struct match *, enum ofp_version);
char *nx_match_to_string(const uint8_t *, unsigned int match_len);
char *oxm_match_to_string(const struct ofpbuf *, unsigned int match_len);
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index ce14004..cc1f9a0 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -825,14 +825,15 @@ set_field_from_openflow(const struct
ofp12_action_set_field *oasf,
static void
set_field_to_openflow12(const struct ofpact_set_field *sf,
- struct ofpbuf *openflow)
+ struct ofpbuf *openflow,
+ enum ofp_version version)
{
uint16_t padded_value_len = ROUND_UP(sf->field->n_bytes, 8);
struct ofp12_action_set_field *oasf;
char *value;
oasf = ofputil_put_OFPAT12_SET_FIELD(openflow);
- oasf->dst = htonl(sf->field->oxm_header);
+ oasf->dst = htonl(mf_oxm_header(sf->field->id, version));
oasf->len = htons(sizeof *oasf + padded_value_len);
value = ofpbuf_put_zeros(openflow, padded_value_len);
@@ -1080,7 +1081,7 @@ set_field_to_openflow(const struct ofpact_set_field *sf,
struct ofp_header *oh = (struct ofp_header *)openflow->frame;
if (oh->version >= OFP12_VERSION) {
- set_field_to_openflow12(sf, openflow);
+ set_field_to_openflow12(sf, openflow, oh->version);
} else if (oh->version == OFP11_VERSION) {
set_field_to_openflow11(sf, openflow);
} else if (oh->version == OFP10_VERSION) {
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 4bf101a..e29c454 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -665,7 +665,8 @@ ofputil_put_ofp11_match(struct ofpbuf *b, const struct
match *match,
case OFPUTIL_P_OF13_OXM:
case OFPUTIL_P_OF14_OXM:
case OFPUTIL_P_OF15_OXM:
- return oxm_put_match(b, match);
+ return oxm_put_match(b, match,
+ ofputil_protocol_to_ofp_version(protocol));
}
OVS_NOT_REACHED();
@@ -1068,7 +1069,7 @@ ofputil_protocols_from_string(const char *s)
return protocols;
}
-static int
+enum ofp_version
ofputil_version_from_string(const char *s)
{
if (!strcasecmp(s, "OpenFlow10")) {
@@ -2929,7 +2930,7 @@ ofputil_append_flow_stats_reply(const struct
ofputil_flow_stats *fs,
struct ofp11_flow_stats *ofs;
ofpbuf_put_uninit(reply, sizeof *ofs);
- oxm_put_match(reply, &fs->match);
+ oxm_put_match(reply, &fs->match, version);
ofpacts_put_openflow_instructions(fs->ofpacts, fs->ofpacts_len, reply,
version);
@@ -3473,7 +3474,7 @@ ofputil_encode_ofp12_packet_in(const struct
ofputil_packet_in *pin,
htonl(0), (sizeof(struct flow_metadata) * 2
+ 2 + pin->packet_len));
ofpbuf_put_zeros(packet, packet_in_size);
- oxm_put_match(packet, &match);
+ oxm_put_match(packet, &match, ofputil_protocol_to_ofp_version(protocol));
ofpbuf_put_zeros(packet, 2);
ofpbuf_put(packet, pin->packet, pin->packet_len);
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index f0b6604..ce6045b 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -170,6 +170,8 @@ void ofputil_format_version_name(struct ds *, enum
ofp_version);
void ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap);
void ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap);
+enum ofp_version ofputil_version_from_string(const char *s);
+
uint32_t ofputil_protocols_to_version_bitmap(enum ofputil_protocol);
enum ofputil_protocol ofputil_protocols_from_version_bitmap(uint32_t bitmap);
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index bda8666..88e4220 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -1890,7 +1890,7 @@ OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(3a)
OXM_OF_ICMPV6_TYPE(88) OXM_OF_IPV6_ND_
# Invalid field number.
01020304(1111/2222)
])
-AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' --strict parse-oxm < oxm.txt],
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' --strict parse-oxm OpenFlow12
< oxm.txt],
[0], [dnl
<any>
@@ -2123,11 +2123,11 @@ AT_DATA([oxm.txt], [dnl
OXM_OF_IN_PORT(00000001), 01020304(1111/2222), OXM_OF_ETH_TYPE(0800)
])
-AT_CHECK([ovs-ofctl --strict parse-oxm < oxm.txt], [0], [dnl
+AT_CHECK([ovs-ofctl --strict parse-oxm OpenFlow12 < oxm.txt], [0], [dnl
nx_pull_match() returned error OFPBMC_BAD_FIELD
])
-AT_CHECK([ovs-ofctl parse-oxm < oxm.txt], [0], [dnl
+AT_CHECK([ovs-ofctl parse-oxm OpenFlow12 < oxm.txt], [0], [dnl
OXM_OF_IN_PORT(00000001), OXM_OF_ETH_TYPE(0800)
])
AT_CLEANUP
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 986c18f..d62d328 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -2823,7 +2823,7 @@ ofctl_parse_flows(int argc OVS_UNUSED, char *argv[])
}
static void
-ofctl_parse_nxm__(bool oxm)
+ofctl_parse_nxm__(bool oxm, enum ofp_version version)
{
struct ds in;
@@ -2868,7 +2868,7 @@ ofctl_parse_nxm__(bool oxm)
ofpbuf_uninit(&nx_match);
ofpbuf_init(&nx_match, 0);
if (oxm) {
- match_len = oxm_put_match(&nx_match, &match);
+ match_len = oxm_put_match(&nx_match, &match, version);
out = oxm_match_to_string(&nx_match, match_len);
} else {
match_len = nx_put_match(&nx_match, &match,
@@ -2894,16 +2894,22 @@ ofctl_parse_nxm__(bool oxm)
static void
ofctl_parse_nxm(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
- return ofctl_parse_nxm__(false);
+ return ofctl_parse_nxm__(false, 0);
}
-/* "parse-oxm": reads a series of OXM nx_match specifications as strings from
- * stdin, does some internal fussing with them, and then prints them back as
- * strings on stdout. */
+/* "parse-oxm VERSION": reads a series of OXM nx_match specifications as
+ * strings from stdin, does some internal fussing with them, and then prints
+ * them back as strings on stdout. VERSION must specify an OpenFlow version,
+ * e.g. "OpenFlow12". */
static void
-ofctl_parse_oxm(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+ofctl_parse_oxm(int argc OVS_UNUSED, char *argv[])
{
- return ofctl_parse_nxm__(true);
+ enum ofp_version version = ofputil_version_from_string(argv[1]);
+ if (version < OFP12_VERSION) {
+ ovs_fatal(0, "%s: not a valid version for OXM", argv[1]);
+ }
+
+ return ofctl_parse_nxm__(true, version);
}
static void
@@ -3349,7 +3355,7 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
/* Convert to and from OXM. */
ofpbuf_init(&nxm, 0);
- nxm_match_len = oxm_put_match(&nxm, &match);
+ nxm_match_len = oxm_put_match(&nxm, &match, OFP12_VERSION);
nxm_s = oxm_match_to_string(&nxm, nxm_match_len);
error = oxm_pull_match(&nxm, &nxm_match);
printf("OXM: %s -> ", nxm_s);
@@ -3539,7 +3545,7 @@ static const struct command all_commands[] = {
{ "parse-flows", 1, 1, ofctl_parse_flows },
{ "parse-nx-match", 0, 0, ofctl_parse_nxm },
{ "parse-nxm", 0, 0, ofctl_parse_nxm },
- { "parse-oxm", 0, 0, ofctl_parse_oxm },
+ { "parse-oxm", 1, 1, ofctl_parse_oxm },
{ "parse-ofp10-actions", 0, 0, ofctl_parse_ofp10_actions },
{ "parse-ofp10-match", 0, 0, ofctl_parse_ofp10_match },
{ "parse-ofp11-match", 0, 0, ofctl_parse_ofp11_match },
--
1.9.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev