/* Data path hash algorithm for computing Datapath hash.
*
- * The Algorithm type only specifies the fields in a flow
+ * The algorithm type only specifies the fields in a flow
* will be used as part of the hash. Each datapath is free
* to use its own hash algorithm. The hash value will be
* opaque to the user space daemon.
*/
-enum ovs_recirc_hash_alg {
- OVS_RECIRC_HASH_ALG_NONE,
- OVS_RECIRC_HASH_ALG_L4,
+enum ovs_hash_alg {
+ OVS_HASH_ALG_L4,
};
/*
- * struct ovs_action_recirc - %OVS_ACTION_ATTR_RECIRC action argument.
- * @recirc_id: The Recirculation label, Zero is invalid.
+ * struct ovs_action_hash - %OVS_ACTION_ATTR_HASH action argument.
* @hash_alg: Algorithm used to compute hash prior to recirculation.
- * @hash_bias: bias used for computing hash. used to compute hash prior to
- * recirculation.
+ * @hash_bias: bias used for computing hash.
*/
-struct ovs_action_recirc {
- uint32_t hash_alg; /* One of ovs_dp_hash_alg. */
+struct ovs_action_hash {
+ uint32_t hash_alg; /* One of ovs_hash_alg. */
uint32_t hash_bias;
- uint32_t recirc_id; /* Recirculation label. */
};
/**
OVS_ACTION_ATTR_SAMPLE, /* Nested OVS_SAMPLE_ATTR_*. */
OVS_ACTION_ATTR_PUSH_MPLS, /* struct ovs_action_push_mpls. */
OVS_ACTION_ATTR_POP_MPLS, /* __be16 ethertype. */
- OVS_ACTION_ATTR_RECIRC, /* struct ovs_action_recirc. */
+ OVS_ACTION_ATTR_RECIRC, /* u32 recirc_id. */
+ OVS_ACTION_ATTR_HASH, /* struct ovs_action_hash. */
__OVS_ACTION_ATTR_MAX
};
break;
}
+ case OVS_ACTION_ATTR_HASH: {
+ const struct ovs_action_hash *hash_act;
+ uint32_t hash;
+
+ hash_act = nl_attr_get(a);
+ if (hash_act->hash_alg == OVS_HASH_ALG_L4) {
+
+ hash = flow_hash_symmetric_l4(aux->key, hash_act->hash_bias);
+ if (!hash) {
+ hash = 1; /* 0 is not valid */
+ }
+
+ } else {
+ VLOG_WARN("Unknown hash algorithm specified for the hash action.");
+ hash = 2;
+ }
+
+ md->dp_hash = hash;
+ break;
+ }
+
case OVS_ACTION_ATTR_RECIRC:
if (*depth < MAX_RECIRC_DEPTH) {
struct pkt_metadata recirc_md = *md;
struct ofpbuf *recirc_packet;
- const struct ovs_action_recirc *act;
recirc_packet = may_steal ? packet : ofpbuf_clone(packet);
-
- act = nl_attr_get(a);
- recirc_md.recirc_id = act->recirc_id;
- recirc_md.dp_hash = 0;
-
- if (act->hash_alg == OVS_RECIRC_HASH_ALG_L4) {
- recirc_md.dp_hash = flow_hash_symmetric_l4(aux->key,
- act->hash_bias);
- if (!recirc_md.dp_hash) {
- recirc_md.dp_hash = 1; /* 0 is not valid */
- }
- }
+ recirc_md.recirc_id = nl_attr_get_u32(a);
(*depth)++;
dp_netdev_input(aux->dp, recirc_packet, &recirc_md);
case OVS_ACTION_ATTR_SAMPLE:
case OVS_ACTION_ATTR_UNSPEC:
case OVS_ACTION_ATTR_RECIRC:
+ case OVS_ACTION_ATTR_HASH:
case __OVS_ACTION_ATTR_MAX:
OVS_NOT_REACHED();
}
case OVS_ACTION_ATTR_OUTPUT:
case OVS_ACTION_ATTR_USERSPACE:
case OVS_ACTION_ATTR_RECIRC:
+ case OVS_ACTION_ATTR_HASH:
if (dp_execute_action) {
/* Allow 'dp_execute_action' to steal the packet data if we do
* not need it any more. */
case OVS_ACTION_ATTR_POP_VLAN: return 0;
case OVS_ACTION_ATTR_PUSH_MPLS: return sizeof(struct ovs_action_push_mpls);
case OVS_ACTION_ATTR_POP_MPLS: return sizeof(ovs_be16);
- case OVS_ACTION_ATTR_RECIRC: return sizeof(struct ovs_action_recirc);
+ case OVS_ACTION_ATTR_RECIRC: return sizeof(uint32_t);
+ case OVS_ACTION_ATTR_HASH: return sizeof(struct ovs_action_hash);
case OVS_ACTION_ATTR_SET: return -2;
case OVS_ACTION_ATTR_SAMPLE: return -2;
}
static void
-format_odp_recirc_action(struct ds *ds,
- const struct ovs_action_recirc *act)
+format_odp_recirc_action(struct ds *ds, uint32_t recirc_id)
{
- ds_put_format(ds, "recirc(");
+ ds_put_format(ds, "recirc(%"PRIu32")", recirc_id);
+}
- if (act->hash_alg == OVS_RECIRC_HASH_ALG_L4) {
- ds_put_format(ds, "hash_l4(%"PRIu32"), ", act->hash_bias);
- }
+static void
+format_odp_hash_action(struct ds *ds, const struct ovs_action_hash *hash_act)
+{
+ ds_put_format(ds, "hash(");
- ds_put_format(ds, "%"PRIu32")", act->recirc_id);
+ if (hash_act->hash_alg == OVS_HASH_ALG_L4) {
+ ds_put_format(ds, "hash_l4(%"PRIu32")", hash_act->hash_bias);
+ } else {
+ ds_put_format(ds, "Unknown hash algorithm(%"PRIu32")",
+ hash_act->hash_alg);
+ }
+ ds_put_format(ds, ")");
}
static void
format_odp_userspace_action(ds, a);
break;
case OVS_ACTION_ATTR_RECIRC:
- format_odp_recirc_action(ds, nl_attr_get(a));
+ format_odp_recirc_action(ds, nl_attr_get_u32(a));
+ break;
+ case OVS_ACTION_ATTR_HASH:
+ format_odp_hash_action(ds, nl_attr_get(a));
break;
case OVS_ACTION_ATTR_SET:
ds_put_cstr(ds, "set(");
if (ctx->xout->use_recirc) {
/* Only TCP mode uses recirculation. */
- xr->hash_alg = OVS_RECIRC_HASH_ALG_L4;
+ xr->hash_alg = OVS_HASH_ALG_L4;
bond_update_post_recirc_rules(out_xbundle->bond, false);
/* Recirculation does not require unmasking hash fields. */
&ctx->xout->wc);
if (ctx->xout->use_recirc) {
- struct ovs_action_recirc *act_recirc;
+ struct ovs_action_hash *act_hash;
struct xlate_recirc *xr = &ctx->xout->recirc;
- act_recirc = nl_msg_put_unspec_uninit(&ctx->xout->odp_actions,
- OVS_ACTION_ATTR_RECIRC, sizeof *act_recirc);
- act_recirc->recirc_id = xr->recirc_id;
- act_recirc->hash_alg = xr->hash_alg;
- act_recirc->hash_bias = xr->hash_bias;
+ /* Hash action. */
+ act_hash = nl_msg_put_unspec_uninit(&ctx->xout->odp_actions,
+ OVS_ACTION_ATTR_HASH,
+ sizeof *act_hash);
+ act_hash->hash_alg = xr->hash_alg;
+ act_hash->hash_bias = xr->hash_bias;
+
+ /* Recirc action. */
+ nl_msg_put_u32(&ctx->xout->odp_actions, OVS_ACTION_ATTR_RECIRC,
+ xr->recirc_id);
} else {
nl_msg_put_odp_port(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT,
out_port);