xref: /openbmc/linux/net/openvswitch/flow_table.c (revision 64948427a63f49dd0ce403388d232f22cc1971a8)
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)
465*64948427STonghao Zhang 			hlist_for_each_entry_rcu(flow, head,
466*64948427STonghao Zhang 						 ufid_table.node[old_ver],
467*64948427STonghao Zhang 						 lockdep_ovsl_is_held())
46874ed7ab9SJoe Stringer 				ufid_table_instance_insert(new, flow);
46974ed7ab9SJoe Stringer 		else
470*64948427STonghao Zhang 			hlist_for_each_entry_rcu(flow, head,
471*64948427STonghao Zhang 						 flow_table.node[old_ver],
472*64948427STonghao Zhang 						 lockdep_ovsl_is_held())
473b637e498SPravin B Shelar 				table_instance_insert(new, flow);
474e6445719SPravin B Shelar 	}
475e6445719SPravin B Shelar 
476e6445719SPravin B Shelar 	old->keep_flows = true;
477e6445719SPravin B Shelar }
478e6445719SPravin B Shelar 
479b637e498SPravin B Shelar static struct table_instance *table_instance_rehash(struct table_instance *ti,
48074ed7ab9SJoe Stringer 						    int n_buckets, bool ufid)
481e6445719SPravin B Shelar {
482b637e498SPravin B Shelar 	struct table_instance *new_ti;
483e6445719SPravin B Shelar 
484b637e498SPravin B Shelar 	new_ti = table_instance_alloc(n_buckets);
485b637e498SPravin B Shelar 	if (!new_ti)
486618ed0c8SPravin B Shelar 		return NULL;
487e6445719SPravin B Shelar 
48874ed7ab9SJoe Stringer 	flow_table_copy_flows(ti, new_ti, ufid);
489e6445719SPravin B Shelar 
490b637e498SPravin B Shelar 	return new_ti;
491e6445719SPravin B Shelar }
492e6445719SPravin B Shelar 
493b637e498SPravin B Shelar int ovs_flow_tbl_flush(struct flow_table *flow_table)
494e6445719SPravin B Shelar {
49574ed7ab9SJoe Stringer 	struct table_instance *old_ti, *new_ti;
49674ed7ab9SJoe Stringer 	struct table_instance *old_ufid_ti, *new_ufid_ti;
497e6445719SPravin B Shelar 
498b637e498SPravin B Shelar 	new_ti = table_instance_alloc(TBL_MIN_BUCKETS);
499b637e498SPravin B Shelar 	if (!new_ti)
500b637e498SPravin B Shelar 		return -ENOMEM;
50174ed7ab9SJoe Stringer 	new_ufid_ti = table_instance_alloc(TBL_MIN_BUCKETS);
50274ed7ab9SJoe Stringer 	if (!new_ufid_ti)
50374ed7ab9SJoe Stringer 		goto err_free_ti;
50474ed7ab9SJoe Stringer 
50574ed7ab9SJoe Stringer 	old_ti = ovsl_dereference(flow_table->ti);
50674ed7ab9SJoe Stringer 	old_ufid_ti = ovsl_dereference(flow_table->ufid_ti);
507b637e498SPravin B Shelar 
508b637e498SPravin B Shelar 	rcu_assign_pointer(flow_table->ti, new_ti);
50974ed7ab9SJoe Stringer 	rcu_assign_pointer(flow_table->ufid_ti, new_ufid_ti);
510b637e498SPravin B Shelar 	flow_table->last_rehash = jiffies;
511b637e498SPravin B Shelar 	flow_table->count = 0;
51274ed7ab9SJoe Stringer 	flow_table->ufid_count = 0;
513b637e498SPravin B Shelar 
51450b0e61bSTonghao Zhang 	table_instance_destroy(flow_table, old_ti, old_ufid_ti, true);
515b637e498SPravin B Shelar 	return 0;
51674ed7ab9SJoe Stringer 
51774ed7ab9SJoe Stringer err_free_ti:
51874ed7ab9SJoe Stringer 	__table_instance_destroy(new_ti);
51974ed7ab9SJoe Stringer 	return -ENOMEM;
520e6445719SPravin B Shelar }
521e6445719SPravin B Shelar 
522272c2cf8SJoe Stringer static u32 flow_hash(const struct sw_flow_key *key,
523272c2cf8SJoe Stringer 		     const struct sw_flow_key_range *range)
524e6445719SPravin B Shelar {
525515b65a4STonghao Zhang 	const u32 *hash_key = (const u32 *)((const u8 *)key + range->start);
526e6445719SPravin B Shelar 
527e6445719SPravin B Shelar 	/* Make sure number of hash bytes are multiple of u32. */
528515b65a4STonghao Zhang 	int hash_u32s = range_n_bytes(range) >> 2;
529e6445719SPravin B Shelar 
53087545899SDaniel Borkmann 	return jhash2(hash_key, hash_u32s, 0);
531e6445719SPravin B Shelar }
532e6445719SPravin B Shelar 
533e6445719SPravin B Shelar static int flow_key_start(const struct sw_flow_key *key)
534e6445719SPravin B Shelar {
53500a93babSJiri Benc 	if (key->tun_proto)
536e6445719SPravin B Shelar 		return 0;
537e6445719SPravin B Shelar 	else
538e6445719SPravin B Shelar 		return rounddown(offsetof(struct sw_flow_key, phy),
539e6445719SPravin B Shelar 					  sizeof(long));
540e6445719SPravin B Shelar }
541e6445719SPravin B Shelar 
542e6445719SPravin B Shelar static bool cmp_key(const struct sw_flow_key *key1,
543e6445719SPravin B Shelar 		    const struct sw_flow_key *key2,
544e6445719SPravin B Shelar 		    int key_start, int key_end)
545e6445719SPravin B Shelar {
5467085130bSDaniele Di Proietto 	const long *cp1 = (const long *)((const u8 *)key1 + key_start);
5477085130bSDaniele Di Proietto 	const long *cp2 = (const long *)((const u8 *)key2 + key_start);
548e6445719SPravin B Shelar 	long diffs = 0;
549e6445719SPravin B Shelar 	int i;
550e6445719SPravin B Shelar 
551e6445719SPravin B Shelar 	for (i = key_start; i < key_end;  i += sizeof(long))
552e6445719SPravin B Shelar 		diffs |= *cp1++ ^ *cp2++;
553e6445719SPravin B Shelar 
554e6445719SPravin B Shelar 	return diffs == 0;
555e6445719SPravin B Shelar }
556e6445719SPravin B Shelar 
557e6445719SPravin B Shelar static bool flow_cmp_masked_key(const struct sw_flow *flow,
558e6445719SPravin B Shelar 				const struct sw_flow_key *key,
559272c2cf8SJoe Stringer 				const struct sw_flow_key_range *range)
560e6445719SPravin B Shelar {
561272c2cf8SJoe Stringer 	return cmp_key(&flow->key, key, range->start, range->end);
562e6445719SPravin B Shelar }
563e6445719SPravin B Shelar 
56474ed7ab9SJoe Stringer static bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
56512eb18f7SThomas Graf 				      const struct sw_flow_match *match)
566e6445719SPravin B Shelar {
567e6445719SPravin B Shelar 	struct sw_flow_key *key = match->key;
568e6445719SPravin B Shelar 	int key_start = flow_key_start(key);
569e6445719SPravin B Shelar 	int key_end = match->range.end;
570e6445719SPravin B Shelar 
57174ed7ab9SJoe Stringer 	BUG_ON(ovs_identifier_is_ufid(&flow->id));
57274ed7ab9SJoe Stringer 	return cmp_key(flow->id.unmasked_key, key, key_start, key_end);
573e6445719SPravin B Shelar }
574e6445719SPravin B Shelar 
575b637e498SPravin B Shelar static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
576e6445719SPravin B Shelar 					  const struct sw_flow_key *unmasked,
57704b7d136STonghao Zhang 					  const struct sw_flow_mask *mask,
57804b7d136STonghao Zhang 					  u32 *n_mask_hit)
579e6445719SPravin B Shelar {
580e6445719SPravin B Shelar 	struct sw_flow *flow;
581e6445719SPravin B Shelar 	struct hlist_head *head;
582e6445719SPravin B Shelar 	u32 hash;
583e6445719SPravin B Shelar 	struct sw_flow_key masked_key;
584e6445719SPravin B Shelar 
585ae5f2fb1SJesse Gross 	ovs_flow_mask_key(&masked_key, unmasked, false, mask);
586272c2cf8SJoe Stringer 	hash = flow_hash(&masked_key, &mask->range);
587b637e498SPravin B Shelar 	head = find_bucket(ti, hash);
58804b7d136STonghao Zhang 	(*n_mask_hit)++;
58904b7d136STonghao Zhang 
590a2cfb96cSMadhuparna Bhowmik 	hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver],
591a2cfb96cSMadhuparna Bhowmik 				lockdep_ovsl_is_held()) {
59274ed7ab9SJoe Stringer 		if (flow->mask == mask && flow->flow_table.hash == hash &&
593272c2cf8SJoe Stringer 		    flow_cmp_masked_key(flow, &masked_key, &mask->range))
594e6445719SPravin B Shelar 			return flow;
595e6445719SPravin B Shelar 	}
596e6445719SPravin B Shelar 	return NULL;
597e6445719SPravin B Shelar }
598e6445719SPravin B Shelar 
599a7f35e78STonghao Zhang /* Flow lookup does full lookup on flow table. It starts with
600a7f35e78STonghao Zhang  * mask from index passed in *index.
601a7f35e78STonghao Zhang  */
60204b7d136STonghao Zhang static struct sw_flow *flow_lookup(struct flow_table *tbl,
60304b7d136STonghao Zhang 				   struct table_instance *ti,
6044bc63b1bSTonghao Zhang 				   struct mask_array *ma,
6051bd7116fSAndy Zhou 				   const struct sw_flow_key *key,
6064bc63b1bSTonghao Zhang 				   u32 *n_mask_hit,
6074bc63b1bSTonghao Zhang 				   u32 *index)
608e6445719SPravin B Shelar {
609b637e498SPravin B Shelar 	struct sw_flow *flow;
61057f7d7b9STonghao Zhang 	struct sw_flow_mask *mask;
6114bc63b1bSTonghao Zhang 	int i;
612e6445719SPravin B Shelar 
6130a3e0137STonghao Zhang 	if (likely(*index < ma->max)) {
614a7f35e78STonghao Zhang 		mask = rcu_dereference_ovsl(ma->masks[*index]);
615a7f35e78STonghao Zhang 		if (mask) {
616a7f35e78STonghao Zhang 			flow = masked_flow_lookup(ti, key, mask, n_mask_hit);
617a7f35e78STonghao Zhang 			if (flow)
618a7f35e78STonghao Zhang 				return flow;
619a7f35e78STonghao Zhang 		}
620a7f35e78STonghao Zhang 	}
621a7f35e78STonghao Zhang 
6224bc63b1bSTonghao Zhang 	for (i = 0; i < ma->max; i++)  {
623a7f35e78STonghao Zhang 
624a7f35e78STonghao Zhang 		if (i == *index)
625a7f35e78STonghao Zhang 			continue;
6264bc63b1bSTonghao Zhang 
6274bc63b1bSTonghao Zhang 		mask = rcu_dereference_ovsl(ma->masks[i]);
6280a3e0137STonghao Zhang 		if (unlikely(!mask))
62957f7d7b9STonghao Zhang 			break;
630a7f35e78STonghao Zhang 
63104b7d136STonghao Zhang 		flow = masked_flow_lookup(ti, key, mask, n_mask_hit);
6324bc63b1bSTonghao Zhang 		if (flow) { /* Found */
6334bc63b1bSTonghao Zhang 			*index = i;
634b637e498SPravin B Shelar 			return flow;
635b637e498SPravin B Shelar 		}
6364bc63b1bSTonghao Zhang 	}
6374bc63b1bSTonghao Zhang 
638b637e498SPravin B Shelar 	return NULL;
639e6445719SPravin B Shelar }
640e6445719SPravin B Shelar 
64104b7d136STonghao Zhang /*
64204b7d136STonghao Zhang  * mask_cache maps flow to probable mask. This cache is not tightly
64304b7d136STonghao Zhang  * coupled cache, It means updates to  mask list can result in inconsistent
64404b7d136STonghao Zhang  * cache entry in mask cache.
64504b7d136STonghao Zhang  * This is per cpu cache and is divided in MC_HASH_SEGS segments.
64604b7d136STonghao Zhang  * In case of a hash collision the entry is hashed in next segment.
64704b7d136STonghao Zhang  * */
64804b7d136STonghao Zhang struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl,
64904b7d136STonghao Zhang 					  const struct sw_flow_key *key,
65004b7d136STonghao Zhang 					  u32 skb_hash,
65104b7d136STonghao Zhang 					  u32 *n_mask_hit)
65204b7d136STonghao Zhang {
653a7f35e78STonghao Zhang 	struct mask_array *ma = rcu_dereference(tbl->mask_array);
654a7f35e78STonghao Zhang 	struct table_instance *ti = rcu_dereference(tbl->ti);
655a7f35e78STonghao Zhang 	struct mask_cache_entry *entries, *ce;
65604b7d136STonghao Zhang 	struct sw_flow *flow;
657a7f35e78STonghao Zhang 	u32 hash;
65804b7d136STonghao Zhang 	int seg;
65904b7d136STonghao Zhang 
66004b7d136STonghao Zhang 	*n_mask_hit = 0;
6614bc63b1bSTonghao Zhang 	if (unlikely(!skb_hash)) {
662a7f35e78STonghao Zhang 		u32 mask_index = 0;
6634bc63b1bSTonghao Zhang 
6644bc63b1bSTonghao Zhang 		return flow_lookup(tbl, ti, ma, key, n_mask_hit, &mask_index);
6654bc63b1bSTonghao Zhang 	}
66604b7d136STonghao Zhang 
667a7f35e78STonghao Zhang 	/* Pre and post recirulation flows usually have the same skb_hash
668a7f35e78STonghao Zhang 	 * value. To avoid hash collisions, rehash the 'skb_hash' with
669a7f35e78STonghao Zhang 	 * 'recirc_id'.  */
670a7f35e78STonghao Zhang 	if (key->recirc_id)
671a7f35e78STonghao Zhang 		skb_hash = jhash_1word(skb_hash, key->recirc_id);
672a7f35e78STonghao Zhang 
673a7f35e78STonghao Zhang 	ce = NULL;
674a7f35e78STonghao Zhang 	hash = skb_hash;
67504b7d136STonghao Zhang 	entries = this_cpu_ptr(tbl->mask_cache);
67604b7d136STonghao Zhang 
677a7f35e78STonghao Zhang 	/* Find the cache entry 'ce' to operate on. */
67804b7d136STonghao Zhang 	for (seg = 0; seg < MC_HASH_SEGS; seg++) {
679a7f35e78STonghao Zhang 		int index = hash & (MC_HASH_ENTRIES - 1);
680a7f35e78STonghao Zhang 		struct mask_cache_entry *e;
68104b7d136STonghao Zhang 
682a7f35e78STonghao Zhang 		e = &entries[index];
683a7f35e78STonghao Zhang 		if (e->skb_hash == skb_hash) {
684a7f35e78STonghao Zhang 			flow = flow_lookup(tbl, ti, ma, key, n_mask_hit,
685a7f35e78STonghao Zhang 					   &e->mask_index);
686a7f35e78STonghao Zhang 			if (!flow)
687a7f35e78STonghao Zhang 				e->skb_hash = 0;
68804b7d136STonghao Zhang 			return flow;
68904b7d136STonghao Zhang 		}
69004b7d136STonghao Zhang 
691a7f35e78STonghao Zhang 		if (!ce || e->skb_hash < ce->skb_hash)
692a7f35e78STonghao Zhang 			ce = e;  /* A better replacement cache candidate. */
69304b7d136STonghao Zhang 
69404b7d136STonghao Zhang 		hash >>= MC_HASH_SHIFT;
69504b7d136STonghao Zhang 	}
69604b7d136STonghao Zhang 
697a7f35e78STonghao Zhang 	/* Cache miss, do full lookup. */
698a7f35e78STonghao Zhang 	flow = flow_lookup(tbl, ti, ma, key, n_mask_hit, &ce->mask_index);
6994bc63b1bSTonghao Zhang 	if (flow)
700a7f35e78STonghao Zhang 		ce->skb_hash = skb_hash;
70104b7d136STonghao Zhang 
70204b7d136STonghao Zhang 	return flow;
70304b7d136STonghao Zhang }
70404b7d136STonghao Zhang 
7055bb50632SAndy Zhou struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
7065bb50632SAndy Zhou 				    const struct sw_flow_key *key)
7075bb50632SAndy Zhou {
70804b7d136STonghao Zhang 	struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
7094bc63b1bSTonghao Zhang 	struct mask_array *ma = rcu_dereference_ovsl(tbl->mask_array);
7104bc63b1bSTonghao Zhang 	u32 __always_unused n_mask_hit;
711a7f35e78STonghao Zhang 	u32 index = 0;
7124bc63b1bSTonghao Zhang 
7134bc63b1bSTonghao Zhang 	return flow_lookup(tbl, ti, ma, key, &n_mask_hit, &index);
7145bb50632SAndy Zhou }
7155bb50632SAndy Zhou 
7164a46b24eSAlex Wang struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
71712eb18f7SThomas Graf 					  const struct sw_flow_match *match)
7184a46b24eSAlex Wang {
7194bc63b1bSTonghao Zhang 	struct mask_array *ma = ovsl_dereference(tbl->mask_array);
7204bc63b1bSTonghao Zhang 	int i;
7214a46b24eSAlex Wang 
7224a46b24eSAlex Wang 	/* Always called under ovs-mutex. */
7234bc63b1bSTonghao Zhang 	for (i = 0; i < ma->max; i++) {
7244bc63b1bSTonghao Zhang 		struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
7254bc63b1bSTonghao Zhang 		u32 __always_unused n_mask_hit;
7264bc63b1bSTonghao Zhang 		struct sw_flow_mask *mask;
7274bc63b1bSTonghao Zhang 		struct sw_flow *flow;
7284bc63b1bSTonghao Zhang 
7294bc63b1bSTonghao Zhang 		mask = ovsl_dereference(ma->masks[i]);
7304bc63b1bSTonghao Zhang 		if (!mask)
7314bc63b1bSTonghao Zhang 			continue;
7324bc63b1bSTonghao Zhang 
73304b7d136STonghao Zhang 		flow = masked_flow_lookup(ti, match->key, mask, &n_mask_hit);
73474ed7ab9SJoe Stringer 		if (flow && ovs_identifier_is_key(&flow->id) &&
7354bc63b1bSTonghao Zhang 		    ovs_flow_cmp_unmasked_key(flow, match)) {
73674ed7ab9SJoe Stringer 			return flow;
73774ed7ab9SJoe Stringer 		}
7384bc63b1bSTonghao Zhang 	}
7394bc63b1bSTonghao Zhang 
74074ed7ab9SJoe Stringer 	return NULL;
74174ed7ab9SJoe Stringer }
74274ed7ab9SJoe Stringer 
74374ed7ab9SJoe Stringer static u32 ufid_hash(const struct sw_flow_id *sfid)
74474ed7ab9SJoe Stringer {
74574ed7ab9SJoe Stringer 	return jhash(sfid->ufid, sfid->ufid_len, 0);
74674ed7ab9SJoe Stringer }
74774ed7ab9SJoe Stringer 
74874ed7ab9SJoe Stringer static bool ovs_flow_cmp_ufid(const struct sw_flow *flow,
74974ed7ab9SJoe Stringer 			      const struct sw_flow_id *sfid)
75074ed7ab9SJoe Stringer {
75174ed7ab9SJoe Stringer 	if (flow->id.ufid_len != sfid->ufid_len)
75274ed7ab9SJoe Stringer 		return false;
75374ed7ab9SJoe Stringer 
75474ed7ab9SJoe Stringer 	return !memcmp(flow->id.ufid, sfid->ufid, sfid->ufid_len);
75574ed7ab9SJoe Stringer }
75674ed7ab9SJoe Stringer 
75774ed7ab9SJoe Stringer bool ovs_flow_cmp(const struct sw_flow *flow, const struct sw_flow_match *match)
75874ed7ab9SJoe Stringer {
75974ed7ab9SJoe Stringer 	if (ovs_identifier_is_ufid(&flow->id))
76074ed7ab9SJoe Stringer 		return flow_cmp_masked_key(flow, match->key, &match->range);
76174ed7ab9SJoe Stringer 
76274ed7ab9SJoe Stringer 	return ovs_flow_cmp_unmasked_key(flow, match);
76374ed7ab9SJoe Stringer }
76474ed7ab9SJoe Stringer 
76574ed7ab9SJoe Stringer struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *tbl,
76674ed7ab9SJoe Stringer 					 const struct sw_flow_id *ufid)
76774ed7ab9SJoe Stringer {
76874ed7ab9SJoe Stringer 	struct table_instance *ti = rcu_dereference_ovsl(tbl->ufid_ti);
76974ed7ab9SJoe Stringer 	struct sw_flow *flow;
77074ed7ab9SJoe Stringer 	struct hlist_head *head;
77174ed7ab9SJoe Stringer 	u32 hash;
77274ed7ab9SJoe Stringer 
77374ed7ab9SJoe Stringer 	hash = ufid_hash(ufid);
77474ed7ab9SJoe Stringer 	head = find_bucket(ti, hash);
775a2cfb96cSMadhuparna Bhowmik 	hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver],
776a2cfb96cSMadhuparna Bhowmik 				lockdep_ovsl_is_held()) {
77774ed7ab9SJoe Stringer 		if (flow->ufid_table.hash == hash &&
77874ed7ab9SJoe Stringer 		    ovs_flow_cmp_ufid(flow, ufid))
7794a46b24eSAlex Wang 			return flow;
7804a46b24eSAlex Wang 	}
7814a46b24eSAlex Wang 	return NULL;
7824a46b24eSAlex Wang }
7834a46b24eSAlex Wang 
7841bd7116fSAndy Zhou int ovs_flow_tbl_num_masks(const struct flow_table *table)
7851bd7116fSAndy Zhou {
7864bc63b1bSTonghao Zhang 	struct mask_array *ma = rcu_dereference_ovsl(table->mask_array);
78757f7d7b9STonghao Zhang 	return READ_ONCE(ma->count);
7881bd7116fSAndy Zhou }
7891bd7116fSAndy Zhou 
79074ed7ab9SJoe Stringer static struct table_instance *table_instance_expand(struct table_instance *ti,
79174ed7ab9SJoe Stringer 						    bool ufid)
792b637e498SPravin B Shelar {
79374ed7ab9SJoe Stringer 	return table_instance_rehash(ti, ti->n_buckets * 2, ufid);
794e6445719SPravin B Shelar }
795e6445719SPravin B Shelar 
79656c19868SJarno Rajahalme /* Must be called with OVS mutex held. */
797e6445719SPravin B Shelar void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
798e6445719SPravin B Shelar {
799b637e498SPravin B Shelar 	struct table_instance *ti = ovsl_dereference(table->ti);
80074ed7ab9SJoe Stringer 	struct table_instance *ufid_ti = ovsl_dereference(table->ufid_ti);
801b637e498SPravin B Shelar 
802e6445719SPravin B Shelar 	BUG_ON(table->count == 0);
80350b0e61bSTonghao Zhang 	table_instance_flow_free(table, ti, ufid_ti, flow, true);
804e6445719SPravin B Shelar }
805e6445719SPravin B Shelar 
806618ed0c8SPravin B Shelar static struct sw_flow_mask *mask_alloc(void)
807e6445719SPravin B Shelar {
808e6445719SPravin B Shelar 	struct sw_flow_mask *mask;
809e6445719SPravin B Shelar 
810e6445719SPravin B Shelar 	mask = kmalloc(sizeof(*mask), GFP_KERNEL);
811e6445719SPravin B Shelar 	if (mask)
812e80857ccSAndy Zhou 		mask->ref_count = 1;
813e6445719SPravin B Shelar 
814e6445719SPravin B Shelar 	return mask;
815e6445719SPravin B Shelar }
816e6445719SPravin B Shelar 
817e6445719SPravin B Shelar static bool mask_equal(const struct sw_flow_mask *a,
818e6445719SPravin B Shelar 		       const struct sw_flow_mask *b)
819e6445719SPravin B Shelar {
8207085130bSDaniele Di Proietto 	const u8 *a_ = (const u8 *)&a->key + a->range.start;
8217085130bSDaniele Di Proietto 	const u8 *b_ = (const u8 *)&b->key + b->range.start;
822e6445719SPravin B Shelar 
823e6445719SPravin B Shelar 	return  (a->range.end == b->range.end)
824e6445719SPravin B Shelar 		&& (a->range.start == b->range.start)
825e6445719SPravin B Shelar 		&& (memcmp(a_, b_, range_n_bytes(&a->range)) == 0);
826e6445719SPravin B Shelar }
827e6445719SPravin B Shelar 
828618ed0c8SPravin B Shelar static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl,
829e6445719SPravin B Shelar 					   const struct sw_flow_mask *mask)
830e6445719SPravin B Shelar {
8314bc63b1bSTonghao Zhang 	struct mask_array *ma;
8324bc63b1bSTonghao Zhang 	int i;
833e6445719SPravin B Shelar 
8344bc63b1bSTonghao Zhang 	ma = ovsl_dereference(tbl->mask_array);
8354bc63b1bSTonghao Zhang 	for (i = 0; i < ma->max; i++) {
8364bc63b1bSTonghao Zhang 		struct sw_flow_mask *t;
8374bc63b1bSTonghao Zhang 		t = ovsl_dereference(ma->masks[i]);
8384bc63b1bSTonghao Zhang 
8394bc63b1bSTonghao Zhang 		if (t && mask_equal(mask, t))
8404bc63b1bSTonghao Zhang 			return t;
841e6445719SPravin B Shelar 	}
842e6445719SPravin B Shelar 
843e6445719SPravin B Shelar 	return NULL;
844e6445719SPravin B Shelar }
845e6445719SPravin B Shelar 
846d1211908SBen Pfaff /* Add 'mask' into the mask list, if it is not already there. */
847618ed0c8SPravin B Shelar static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
84812eb18f7SThomas Graf 			    const struct sw_flow_mask *new)
849e6445719SPravin B Shelar {
850618ed0c8SPravin B Shelar 	struct sw_flow_mask *mask;
8514bc63b1bSTonghao Zhang 
852618ed0c8SPravin B Shelar 	mask = flow_mask_find(tbl, new);
853618ed0c8SPravin B Shelar 	if (!mask) {
854618ed0c8SPravin B Shelar 		/* Allocate a new mask if none exsits. */
855618ed0c8SPravin B Shelar 		mask = mask_alloc();
856618ed0c8SPravin B Shelar 		if (!mask)
857618ed0c8SPravin B Shelar 			return -ENOMEM;
858618ed0c8SPravin B Shelar 		mask->key = new->key;
859618ed0c8SPravin B Shelar 		mask->range = new->range;
8604bc63b1bSTonghao Zhang 
8614bc63b1bSTonghao Zhang 		/* Add mask to mask-list. */
86257f7d7b9STonghao Zhang 		if (tbl_mask_array_add_mask(tbl, mask)) {
8634bc63b1bSTonghao Zhang 			kfree(mask);
86457f7d7b9STonghao Zhang 			return -ENOMEM;
8654bc63b1bSTonghao Zhang 		}
866e80857ccSAndy Zhou 	} else {
867e80857ccSAndy Zhou 		BUG_ON(!mask->ref_count);
868e80857ccSAndy Zhou 		mask->ref_count++;
869e6445719SPravin B Shelar 	}
870e6445719SPravin B Shelar 
871618ed0c8SPravin B Shelar 	flow->mask = mask;
872618ed0c8SPravin B Shelar 	return 0;
873618ed0c8SPravin B Shelar }
874618ed0c8SPravin B Shelar 
87556c19868SJarno Rajahalme /* Must be called with OVS mutex held. */
876d29ab6f8SJoe Stringer static void flow_key_insert(struct flow_table *table, struct sw_flow *flow)
877618ed0c8SPravin B Shelar {
878618ed0c8SPravin B Shelar 	struct table_instance *new_ti = NULL;
879618ed0c8SPravin B Shelar 	struct table_instance *ti;
880618ed0c8SPravin B Shelar 
88174ed7ab9SJoe Stringer 	flow->flow_table.hash = flow_hash(&flow->key, &flow->mask->range);
882618ed0c8SPravin B Shelar 	ti = ovsl_dereference(table->ti);
883618ed0c8SPravin B Shelar 	table_instance_insert(ti, flow);
884618ed0c8SPravin B Shelar 	table->count++;
885618ed0c8SPravin B Shelar 
886618ed0c8SPravin B Shelar 	/* Expand table, if necessary, to make room. */
887618ed0c8SPravin B Shelar 	if (table->count > ti->n_buckets)
88874ed7ab9SJoe Stringer 		new_ti = table_instance_expand(ti, false);
889618ed0c8SPravin B Shelar 	else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL))
89074ed7ab9SJoe Stringer 		new_ti = table_instance_rehash(ti, ti->n_buckets, false);
891618ed0c8SPravin B Shelar 
892618ed0c8SPravin B Shelar 	if (new_ti) {
893618ed0c8SPravin B Shelar 		rcu_assign_pointer(table->ti, new_ti);
89474ed7ab9SJoe Stringer 		call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
895618ed0c8SPravin B Shelar 		table->last_rehash = jiffies;
896618ed0c8SPravin B Shelar 	}
897d29ab6f8SJoe Stringer }
898d29ab6f8SJoe Stringer 
899d29ab6f8SJoe Stringer /* Must be called with OVS mutex held. */
90074ed7ab9SJoe Stringer static void flow_ufid_insert(struct flow_table *table, struct sw_flow *flow)
90174ed7ab9SJoe Stringer {
90274ed7ab9SJoe Stringer 	struct table_instance *ti;
90374ed7ab9SJoe Stringer 
90474ed7ab9SJoe Stringer 	flow->ufid_table.hash = ufid_hash(&flow->id);
90574ed7ab9SJoe Stringer 	ti = ovsl_dereference(table->ufid_ti);
90674ed7ab9SJoe Stringer 	ufid_table_instance_insert(ti, flow);
90774ed7ab9SJoe Stringer 	table->ufid_count++;
90874ed7ab9SJoe Stringer 
90974ed7ab9SJoe Stringer 	/* Expand table, if necessary, to make room. */
91074ed7ab9SJoe Stringer 	if (table->ufid_count > ti->n_buckets) {
91174ed7ab9SJoe Stringer 		struct table_instance *new_ti;
91274ed7ab9SJoe Stringer 
91374ed7ab9SJoe Stringer 		new_ti = table_instance_expand(ti, true);
91474ed7ab9SJoe Stringer 		if (new_ti) {
91574ed7ab9SJoe Stringer 			rcu_assign_pointer(table->ufid_ti, new_ti);
91674ed7ab9SJoe Stringer 			call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
91774ed7ab9SJoe Stringer 		}
91874ed7ab9SJoe Stringer 	}
91974ed7ab9SJoe Stringer }
92074ed7ab9SJoe Stringer 
92174ed7ab9SJoe Stringer /* Must be called with OVS mutex held. */
922d29ab6f8SJoe Stringer int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
923d29ab6f8SJoe Stringer 			const struct sw_flow_mask *mask)
924d29ab6f8SJoe Stringer {
925d29ab6f8SJoe Stringer 	int err;
926d29ab6f8SJoe Stringer 
927d29ab6f8SJoe Stringer 	err = flow_mask_insert(table, flow, mask);
928d29ab6f8SJoe Stringer 	if (err)
929d29ab6f8SJoe Stringer 		return err;
930d29ab6f8SJoe Stringer 	flow_key_insert(table, flow);
93174ed7ab9SJoe Stringer 	if (ovs_identifier_is_ufid(&flow->id))
93274ed7ab9SJoe Stringer 		flow_ufid_insert(table, flow);
933d29ab6f8SJoe Stringer 
934618ed0c8SPravin B Shelar 	return 0;
935618ed0c8SPravin B Shelar }
936618ed0c8SPravin B Shelar 
937e6445719SPravin B Shelar /* Initializes the flow module.
938e6445719SPravin B Shelar  * Returns zero if successful or a negative error code. */
939e6445719SPravin B Shelar int ovs_flow_init(void)
940e6445719SPravin B Shelar {
941e6445719SPravin B Shelar 	BUILD_BUG_ON(__alignof__(struct sw_flow_key) % __alignof__(long));
942e6445719SPravin B Shelar 	BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long));
943e6445719SPravin B Shelar 
94463e7959cSJarno Rajahalme 	flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow)
945db74a333SThadeu Lima de Souza Cascardo 				       + (nr_cpu_ids
946aef833c5SPablo Neira Ayuso 					  * sizeof(struct sw_flow_stats *)),
94763e7959cSJarno Rajahalme 				       0, 0, NULL);
948e6445719SPravin B Shelar 	if (flow_cache == NULL)
949e6445719SPravin B Shelar 		return -ENOMEM;
950e6445719SPravin B Shelar 
95163e7959cSJarno Rajahalme 	flow_stats_cache
952aef833c5SPablo Neira Ayuso 		= kmem_cache_create("sw_flow_stats", sizeof(struct sw_flow_stats),
95363e7959cSJarno Rajahalme 				    0, SLAB_HWCACHE_ALIGN, NULL);
95463e7959cSJarno Rajahalme 	if (flow_stats_cache == NULL) {
95563e7959cSJarno Rajahalme 		kmem_cache_destroy(flow_cache);
95663e7959cSJarno Rajahalme 		flow_cache = NULL;
95763e7959cSJarno Rajahalme 		return -ENOMEM;
95863e7959cSJarno Rajahalme 	}
95963e7959cSJarno Rajahalme 
960e6445719SPravin B Shelar 	return 0;
961e6445719SPravin B Shelar }
962e6445719SPravin B Shelar 
963e6445719SPravin B Shelar /* Uninitializes the flow module. */
964e6445719SPravin B Shelar void ovs_flow_exit(void)
965e6445719SPravin B Shelar {
96663e7959cSJarno Rajahalme 	kmem_cache_destroy(flow_stats_cache);
967e6445719SPravin B Shelar 	kmem_cache_destroy(flow_cache);
968e6445719SPravin B Shelar }
969