\f
/* multipath_check(). */
int
-multipath_check(const struct nx_action_multipath *mp)
+multipath_check(const struct nx_action_multipath *mp, const struct flow *flow)
{
- uint32_t dst = ntohl(mp->dst);
+ uint32_t n_links = ntohs(mp->max_link) + 1;
+ size_t min_n_bits = log_2_floor(n_links) + 1;
int ofs = nxm_decode_ofs(mp->ofs_nbits);
int n_bits = nxm_decode_n_bits(mp->ofs_nbits);
+ int error;
- if (mp->fields != htons(NX_MP_FIELDS_ETH_SRC)
- && mp->fields != htons(NX_MP_FIELDS_SYMMETRIC_L4)) {
+ error = nxm_dst_check(mp->dst, ofs, n_bits, flow);
+ if (error) {
+ return error;
+ }
+
+ if (!flow_hash_fields_valid(ntohs(mp->fields))) {
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_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 if (n_bits < min_n_bits) {
+ VLOG_WARN_RL(&rl, "multipath action requires at least %zu bits for "
+ "%"PRIu32" links", min_n_bits, n_links);
} else {
return 0;
}
\f
/* multipath_execute(). */
-static uint32_t multipath_hash(const struct flow *, enum nx_mp_fields,
- uint16_t basis);
static uint16_t multipath_algorithm(uint32_t hash, enum nx_mp_algorithm,
unsigned int n_links, unsigned int arg);
multipath_execute(const struct nx_action_multipath *mp, struct flow *flow)
{
/* Calculate value to store. */
- uint32_t hash = multipath_hash(flow, ntohs(mp->fields), ntohs(mp->basis));
+ uint32_t hash = flow_hash_fields(flow, ntohs(mp->fields),
+ ntohs(mp->basis));
uint16_t link = multipath_algorithm(hash, ntohs(mp->algorithm),
ntohs(mp->max_link) + 1,
ntohl(mp->arg));
- /* Store it. */
- uint32_t *reg = &flow->regs[NXM_NX_REG_IDX(ntohl(mp->dst))];
- int ofs = nxm_decode_ofs(mp->ofs_nbits);
- int n_bits = nxm_decode_n_bits(mp->ofs_nbits);
- uint32_t mask = n_bits == 32 ? UINT32_MAX : (UINT32_C(1) << n_bits) - 1;
- *reg = (*reg & ~(mask << ofs)) | (link << ofs);
-}
-
-static uint32_t
-multipath_hash(const struct flow *flow, enum nx_mp_fields fields,
- uint16_t basis)
-{
- switch (fields) {
- case NX_MP_FIELDS_ETH_SRC:
- return hash_bytes(flow->dl_src, sizeof flow->dl_src, basis);
-
- case NX_MP_FIELDS_SYMMETRIC_L4:
- return flow_hash_symmetric_l4(flow, basis);
- }
-
- NOT_REACHED();
+ nxm_reg_load(mp->dst, mp->ofs_nbits, link, flow);
}
static uint16_t
mp->vendor = htonl(NX_VENDOR_ID);
mp->subtype = htons(NXAST_MULTIPATH);
if (!strcasecmp(fields, "eth_src")) {
- mp->fields = htons(NX_MP_FIELDS_ETH_SRC);
+ mp->fields = htons(NX_HASH_FIELDS_ETH_SRC);
} else if (!strcasecmp(fields, "symmetric_l4")) {
- mp->fields = htons(NX_MP_FIELDS_SYMMETRIC_L4);
+ mp->fields = htons(NX_HASH_FIELDS_SYMMETRIC_L4);
} else {
ovs_fatal(0, "%s: unknown fields `%s'", s_, fields);
}
mp->arg = htonl(atoi(arg));
nxm_parse_field_bits(dst, &header, &ofs, &n_bits);
- if (!NXM_IS_NX_REG(header) || NXM_NX_REG_IDX(header) >= FLOW_N_REGS) {
- ovs_fatal(0, "%s: destination field must be register", s_);
- }
if (n_bits < 16 && n_links > (1u << n_bits)) {
ovs_fatal(0, "%s: %d-bit destination field has %u possible values, "
"less than specified n_links %d",
uint16_t mp_fields = ntohs(mp->fields);
uint16_t mp_algorithm = ntohs(mp->algorithm);
- switch ((enum nx_mp_fields) mp_fields) {
- case NX_MP_FIELDS_ETH_SRC:
- fields = "eth_src";
- break;
- case NX_MP_FIELDS_SYMMETRIC_L4:
- fields = "symmetric_l4";
- break;
- default:
- fields = "<unknown>";
- }
+ fields = flow_hash_fields_to_str(mp_fields);
switch ((enum nx_mp_algorithm) mp_algorithm) {
case NX_MP_ALG_MODULO_N: