+ return jhash_bytes(&fields, sizeof fields, basis);
+}
+
+/* Masks the fields in 'wc' that are used by the flow hash 'fields'. */
+void
+flow_mask_hash_fields(const struct flow *flow, struct flow_wildcards *wc,
+ enum nx_hash_fields fields)
+{
+ switch (fields) {
+ case NX_HASH_FIELDS_ETH_SRC:
+ memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
+ break;
+
+ case NX_HASH_FIELDS_SYMMETRIC_L4:
+ memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
+ memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
+ if (flow->dl_type == htons(ETH_TYPE_IP)) {
+ memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
+ memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
+ } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
+ memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
+ memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
+ }
+ if (is_ip_any(flow)) {
+ memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
+ memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
+ memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
+ }
+ wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
+ break;
+
+ default:
+ NOT_REACHED();
+ }