18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2007-2014 Nicira, Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "flow.h"
78c2ecf20Sopenharmony_ci#include "datapath.h"
88c2ecf20Sopenharmony_ci#include "flow_netlink.h"
98c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
108c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
118c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
128c2ecf20Sopenharmony_ci#include <linux/if_ether.h>
138c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
148c2ecf20Sopenharmony_ci#include <net/llc_pdu.h>
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/jhash.h>
178c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
188c2ecf20Sopenharmony_ci#include <linux/llc.h>
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/in.h>
218c2ecf20Sopenharmony_ci#include <linux/rcupdate.h>
228c2ecf20Sopenharmony_ci#include <linux/cpumask.h>
238c2ecf20Sopenharmony_ci#include <linux/if_arp.h>
248c2ecf20Sopenharmony_ci#include <linux/ip.h>
258c2ecf20Sopenharmony_ci#include <linux/ipv6.h>
268c2ecf20Sopenharmony_ci#include <linux/sctp.h>
278c2ecf20Sopenharmony_ci#include <linux/tcp.h>
288c2ecf20Sopenharmony_ci#include <linux/udp.h>
298c2ecf20Sopenharmony_ci#include <linux/icmp.h>
308c2ecf20Sopenharmony_ci#include <linux/icmpv6.h>
318c2ecf20Sopenharmony_ci#include <linux/rculist.h>
328c2ecf20Sopenharmony_ci#include <linux/sort.h>
338c2ecf20Sopenharmony_ci#include <net/ip.h>
348c2ecf20Sopenharmony_ci#include <net/ipv6.h>
358c2ecf20Sopenharmony_ci#include <net/ndisc.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define TBL_MIN_BUCKETS		1024
388c2ecf20Sopenharmony_ci#define MASK_ARRAY_SIZE_MIN	16
398c2ecf20Sopenharmony_ci#define REHASH_INTERVAL		(10 * 60 * HZ)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define MC_DEFAULT_HASH_ENTRIES	256
428c2ecf20Sopenharmony_ci#define MC_HASH_SHIFT		8
438c2ecf20Sopenharmony_ci#define MC_HASH_SEGS		((sizeof(uint32_t) * 8) / MC_HASH_SHIFT)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic struct kmem_cache *flow_cache;
468c2ecf20Sopenharmony_cistruct kmem_cache *flow_stats_cache __read_mostly;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic u16 range_n_bytes(const struct sw_flow_key_range *range)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	return range->end - range->start;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_civoid ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
548c2ecf20Sopenharmony_ci		       bool full, const struct sw_flow_mask *mask)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	int start = full ? 0 : mask->range.start;
578c2ecf20Sopenharmony_ci	int len = full ? sizeof *dst : range_n_bytes(&mask->range);
588c2ecf20Sopenharmony_ci	const long *m = (const long *)((const u8 *)&mask->key + start);
598c2ecf20Sopenharmony_ci	const long *s = (const long *)((const u8 *)src + start);
608c2ecf20Sopenharmony_ci	long *d = (long *)((u8 *)dst + start);
618c2ecf20Sopenharmony_ci	int i;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	/* If 'full' is true then all of 'dst' is fully initialized. Otherwise,
648c2ecf20Sopenharmony_ci	 * if 'full' is false the memory outside of the 'mask->range' is left
658c2ecf20Sopenharmony_ci	 * uninitialized. This can be used as an optimization when further
668c2ecf20Sopenharmony_ci	 * operations on 'dst' only use contents within 'mask->range'.
678c2ecf20Sopenharmony_ci	 */
688c2ecf20Sopenharmony_ci	for (i = 0; i < len; i += sizeof(long))
698c2ecf20Sopenharmony_ci		*d++ = *s++ & *m++;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistruct sw_flow *ovs_flow_alloc(void)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct sw_flow *flow;
758c2ecf20Sopenharmony_ci	struct sw_flow_stats *stats;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	flow = kmem_cache_zalloc(flow_cache, GFP_KERNEL);
788c2ecf20Sopenharmony_ci	if (!flow)
798c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	flow->stats_last_writer = -1;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	/* Initialize the default stat node. */
848c2ecf20Sopenharmony_ci	stats = kmem_cache_alloc_node(flow_stats_cache,
858c2ecf20Sopenharmony_ci				      GFP_KERNEL | __GFP_ZERO,
868c2ecf20Sopenharmony_ci				      node_online(0) ? 0 : NUMA_NO_NODE);
878c2ecf20Sopenharmony_ci	if (!stats)
888c2ecf20Sopenharmony_ci		goto err;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	spin_lock_init(&stats->lock);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	RCU_INIT_POINTER(flow->stats[0], stats);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	cpumask_set_cpu(0, &flow->cpu_used_mask);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	return flow;
978c2ecf20Sopenharmony_cierr:
988c2ecf20Sopenharmony_ci	kmem_cache_free(flow_cache, flow);
998c2ecf20Sopenharmony_ci	return ERR_PTR(-ENOMEM);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ciint ovs_flow_tbl_count(const struct flow_table *table)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	return table->count;
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic void flow_free(struct sw_flow *flow)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	int cpu;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	if (ovs_identifier_is_key(&flow->id))
1128c2ecf20Sopenharmony_ci		kfree(flow->id.unmasked_key);
1138c2ecf20Sopenharmony_ci	if (flow->sf_acts)
1148c2ecf20Sopenharmony_ci		ovs_nla_free_flow_actions((struct sw_flow_actions __force *)
1158c2ecf20Sopenharmony_ci					  flow->sf_acts);
1168c2ecf20Sopenharmony_ci	/* We open code this to make sure cpu 0 is always considered */
1178c2ecf20Sopenharmony_ci	for (cpu = 0; cpu < nr_cpu_ids;
1188c2ecf20Sopenharmony_ci	     cpu = cpumask_next(cpu, &flow->cpu_used_mask)) {
1198c2ecf20Sopenharmony_ci		if (flow->stats[cpu])
1208c2ecf20Sopenharmony_ci			kmem_cache_free(flow_stats_cache,
1218c2ecf20Sopenharmony_ci					(struct sw_flow_stats __force *)flow->stats[cpu]);
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	kmem_cache_free(flow_cache, flow);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic void rcu_free_flow_callback(struct rcu_head *rcu)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	flow_free(flow);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_civoid ovs_flow_free(struct sw_flow *flow, bool deferred)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	if (!flow)
1378c2ecf20Sopenharmony_ci		return;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (deferred)
1408c2ecf20Sopenharmony_ci		call_rcu(&flow->rcu, rcu_free_flow_callback);
1418c2ecf20Sopenharmony_ci	else
1428c2ecf20Sopenharmony_ci		flow_free(flow);
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic void __table_instance_destroy(struct table_instance *ti)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	kvfree(ti->buckets);
1488c2ecf20Sopenharmony_ci	kfree(ti);
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic struct table_instance *table_instance_alloc(int new_size)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	struct table_instance *ti = kmalloc(sizeof(*ti), GFP_KERNEL);
1548c2ecf20Sopenharmony_ci	int i;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	if (!ti)
1578c2ecf20Sopenharmony_ci		return NULL;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	ti->buckets = kvmalloc_array(new_size, sizeof(struct hlist_head),
1608c2ecf20Sopenharmony_ci				     GFP_KERNEL);
1618c2ecf20Sopenharmony_ci	if (!ti->buckets) {
1628c2ecf20Sopenharmony_ci		kfree(ti);
1638c2ecf20Sopenharmony_ci		return NULL;
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	for (i = 0; i < new_size; i++)
1678c2ecf20Sopenharmony_ci		INIT_HLIST_HEAD(&ti->buckets[i]);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	ti->n_buckets = new_size;
1708c2ecf20Sopenharmony_ci	ti->node_ver = 0;
1718c2ecf20Sopenharmony_ci	get_random_bytes(&ti->hash_seed, sizeof(u32));
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	return ti;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic void __mask_array_destroy(struct mask_array *ma)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	free_percpu(ma->masks_usage_stats);
1798c2ecf20Sopenharmony_ci	kfree(ma);
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic void mask_array_rcu_cb(struct rcu_head *rcu)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	struct mask_array *ma = container_of(rcu, struct mask_array, rcu);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	__mask_array_destroy(ma);
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_cistatic void tbl_mask_array_reset_counters(struct mask_array *ma)
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci	int i, cpu;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/* As the per CPU counters are not atomic we can not go ahead and
1948c2ecf20Sopenharmony_ci	 * reset them from another CPU. To be able to still have an approximate
1958c2ecf20Sopenharmony_ci	 * zero based counter we store the value at reset, and subtract it
1968c2ecf20Sopenharmony_ci	 * later when processing.
1978c2ecf20Sopenharmony_ci	 */
1988c2ecf20Sopenharmony_ci	for (i = 0; i < ma->max; i++) {
1998c2ecf20Sopenharmony_ci		ma->masks_usage_zero_cntr[i] = 0;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		for_each_possible_cpu(cpu) {
2028c2ecf20Sopenharmony_ci			struct mask_array_stats *stats;
2038c2ecf20Sopenharmony_ci			unsigned int start;
2048c2ecf20Sopenharmony_ci			u64 counter;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci			stats = per_cpu_ptr(ma->masks_usage_stats, cpu);
2078c2ecf20Sopenharmony_ci			do {
2088c2ecf20Sopenharmony_ci				start = u64_stats_fetch_begin_irq(&stats->syncp);
2098c2ecf20Sopenharmony_ci				counter = stats->usage_cntrs[i];
2108c2ecf20Sopenharmony_ci			} while (u64_stats_fetch_retry_irq(&stats->syncp, start));
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci			ma->masks_usage_zero_cntr[i] += counter;
2138c2ecf20Sopenharmony_ci		}
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic struct mask_array *tbl_mask_array_alloc(int size)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	struct mask_array *new;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	size = max(MASK_ARRAY_SIZE_MIN, size);
2228c2ecf20Sopenharmony_ci	new = kzalloc(sizeof(struct mask_array) +
2238c2ecf20Sopenharmony_ci		      sizeof(struct sw_flow_mask *) * size +
2248c2ecf20Sopenharmony_ci		      sizeof(u64) * size, GFP_KERNEL);
2258c2ecf20Sopenharmony_ci	if (!new)
2268c2ecf20Sopenharmony_ci		return NULL;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	new->masks_usage_zero_cntr = (u64 *)((u8 *)new +
2298c2ecf20Sopenharmony_ci					     sizeof(struct mask_array) +
2308c2ecf20Sopenharmony_ci					     sizeof(struct sw_flow_mask *) *
2318c2ecf20Sopenharmony_ci					     size);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	new->masks_usage_stats = __alloc_percpu(sizeof(struct mask_array_stats) +
2348c2ecf20Sopenharmony_ci						sizeof(u64) * size,
2358c2ecf20Sopenharmony_ci						__alignof__(u64));
2368c2ecf20Sopenharmony_ci	if (!new->masks_usage_stats) {
2378c2ecf20Sopenharmony_ci		kfree(new);
2388c2ecf20Sopenharmony_ci		return NULL;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	new->count = 0;
2428c2ecf20Sopenharmony_ci	new->max = size;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	return new;
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic int tbl_mask_array_realloc(struct flow_table *tbl, int size)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	struct mask_array *old;
2508c2ecf20Sopenharmony_ci	struct mask_array *new;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	new = tbl_mask_array_alloc(size);
2538c2ecf20Sopenharmony_ci	if (!new)
2548c2ecf20Sopenharmony_ci		return -ENOMEM;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	old = ovsl_dereference(tbl->mask_array);
2578c2ecf20Sopenharmony_ci	if (old) {
2588c2ecf20Sopenharmony_ci		int i;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci		for (i = 0; i < old->max; i++) {
2618c2ecf20Sopenharmony_ci			if (ovsl_dereference(old->masks[i]))
2628c2ecf20Sopenharmony_ci				new->masks[new->count++] = old->masks[i];
2638c2ecf20Sopenharmony_ci		}
2648c2ecf20Sopenharmony_ci		call_rcu(&old->rcu, mask_array_rcu_cb);
2658c2ecf20Sopenharmony_ci	}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	rcu_assign_pointer(tbl->mask_array, new);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	return 0;
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic int tbl_mask_array_add_mask(struct flow_table *tbl,
2738c2ecf20Sopenharmony_ci				   struct sw_flow_mask *new)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct mask_array *ma = ovsl_dereference(tbl->mask_array);
2768c2ecf20Sopenharmony_ci	int err, ma_count = READ_ONCE(ma->count);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	if (ma_count >= ma->max) {
2798c2ecf20Sopenharmony_ci		err = tbl_mask_array_realloc(tbl, ma->max +
2808c2ecf20Sopenharmony_ci						  MASK_ARRAY_SIZE_MIN);
2818c2ecf20Sopenharmony_ci		if (err)
2828c2ecf20Sopenharmony_ci			return err;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci		ma = ovsl_dereference(tbl->mask_array);
2858c2ecf20Sopenharmony_ci	} else {
2868c2ecf20Sopenharmony_ci		/* On every add or delete we need to reset the counters so
2878c2ecf20Sopenharmony_ci		 * every new mask gets a fair chance of being prioritized.
2888c2ecf20Sopenharmony_ci		 */
2898c2ecf20Sopenharmony_ci		tbl_mask_array_reset_counters(ma);
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	BUG_ON(ovsl_dereference(ma->masks[ma_count]));
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	rcu_assign_pointer(ma->masks[ma_count], new);
2958c2ecf20Sopenharmony_ci	WRITE_ONCE(ma->count, ma_count + 1);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	return 0;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic void tbl_mask_array_del_mask(struct flow_table *tbl,
3018c2ecf20Sopenharmony_ci				    struct sw_flow_mask *mask)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	struct mask_array *ma = ovsl_dereference(tbl->mask_array);
3048c2ecf20Sopenharmony_ci	int i, ma_count = READ_ONCE(ma->count);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/* Remove the deleted mask pointers from the array */
3078c2ecf20Sopenharmony_ci	for (i = 0; i < ma_count; i++) {
3088c2ecf20Sopenharmony_ci		if (mask == ovsl_dereference(ma->masks[i]))
3098c2ecf20Sopenharmony_ci			goto found;
3108c2ecf20Sopenharmony_ci	}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	BUG();
3138c2ecf20Sopenharmony_ci	return;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cifound:
3168c2ecf20Sopenharmony_ci	WRITE_ONCE(ma->count, ma_count - 1);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	rcu_assign_pointer(ma->masks[i], ma->masks[ma_count - 1]);
3198c2ecf20Sopenharmony_ci	RCU_INIT_POINTER(ma->masks[ma_count - 1], NULL);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	kfree_rcu(mask, rcu);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	/* Shrink the mask array if necessary. */
3248c2ecf20Sopenharmony_ci	if (ma->max >= (MASK_ARRAY_SIZE_MIN * 2) &&
3258c2ecf20Sopenharmony_ci	    ma_count <= (ma->max / 3))
3268c2ecf20Sopenharmony_ci		tbl_mask_array_realloc(tbl, ma->max / 2);
3278c2ecf20Sopenharmony_ci	else
3288c2ecf20Sopenharmony_ci		tbl_mask_array_reset_counters(ma);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci/* Remove 'mask' from the mask list, if it is not needed any more. */
3338c2ecf20Sopenharmony_cistatic void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	if (mask) {
3368c2ecf20Sopenharmony_ci		/* ovs-lock is required to protect mask-refcount and
3378c2ecf20Sopenharmony_ci		 * mask list.
3388c2ecf20Sopenharmony_ci		 */
3398c2ecf20Sopenharmony_ci		ASSERT_OVSL();
3408c2ecf20Sopenharmony_ci		BUG_ON(!mask->ref_count);
3418c2ecf20Sopenharmony_ci		mask->ref_count--;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		if (!mask->ref_count)
3448c2ecf20Sopenharmony_ci			tbl_mask_array_del_mask(tbl, mask);
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_cistatic void __mask_cache_destroy(struct mask_cache *mc)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	free_percpu(mc->mask_cache);
3518c2ecf20Sopenharmony_ci	kfree(mc);
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic void mask_cache_rcu_cb(struct rcu_head *rcu)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	struct mask_cache *mc = container_of(rcu, struct mask_cache, rcu);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	__mask_cache_destroy(mc);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic struct mask_cache *tbl_mask_cache_alloc(u32 size)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	struct mask_cache_entry __percpu *cache = NULL;
3648c2ecf20Sopenharmony_ci	struct mask_cache *new;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/* Only allow size to be 0, or a power of 2, and does not exceed
3678c2ecf20Sopenharmony_ci	 * percpu allocation size.
3688c2ecf20Sopenharmony_ci	 */
3698c2ecf20Sopenharmony_ci	if ((!is_power_of_2(size) && size != 0) ||
3708c2ecf20Sopenharmony_ci	    (size * sizeof(struct mask_cache_entry)) > PCPU_MIN_UNIT_SIZE)
3718c2ecf20Sopenharmony_ci		return NULL;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	new = kzalloc(sizeof(*new), GFP_KERNEL);
3748c2ecf20Sopenharmony_ci	if (!new)
3758c2ecf20Sopenharmony_ci		return NULL;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	new->cache_size = size;
3788c2ecf20Sopenharmony_ci	if (new->cache_size > 0) {
3798c2ecf20Sopenharmony_ci		cache = __alloc_percpu(array_size(sizeof(struct mask_cache_entry),
3808c2ecf20Sopenharmony_ci						  new->cache_size),
3818c2ecf20Sopenharmony_ci				       __alignof__(struct mask_cache_entry));
3828c2ecf20Sopenharmony_ci		if (!cache) {
3838c2ecf20Sopenharmony_ci			kfree(new);
3848c2ecf20Sopenharmony_ci			return NULL;
3858c2ecf20Sopenharmony_ci		}
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	new->mask_cache = cache;
3898c2ecf20Sopenharmony_ci	return new;
3908c2ecf20Sopenharmony_ci}
3918c2ecf20Sopenharmony_ciint ovs_flow_tbl_masks_cache_resize(struct flow_table *table, u32 size)
3928c2ecf20Sopenharmony_ci{
3938c2ecf20Sopenharmony_ci	struct mask_cache *mc = rcu_dereference_ovsl(table->mask_cache);
3948c2ecf20Sopenharmony_ci	struct mask_cache *new;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	if (size == mc->cache_size)
3978c2ecf20Sopenharmony_ci		return 0;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	if ((!is_power_of_2(size) && size != 0) ||
4008c2ecf20Sopenharmony_ci	    (size * sizeof(struct mask_cache_entry)) > PCPU_MIN_UNIT_SIZE)
4018c2ecf20Sopenharmony_ci		return -EINVAL;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	new = tbl_mask_cache_alloc(size);
4048c2ecf20Sopenharmony_ci	if (!new)
4058c2ecf20Sopenharmony_ci		return -ENOMEM;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	rcu_assign_pointer(table->mask_cache, new);
4088c2ecf20Sopenharmony_ci	call_rcu(&mc->rcu, mask_cache_rcu_cb);
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	return 0;
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ciint ovs_flow_tbl_init(struct flow_table *table)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	struct table_instance *ti, *ufid_ti;
4168c2ecf20Sopenharmony_ci	struct mask_cache *mc;
4178c2ecf20Sopenharmony_ci	struct mask_array *ma;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	mc = tbl_mask_cache_alloc(MC_DEFAULT_HASH_ENTRIES);
4208c2ecf20Sopenharmony_ci	if (!mc)
4218c2ecf20Sopenharmony_ci		return -ENOMEM;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	ma = tbl_mask_array_alloc(MASK_ARRAY_SIZE_MIN);
4248c2ecf20Sopenharmony_ci	if (!ma)
4258c2ecf20Sopenharmony_ci		goto free_mask_cache;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	ti = table_instance_alloc(TBL_MIN_BUCKETS);
4288c2ecf20Sopenharmony_ci	if (!ti)
4298c2ecf20Sopenharmony_ci		goto free_mask_array;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	ufid_ti = table_instance_alloc(TBL_MIN_BUCKETS);
4328c2ecf20Sopenharmony_ci	if (!ufid_ti)
4338c2ecf20Sopenharmony_ci		goto free_ti;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	rcu_assign_pointer(table->ti, ti);
4368c2ecf20Sopenharmony_ci	rcu_assign_pointer(table->ufid_ti, ufid_ti);
4378c2ecf20Sopenharmony_ci	rcu_assign_pointer(table->mask_array, ma);
4388c2ecf20Sopenharmony_ci	rcu_assign_pointer(table->mask_cache, mc);
4398c2ecf20Sopenharmony_ci	table->last_rehash = jiffies;
4408c2ecf20Sopenharmony_ci	table->count = 0;
4418c2ecf20Sopenharmony_ci	table->ufid_count = 0;
4428c2ecf20Sopenharmony_ci	return 0;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cifree_ti:
4458c2ecf20Sopenharmony_ci	__table_instance_destroy(ti);
4468c2ecf20Sopenharmony_cifree_mask_array:
4478c2ecf20Sopenharmony_ci	__mask_array_destroy(ma);
4488c2ecf20Sopenharmony_cifree_mask_cache:
4498c2ecf20Sopenharmony_ci	__mask_cache_destroy(mc);
4508c2ecf20Sopenharmony_ci	return -ENOMEM;
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_cistatic void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	struct table_instance *ti;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	ti = container_of(rcu, struct table_instance, rcu);
4588c2ecf20Sopenharmony_ci	__table_instance_destroy(ti);
4598c2ecf20Sopenharmony_ci}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic void table_instance_flow_free(struct flow_table *table,
4628c2ecf20Sopenharmony_ci				     struct table_instance *ti,
4638c2ecf20Sopenharmony_ci				     struct table_instance *ufid_ti,
4648c2ecf20Sopenharmony_ci				     struct sw_flow *flow)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	hlist_del_rcu(&flow->flow_table.node[ti->node_ver]);
4678c2ecf20Sopenharmony_ci	table->count--;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	if (ovs_identifier_is_ufid(&flow->id)) {
4708c2ecf20Sopenharmony_ci		hlist_del_rcu(&flow->ufid_table.node[ufid_ti->node_ver]);
4718c2ecf20Sopenharmony_ci		table->ufid_count--;
4728c2ecf20Sopenharmony_ci	}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	flow_mask_remove(table, flow->mask);
4758c2ecf20Sopenharmony_ci}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci/* Must be called with OVS mutex held. */
4788c2ecf20Sopenharmony_civoid table_instance_flow_flush(struct flow_table *table,
4798c2ecf20Sopenharmony_ci			       struct table_instance *ti,
4808c2ecf20Sopenharmony_ci			       struct table_instance *ufid_ti)
4818c2ecf20Sopenharmony_ci{
4828c2ecf20Sopenharmony_ci	int i;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	for (i = 0; i < ti->n_buckets; i++) {
4858c2ecf20Sopenharmony_ci		struct hlist_head *head = &ti->buckets[i];
4868c2ecf20Sopenharmony_ci		struct hlist_node *n;
4878c2ecf20Sopenharmony_ci		struct sw_flow *flow;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci		hlist_for_each_entry_safe(flow, n, head,
4908c2ecf20Sopenharmony_ci					  flow_table.node[ti->node_ver]) {
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci			table_instance_flow_free(table, ti, ufid_ti,
4938c2ecf20Sopenharmony_ci						 flow);
4948c2ecf20Sopenharmony_ci			ovs_flow_free(flow, true);
4958c2ecf20Sopenharmony_ci		}
4968c2ecf20Sopenharmony_ci	}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	if (WARN_ON(table->count != 0 ||
4998c2ecf20Sopenharmony_ci		    table->ufid_count != 0)) {
5008c2ecf20Sopenharmony_ci		table->count = 0;
5018c2ecf20Sopenharmony_ci		table->ufid_count = 0;
5028c2ecf20Sopenharmony_ci	}
5038c2ecf20Sopenharmony_ci}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_cistatic void table_instance_destroy(struct table_instance *ti,
5068c2ecf20Sopenharmony_ci				   struct table_instance *ufid_ti)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
5098c2ecf20Sopenharmony_ci	call_rcu(&ufid_ti->rcu, flow_tbl_destroy_rcu_cb);
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci/* No need for locking this function is called from RCU callback or
5138c2ecf20Sopenharmony_ci * error path.
5148c2ecf20Sopenharmony_ci */
5158c2ecf20Sopenharmony_civoid ovs_flow_tbl_destroy(struct flow_table *table)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	struct table_instance *ti = rcu_dereference_raw(table->ti);
5188c2ecf20Sopenharmony_ci	struct table_instance *ufid_ti = rcu_dereference_raw(table->ufid_ti);
5198c2ecf20Sopenharmony_ci	struct mask_cache *mc = rcu_dereference_raw(table->mask_cache);
5208c2ecf20Sopenharmony_ci	struct mask_array *ma = rcu_dereference_raw(table->mask_array);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	call_rcu(&mc->rcu, mask_cache_rcu_cb);
5238c2ecf20Sopenharmony_ci	call_rcu(&ma->rcu, mask_array_rcu_cb);
5248c2ecf20Sopenharmony_ci	table_instance_destroy(ti, ufid_ti);
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_cistruct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
5288c2ecf20Sopenharmony_ci				       u32 *bucket, u32 *last)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	struct sw_flow *flow;
5318c2ecf20Sopenharmony_ci	struct hlist_head *head;
5328c2ecf20Sopenharmony_ci	int ver;
5338c2ecf20Sopenharmony_ci	int i;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	ver = ti->node_ver;
5368c2ecf20Sopenharmony_ci	while (*bucket < ti->n_buckets) {
5378c2ecf20Sopenharmony_ci		i = 0;
5388c2ecf20Sopenharmony_ci		head = &ti->buckets[*bucket];
5398c2ecf20Sopenharmony_ci		hlist_for_each_entry_rcu(flow, head, flow_table.node[ver]) {
5408c2ecf20Sopenharmony_ci			if (i < *last) {
5418c2ecf20Sopenharmony_ci				i++;
5428c2ecf20Sopenharmony_ci				continue;
5438c2ecf20Sopenharmony_ci			}
5448c2ecf20Sopenharmony_ci			*last = i + 1;
5458c2ecf20Sopenharmony_ci			return flow;
5468c2ecf20Sopenharmony_ci		}
5478c2ecf20Sopenharmony_ci		(*bucket)++;
5488c2ecf20Sopenharmony_ci		*last = 0;
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	return NULL;
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_cistatic struct hlist_head *find_bucket(struct table_instance *ti, u32 hash)
5558c2ecf20Sopenharmony_ci{
5568c2ecf20Sopenharmony_ci	hash = jhash_1word(hash, ti->hash_seed);
5578c2ecf20Sopenharmony_ci	return &ti->buckets[hash & (ti->n_buckets - 1)];
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic void table_instance_insert(struct table_instance *ti,
5618c2ecf20Sopenharmony_ci				  struct sw_flow *flow)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct hlist_head *head;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	head = find_bucket(ti, flow->flow_table.hash);
5668c2ecf20Sopenharmony_ci	hlist_add_head_rcu(&flow->flow_table.node[ti->node_ver], head);
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_cistatic void ufid_table_instance_insert(struct table_instance *ti,
5708c2ecf20Sopenharmony_ci				       struct sw_flow *flow)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	struct hlist_head *head;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	head = find_bucket(ti, flow->ufid_table.hash);
5758c2ecf20Sopenharmony_ci	hlist_add_head_rcu(&flow->ufid_table.node[ti->node_ver], head);
5768c2ecf20Sopenharmony_ci}
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_cistatic void flow_table_copy_flows(struct table_instance *old,
5798c2ecf20Sopenharmony_ci				  struct table_instance *new, bool ufid)
5808c2ecf20Sopenharmony_ci{
5818c2ecf20Sopenharmony_ci	int old_ver;
5828c2ecf20Sopenharmony_ci	int i;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	old_ver = old->node_ver;
5858c2ecf20Sopenharmony_ci	new->node_ver = !old_ver;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	/* Insert in new table. */
5888c2ecf20Sopenharmony_ci	for (i = 0; i < old->n_buckets; i++) {
5898c2ecf20Sopenharmony_ci		struct sw_flow *flow;
5908c2ecf20Sopenharmony_ci		struct hlist_head *head = &old->buckets[i];
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci		if (ufid)
5938c2ecf20Sopenharmony_ci			hlist_for_each_entry_rcu(flow, head,
5948c2ecf20Sopenharmony_ci						 ufid_table.node[old_ver],
5958c2ecf20Sopenharmony_ci						 lockdep_ovsl_is_held())
5968c2ecf20Sopenharmony_ci				ufid_table_instance_insert(new, flow);
5978c2ecf20Sopenharmony_ci		else
5988c2ecf20Sopenharmony_ci			hlist_for_each_entry_rcu(flow, head,
5998c2ecf20Sopenharmony_ci						 flow_table.node[old_ver],
6008c2ecf20Sopenharmony_ci						 lockdep_ovsl_is_held())
6018c2ecf20Sopenharmony_ci				table_instance_insert(new, flow);
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci}
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_cistatic struct table_instance *table_instance_rehash(struct table_instance *ti,
6068c2ecf20Sopenharmony_ci						    int n_buckets, bool ufid)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	struct table_instance *new_ti;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	new_ti = table_instance_alloc(n_buckets);
6118c2ecf20Sopenharmony_ci	if (!new_ti)
6128c2ecf20Sopenharmony_ci		return NULL;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	flow_table_copy_flows(ti, new_ti, ufid);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	return new_ti;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ciint ovs_flow_tbl_flush(struct flow_table *flow_table)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	struct table_instance *old_ti, *new_ti;
6228c2ecf20Sopenharmony_ci	struct table_instance *old_ufid_ti, *new_ufid_ti;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	new_ti = table_instance_alloc(TBL_MIN_BUCKETS);
6258c2ecf20Sopenharmony_ci	if (!new_ti)
6268c2ecf20Sopenharmony_ci		return -ENOMEM;
6278c2ecf20Sopenharmony_ci	new_ufid_ti = table_instance_alloc(TBL_MIN_BUCKETS);
6288c2ecf20Sopenharmony_ci	if (!new_ufid_ti)
6298c2ecf20Sopenharmony_ci		goto err_free_ti;
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	old_ti = ovsl_dereference(flow_table->ti);
6328c2ecf20Sopenharmony_ci	old_ufid_ti = ovsl_dereference(flow_table->ufid_ti);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	rcu_assign_pointer(flow_table->ti, new_ti);
6358c2ecf20Sopenharmony_ci	rcu_assign_pointer(flow_table->ufid_ti, new_ufid_ti);
6368c2ecf20Sopenharmony_ci	flow_table->last_rehash = jiffies;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	table_instance_flow_flush(flow_table, old_ti, old_ufid_ti);
6398c2ecf20Sopenharmony_ci	table_instance_destroy(old_ti, old_ufid_ti);
6408c2ecf20Sopenharmony_ci	return 0;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_cierr_free_ti:
6438c2ecf20Sopenharmony_ci	__table_instance_destroy(new_ti);
6448c2ecf20Sopenharmony_ci	return -ENOMEM;
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_cistatic u32 flow_hash(const struct sw_flow_key *key,
6488c2ecf20Sopenharmony_ci		     const struct sw_flow_key_range *range)
6498c2ecf20Sopenharmony_ci{
6508c2ecf20Sopenharmony_ci	const u32 *hash_key = (const u32 *)((const u8 *)key + range->start);
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	/* Make sure number of hash bytes are multiple of u32. */
6538c2ecf20Sopenharmony_ci	int hash_u32s = range_n_bytes(range) >> 2;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	return jhash2(hash_key, hash_u32s, 0);
6568c2ecf20Sopenharmony_ci}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_cistatic int flow_key_start(const struct sw_flow_key *key)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	if (key->tun_proto)
6618c2ecf20Sopenharmony_ci		return 0;
6628c2ecf20Sopenharmony_ci	else
6638c2ecf20Sopenharmony_ci		return rounddown(offsetof(struct sw_flow_key, phy),
6648c2ecf20Sopenharmony_ci				 sizeof(long));
6658c2ecf20Sopenharmony_ci}
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_cistatic bool cmp_key(const struct sw_flow_key *key1,
6688c2ecf20Sopenharmony_ci		    const struct sw_flow_key *key2,
6698c2ecf20Sopenharmony_ci		    int key_start, int key_end)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	const long *cp1 = (const long *)((const u8 *)key1 + key_start);
6728c2ecf20Sopenharmony_ci	const long *cp2 = (const long *)((const u8 *)key2 + key_start);
6738c2ecf20Sopenharmony_ci	long diffs = 0;
6748c2ecf20Sopenharmony_ci	int i;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	for (i = key_start; i < key_end; i += sizeof(long))
6778c2ecf20Sopenharmony_ci		diffs |= *cp1++ ^ *cp2++;
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	return diffs == 0;
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_cistatic bool flow_cmp_masked_key(const struct sw_flow *flow,
6838c2ecf20Sopenharmony_ci				const struct sw_flow_key *key,
6848c2ecf20Sopenharmony_ci				const struct sw_flow_key_range *range)
6858c2ecf20Sopenharmony_ci{
6868c2ecf20Sopenharmony_ci	return cmp_key(&flow->key, key, range->start, range->end);
6878c2ecf20Sopenharmony_ci}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_cistatic bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
6908c2ecf20Sopenharmony_ci				      const struct sw_flow_match *match)
6918c2ecf20Sopenharmony_ci{
6928c2ecf20Sopenharmony_ci	struct sw_flow_key *key = match->key;
6938c2ecf20Sopenharmony_ci	int key_start = flow_key_start(key);
6948c2ecf20Sopenharmony_ci	int key_end = match->range.end;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	BUG_ON(ovs_identifier_is_ufid(&flow->id));
6978c2ecf20Sopenharmony_ci	return cmp_key(flow->id.unmasked_key, key, key_start, key_end);
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_cistatic struct sw_flow *masked_flow_lookup(struct table_instance *ti,
7018c2ecf20Sopenharmony_ci					  const struct sw_flow_key *unmasked,
7028c2ecf20Sopenharmony_ci					  const struct sw_flow_mask *mask,
7038c2ecf20Sopenharmony_ci					  u32 *n_mask_hit)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	struct sw_flow *flow;
7068c2ecf20Sopenharmony_ci	struct hlist_head *head;
7078c2ecf20Sopenharmony_ci	u32 hash;
7088c2ecf20Sopenharmony_ci	struct sw_flow_key masked_key;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	ovs_flow_mask_key(&masked_key, unmasked, false, mask);
7118c2ecf20Sopenharmony_ci	hash = flow_hash(&masked_key, &mask->range);
7128c2ecf20Sopenharmony_ci	head = find_bucket(ti, hash);
7138c2ecf20Sopenharmony_ci	(*n_mask_hit)++;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver],
7168c2ecf20Sopenharmony_ci				 lockdep_ovsl_is_held()) {
7178c2ecf20Sopenharmony_ci		if (flow->mask == mask && flow->flow_table.hash == hash &&
7188c2ecf20Sopenharmony_ci		    flow_cmp_masked_key(flow, &masked_key, &mask->range))
7198c2ecf20Sopenharmony_ci			return flow;
7208c2ecf20Sopenharmony_ci	}
7218c2ecf20Sopenharmony_ci	return NULL;
7228c2ecf20Sopenharmony_ci}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci/* Flow lookup does full lookup on flow table. It starts with
7258c2ecf20Sopenharmony_ci * mask from index passed in *index.
7268c2ecf20Sopenharmony_ci * This function MUST be called with BH disabled due to the use
7278c2ecf20Sopenharmony_ci * of CPU specific variables.
7288c2ecf20Sopenharmony_ci */
7298c2ecf20Sopenharmony_cistatic struct sw_flow *flow_lookup(struct flow_table *tbl,
7308c2ecf20Sopenharmony_ci				   struct table_instance *ti,
7318c2ecf20Sopenharmony_ci				   struct mask_array *ma,
7328c2ecf20Sopenharmony_ci				   const struct sw_flow_key *key,
7338c2ecf20Sopenharmony_ci				   u32 *n_mask_hit,
7348c2ecf20Sopenharmony_ci				   u32 *n_cache_hit,
7358c2ecf20Sopenharmony_ci				   u32 *index)
7368c2ecf20Sopenharmony_ci{
7378c2ecf20Sopenharmony_ci	struct mask_array_stats *stats = this_cpu_ptr(ma->masks_usage_stats);
7388c2ecf20Sopenharmony_ci	struct sw_flow *flow;
7398c2ecf20Sopenharmony_ci	struct sw_flow_mask *mask;
7408c2ecf20Sopenharmony_ci	int i;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	if (likely(*index < ma->max)) {
7438c2ecf20Sopenharmony_ci		mask = rcu_dereference_ovsl(ma->masks[*index]);
7448c2ecf20Sopenharmony_ci		if (mask) {
7458c2ecf20Sopenharmony_ci			flow = masked_flow_lookup(ti, key, mask, n_mask_hit);
7468c2ecf20Sopenharmony_ci			if (flow) {
7478c2ecf20Sopenharmony_ci				u64_stats_update_begin(&stats->syncp);
7488c2ecf20Sopenharmony_ci				stats->usage_cntrs[*index]++;
7498c2ecf20Sopenharmony_ci				u64_stats_update_end(&stats->syncp);
7508c2ecf20Sopenharmony_ci				(*n_cache_hit)++;
7518c2ecf20Sopenharmony_ci				return flow;
7528c2ecf20Sopenharmony_ci			}
7538c2ecf20Sopenharmony_ci		}
7548c2ecf20Sopenharmony_ci	}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	for (i = 0; i < ma->max; i++)  {
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci		if (i == *index)
7598c2ecf20Sopenharmony_ci			continue;
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci		mask = rcu_dereference_ovsl(ma->masks[i]);
7628c2ecf20Sopenharmony_ci		if (unlikely(!mask))
7638c2ecf20Sopenharmony_ci			break;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci		flow = masked_flow_lookup(ti, key, mask, n_mask_hit);
7668c2ecf20Sopenharmony_ci		if (flow) { /* Found */
7678c2ecf20Sopenharmony_ci			*index = i;
7688c2ecf20Sopenharmony_ci			u64_stats_update_begin(&stats->syncp);
7698c2ecf20Sopenharmony_ci			stats->usage_cntrs[*index]++;
7708c2ecf20Sopenharmony_ci			u64_stats_update_end(&stats->syncp);
7718c2ecf20Sopenharmony_ci			return flow;
7728c2ecf20Sopenharmony_ci		}
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	return NULL;
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci/*
7798c2ecf20Sopenharmony_ci * mask_cache maps flow to probable mask. This cache is not tightly
7808c2ecf20Sopenharmony_ci * coupled cache, It means updates to  mask list can result in inconsistent
7818c2ecf20Sopenharmony_ci * cache entry in mask cache.
7828c2ecf20Sopenharmony_ci * This is per cpu cache and is divided in MC_HASH_SEGS segments.
7838c2ecf20Sopenharmony_ci * In case of a hash collision the entry is hashed in next segment.
7848c2ecf20Sopenharmony_ci * */
7858c2ecf20Sopenharmony_cistruct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl,
7868c2ecf20Sopenharmony_ci					  const struct sw_flow_key *key,
7878c2ecf20Sopenharmony_ci					  u32 skb_hash,
7888c2ecf20Sopenharmony_ci					  u32 *n_mask_hit,
7898c2ecf20Sopenharmony_ci					  u32 *n_cache_hit)
7908c2ecf20Sopenharmony_ci{
7918c2ecf20Sopenharmony_ci	struct mask_cache *mc = rcu_dereference(tbl->mask_cache);
7928c2ecf20Sopenharmony_ci	struct mask_array *ma = rcu_dereference(tbl->mask_array);
7938c2ecf20Sopenharmony_ci	struct table_instance *ti = rcu_dereference(tbl->ti);
7948c2ecf20Sopenharmony_ci	struct mask_cache_entry *entries, *ce;
7958c2ecf20Sopenharmony_ci	struct sw_flow *flow;
7968c2ecf20Sopenharmony_ci	u32 hash;
7978c2ecf20Sopenharmony_ci	int seg;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	*n_mask_hit = 0;
8008c2ecf20Sopenharmony_ci	*n_cache_hit = 0;
8018c2ecf20Sopenharmony_ci	if (unlikely(!skb_hash || mc->cache_size == 0)) {
8028c2ecf20Sopenharmony_ci		u32 mask_index = 0;
8038c2ecf20Sopenharmony_ci		u32 cache = 0;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci		return flow_lookup(tbl, ti, ma, key, n_mask_hit, &cache,
8068c2ecf20Sopenharmony_ci				   &mask_index);
8078c2ecf20Sopenharmony_ci	}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	/* Pre and post recirulation flows usually have the same skb_hash
8108c2ecf20Sopenharmony_ci	 * value. To avoid hash collisions, rehash the 'skb_hash' with
8118c2ecf20Sopenharmony_ci	 * 'recirc_id'.  */
8128c2ecf20Sopenharmony_ci	if (key->recirc_id)
8138c2ecf20Sopenharmony_ci		skb_hash = jhash_1word(skb_hash, key->recirc_id);
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	ce = NULL;
8168c2ecf20Sopenharmony_ci	hash = skb_hash;
8178c2ecf20Sopenharmony_ci	entries = this_cpu_ptr(mc->mask_cache);
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	/* Find the cache entry 'ce' to operate on. */
8208c2ecf20Sopenharmony_ci	for (seg = 0; seg < MC_HASH_SEGS; seg++) {
8218c2ecf20Sopenharmony_ci		int index = hash & (mc->cache_size - 1);
8228c2ecf20Sopenharmony_ci		struct mask_cache_entry *e;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci		e = &entries[index];
8258c2ecf20Sopenharmony_ci		if (e->skb_hash == skb_hash) {
8268c2ecf20Sopenharmony_ci			flow = flow_lookup(tbl, ti, ma, key, n_mask_hit,
8278c2ecf20Sopenharmony_ci					   n_cache_hit, &e->mask_index);
8288c2ecf20Sopenharmony_ci			if (!flow)
8298c2ecf20Sopenharmony_ci				e->skb_hash = 0;
8308c2ecf20Sopenharmony_ci			return flow;
8318c2ecf20Sopenharmony_ci		}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci		if (!ce || e->skb_hash < ce->skb_hash)
8348c2ecf20Sopenharmony_ci			ce = e;  /* A better replacement cache candidate. */
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci		hash >>= MC_HASH_SHIFT;
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	/* Cache miss, do full lookup. */
8408c2ecf20Sopenharmony_ci	flow = flow_lookup(tbl, ti, ma, key, n_mask_hit, n_cache_hit,
8418c2ecf20Sopenharmony_ci			   &ce->mask_index);
8428c2ecf20Sopenharmony_ci	if (flow)
8438c2ecf20Sopenharmony_ci		ce->skb_hash = skb_hash;
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	*n_cache_hit = 0;
8468c2ecf20Sopenharmony_ci	return flow;
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistruct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
8508c2ecf20Sopenharmony_ci				    const struct sw_flow_key *key)
8518c2ecf20Sopenharmony_ci{
8528c2ecf20Sopenharmony_ci	struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
8538c2ecf20Sopenharmony_ci	struct mask_array *ma = rcu_dereference_ovsl(tbl->mask_array);
8548c2ecf20Sopenharmony_ci	u32 __always_unused n_mask_hit;
8558c2ecf20Sopenharmony_ci	u32 __always_unused n_cache_hit;
8568c2ecf20Sopenharmony_ci	struct sw_flow *flow;
8578c2ecf20Sopenharmony_ci	u32 index = 0;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	/* This function gets called trough the netlink interface and therefore
8608c2ecf20Sopenharmony_ci	 * is preemptible. However, flow_lookup() function needs to be called
8618c2ecf20Sopenharmony_ci	 * with BH disabled due to CPU specific variables.
8628c2ecf20Sopenharmony_ci	 */
8638c2ecf20Sopenharmony_ci	local_bh_disable();
8648c2ecf20Sopenharmony_ci	flow = flow_lookup(tbl, ti, ma, key, &n_mask_hit, &n_cache_hit, &index);
8658c2ecf20Sopenharmony_ci	local_bh_enable();
8668c2ecf20Sopenharmony_ci	return flow;
8678c2ecf20Sopenharmony_ci}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_cistruct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
8708c2ecf20Sopenharmony_ci					  const struct sw_flow_match *match)
8718c2ecf20Sopenharmony_ci{
8728c2ecf20Sopenharmony_ci	struct mask_array *ma = ovsl_dereference(tbl->mask_array);
8738c2ecf20Sopenharmony_ci	int i;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	/* Always called under ovs-mutex. */
8768c2ecf20Sopenharmony_ci	for (i = 0; i < ma->max; i++) {
8778c2ecf20Sopenharmony_ci		struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
8788c2ecf20Sopenharmony_ci		u32 __always_unused n_mask_hit;
8798c2ecf20Sopenharmony_ci		struct sw_flow_mask *mask;
8808c2ecf20Sopenharmony_ci		struct sw_flow *flow;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci		mask = ovsl_dereference(ma->masks[i]);
8838c2ecf20Sopenharmony_ci		if (!mask)
8848c2ecf20Sopenharmony_ci			continue;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci		flow = masked_flow_lookup(ti, match->key, mask, &n_mask_hit);
8878c2ecf20Sopenharmony_ci		if (flow && ovs_identifier_is_key(&flow->id) &&
8888c2ecf20Sopenharmony_ci		    ovs_flow_cmp_unmasked_key(flow, match)) {
8898c2ecf20Sopenharmony_ci			return flow;
8908c2ecf20Sopenharmony_ci		}
8918c2ecf20Sopenharmony_ci	}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	return NULL;
8948c2ecf20Sopenharmony_ci}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_cistatic u32 ufid_hash(const struct sw_flow_id *sfid)
8978c2ecf20Sopenharmony_ci{
8988c2ecf20Sopenharmony_ci	return jhash(sfid->ufid, sfid->ufid_len, 0);
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_cistatic bool ovs_flow_cmp_ufid(const struct sw_flow *flow,
9028c2ecf20Sopenharmony_ci			      const struct sw_flow_id *sfid)
9038c2ecf20Sopenharmony_ci{
9048c2ecf20Sopenharmony_ci	if (flow->id.ufid_len != sfid->ufid_len)
9058c2ecf20Sopenharmony_ci		return false;
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	return !memcmp(flow->id.ufid, sfid->ufid, sfid->ufid_len);
9088c2ecf20Sopenharmony_ci}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_cibool ovs_flow_cmp(const struct sw_flow *flow,
9118c2ecf20Sopenharmony_ci		  const struct sw_flow_match *match)
9128c2ecf20Sopenharmony_ci{
9138c2ecf20Sopenharmony_ci	if (ovs_identifier_is_ufid(&flow->id))
9148c2ecf20Sopenharmony_ci		return flow_cmp_masked_key(flow, match->key, &match->range);
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	return ovs_flow_cmp_unmasked_key(flow, match);
9178c2ecf20Sopenharmony_ci}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_cistruct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *tbl,
9208c2ecf20Sopenharmony_ci					 const struct sw_flow_id *ufid)
9218c2ecf20Sopenharmony_ci{
9228c2ecf20Sopenharmony_ci	struct table_instance *ti = rcu_dereference_ovsl(tbl->ufid_ti);
9238c2ecf20Sopenharmony_ci	struct sw_flow *flow;
9248c2ecf20Sopenharmony_ci	struct hlist_head *head;
9258c2ecf20Sopenharmony_ci	u32 hash;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	hash = ufid_hash(ufid);
9288c2ecf20Sopenharmony_ci	head = find_bucket(ti, hash);
9298c2ecf20Sopenharmony_ci	hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver],
9308c2ecf20Sopenharmony_ci				 lockdep_ovsl_is_held()) {
9318c2ecf20Sopenharmony_ci		if (flow->ufid_table.hash == hash &&
9328c2ecf20Sopenharmony_ci		    ovs_flow_cmp_ufid(flow, ufid))
9338c2ecf20Sopenharmony_ci			return flow;
9348c2ecf20Sopenharmony_ci	}
9358c2ecf20Sopenharmony_ci	return NULL;
9368c2ecf20Sopenharmony_ci}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ciint ovs_flow_tbl_num_masks(const struct flow_table *table)
9398c2ecf20Sopenharmony_ci{
9408c2ecf20Sopenharmony_ci	struct mask_array *ma = rcu_dereference_ovsl(table->mask_array);
9418c2ecf20Sopenharmony_ci	return READ_ONCE(ma->count);
9428c2ecf20Sopenharmony_ci}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ciu32 ovs_flow_tbl_masks_cache_size(const struct flow_table *table)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	struct mask_cache *mc = rcu_dereference_ovsl(table->mask_cache);
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	return READ_ONCE(mc->cache_size);
9498c2ecf20Sopenharmony_ci}
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_cistatic struct table_instance *table_instance_expand(struct table_instance *ti,
9528c2ecf20Sopenharmony_ci						    bool ufid)
9538c2ecf20Sopenharmony_ci{
9548c2ecf20Sopenharmony_ci	return table_instance_rehash(ti, ti->n_buckets * 2, ufid);
9558c2ecf20Sopenharmony_ci}
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci/* Must be called with OVS mutex held. */
9588c2ecf20Sopenharmony_civoid ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
9598c2ecf20Sopenharmony_ci{
9608c2ecf20Sopenharmony_ci	struct table_instance *ti = ovsl_dereference(table->ti);
9618c2ecf20Sopenharmony_ci	struct table_instance *ufid_ti = ovsl_dereference(table->ufid_ti);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	BUG_ON(table->count == 0);
9648c2ecf20Sopenharmony_ci	table_instance_flow_free(table, ti, ufid_ti, flow);
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_cistatic struct sw_flow_mask *mask_alloc(void)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	struct sw_flow_mask *mask;
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	mask = kmalloc(sizeof(*mask), GFP_KERNEL);
9728c2ecf20Sopenharmony_ci	if (mask)
9738c2ecf20Sopenharmony_ci		mask->ref_count = 1;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	return mask;
9768c2ecf20Sopenharmony_ci}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_cistatic bool mask_equal(const struct sw_flow_mask *a,
9798c2ecf20Sopenharmony_ci		       const struct sw_flow_mask *b)
9808c2ecf20Sopenharmony_ci{
9818c2ecf20Sopenharmony_ci	const u8 *a_ = (const u8 *)&a->key + a->range.start;
9828c2ecf20Sopenharmony_ci	const u8 *b_ = (const u8 *)&b->key + b->range.start;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	return  (a->range.end == b->range.end)
9858c2ecf20Sopenharmony_ci		&& (a->range.start == b->range.start)
9868c2ecf20Sopenharmony_ci		&& (memcmp(a_, b_, range_n_bytes(&a->range)) == 0);
9878c2ecf20Sopenharmony_ci}
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_cistatic struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl,
9908c2ecf20Sopenharmony_ci					   const struct sw_flow_mask *mask)
9918c2ecf20Sopenharmony_ci{
9928c2ecf20Sopenharmony_ci	struct mask_array *ma;
9938c2ecf20Sopenharmony_ci	int i;
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	ma = ovsl_dereference(tbl->mask_array);
9968c2ecf20Sopenharmony_ci	for (i = 0; i < ma->max; i++) {
9978c2ecf20Sopenharmony_ci		struct sw_flow_mask *t;
9988c2ecf20Sopenharmony_ci		t = ovsl_dereference(ma->masks[i]);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci		if (t && mask_equal(mask, t))
10018c2ecf20Sopenharmony_ci			return t;
10028c2ecf20Sopenharmony_ci	}
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	return NULL;
10058c2ecf20Sopenharmony_ci}
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci/* Add 'mask' into the mask list, if it is not already there. */
10088c2ecf20Sopenharmony_cistatic int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
10098c2ecf20Sopenharmony_ci			    const struct sw_flow_mask *new)
10108c2ecf20Sopenharmony_ci{
10118c2ecf20Sopenharmony_ci	struct sw_flow_mask *mask;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	mask = flow_mask_find(tbl, new);
10148c2ecf20Sopenharmony_ci	if (!mask) {
10158c2ecf20Sopenharmony_ci		/* Allocate a new mask if none exsits. */
10168c2ecf20Sopenharmony_ci		mask = mask_alloc();
10178c2ecf20Sopenharmony_ci		if (!mask)
10188c2ecf20Sopenharmony_ci			return -ENOMEM;
10198c2ecf20Sopenharmony_ci		mask->key = new->key;
10208c2ecf20Sopenharmony_ci		mask->range = new->range;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci		/* Add mask to mask-list. */
10238c2ecf20Sopenharmony_ci		if (tbl_mask_array_add_mask(tbl, mask)) {
10248c2ecf20Sopenharmony_ci			kfree(mask);
10258c2ecf20Sopenharmony_ci			return -ENOMEM;
10268c2ecf20Sopenharmony_ci		}
10278c2ecf20Sopenharmony_ci	} else {
10288c2ecf20Sopenharmony_ci		BUG_ON(!mask->ref_count);
10298c2ecf20Sopenharmony_ci		mask->ref_count++;
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	flow->mask = mask;
10338c2ecf20Sopenharmony_ci	return 0;
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci/* Must be called with OVS mutex held. */
10378c2ecf20Sopenharmony_cistatic void flow_key_insert(struct flow_table *table, struct sw_flow *flow)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	struct table_instance *new_ti = NULL;
10408c2ecf20Sopenharmony_ci	struct table_instance *ti;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	flow->flow_table.hash = flow_hash(&flow->key, &flow->mask->range);
10438c2ecf20Sopenharmony_ci	ti = ovsl_dereference(table->ti);
10448c2ecf20Sopenharmony_ci	table_instance_insert(ti, flow);
10458c2ecf20Sopenharmony_ci	table->count++;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	/* Expand table, if necessary, to make room. */
10488c2ecf20Sopenharmony_ci	if (table->count > ti->n_buckets)
10498c2ecf20Sopenharmony_ci		new_ti = table_instance_expand(ti, false);
10508c2ecf20Sopenharmony_ci	else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL))
10518c2ecf20Sopenharmony_ci		new_ti = table_instance_rehash(ti, ti->n_buckets, false);
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	if (new_ti) {
10548c2ecf20Sopenharmony_ci		rcu_assign_pointer(table->ti, new_ti);
10558c2ecf20Sopenharmony_ci		call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
10568c2ecf20Sopenharmony_ci		table->last_rehash = jiffies;
10578c2ecf20Sopenharmony_ci	}
10588c2ecf20Sopenharmony_ci}
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci/* Must be called with OVS mutex held. */
10618c2ecf20Sopenharmony_cistatic void flow_ufid_insert(struct flow_table *table, struct sw_flow *flow)
10628c2ecf20Sopenharmony_ci{
10638c2ecf20Sopenharmony_ci	struct table_instance *ti;
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	flow->ufid_table.hash = ufid_hash(&flow->id);
10668c2ecf20Sopenharmony_ci	ti = ovsl_dereference(table->ufid_ti);
10678c2ecf20Sopenharmony_ci	ufid_table_instance_insert(ti, flow);
10688c2ecf20Sopenharmony_ci	table->ufid_count++;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	/* Expand table, if necessary, to make room. */
10718c2ecf20Sopenharmony_ci	if (table->ufid_count > ti->n_buckets) {
10728c2ecf20Sopenharmony_ci		struct table_instance *new_ti;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci		new_ti = table_instance_expand(ti, true);
10758c2ecf20Sopenharmony_ci		if (new_ti) {
10768c2ecf20Sopenharmony_ci			rcu_assign_pointer(table->ufid_ti, new_ti);
10778c2ecf20Sopenharmony_ci			call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
10788c2ecf20Sopenharmony_ci		}
10798c2ecf20Sopenharmony_ci	}
10808c2ecf20Sopenharmony_ci}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci/* Must be called with OVS mutex held. */
10838c2ecf20Sopenharmony_ciint ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
10848c2ecf20Sopenharmony_ci			const struct sw_flow_mask *mask)
10858c2ecf20Sopenharmony_ci{
10868c2ecf20Sopenharmony_ci	int err;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	err = flow_mask_insert(table, flow, mask);
10898c2ecf20Sopenharmony_ci	if (err)
10908c2ecf20Sopenharmony_ci		return err;
10918c2ecf20Sopenharmony_ci	flow_key_insert(table, flow);
10928c2ecf20Sopenharmony_ci	if (ovs_identifier_is_ufid(&flow->id))
10938c2ecf20Sopenharmony_ci		flow_ufid_insert(table, flow);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	return 0;
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic int compare_mask_and_count(const void *a, const void *b)
10998c2ecf20Sopenharmony_ci{
11008c2ecf20Sopenharmony_ci	const struct mask_count *mc_a = a;
11018c2ecf20Sopenharmony_ci	const struct mask_count *mc_b = b;
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	return (s64)mc_b->counter - (s64)mc_a->counter;
11048c2ecf20Sopenharmony_ci}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci/* Must be called with OVS mutex held. */
11078c2ecf20Sopenharmony_civoid ovs_flow_masks_rebalance(struct flow_table *table)
11088c2ecf20Sopenharmony_ci{
11098c2ecf20Sopenharmony_ci	struct mask_array *ma = rcu_dereference_ovsl(table->mask_array);
11108c2ecf20Sopenharmony_ci	struct mask_count *masks_and_count;
11118c2ecf20Sopenharmony_ci	struct mask_array *new;
11128c2ecf20Sopenharmony_ci	int masks_entries = 0;
11138c2ecf20Sopenharmony_ci	int i;
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	/* Build array of all current entries with use counters. */
11168c2ecf20Sopenharmony_ci	masks_and_count = kmalloc_array(ma->max, sizeof(*masks_and_count),
11178c2ecf20Sopenharmony_ci					GFP_KERNEL);
11188c2ecf20Sopenharmony_ci	if (!masks_and_count)
11198c2ecf20Sopenharmony_ci		return;
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	for (i = 0; i < ma->max; i++) {
11228c2ecf20Sopenharmony_ci		struct sw_flow_mask *mask;
11238c2ecf20Sopenharmony_ci		int cpu;
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci		mask = rcu_dereference_ovsl(ma->masks[i]);
11268c2ecf20Sopenharmony_ci		if (unlikely(!mask))
11278c2ecf20Sopenharmony_ci			break;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci		masks_and_count[i].index = i;
11308c2ecf20Sopenharmony_ci		masks_and_count[i].counter = 0;
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci		for_each_possible_cpu(cpu) {
11338c2ecf20Sopenharmony_ci			struct mask_array_stats *stats;
11348c2ecf20Sopenharmony_ci			unsigned int start;
11358c2ecf20Sopenharmony_ci			u64 counter;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci			stats = per_cpu_ptr(ma->masks_usage_stats, cpu);
11388c2ecf20Sopenharmony_ci			do {
11398c2ecf20Sopenharmony_ci				start = u64_stats_fetch_begin_irq(&stats->syncp);
11408c2ecf20Sopenharmony_ci				counter = stats->usage_cntrs[i];
11418c2ecf20Sopenharmony_ci			} while (u64_stats_fetch_retry_irq(&stats->syncp,
11428c2ecf20Sopenharmony_ci							   start));
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci			masks_and_count[i].counter += counter;
11458c2ecf20Sopenharmony_ci		}
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci		/* Subtract the zero count value. */
11488c2ecf20Sopenharmony_ci		masks_and_count[i].counter -= ma->masks_usage_zero_cntr[i];
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci		/* Rather than calling tbl_mask_array_reset_counters()
11518c2ecf20Sopenharmony_ci		 * below when no change is needed, do it inline here.
11528c2ecf20Sopenharmony_ci		 */
11538c2ecf20Sopenharmony_ci		ma->masks_usage_zero_cntr[i] += masks_and_count[i].counter;
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	if (i == 0)
11578c2ecf20Sopenharmony_ci		goto free_mask_entries;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	/* Sort the entries */
11608c2ecf20Sopenharmony_ci	masks_entries = i;
11618c2ecf20Sopenharmony_ci	sort(masks_and_count, masks_entries, sizeof(*masks_and_count),
11628c2ecf20Sopenharmony_ci	     compare_mask_and_count, NULL);
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	/* If the order is the same, nothing to do... */
11658c2ecf20Sopenharmony_ci	for (i = 0; i < masks_entries; i++) {
11668c2ecf20Sopenharmony_ci		if (i != masks_and_count[i].index)
11678c2ecf20Sopenharmony_ci			break;
11688c2ecf20Sopenharmony_ci	}
11698c2ecf20Sopenharmony_ci	if (i == masks_entries)
11708c2ecf20Sopenharmony_ci		goto free_mask_entries;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	/* Rebuilt the new list in order of usage. */
11738c2ecf20Sopenharmony_ci	new = tbl_mask_array_alloc(ma->max);
11748c2ecf20Sopenharmony_ci	if (!new)
11758c2ecf20Sopenharmony_ci		goto free_mask_entries;
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	for (i = 0; i < masks_entries; i++) {
11788c2ecf20Sopenharmony_ci		int index = masks_and_count[i].index;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci		if (ovsl_dereference(ma->masks[index]))
11818c2ecf20Sopenharmony_ci			new->masks[new->count++] = ma->masks[index];
11828c2ecf20Sopenharmony_ci	}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	rcu_assign_pointer(table->mask_array, new);
11858c2ecf20Sopenharmony_ci	call_rcu(&ma->rcu, mask_array_rcu_cb);
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_cifree_mask_entries:
11888c2ecf20Sopenharmony_ci	kfree(masks_and_count);
11898c2ecf20Sopenharmony_ci}
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci/* Initializes the flow module.
11928c2ecf20Sopenharmony_ci * Returns zero if successful or a negative error code. */
11938c2ecf20Sopenharmony_ciint ovs_flow_init(void)
11948c2ecf20Sopenharmony_ci{
11958c2ecf20Sopenharmony_ci	BUILD_BUG_ON(__alignof__(struct sw_flow_key) % __alignof__(long));
11968c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long));
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow)
11998c2ecf20Sopenharmony_ci				       + (nr_cpu_ids
12008c2ecf20Sopenharmony_ci					  * sizeof(struct sw_flow_stats *)),
12018c2ecf20Sopenharmony_ci				       0, 0, NULL);
12028c2ecf20Sopenharmony_ci	if (flow_cache == NULL)
12038c2ecf20Sopenharmony_ci		return -ENOMEM;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	flow_stats_cache
12068c2ecf20Sopenharmony_ci		= kmem_cache_create("sw_flow_stats", sizeof(struct sw_flow_stats),
12078c2ecf20Sopenharmony_ci				    0, SLAB_HWCACHE_ALIGN, NULL);
12088c2ecf20Sopenharmony_ci	if (flow_stats_cache == NULL) {
12098c2ecf20Sopenharmony_ci		kmem_cache_destroy(flow_cache);
12108c2ecf20Sopenharmony_ci		flow_cache = NULL;
12118c2ecf20Sopenharmony_ci		return -ENOMEM;
12128c2ecf20Sopenharmony_ci	}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	return 0;
12158c2ecf20Sopenharmony_ci}
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci/* Uninitializes the flow module. */
12188c2ecf20Sopenharmony_civoid ovs_flow_exit(void)
12198c2ecf20Sopenharmony_ci{
12208c2ecf20Sopenharmony_ci	kmem_cache_destroy(flow_stats_cache);
12218c2ecf20Sopenharmony_ci	kmem_cache_destroy(flow_cache);
12228c2ecf20Sopenharmony_ci}
1223