((LEFT) -= ntohs((ITER)->header.len) / sizeof(union ofp_action), \
(ITER) = action_next(ITER)))
+static void
+log_bad_action(const union ofp_action *actions, size_t n_actions, size_t ofs,
+ enum ofperr error)
+{
+ if (!VLOG_DROP_WARN(&rl)) {
+ struct ds s;
+
+ ds_init(&s);
+ ds_put_hex_dump(&s, actions, n_actions * sizeof *actions, 0, false);
+ VLOG_WARN("bad action at offset %#zx (%s):\n%s",
+ ofs * sizeof *actions, ofperr_get_name(error), ds_cstr(&s));
+ ds_destroy(&s);
+ }
+}
+
static enum ofperr
ofpacts_from_openflow10(const union ofp_action *in, size_t n_in,
struct ofpbuf *out)
ACTION_FOR_EACH (a, left, in, n_in) {
enum ofperr error = ofpact_from_openflow10(a, out);
if (error) {
- VLOG_WARN_RL(&rl, "bad action at offset %td (%s)",
- (a - in) * sizeof *a, ofperr_get_name(error));
+ log_bad_action(in, n_in, a - in, error);
return error;
}
}
if (left) {
- VLOG_WARN_RL(&rl, "bad action format at offset %zu",
- (n_in - left) * sizeof *a);
- return OFPERR_OFPBAC_BAD_LEN;
+ enum ofperr error = OFPERR_OFPBAC_BAD_LEN;
+ log_bad_action(in, n_in, n_in - left, error);
+ return error;
}
ofpact_pad(out);
* in 'ofpacts' by the converted ofpacts; on failure, clears 'ofpacts'.
* Returns 0 if successful, otherwise an OpenFlow error.
*
- * This function does not check that the actions are valid in a given context.
- * The caller should do so, with ofpacts_check(). */
+ * The parsed actions are valid generically, but they may not be valid in a
+ * specific context. For example, port numbers up to OFPP_MAX are valid
+ * generically, but specific datapaths may only support port numbers in a
+ * smaller range. Use ofpacts_check() to additional check whether actions are
+ * valid in a specific context. */
enum ofperr
ofpacts_pull_openflow10(struct ofpbuf *openflow, unsigned int actions_len,
struct ofpbuf *ofpacts)
* instructions, so you should call ofpacts_pull_openflow11_instructions()
* instead of this function.
*
- * This function does not check that the actions are valid in a given context.
- * The caller should do so, with ofpacts_check(). */
+ * The parsed actions are valid generically, but they may not be valid in a
+ * specific context. For example, port numbers up to OFPP_MAX are valid
+ * generically, but specific datapaths may only support port numbers in a
+ * smaller range. Use ofpacts_check() to additional check whether actions are
+ * valid in a specific context. */
enum ofperr
ofpacts_pull_openflow11_actions(struct ofpbuf *openflow,
unsigned int actions_len,