flow_wildcards_init_catchall(wc);
wc->wildcards = (OVS_FORCE flow_wildcards_t) ofpfw & WC_INVARIANTS;
- /* Wildcard fields that aren't defined by ofp10_match or tun_id. */
+ /* Wildcard fields that aren't defined by ofp10_match. */
wc->wildcards |= FWW_NW_ECN | FWW_NW_TTL;
if (ofpfw & OFPFW10_NW_TOS) {
match->in_port = ofputil_port_to_ofp11(rule->flow.in_port);
}
-
memcpy(match->dl_src, rule->flow.dl_src, ETH_ADDR_LEN);
for (i = 0; i < ETH_ADDR_LEN; i++) {
match->dl_src_mask[i] = ~rule->wc.dl_src_mask[i];
return 0;
}
+static ovs_be16
+ofputil_tid_command(const struct ofputil_flow_mod *fm,
+ enum ofputil_protocol protocol)
+{
+ return htons(protocol & OFPUTIL_P_TID
+ ? (fm->command & 0xff) | (fm->table_id << 8)
+ : fm->command);
+}
+
/* Converts 'fm' into an OFPT_FLOW_MOD or NXT_FLOW_MOD message according to
* 'protocol' and returns the message. */
struct ofpbuf *
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)
- : fm->command);
switch (protocol) {
+ case OFPUTIL_P_OF12: {
+ struct ofp11_flow_mod *ofm;
+
+ msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD, OFP12_VERSION,
+ NXM_TYPICAL_LEN + fm->ofpacts_len);
+ ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
+ ofm->cookie = fm->new_cookie;
+ ofm->cookie_mask = fm->cookie_mask;
+ ofm->table_id = fm->table_id;
+ ofm->command = fm->command;
+ ofm->idle_timeout = htons(fm->idle_timeout);
+ ofm->hard_timeout = htons(fm->hard_timeout);
+ ofm->priority = htons(fm->cr.priority);
+ ofm->buffer_id = htonl(fm->buffer_id);
+ ofm->out_port = ofputil_port_to_ofp11(fm->out_port);
+ ofm->out_group = htonl(OFPG11_ANY);
+ ofm->flags = htons(fm->flags);
+ oxm_put_match(msg, &fm->cr);
+ if (fm->ofpacts) {
+ ofpacts_put_openflow11_instructions(fm->ofpacts, fm->ofpacts_len,
+ msg);
+ }
+ break;
+ }
+
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);
ofputil_cls_rule_to_ofp10_match(&fm->cr, &ofm->match);
ofm->cookie = fm->new_cookie;
- ofm->command = htons(command);
+ ofm->command = ofputil_tid_command(fm, protocol);
ofm->idle_timeout = htons(fm->idle_timeout);
ofm->hard_timeout = htons(fm->hard_timeout);
ofm->priority = htons(fm->cr.priority);
ofm->buffer_id = htonl(fm->buffer_id);
ofm->out_port = htons(fm->out_port);
ofm->flags = htons(fm->flags);
+ if (fm->ofpacts) {
+ ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
+ }
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->command = htons(command);
+ nfm->command = ofputil_tid_command(fm, protocol);
nfm->cookie = fm->new_cookie;
- match_len = nx_put_match(msg, false, &fm->cr,
- fm->cookie, fm->cookie_mask);
+ match_len = nx_put_match(msg, &fm->cr, fm->cookie, fm->cookie_mask);
nfm = msg->l3;
nfm->idle_timeout = htons(fm->idle_timeout);
nfm->hard_timeout = htons(fm->hard_timeout);
nfm->out_port = htons(fm->out_port);
nfm->flags = htons(fm->flags);
nfm->match_len = htons(match_len);
+ if (fm->ofpacts) {
+ ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
+ }
break;
+ }
- case OFPUTIL_P_OF12:
default:
NOT_REACHED();
}
- if (fm->ofpacts) {
- ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
- }
ofpmsg_update_length(msg);
return msg;
}
: OFPRAW_NXST_FLOW_REQUEST);
msg = ofpraw_alloc(raw, OFP10_VERSION, 0);
ofpbuf_put_zeros(msg, sizeof *nfsr);
- match_len = nx_put_match(msg, false, &fsr->match,
+ match_len = nx_put_match(msg, &fsr->match,
fsr->cookie, fsr->cookie_mask);
nfsr = msg->l3;
int match_len;
ofpbuf_put_uninit(reply, sizeof *nfs);
- match_len = nx_put_match(reply, false, &fs->rule, 0, 0);
+ match_len = nx_put_match(reply, &fs->rule, 0, 0);
ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_REMOVED, OFP10_VERSION,
htonl(0), NXM_TYPICAL_LEN);
nfr = ofpbuf_put_zeros(msg, sizeof *nfr);
- match_len = nx_put_match(msg, false, &fr->rule, 0, 0);
+ match_len = nx_put_match(msg, &fr->rule, 0, 0);
nfr = msg->l3;
nfr->cookie = fr->cookie;
htonl(0), (sizeof(struct flow_metadata) * 2
+ 2 + send_len));
ofpbuf_put_zeros(packet, sizeof *npi);
- match_len = nx_put_match(packet, false, &rule, 0, 0);
+ match_len = nx_put_match(packet, &rule, 0, 0);
ofpbuf_put_zeros(packet, 2);
ofpbuf_put(packet, pin->packet, send_len);
/* 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 of11_action_bits[] = {
- { OFPUTIL_A_OUTPUT, OFPAT11_OUTPUT },
- { OFPUTIL_A_SET_VLAN_VID, OFPAT11_SET_VLAN_VID },
- { OFPUTIL_A_SET_VLAN_PCP, OFPAT11_SET_VLAN_PCP },
- { OFPUTIL_A_SET_DL_SRC, OFPAT11_SET_DL_SRC },
- { OFPUTIL_A_SET_DL_DST, OFPAT11_SET_DL_DST },
- { OFPUTIL_A_SET_NW_SRC, OFPAT11_SET_NW_SRC },
- { OFPUTIL_A_SET_NW_DST, OFPAT11_SET_NW_DST },
- { OFPUTIL_A_SET_NW_TOS, OFPAT11_SET_NW_TOS },
- { OFPUTIL_A_SET_NW_ECN, OFPAT11_SET_NW_ECN },
- { OFPUTIL_A_SET_TP_SRC, OFPAT11_SET_TP_SRC },
- { OFPUTIL_A_SET_TP_DST, OFPAT11_SET_TP_DST },
- { OFPUTIL_A_COPY_TTL_OUT, OFPAT11_COPY_TTL_OUT },
- { OFPUTIL_A_COPY_TTL_IN, OFPAT11_COPY_TTL_IN },
- { OFPUTIL_A_SET_MPLS_LABEL, OFPAT11_SET_MPLS_LABEL },
- { OFPUTIL_A_SET_MPLS_TC, OFPAT11_SET_MPLS_TC },
- { OFPUTIL_A_SET_MPLS_TTL, OFPAT11_SET_MPLS_TTL },
- { OFPUTIL_A_DEC_MPLS_TTL, OFPAT11_DEC_MPLS_TTL },
- { OFPUTIL_A_PUSH_VLAN, OFPAT11_PUSH_VLAN },
- { OFPUTIL_A_POP_VLAN, OFPAT11_POP_VLAN },
- { OFPUTIL_A_PUSH_MPLS, OFPAT11_PUSH_MPLS },
- { OFPUTIL_A_POP_MPLS, OFPAT11_POP_MPLS },
- { OFPUTIL_A_SET_QUEUE, OFPAT11_SET_QUEUE },
- { OFPUTIL_A_GROUP, OFPAT11_GROUP },
- { OFPUTIL_A_SET_NW_TTL, OFPAT11_SET_NW_TTL },
- { OFPUTIL_A_DEC_NW_TTL, OFPAT11_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;
if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) {
features->capabilities |= OFPUTIL_C_GROUP_STATS;
}
- features->actions = decode_action_bits(osf->actions, of11_action_bits);
+ features->actions = 0;
} else {
return OFPERR_OFPBRC_BAD_VERSION;
}
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) {
if (features->capabilities & OFPUTIL_C_GROUP_STATS) {
osf->capabilities |= htonl(OFPC11_GROUP_STATS);
}
- osf->actions = encode_action_bits(features->actions, of11_action_bits);
break;
default:
NOT_REACHED();
start_ofs = msg->size;
ofpbuf_put_zeros(msg, sizeof *nfmr);
- match_len = nx_put_match(msg, false, &rq->match, htonll(0), htonll(0));
+ match_len = nx_put_match(msg, &rq->match, htonll(0), htonll(0));
nfmr = ofpbuf_at_assert(msg, start_ofs, sizeof *nfmr);
nfmr->id = htonl(rq->id);
int match_len;
ofpbuf_put_zeros(msg, sizeof *nfuf);
- match_len = nx_put_match(msg, false, update->match,
- htonll(0), htonll(0));
+ match_len = nx_put_match(msg, update->match, htonll(0), htonll(0));
ofpacts_put_openflow10(update->ofpacts, update->ofpacts_len, msg);
nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
\f
/* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */
struct ofpbuf *
-make_echo_request(void)
+make_echo_request(enum ofp_version ofp_version)
{
- return ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST, OFP10_VERSION,
+ return ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST, ofp_version,
htonl(0), 0);
}
}
struct ofpbuf *
-ofputil_encode_barrier_request(void)
+ofputil_encode_barrier_request(enum ofp_version ofp_version)
{
- return ofpraw_alloc(OFPRAW_OFPT10_BARRIER_REQUEST, OFP10_VERSION, 0);
+ enum ofpraw type;
+
+ switch (ofp_version) {
+ case OFP12_VERSION:
+ case OFP11_VERSION:
+ type = OFPRAW_OFPT11_BARRIER_REQUEST;
+ break;
+
+ case OFP10_VERSION:
+ type = OFPRAW_OFPT10_BARRIER_REQUEST;
+ break;
+
+ default:
+ NOT_REACHED();
+ }
+
+ return ofpraw_alloc(type, ofp_version, 0);
}
const char *