ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
enum ofputil_protocol protocol)
{
- struct ofp10_flow_mod *ofm;
- struct nx_flow_mod *nfm;
struct ofpbuf *msg;
uint16_t command;
- int match_len;
command = (protocol & OFPUTIL_P_TID
? (fm->command & 0xff) | (fm->table_id << 8)
switch (protocol) {
case OFPUTIL_P_OF10:
- case OFPUTIL_P_OF10_TID:
+ case OFPUTIL_P_OF10_TID: {
+ struct ofp10_flow_mod *ofm;
+
msg = ofpraw_alloc(OFPRAW_OFPT10_FLOW_MOD, OFP10_VERSION,
fm->ofpacts_len);
ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
ofm->out_port = htons(fm->out_port);
ofm->flags = htons(fm->flags);
break;
+ }
case OFPUTIL_P_NXM:
- case OFPUTIL_P_NXM_TID:
+ case OFPUTIL_P_NXM_TID: {
+ struct nx_flow_mod *nfm;
+ int match_len;
+
msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD, OFP10_VERSION,
NXM_TYPICAL_LEN + fm->ofpacts_len);
nfm = ofpbuf_put_zeros(msg, sizeof *nfm);
nfm->flags = htons(fm->flags);
nfm->match_len = htons(match_len);
break;
+ }
case OFPUTIL_P_OF12:
default:
/* ofputil_switch_features */
#define OFPC_COMMON (OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
- OFPC_IP_REASM | OFPC_QUEUE_STATS | OFPC_ARP_MATCH_IP)
+ OFPC_IP_REASM | OFPC_QUEUE_STATS)
BUILD_ASSERT_DECL((int) OFPUTIL_C_FLOW_STATS == OFPC_FLOW_STATS);
BUILD_ASSERT_DECL((int) OFPUTIL_C_TABLE_STATS == OFPC_TABLE_STATS);
BUILD_ASSERT_DECL((int) OFPUTIL_C_PORT_STATS == OFPC_PORT_STATS);
{ 0, 0 },
};
+static const struct ofputil_action_bit_translation of12_action_bits[] = {
+ { OFPUTIL_A_OUTPUT, OFPAT12_OUTPUT },
+ { OFPUTIL_A_COPY_TTL_OUT, OFPAT12_COPY_TTL_OUT },
+ { OFPUTIL_A_COPY_TTL_IN, OFPAT12_COPY_TTL_IN },
+ { OFPUTIL_A_SET_MPLS_TTL, OFPAT12_SET_MPLS_TTL },
+ { OFPUTIL_A_DEC_MPLS_TTL, OFPAT12_DEC_MPLS_TTL },
+ { OFPUTIL_A_PUSH_VLAN, OFPAT12_PUSH_VLAN },
+ { OFPUTIL_A_POP_VLAN, OFPAT12_POP_VLAN },
+ { OFPUTIL_A_PUSH_MPLS, OFPAT12_PUSH_MPLS },
+ { OFPUTIL_A_POP_MPLS, OFPAT12_POP_MPLS },
+ { OFPUTIL_A_SET_QUEUE, OFPAT12_SET_QUEUE },
+ { OFPUTIL_A_GROUP, OFPAT12_GROUP },
+ { OFPUTIL_A_SET_NW_TTL, OFPAT12_SET_NW_TTL },
+ { OFPUTIL_A_DEC_NW_TTL, OFPAT12_DEC_NW_TTL },
+ { 0, 0 },
+};
+
static enum ofputil_action_bitmap
decode_action_bits(ovs_be32 of_actions,
const struct ofputil_action_bit_translation *x)
return ofputil_actions;
}
+static uint32_t
+ofputil_capabilities_mask(enum ofp_version ofp_version)
+{
+ /* Handle capabilities whose bit is unique for all Open Flow versions */
+ switch (ofp_version) {
+ case OFP10_VERSION:
+ case OFP11_VERSION:
+ return OFPC_COMMON | OFPC_ARP_MATCH_IP;
+ case OFP12_VERSION:
+ return OFPC_COMMON | OFPC12_PORT_BLOCKED;
+ default:
+ /* Caller needs to check osf->header.version itself */
+ return 0;
+ }
+}
+
/* Decodes an OpenFlow 1.0 or 1.1 "switch_features" structure 'osf' into an
* abstract representation in '*features'. Initializes '*b' to iterate over
* the OpenFlow port structures following 'osf' with later calls to
features->n_buffers = ntohl(osf->n_buffers);
features->n_tables = osf->n_tables;
- features->capabilities = ntohl(osf->capabilities) & OFPC_COMMON;
+ features->capabilities = ntohl(osf->capabilities) &
+ ofputil_capabilities_mask(oh->version);
if (b->size % ofputil_get_phy_port_size(oh->version)) {
return OFPERR_OFPBRC_BAD_LEN;
}
switch ((enum ofp_version)oh->version) {
case OFP11_VERSION:
- case OFP12_VERSION:
features->actions = decode_action_bits(htonl(UINT32_MAX),
of11_action_bits);
break;
+ case OFP12_VERSION:
+ features->actions = decode_action_bits(htonl(UINT32_MAX),
+ of12_action_bits);
+ break;
case OFP10_VERSION:
default:
NOT_REACHED();
osf->n_tables = features->n_tables;
osf->capabilities = htonl(features->capabilities & OFPC_COMMON);
+ osf->capabilities = htonl(features->capabilities &
+ ofputil_capabilities_mask(version));
switch (version) {
case OFP10_VERSION:
if (features->capabilities & OFPUTIL_C_STP) {