xref: /openbmc/linux/net/openvswitch/flow_table.c (revision a2cfb96cc3654c6d451020480a4bcfbbca564350)
1c9422999SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e6445719SPravin B Shelar /*
39b996e54SPravin B Shelar  * Copyright (c) 2007-2014 Nicira, Inc.
4e6445719SPravin B Shelar  */
5e6445719SPravin B Shelar 
6e6445719SPravin B Shelar #include "flow.h"
7e6445719SPravin B Shelar #include "datapath.h"
834ae932aSThomas Graf #include "flow_netlink.h"
9e6445719SPravin B Shelar #include <linux/uaccess.h>
10e6445719SPravin B Shelar #include <linux/netdevice.h>
11e6445719SPravin B Shelar #include <linux/etherdevice.h>
12e6445719SPravin B Shelar #include <linux/if_ether.h>
13e6445719SPravin B Shelar #include <linux/if_vlan.h>
14e6445719SPravin B Shelar #include <net/llc_pdu.h>
15e6445719SPravin B Shelar #include <linux/kernel.h>
1687545899SDaniel Borkmann #include <linux/jhash.h>
17e6445719SPravin B Shelar #include <linux/jiffies.h>
18e6445719SPravin B Shelar #include <linux/llc.h>
19e6445719SPravin B Shelar #include <linux/module.h>
20e6445719SPravin B Shelar #include <linux/in.h>
21e6445719SPravin B Shelar #include <linux/rcupdate.h>
22db74a333SThadeu Lima de Souza Cascardo #include <linux/cpumask.h>
23e6445719SPravin B Shelar #include <linux/if_arp.h>
24e6445719SPravin B Shelar #include <linux/ip.h>
25e6445719SPravin B Shelar #include <linux/ipv6.h>
26e6445719SPravin B Shelar #include <linux/sctp.h>
27e6445719SPravin B Shelar #include <linux/tcp.h>
28e6445719SPravin B Shelar #include <linux/udp.h>
29e6445719SPravin B Shelar #include <linux/icmp.h>
30e6445719SPravin B Shelar #include <linux/icmpv6.h>
31e6445719SPravin B Shelar #include <linux/rculist.h>
32e6445719SPravin B Shelar #include <net/ip.h>
33e6445719SPravin B Shelar #include <net/ipv6.h>
34e6445719SPravin B Shelar #include <net/ndisc.h>
35e6445719SPravin B Shelar 
36b637e498SPravin B Shelar #define TBL_MIN_BUCKETS		1024
374bc63b1bSTonghao Zhang #define MASK_ARRAY_SIZE_MIN	16
38b637e498SPravin B Shelar #define REHASH_INTERVAL		(10 * 60 * HZ)
39b637e498SPravin B Shelar 
4004b7d136STonghao Zhang #define MC_HASH_SHIFT		8
4104b7d136STonghao Zhang #define MC_HASH_ENTRIES		(1u << MC_HASH_SHIFT)
4204b7d136STonghao Zhang #define MC_HASH_SEGS		((sizeof(uint32_t) * 8) / MC_HASH_SHIFT)
4304b7d136STonghao Zhang 
44e6445719SPravin B Shelar static struct kmem_cache *flow_cache;
4563e7959cSJarno Rajahalme struct kmem_cache *flow_stats_cache __read_mostly;
46e6445719SPravin B Shelar 
47e6445719SPravin B Shelar static u16 range_n_bytes(const struct sw_flow_key_range *range)
48e6445719SPravin B Shelar {
49e6445719SPravin B Shelar 	return range->end - range->start;
50e6445719SPravin B Shelar }
51e6445719SPravin B Shelar 
52e6445719SPravin B Shelar void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
53ae5f2fb1SJesse Gross 		       bool full, const struct sw_flow_mask *mask)
54e6445719SPravin B Shelar {
55ae5f2fb1SJesse Gross 	int start = full ? 0 : mask->range.start;
56ae5f2fb1SJesse Gross 	int len = full ? sizeof *dst : range_n_bytes(&mask->range);
57ae5f2fb1SJesse Gross 	const long *m = (const long *)((const u8 *)&mask->key + start);
58ae5f2fb1SJesse Gross 	const long *s = (const long *)((const u8 *)src + start);
59ae5f2fb1SJesse Gross 	long *d = (long *)((u8 *)dst + start);
60e6445719SPravin B Shelar 	int i;
61e6445719SPravin B Shelar 
62ae5f2fb1SJesse Gross 	/* If 'full' is true then all of 'dst' is fully initialized. Otherwise,
63ae5f2fb1SJesse Gross 	 * if 'full' is false the memory outside of the 'mask->range' is left
64ae5f2fb1SJesse Gross 	 * uninitialized. This can be used as an optimization when further
65ae5f2fb1SJesse Gross 	 * operations on 'dst' only use contents within 'mask->range'.
66e6445719SPravin B Shelar 	 */
67ae5f2fb1SJesse Gross 	for (i = 0; i < len; i += sizeof(long))
68e6445719SPravin B Shelar 		*d++ = *s++ & *m++;
69e6445719SPravin B Shelar }
70e6445719SPravin B Shelar 
7123dabf88SJarno Rajahalme struct sw_flow *ovs_flow_alloc(void)
72e6445719SPravin B Shelar {
73e6445719SPravin B Shelar 	struct sw_flow *flow;
74aef833c5SPablo Neira Ayuso 	struct sw_flow_stats *stats;
75e6445719SPravin B Shelar 
76db74a333SThadeu Lima de Souza Cascardo 	flow = kmem_cache_zalloc(flow_cache, GFP_KERNEL);
77e6445719SPravin B Shelar 	if (!flow)
78e6445719SPravin B Shelar 		return ERR_PTR(-ENOMEM);
79e6445719SPravin B Shelar 
80db74a333SThadeu Lima de Souza Cascardo 	flow->stats_last_writer = -1;
81e6445719SPravin B Shelar 
8263e7959cSJarno Rajahalme 	/* Initialize the default stat node. */
8363e7959cSJarno Rajahalme 	stats = kmem_cache_alloc_node(flow_stats_cache,
84598c12d0SKonstantin Khlebnikov 				      GFP_KERNEL | __GFP_ZERO,
85598c12d0SKonstantin Khlebnikov 				      node_online(0) ? 0 : NUMA_NO_NODE);
8663e7959cSJarno Rajahalme 	if (!stats)
87e298e505SPravin B Shelar 		goto err;
88e298e505SPravin B Shelar 
8963e7959cSJarno Rajahalme 	spin_lock_init(&stats->lock);
90e298e505SPravin B Shelar 
9163e7959cSJarno Rajahalme 	RCU_INIT_POINTER(flow->stats[0], stats);
9263e7959cSJarno Rajahalme 
93c4b2bf6bSTonghao Zhang 	cpumask_set_cpu(0, &flow->cpu_used_mask);
94c4b2bf6bSTonghao Zhang 
95e6445719SPravin B Shelar 	return flow;
96e298e505SPravin B Shelar err:
97ece37c87SWei Yongjun 	kmem_cache_free(flow_cache, flow);
98e298e505SPravin B Shelar 	return ERR_PTR(-ENOMEM);
99e6445719SPravin B Shelar }
100e6445719SPravin B Shelar 
10112eb18f7SThomas Graf int ovs_flow_tbl_count(const struct flow_table *table)
102b637e498SPravin B Shelar {
103b637e498SPravin B Shelar 	return table->count;
104b637e498SPravin B Shelar }
105b637e498SPravin B Shelar 
106e6445719SPravin B Shelar static void flow_free(struct sw_flow *flow)
107e6445719SPravin B Shelar {
108db74a333SThadeu Lima de Souza Cascardo 	int cpu;
10963e7959cSJarno Rajahalme 
11074ed7ab9SJoe Stringer 	if (ovs_identifier_is_key(&flow->id))
11174ed7ab9SJoe Stringer 		kfree(flow->id.unmasked_key);
11234ae932aSThomas Graf 	if (flow->sf_acts)
11334ae932aSThomas Graf 		ovs_nla_free_flow_actions((struct sw_flow_actions __force *)flow->sf_acts);
114db74a333SThadeu Lima de Souza Cascardo 	/* We open code this to make sure cpu 0 is always considered */
115c4b2bf6bSTonghao Zhang 	for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask))
116db74a333SThadeu Lima de Souza Cascardo 		if (flow->stats[cpu])
11763e7959cSJarno Rajahalme 			kmem_cache_free(flow_stats_cache,
118aef833c5SPablo Neira Ayuso 					(struct sw_flow_stats __force *)flow->stats[cpu]);
119e6445719SPravin B Shelar 	kmem_cache_free(flow_cache, flow);
120e6445719SPravin B Shelar }
121e6445719SPravin B Shelar 
122e6445719SPravin B Shelar static void rcu_free_flow_callback(struct rcu_head *rcu)
123e6445719SPravin B Shelar {
124e6445719SPravin B Shelar 	struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
125e6445719SPravin B Shelar 
126e6445719SPravin B Shelar 	flow_free(flow);
127e6445719SPravin B Shelar }
128e6445719SPravin B Shelar 
129e80857ccSAndy Zhou void ovs_flow_free(struct sw_flow *flow, bool deferred)
130618ed0c8SPravin B Shelar {
131e80857ccSAndy Zhou 	if (!flow)
132618ed0c8SPravin B Shelar 		return;
133618ed0c8SPravin B Shelar 
134e6445719SPravin B Shelar 	if (deferred)
135e6445719SPravin B Shelar 		call_rcu(&flow->rcu, rcu_free_flow_callback);
136e6445719SPravin B Shelar 	else
137e6445719SPravin B Shelar 		flow_free(flow);
138e6445719SPravin B Shelar }
139e6445719SPravin B Shelar 
140b637e498SPravin B Shelar static void __table_instance_destroy(struct table_instance *ti)
141e6445719SPravin B Shelar {
142ee9c5e67SKent Overstreet 	kvfree(ti->buckets);
143b637e498SPravin B Shelar 	kfree(ti);
144e6445719SPravin B Shelar }
145e6445719SPravin B Shelar 
146b637e498SPravin B Shelar static struct table_instance *table_instance_alloc(int new_size)
147e6445719SPravin B Shelar {
148b637e498SPravin B Shelar 	struct table_instance *ti = kmalloc(sizeof(*ti), GFP_KERNEL);
149ee9c5e67SKent Overstreet 	int i;
150e6445719SPravin B Shelar 
151b637e498SPravin B Shelar 	if (!ti)
152e6445719SPravin B Shelar 		return NULL;
153e6445719SPravin B Shelar 
154ee9c5e67SKent Overstreet 	ti->buckets = kvmalloc_array(new_size, sizeof(struct hlist_head),
155ee9c5e67SKent Overstreet 				     GFP_KERNEL);
156b637e498SPravin B Shelar 	if (!ti->buckets) {
157b637e498SPravin B Shelar 		kfree(ti);
158e6445719SPravin B Shelar 		return NULL;
159e6445719SPravin B Shelar 	}
160ee9c5e67SKent Overstreet 
161ee9c5e67SKent Overstreet 	for (i = 0; i < new_size; i++)
162ee9c5e67SKent Overstreet 		INIT_HLIST_HEAD(&ti->buckets[i]);
163ee9c5e67SKent Overstreet 
164b637e498SPravin B Shelar 	ti->n_buckets = new_size;
165b637e498SPravin B Shelar 	ti->node_ver = 0;
166b637e498SPravin B Shelar 	ti->keep_flows = false;
167b637e498SPravin B Shelar 	get_random_bytes(&ti->hash_seed, sizeof(u32));
168b637e498SPravin B Shelar 
169b637e498SPravin B Shelar 	return ti;
170b637e498SPravin B Shelar }
171b637e498SPravin B Shelar 
1724bc63b1bSTonghao Zhang static struct mask_array *tbl_mask_array_alloc(int size)
1734bc63b1bSTonghao Zhang {
1744bc63b1bSTonghao Zhang 	struct mask_array *new;
1754bc63b1bSTonghao Zhang 
1764bc63b1bSTonghao Zhang 	size = max(MASK_ARRAY_SIZE_MIN, size);
1774bc63b1bSTonghao Zhang 	new = kzalloc(sizeof(struct mask_array) +
1784bc63b1bSTonghao Zhang 		      sizeof(struct sw_flow_mask *) * size, GFP_KERNEL);
1794bc63b1bSTonghao Zhang 	if (!new)
1804bc63b1bSTonghao Zhang 		return NULL;
1814bc63b1bSTonghao Zhang 
1824bc63b1bSTonghao Zhang 	new->count = 0;
1834bc63b1bSTonghao Zhang 	new->max = size;
1844bc63b1bSTonghao Zhang 
1854bc63b1bSTonghao Zhang 	return new;
1864bc63b1bSTonghao Zhang }
1874bc63b1bSTonghao Zhang 
1884bc63b1bSTonghao Zhang static int tbl_mask_array_realloc(struct flow_table *tbl, int size)
1894bc63b1bSTonghao Zhang {
1904bc63b1bSTonghao Zhang 	struct mask_array *old;
1914bc63b1bSTonghao Zhang 	struct mask_array *new;
1924bc63b1bSTonghao Zhang 
1934bc63b1bSTonghao Zhang 	new = tbl_mask_array_alloc(size);
1944bc63b1bSTonghao Zhang 	if (!new)
1954bc63b1bSTonghao Zhang 		return -ENOMEM;
1964bc63b1bSTonghao Zhang 
1974bc63b1bSTonghao Zhang 	old = ovsl_dereference(tbl->mask_array);
1984bc63b1bSTonghao Zhang 	if (old) {
1994bc63b1bSTonghao Zhang 		int i;
2004bc63b1bSTonghao Zhang 
2014bc63b1bSTonghao Zhang 		for (i = 0; i < old->max; i++) {
2024bc63b1bSTonghao Zhang 			if (ovsl_dereference(old->masks[i]))
2034bc63b1bSTonghao Zhang 				new->masks[new->count++] = old->masks[i];
2044bc63b1bSTonghao Zhang 		}
2054bc63b1bSTonghao Zhang 	}
2064bc63b1bSTonghao Zhang 
2074bc63b1bSTonghao Zhang 	rcu_assign_pointer(tbl->mask_array, new);
2084bc63b1bSTonghao Zhang 	kfree_rcu(old, rcu);
2094bc63b1bSTonghao Zhang 
2104bc63b1bSTonghao Zhang 	return 0;
2114bc63b1bSTonghao Zhang }
2124bc63b1bSTonghao Zhang 
21350b0e61bSTonghao Zhang static int tbl_mask_array_add_mask(struct flow_table *tbl,
21450b0e61bSTonghao Zhang 				   struct sw_flow_mask *new)
21550b0e61bSTonghao Zhang {
21650b0e61bSTonghao Zhang 	struct mask_array *ma = ovsl_dereference(tbl->mask_array);
21750b0e61bSTonghao Zhang 	int err, ma_count = READ_ONCE(ma->count);
21850b0e61bSTonghao Zhang 
21950b0e61bSTonghao Zhang 	if (ma_count >= ma->max) {
22050b0e61bSTonghao Zhang 		err = tbl_mask_array_realloc(tbl, ma->max +
22150b0e61bSTonghao Zhang 					      MASK_ARRAY_SIZE_MIN);
22250b0e61bSTonghao Zhang 		if (err)
22350b0e61bSTonghao Zhang 			return err;
22450b0e61bSTonghao Zhang 
22550b0e61bSTonghao Zhang 		ma = ovsl_dereference(tbl->mask_array);
22650b0e61bSTonghao Zhang 	}
22750b0e61bSTonghao Zhang 
22850b0e61bSTonghao Zhang 	BUG_ON(ovsl_dereference(ma->masks[ma_count]));
22950b0e61bSTonghao Zhang 
23050b0e61bSTonghao Zhang 	rcu_assign_pointer(ma->masks[ma_count], new);
23150b0e61bSTonghao Zhang 	WRITE_ONCE(ma->count, ma_count +1);
23250b0e61bSTonghao Zhang 
23350b0e61bSTonghao Zhang 	return 0;
23450b0e61bSTonghao Zhang }
23550b0e61bSTonghao Zhang 
23650b0e61bSTonghao Zhang static void tbl_mask_array_del_mask(struct flow_table *tbl,
23750b0e61bSTonghao Zhang 				    struct sw_flow_mask *mask)
23850b0e61bSTonghao Zhang {
23950b0e61bSTonghao Zhang 	struct mask_array *ma = ovsl_dereference(tbl->mask_array);
24050b0e61bSTonghao Zhang 	int i, ma_count = READ_ONCE(ma->count);
24150b0e61bSTonghao Zhang 
24250b0e61bSTonghao Zhang 	/* Remove the deleted mask pointers from the array */
24350b0e61bSTonghao Zhang 	for (i = 0; i < ma_count; i++) {
24450b0e61bSTonghao Zhang 		if (mask == ovsl_dereference(ma->masks[i]))
24550b0e61bSTonghao Zhang 			goto found;
24650b0e61bSTonghao Zhang 	}
24750b0e61bSTonghao Zhang 
24850b0e61bSTonghao Zhang 	BUG();
24950b0e61bSTonghao Zhang 	return;
25050b0e61bSTonghao Zhang 
25150b0e61bSTonghao Zhang found:
25250b0e61bSTonghao Zhang 	WRITE_ONCE(ma->count, ma_count -1);
25350b0e61bSTonghao Zhang 
25450b0e61bSTonghao Zhang 	rcu_assign_pointer(ma->masks[i], ma->masks[ma_count -1]);
25550b0e61bSTonghao Zhang 	RCU_INIT_POINTER(ma->masks[ma_count -1], NULL);
25650b0e61bSTonghao Zhang 
25750b0e61bSTonghao Zhang 	kfree_rcu(mask, rcu);
25850b0e61bSTonghao Zhang 
25950b0e61bSTonghao Zhang 	/* Shrink the mask array if necessary. */
26050b0e61bSTonghao Zhang 	if (ma->max >= (MASK_ARRAY_SIZE_MIN * 2) &&
26150b0e61bSTonghao Zhang 	    ma_count <= (ma->max / 3))
26250b0e61bSTonghao Zhang 		tbl_mask_array_realloc(tbl, ma->max / 2);
26350b0e61bSTonghao Zhang }
26450b0e61bSTonghao Zhang 
26550b0e61bSTonghao Zhang /* Remove 'mask' from the mask list, if it is not needed any more. */
26650b0e61bSTonghao Zhang static void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask)
26750b0e61bSTonghao Zhang {
26850b0e61bSTonghao Zhang 	if (mask) {
26950b0e61bSTonghao Zhang 		/* ovs-lock is required to protect mask-refcount and
27050b0e61bSTonghao Zhang 		 * mask list.
27150b0e61bSTonghao Zhang 		 */
27250b0e61bSTonghao Zhang 		ASSERT_OVSL();
27350b0e61bSTonghao Zhang 		BUG_ON(!mask->ref_count);
27450b0e61bSTonghao Zhang 		mask->ref_count--;
27550b0e61bSTonghao Zhang 
27650b0e61bSTonghao Zhang 		if (!mask->ref_count)
27750b0e61bSTonghao Zhang 			tbl_mask_array_del_mask(tbl, mask);
27850b0e61bSTonghao Zhang 	}
27950b0e61bSTonghao Zhang }
28050b0e61bSTonghao Zhang 
281b637e498SPravin B Shelar int ovs_flow_tbl_init(struct flow_table *table)
282b637e498SPravin B Shelar {
28374ed7ab9SJoe Stringer 	struct table_instance *ti, *ufid_ti;
2844bc63b1bSTonghao Zhang 	struct mask_array *ma;
285b637e498SPravin B Shelar 
28604b7d136STonghao Zhang 	table->mask_cache = __alloc_percpu(sizeof(struct mask_cache_entry) *
28704b7d136STonghao Zhang 					   MC_HASH_ENTRIES,
28804b7d136STonghao Zhang 					   __alignof__(struct mask_cache_entry));
28904b7d136STonghao Zhang 	if (!table->mask_cache)
290b637e498SPravin B Shelar 		return -ENOMEM;
291b637e498SPravin B Shelar 
2924bc63b1bSTonghao Zhang 	ma = tbl_mask_array_alloc(MASK_ARRAY_SIZE_MIN);
2934bc63b1bSTonghao Zhang 	if (!ma)
2944bc63b1bSTonghao Zhang 		goto free_mask_cache;
2954bc63b1bSTonghao Zhang 
29604b7d136STonghao Zhang 	ti = table_instance_alloc(TBL_MIN_BUCKETS);
29704b7d136STonghao Zhang 	if (!ti)
2984bc63b1bSTonghao Zhang 		goto free_mask_array;
29904b7d136STonghao Zhang 
30074ed7ab9SJoe Stringer 	ufid_ti = table_instance_alloc(TBL_MIN_BUCKETS);
30174ed7ab9SJoe Stringer 	if (!ufid_ti)
30274ed7ab9SJoe Stringer 		goto free_ti;
30374ed7ab9SJoe Stringer 
304b637e498SPravin B Shelar 	rcu_assign_pointer(table->ti, ti);
30574ed7ab9SJoe Stringer 	rcu_assign_pointer(table->ufid_ti, ufid_ti);
3064bc63b1bSTonghao Zhang 	rcu_assign_pointer(table->mask_array, ma);
307b637e498SPravin B Shelar 	table->last_rehash = jiffies;
308e6445719SPravin B Shelar 	table->count = 0;
30974ed7ab9SJoe Stringer 	table->ufid_count = 0;
310b637e498SPravin B Shelar 	return 0;
31174ed7ab9SJoe Stringer 
31274ed7ab9SJoe Stringer free_ti:
31374ed7ab9SJoe Stringer 	__table_instance_destroy(ti);
3144bc63b1bSTonghao Zhang free_mask_array:
3154bc63b1bSTonghao Zhang 	kfree(ma);
31604b7d136STonghao Zhang free_mask_cache:
31704b7d136STonghao Zhang 	free_percpu(table->mask_cache);
31874ed7ab9SJoe Stringer 	return -ENOMEM;
319e6445719SPravin B Shelar }
320e6445719SPravin B Shelar 
321e6445719SPravin B Shelar static void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu)
322e6445719SPravin B Shelar {
323b637e498SPravin B Shelar 	struct table_instance *ti = container_of(rcu, struct table_instance, rcu);
324e6445719SPravin B Shelar 
325b637e498SPravin B Shelar 	__table_instance_destroy(ti);
326b637e498SPravin B Shelar }
327b637e498SPravin B Shelar 
32850b0e61bSTonghao Zhang static void table_instance_flow_free(struct flow_table *table,
32950b0e61bSTonghao Zhang 				  struct table_instance *ti,
33050b0e61bSTonghao Zhang 				  struct table_instance *ufid_ti,
33150b0e61bSTonghao Zhang 				  struct sw_flow *flow,
33250b0e61bSTonghao Zhang 				  bool count)
33350b0e61bSTonghao Zhang {
33450b0e61bSTonghao Zhang 	hlist_del_rcu(&flow->flow_table.node[ti->node_ver]);
33550b0e61bSTonghao Zhang 	if (count)
33650b0e61bSTonghao Zhang 		table->count--;
33750b0e61bSTonghao Zhang 
33850b0e61bSTonghao Zhang 	if (ovs_identifier_is_ufid(&flow->id)) {
33950b0e61bSTonghao Zhang 		hlist_del_rcu(&flow->ufid_table.node[ufid_ti->node_ver]);
34050b0e61bSTonghao Zhang 
34150b0e61bSTonghao Zhang 		if (count)
34250b0e61bSTonghao Zhang 			table->ufid_count--;
34350b0e61bSTonghao Zhang 	}
34450b0e61bSTonghao Zhang 
34550b0e61bSTonghao Zhang 	flow_mask_remove(table, flow->mask);
34650b0e61bSTonghao Zhang }
34750b0e61bSTonghao Zhang 
34850b0e61bSTonghao Zhang static void table_instance_destroy(struct flow_table *table,
34950b0e61bSTonghao Zhang 				   struct table_instance *ti,
35074ed7ab9SJoe Stringer 				   struct table_instance *ufid_ti,
35174ed7ab9SJoe Stringer 				   bool deferred)
352b637e498SPravin B Shelar {
353e80857ccSAndy Zhou 	int i;
354e80857ccSAndy Zhou 
355b637e498SPravin B Shelar 	if (!ti)
356b637e498SPravin B Shelar 		return;
357b637e498SPravin B Shelar 
35874ed7ab9SJoe Stringer 	BUG_ON(!ufid_ti);
359e80857ccSAndy Zhou 	if (ti->keep_flows)
360e80857ccSAndy Zhou 		goto skip_flows;
361e80857ccSAndy Zhou 
362e80857ccSAndy Zhou 	for (i = 0; i < ti->n_buckets; i++) {
363e80857ccSAndy Zhou 		struct sw_flow *flow;
364ee9c5e67SKent Overstreet 		struct hlist_head *head = &ti->buckets[i];
365e80857ccSAndy Zhou 		struct hlist_node *n;
366e80857ccSAndy Zhou 
36750b0e61bSTonghao Zhang 		hlist_for_each_entry_safe(flow, n, head,
36850b0e61bSTonghao Zhang 					  flow_table.node[ti->node_ver]) {
36950b0e61bSTonghao Zhang 
37050b0e61bSTonghao Zhang 			table_instance_flow_free(table, ti, ufid_ti,
37150b0e61bSTonghao Zhang 						 flow, false);
372e80857ccSAndy Zhou 			ovs_flow_free(flow, deferred);
373e80857ccSAndy Zhou 		}
374e80857ccSAndy Zhou 	}
375e80857ccSAndy Zhou 
376e80857ccSAndy Zhou skip_flows:
37774ed7ab9SJoe Stringer 	if (deferred) {
378b637e498SPravin B Shelar 		call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
37974ed7ab9SJoe Stringer 		call_rcu(&ufid_ti->rcu, flow_tbl_destroy_rcu_cb);
38074ed7ab9SJoe Stringer 	} else {
381b637e498SPravin B Shelar 		__table_instance_destroy(ti);
38274ed7ab9SJoe Stringer 		__table_instance_destroy(ufid_ti);
38374ed7ab9SJoe Stringer 	}
384e6445719SPravin B Shelar }
385e6445719SPravin B Shelar 
3869b996e54SPravin B Shelar /* No need for locking this function is called from RCU callback or
3879b996e54SPravin B Shelar  * error path.
3889b996e54SPravin B Shelar  */
3899b996e54SPravin B Shelar void ovs_flow_tbl_destroy(struct flow_table *table)
390e6445719SPravin B Shelar {
3919b996e54SPravin B Shelar 	struct table_instance *ti = rcu_dereference_raw(table->ti);
39274ed7ab9SJoe Stringer 	struct table_instance *ufid_ti = rcu_dereference_raw(table->ufid_ti);
393e6445719SPravin B Shelar 
39404b7d136STonghao Zhang 	free_percpu(table->mask_cache);
3954bc63b1bSTonghao Zhang 	kfree_rcu(rcu_dereference_raw(table->mask_array), rcu);
39650b0e61bSTonghao Zhang 	table_instance_destroy(table, ti, ufid_ti, false);
397e6445719SPravin B Shelar }
398e6445719SPravin B Shelar 
399b637e498SPravin B Shelar struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
400e6445719SPravin B Shelar 				       u32 *bucket, u32 *last)
401e6445719SPravin B Shelar {
402e6445719SPravin B Shelar 	struct sw_flow *flow;
403e6445719SPravin B Shelar 	struct hlist_head *head;
404e6445719SPravin B Shelar 	int ver;
405e6445719SPravin B Shelar 	int i;
406e6445719SPravin B Shelar 
407b637e498SPravin B Shelar 	ver = ti->node_ver;
408b637e498SPravin B Shelar 	while (*bucket < ti->n_buckets) {
409e6445719SPravin B Shelar 		i = 0;
410ee9c5e67SKent Overstreet 		head = &ti->buckets[*bucket];
41174ed7ab9SJoe Stringer 		hlist_for_each_entry_rcu(flow, head, flow_table.node[ver]) {
412e6445719SPravin B Shelar 			if (i < *last) {
413e6445719SPravin B Shelar 				i++;
414e6445719SPravin B Shelar 				continue;
415e6445719SPravin B Shelar 			}
416e6445719SPravin B Shelar 			*last = i + 1;
417e6445719SPravin B Shelar 			return flow;
418e6445719SPravin B Shelar 		}
419e6445719SPravin B Shelar 		(*bucket)++;
420e6445719SPravin B Shelar 		*last = 0;
421e6445719SPravin B Shelar 	}
422e6445719SPravin B Shelar 
423e6445719SPravin B Shelar 	return NULL;
424e6445719SPravin B Shelar }
425e6445719SPravin B Shelar 
426b637e498SPravin B Shelar static struct hlist_head *find_bucket(struct table_instance *ti, u32 hash)
427e6445719SPravin B Shelar {
428b637e498SPravin B Shelar 	hash = jhash_1word(hash, ti->hash_seed);
429ee9c5e67SKent Overstreet 	return &ti->buckets[hash & (ti->n_buckets - 1)];
430e6445719SPravin B Shelar }
431e6445719SPravin B Shelar 
43274ed7ab9SJoe Stringer static void table_instance_insert(struct table_instance *ti,
43374ed7ab9SJoe Stringer 				  struct sw_flow *flow)
434e6445719SPravin B Shelar {
435e6445719SPravin B Shelar 	struct hlist_head *head;
436e6445719SPravin B Shelar 
43774ed7ab9SJoe Stringer 	head = find_bucket(ti, flow->flow_table.hash);
43874ed7ab9SJoe Stringer 	hlist_add_head_rcu(&flow->flow_table.node[ti->node_ver], head);
43974ed7ab9SJoe Stringer }
44074ed7ab9SJoe Stringer 
44174ed7ab9SJoe Stringer static void ufid_table_instance_insert(struct table_instance *ti,
44274ed7ab9SJoe Stringer 				       struct sw_flow *flow)
44374ed7ab9SJoe Stringer {
44474ed7ab9SJoe Stringer 	struct hlist_head *head;
44574ed7ab9SJoe Stringer 
44674ed7ab9SJoe Stringer 	head = find_bucket(ti, flow->ufid_table.hash);
44774ed7ab9SJoe Stringer 	hlist_add_head_rcu(&flow->ufid_table.node[ti->node_ver], head);
448e6445719SPravin B Shelar }
449e6445719SPravin B Shelar 
450b637e498SPravin B Shelar static void flow_table_copy_flows(struct table_instance *old,
45174ed7ab9SJoe Stringer 				  struct table_instance *new, bool ufid)
452e6445719SPravin B Shelar {
453e6445719SPravin B Shelar 	int old_ver;
454e6445719SPravin B Shelar 	int i;
455e6445719SPravin B Shelar 
456e6445719SPravin B Shelar 	old_ver = old->node_ver;
457e6445719SPravin B Shelar 	new->node_ver = !old_ver;
458e6445719SPravin B Shelar 
459e6445719SPravin B Shelar 	/* Insert in new table. */
460e6445719SPravin B Shelar 	for (i = 0; i < old->n_buckets; i++) {
461e6445719SPravin B Shelar 		struct sw_flow *flow;
462ee9c5e67SKent Overstreet 		struct hlist_head *head = &old->buckets[i];
463e6445719SPravin B Shelar 
46474ed7ab9SJoe Stringer 		if (ufid)
46574ed7ab9SJoe Stringer 			hlist_for_each_entry(flow, head,
46674ed7ab9SJoe Stringer 					     ufid_table.node[old_ver])
46774ed7ab9SJoe Stringer 				ufid_table_instance_insert(new, flow);
46874ed7ab9SJoe Stringer 		else
46974ed7ab9SJoe Stringer 			hlist_for_each_entry(flow, head,
47074ed7ab9SJoe Stringer 					     flow_table.node[old_ver])
471b637e498SPravin B Shelar 				table_instance_insert(new, flow);
472e6445719SPravin B Shelar 	}
473e6445719SPravin B Shelar 
474e6445719SPravin B Shelar 	old->keep_flows = true;
475e6445719SPravin B Shelar }
476e6445719SPravin B Shelar 
477b637e498SPravin B Shelar static struct table_instance *table_instance_rehash(struct table_instance *ti,
47874ed7ab9SJoe Stringer 						    int n_buckets, bool ufid)
479e6445719SPravin B Shelar {
480b637e498SPravin B Shelar 	struct table_instance *new_ti;
481e6445719SPravin B Shelar 
482b637e498SPravin B Shelar 	new_ti = table_instance_alloc(n_buckets);
483b637e498SPravin B Shelar 	if (!new_ti)
484618ed0c8SPravin B Shelar 		return NULL;
485e6445719SPravin B Shelar 
48674ed7ab9SJoe Stringer 	flow_table_copy_flows(ti, new_ti, ufid);
487e6445719SPravin B Shelar 
488b637e498SPravin B Shelar 	return new_ti;
489e6445719SPravin B Shelar }
490e6445719SPravin B Shelar 
491b637e498SPravin B Shelar int ovs_flow_tbl_flush(struct flow_table *flow_table)
492e6445719SPravin B Shelar {
49374ed7ab9SJoe Stringer 	struct table_instance *old_ti, *new_ti;
49474ed7ab9SJoe Stringer 	struct table_instance *old_ufid_ti, *new_ufid_ti;
495e6445719SPravin B Shelar 
496b637e498SPravin B Shelar 	new_ti = table_instance_alloc(TBL_MIN_BUCKETS);
497b637e498SPravin B Shelar 	if (!new_ti)
498b637e498SPravin B Shelar 		return -ENOMEM;
49974ed7ab9SJoe Stringer 	new_ufid_ti = table_instance_alloc(TBL_MIN_BUCKETS);
50074ed7ab9SJoe Stringer 	if (!new_ufid_ti)
50174ed7ab9SJoe Stringer 		goto err_free_ti;
50274ed7ab9SJoe Stringer 
50374ed7ab9SJoe Stringer 	old_ti = ovsl_dereference(flow_table->ti);
50474ed7ab9SJoe Stringer 	old_ufid_ti = ovsl_dereference(flow_table->ufid_ti);
505b637e498SPravin B Shelar 
506b637e498SPravin B Shelar 	rcu_assign_pointer(flow_table->ti, new_ti);
50774ed7ab9SJoe Stringer 	rcu_assign_pointer(flow_table->ufid_ti, new_ufid_ti);
508b637e498SPravin B Shelar 	flow_table->last_rehash = jiffies;
509b637e498SPravin B Shelar 	flow_table->count = 0;
51074ed7ab9SJoe Stringer 	flow_table->ufid_count = 0;
511b637e498SPravin B Shelar 
51250b0e61bSTonghao Zhang 	table_instance_destroy(flow_table, old_ti, old_ufid_ti, true);
513b637e498SPravin B Shelar 	return 0;
51474ed7ab9SJoe Stringer 
51574ed7ab9SJoe Stringer err_free_ti:
51674ed7ab9SJoe Stringer 	__table_instance_destroy(new_ti);
51774ed7ab9SJoe Stringer 	return -ENOMEM;
518e6445719SPravin B Shelar }
519e6445719SPravin B Shelar 
520272c2cf8SJoe Stringer static u32 flow_hash(const struct sw_flow_key *key,
521272c2cf8SJoe Stringer 		     const struct sw_flow_key_range *range)
522e6445719SPravin B Shelar {
523515b65a4STonghao Zhang 	const u32 *hash_key = (const u32 *)((const u8 *)key + range->start);
524e6445719SPravin B Shelar 
525e6445719SPravin B Shelar 	/* Make sure number of hash bytes are multiple of u32. */
526515b65a4STonghao Zhang 	int hash_u32s = range_n_bytes(range) >> 2;
527e6445719SPravin B Shelar 
52887545899SDaniel Borkmann 	return jhash2(hash_key, hash_u32s, 0);
529e6445719SPravin B Shelar }
530e6445719SPravin B Shelar 
531e6445719SPravin B Shelar static int flow_key_start(const struct sw_flow_key *key)
532e6445719SPravin B Shelar {
53300a93babSJiri Benc 	if (key->tun_proto)
534e6445719SPravin B Shelar 		return 0;
535e6445719SPravin B Shelar 	else
536e6445719SPravin B Shelar 		return rounddown(offsetof(struct sw_flow_key, phy),
537e6445719SPravin B Shelar 					  sizeof(long));
538e6445719SPravin B Shelar }
539e6445719SPravin B Shelar 
540e6445719SPravin B Shelar static bool cmp_key(const struct sw_flow_key *key1,
541e6445719SPravin B Shelar 		    const struct sw_flow_key *key2,
542e6445719SPravin B Shelar 		    int key_start, int key_end)
543e6445719SPravin B Shelar {
5447085130bSDaniele Di Proietto 	const long *cp1 = (const long *)((const u8 *)key1 + key_start);
5457085130bSDaniele Di Proietto 	const long *cp2 = (const long *)((const u8 *)key2 + key_start);
546e6445719SPravin B Shelar 	long diffs = 0;
547e6445719SPravin B Shelar 	int i;
548e6445719SPravin B Shelar 
549e6445719SPravin B Shelar 	for (i = key_start; i < key_end;  i += sizeof(long))
550e6445719SPravin B Shelar 		diffs |= *cp1++ ^ *cp2++;
551e6445719SPravin B Shelar 
552e6445719SPravin B Shelar 	return diffs == 0;
553e6445719SPravin B Shelar }
554e6445719SPravin B Shelar 
555e6445719SPravin B Shelar static bool flow_cmp_masked_key(const struct sw_flow *flow,
556e6445719SPravin B Shelar 				const struct sw_flow_key *key,
557272c2cf8SJoe Stringer 				const struct sw_flow_key_range *range)
558e6445719SPravin B Shelar {
559272c2cf8SJoe Stringer 	return cmp_key(&flow->key, key, range->start, range->end);
560e6445719SPravin B Shelar }
561e6445719SPravin B Shelar 
56274ed7ab9SJoe Stringer static bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
56312eb18f7SThomas Graf 				      const struct sw_flow_match *match)
564e6445719SPravin B Shelar {
565e6445719SPravin B Shelar 	struct sw_flow_key *key = match->key;
566e6445719SPravin B Shelar 	int key_start = flow_key_start(key);
567e6445719SPravin B Shelar 	int key_end = match->range.end;
568e6445719SPravin B Shelar 
56974ed7ab9SJoe Stringer 	BUG_ON(ovs_identifier_is_ufid(&flow->id));
57074ed7ab9SJoe Stringer 	return cmp_key(flow->id.unmasked_key, key, key_start, key_end);
571e6445719SPravin B Shelar }
572e6445719SPravin B Shelar 
573b637e498SPravin B Shelar static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
574e6445719SPravin B Shelar 					  const struct sw_flow_key *unmasked,
57504b7d136STonghao Zhang 					  const struct sw_flow_mask *mask,
57604b7d136STonghao Zhang 					  u32 *n_mask_hit)
577e6445719SPravin B Shelar {
578e6445719SPravin B Shelar 	struct sw_flow *flow;
579e6445719SPravin B Shelar 	struct hlist_head *head;
580e6445719SPravin B Shelar 	u32 hash;
581e6445719SPravin B Shelar 	struct sw_flow_key masked_key;
582e6445719SPravin B Shelar 
583ae5f2fb1SJesse Gross 	ovs_flow_mask_key(&masked_key, unmasked, false, mask);
584272c2cf8SJoe Stringer 	hash = flow_hash(&masked_key, &mask->range);
585b637e498SPravin B Shelar 	head = find_bucket(ti, hash);
58604b7d136STonghao Zhang 	(*n_mask_hit)++;
58704b7d136STonghao Zhang 
588*a2cfb96cSMadhuparna Bhowmik 	hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver],
589*a2cfb96cSMadhuparna Bhowmik 				lockdep_ovsl_is_held()) {
59074ed7ab9SJoe Stringer 		if (flow->mask == mask && flow->flow_table.hash == hash &&
591272c2cf8SJoe Stringer 		    flow_cmp_masked_key(flow, &masked_key, &mask->range))
592e6445719SPravin B Shelar 			return flow;
593e6445719SPravin B Shelar 	}
594e6445719SPravin B Shelar 	return NULL;
595e6445719SPravin B Shelar }
596e6445719SPravin B Shelar 
597a7f35e78STonghao Zhang /* Flow lookup does full lookup on flow table. It starts with
598a7f35e78STonghao Zhang  * mask from index passed in *index.
599a7f35e78STonghao Zhang  */
60004b7d136STonghao Zhang static struct sw_flow *flow_lookup(struct flow_table *tbl,
60104b7d136STonghao Zhang 				   struct table_instance *ti,
6024bc63b1bSTonghao Zhang 				   struct mask_array *ma,
6031bd7116fSAndy Zhou 				   const struct sw_flow_key *key,
6044bc63b1bSTonghao Zhang 				   u32 *n_mask_hit,
6054bc63b1bSTonghao Zhang 				   u32 *index)
606e6445719SPravin B Shelar {
607b637e498SPravin B Shelar 	struct sw_flow *flow;
60857f7d7b9STonghao Zhang 	struct sw_flow_mask *mask;
6094bc63b1bSTonghao Zhang 	int i;
610e6445719SPravin B Shelar 
6110a3e0137STonghao Zhang 	if (likely(*index < ma->max)) {
612a7f35e78STonghao Zhang 		mask = rcu_dereference_ovsl(ma->masks[*index]);
613a7f35e78STonghao Zhang 		if (mask) {
614a7f35e78STonghao Zhang 			flow = masked_flow_lookup(ti, key, mask, n_mask_hit);
615a7f35e78STonghao Zhang 			if (flow)
616a7f35e78STonghao Zhang 				return flow;
617a7f35e78STonghao Zhang 		}
618a7f35e78STonghao Zhang 	}
619a7f35e78STonghao Zhang 
6204bc63b1bSTonghao Zhang 	for (i = 0; i < ma->max; i++)  {
621a7f35e78STonghao Zhang 
622a7f35e78STonghao Zhang 		if (i == *index)
623a7f35e78STonghao Zhang 			continue;
6244bc63b1bSTonghao Zhang 
6254bc63b1bSTonghao Zhang 		mask = rcu_dereference_ovsl(ma->masks[i]);
6260a3e0137STonghao Zhang 		if (unlikely(!mask))
62757f7d7b9STonghao Zhang 			break;
628a7f35e78STonghao Zhang 
62904b7d136STonghao Zhang 		flow = masked_flow_lookup(ti, key, mask, n_mask_hit);
6304bc63b1bSTonghao Zhang 		if (flow) { /* Found */
6314bc63b1bSTonghao Zhang 			*index = i;
632b637e498SPravin B Shelar 			return flow;
633b637e498SPravin B Shelar 		}
6344bc63b1bSTonghao Zhang 	}
6354bc63b1bSTonghao Zhang 
636b637e498SPravin B Shelar 	return NULL;
637e6445719SPravin B Shelar }
638e6445719SPravin B Shelar 
63904b7d136STonghao Zhang /*
64004b7d136STonghao Zhang  * mask_cache maps flow to probable mask. This cache is not tightly
64104b7d136STonghao Zhang  * coupled cache, It means updates to  mask list can result in inconsistent
64204b7d136STonghao Zhang  * cache entry in mask cache.
64304b7d136STonghao Zhang  * This is per cpu cache and is divided in MC_HASH_SEGS segments.
64404b7d136STonghao Zhang  * In case of a hash collision the entry is hashed in next segment.
64504b7d136STonghao Zhang  * */
64604b7d136STonghao Zhang struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl,
64704b7d136STonghao Zhang 					  const struct sw_flow_key *key,
64804b7d136STonghao Zhang 					  u32 skb_hash,
64904b7d136STonghao Zhang 					  u32 *n_mask_hit)
65004b7d136STonghao Zhang {
651a7f35e78STonghao Zhang 	struct mask_array *ma = rcu_dereference(tbl->mask_array);
652a7f35e78STonghao Zhang 	struct table_instance *ti = rcu_dereference(tbl->ti);
653a7f35e78STonghao Zhang 	struct mask_cache_entry *entries, *ce;
65404b7d136STonghao Zhang 	struct sw_flow *flow;
655a7f35e78STonghao Zhang 	u32 hash;
65604b7d136STonghao Zhang 	int seg;
65704b7d136STonghao Zhang 
65804b7d136STonghao Zhang 	*n_mask_hit = 0;
6594bc63b1bSTonghao Zhang 	if (unlikely(!skb_hash)) {
660a7f35e78STonghao Zhang 		u32 mask_index = 0;
6614bc63b1bSTonghao Zhang 
6624bc63b1bSTonghao Zhang 		return flow_lookup(tbl, ti, ma, key, n_mask_hit, &mask_index);
6634bc63b1bSTonghao Zhang 	}
66404b7d136STonghao Zhang 
665a7f35e78STonghao Zhang 	/* Pre and post recirulation flows usually have the same skb_hash
666a7f35e78STonghao Zhang 	 * value. To avoid hash collisions, rehash the 'skb_hash' with
667a7f35e78STonghao Zhang 	 * 'recirc_id'.  */
668a7f35e78STonghao Zhang 	if (key->recirc_id)
669a7f35e78STonghao Zhang 		skb_hash = jhash_1word(skb_hash, key->recirc_id);
670a7f35e78STonghao Zhang 
671a7f35e78STonghao Zhang 	ce = NULL;
672a7f35e78STonghao Zhang 	hash = skb_hash;
67304b7d136STonghao Zhang 	entries = this_cpu_ptr(tbl->mask_cache);
67404b7d136STonghao Zhang 
675a7f35e78STonghao Zhang 	/* Find the cache entry 'ce' to operate on. */
67604b7d136STonghao Zhang 	for (seg = 0; seg < MC_HASH_SEGS; seg++) {
677a7f35e78STonghao Zhang 		int index = hash & (MC_HASH_ENTRIES - 1);
678a7f35e78STonghao Zhang 		struct mask_cache_entry *e;
67904b7d136STonghao Zhang 
680a7f35e78STonghao Zhang 		e = &entries[index];
681a7f35e78STonghao Zhang 		if (e->skb_hash == skb_hash) {
682a7f35e78STonghao Zhang 			flow = flow_lookup(tbl, ti, ma, key, n_mask_hit,
683a7f35e78STonghao Zhang 					   &e->mask_index);
684a7f35e78STonghao Zhang 			if (!flow)
685a7f35e78STonghao Zhang 				e->skb_hash = 0;
68604b7d136STonghao Zhang 			return flow;
68704b7d136STonghao Zhang 		}
68804b7d136STonghao Zhang 
689a7f35e78STonghao Zhang 		if (!ce || e->skb_hash < ce->skb_hash)
690a7f35e78STonghao Zhang 			ce = e;  /* A better replacement cache candidate. */
69104b7d136STonghao Zhang 
69204b7d136STonghao Zhang 		hash >>= MC_HASH_SHIFT;
69304b7d136STonghao Zhang 	}
69404b7d136STonghao Zhang 
695a7f35e78STonghao Zhang 	/* Cache miss, do full lookup. */
696a7f35e78STonghao Zhang 	flow = flow_lookup(tbl, ti, ma, key, n_mask_hit, &ce->mask_index);
6974bc63b1bSTonghao Zhang 	if (flow)
698a7f35e78STonghao Zhang 		ce->skb_hash = skb_hash;
69904b7d136STonghao Zhang 
70004b7d136STonghao Zhang 	return flow;
70104b7d136STonghao Zhang }
70204b7d136STonghao Zhang 
7035bb50632SAndy Zhou struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
7045bb50632SAndy Zhou 				    const struct sw_flow_key *key)
7055bb50632SAndy Zhou {
70604b7d136STonghao Zhang 	struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
7074bc63b1bSTonghao Zhang 	struct mask_array *ma = rcu_dereference_ovsl(tbl->mask_array);
7084bc63b1bSTonghao Zhang 	u32 __always_unused n_mask_hit;
709a7f35e78STonghao Zhang 	u32 index = 0;
7104bc63b1bSTonghao Zhang 
7114bc63b1bSTonghao Zhang 	return flow_lookup(tbl, ti, ma, key, &n_mask_hit, &index);
7125bb50632SAndy Zhou }
7135bb50632SAndy Zhou 
7144a46b24eSAlex Wang struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
71512eb18f7SThomas Graf 					  const struct sw_flow_match *match)
7164a46b24eSAlex Wang {
7174bc63b1bSTonghao Zhang 	struct mask_array *ma = ovsl_dereference(tbl->mask_array);
7184bc63b1bSTonghao Zhang 	int i;
7194a46b24eSAlex Wang 
7204a46b24eSAlex Wang 	/* Always called under ovs-mutex. */
7214bc63b1bSTonghao Zhang 	for (i = 0; i < ma->max; i++) {
7224bc63b1bSTonghao Zhang 		struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
7234bc63b1bSTonghao Zhang 		u32 __always_unused n_mask_hit;
7244bc63b1bSTonghao Zhang 		struct sw_flow_mask *mask;
7254bc63b1bSTonghao Zhang 		struct sw_flow *flow;
7264bc63b1bSTonghao Zhang 
7274bc63b1bSTonghao Zhang 		mask = ovsl_dereference(ma->masks[i]);
7284bc63b1bSTonghao Zhang 		if (!mask)
7294bc63b1bSTonghao Zhang 			continue;
7304bc63b1bSTonghao Zhang 
73104b7d136STonghao Zhang 		flow = masked_flow_lookup(ti, match->key, mask, &n_mask_hit);
73274ed7ab9SJoe Stringer 		if (flow && ovs_identifier_is_key(&flow->id) &&
7334bc63b1bSTonghao Zhang 		    ovs_flow_cmp_unmasked_key(flow, match)) {
73474ed7ab9SJoe Stringer 			return flow;
73574ed7ab9SJoe Stringer 		}
7364bc63b1bSTonghao Zhang 	}
7374bc63b1bSTonghao Zhang 
73874ed7ab9SJoe Stringer 	return NULL;
73974ed7ab9SJoe Stringer }
74074ed7ab9SJoe Stringer 
74174ed7ab9SJoe Stringer static u32 ufid_hash(const struct sw_flow_id *sfid)
74274ed7ab9SJoe Stringer {
74374ed7ab9SJoe Stringer 	return jhash(sfid->ufid, sfid->ufid_len, 0);
74474ed7ab9SJoe Stringer }
74574ed7ab9SJoe Stringer 
74674ed7ab9SJoe Stringer static bool ovs_flow_cmp_ufid(const struct sw_flow *flow,
74774ed7ab9SJoe Stringer 			      const struct sw_flow_id *sfid)
74874ed7ab9SJoe Stringer {
74974ed7ab9SJoe Stringer 	if (flow->id.ufid_len != sfid->ufid_len)
75074ed7ab9SJoe Stringer 		return false;
75174ed7ab9SJoe Stringer 
75274ed7ab9SJoe Stringer 	return !memcmp(flow->id.ufid, sfid->ufid, sfid->ufid_len);
75374ed7ab9SJoe Stringer }
75474ed7ab9SJoe Stringer 
75574ed7ab9SJoe Stringer bool ovs_flow_cmp(const struct sw_flow *flow, const struct sw_flow_match *match)
75674ed7ab9SJoe Stringer {
75774ed7ab9SJoe Stringer 	if (ovs_identifier_is_ufid(&flow->id))
75874ed7ab9SJoe Stringer 		return flow_cmp_masked_key(flow, match->key, &match->range);
75974ed7ab9SJoe Stringer 
76074ed7ab9SJoe Stringer 	return ovs_flow_cmp_unmasked_key(flow, match);
76174ed7ab9SJoe Stringer }
76274ed7ab9SJoe Stringer 
76374ed7ab9SJoe Stringer struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *tbl,
76474ed7ab9SJoe Stringer 					 const struct sw_flow_id *ufid)
76574ed7ab9SJoe Stringer {
76674ed7ab9SJoe Stringer 	struct table_instance *ti = rcu_dereference_ovsl(tbl->ufid_ti);
76774ed7ab9SJoe Stringer 	struct sw_flow *flow;
76874ed7ab9SJoe Stringer 	struct hlist_head *head;
76974ed7ab9SJoe Stringer 	u32 hash;
77074ed7ab9SJoe Stringer 
77174ed7ab9SJoe Stringer 	hash = ufid_hash(ufid);
77274ed7ab9SJoe Stringer 	head = find_bucket(ti, hash);
773*a2cfb96cSMadhuparna Bhowmik 	hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver],
774*a2cfb96cSMadhuparna Bhowmik 				lockdep_ovsl_is_held()) {
77574ed7ab9SJoe Stringer 		if (flow->ufid_table.hash == hash &&
77674ed7ab9SJoe Stringer 		    ovs_flow_cmp_ufid(flow, ufid))
7774a46b24eSAlex Wang 			return flow;
7784a46b24eSAlex Wang 	}
7794a46b24eSAlex Wang 	return NULL;
7804a46b24eSAlex Wang }
7814a46b24eSAlex Wang 
7821bd7116fSAndy Zhou int ovs_flow_tbl_num_masks(const struct flow_table *table)
7831bd7116fSAndy Zhou {
7844bc63b1bSTonghao Zhang 	struct mask_array *ma = rcu_dereference_ovsl(table->mask_array);
78557f7d7b9STonghao Zhang 	return READ_ONCE(ma->count);
7861bd7116fSAndy Zhou }
7871bd7116fSAndy Zhou 
78874ed7ab9SJoe Stringer static struct table_instance *table_instance_expand(struct table_instance *ti,
78974ed7ab9SJoe Stringer 						    bool ufid)
790b637e498SPravin B Shelar {
79174ed7ab9SJoe Stringer 	return table_instance_rehash(ti, ti->n_buckets * 2, ufid);
792e6445719SPravin B Shelar }
793e6445719SPravin B Shelar 
79456c19868SJarno Rajahalme /* Must be called with OVS mutex held. */
795e6445719SPravin B Shelar void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
796e6445719SPravin B Shelar {
797b637e498SPravin B Shelar 	struct table_instance *ti = ovsl_dereference(table->ti);
79874ed7ab9SJoe Stringer 	struct table_instance *ufid_ti = ovsl_dereference(table->ufid_ti);
799b637e498SPravin B Shelar 
800e6445719SPravin B Shelar 	BUG_ON(table->count == 0);
80150b0e61bSTonghao Zhang 	table_instance_flow_free(table, ti, ufid_ti, flow, true);
802e6445719SPravin B Shelar }
803e6445719SPravin B Shelar 
804618ed0c8SPravin B Shelar static struct sw_flow_mask *mask_alloc(void)
805e6445719SPravin B Shelar {
806e6445719SPravin B Shelar 	struct sw_flow_mask *mask;
807e6445719SPravin B Shelar 
808e6445719SPravin B Shelar 	mask = kmalloc(sizeof(*mask), GFP_KERNEL);
809e6445719SPravin B Shelar 	if (mask)
810e80857ccSAndy Zhou 		mask->ref_count = 1;
811e6445719SPravin B Shelar 
812e6445719SPravin B Shelar 	return mask;
813e6445719SPravin B Shelar }
814e6445719SPravin B Shelar 
815e6445719SPravin B Shelar static bool mask_equal(const struct sw_flow_mask *a,
816e6445719SPravin B Shelar 		       const struct sw_flow_mask *b)
817e6445719SPravin B Shelar {
8187085130bSDaniele Di Proietto 	const u8 *a_ = (const u8 *)&a->key + a->range.start;
8197085130bSDaniele Di Proietto 	const u8 *b_ = (const u8 *)&b->key + b->range.start;
820e6445719SPravin B Shelar 
821e6445719SPravin B Shelar 	return  (a->range.end == b->range.end)
822e6445719SPravin B Shelar 		&& (a->range.start == b->range.start)
823e6445719SPravin B Shelar 		&& (memcmp(a_, b_, range_n_bytes(&a->range)) == 0);
824e6445719SPravin B Shelar }
825e6445719SPravin B Shelar 
826618ed0c8SPravin B Shelar static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl,
827e6445719SPravin B Shelar 					   const struct sw_flow_mask *mask)
828e6445719SPravin B Shelar {
8294bc63b1bSTonghao Zhang 	struct mask_array *ma;
8304bc63b1bSTonghao Zhang 	int i;
831e6445719SPravin B Shelar 
8324bc63b1bSTonghao Zhang 	ma = ovsl_dereference(tbl->mask_array);
8334bc63b1bSTonghao Zhang 	for (i = 0; i < ma->max; i++) {
8344bc63b1bSTonghao Zhang 		struct sw_flow_mask *t;
8354bc63b1bSTonghao Zhang 		t = ovsl_dereference(ma->masks[i]);
8364bc63b1bSTonghao Zhang 
8374bc63b1bSTonghao Zhang 		if (t && mask_equal(mask, t))
8384bc63b1bSTonghao Zhang 			return t;
839e6445719SPravin B Shelar 	}
840e6445719SPravin B Shelar 
841e6445719SPravin B Shelar 	return NULL;
842e6445719SPravin B Shelar }
843e6445719SPravin B Shelar 
844d1211908SBen Pfaff /* Add 'mask' into the mask list, if it is not already there. */
845618ed0c8SPravin B Shelar static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
84612eb18f7SThomas Graf 			    const struct sw_flow_mask *new)
847e6445719SPravin B Shelar {
848618ed0c8SPravin B Shelar 	struct sw_flow_mask *mask;
8494bc63b1bSTonghao Zhang 
850618ed0c8SPravin B Shelar 	mask = flow_mask_find(tbl, new);
851618ed0c8SPravin B Shelar 	if (!mask) {
852618ed0c8SPravin B Shelar 		/* Allocate a new mask if none exsits. */
853618ed0c8SPravin B Shelar 		mask = mask_alloc();
854618ed0c8SPravin B Shelar 		if (!mask)
855618ed0c8SPravin B Shelar 			return -ENOMEM;
856618ed0c8SPravin B Shelar 		mask->key = new->key;
857618ed0c8SPravin B Shelar 		mask->range = new->range;
8584bc63b1bSTonghao Zhang 
8594bc63b1bSTonghao Zhang 		/* Add mask to mask-list. */
86057f7d7b9STonghao Zhang 		if (tbl_mask_array_add_mask(tbl, mask)) {
8614bc63b1bSTonghao Zhang 			kfree(mask);
86257f7d7b9STonghao Zhang 			return -ENOMEM;
8634bc63b1bSTonghao Zhang 		}
864e80857ccSAndy Zhou 	} else {
865e80857ccSAndy Zhou 		BUG_ON(!mask->ref_count);
866e80857ccSAndy Zhou 		mask->ref_count++;
867e6445719SPravin B Shelar 	}
868e6445719SPravin B Shelar 
869618ed0c8SPravin B Shelar 	flow->mask = mask;
870618ed0c8SPravin B Shelar 	return 0;
871618ed0c8SPravin B Shelar }
872618ed0c8SPravin B Shelar 
87356c19868SJarno Rajahalme /* Must be called with OVS mutex held. */
874d29ab6f8SJoe Stringer static void flow_key_insert(struct flow_table *table, struct sw_flow *flow)
875618ed0c8SPravin B Shelar {
876618ed0c8SPravin B Shelar 	struct table_instance *new_ti = NULL;
877618ed0c8SPravin B Shelar 	struct table_instance *ti;
878618ed0c8SPravin B Shelar 
87974ed7ab9SJoe Stringer 	flow->flow_table.hash = flow_hash(&flow->key, &flow->mask->range);
880618ed0c8SPravin B Shelar 	ti = ovsl_dereference(table->ti);
881618ed0c8SPravin B Shelar 	table_instance_insert(ti, flow);
882618ed0c8SPravin B Shelar 	table->count++;
883618ed0c8SPravin B Shelar 
884618ed0c8SPravin B Shelar 	/* Expand table, if necessary, to make room. */
885618ed0c8SPravin B Shelar 	if (table->count > ti->n_buckets)
88674ed7ab9SJoe Stringer 		new_ti = table_instance_expand(ti, false);
887618ed0c8SPravin B Shelar 	else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL))
88874ed7ab9SJoe Stringer 		new_ti = table_instance_rehash(ti, ti->n_buckets, false);
889618ed0c8SPravin B Shelar 
890618ed0c8SPravin B Shelar 	if (new_ti) {
891618ed0c8SPravin B Shelar 		rcu_assign_pointer(table->ti, new_ti);
89274ed7ab9SJoe Stringer 		call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
893618ed0c8SPravin B Shelar 		table->last_rehash = jiffies;
894618ed0c8SPravin B Shelar 	}
895d29ab6f8SJoe Stringer }
896d29ab6f8SJoe Stringer 
897d29ab6f8SJoe Stringer /* Must be called with OVS mutex held. */
89874ed7ab9SJoe Stringer static void flow_ufid_insert(struct flow_table *table, struct sw_flow *flow)
89974ed7ab9SJoe Stringer {
90074ed7ab9SJoe Stringer 	struct table_instance *ti;
90174ed7ab9SJoe Stringer 
90274ed7ab9SJoe Stringer 	flow->ufid_table.hash = ufid_hash(&flow->id);
90374ed7ab9SJoe Stringer 	ti = ovsl_dereference(table->ufid_ti);
90474ed7ab9SJoe Stringer 	ufid_table_instance_insert(ti, flow);
90574ed7ab9SJoe Stringer 	table->ufid_count++;
90674ed7ab9SJoe Stringer 
90774ed7ab9SJoe Stringer 	/* Expand table, if necessary, to make room. */
90874ed7ab9SJoe Stringer 	if (table->ufid_count > ti->n_buckets) {
90974ed7ab9SJoe Stringer 		struct table_instance *new_ti;
91074ed7ab9SJoe Stringer 
91174ed7ab9SJoe Stringer 		new_ti = table_instance_expand(ti, true);
91274ed7ab9SJoe Stringer 		if (new_ti) {
91374ed7ab9SJoe Stringer 			rcu_assign_pointer(table->ufid_ti, new_ti);
91474ed7ab9SJoe Stringer 			call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
91574ed7ab9SJoe Stringer 		}
91674ed7ab9SJoe Stringer 	}
91774ed7ab9SJoe Stringer }
91874ed7ab9SJoe Stringer 
91974ed7ab9SJoe Stringer /* Must be called with OVS mutex held. */
920d29ab6f8SJoe Stringer int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
921d29ab6f8SJoe Stringer 			const struct sw_flow_mask *mask)
922d29ab6f8SJoe Stringer {
923d29ab6f8SJoe Stringer 	int err;
924d29ab6f8SJoe Stringer 
925d29ab6f8SJoe Stringer 	err = flow_mask_insert(table, flow, mask);
926d29ab6f8SJoe Stringer 	if (err)
927d29ab6f8SJoe Stringer 		return err;
928d29ab6f8SJoe Stringer 	flow_key_insert(table, flow);
92974ed7ab9SJoe Stringer 	if (ovs_identifier_is_ufid(&flow->id))
93074ed7ab9SJoe Stringer 		flow_ufid_insert(table, flow);
931d29ab6f8SJoe Stringer 
932618ed0c8SPravin B Shelar 	return 0;
933618ed0c8SPravin B Shelar }
934618ed0c8SPravin B Shelar 
935e6445719SPravin B Shelar /* Initializes the flow module.
936e6445719SPravin B Shelar  * Returns zero if successful or a negative error code. */
937e6445719SPravin B Shelar int ovs_flow_init(void)
938e6445719SPravin B Shelar {
939e6445719SPravin B Shelar 	BUILD_BUG_ON(__alignof__(struct sw_flow_key) % __alignof__(long));
940e6445719SPravin B Shelar 	BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long));
941e6445719SPravin B Shelar 
94263e7959cSJarno Rajahalme 	flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow)
943db74a333SThadeu Lima de Souza Cascardo 				       + (nr_cpu_ids
944aef833c5SPablo Neira Ayuso 					  * sizeof(struct sw_flow_stats *)),
94563e7959cSJarno Rajahalme 				       0, 0, NULL);
946e6445719SPravin B Shelar 	if (flow_cache == NULL)
947e6445719SPravin B Shelar 		return -ENOMEM;
948e6445719SPravin B Shelar 
94963e7959cSJarno Rajahalme 	flow_stats_cache
950aef833c5SPablo Neira Ayuso 		= kmem_cache_create("sw_flow_stats", sizeof(struct sw_flow_stats),
95163e7959cSJarno Rajahalme 				    0, SLAB_HWCACHE_ALIGN, NULL);
95263e7959cSJarno Rajahalme 	if (flow_stats_cache == NULL) {
95363e7959cSJarno Rajahalme 		kmem_cache_destroy(flow_cache);
95463e7959cSJarno Rajahalme 		flow_cache = NULL;
95563e7959cSJarno Rajahalme 		return -ENOMEM;
95663e7959cSJarno Rajahalme 	}
95763e7959cSJarno Rajahalme 
958e6445719SPravin B Shelar 	return 0;
959e6445719SPravin B Shelar }
960e6445719SPravin B Shelar 
961e6445719SPravin B Shelar /* Uninitializes the flow module. */
962e6445719SPravin B Shelar void ovs_flow_exit(void)
963e6445719SPravin B Shelar {
96463e7959cSJarno Rajahalme 	kmem_cache_destroy(flow_stats_cache);
965e6445719SPravin B Shelar 	kmem_cache_destroy(flow_cache);
966e6445719SPravin B Shelar }
967