if (a->type == OFPACT_CONJUNCTION) {
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
- if (a->type != OFPACT_CONJUNCTION) {
- VLOG_WARN("when conjunction action is present, it must be "
- "the only kind of action used (saw '%s' action)",
+ if (a->type != OFPACT_CONJUNCTION && a->type != OFPACT_NOTE) {
+ VLOG_WARN("\"conjunction\" actions may be used along with "
+ "\"note\" but not any other kind of action "
+ "(such as the \"%s\" action used here)",
ofpact_name(a->type));
return OFPERR_NXBAC_BAD_CONJUNCTION;
}
return error;
}
-static bool
-is_conjunction(const struct ofpact *ofpacts, size_t ofpacts_len)
-{
- return ofpacts_len > 0 && ofpacts->type == OFPACT_CONJUNCTION;
-}
-
static void
get_conjunctions(const struct ofputil_flow_mod *fm,
struct cls_conjunction **conjsp, size_t *n_conjsp)
struct cls_conjunction *conjs = NULL;
int n_conjs = 0;
- if (is_conjunction(fm->ofpacts, fm->ofpacts_len)) {
- const struct ofpact *ofpact;
- int i;
-
- n_conjs = 0;
- OFPACT_FOR_EACH (ofpact, fm->ofpacts, fm->ofpacts_len) {
+ const struct ofpact *ofpact;
+ OFPACT_FOR_EACH (ofpact, fm->ofpacts, fm->ofpacts_len) {
+ if (ofpact->type == OFPACT_CONJUNCTION) {
n_conjs++;
+ } else if (ofpact->type != OFPACT_NOTE) {
+ /* "conjunction" may appear with "note" actions but not with any
+ * other type of actions. */
+ ovs_assert(!n_conjs);
+ break;
}
+ }
+ if (n_conjs) {
+ int i = 0;
conjs = xzalloc(n_conjs * sizeof *conjs);
- i = 0;
OFPACT_FOR_EACH (ofpact, fm->ofpacts, fm->ofpacts_len) {
- struct ofpact_conjunction *oc = ofpact_get_CONJUNCTION(ofpact);
- conjs[i].clause = oc->clause;
- conjs[i].n_clauses = oc->n_clauses;
- conjs[i].id = oc->id;
- i++;
+ if (ofpact->type == OFPACT_CONJUNCTION) {
+ struct ofpact_conjunction *oc = ofpact_get_CONJUNCTION(ofpact);
+ conjs[i].clause = oc->clause;
+ conjs[i].n_clauses = oc->n_clauses;
+ conjs[i].id = oc->id;
+ i++;
+ }
}
}
done
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+AT_SETUP([conjunctive match and other actions])
+OVS_VSWITCHD_START
+# It's OK to use "conjunction" actions with "note" actions.
+AT_CHECK([ovs-ofctl add-flow br0 'actions=conjunction(3,1/2),note:41.42.43.44.45.46'])
+AT_CHECK([ovs-ofctl add-flow br0 'actions=note:41.42.43.44.45.46,conjunction(3,1/2)'])
+# It's not OK to use "conjunction" actions with other types of actions.
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' add-flow br0 'actions=output:1,conjunction(3,1/2)'], [1], [], [dnl
+ofp_actions|WARN|"conjunction" actions may be used along with "note" but not any other kind of action (such as the "output" action used here)
+ovs-ofctl: Incorrect instruction ordering
+])
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' add-flow br0 'actions=conjunction(3,1/2),output:1'], [1], [], [dnl
+ofp_actions|WARN|"conjunction" actions may be used along with "note" but not any other kind of action (such as the "output" action used here)
+ovs-ofctl: Incorrect instruction ordering
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
of \fBconjunction\fR actions within a list of actions is not
significant.
.IP \(bu
-A flow with \fBconjunction\fR actions may not have any other actions.
-(It would not be useful.)
+A flow with \fBconjunction\fR actions may also include \fBnote\fR
+actions for annotations, but not any other kind of actions. (They
+would not be useful because they would never be executed.)
.IP \(bu
All of the flows that constitute a conjunctive flow with a given
\fIid\fR must have the same priority. (Flows with the same \fIid\fR