- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
- char *s = ovn_flow_to_string(f);
- VLOG_WARN_RL(&rl, "found duplicate flow %s for parent "UUID_FMT,
- s, UUID_ARGS(&f->uuid));
+ /* Duplicate flows with the same UUID indicate some kind of bug
+ * (see the function-level comment), but we distinguish two
+ * cases:
+ *
+ * - If the actions for the duplicate flow are the same, then
+ * it's benign; it's hard to imagine how there could be a
+ * real problem. Log at INFO level.
+ *
+ * - If the actions are different, then one or the other set of
+ * actions must be wrong or (perhaps more likely) we've got a
+ * new set of actions replacing an old set but the caller
+ * neglected to use ofctrl_remove_flows() or
+ * ofctrl_set_flow() to do it properly. Log at WARN level to
+ * get some attention.
+ */
+ if (ofpacts_equal(f->ofpacts, f->ofpacts_len,
+ d->ofpacts, d->ofpacts_len)) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+ log_ovn_flow_rl(&rl, VLL_INFO, f, "duplicate flow");
+ } else {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+ log_ovn_flow_rl(&rl, VLL_WARN, f,
+ "duplicate flow with modified action");
+
+ /* It seems likely that the newer actions are the correct
+ * ones. */
+ free(d->ofpacts);
+ d->ofpacts = f->ofpacts;
+ d->ofpacts_len = f->ofpacts_len;
+ f->ofpacts = NULL;
+ }