- uint32_t hash = multipath_hash(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
-hash_symmetric_l4(const struct flow *flow, uint16_t basis)
-{
- struct {
- ovs_be32 ip_addr;
- ovs_be16 eth_type;
- ovs_be16 vlan_tci;
- ovs_be16 tp_addr;
- uint8_t eth_addr[ETH_ADDR_LEN];
- uint8_t ip_proto;
- } fields;
-
- int i;
-
- memset(&fields, 0, sizeof fields);
- for (i = 0; i < ETH_ADDR_LEN; i++) {
- fields.eth_addr[i] = flow->dl_src[i] ^ flow->dl_dst[i];
- }
- fields.vlan_tci = flow->vlan_tci & htons(VLAN_VID_MASK);
- fields.eth_type = flow->dl_type;
- if (fields.eth_type == htons(ETH_TYPE_IP)) {
- fields.ip_addr = flow->nw_src ^ flow->nw_dst;
- fields.ip_proto = flow->nw_proto;
- if (fields.ip_proto == IP_TYPE_TCP || fields.ip_proto == IP_TYPE_UDP) {
- fields.tp_addr = flow->tp_src ^ flow->tp_dst;
- } else {
- fields.tp_addr = htons(0);
- }
- } else {
- fields.ip_addr = htonl(0);
- fields.ip_proto = 0;
- fields.tp_addr = htons(0);
- }
- return hash_bytes(&fields, sizeof fields, basis);
-}
-
-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 hash_symmetric_l4(flow, basis);
- }