- uint32_t dst = ntohl(mp->dst);
- int ofs = nxm_decode_ofs(mp->ofs_nbits);
- int n_bits = nxm_decode_n_bits(mp->ofs_nbits);
-
- if (mp->fields != htons(NX_MP_FIELDS_ETH_SRC)
- && mp->fields != htons(NX_MP_FIELDS_SYMMETRIC_L4)) {
- VLOG_WARN_RL(&rl, "unsupported fields %"PRIu16, ntohs(mp->fields));
- } else if (mp->algorithm != htons(NX_MP_ALG_MODULO_N)
- && mp->algorithm != htons(NX_MP_ALG_HASH_THRESHOLD)
- && mp->algorithm != htons(NX_MP_ALG_HRW)
- && mp->algorithm != htons(NX_MP_ALG_ITER_HASH)) {
- VLOG_WARN_RL(&rl, "unsupported algorithm %"PRIu16,
- ntohs(mp->algorithm));
- } else if (!NXM_IS_NX_REG(dst) || NXM_NX_REG_IDX(dst) >= FLOW_N_REGS) {
- VLOG_WARN_RL(&rl, "unsupported destination field %#"PRIx32, dst);
- } else if (ofs + n_bits > nxm_field_bits(dst)) {
- VLOG_WARN_RL(&rl, "destination overflows output field");
- } else if (n_bits < 16 && ntohs(mp->max_link) > (1u << n_bits)) {
- VLOG_WARN_RL(&rl, "max_link overflows output field");
- } else {
- return 0;
+ uint32_t n_links = ntohs(nam->max_link) + 1;
+ size_t min_n_bits = log_2_ceil(n_links);
+
+ ofpact_init_MULTIPATH(mp);
+ mp->fields = ntohs(nam->fields);
+ mp->basis = ntohs(nam->basis);
+ mp->algorithm = ntohs(nam->algorithm);
+ mp->max_link = ntohs(nam->max_link);
+ mp->arg = ntohl(nam->arg);
+ mp->dst.field = mf_from_nxm_header(ntohl(nam->dst));
+ mp->dst.ofs = nxm_decode_ofs(nam->ofs_nbits);
+ mp->dst.n_bits = nxm_decode_n_bits(nam->ofs_nbits);
+
+ if (!flow_hash_fields_valid(mp->fields)) {
+ VLOG_WARN_RL(&rl, "unsupported fields %d", (int) mp->fields);
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
+ } else if (mp->algorithm != NX_MP_ALG_MODULO_N
+ && mp->algorithm != NX_MP_ALG_HASH_THRESHOLD
+ && mp->algorithm != NX_MP_ALG_HRW
+ && mp->algorithm != NX_MP_ALG_ITER_HASH) {
+ VLOG_WARN_RL(&rl, "unsupported algorithm %d", (int) mp->algorithm);
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
+ } else if (mp->dst.n_bits < min_n_bits) {
+ VLOG_WARN_RL(&rl, "multipath action requires at least %"PRIuSIZE" bits for "
+ "%"PRIu32" links", min_n_bits, n_links);
+ return OFPERR_OFPBAC_BAD_ARGUMENT;