/* Initialize most of rule->flow. */
rule->flow.nw_src = match->nw_src;
rule->flow.nw_dst = match->nw_dst;
- rule->flow.in_port = (match->in_port == htons(OFPP_LOCAL) ? ODPP_LOCAL
- : ntohs(match->in_port));
+ rule->flow.in_port = ntohs(match->in_port);
rule->flow.dl_type = ofputil_dl_type_from_openflow(match->dl_type);
rule->flow.tp_src = match->tp_src;
rule->flow.tp_dst = match->tp_dst;
/* Compose most of the match structure. */
match->wildcards = htonl(ofpfw);
- match->in_port = htons(rule->flow.in_port == ODPP_LOCAL ? OFPP_LOCAL
- : rule->flow.in_port);
+ match->in_port = htons(rule->flow.in_port);
memcpy(match->dl_src, rule->flow.dl_src, ETH_ADDR_LEN);
memcpy(match->dl_dst, rule->flow.dl_dst, ETH_ADDR_LEN);
match->dl_type = ofputil_dl_type_to_openflow(rule->flow.dl_type);
const struct ofputil_msg_type **typep)
{
const struct ofputil_msg_type *type;
+ bool found;
+ found = false;
for (type = cat->types; type < &cat->types[cat->n_types]; type++) {
if (type->value == value) {
- if (!ofputil_length_ok(cat, type, size)) {
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
+ if (ofputil_length_ok(cat, type, size)) {
+ *typep = type;
+ return 0;
}
- *typep = type;
- return 0;
+
+ /* We found a matching command type but it had the wrong length.
+ * Probably this is just an error. However, a screwup means that
+ * NXT_SET_FLOW_FORMAT and NXT_FLOW_MOD_TABLE_ID have the same
+ * value. They do have different lengths, so we can distinguish
+ * them that way. */
+ found = true;
}
}
+ if (found) {
+ return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
+ }
VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu32,
cat->name, value);
ofputil_decode_vendor(const struct ofp_header *oh,
const struct ofputil_msg_type **typep)
{
+ BUILD_ASSERT_DECL(sizeof(struct nxt_set_flow_format)
+ != sizeof(struct nxt_flow_mod_table_id));
+
static const struct ofputil_msg_type nxt_messages[] = {
{ OFPUTIL_NXT_ROLE_REQUEST,
NXT_ROLE_REQUEST, "NXT_ROLE_REQUEST",
NXT_SET_FLOW_FORMAT, "NXT_SET_FLOW_FORMAT",
sizeof(struct nxt_set_flow_format), 0 },
+ { OFPUTIL_NXT_FLOW_MOD_TABLE_ID,
+ NXT_FLOW_MOD_TABLE_ID, "NXT_FLOW_MOD_TABLE_ID",
+ sizeof(struct nxt_flow_mod_table_id), 0 },
+
{ OFPUTIL_NXT_FLOW_MOD,
NXT_FLOW_MOD, "NXT_FLOW_MOD",
sizeof(struct nx_flow_mod), 8 },
return msg;
}
+/* Returns an OpenFlow message that can be used to turn the flow_mod_table_id
+ * extension on or off (according to 'flow_mod_table_id'). */
+struct ofpbuf *
+ofputil_make_flow_mod_table_id(bool flow_mod_table_id)
+{
+ struct nxt_flow_mod_table_id *nfmti;
+ struct ofpbuf *msg;
+
+ nfmti = make_nxmsg(sizeof *nfmti, NXT_FLOW_MOD_TABLE_ID, &msg);
+ nfmti->set = flow_mod_table_id;
+ return msg;
+}
+
/* Converts an OFPT_FLOW_MOD or NXT_FLOW_MOD message 'oh' into an abstract
* flow_mod in 'fm'. Returns 0 if successful, otherwise an OpenFlow error
* code.
*
+ * 'flow_mod_table_id' should be true if the NXT_FLOW_MOD_TABLE_ID extension is
+ * enabled, false otherwise.
+ *
* Does not validate the flow_mod actions. */
int
-ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh)
+ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh,
+ bool flow_mod_table_id)
{
const struct ofputil_msg_type *type;
+ uint16_t command;
struct ofpbuf b;
ofpbuf_use_const(&b, oh, ntohs(oh->length));
/* Translate the message. */
ofputil_cls_rule_from_match(&match, ntohs(ofm->priority), &fm->cr);
fm->cookie = ofm->cookie;
- fm->command = ntohs(ofm->command);
+ command = ntohs(ofm->command);
fm->idle_timeout = ntohs(ofm->idle_timeout);
fm->hard_timeout = ntohs(ofm->hard_timeout);
fm->buffer_id = ntohl(ofm->buffer_id);
/* Translate the message. */
fm->cookie = nfm->cookie;
- fm->command = ntohs(nfm->command);
+ command = ntohs(nfm->command);
fm->idle_timeout = ntohs(nfm->idle_timeout);
fm->hard_timeout = ntohs(nfm->hard_timeout);
fm->buffer_id = ntohl(nfm->buffer_id);
NOT_REACHED();
}
+ if (flow_mod_table_id) {
+ fm->command = command & 0xff;
+ fm->table_id = command >> 8;
+ } else {
+ fm->command = command;
+ fm->table_id = 0xff;
+ }
+
return 0;
}
/* Converts 'fm' into an OFPT_FLOW_MOD or NXT_FLOW_MOD message according to
- * 'flow_format' and returns the message. */
+ * 'flow_format' and returns the message.
+ *
+ * 'flow_mod_table_id' should be true if the NXT_FLOW_MOD_TABLE_ID extension is
+ * enabled, false otherwise. */
struct ofpbuf *
ofputil_encode_flow_mod(const struct flow_mod *fm,
- enum nx_flow_format flow_format)
+ enum nx_flow_format flow_format,
+ bool flow_mod_table_id)
{
size_t actions_len = fm->n_actions * sizeof *fm->actions;
struct ofpbuf *msg;
+ uint16_t command;
+
+ command = (flow_mod_table_id
+ ? (fm->command & 0xff) | (fm->table_id << 8)
+ : fm->command);
if (flow_format == NXFF_OPENFLOW10) {
struct ofp_flow_mod *ofm;
msg = ofpbuf_new(sizeof *ofm + actions_len);
ofm = put_openflow(sizeof *ofm, OFPT_FLOW_MOD, msg);
ofputil_cls_rule_to_match(&fm->cr, &ofm->match);
- ofm->cookie = fm->cookie;
ofm->command = htons(fm->command);
ofm->idle_timeout = htons(fm->idle_timeout);
ofm->hard_timeout = htons(fm->hard_timeout);
nfm = msg->data;
nfm->cookie = fm->cookie;
- nfm->command = htons(fm->command);
+ nfm->command = htons(command);
nfm->idle_timeout = htons(fm->idle_timeout);
nfm->hard_timeout = htons(fm->hard_timeout);
nfm->priority = htons(fm->cr.priority);
return out;
}
-/* Converts the members of 'opp' from host to network byte order. */
-void
-hton_ofp_phy_port(struct ofp_phy_port *opp)
-{
- opp->port_no = htons(opp->port_no);
- opp->config = htonl(opp->config);
- opp->state = htonl(opp->state);
- opp->curr = htonl(opp->curr);
- opp->advertised = htonl(opp->advertised);
- opp->supported = htonl(opp->supported);
- opp->peer = htonl(opp->peer);
-}
-
static int
check_action_exact_len(const union ofp_action *a, unsigned int len,
unsigned int required_len)
return 0;
}
-/* Returns true if 'action' outputs to 'port' (which must be in network byte
- * order), false otherwise. */
+/* Returns true if 'action' outputs to 'port', false otherwise. */
bool
-action_outputs_to_port(const union ofp_action *action, uint16_t port)
+action_outputs_to_port(const union ofp_action *action, ovs_be16 port)
{
switch (ntohs(action->type)) {
case OFPAT_OUTPUT: