/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "nx-match.h"
#include "ofp-util.h"
#include "ofpbuf.h"
+#include "util.h"
#include "vlog.h"
VLOG_DEFINE_THIS_MODULE(ofp_actions);
case OFPUTIL_OFPAT11_PUSH_VLAN:
if (((const struct ofp11_action_push *)a)->ethertype !=
htons(ETH_TYPE_VLAN_8021Q)) {
- /* TODO:XXX 802.1AD(QinQ) isn't supported at the moment */
- return OFPERR_OFPET_BAD_ACTION;
+ /* XXX 802.1AD(QinQ) isn't supported at the moment */
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
}
ofpact_put_PUSH_VLAN(out);
break;
static inline const struct STRUCT * \
instruction_get_##ENUM(const struct ofp11_instruction *inst)\
{ \
- assert(inst->type == htons(ENUM)); \
+ ovs_assert(inst->type == htons(ENUM)); \
return (struct STRUCT *)inst; \
} \
\
}
if (out[type]) {
- return OFPERR_OFPIT_BAD_INSTRUCTION;
+ return OFPERR_OFPBAC_UNSUPPORTED_ORDER; /* No specific code for
+ * a duplicate instruction
+ * exist */
}
out[type] = inst;
}
insts[OVSINST_OFPIT11_CLEAR_ACTIONS]);
ofpact_put_CLEAR_ACTIONS(ofpacts);
}
- /* TODO:XXX Write-Actions */
+ /* XXX Write-Actions */
if (insts[OVSINST_OFPIT11_WRITE_METADATA]) {
const struct ofp11_instruction_write_metadata *oiwm;
struct ofpact_metadata *om;
ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len)
{
const struct ofpact *a;
- const struct ofpact_metadata *om = NULL;
+ enum ovs_instruction_type inst;
+ inst = OVSINST_OFPIT11_APPLY_ACTIONS;
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
- if (om) {
- if (a->type == OFPACT_WRITE_METADATA) {
- VLOG_WARN("duplicate write_metadata instruction specified");
- /* should be OFPERR_OFPET_BAD_ACTION? */
- return OFPERR_OFPBAC_UNSUPPORTED_ORDER;
+ enum ovs_instruction_type next;
+
+ if (a->type == OFPACT_CLEAR_ACTIONS) {
+ next = OVSINST_OFPIT11_CLEAR_ACTIONS;
+ } else if (a->type == OFPACT_WRITE_METADATA) {
+ next = OVSINST_OFPIT11_WRITE_METADATA;
+ } else if (a->type == OFPACT_GOTO_TABLE) {
+ next = OVSINST_OFPIT11_GOTO_TABLE;
+ } else {
+ next = OVSINST_OFPIT11_APPLY_ACTIONS;
+ }
+
+ if (inst != OVSINST_OFPIT11_APPLY_ACTIONS && next <= inst) {
+ const char *name = ofpact_instruction_name_from_type(inst);
+ const char *next_name = ofpact_instruction_name_from_type(next);
+
+ if (next == inst) {
+ VLOG_WARN("duplicate %s instruction not allowed, for OpenFlow "
+ "1.1+ compatibility", name);
} else {
- VLOG_WARN("write_metadata instruction must be specified after "
- "other instructions/actions");
- return OFPERR_OFPBAC_UNSUPPORTED_ORDER;
+ VLOG_WARN("invalid instruction ordering: %s must appear "
+ "before %s, for OpenFlow 1.1+ compatibility",
+ next_name, name);
}
+ return OFPERR_OFPBAC_UNSUPPORTED_ORDER;
}
- if (a->type == OFPACT_WRITE_METADATA) {
- om = (const struct ofpact_metadata *) a;
- }
+ inst = next;
}
return 0;
case OFPACT_PUSH_VLAN:
case OFPACT_CLEAR_ACTIONS:
case OFPACT_GOTO_TABLE:
- /* TODO:XXX */
+ /* XXX */
break;
case OFPACT_CONTROLLER:
break;
case OFPACT_PUSH_VLAN:
- /* TODO:XXX ETH_TYPE_VLAN_8021AD case */
+ /* XXX ETH_TYPE_VLAN_8021AD case */
ofputil_put_OFPAT11_PUSH_VLAN(out)->ethertype =
htons(ETH_TYPE_VLAN_8021Q);
break;
const struct ofpact *a;
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
- /* TODO:XXX Write-Actions */
+ /* XXX Write-Actions */
if (a->type == OFPACT_CLEAR_ACTIONS) {
instruction_put_OFPIT11_CLEAR_ACTIONS(openflow);
break;
case OFPACT_PUSH_VLAN:
- /* TODO:XXX 802.1AD case*/
+ /* XXX 802.1AD case*/
ds_put_format(s, "push_vlan:%#"PRIx16, ETH_TYPE_VLAN_8021Q);
break;
case OFPACT_SET_IPV4_SRC:
ds_put_format(s, "mod_nw_src:"IP_FMT,
- IP_ARGS(&ofpact_get_SET_IPV4_SRC(a)->ipv4));
+ IP_ARGS(ofpact_get_SET_IPV4_SRC(a)->ipv4));
break;
case OFPACT_SET_IPV4_DST:
ds_put_format(s, "mod_nw_dst:"IP_FMT,
- IP_ARGS(&ofpact_get_SET_IPV4_DST(a)->ipv4));
+ IP_ARGS(ofpact_get_SET_IPV4_DST(a)->ipv4));
break;
case OFPACT_SET_IPV4_DSCP:
ds_put_cstr(string, ",");
}
- /* TODO:XXX write-actions */
+ /* XXX write-actions */
ofpact_format(a, string);
}
}
void
ofpact_update_len(struct ofpbuf *ofpacts, struct ofpact *ofpact)
{
- assert(ofpact == ofpacts->l2);
+ ovs_assert(ofpact == ofpacts->l2);
ofpact->len = (char *) ofpbuf_tail(ofpacts) - (char *) ofpact;
}