switch ((enum ovs_action_attr)type) {
case OVS_ACTION_ATTR_OUTPUT:
case OVS_ACTION_ATTR_USERSPACE:
+ case OVS_ACTION_ATTR_RECIRC:
execute.actions = action;
execute.actions_len = NLA_ALIGN(action->nla_len);
execute.packet = packet;
aux->error = aux->dpif->dpif_class->execute(aux->dpif, &execute);
break;
+ case OVS_ACTION_ATTR_HASH:
case OVS_ACTION_ATTR_PUSH_VLAN:
case OVS_ACTION_ATTR_POP_VLAN:
case OVS_ACTION_ATTR_PUSH_MPLS:
case OVS_ACTION_ATTR_SET:
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();
}
#include "ofpbuf.h"
#include "odp-util.h"
#include "packets.h"
+#include "flow.h"
#include "unaligned.h"
#include "util.h"
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. */
}
break;
+ case OVS_ACTION_ATTR_HASH: {
+ const struct ovs_action_hash *hash_act = nl_attr_get(a);
+
+ /* Calculate a hash value directly. This might not match the
+ * value computed by the datapath, but it is much less expensive,
+ * and the current use case (bonding) does not require a strict
+ * match to work properly. */
+ if (hash_act->hash_alg == OVS_HASH_ALG_L4) {
+ struct flow flow;
+ uint32_t hash;
+
+ flow_extract(packet, md, &flow);
+ hash = flow_hash_5tuple(&flow, hash_act->hash_basis);
+ md->dp_hash = hash ? hash : 1;
+ } else {
+ /* Assert on unknown hash algorithm. */
+ OVS_NOT_REACHED();
+ }
+ break;
+ }
+
case OVS_ACTION_ATTR_PUSH_VLAN: {
const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
eth_push_vlan(packet, htons(ETH_TYPE_VLAN), vlan->vlan_tci);