xref: /linux-6.15/net/openvswitch/datapath.c (revision ea8564c8)
1c9422999SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ccb1352eSJesse Gross /*
3ad552007SBen Pfaff  * Copyright (c) 2007-2014 Nicira, Inc.
4ccb1352eSJesse Gross  */
5ccb1352eSJesse Gross 
6ccb1352eSJesse Gross #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7ccb1352eSJesse Gross 
8ccb1352eSJesse Gross #include <linux/init.h>
9ccb1352eSJesse Gross #include <linux/module.h>
10ccb1352eSJesse Gross #include <linux/if_arp.h>
11ccb1352eSJesse Gross #include <linux/if_vlan.h>
12ccb1352eSJesse Gross #include <linux/in.h>
13ccb1352eSJesse Gross #include <linux/ip.h>
14ccb1352eSJesse Gross #include <linux/jhash.h>
15ccb1352eSJesse Gross #include <linux/delay.h>
16ccb1352eSJesse Gross #include <linux/time.h>
17ccb1352eSJesse Gross #include <linux/etherdevice.h>
18ccb1352eSJesse Gross #include <linux/genetlink.h>
19ccb1352eSJesse Gross #include <linux/kernel.h>
20ccb1352eSJesse Gross #include <linux/kthread.h>
21ccb1352eSJesse Gross #include <linux/mutex.h>
22ccb1352eSJesse Gross #include <linux/percpu.h>
23ccb1352eSJesse Gross #include <linux/rcupdate.h>
24ccb1352eSJesse Gross #include <linux/tcp.h>
25ccb1352eSJesse Gross #include <linux/udp.h>
26ccb1352eSJesse Gross #include <linux/ethtool.h>
27ccb1352eSJesse Gross #include <linux/wait.h>
28ccb1352eSJesse Gross #include <asm/div64.h>
29ccb1352eSJesse Gross #include <linux/highmem.h>
30ccb1352eSJesse Gross #include <linux/netfilter_bridge.h>
31ccb1352eSJesse Gross #include <linux/netfilter_ipv4.h>
32ccb1352eSJesse Gross #include <linux/inetdevice.h>
33ccb1352eSJesse Gross #include <linux/list.h>
34ccb1352eSJesse Gross #include <linux/openvswitch.h>
35ccb1352eSJesse Gross #include <linux/rculist.h>
36ccb1352eSJesse Gross #include <linux/dmi.h>
37ccb1352eSJesse Gross #include <net/genetlink.h>
3846df7b81SPravin B Shelar #include <net/net_namespace.h>
3946df7b81SPravin B Shelar #include <net/netns/generic.h>
40ccb1352eSJesse Gross 
41ccb1352eSJesse Gross #include "datapath.h"
42ccb1352eSJesse Gross #include "flow.h"
43e80857ccSAndy Zhou #include "flow_table.h"
44e6445719SPravin B Shelar #include "flow_netlink.h"
4596fbc13dSAndy Zhou #include "meter.h"
46ccb1352eSJesse Gross #include "vport-internal_dev.h"
47cff63a52SThomas Graf #include "vport-netdev.h"
48ccb1352eSJesse Gross 
49c7d03a00SAlexey Dobriyan unsigned int ovs_net_id __read_mostly;
508e4e1713SPravin B Shelar 
510c200ef9SPravin B Shelar static struct genl_family dp_packet_genl_family;
520c200ef9SPravin B Shelar static struct genl_family dp_flow_genl_family;
530c200ef9SPravin B Shelar static struct genl_family dp_datapath_genl_family;
540c200ef9SPravin B Shelar 
5574ed7ab9SJoe Stringer static const struct nla_policy flow_policy[];
5674ed7ab9SJoe Stringer 
5748e48a70Sstephen hemminger static const struct genl_multicast_group ovs_dp_flow_multicast_group = {
5848e48a70Sstephen hemminger 	.name = OVS_FLOW_MCGROUP,
590c200ef9SPravin B Shelar };
600c200ef9SPravin B Shelar 
6148e48a70Sstephen hemminger static const struct genl_multicast_group ovs_dp_datapath_multicast_group = {
6248e48a70Sstephen hemminger 	.name = OVS_DATAPATH_MCGROUP,
630c200ef9SPravin B Shelar };
640c200ef9SPravin B Shelar 
6548e48a70Sstephen hemminger static const struct genl_multicast_group ovs_dp_vport_multicast_group = {
6648e48a70Sstephen hemminger 	.name = OVS_VPORT_MCGROUP,
670c200ef9SPravin B Shelar };
680c200ef9SPravin B Shelar 
69fb5d1e9eSJarno Rajahalme /* Check if need to build a reply message.
70fb5d1e9eSJarno Rajahalme  * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
719b67aa4aSSamuel Gauthier static bool ovs_must_notify(struct genl_family *family, struct genl_info *info,
729b67aa4aSSamuel Gauthier 			    unsigned int group)
73fb5d1e9eSJarno Rajahalme {
74fb5d1e9eSJarno Rajahalme 	return info->nlhdr->nlmsg_flags & NLM_F_ECHO ||
75f8403a2eSJohannes Berg 	       genl_has_listeners(family, genl_info_net(info), group);
76fb5d1e9eSJarno Rajahalme }
77fb5d1e9eSJarno Rajahalme 
7868eb5503SJohannes Berg static void ovs_notify(struct genl_family *family,
792a94fe48SJohannes Berg 		       struct sk_buff *skb, struct genl_info *info)
80ed661185SThomas Graf {
8192c14d9bSJiri Benc 	genl_notify(family, skb, info, 0, GFP_KERNEL);
82ed661185SThomas Graf }
83ed661185SThomas Graf 
8446df7b81SPravin B Shelar /**
85ccb1352eSJesse Gross  * DOC: Locking:
86ccb1352eSJesse Gross  *
878e4e1713SPravin B Shelar  * All writes e.g. Writes to device state (add/remove datapath, port, set
888e4e1713SPravin B Shelar  * operations on vports, etc.), Writes to other state (flow table
898e4e1713SPravin B Shelar  * modifications, set miscellaneous datapath parameters, etc.) are protected
908e4e1713SPravin B Shelar  * by ovs_lock.
91ccb1352eSJesse Gross  *
92ccb1352eSJesse Gross  * Reads are protected by RCU.
93ccb1352eSJesse Gross  *
94ccb1352eSJesse Gross  * There are a few special cases (mostly stats) that have their own
95ccb1352eSJesse Gross  * synchronization but they nest under all of above and don't interact with
96ccb1352eSJesse Gross  * each other.
978e4e1713SPravin B Shelar  *
988e4e1713SPravin B Shelar  * The RTNL lock nests inside ovs_mutex.
99ccb1352eSJesse Gross  */
100ccb1352eSJesse Gross 
1018e4e1713SPravin B Shelar static DEFINE_MUTEX(ovs_mutex);
1028e4e1713SPravin B Shelar 
1038e4e1713SPravin B Shelar void ovs_lock(void)
1048e4e1713SPravin B Shelar {
1058e4e1713SPravin B Shelar 	mutex_lock(&ovs_mutex);
1068e4e1713SPravin B Shelar }
1078e4e1713SPravin B Shelar 
1088e4e1713SPravin B Shelar void ovs_unlock(void)
1098e4e1713SPravin B Shelar {
1108e4e1713SPravin B Shelar 	mutex_unlock(&ovs_mutex);
1118e4e1713SPravin B Shelar }
1128e4e1713SPravin B Shelar 
1138e4e1713SPravin B Shelar #ifdef CONFIG_LOCKDEP
1148e4e1713SPravin B Shelar int lockdep_ovsl_is_held(void)
1158e4e1713SPravin B Shelar {
1168e4e1713SPravin B Shelar 	if (debug_locks)
1178e4e1713SPravin B Shelar 		return lockdep_is_held(&ovs_mutex);
1188e4e1713SPravin B Shelar 	else
1198e4e1713SPravin B Shelar 		return 1;
1208e4e1713SPravin B Shelar }
1218e4e1713SPravin B Shelar #endif
1228e4e1713SPravin B Shelar 
123ccb1352eSJesse Gross static struct vport *new_vport(const struct vport_parms *);
1248055a89cSThomas Graf static int queue_gso_packets(struct datapath *dp, struct sk_buff *,
125e8eedb85SPravin B Shelar 			     const struct sw_flow_key *,
126f2a4d086SWilliam Tu 			     const struct dp_upcall_info *,
127f2a4d086SWilliam Tu 			     uint32_t cutlen);
1288055a89cSThomas Graf static int queue_userspace_packet(struct datapath *dp, struct sk_buff *,
129e8eedb85SPravin B Shelar 				  const struct sw_flow_key *,
130f2a4d086SWilliam Tu 				  const struct dp_upcall_info *,
131f2a4d086SWilliam Tu 				  uint32_t cutlen);
132ccb1352eSJesse Gross 
1338e4e1713SPravin B Shelar /* Must be called with rcu_read_lock or ovs_mutex. */
134971427f3SAndy Zhou const char *ovs_dp_name(const struct datapath *dp)
135ccb1352eSJesse Gross {
1368e4e1713SPravin B Shelar 	struct vport *vport = ovs_vport_ovsl_rcu(dp, OVSP_LOCAL);
137c9db965cSThomas Graf 	return ovs_vport_name(vport);
138ccb1352eSJesse Gross }
139ccb1352eSJesse Gross 
14012eb18f7SThomas Graf static int get_dpifindex(const struct datapath *dp)
141ccb1352eSJesse Gross {
142ccb1352eSJesse Gross 	struct vport *local;
143ccb1352eSJesse Gross 	int ifindex;
144ccb1352eSJesse Gross 
145ccb1352eSJesse Gross 	rcu_read_lock();
146ccb1352eSJesse Gross 
14715eac2a7SPravin B Shelar 	local = ovs_vport_rcu(dp, OVSP_LOCAL);
148ccb1352eSJesse Gross 	if (local)
149be4ace6eSThomas Graf 		ifindex = local->dev->ifindex;
150ccb1352eSJesse Gross 	else
151ccb1352eSJesse Gross 		ifindex = 0;
152ccb1352eSJesse Gross 
153ccb1352eSJesse Gross 	rcu_read_unlock();
154ccb1352eSJesse Gross 
155ccb1352eSJesse Gross 	return ifindex;
156ccb1352eSJesse Gross }
157ccb1352eSJesse Gross 
158ccb1352eSJesse Gross static void destroy_dp_rcu(struct rcu_head *rcu)
159ccb1352eSJesse Gross {
160ccb1352eSJesse Gross 	struct datapath *dp = container_of(rcu, struct datapath, rcu);
161ccb1352eSJesse Gross 
1629b996e54SPravin B Shelar 	ovs_flow_tbl_destroy(&dp->table);
163ccb1352eSJesse Gross 	free_percpu(dp->stats_percpu);
16415eac2a7SPravin B Shelar 	kfree(dp->ports);
16596fbc13dSAndy Zhou 	ovs_meters_exit(dp);
166ccb1352eSJesse Gross 	kfree(dp);
167ccb1352eSJesse Gross }
168ccb1352eSJesse Gross 
16915eac2a7SPravin B Shelar static struct hlist_head *vport_hash_bucket(const struct datapath *dp,
17015eac2a7SPravin B Shelar 					    u16 port_no)
17115eac2a7SPravin B Shelar {
17215eac2a7SPravin B Shelar 	return &dp->ports[port_no & (DP_VPORT_HASH_BUCKETS - 1)];
17315eac2a7SPravin B Shelar }
17415eac2a7SPravin B Shelar 
175bb6f9a70SJarno Rajahalme /* Called with ovs_mutex or RCU read lock. */
17615eac2a7SPravin B Shelar struct vport *ovs_lookup_vport(const struct datapath *dp, u16 port_no)
17715eac2a7SPravin B Shelar {
17815eac2a7SPravin B Shelar 	struct vport *vport;
17915eac2a7SPravin B Shelar 	struct hlist_head *head;
18015eac2a7SPravin B Shelar 
18115eac2a7SPravin B Shelar 	head = vport_hash_bucket(dp, port_no);
182b67bfe0dSSasha Levin 	hlist_for_each_entry_rcu(vport, head, dp_hash_node) {
18315eac2a7SPravin B Shelar 		if (vport->port_no == port_no)
18415eac2a7SPravin B Shelar 			return vport;
18515eac2a7SPravin B Shelar 	}
18615eac2a7SPravin B Shelar 	return NULL;
18715eac2a7SPravin B Shelar }
18815eac2a7SPravin B Shelar 
1898e4e1713SPravin B Shelar /* Called with ovs_mutex. */
190ccb1352eSJesse Gross static struct vport *new_vport(const struct vport_parms *parms)
191ccb1352eSJesse Gross {
192ccb1352eSJesse Gross 	struct vport *vport;
193ccb1352eSJesse Gross 
194ccb1352eSJesse Gross 	vport = ovs_vport_add(parms);
195ccb1352eSJesse Gross 	if (!IS_ERR(vport)) {
196ccb1352eSJesse Gross 		struct datapath *dp = parms->dp;
19715eac2a7SPravin B Shelar 		struct hlist_head *head = vport_hash_bucket(dp, vport->port_no);
198ccb1352eSJesse Gross 
19915eac2a7SPravin B Shelar 		hlist_add_head_rcu(&vport->dp_hash_node, head);
200ccb1352eSJesse Gross 	}
201ccb1352eSJesse Gross 	return vport;
202ccb1352eSJesse Gross }
203ccb1352eSJesse Gross 
204ccb1352eSJesse Gross void ovs_dp_detach_port(struct vport *p)
205ccb1352eSJesse Gross {
2068e4e1713SPravin B Shelar 	ASSERT_OVSL();
207ccb1352eSJesse Gross 
208ccb1352eSJesse Gross 	/* First drop references to device. */
20915eac2a7SPravin B Shelar 	hlist_del_rcu(&p->dp_hash_node);
210ccb1352eSJesse Gross 
211ccb1352eSJesse Gross 	/* Then destroy it. */
212ccb1352eSJesse Gross 	ovs_vport_del(p);
213ccb1352eSJesse Gross }
214ccb1352eSJesse Gross 
215ccb1352eSJesse Gross /* Must be called with rcu_read_lock. */
2168c8b1b83SPravin B Shelar void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)
217ccb1352eSJesse Gross {
21883c8df26SPravin B Shelar 	const struct vport *p = OVS_CB(skb)->input_vport;
219ccb1352eSJesse Gross 	struct datapath *dp = p->dp;
220ccb1352eSJesse Gross 	struct sw_flow *flow;
221d98612b8SLorand Jakab 	struct sw_flow_actions *sf_acts;
222ccb1352eSJesse Gross 	struct dp_stats_percpu *stats;
223ccb1352eSJesse Gross 	u64 *stats_counter;
2241bd7116fSAndy Zhou 	u32 n_mask_hit;
225aa733660SYifeng Sun 	int error;
226ccb1352eSJesse Gross 
227404f2f10SShan Wei 	stats = this_cpu_ptr(dp->stats_percpu);
228ccb1352eSJesse Gross 
229ccb1352eSJesse Gross 	/* Look up flow. */
2308c8b1b83SPravin B Shelar 	flow = ovs_flow_tbl_lookup_stats(&dp->table, key, &n_mask_hit);
231ccb1352eSJesse Gross 	if (unlikely(!flow)) {
232ccb1352eSJesse Gross 		struct dp_upcall_info upcall;
233ccb1352eSJesse Gross 
234ccea7445SNeil McKee 		memset(&upcall, 0, sizeof(upcall));
235ccb1352eSJesse Gross 		upcall.cmd = OVS_PACKET_CMD_MISS;
2365cd667b0SAlex Wang 		upcall.portid = ovs_vport_find_upcall_portid(p, skb);
2377f8a436eSJoe Stringer 		upcall.mru = OVS_CB(skb)->mru;
238f2a4d086SWilliam Tu 		error = ovs_dp_upcall(dp, skb, key, &upcall, 0);
239c5eba0b6SLi RongQing 		if (unlikely(error))
240c5eba0b6SLi RongQing 			kfree_skb(skb);
241c5eba0b6SLi RongQing 		else
242ccb1352eSJesse Gross 			consume_skb(skb);
243ccb1352eSJesse Gross 		stats_counter = &stats->n_missed;
244ccb1352eSJesse Gross 		goto out;
245ccb1352eSJesse Gross 	}
246ccb1352eSJesse Gross 
247d98612b8SLorand Jakab 	ovs_flow_stats_update(flow, key->tp.flags, skb);
248d98612b8SLorand Jakab 	sf_acts = rcu_dereference(flow->sf_acts);
249aa733660SYifeng Sun 	error = ovs_execute_actions(dp, skb, sf_acts, key);
250aa733660SYifeng Sun 	if (unlikely(error))
251aa733660SYifeng Sun 		net_dbg_ratelimited("ovs: action execution error on datapath %s: %d\n",
252aa733660SYifeng Sun 							ovs_dp_name(dp), error);
253ccb1352eSJesse Gross 
254e298e505SPravin B Shelar 	stats_counter = &stats->n_hit;
255ccb1352eSJesse Gross 
256ccb1352eSJesse Gross out:
257ccb1352eSJesse Gross 	/* Update datapath statistics. */
258df9d9fdfSWANG Cong 	u64_stats_update_begin(&stats->syncp);
259ccb1352eSJesse Gross 	(*stats_counter)++;
2601bd7116fSAndy Zhou 	stats->n_mask_hit += n_mask_hit;
261df9d9fdfSWANG Cong 	u64_stats_update_end(&stats->syncp);
262ccb1352eSJesse Gross }
263ccb1352eSJesse Gross 
264ccb1352eSJesse Gross int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
265e8eedb85SPravin B Shelar 		  const struct sw_flow_key *key,
266f2a4d086SWilliam Tu 		  const struct dp_upcall_info *upcall_info,
267f2a4d086SWilliam Tu 		  uint32_t cutlen)
268ccb1352eSJesse Gross {
269ccb1352eSJesse Gross 	struct dp_stats_percpu *stats;
270ccb1352eSJesse Gross 	int err;
271ccb1352eSJesse Gross 
27215e47304SEric W. Biederman 	if (upcall_info->portid == 0) {
273ccb1352eSJesse Gross 		err = -ENOTCONN;
274ccb1352eSJesse Gross 		goto err;
275ccb1352eSJesse Gross 	}
276ccb1352eSJesse Gross 
277ccb1352eSJesse Gross 	if (!skb_is_gso(skb))
278f2a4d086SWilliam Tu 		err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen);
279ccb1352eSJesse Gross 	else
280f2a4d086SWilliam Tu 		err = queue_gso_packets(dp, skb, key, upcall_info, cutlen);
281ccb1352eSJesse Gross 	if (err)
282ccb1352eSJesse Gross 		goto err;
283ccb1352eSJesse Gross 
284ccb1352eSJesse Gross 	return 0;
285ccb1352eSJesse Gross 
286ccb1352eSJesse Gross err:
287404f2f10SShan Wei 	stats = this_cpu_ptr(dp->stats_percpu);
288ccb1352eSJesse Gross 
289df9d9fdfSWANG Cong 	u64_stats_update_begin(&stats->syncp);
290ccb1352eSJesse Gross 	stats->n_lost++;
291df9d9fdfSWANG Cong 	u64_stats_update_end(&stats->syncp);
292ccb1352eSJesse Gross 
293ccb1352eSJesse Gross 	return err;
294ccb1352eSJesse Gross }
295ccb1352eSJesse Gross 
2968055a89cSThomas Graf static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
297e8eedb85SPravin B Shelar 			     const struct sw_flow_key *key,
298f2a4d086SWilliam Tu 			     const struct dp_upcall_info *upcall_info,
299f2a4d086SWilliam Tu 				 uint32_t cutlen)
300ccb1352eSJesse Gross {
3012734166eSGustavo A. R. Silva 	unsigned int gso_type = skb_shinfo(skb)->gso_type;
3020c19f846SWillem de Bruijn 	struct sw_flow_key later_key;
303ccb1352eSJesse Gross 	struct sk_buff *segs, *nskb;
304ccb1352eSJesse Gross 	int err;
305ccb1352eSJesse Gross 
3069207f9d4SKonstantin Khlebnikov 	BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_SGO_CB_OFFSET);
30709c5e605SThomas Graf 	segs = __skb_gso_segment(skb, NETIF_F_SG, false);
30892e5dfc3SPravin B Shelar 	if (IS_ERR(segs))
30992e5dfc3SPravin B Shelar 		return PTR_ERR(segs);
310330966e5SFlorian Westphal 	if (segs == NULL)
311330966e5SFlorian Westphal 		return -EINVAL;
312ccb1352eSJesse Gross 
3130c19f846SWillem de Bruijn 	if (gso_type & SKB_GSO_UDP) {
3140c19f846SWillem de Bruijn 		/* The initial flow key extracted by ovs_flow_key_extract()
3150c19f846SWillem de Bruijn 		 * in this case is for a first fragment, so we need to
3160c19f846SWillem de Bruijn 		 * properly mark later fragments.
3170c19f846SWillem de Bruijn 		 */
3180c19f846SWillem de Bruijn 		later_key = *key;
3190c19f846SWillem de Bruijn 		later_key.ip.frag = OVS_FRAG_TYPE_LATER;
3200c19f846SWillem de Bruijn 	}
3210c19f846SWillem de Bruijn 
322e8eedb85SPravin B Shelar 	/* Queue all of the segments. */
323e8eedb85SPravin B Shelar 	skb = segs;
324e8eedb85SPravin B Shelar 	do {
3250c19f846SWillem de Bruijn 		if (gso_type & SKB_GSO_UDP && skb != segs)
3260c19f846SWillem de Bruijn 			key = &later_key;
3270c19f846SWillem de Bruijn 
328f2a4d086SWilliam Tu 		err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen);
329e8eedb85SPravin B Shelar 		if (err)
330e8eedb85SPravin B Shelar 			break;
331e8eedb85SPravin B Shelar 
332ccb1352eSJesse Gross 	} while ((skb = skb->next));
333ccb1352eSJesse Gross 
334ccb1352eSJesse Gross 	/* Free all of the segments. */
335ccb1352eSJesse Gross 	skb = segs;
336ccb1352eSJesse Gross 	do {
337ccb1352eSJesse Gross 		nskb = skb->next;
338ccb1352eSJesse Gross 		if (err)
339ccb1352eSJesse Gross 			kfree_skb(skb);
340ccb1352eSJesse Gross 		else
341ccb1352eSJesse Gross 			consume_skb(skb);
342ccb1352eSJesse Gross 	} while ((skb = nskb));
343ccb1352eSJesse Gross 	return err;
344ccb1352eSJesse Gross }
345ccb1352eSJesse Gross 
3468f0aad6fSWenyu Zhang static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
347494bea39SLiping Zhang 			      unsigned int hdrlen, int actions_attrlen)
348c3ff8cfeSThomas Graf {
349c3ff8cfeSThomas Graf 	size_t size = NLMSG_ALIGN(sizeof(struct ovs_header))
350bda56f14SThomas Graf 		+ nla_total_size(hdrlen) /* OVS_PACKET_ATTR_PACKET */
351b95e5928SWilliam Tu 		+ nla_total_size(ovs_key_attr_size()) /* OVS_PACKET_ATTR_KEY */
352b95e5928SWilliam Tu 		+ nla_total_size(sizeof(unsigned int)); /* OVS_PACKET_ATTR_LEN */
353c3ff8cfeSThomas Graf 
354c3ff8cfeSThomas Graf 	/* OVS_PACKET_ATTR_USERDATA */
3558f0aad6fSWenyu Zhang 	if (upcall_info->userdata)
3568f0aad6fSWenyu Zhang 		size += NLA_ALIGN(upcall_info->userdata->nla_len);
3578f0aad6fSWenyu Zhang 
3588f0aad6fSWenyu Zhang 	/* OVS_PACKET_ATTR_EGRESS_TUN_KEY */
3598f0aad6fSWenyu Zhang 	if (upcall_info->egress_tun_info)
3608f0aad6fSWenyu Zhang 		size += nla_total_size(ovs_tun_key_attr_size());
361c3ff8cfeSThomas Graf 
362ccea7445SNeil McKee 	/* OVS_PACKET_ATTR_ACTIONS */
363ccea7445SNeil McKee 	if (upcall_info->actions_len)
364494bea39SLiping Zhang 		size += nla_total_size(actions_attrlen);
365ccea7445SNeil McKee 
3667f8a436eSJoe Stringer 	/* OVS_PACKET_ATTR_MRU */
3677f8a436eSJoe Stringer 	if (upcall_info->mru)
3687f8a436eSJoe Stringer 		size += nla_total_size(sizeof(upcall_info->mru));
3697f8a436eSJoe Stringer 
370c3ff8cfeSThomas Graf 	return size;
371c3ff8cfeSThomas Graf }
372c3ff8cfeSThomas Graf 
3737f8a436eSJoe Stringer static void pad_packet(struct datapath *dp, struct sk_buff *skb)
3747f8a436eSJoe Stringer {
3757f8a436eSJoe Stringer 	if (!(dp->user_features & OVS_DP_F_UNALIGNED)) {
3767f8a436eSJoe Stringer 		size_t plen = NLA_ALIGN(skb->len) - skb->len;
3777f8a436eSJoe Stringer 
3787f8a436eSJoe Stringer 		if (plen > 0)
379b080db58SJohannes Berg 			skb_put_zero(skb, plen);
3807f8a436eSJoe Stringer 	}
3817f8a436eSJoe Stringer }
3827f8a436eSJoe Stringer 
3838055a89cSThomas Graf static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
384e8eedb85SPravin B Shelar 				  const struct sw_flow_key *key,
385f2a4d086SWilliam Tu 				  const struct dp_upcall_info *upcall_info,
386f2a4d086SWilliam Tu 				  uint32_t cutlen)
387ccb1352eSJesse Gross {
388ccb1352eSJesse Gross 	struct ovs_header *upcall;
389ccb1352eSJesse Gross 	struct sk_buff *nskb = NULL;
3904ee45ea0SLi RongQing 	struct sk_buff *user_skb = NULL; /* to be queued to userspace */
391ccb1352eSJesse Gross 	struct nlattr *nla;
392795449d8SThomas Graf 	size_t len;
393bda56f14SThomas Graf 	unsigned int hlen;
3948055a89cSThomas Graf 	int err, dp_ifindex;
3958055a89cSThomas Graf 
3968055a89cSThomas Graf 	dp_ifindex = get_dpifindex(dp);
3978055a89cSThomas Graf 	if (!dp_ifindex)
3988055a89cSThomas Graf 		return -ENODEV;
399ccb1352eSJesse Gross 
400df8a39deSJiri Pirko 	if (skb_vlan_tag_present(skb)) {
401ccb1352eSJesse Gross 		nskb = skb_clone(skb, GFP_ATOMIC);
402ccb1352eSJesse Gross 		if (!nskb)
403ccb1352eSJesse Gross 			return -ENOMEM;
404ccb1352eSJesse Gross 
4055968250cSJiri Pirko 		nskb = __vlan_hwaccel_push_inside(nskb);
4068aa51d64SDan Carpenter 		if (!nskb)
407ccb1352eSJesse Gross 			return -ENOMEM;
408ccb1352eSJesse Gross 
409ccb1352eSJesse Gross 		skb = nskb;
410ccb1352eSJesse Gross 	}
411ccb1352eSJesse Gross 
412ccb1352eSJesse Gross 	if (nla_attr_size(skb->len) > USHRT_MAX) {
413ccb1352eSJesse Gross 		err = -EFBIG;
414ccb1352eSJesse Gross 		goto out;
415ccb1352eSJesse Gross 	}
416ccb1352eSJesse Gross 
417bda56f14SThomas Graf 	/* Complete checksum if needed */
418bda56f14SThomas Graf 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
4197529390dSDavide Caratti 	    (err = skb_csum_hwoffload_help(skb, 0)))
420bda56f14SThomas Graf 		goto out;
421bda56f14SThomas Graf 
422bda56f14SThomas Graf 	/* Older versions of OVS user space enforce alignment of the last
423bda56f14SThomas Graf 	 * Netlink attribute to NLA_ALIGNTO which would require extensive
424bda56f14SThomas Graf 	 * padding logic. Only perform zerocopy if padding is not required.
425bda56f14SThomas Graf 	 */
426bda56f14SThomas Graf 	if (dp->user_features & OVS_DP_F_UNALIGNED)
427bda56f14SThomas Graf 		hlen = skb_zerocopy_headlen(skb);
428bda56f14SThomas Graf 	else
429bda56f14SThomas Graf 		hlen = skb->len;
430bda56f14SThomas Graf 
431494bea39SLiping Zhang 	len = upcall_msg_size(upcall_info, hlen - cutlen,
432494bea39SLiping Zhang 			      OVS_CB(skb)->acts_origlen);
433551ddc05SFlorian Westphal 	user_skb = genlmsg_new(len, GFP_ATOMIC);
434ccb1352eSJesse Gross 	if (!user_skb) {
435ccb1352eSJesse Gross 		err = -ENOMEM;
436ccb1352eSJesse Gross 		goto out;
437ccb1352eSJesse Gross 	}
438ccb1352eSJesse Gross 
439ccb1352eSJesse Gross 	upcall = genlmsg_put(user_skb, 0, 0, &dp_packet_genl_family,
440ccb1352eSJesse Gross 			     0, upcall_info->cmd);
4416f19893bSKangjie Lu 	if (!upcall) {
4426f19893bSKangjie Lu 		err = -EINVAL;
4436f19893bSKangjie Lu 		goto out;
4446f19893bSKangjie Lu 	}
445ccb1352eSJesse Gross 	upcall->dp_ifindex = dp_ifindex;
446ccb1352eSJesse Gross 
4475b4237bbSJoe Stringer 	err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, user_skb);
448a734d1f4SEelco Chaudron 	if (err)
449a734d1f4SEelco Chaudron 		goto out;
450ccb1352eSJesse Gross 
451ccb1352eSJesse Gross 	if (upcall_info->userdata)
4524490108bSBen Pfaff 		__nla_put(user_skb, OVS_PACKET_ATTR_USERDATA,
4534490108bSBen Pfaff 			  nla_len(upcall_info->userdata),
4544490108bSBen Pfaff 			  nla_data(upcall_info->userdata));
455ccb1352eSJesse Gross 
4568f0aad6fSWenyu Zhang 	if (upcall_info->egress_tun_info) {
457ae0be8deSMichal Kubecek 		nla = nla_nest_start_noflag(user_skb,
458ae0be8deSMichal Kubecek 					    OVS_PACKET_ATTR_EGRESS_TUN_KEY);
4590fff9bd4SKangjie Lu 		if (!nla) {
4600fff9bd4SKangjie Lu 			err = -EMSGSIZE;
4610fff9bd4SKangjie Lu 			goto out;
4620fff9bd4SKangjie Lu 		}
463fc4099f1SPravin B Shelar 		err = ovs_nla_put_tunnel_info(user_skb,
464fc4099f1SPravin B Shelar 					      upcall_info->egress_tun_info);
465a734d1f4SEelco Chaudron 		if (err)
466a734d1f4SEelco Chaudron 			goto out;
467a734d1f4SEelco Chaudron 
4688f0aad6fSWenyu Zhang 		nla_nest_end(user_skb, nla);
4698f0aad6fSWenyu Zhang 	}
4708f0aad6fSWenyu Zhang 
471ccea7445SNeil McKee 	if (upcall_info->actions_len) {
472ae0be8deSMichal Kubecek 		nla = nla_nest_start_noflag(user_skb, OVS_PACKET_ATTR_ACTIONS);
4730fff9bd4SKangjie Lu 		if (!nla) {
4740fff9bd4SKangjie Lu 			err = -EMSGSIZE;
4750fff9bd4SKangjie Lu 			goto out;
4760fff9bd4SKangjie Lu 		}
477ccea7445SNeil McKee 		err = ovs_nla_put_actions(upcall_info->actions,
478ccea7445SNeil McKee 					  upcall_info->actions_len,
479ccea7445SNeil McKee 					  user_skb);
480ccea7445SNeil McKee 		if (!err)
481ccea7445SNeil McKee 			nla_nest_end(user_skb, nla);
482ccea7445SNeil McKee 		else
483ccea7445SNeil McKee 			nla_nest_cancel(user_skb, nla);
484ccea7445SNeil McKee 	}
485ccea7445SNeil McKee 
4867f8a436eSJoe Stringer 	/* Add OVS_PACKET_ATTR_MRU */
4877f8a436eSJoe Stringer 	if (upcall_info->mru) {
4887f8a436eSJoe Stringer 		if (nla_put_u16(user_skb, OVS_PACKET_ATTR_MRU,
4897f8a436eSJoe Stringer 				upcall_info->mru)) {
4907f8a436eSJoe Stringer 			err = -ENOBUFS;
4917f8a436eSJoe Stringer 			goto out;
4927f8a436eSJoe Stringer 		}
4937f8a436eSJoe Stringer 		pad_packet(dp, user_skb);
4947f8a436eSJoe Stringer 	}
4957f8a436eSJoe Stringer 
496b95e5928SWilliam Tu 	/* Add OVS_PACKET_ATTR_LEN when packet is truncated */
497b95e5928SWilliam Tu 	if (cutlen > 0) {
498b95e5928SWilliam Tu 		if (nla_put_u32(user_skb, OVS_PACKET_ATTR_LEN,
499b95e5928SWilliam Tu 				skb->len)) {
500b95e5928SWilliam Tu 			err = -ENOBUFS;
501b95e5928SWilliam Tu 			goto out;
502b95e5928SWilliam Tu 		}
503b95e5928SWilliam Tu 		pad_packet(dp, user_skb);
504b95e5928SWilliam Tu 	}
505b95e5928SWilliam Tu 
506bda56f14SThomas Graf 	/* Only reserve room for attribute header, packet data is added
507bda56f14SThomas Graf 	 * in skb_zerocopy() */
508bda56f14SThomas Graf 	if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) {
509bda56f14SThomas Graf 		err = -ENOBUFS;
510bda56f14SThomas Graf 		goto out;
511bda56f14SThomas Graf 	}
512f2a4d086SWilliam Tu 	nla->nla_len = nla_attr_size(skb->len - cutlen);
513ccb1352eSJesse Gross 
514f2a4d086SWilliam Tu 	err = skb_zerocopy(user_skb, skb, skb->len - cutlen, hlen);
51536d5fe6aSZoltan Kiss 	if (err)
51636d5fe6aSZoltan Kiss 		goto out;
517ccb1352eSJesse Gross 
518aea0bb4fSThomas Graf 	/* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */
5197f8a436eSJoe Stringer 	pad_packet(dp, user_skb);
520aea0bb4fSThomas Graf 
521bda56f14SThomas Graf 	((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len;
522bda56f14SThomas Graf 
5238055a89cSThomas Graf 	err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);
5244ee45ea0SLi RongQing 	user_skb = NULL;
525ccb1352eSJesse Gross out:
52636d5fe6aSZoltan Kiss 	if (err)
52736d5fe6aSZoltan Kiss 		skb_tx_error(skb);
5284ee45ea0SLi RongQing 	kfree_skb(user_skb);
529ccb1352eSJesse Gross 	kfree_skb(nskb);
530ccb1352eSJesse Gross 	return err;
531ccb1352eSJesse Gross }
532ccb1352eSJesse Gross 
533ccb1352eSJesse Gross static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
534ccb1352eSJesse Gross {
535ccb1352eSJesse Gross 	struct ovs_header *ovs_header = info->userhdr;
5367f8a436eSJoe Stringer 	struct net *net = sock_net(skb->sk);
537ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
538ccb1352eSJesse Gross 	struct sw_flow_actions *acts;
539ccb1352eSJesse Gross 	struct sk_buff *packet;
540ccb1352eSJesse Gross 	struct sw_flow *flow;
541d98612b8SLorand Jakab 	struct sw_flow_actions *sf_acts;
542ccb1352eSJesse Gross 	struct datapath *dp;
54383c8df26SPravin B Shelar 	struct vport *input_vport;
5447f8a436eSJoe Stringer 	u16 mru = 0;
545ccb1352eSJesse Gross 	int len;
546ccb1352eSJesse Gross 	int err;
5471ba39804SThomas Graf 	bool log = !a[OVS_PACKET_ATTR_PROBE];
548ccb1352eSJesse Gross 
549ccb1352eSJesse Gross 	err = -EINVAL;
550ccb1352eSJesse Gross 	if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] ||
551dded45fcSThomas Graf 	    !a[OVS_PACKET_ATTR_ACTIONS])
552ccb1352eSJesse Gross 		goto err;
553ccb1352eSJesse Gross 
554ccb1352eSJesse Gross 	len = nla_len(a[OVS_PACKET_ATTR_PACKET]);
555ccb1352eSJesse Gross 	packet = __dev_alloc_skb(NET_IP_ALIGN + len, GFP_KERNEL);
556ccb1352eSJesse Gross 	err = -ENOMEM;
557ccb1352eSJesse Gross 	if (!packet)
558ccb1352eSJesse Gross 		goto err;
559ccb1352eSJesse Gross 	skb_reserve(packet, NET_IP_ALIGN);
560ccb1352eSJesse Gross 
56132686a9dSThomas Graf 	nla_memcpy(__skb_put(packet, len), a[OVS_PACKET_ATTR_PACKET], len);
562ccb1352eSJesse Gross 
5637f8a436eSJoe Stringer 	/* Set packet's mru */
5647f8a436eSJoe Stringer 	if (a[OVS_PACKET_ATTR_MRU]) {
5657f8a436eSJoe Stringer 		mru = nla_get_u16(a[OVS_PACKET_ATTR_MRU]);
5667f8a436eSJoe Stringer 		packet->ignore_df = 1;
5677f8a436eSJoe Stringer 	}
5687f8a436eSJoe Stringer 	OVS_CB(packet)->mru = mru;
5697f8a436eSJoe Stringer 
570ccb1352eSJesse Gross 	/* Build an sw_flow for sending this packet. */
57123dabf88SJarno Rajahalme 	flow = ovs_flow_alloc();
572ccb1352eSJesse Gross 	err = PTR_ERR(flow);
573ccb1352eSJesse Gross 	if (IS_ERR(flow))
574ccb1352eSJesse Gross 		goto err_kfree_skb;
575ccb1352eSJesse Gross 
576c2ac6673SJoe Stringer 	err = ovs_flow_key_extract_userspace(net, a[OVS_PACKET_ATTR_KEY],
577c2ac6673SJoe Stringer 					     packet, &flow->key, log);
578ccb1352eSJesse Gross 	if (err)
579ccb1352eSJesse Gross 		goto err_flow_free;
580ccb1352eSJesse Gross 
5817f8a436eSJoe Stringer 	err = ovs_nla_copy_actions(net, a[OVS_PACKET_ATTR_ACTIONS],
58205da5898SJarno Rajahalme 				   &flow->key, &acts, log);
58374f84a57SPravin B Shelar 	if (err)
58474f84a57SPravin B Shelar 		goto err_flow_free;
585ccb1352eSJesse Gross 
586f5796684SJesse Gross 	rcu_assign_pointer(flow->sf_acts, acts);
587ccb1352eSJesse Gross 	packet->priority = flow->key.phy.priority;
58839c7caebSAnsis Atteka 	packet->mark = flow->key.phy.skb_mark;
589ccb1352eSJesse Gross 
590ccb1352eSJesse Gross 	rcu_read_lock();
5917f8a436eSJoe Stringer 	dp = get_dp_rcu(net, ovs_header->dp_ifindex);
592ccb1352eSJesse Gross 	err = -ENODEV;
593ccb1352eSJesse Gross 	if (!dp)
594ccb1352eSJesse Gross 		goto err_unlock;
595ccb1352eSJesse Gross 
59683c8df26SPravin B Shelar 	input_vport = ovs_vport_rcu(dp, flow->key.phy.in_port);
59783c8df26SPravin B Shelar 	if (!input_vport)
59883c8df26SPravin B Shelar 		input_vport = ovs_vport_rcu(dp, OVSP_LOCAL);
59983c8df26SPravin B Shelar 
60083c8df26SPravin B Shelar 	if (!input_vport)
60183c8df26SPravin B Shelar 		goto err_unlock;
60283c8df26SPravin B Shelar 
6037f8a436eSJoe Stringer 	packet->dev = input_vport->dev;
60483c8df26SPravin B Shelar 	OVS_CB(packet)->input_vport = input_vport;
605d98612b8SLorand Jakab 	sf_acts = rcu_dereference(flow->sf_acts);
60683c8df26SPravin B Shelar 
607ccb1352eSJesse Gross 	local_bh_disable();
608d98612b8SLorand Jakab 	err = ovs_execute_actions(dp, packet, sf_acts, &flow->key);
609ccb1352eSJesse Gross 	local_bh_enable();
610ccb1352eSJesse Gross 	rcu_read_unlock();
611ccb1352eSJesse Gross 
61203f0d916SAndy Zhou 	ovs_flow_free(flow, false);
613ccb1352eSJesse Gross 	return err;
614ccb1352eSJesse Gross 
615ccb1352eSJesse Gross err_unlock:
616ccb1352eSJesse Gross 	rcu_read_unlock();
617ccb1352eSJesse Gross err_flow_free:
61803f0d916SAndy Zhou 	ovs_flow_free(flow, false);
619ccb1352eSJesse Gross err_kfree_skb:
620ccb1352eSJesse Gross 	kfree_skb(packet);
621ccb1352eSJesse Gross err:
622ccb1352eSJesse Gross 	return err;
623ccb1352eSJesse Gross }
624ccb1352eSJesse Gross 
625ccb1352eSJesse Gross static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = {
626dded45fcSThomas Graf 	[OVS_PACKET_ATTR_PACKET] = { .len = ETH_HLEN },
627ccb1352eSJesse Gross 	[OVS_PACKET_ATTR_KEY] = { .type = NLA_NESTED },
628ccb1352eSJesse Gross 	[OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED },
6291ba39804SThomas Graf 	[OVS_PACKET_ATTR_PROBE] = { .type = NLA_FLAG },
6307f8a436eSJoe Stringer 	[OVS_PACKET_ATTR_MRU] = { .type = NLA_U16 },
631ccb1352eSJesse Gross };
632ccb1352eSJesse Gross 
6334534de83SJohannes Berg static const struct genl_ops dp_packet_genl_ops[] = {
634ccb1352eSJesse Gross 	{ .cmd = OVS_PACKET_CMD_EXECUTE,
635ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6364a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
637ccb1352eSJesse Gross 	  .doit = ovs_packet_cmd_execute
638ccb1352eSJesse Gross 	}
639ccb1352eSJesse Gross };
640ccb1352eSJesse Gross 
64156989f6dSJohannes Berg static struct genl_family dp_packet_genl_family __ro_after_init = {
6420c200ef9SPravin B Shelar 	.hdrsize = sizeof(struct ovs_header),
6430c200ef9SPravin B Shelar 	.name = OVS_PACKET_FAMILY,
6440c200ef9SPravin B Shelar 	.version = OVS_PACKET_VERSION,
6450c200ef9SPravin B Shelar 	.maxattr = OVS_PACKET_ATTR_MAX,
6463b0f31f2SJohannes Berg 	.policy = packet_policy,
6470c200ef9SPravin B Shelar 	.netnsok = true,
6480c200ef9SPravin B Shelar 	.parallel_ops = true,
6490c200ef9SPravin B Shelar 	.ops = dp_packet_genl_ops,
6500c200ef9SPravin B Shelar 	.n_ops = ARRAY_SIZE(dp_packet_genl_ops),
651489111e5SJohannes Berg 	.module = THIS_MODULE,
6520c200ef9SPravin B Shelar };
6530c200ef9SPravin B Shelar 
65412eb18f7SThomas Graf static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
6551bd7116fSAndy Zhou 			 struct ovs_dp_megaflow_stats *mega_stats)
656ccb1352eSJesse Gross {
657ccb1352eSJesse Gross 	int i;
658ccb1352eSJesse Gross 
6591bd7116fSAndy Zhou 	memset(mega_stats, 0, sizeof(*mega_stats));
6601bd7116fSAndy Zhou 
661b637e498SPravin B Shelar 	stats->n_flows = ovs_flow_tbl_count(&dp->table);
6621bd7116fSAndy Zhou 	mega_stats->n_masks = ovs_flow_tbl_num_masks(&dp->table);
663ccb1352eSJesse Gross 
664ccb1352eSJesse Gross 	stats->n_hit = stats->n_missed = stats->n_lost = 0;
6651bd7116fSAndy Zhou 
666ccb1352eSJesse Gross 	for_each_possible_cpu(i) {
667ccb1352eSJesse Gross 		const struct dp_stats_percpu *percpu_stats;
668ccb1352eSJesse Gross 		struct dp_stats_percpu local_stats;
669ccb1352eSJesse Gross 		unsigned int start;
670ccb1352eSJesse Gross 
671ccb1352eSJesse Gross 		percpu_stats = per_cpu_ptr(dp->stats_percpu, i);
672ccb1352eSJesse Gross 
673ccb1352eSJesse Gross 		do {
67457a7744eSEric W. Biederman 			start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
675ccb1352eSJesse Gross 			local_stats = *percpu_stats;
67657a7744eSEric W. Biederman 		} while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
677ccb1352eSJesse Gross 
678ccb1352eSJesse Gross 		stats->n_hit += local_stats.n_hit;
679ccb1352eSJesse Gross 		stats->n_missed += local_stats.n_missed;
680ccb1352eSJesse Gross 		stats->n_lost += local_stats.n_lost;
6811bd7116fSAndy Zhou 		mega_stats->n_mask_hit += local_stats.n_mask_hit;
682ccb1352eSJesse Gross 	}
683ccb1352eSJesse Gross }
684ccb1352eSJesse Gross 
68574ed7ab9SJoe Stringer static bool should_fill_key(const struct sw_flow_id *sfid, uint32_t ufid_flags)
686c3ff8cfeSThomas Graf {
68774ed7ab9SJoe Stringer 	return ovs_identifier_is_ufid(sfid) &&
68874ed7ab9SJoe Stringer 	       !(ufid_flags & OVS_UFID_F_OMIT_KEY);
68974ed7ab9SJoe Stringer }
69074ed7ab9SJoe Stringer 
69174ed7ab9SJoe Stringer static bool should_fill_mask(uint32_t ufid_flags)
69274ed7ab9SJoe Stringer {
69374ed7ab9SJoe Stringer 	return !(ufid_flags & OVS_UFID_F_OMIT_MASK);
69474ed7ab9SJoe Stringer }
69574ed7ab9SJoe Stringer 
69674ed7ab9SJoe Stringer static bool should_fill_actions(uint32_t ufid_flags)
69774ed7ab9SJoe Stringer {
69874ed7ab9SJoe Stringer 	return !(ufid_flags & OVS_UFID_F_OMIT_ACTIONS);
69974ed7ab9SJoe Stringer }
70074ed7ab9SJoe Stringer 
70174ed7ab9SJoe Stringer static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts,
70274ed7ab9SJoe Stringer 				    const struct sw_flow_id *sfid,
70374ed7ab9SJoe Stringer 				    uint32_t ufid_flags)
70474ed7ab9SJoe Stringer {
70574ed7ab9SJoe Stringer 	size_t len = NLMSG_ALIGN(sizeof(struct ovs_header));
70674ed7ab9SJoe Stringer 
70774ed7ab9SJoe Stringer 	/* OVS_FLOW_ATTR_UFID */
70874ed7ab9SJoe Stringer 	if (sfid && ovs_identifier_is_ufid(sfid))
70974ed7ab9SJoe Stringer 		len += nla_total_size(sfid->ufid_len);
71074ed7ab9SJoe Stringer 
71174ed7ab9SJoe Stringer 	/* OVS_FLOW_ATTR_KEY */
71274ed7ab9SJoe Stringer 	if (!sfid || should_fill_key(sfid, ufid_flags))
71374ed7ab9SJoe Stringer 		len += nla_total_size(ovs_key_attr_size());
71474ed7ab9SJoe Stringer 
71574ed7ab9SJoe Stringer 	/* OVS_FLOW_ATTR_MASK */
71674ed7ab9SJoe Stringer 	if (should_fill_mask(ufid_flags))
71774ed7ab9SJoe Stringer 		len += nla_total_size(ovs_key_attr_size());
71874ed7ab9SJoe Stringer 
71974ed7ab9SJoe Stringer 	/* OVS_FLOW_ATTR_ACTIONS */
72074ed7ab9SJoe Stringer 	if (should_fill_actions(ufid_flags))
7218e2fed1cSJoe Stringer 		len += nla_total_size(acts->orig_len);
72274ed7ab9SJoe Stringer 
72374ed7ab9SJoe Stringer 	return len
72466c7a5eeSNicolas Dichtel 		+ nla_total_size_64bit(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */
725c3ff8cfeSThomas Graf 		+ nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */
72666c7a5eeSNicolas Dichtel 		+ nla_total_size_64bit(8); /* OVS_FLOW_ATTR_USED */
727c3ff8cfeSThomas Graf }
728c3ff8cfeSThomas Graf 
729bb6f9a70SJarno Rajahalme /* Called with ovs_mutex or RCU read lock. */
730ca7105f2SJoe Stringer static int ovs_flow_cmd_fill_stats(const struct sw_flow *flow,
731ca7105f2SJoe Stringer 				   struct sk_buff *skb)
732ca7105f2SJoe Stringer {
733ca7105f2SJoe Stringer 	struct ovs_flow_stats stats;
734ca7105f2SJoe Stringer 	__be16 tcp_flags;
735ca7105f2SJoe Stringer 	unsigned long used;
73603f0d916SAndy Zhou 
737e298e505SPravin B Shelar 	ovs_flow_stats_get(flow, &stats, &used, &tcp_flags);
7380e9796b4SJarno Rajahalme 
739028d6a67SDavid S. Miller 	if (used &&
7400238b720SNicolas Dichtel 	    nla_put_u64_64bit(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used),
7410238b720SNicolas Dichtel 			      OVS_FLOW_ATTR_PAD))
742ca7105f2SJoe Stringer 		return -EMSGSIZE;
743ccb1352eSJesse Gross 
744028d6a67SDavid S. Miller 	if (stats.n_packets &&
74566c7a5eeSNicolas Dichtel 	    nla_put_64bit(skb, OVS_FLOW_ATTR_STATS,
74666c7a5eeSNicolas Dichtel 			  sizeof(struct ovs_flow_stats), &stats,
74766c7a5eeSNicolas Dichtel 			  OVS_FLOW_ATTR_PAD))
748ca7105f2SJoe Stringer 		return -EMSGSIZE;
749ccb1352eSJesse Gross 
750e298e505SPravin B Shelar 	if ((u8)ntohs(tcp_flags) &&
751e298e505SPravin B Shelar 	     nla_put_u8(skb, OVS_FLOW_ATTR_TCP_FLAGS, (u8)ntohs(tcp_flags)))
752ca7105f2SJoe Stringer 		return -EMSGSIZE;
753ca7105f2SJoe Stringer 
754ca7105f2SJoe Stringer 	return 0;
755ca7105f2SJoe Stringer }
756ca7105f2SJoe Stringer 
757ca7105f2SJoe Stringer /* Called with ovs_mutex or RCU read lock. */
758ca7105f2SJoe Stringer static int ovs_flow_cmd_fill_actions(const struct sw_flow *flow,
759ca7105f2SJoe Stringer 				     struct sk_buff *skb, int skb_orig_len)
760ca7105f2SJoe Stringer {
761ca7105f2SJoe Stringer 	struct nlattr *start;
762ca7105f2SJoe Stringer 	int err;
763ccb1352eSJesse Gross 
764ccb1352eSJesse Gross 	/* If OVS_FLOW_ATTR_ACTIONS doesn't fit, skip dumping the actions if
765ccb1352eSJesse Gross 	 * this is the first flow to be dumped into 'skb'.  This is unusual for
766ccb1352eSJesse Gross 	 * Netlink but individual action lists can be longer than
767ccb1352eSJesse Gross 	 * NLMSG_GOODSIZE and thus entirely undumpable if we didn't do this.
768ccb1352eSJesse Gross 	 * The userspace caller can always fetch the actions separately if it
769ccb1352eSJesse Gross 	 * really wants them.  (Most userspace callers in fact don't care.)
770ccb1352eSJesse Gross 	 *
771ccb1352eSJesse Gross 	 * This can only fail for dump operations because the skb is always
772ccb1352eSJesse Gross 	 * properly sized for single flows.
773ccb1352eSJesse Gross 	 */
774ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_FLOW_ATTR_ACTIONS);
77574f84a57SPravin B Shelar 	if (start) {
776d57170b1SPravin B Shelar 		const struct sw_flow_actions *sf_acts;
777d57170b1SPravin B Shelar 
778663efa36SJesse Gross 		sf_acts = rcu_dereference_ovsl(flow->sf_acts);
779e6445719SPravin B Shelar 		err = ovs_nla_put_actions(sf_acts->actions,
780e6445719SPravin B Shelar 					  sf_acts->actions_len, skb);
7810e9796b4SJarno Rajahalme 
78274f84a57SPravin B Shelar 		if (!err)
78374f84a57SPravin B Shelar 			nla_nest_end(skb, start);
78474f84a57SPravin B Shelar 		else {
78574f84a57SPravin B Shelar 			if (skb_orig_len)
786ca7105f2SJoe Stringer 				return err;
787ccb1352eSJesse Gross 
78874f84a57SPravin B Shelar 			nla_nest_cancel(skb, start);
78974f84a57SPravin B Shelar 		}
790ca7105f2SJoe Stringer 	} else if (skb_orig_len) {
791ca7105f2SJoe Stringer 		return -EMSGSIZE;
792ca7105f2SJoe Stringer 	}
793ca7105f2SJoe Stringer 
794ca7105f2SJoe Stringer 	return 0;
795ca7105f2SJoe Stringer }
796ca7105f2SJoe Stringer 
797ca7105f2SJoe Stringer /* Called with ovs_mutex or RCU read lock. */
798ca7105f2SJoe Stringer static int ovs_flow_cmd_fill_info(const struct sw_flow *flow, int dp_ifindex,
799ca7105f2SJoe Stringer 				  struct sk_buff *skb, u32 portid,
80074ed7ab9SJoe Stringer 				  u32 seq, u32 flags, u8 cmd, u32 ufid_flags)
801ca7105f2SJoe Stringer {
802ca7105f2SJoe Stringer 	const int skb_orig_len = skb->len;
803ca7105f2SJoe Stringer 	struct ovs_header *ovs_header;
804ca7105f2SJoe Stringer 	int err;
805ca7105f2SJoe Stringer 
806ca7105f2SJoe Stringer 	ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family,
807ca7105f2SJoe Stringer 				 flags, cmd);
808ca7105f2SJoe Stringer 	if (!ovs_header)
809ca7105f2SJoe Stringer 		return -EMSGSIZE;
810ca7105f2SJoe Stringer 
811ca7105f2SJoe Stringer 	ovs_header->dp_ifindex = dp_ifindex;
812ca7105f2SJoe Stringer 
81374ed7ab9SJoe Stringer 	err = ovs_nla_put_identifier(flow, skb);
8145b4237bbSJoe Stringer 	if (err)
8155b4237bbSJoe Stringer 		goto error;
8165b4237bbSJoe Stringer 
81774ed7ab9SJoe Stringer 	if (should_fill_key(&flow->id, ufid_flags)) {
81874ed7ab9SJoe Stringer 		err = ovs_nla_put_masked_key(flow, skb);
81974ed7ab9SJoe Stringer 		if (err)
82074ed7ab9SJoe Stringer 			goto error;
82174ed7ab9SJoe Stringer 	}
82274ed7ab9SJoe Stringer 
82374ed7ab9SJoe Stringer 	if (should_fill_mask(ufid_flags)) {
8245b4237bbSJoe Stringer 		err = ovs_nla_put_mask(flow, skb);
825ca7105f2SJoe Stringer 		if (err)
826ca7105f2SJoe Stringer 			goto error;
82774ed7ab9SJoe Stringer 	}
828ca7105f2SJoe Stringer 
829ca7105f2SJoe Stringer 	err = ovs_flow_cmd_fill_stats(flow, skb);
830ca7105f2SJoe Stringer 	if (err)
831ca7105f2SJoe Stringer 		goto error;
832ca7105f2SJoe Stringer 
83374ed7ab9SJoe Stringer 	if (should_fill_actions(ufid_flags)) {
834ca7105f2SJoe Stringer 		err = ovs_flow_cmd_fill_actions(flow, skb, skb_orig_len);
835ca7105f2SJoe Stringer 		if (err)
836ca7105f2SJoe Stringer 			goto error;
83774ed7ab9SJoe Stringer 	}
83874f84a57SPravin B Shelar 
839053c095aSJohannes Berg 	genlmsg_end(skb, ovs_header);
840053c095aSJohannes Berg 	return 0;
841ccb1352eSJesse Gross 
842ccb1352eSJesse Gross error:
843ccb1352eSJesse Gross 	genlmsg_cancel(skb, ovs_header);
844ccb1352eSJesse Gross 	return err;
845ccb1352eSJesse Gross }
846ccb1352eSJesse Gross 
8470e9796b4SJarno Rajahalme /* May not be called with RCU read lock. */
8480e9796b4SJarno Rajahalme static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *acts,
84974ed7ab9SJoe Stringer 					       const struct sw_flow_id *sfid,
850fb5d1e9eSJarno Rajahalme 					       struct genl_info *info,
85174ed7ab9SJoe Stringer 					       bool always,
85274ed7ab9SJoe Stringer 					       uint32_t ufid_flags)
853ccb1352eSJesse Gross {
854fb5d1e9eSJarno Rajahalme 	struct sk_buff *skb;
85574ed7ab9SJoe Stringer 	size_t len;
856ccb1352eSJesse Gross 
8579b67aa4aSSamuel Gauthier 	if (!always && !ovs_must_notify(&dp_flow_genl_family, info, 0))
858fb5d1e9eSJarno Rajahalme 		return NULL;
859fb5d1e9eSJarno Rajahalme 
86074ed7ab9SJoe Stringer 	len = ovs_flow_cmd_msg_size(acts, sfid, ufid_flags);
861551ddc05SFlorian Westphal 	skb = genlmsg_new(len, GFP_KERNEL);
862fb5d1e9eSJarno Rajahalme 	if (!skb)
863fb5d1e9eSJarno Rajahalme 		return ERR_PTR(-ENOMEM);
864fb5d1e9eSJarno Rajahalme 
865fb5d1e9eSJarno Rajahalme 	return skb;
866ccb1352eSJesse Gross }
867ccb1352eSJesse Gross 
8680e9796b4SJarno Rajahalme /* Called with ovs_mutex. */
8690e9796b4SJarno Rajahalme static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow,
8700e9796b4SJarno Rajahalme 					       int dp_ifindex,
8710e9796b4SJarno Rajahalme 					       struct genl_info *info, u8 cmd,
87274ed7ab9SJoe Stringer 					       bool always, u32 ufid_flags)
873ccb1352eSJesse Gross {
874ccb1352eSJesse Gross 	struct sk_buff *skb;
875ccb1352eSJesse Gross 	int retval;
876ccb1352eSJesse Gross 
87774ed7ab9SJoe Stringer 	skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts),
87874ed7ab9SJoe Stringer 				      &flow->id, info, always, ufid_flags);
879d0e992aaSHimangi Saraogi 	if (IS_ERR_OR_NULL(skb))
880fb5d1e9eSJarno Rajahalme 		return skb;
881ccb1352eSJesse Gross 
8820e9796b4SJarno Rajahalme 	retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb,
8830e9796b4SJarno Rajahalme 					info->snd_portid, info->snd_seq, 0,
88474ed7ab9SJoe Stringer 					cmd, ufid_flags);
885ccb1352eSJesse Gross 	BUG_ON(retval < 0);
886ccb1352eSJesse Gross 	return skb;
887ccb1352eSJesse Gross }
888ccb1352eSJesse Gross 
88937bdc87bSJarno Rajahalme static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
890ccb1352eSJesse Gross {
8917f8a436eSJoe Stringer 	struct net *net = sock_net(skb->sk);
892ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
893ccb1352eSJesse Gross 	struct ovs_header *ovs_header = info->userhdr;
89474ed7ab9SJoe Stringer 	struct sw_flow *flow = NULL, *new_flow;
89503f0d916SAndy Zhou 	struct sw_flow_mask mask;
896ccb1352eSJesse Gross 	struct sk_buff *reply;
897ccb1352eSJesse Gross 	struct datapath *dp;
89837bdc87bSJarno Rajahalme 	struct sw_flow_actions *acts;
89937bdc87bSJarno Rajahalme 	struct sw_flow_match match;
90074ed7ab9SJoe Stringer 	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
90137bdc87bSJarno Rajahalme 	int error;
90205da5898SJarno Rajahalme 	bool log = !a[OVS_FLOW_ATTR_PROBE];
90337bdc87bSJarno Rajahalme 
904893f139bSJarno Rajahalme 	/* Must have key and actions. */
90537bdc87bSJarno Rajahalme 	error = -EINVAL;
906426cda5cSJesse Gross 	if (!a[OVS_FLOW_ATTR_KEY]) {
90705da5898SJarno Rajahalme 		OVS_NLERR(log, "Flow key attr not present in new flow.");
90837bdc87bSJarno Rajahalme 		goto error;
909426cda5cSJesse Gross 	}
910426cda5cSJesse Gross 	if (!a[OVS_FLOW_ATTR_ACTIONS]) {
91105da5898SJarno Rajahalme 		OVS_NLERR(log, "Flow actions attr not present in new flow.");
91237bdc87bSJarno Rajahalme 		goto error;
913426cda5cSJesse Gross 	}
91437bdc87bSJarno Rajahalme 
915893f139bSJarno Rajahalme 	/* Most of the time we need to allocate a new flow, do it before
916893f139bSJarno Rajahalme 	 * locking.
917893f139bSJarno Rajahalme 	 */
918893f139bSJarno Rajahalme 	new_flow = ovs_flow_alloc();
919893f139bSJarno Rajahalme 	if (IS_ERR(new_flow)) {
920893f139bSJarno Rajahalme 		error = PTR_ERR(new_flow);
921893f139bSJarno Rajahalme 		goto error;
922893f139bSJarno Rajahalme 	}
923893f139bSJarno Rajahalme 
924893f139bSJarno Rajahalme 	/* Extract key. */
9252279994dSpravin shelar 	ovs_match_init(&match, &new_flow->key, false, &mask);
926c2ac6673SJoe Stringer 	error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
92705da5898SJarno Rajahalme 				  a[OVS_FLOW_ATTR_MASK], log);
928893f139bSJarno Rajahalme 	if (error)
929893f139bSJarno Rajahalme 		goto err_kfree_flow;
930893f139bSJarno Rajahalme 
93174ed7ab9SJoe Stringer 	/* Extract flow identifier. */
93274ed7ab9SJoe Stringer 	error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
933190aa3e7Spravin shelar 				       &new_flow->key, log);
93474ed7ab9SJoe Stringer 	if (error)
93574ed7ab9SJoe Stringer 		goto err_kfree_flow;
936893f139bSJarno Rajahalme 
937190aa3e7Spravin shelar 	/* unmasked key is needed to match when ufid is not used. */
938190aa3e7Spravin shelar 	if (ovs_identifier_is_key(&new_flow->id))
939190aa3e7Spravin shelar 		match.key = new_flow->id.unmasked_key;
940190aa3e7Spravin shelar 
941190aa3e7Spravin shelar 	ovs_flow_mask_key(&new_flow->key, &new_flow->key, true, &mask);
942190aa3e7Spravin shelar 
943893f139bSJarno Rajahalme 	/* Validate actions. */
9447f8a436eSJoe Stringer 	error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
9457f8a436eSJoe Stringer 				     &new_flow->key, &acts, log);
94637bdc87bSJarno Rajahalme 	if (error) {
94705da5898SJarno Rajahalme 		OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
9482fdb957dSPravin B Shelar 		goto err_kfree_flow;
949893f139bSJarno Rajahalme 	}
950893f139bSJarno Rajahalme 
95174ed7ab9SJoe Stringer 	reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
95274ed7ab9SJoe Stringer 					ufid_flags);
953893f139bSJarno Rajahalme 	if (IS_ERR(reply)) {
954893f139bSJarno Rajahalme 		error = PTR_ERR(reply);
955893f139bSJarno Rajahalme 		goto err_kfree_acts;
95637bdc87bSJarno Rajahalme 	}
95737bdc87bSJarno Rajahalme 
95837bdc87bSJarno Rajahalme 	ovs_lock();
9597f8a436eSJoe Stringer 	dp = get_dp(net, ovs_header->dp_ifindex);
960893f139bSJarno Rajahalme 	if (unlikely(!dp)) {
96137bdc87bSJarno Rajahalme 		error = -ENODEV;
96237bdc87bSJarno Rajahalme 		goto err_unlock_ovs;
96337bdc87bSJarno Rajahalme 	}
96474ed7ab9SJoe Stringer 
965893f139bSJarno Rajahalme 	/* Check if this is a duplicate flow */
96674ed7ab9SJoe Stringer 	if (ovs_identifier_is_ufid(&new_flow->id))
96774ed7ab9SJoe Stringer 		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);
96874ed7ab9SJoe Stringer 	if (!flow)
969190aa3e7Spravin shelar 		flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->key);
970893f139bSJarno Rajahalme 	if (likely(!flow)) {
971893f139bSJarno Rajahalme 		rcu_assign_pointer(new_flow->sf_acts, acts);
97237bdc87bSJarno Rajahalme 
97337bdc87bSJarno Rajahalme 		/* Put flow in bucket. */
974893f139bSJarno Rajahalme 		error = ovs_flow_tbl_insert(&dp->table, new_flow, &mask);
975893f139bSJarno Rajahalme 		if (unlikely(error)) {
97637bdc87bSJarno Rajahalme 			acts = NULL;
977893f139bSJarno Rajahalme 			goto err_unlock_ovs;
97837bdc87bSJarno Rajahalme 		}
979893f139bSJarno Rajahalme 
980893f139bSJarno Rajahalme 		if (unlikely(reply)) {
981893f139bSJarno Rajahalme 			error = ovs_flow_cmd_fill_info(new_flow,
982893f139bSJarno Rajahalme 						       ovs_header->dp_ifindex,
983893f139bSJarno Rajahalme 						       reply, info->snd_portid,
984893f139bSJarno Rajahalme 						       info->snd_seq, 0,
98574ed7ab9SJoe Stringer 						       OVS_FLOW_CMD_NEW,
98674ed7ab9SJoe Stringer 						       ufid_flags);
987893f139bSJarno Rajahalme 			BUG_ON(error < 0);
988893f139bSJarno Rajahalme 		}
989893f139bSJarno Rajahalme 		ovs_unlock();
99037bdc87bSJarno Rajahalme 	} else {
99137bdc87bSJarno Rajahalme 		struct sw_flow_actions *old_acts;
99237bdc87bSJarno Rajahalme 
99337bdc87bSJarno Rajahalme 		/* Bail out if we're not allowed to modify an existing flow.
99437bdc87bSJarno Rajahalme 		 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
99537bdc87bSJarno Rajahalme 		 * because Generic Netlink treats the latter as a dump
99637bdc87bSJarno Rajahalme 		 * request.  We also accept NLM_F_EXCL in case that bug ever
99737bdc87bSJarno Rajahalme 		 * gets fixed.
99837bdc87bSJarno Rajahalme 		 */
999893f139bSJarno Rajahalme 		if (unlikely(info->nlhdr->nlmsg_flags & (NLM_F_CREATE
1000893f139bSJarno Rajahalme 							 | NLM_F_EXCL))) {
100137bdc87bSJarno Rajahalme 			error = -EEXIST;
100237bdc87bSJarno Rajahalme 			goto err_unlock_ovs;
1003893f139bSJarno Rajahalme 		}
100474ed7ab9SJoe Stringer 		/* The flow identifier has to be the same for flow updates.
100574ed7ab9SJoe Stringer 		 * Look for any overlapping flow.
100674ed7ab9SJoe Stringer 		 */
100774ed7ab9SJoe Stringer 		if (unlikely(!ovs_flow_cmp(flow, &match))) {
100874ed7ab9SJoe Stringer 			if (ovs_identifier_is_key(&flow->id))
100974ed7ab9SJoe Stringer 				flow = ovs_flow_tbl_lookup_exact(&dp->table,
101074ed7ab9SJoe Stringer 								 &match);
101174ed7ab9SJoe Stringer 			else /* UFID matches but key is different */
101274ed7ab9SJoe Stringer 				flow = NULL;
10134a46b24eSAlex Wang 			if (!flow) {
10144a46b24eSAlex Wang 				error = -ENOENT;
101537bdc87bSJarno Rajahalme 				goto err_unlock_ovs;
1016893f139bSJarno Rajahalme 			}
10174a46b24eSAlex Wang 		}
101837bdc87bSJarno Rajahalme 		/* Update actions. */
101937bdc87bSJarno Rajahalme 		old_acts = ovsl_dereference(flow->sf_acts);
102037bdc87bSJarno Rajahalme 		rcu_assign_pointer(flow->sf_acts, acts);
102137bdc87bSJarno Rajahalme 
1022893f139bSJarno Rajahalme 		if (unlikely(reply)) {
1023893f139bSJarno Rajahalme 			error = ovs_flow_cmd_fill_info(flow,
1024893f139bSJarno Rajahalme 						       ovs_header->dp_ifindex,
1025893f139bSJarno Rajahalme 						       reply, info->snd_portid,
1026893f139bSJarno Rajahalme 						       info->snd_seq, 0,
102774ed7ab9SJoe Stringer 						       OVS_FLOW_CMD_NEW,
102874ed7ab9SJoe Stringer 						       ufid_flags);
1029893f139bSJarno Rajahalme 			BUG_ON(error < 0);
1030893f139bSJarno Rajahalme 		}
103137bdc87bSJarno Rajahalme 		ovs_unlock();
103237bdc87bSJarno Rajahalme 
103334ae932aSThomas Graf 		ovs_nla_free_flow_actions_rcu(old_acts);
1034893f139bSJarno Rajahalme 		ovs_flow_free(new_flow, false);
103537bdc87bSJarno Rajahalme 	}
1036893f139bSJarno Rajahalme 
1037893f139bSJarno Rajahalme 	if (reply)
1038893f139bSJarno Rajahalme 		ovs_notify(&dp_flow_genl_family, reply, info);
103937bdc87bSJarno Rajahalme 	return 0;
104037bdc87bSJarno Rajahalme 
104137bdc87bSJarno Rajahalme err_unlock_ovs:
104237bdc87bSJarno Rajahalme 	ovs_unlock();
1043893f139bSJarno Rajahalme 	kfree_skb(reply);
1044893f139bSJarno Rajahalme err_kfree_acts:
104534ae932aSThomas Graf 	ovs_nla_free_flow_actions(acts);
1046893f139bSJarno Rajahalme err_kfree_flow:
1047893f139bSJarno Rajahalme 	ovs_flow_free(new_flow, false);
104837bdc87bSJarno Rajahalme error:
104937bdc87bSJarno Rajahalme 	return error;
105037bdc87bSJarno Rajahalme }
105137bdc87bSJarno Rajahalme 
10522fdb957dSPravin B Shelar /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */
105326063790SArnd Bergmann static noinline_for_stack struct sw_flow_actions *get_flow_actions(struct net *net,
10547f8a436eSJoe Stringer 						const struct nlattr *a,
10556b205b2cSJesse Gross 						const struct sw_flow_key *key,
105605da5898SJarno Rajahalme 						const struct sw_flow_mask *mask,
105705da5898SJarno Rajahalme 						bool log)
10586b205b2cSJesse Gross {
10596b205b2cSJesse Gross 	struct sw_flow_actions *acts;
10606b205b2cSJesse Gross 	struct sw_flow_key masked_key;
10616b205b2cSJesse Gross 	int error;
10626b205b2cSJesse Gross 
1063ae5f2fb1SJesse Gross 	ovs_flow_mask_key(&masked_key, key, true, mask);
10647f8a436eSJoe Stringer 	error = ovs_nla_copy_actions(net, a, &masked_key, &acts, log);
10656b205b2cSJesse Gross 	if (error) {
106605da5898SJarno Rajahalme 		OVS_NLERR(log,
106705da5898SJarno Rajahalme 			  "Actions may not be safe on all matching packets");
10686b205b2cSJesse Gross 		return ERR_PTR(error);
10696b205b2cSJesse Gross 	}
10706b205b2cSJesse Gross 
10716b205b2cSJesse Gross 	return acts;
10726b205b2cSJesse Gross }
10736b205b2cSJesse Gross 
10749cc9a5cbSTonghao Zhang /* Factor out match-init and action-copy to avoid
10759cc9a5cbSTonghao Zhang  * "Wframe-larger-than=1024" warning. Because mask is only
10769cc9a5cbSTonghao Zhang  * used to get actions, we new a function to save some
10779cc9a5cbSTonghao Zhang  * stack space.
10789cc9a5cbSTonghao Zhang  *
10799cc9a5cbSTonghao Zhang  * If there are not key and action attrs, we return 0
10809cc9a5cbSTonghao Zhang  * directly. In the case, the caller will also not use the
10819cc9a5cbSTonghao Zhang  * match as before. If there is action attr, we try to get
10829cc9a5cbSTonghao Zhang  * actions and save them to *acts. Before returning from
10839cc9a5cbSTonghao Zhang  * the function, we reset the match->mask pointer. Because
10849cc9a5cbSTonghao Zhang  * we should not to return match object with dangling reference
10859cc9a5cbSTonghao Zhang  * to mask.
10869cc9a5cbSTonghao Zhang  * */
108726063790SArnd Bergmann static noinline_for_stack int
108826063790SArnd Bergmann ovs_nla_init_match_and_action(struct net *net,
10899cc9a5cbSTonghao Zhang 			      struct sw_flow_match *match,
10909cc9a5cbSTonghao Zhang 			      struct sw_flow_key *key,
10919cc9a5cbSTonghao Zhang 			      struct nlattr **a,
10929cc9a5cbSTonghao Zhang 			      struct sw_flow_actions **acts,
10939cc9a5cbSTonghao Zhang 			      bool log)
10949cc9a5cbSTonghao Zhang {
10959cc9a5cbSTonghao Zhang 	struct sw_flow_mask mask;
10969cc9a5cbSTonghao Zhang 	int error = 0;
10979cc9a5cbSTonghao Zhang 
10989cc9a5cbSTonghao Zhang 	if (a[OVS_FLOW_ATTR_KEY]) {
10999cc9a5cbSTonghao Zhang 		ovs_match_init(match, key, true, &mask);
11009cc9a5cbSTonghao Zhang 		error = ovs_nla_get_match(net, match, a[OVS_FLOW_ATTR_KEY],
11019cc9a5cbSTonghao Zhang 					  a[OVS_FLOW_ATTR_MASK], log);
11029cc9a5cbSTonghao Zhang 		if (error)
11039cc9a5cbSTonghao Zhang 			goto error;
11049cc9a5cbSTonghao Zhang 	}
11059cc9a5cbSTonghao Zhang 
11069cc9a5cbSTonghao Zhang 	if (a[OVS_FLOW_ATTR_ACTIONS]) {
11079cc9a5cbSTonghao Zhang 		if (!a[OVS_FLOW_ATTR_KEY]) {
11089cc9a5cbSTonghao Zhang 			OVS_NLERR(log,
11099cc9a5cbSTonghao Zhang 				  "Flow key attribute not present in set flow.");
11105829e62aSChristophe JAILLET 			error = -EINVAL;
11115829e62aSChristophe JAILLET 			goto error;
11129cc9a5cbSTonghao Zhang 		}
11139cc9a5cbSTonghao Zhang 
11149cc9a5cbSTonghao Zhang 		*acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], key,
11159cc9a5cbSTonghao Zhang 					 &mask, log);
11169cc9a5cbSTonghao Zhang 		if (IS_ERR(*acts)) {
11179cc9a5cbSTonghao Zhang 			error = PTR_ERR(*acts);
11189cc9a5cbSTonghao Zhang 			goto error;
11199cc9a5cbSTonghao Zhang 		}
11209cc9a5cbSTonghao Zhang 	}
11219cc9a5cbSTonghao Zhang 
11229cc9a5cbSTonghao Zhang 	/* On success, error is 0. */
11239cc9a5cbSTonghao Zhang error:
11249cc9a5cbSTonghao Zhang 	match->mask = NULL;
11259cc9a5cbSTonghao Zhang 	return error;
11269cc9a5cbSTonghao Zhang }
11279cc9a5cbSTonghao Zhang 
112837bdc87bSJarno Rajahalme static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
112937bdc87bSJarno Rajahalme {
11307f8a436eSJoe Stringer 	struct net *net = sock_net(skb->sk);
113137bdc87bSJarno Rajahalme 	struct nlattr **a = info->attrs;
113237bdc87bSJarno Rajahalme 	struct ovs_header *ovs_header = info->userhdr;
11336b205b2cSJesse Gross 	struct sw_flow_key key;
113437bdc87bSJarno Rajahalme 	struct sw_flow *flow;
113537bdc87bSJarno Rajahalme 	struct sk_buff *reply = NULL;
113637bdc87bSJarno Rajahalme 	struct datapath *dp;
1137893f139bSJarno Rajahalme 	struct sw_flow_actions *old_acts = NULL, *acts = NULL;
113803f0d916SAndy Zhou 	struct sw_flow_match match;
113974ed7ab9SJoe Stringer 	struct sw_flow_id sfid;
114074ed7ab9SJoe Stringer 	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
11416f15cdbfSSamuel Gauthier 	int error = 0;
114205da5898SJarno Rajahalme 	bool log = !a[OVS_FLOW_ATTR_PROBE];
114374ed7ab9SJoe Stringer 	bool ufid_present;
1144ccb1352eSJesse Gross 
114574ed7ab9SJoe Stringer 	ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log);
11469cc9a5cbSTonghao Zhang 	if (!a[OVS_FLOW_ATTR_KEY] && !ufid_present) {
11476f15cdbfSSamuel Gauthier 		OVS_NLERR(log,
11486f15cdbfSSamuel Gauthier 			  "Flow set message rejected, Key attribute missing.");
11499cc9a5cbSTonghao Zhang 		return -EINVAL;
11506f15cdbfSSamuel Gauthier 	}
11519cc9a5cbSTonghao Zhang 
11529cc9a5cbSTonghao Zhang 	error = ovs_nla_init_match_and_action(net, &match, &key, a,
11539cc9a5cbSTonghao Zhang 					      &acts, log);
1154ccb1352eSJesse Gross 	if (error)
1155ccb1352eSJesse Gross 		goto error;
1156ccb1352eSJesse Gross 
11579cc9a5cbSTonghao Zhang 	if (acts) {
1158893f139bSJarno Rajahalme 		/* Can allocate before locking if have acts. */
115974ed7ab9SJoe Stringer 		reply = ovs_flow_cmd_alloc_info(acts, &sfid, info, false,
116074ed7ab9SJoe Stringer 						ufid_flags);
1161893f139bSJarno Rajahalme 		if (IS_ERR(reply)) {
1162893f139bSJarno Rajahalme 			error = PTR_ERR(reply);
1163893f139bSJarno Rajahalme 			goto err_kfree_acts;
116403f0d916SAndy Zhou 		}
1165ccb1352eSJesse Gross 	}
1166ccb1352eSJesse Gross 
11678e4e1713SPravin B Shelar 	ovs_lock();
11687f8a436eSJoe Stringer 	dp = get_dp(net, ovs_header->dp_ifindex);
1169893f139bSJarno Rajahalme 	if (unlikely(!dp)) {
1170ccb1352eSJesse Gross 		error = -ENODEV;
11718e4e1713SPravin B Shelar 		goto err_unlock_ovs;
1172893f139bSJarno Rajahalme 	}
117337bdc87bSJarno Rajahalme 	/* Check that the flow exists. */
117474ed7ab9SJoe Stringer 	if (ufid_present)
117574ed7ab9SJoe Stringer 		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &sfid);
117674ed7ab9SJoe Stringer 	else
11774a46b24eSAlex Wang 		flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
1178893f139bSJarno Rajahalme 	if (unlikely(!flow)) {
1179ccb1352eSJesse Gross 		error = -ENOENT;
11808e4e1713SPravin B Shelar 		goto err_unlock_ovs;
1181893f139bSJarno Rajahalme 	}
11824a46b24eSAlex Wang 
1183be52c9e9SJarno Rajahalme 	/* Update actions, if present. */
1184893f139bSJarno Rajahalme 	if (likely(acts)) {
11858e4e1713SPravin B Shelar 		old_acts = ovsl_dereference(flow->sf_acts);
118674f84a57SPravin B Shelar 		rcu_assign_pointer(flow->sf_acts, acts);
11870e9796b4SJarno Rajahalme 
1188893f139bSJarno Rajahalme 		if (unlikely(reply)) {
1189893f139bSJarno Rajahalme 			error = ovs_flow_cmd_fill_info(flow,
1190893f139bSJarno Rajahalme 						       ovs_header->dp_ifindex,
1191893f139bSJarno Rajahalme 						       reply, info->snd_portid,
1192893f139bSJarno Rajahalme 						       info->snd_seq, 0,
1193804fe108SYifeng Sun 						       OVS_FLOW_CMD_SET,
119474ed7ab9SJoe Stringer 						       ufid_flags);
1195893f139bSJarno Rajahalme 			BUG_ON(error < 0);
1196893f139bSJarno Rajahalme 		}
1197893f139bSJarno Rajahalme 	} else {
1198893f139bSJarno Rajahalme 		/* Could not alloc without acts before locking. */
11990e9796b4SJarno Rajahalme 		reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
1200804fe108SYifeng Sun 						info, OVS_FLOW_CMD_SET, false,
120174ed7ab9SJoe Stringer 						ufid_flags);
120274ed7ab9SJoe Stringer 
1203b5ffe634SViresh Kumar 		if (IS_ERR(reply)) {
1204893f139bSJarno Rajahalme 			error = PTR_ERR(reply);
1205893f139bSJarno Rajahalme 			goto err_unlock_ovs;
1206893f139bSJarno Rajahalme 		}
1207893f139bSJarno Rajahalme 	}
1208893f139bSJarno Rajahalme 
1209ccb1352eSJesse Gross 	/* Clear stats. */
1210e298e505SPravin B Shelar 	if (a[OVS_FLOW_ATTR_CLEAR])
1211e298e505SPravin B Shelar 		ovs_flow_stats_clear(flow);
12128e4e1713SPravin B Shelar 	ovs_unlock();
1213ccb1352eSJesse Gross 
1214893f139bSJarno Rajahalme 	if (reply)
12152a94fe48SJohannes Berg 		ovs_notify(&dp_flow_genl_family, reply, info);
1216893f139bSJarno Rajahalme 	if (old_acts)
121734ae932aSThomas Graf 		ovs_nla_free_flow_actions_rcu(old_acts);
1218fb5d1e9eSJarno Rajahalme 
1219ccb1352eSJesse Gross 	return 0;
1220ccb1352eSJesse Gross 
12218e4e1713SPravin B Shelar err_unlock_ovs:
12228e4e1713SPravin B Shelar 	ovs_unlock();
1223893f139bSJarno Rajahalme 	kfree_skb(reply);
1224893f139bSJarno Rajahalme err_kfree_acts:
122534ae932aSThomas Graf 	ovs_nla_free_flow_actions(acts);
1226ccb1352eSJesse Gross error:
1227ccb1352eSJesse Gross 	return error;
1228ccb1352eSJesse Gross }
1229ccb1352eSJesse Gross 
1230ccb1352eSJesse Gross static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
1231ccb1352eSJesse Gross {
1232ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
1233ccb1352eSJesse Gross 	struct ovs_header *ovs_header = info->userhdr;
1234c2ac6673SJoe Stringer 	struct net *net = sock_net(skb->sk);
1235ccb1352eSJesse Gross 	struct sw_flow_key key;
1236ccb1352eSJesse Gross 	struct sk_buff *reply;
1237ccb1352eSJesse Gross 	struct sw_flow *flow;
1238ccb1352eSJesse Gross 	struct datapath *dp;
123903f0d916SAndy Zhou 	struct sw_flow_match match;
124074ed7ab9SJoe Stringer 	struct sw_flow_id ufid;
124174ed7ab9SJoe Stringer 	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
124274ed7ab9SJoe Stringer 	int err = 0;
124305da5898SJarno Rajahalme 	bool log = !a[OVS_FLOW_ATTR_PROBE];
124474ed7ab9SJoe Stringer 	bool ufid_present;
1245ccb1352eSJesse Gross 
124674ed7ab9SJoe Stringer 	ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
124774ed7ab9SJoe Stringer 	if (a[OVS_FLOW_ATTR_KEY]) {
12482279994dSpravin shelar 		ovs_match_init(&match, &key, true, NULL);
1249c2ac6673SJoe Stringer 		err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], NULL,
125074ed7ab9SJoe Stringer 					log);
125174ed7ab9SJoe Stringer 	} else if (!ufid_present) {
125205da5898SJarno Rajahalme 		OVS_NLERR(log,
125305da5898SJarno Rajahalme 			  "Flow get message rejected, Key attribute missing.");
125474ed7ab9SJoe Stringer 		err = -EINVAL;
125503f0d916SAndy Zhou 	}
1256ccb1352eSJesse Gross 	if (err)
1257ccb1352eSJesse Gross 		return err;
1258ccb1352eSJesse Gross 
12598e4e1713SPravin B Shelar 	ovs_lock();
126046df7b81SPravin B Shelar 	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
12618e4e1713SPravin B Shelar 	if (!dp) {
12628e4e1713SPravin B Shelar 		err = -ENODEV;
12638e4e1713SPravin B Shelar 		goto unlock;
12648e4e1713SPravin B Shelar 	}
1265ccb1352eSJesse Gross 
126674ed7ab9SJoe Stringer 	if (ufid_present)
126774ed7ab9SJoe Stringer 		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &ufid);
126874ed7ab9SJoe Stringer 	else
12694a46b24eSAlex Wang 		flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
12704a46b24eSAlex Wang 	if (!flow) {
12718e4e1713SPravin B Shelar 		err = -ENOENT;
12728e4e1713SPravin B Shelar 		goto unlock;
12738e4e1713SPravin B Shelar 	}
1274ccb1352eSJesse Gross 
12750e9796b4SJarno Rajahalme 	reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, info,
1276804fe108SYifeng Sun 					OVS_FLOW_CMD_GET, true, ufid_flags);
12778e4e1713SPravin B Shelar 	if (IS_ERR(reply)) {
12788e4e1713SPravin B Shelar 		err = PTR_ERR(reply);
12798e4e1713SPravin B Shelar 		goto unlock;
12808e4e1713SPravin B Shelar 	}
1281ccb1352eSJesse Gross 
12828e4e1713SPravin B Shelar 	ovs_unlock();
1283ccb1352eSJesse Gross 	return genlmsg_reply(reply, info);
12848e4e1713SPravin B Shelar unlock:
12858e4e1713SPravin B Shelar 	ovs_unlock();
12868e4e1713SPravin B Shelar 	return err;
1287ccb1352eSJesse Gross }
1288ccb1352eSJesse Gross 
1289ccb1352eSJesse Gross static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
1290ccb1352eSJesse Gross {
1291ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
1292ccb1352eSJesse Gross 	struct ovs_header *ovs_header = info->userhdr;
1293c2ac6673SJoe Stringer 	struct net *net = sock_net(skb->sk);
1294ccb1352eSJesse Gross 	struct sw_flow_key key;
1295ccb1352eSJesse Gross 	struct sk_buff *reply;
129674ed7ab9SJoe Stringer 	struct sw_flow *flow = NULL;
1297ccb1352eSJesse Gross 	struct datapath *dp;
129803f0d916SAndy Zhou 	struct sw_flow_match match;
129974ed7ab9SJoe Stringer 	struct sw_flow_id ufid;
130074ed7ab9SJoe Stringer 	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
1301ccb1352eSJesse Gross 	int err;
130205da5898SJarno Rajahalme 	bool log = !a[OVS_FLOW_ATTR_PROBE];
130374ed7ab9SJoe Stringer 	bool ufid_present;
1304ccb1352eSJesse Gross 
130574ed7ab9SJoe Stringer 	ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
130674ed7ab9SJoe Stringer 	if (a[OVS_FLOW_ATTR_KEY]) {
13072279994dSpravin shelar 		ovs_match_init(&match, &key, true, NULL);
1308c2ac6673SJoe Stringer 		err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
1309c2ac6673SJoe Stringer 					NULL, log);
1310aed06778SJarno Rajahalme 		if (unlikely(err))
1311aed06778SJarno Rajahalme 			return err;
1312aed06778SJarno Rajahalme 	}
1313aed06778SJarno Rajahalme 
13148e4e1713SPravin B Shelar 	ovs_lock();
131546df7b81SPravin B Shelar 	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
1316aed06778SJarno Rajahalme 	if (unlikely(!dp)) {
13178e4e1713SPravin B Shelar 		err = -ENODEV;
13188e4e1713SPravin B Shelar 		goto unlock;
13198e4e1713SPravin B Shelar 	}
132046df7b81SPravin B Shelar 
132174ed7ab9SJoe Stringer 	if (unlikely(!a[OVS_FLOW_ATTR_KEY] && !ufid_present)) {
1322b637e498SPravin B Shelar 		err = ovs_flow_tbl_flush(&dp->table);
13238e4e1713SPravin B Shelar 		goto unlock;
13248e4e1713SPravin B Shelar 	}
132503f0d916SAndy Zhou 
132674ed7ab9SJoe Stringer 	if (ufid_present)
132774ed7ab9SJoe Stringer 		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &ufid);
132874ed7ab9SJoe Stringer 	else
13294a46b24eSAlex Wang 		flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
13304a46b24eSAlex Wang 	if (unlikely(!flow)) {
13318e4e1713SPravin B Shelar 		err = -ENOENT;
13328e4e1713SPravin B Shelar 		goto unlock;
13338e4e1713SPravin B Shelar 	}
1334ccb1352eSJesse Gross 
1335b637e498SPravin B Shelar 	ovs_flow_tbl_remove(&dp->table, flow);
1336aed06778SJarno Rajahalme 	ovs_unlock();
1337ccb1352eSJesse Gross 
1338aed06778SJarno Rajahalme 	reply = ovs_flow_cmd_alloc_info((const struct sw_flow_actions __force *) flow->sf_acts,
133974ed7ab9SJoe Stringer 					&flow->id, info, false, ufid_flags);
1340aed06778SJarno Rajahalme 	if (likely(reply)) {
1341b90f5aa4SEnrico Weigelt 		if (!IS_ERR(reply)) {
1342aed06778SJarno Rajahalme 			rcu_read_lock();	/*To keep RCU checker happy. */
13430e9796b4SJarno Rajahalme 			err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
13440e9796b4SJarno Rajahalme 						     reply, info->snd_portid,
1345fb5d1e9eSJarno Rajahalme 						     info->snd_seq, 0,
134674ed7ab9SJoe Stringer 						     OVS_FLOW_CMD_DEL,
134774ed7ab9SJoe Stringer 						     ufid_flags);
1348aed06778SJarno Rajahalme 			rcu_read_unlock();
1349ccb1352eSJesse Gross 			BUG_ON(err < 0);
1350ccb1352eSJesse Gross 
13512a94fe48SJohannes Berg 			ovs_notify(&dp_flow_genl_family, reply, info);
1352aed06778SJarno Rajahalme 		} else {
1353aed06778SJarno Rajahalme 			netlink_set_err(sock_net(skb->sk)->genl_sock, 0, 0, PTR_ERR(reply));
1354aed06778SJarno Rajahalme 		}
1355aed06778SJarno Rajahalme 	}
1356aed06778SJarno Rajahalme 
1357aed06778SJarno Rajahalme 	ovs_flow_free(flow, true);
1358ccb1352eSJesse Gross 	return 0;
13598e4e1713SPravin B Shelar unlock:
13608e4e1713SPravin B Shelar 	ovs_unlock();
13618e4e1713SPravin B Shelar 	return err;
1362ccb1352eSJesse Gross }
1363ccb1352eSJesse Gross 
1364ccb1352eSJesse Gross static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1365ccb1352eSJesse Gross {
136674ed7ab9SJoe Stringer 	struct nlattr *a[__OVS_FLOW_ATTR_MAX];
1367ccb1352eSJesse Gross 	struct ovs_header *ovs_header = genlmsg_data(nlmsg_data(cb->nlh));
1368b637e498SPravin B Shelar 	struct table_instance *ti;
1369ccb1352eSJesse Gross 	struct datapath *dp;
137074ed7ab9SJoe Stringer 	u32 ufid_flags;
137174ed7ab9SJoe Stringer 	int err;
137274ed7ab9SJoe Stringer 
13738cb08174SJohannes Berg 	err = genlmsg_parse_deprecated(cb->nlh, &dp_flow_genl_family, a,
1374fceb6435SJohannes Berg 				       OVS_FLOW_ATTR_MAX, flow_policy, NULL);
137574ed7ab9SJoe Stringer 	if (err)
137674ed7ab9SJoe Stringer 		return err;
137774ed7ab9SJoe Stringer 	ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
1378ccb1352eSJesse Gross 
1379d57170b1SPravin B Shelar 	rcu_read_lock();
1380cc3a5ae6SAndy Zhou 	dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
13818e4e1713SPravin B Shelar 	if (!dp) {
1382d57170b1SPravin B Shelar 		rcu_read_unlock();
1383ccb1352eSJesse Gross 		return -ENODEV;
13848e4e1713SPravin B Shelar 	}
1385ccb1352eSJesse Gross 
1386b637e498SPravin B Shelar 	ti = rcu_dereference(dp->table.ti);
1387ccb1352eSJesse Gross 	for (;;) {
1388ccb1352eSJesse Gross 		struct sw_flow *flow;
1389ccb1352eSJesse Gross 		u32 bucket, obj;
1390ccb1352eSJesse Gross 
1391ccb1352eSJesse Gross 		bucket = cb->args[0];
1392ccb1352eSJesse Gross 		obj = cb->args[1];
1393b637e498SPravin B Shelar 		flow = ovs_flow_tbl_dump_next(ti, &bucket, &obj);
1394ccb1352eSJesse Gross 		if (!flow)
1395ccb1352eSJesse Gross 			break;
1396ccb1352eSJesse Gross 
13970e9796b4SJarno Rajahalme 		if (ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex, skb,
139815e47304SEric W. Biederman 					   NETLINK_CB(cb->skb).portid,
1399ccb1352eSJesse Gross 					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
1400804fe108SYifeng Sun 					   OVS_FLOW_CMD_GET, ufid_flags) < 0)
1401ccb1352eSJesse Gross 			break;
1402ccb1352eSJesse Gross 
1403ccb1352eSJesse Gross 		cb->args[0] = bucket;
1404ccb1352eSJesse Gross 		cb->args[1] = obj;
1405ccb1352eSJesse Gross 	}
1406d57170b1SPravin B Shelar 	rcu_read_unlock();
1407ccb1352eSJesse Gross 	return skb->len;
1408ccb1352eSJesse Gross }
1409ccb1352eSJesse Gross 
14100c200ef9SPravin B Shelar static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
14110c200ef9SPravin B Shelar 	[OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
141205da5898SJarno Rajahalme 	[OVS_FLOW_ATTR_MASK] = { .type = NLA_NESTED },
14130c200ef9SPravin B Shelar 	[OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
14140c200ef9SPravin B Shelar 	[OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
141505da5898SJarno Rajahalme 	[OVS_FLOW_ATTR_PROBE] = { .type = NLA_FLAG },
141674ed7ab9SJoe Stringer 	[OVS_FLOW_ATTR_UFID] = { .type = NLA_UNSPEC, .len = 1 },
141774ed7ab9SJoe Stringer 	[OVS_FLOW_ATTR_UFID_FLAGS] = { .type = NLA_U32 },
14180c200ef9SPravin B Shelar };
14190c200ef9SPravin B Shelar 
142048e48a70Sstephen hemminger static const struct genl_ops dp_flow_genl_ops[] = {
1421ccb1352eSJesse Gross 	{ .cmd = OVS_FLOW_CMD_NEW,
1422ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14234a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
142437bdc87bSJarno Rajahalme 	  .doit = ovs_flow_cmd_new
1425ccb1352eSJesse Gross 	},
1426ccb1352eSJesse Gross 	{ .cmd = OVS_FLOW_CMD_DEL,
1427ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14284a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
1429ccb1352eSJesse Gross 	  .doit = ovs_flow_cmd_del
1430ccb1352eSJesse Gross 	},
1431ccb1352eSJesse Gross 	{ .cmd = OVS_FLOW_CMD_GET,
1432ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1433ccb1352eSJesse Gross 	  .flags = 0,		    /* OK for unprivileged users. */
1434ccb1352eSJesse Gross 	  .doit = ovs_flow_cmd_get,
1435ccb1352eSJesse Gross 	  .dumpit = ovs_flow_cmd_dump
1436ccb1352eSJesse Gross 	},
1437ccb1352eSJesse Gross 	{ .cmd = OVS_FLOW_CMD_SET,
1438ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14394a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
144037bdc87bSJarno Rajahalme 	  .doit = ovs_flow_cmd_set,
1441ccb1352eSJesse Gross 	},
1442ccb1352eSJesse Gross };
1443ccb1352eSJesse Gross 
144456989f6dSJohannes Berg static struct genl_family dp_flow_genl_family __ro_after_init = {
1445ccb1352eSJesse Gross 	.hdrsize = sizeof(struct ovs_header),
14460c200ef9SPravin B Shelar 	.name = OVS_FLOW_FAMILY,
14470c200ef9SPravin B Shelar 	.version = OVS_FLOW_VERSION,
14480c200ef9SPravin B Shelar 	.maxattr = OVS_FLOW_ATTR_MAX,
14493b0f31f2SJohannes Berg 	.policy = flow_policy,
14503a4e0d6aSPravin B Shelar 	.netnsok = true,
14513a4e0d6aSPravin B Shelar 	.parallel_ops = true,
14520c200ef9SPravin B Shelar 	.ops = dp_flow_genl_ops,
14530c200ef9SPravin B Shelar 	.n_ops = ARRAY_SIZE(dp_flow_genl_ops),
14540c200ef9SPravin B Shelar 	.mcgrps = &ovs_dp_flow_multicast_group,
14550c200ef9SPravin B Shelar 	.n_mcgrps = 1,
1456489111e5SJohannes Berg 	.module = THIS_MODULE,
1457ccb1352eSJesse Gross };
1458ccb1352eSJesse Gross 
1459c3ff8cfeSThomas Graf static size_t ovs_dp_cmd_msg_size(void)
1460c3ff8cfeSThomas Graf {
1461c3ff8cfeSThomas Graf 	size_t msgsize = NLMSG_ALIGN(sizeof(struct ovs_header));
1462c3ff8cfeSThomas Graf 
1463c3ff8cfeSThomas Graf 	msgsize += nla_total_size(IFNAMSIZ);
146466c7a5eeSNicolas Dichtel 	msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_stats));
146566c7a5eeSNicolas Dichtel 	msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_megaflow_stats));
146645fb9c35SDaniele Di Proietto 	msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */
1467c3ff8cfeSThomas Graf 
1468c3ff8cfeSThomas Graf 	return msgsize;
1469c3ff8cfeSThomas Graf }
1470c3ff8cfeSThomas Graf 
14718ec609d8SPravin B Shelar /* Called with ovs_mutex. */
1472ccb1352eSJesse Gross static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
147315e47304SEric W. Biederman 				u32 portid, u32 seq, u32 flags, u8 cmd)
1474ccb1352eSJesse Gross {
1475ccb1352eSJesse Gross 	struct ovs_header *ovs_header;
1476ccb1352eSJesse Gross 	struct ovs_dp_stats dp_stats;
14771bd7116fSAndy Zhou 	struct ovs_dp_megaflow_stats dp_megaflow_stats;
1478ccb1352eSJesse Gross 	int err;
1479ccb1352eSJesse Gross 
148015e47304SEric W. Biederman 	ovs_header = genlmsg_put(skb, portid, seq, &dp_datapath_genl_family,
1481ccb1352eSJesse Gross 				   flags, cmd);
1482ccb1352eSJesse Gross 	if (!ovs_header)
1483ccb1352eSJesse Gross 		goto error;
1484ccb1352eSJesse Gross 
1485ccb1352eSJesse Gross 	ovs_header->dp_ifindex = get_dpifindex(dp);
1486ccb1352eSJesse Gross 
1487ccb1352eSJesse Gross 	err = nla_put_string(skb, OVS_DP_ATTR_NAME, ovs_dp_name(dp));
1488ccb1352eSJesse Gross 	if (err)
1489ccb1352eSJesse Gross 		goto nla_put_failure;
1490ccb1352eSJesse Gross 
14911bd7116fSAndy Zhou 	get_dp_stats(dp, &dp_stats, &dp_megaflow_stats);
149266c7a5eeSNicolas Dichtel 	if (nla_put_64bit(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats),
149366c7a5eeSNicolas Dichtel 			  &dp_stats, OVS_DP_ATTR_PAD))
14941bd7116fSAndy Zhou 		goto nla_put_failure;
14951bd7116fSAndy Zhou 
149666c7a5eeSNicolas Dichtel 	if (nla_put_64bit(skb, OVS_DP_ATTR_MEGAFLOW_STATS,
14971bd7116fSAndy Zhou 			  sizeof(struct ovs_dp_megaflow_stats),
149866c7a5eeSNicolas Dichtel 			  &dp_megaflow_stats, OVS_DP_ATTR_PAD))
1499028d6a67SDavid S. Miller 		goto nla_put_failure;
1500ccb1352eSJesse Gross 
150143d4be9cSThomas Graf 	if (nla_put_u32(skb, OVS_DP_ATTR_USER_FEATURES, dp->user_features))
150243d4be9cSThomas Graf 		goto nla_put_failure;
150343d4be9cSThomas Graf 
1504053c095aSJohannes Berg 	genlmsg_end(skb, ovs_header);
1505053c095aSJohannes Berg 	return 0;
1506ccb1352eSJesse Gross 
1507ccb1352eSJesse Gross nla_put_failure:
1508ccb1352eSJesse Gross 	genlmsg_cancel(skb, ovs_header);
1509ccb1352eSJesse Gross error:
1510ccb1352eSJesse Gross 	return -EMSGSIZE;
1511ccb1352eSJesse Gross }
1512ccb1352eSJesse Gross 
1513263ea090SFlorian Westphal static struct sk_buff *ovs_dp_cmd_alloc_info(void)
1514ccb1352eSJesse Gross {
1515551ddc05SFlorian Westphal 	return genlmsg_new(ovs_dp_cmd_msg_size(), GFP_KERNEL);
1516ccb1352eSJesse Gross }
1517ccb1352eSJesse Gross 
1518bb6f9a70SJarno Rajahalme /* Called with rcu_read_lock or ovs_mutex. */
151946df7b81SPravin B Shelar static struct datapath *lookup_datapath(struct net *net,
152012eb18f7SThomas Graf 					const struct ovs_header *ovs_header,
1521ccb1352eSJesse Gross 					struct nlattr *a[OVS_DP_ATTR_MAX + 1])
1522ccb1352eSJesse Gross {
1523ccb1352eSJesse Gross 	struct datapath *dp;
1524ccb1352eSJesse Gross 
1525ccb1352eSJesse Gross 	if (!a[OVS_DP_ATTR_NAME])
152646df7b81SPravin B Shelar 		dp = get_dp(net, ovs_header->dp_ifindex);
1527ccb1352eSJesse Gross 	else {
1528ccb1352eSJesse Gross 		struct vport *vport;
1529ccb1352eSJesse Gross 
153046df7b81SPravin B Shelar 		vport = ovs_vport_locate(net, nla_data(a[OVS_DP_ATTR_NAME]));
1531ccb1352eSJesse Gross 		dp = vport && vport->port_no == OVSP_LOCAL ? vport->dp : NULL;
1532ccb1352eSJesse Gross 	}
1533ccb1352eSJesse Gross 	return dp ? dp : ERR_PTR(-ENODEV);
1534ccb1352eSJesse Gross }
1535ccb1352eSJesse Gross 
153644da5ae5SThomas Graf static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *info)
153744da5ae5SThomas Graf {
153844da5ae5SThomas Graf 	struct datapath *dp;
153944da5ae5SThomas Graf 
154044da5ae5SThomas Graf 	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
15413c7eacfcSJiri Pirko 	if (IS_ERR(dp))
154244da5ae5SThomas Graf 		return;
154344da5ae5SThomas Graf 
154444da5ae5SThomas Graf 	WARN(dp->user_features, "Dropping previously announced user features\n");
154544da5ae5SThomas Graf 	dp->user_features = 0;
154644da5ae5SThomas Graf }
154744da5ae5SThomas Graf 
154895a7233cSPaul Blakey DEFINE_STATIC_KEY_FALSE(tc_recirc_sharing_support);
154995a7233cSPaul Blakey 
155095a7233cSPaul Blakey static int ovs_dp_change(struct datapath *dp, struct nlattr *a[])
155143d4be9cSThomas Graf {
155295a7233cSPaul Blakey 	u32 user_features = 0;
155395a7233cSPaul Blakey 
155495a7233cSPaul Blakey 	if (a[OVS_DP_ATTR_USER_FEATURES]) {
155595a7233cSPaul Blakey 		user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]);
155695a7233cSPaul Blakey 
155795a7233cSPaul Blakey 		if (user_features & ~(OVS_DP_F_VPORT_PIDS |
155895a7233cSPaul Blakey 				      OVS_DP_F_UNALIGNED |
155995a7233cSPaul Blakey 				      OVS_DP_F_TC_RECIRC_SHARING))
156095a7233cSPaul Blakey 			return -EOPNOTSUPP;
156195a7233cSPaul Blakey 
156295a7233cSPaul Blakey #if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
156395a7233cSPaul Blakey 		if (user_features & OVS_DP_F_TC_RECIRC_SHARING)
156495a7233cSPaul Blakey 			return -EOPNOTSUPP;
156595a7233cSPaul Blakey #endif
156695a7233cSPaul Blakey 	}
156795a7233cSPaul Blakey 
156895a7233cSPaul Blakey 	dp->user_features = user_features;
156995a7233cSPaul Blakey 
157095a7233cSPaul Blakey 	if (dp->user_features & OVS_DP_F_TC_RECIRC_SHARING)
157195a7233cSPaul Blakey 		static_branch_enable(&tc_recirc_sharing_support);
157295a7233cSPaul Blakey 	else
157395a7233cSPaul Blakey 		static_branch_disable(&tc_recirc_sharing_support);
157495a7233cSPaul Blakey 
157595a7233cSPaul Blakey 	return 0;
157643d4be9cSThomas Graf }
157743d4be9cSThomas Graf 
1578ccb1352eSJesse Gross static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1579ccb1352eSJesse Gross {
1580ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
1581ccb1352eSJesse Gross 	struct vport_parms parms;
1582ccb1352eSJesse Gross 	struct sk_buff *reply;
1583ccb1352eSJesse Gross 	struct datapath *dp;
1584ccb1352eSJesse Gross 	struct vport *vport;
158546df7b81SPravin B Shelar 	struct ovs_net *ovs_net;
158615eac2a7SPravin B Shelar 	int err, i;
1587ccb1352eSJesse Gross 
1588ccb1352eSJesse Gross 	err = -EINVAL;
1589ccb1352eSJesse Gross 	if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID])
1590ccb1352eSJesse Gross 		goto err;
1591ccb1352eSJesse Gross 
1592263ea090SFlorian Westphal 	reply = ovs_dp_cmd_alloc_info();
15936093ae9aSJarno Rajahalme 	if (!reply)
15946093ae9aSJarno Rajahalme 		return -ENOMEM;
1595ccb1352eSJesse Gross 
1596ccb1352eSJesse Gross 	err = -ENOMEM;
1597ccb1352eSJesse Gross 	dp = kzalloc(sizeof(*dp), GFP_KERNEL);
1598ccb1352eSJesse Gross 	if (dp == NULL)
15996093ae9aSJarno Rajahalme 		goto err_free_reply;
160046df7b81SPravin B Shelar 
1601efd7ef1cSEric W. Biederman 	ovs_dp_set_net(dp, sock_net(skb->sk));
1602ccb1352eSJesse Gross 
1603ccb1352eSJesse Gross 	/* Allocate table. */
1604b637e498SPravin B Shelar 	err = ovs_flow_tbl_init(&dp->table);
1605b637e498SPravin B Shelar 	if (err)
1606ccb1352eSJesse Gross 		goto err_free_dp;
1607ccb1352eSJesse Gross 
16081c213bd2SWANG Cong 	dp->stats_percpu = netdev_alloc_pcpu_stats(struct dp_stats_percpu);
1609ccb1352eSJesse Gross 	if (!dp->stats_percpu) {
1610ccb1352eSJesse Gross 		err = -ENOMEM;
1611ccb1352eSJesse Gross 		goto err_destroy_table;
1612ccb1352eSJesse Gross 	}
1613ccb1352eSJesse Gross 
16146da2ec56SKees Cook 	dp->ports = kmalloc_array(DP_VPORT_HASH_BUCKETS,
16156da2ec56SKees Cook 				  sizeof(struct hlist_head),
161615eac2a7SPravin B Shelar 				  GFP_KERNEL);
161715eac2a7SPravin B Shelar 	if (!dp->ports) {
161815eac2a7SPravin B Shelar 		err = -ENOMEM;
161915eac2a7SPravin B Shelar 		goto err_destroy_percpu;
162015eac2a7SPravin B Shelar 	}
162115eac2a7SPravin B Shelar 
162215eac2a7SPravin B Shelar 	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
162315eac2a7SPravin B Shelar 		INIT_HLIST_HEAD(&dp->ports[i]);
162415eac2a7SPravin B Shelar 
162596fbc13dSAndy Zhou 	err = ovs_meters_init(dp);
162696fbc13dSAndy Zhou 	if (err)
162796fbc13dSAndy Zhou 		goto err_destroy_ports_array;
162896fbc13dSAndy Zhou 
1629ccb1352eSJesse Gross 	/* Set up our datapath device. */
1630ccb1352eSJesse Gross 	parms.name = nla_data(a[OVS_DP_ATTR_NAME]);
1631ccb1352eSJesse Gross 	parms.type = OVS_VPORT_TYPE_INTERNAL;
1632ccb1352eSJesse Gross 	parms.options = NULL;
1633ccb1352eSJesse Gross 	parms.dp = dp;
1634ccb1352eSJesse Gross 	parms.port_no = OVSP_LOCAL;
16355cd667b0SAlex Wang 	parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
1636ccb1352eSJesse Gross 
163795a7233cSPaul Blakey 	err = ovs_dp_change(dp, a);
163895a7233cSPaul Blakey 	if (err)
163995a7233cSPaul Blakey 		goto err_destroy_meters;
164043d4be9cSThomas Graf 
16416093ae9aSJarno Rajahalme 	/* So far only local changes have been made, now need the lock. */
16426093ae9aSJarno Rajahalme 	ovs_lock();
16436093ae9aSJarno Rajahalme 
1644ccb1352eSJesse Gross 	vport = new_vport(&parms);
1645ccb1352eSJesse Gross 	if (IS_ERR(vport)) {
1646ccb1352eSJesse Gross 		err = PTR_ERR(vport);
1647ccb1352eSJesse Gross 		if (err == -EBUSY)
1648ccb1352eSJesse Gross 			err = -EEXIST;
1649ccb1352eSJesse Gross 
165044da5ae5SThomas Graf 		if (err == -EEXIST) {
165144da5ae5SThomas Graf 			/* An outdated user space instance that does not understand
165244da5ae5SThomas Graf 			 * the concept of user_features has attempted to create a new
165344da5ae5SThomas Graf 			 * datapath and is likely to reuse it. Drop all user features.
165444da5ae5SThomas Graf 			 */
165544da5ae5SThomas Graf 			if (info->genlhdr->version < OVS_DP_VER_FEATURES)
165644da5ae5SThomas Graf 				ovs_dp_reset_user_features(skb, info);
165744da5ae5SThomas Graf 		}
165844da5ae5SThomas Graf 
165996fbc13dSAndy Zhou 		goto err_destroy_meters;
1660ccb1352eSJesse Gross 	}
1661ccb1352eSJesse Gross 
16626093ae9aSJarno Rajahalme 	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
16636093ae9aSJarno Rajahalme 				   info->snd_seq, 0, OVS_DP_CMD_NEW);
16646093ae9aSJarno Rajahalme 	BUG_ON(err < 0);
1665ccb1352eSJesse Gross 
166646df7b81SPravin B Shelar 	ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
166759a35d60SPravin B Shelar 	list_add_tail_rcu(&dp->list_node, &ovs_net->dps);
16688e4e1713SPravin B Shelar 
16698e4e1713SPravin B Shelar 	ovs_unlock();
1670ccb1352eSJesse Gross 
16712a94fe48SJohannes Berg 	ovs_notify(&dp_datapath_genl_family, reply, info);
1672ccb1352eSJesse Gross 	return 0;
1673ccb1352eSJesse Gross 
167496fbc13dSAndy Zhou err_destroy_meters:
16756093ae9aSJarno Rajahalme 	ovs_unlock();
167696fbc13dSAndy Zhou 	ovs_meters_exit(dp);
167796fbc13dSAndy Zhou err_destroy_ports_array:
167815eac2a7SPravin B Shelar 	kfree(dp->ports);
1679ccb1352eSJesse Gross err_destroy_percpu:
1680ccb1352eSJesse Gross 	free_percpu(dp->stats_percpu);
1681ccb1352eSJesse Gross err_destroy_table:
16829b996e54SPravin B Shelar 	ovs_flow_tbl_destroy(&dp->table);
1683ccb1352eSJesse Gross err_free_dp:
1684ccb1352eSJesse Gross 	kfree(dp);
16856093ae9aSJarno Rajahalme err_free_reply:
16866093ae9aSJarno Rajahalme 	kfree_skb(reply);
1687ccb1352eSJesse Gross err:
1688ccb1352eSJesse Gross 	return err;
1689ccb1352eSJesse Gross }
1690ccb1352eSJesse Gross 
16918e4e1713SPravin B Shelar /* Called with ovs_mutex. */
169246df7b81SPravin B Shelar static void __dp_destroy(struct datapath *dp)
1693ccb1352eSJesse Gross {
169415eac2a7SPravin B Shelar 	int i;
1695ccb1352eSJesse Gross 
169615eac2a7SPravin B Shelar 	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
169715eac2a7SPravin B Shelar 		struct vport *vport;
1698b67bfe0dSSasha Levin 		struct hlist_node *n;
169915eac2a7SPravin B Shelar 
1700b67bfe0dSSasha Levin 		hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node)
1701ccb1352eSJesse Gross 			if (vport->port_no != OVSP_LOCAL)
1702ccb1352eSJesse Gross 				ovs_dp_detach_port(vport);
170315eac2a7SPravin B Shelar 	}
1704ccb1352eSJesse Gross 
170559a35d60SPravin B Shelar 	list_del_rcu(&dp->list_node);
1706ccb1352eSJesse Gross 
17078e4e1713SPravin B Shelar 	/* OVSP_LOCAL is datapath internal port. We need to make sure that
1708e80857ccSAndy Zhou 	 * all ports in datapath are destroyed first before freeing datapath.
1709ccb1352eSJesse Gross 	 */
17108e4e1713SPravin B Shelar 	ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
1711ccb1352eSJesse Gross 
1712e80857ccSAndy Zhou 	/* RCU destroy the flow table */
1713ccb1352eSJesse Gross 	call_rcu(&dp->rcu, destroy_dp_rcu);
171446df7b81SPravin B Shelar }
171546df7b81SPravin B Shelar 
171646df7b81SPravin B Shelar static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
171746df7b81SPravin B Shelar {
171846df7b81SPravin B Shelar 	struct sk_buff *reply;
171946df7b81SPravin B Shelar 	struct datapath *dp;
172046df7b81SPravin B Shelar 	int err;
172146df7b81SPravin B Shelar 
1722263ea090SFlorian Westphal 	reply = ovs_dp_cmd_alloc_info();
17236093ae9aSJarno Rajahalme 	if (!reply)
17246093ae9aSJarno Rajahalme 		return -ENOMEM;
17256093ae9aSJarno Rajahalme 
17268e4e1713SPravin B Shelar 	ovs_lock();
172746df7b81SPravin B Shelar 	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
172846df7b81SPravin B Shelar 	err = PTR_ERR(dp);
172946df7b81SPravin B Shelar 	if (IS_ERR(dp))
17306093ae9aSJarno Rajahalme 		goto err_unlock_free;
173146df7b81SPravin B Shelar 
17326093ae9aSJarno Rajahalme 	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
17336093ae9aSJarno Rajahalme 				   info->snd_seq, 0, OVS_DP_CMD_DEL);
17346093ae9aSJarno Rajahalme 	BUG_ON(err < 0);
173546df7b81SPravin B Shelar 
173646df7b81SPravin B Shelar 	__dp_destroy(dp);
17378e4e1713SPravin B Shelar 	ovs_unlock();
1738ccb1352eSJesse Gross 
17392a94fe48SJohannes Berg 	ovs_notify(&dp_datapath_genl_family, reply, info);
1740ccb1352eSJesse Gross 
1741ccb1352eSJesse Gross 	return 0;
17426093ae9aSJarno Rajahalme 
17436093ae9aSJarno Rajahalme err_unlock_free:
17448e4e1713SPravin B Shelar 	ovs_unlock();
17456093ae9aSJarno Rajahalme 	kfree_skb(reply);
17468e4e1713SPravin B Shelar 	return err;
1747ccb1352eSJesse Gross }
1748ccb1352eSJesse Gross 
1749ccb1352eSJesse Gross static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
1750ccb1352eSJesse Gross {
1751ccb1352eSJesse Gross 	struct sk_buff *reply;
1752ccb1352eSJesse Gross 	struct datapath *dp;
1753ccb1352eSJesse Gross 	int err;
1754ccb1352eSJesse Gross 
1755263ea090SFlorian Westphal 	reply = ovs_dp_cmd_alloc_info();
17566093ae9aSJarno Rajahalme 	if (!reply)
17576093ae9aSJarno Rajahalme 		return -ENOMEM;
17586093ae9aSJarno Rajahalme 
17598e4e1713SPravin B Shelar 	ovs_lock();
176046df7b81SPravin B Shelar 	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
17618e4e1713SPravin B Shelar 	err = PTR_ERR(dp);
1762ccb1352eSJesse Gross 	if (IS_ERR(dp))
17636093ae9aSJarno Rajahalme 		goto err_unlock_free;
1764ccb1352eSJesse Gross 
176595a7233cSPaul Blakey 	err = ovs_dp_change(dp, info->attrs);
176695a7233cSPaul Blakey 	if (err)
176795a7233cSPaul Blakey 		goto err_unlock_free;
176843d4be9cSThomas Graf 
17696093ae9aSJarno Rajahalme 	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1770804fe108SYifeng Sun 				   info->snd_seq, 0, OVS_DP_CMD_SET);
17716093ae9aSJarno Rajahalme 	BUG_ON(err < 0);
1772ccb1352eSJesse Gross 
17738e4e1713SPravin B Shelar 	ovs_unlock();
17742a94fe48SJohannes Berg 	ovs_notify(&dp_datapath_genl_family, reply, info);
1775ccb1352eSJesse Gross 
1776ccb1352eSJesse Gross 	return 0;
17776093ae9aSJarno Rajahalme 
17786093ae9aSJarno Rajahalme err_unlock_free:
17798e4e1713SPravin B Shelar 	ovs_unlock();
17806093ae9aSJarno Rajahalme 	kfree_skb(reply);
17818e4e1713SPravin B Shelar 	return err;
1782ccb1352eSJesse Gross }
1783ccb1352eSJesse Gross 
1784ccb1352eSJesse Gross static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
1785ccb1352eSJesse Gross {
1786ccb1352eSJesse Gross 	struct sk_buff *reply;
1787ccb1352eSJesse Gross 	struct datapath *dp;
17888e4e1713SPravin B Shelar 	int err;
1789ccb1352eSJesse Gross 
1790263ea090SFlorian Westphal 	reply = ovs_dp_cmd_alloc_info();
17916093ae9aSJarno Rajahalme 	if (!reply)
17926093ae9aSJarno Rajahalme 		return -ENOMEM;
17936093ae9aSJarno Rajahalme 
17948ec609d8SPravin B Shelar 	ovs_lock();
179546df7b81SPravin B Shelar 	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
17968e4e1713SPravin B Shelar 	if (IS_ERR(dp)) {
17978e4e1713SPravin B Shelar 		err = PTR_ERR(dp);
17986093ae9aSJarno Rajahalme 		goto err_unlock_free;
17998e4e1713SPravin B Shelar 	}
18006093ae9aSJarno Rajahalme 	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1801804fe108SYifeng Sun 				   info->snd_seq, 0, OVS_DP_CMD_GET);
18026093ae9aSJarno Rajahalme 	BUG_ON(err < 0);
18038ec609d8SPravin B Shelar 	ovs_unlock();
1804ccb1352eSJesse Gross 
1805ccb1352eSJesse Gross 	return genlmsg_reply(reply, info);
18068e4e1713SPravin B Shelar 
18076093ae9aSJarno Rajahalme err_unlock_free:
18088ec609d8SPravin B Shelar 	ovs_unlock();
18096093ae9aSJarno Rajahalme 	kfree_skb(reply);
18108e4e1713SPravin B Shelar 	return err;
1811ccb1352eSJesse Gross }
1812ccb1352eSJesse Gross 
1813ccb1352eSJesse Gross static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1814ccb1352eSJesse Gross {
181546df7b81SPravin B Shelar 	struct ovs_net *ovs_net = net_generic(sock_net(skb->sk), ovs_net_id);
1816ccb1352eSJesse Gross 	struct datapath *dp;
1817ccb1352eSJesse Gross 	int skip = cb->args[0];
1818ccb1352eSJesse Gross 	int i = 0;
1819ccb1352eSJesse Gross 
18208ec609d8SPravin B Shelar 	ovs_lock();
18218ec609d8SPravin B Shelar 	list_for_each_entry(dp, &ovs_net->dps, list_node) {
182277676fdbSBen Pfaff 		if (i >= skip &&
182315e47304SEric W. Biederman 		    ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid,
1824ccb1352eSJesse Gross 					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1825804fe108SYifeng Sun 					 OVS_DP_CMD_GET) < 0)
1826ccb1352eSJesse Gross 			break;
1827ccb1352eSJesse Gross 		i++;
1828ccb1352eSJesse Gross 	}
18298ec609d8SPravin B Shelar 	ovs_unlock();
1830ccb1352eSJesse Gross 
1831ccb1352eSJesse Gross 	cb->args[0] = i;
1832ccb1352eSJesse Gross 
1833ccb1352eSJesse Gross 	return skb->len;
1834ccb1352eSJesse Gross }
1835ccb1352eSJesse Gross 
18360c200ef9SPravin B Shelar static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
18370c200ef9SPravin B Shelar 	[OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
18380c200ef9SPravin B Shelar 	[OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
18390c200ef9SPravin B Shelar 	[OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
18400c200ef9SPravin B Shelar };
18410c200ef9SPravin B Shelar 
184248e48a70Sstephen hemminger static const struct genl_ops dp_datapath_genl_ops[] = {
1843ccb1352eSJesse Gross 	{ .cmd = OVS_DP_CMD_NEW,
1844ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
18454a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
1846ccb1352eSJesse Gross 	  .doit = ovs_dp_cmd_new
1847ccb1352eSJesse Gross 	},
1848ccb1352eSJesse Gross 	{ .cmd = OVS_DP_CMD_DEL,
1849ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
18504a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
1851ccb1352eSJesse Gross 	  .doit = ovs_dp_cmd_del
1852ccb1352eSJesse Gross 	},
1853ccb1352eSJesse Gross 	{ .cmd = OVS_DP_CMD_GET,
1854ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1855ccb1352eSJesse Gross 	  .flags = 0,		    /* OK for unprivileged users. */
1856ccb1352eSJesse Gross 	  .doit = ovs_dp_cmd_get,
1857ccb1352eSJesse Gross 	  .dumpit = ovs_dp_cmd_dump
1858ccb1352eSJesse Gross 	},
1859ccb1352eSJesse Gross 	{ .cmd = OVS_DP_CMD_SET,
1860ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
18614a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
1862ccb1352eSJesse Gross 	  .doit = ovs_dp_cmd_set,
1863ccb1352eSJesse Gross 	},
1864ccb1352eSJesse Gross };
1865ccb1352eSJesse Gross 
186656989f6dSJohannes Berg static struct genl_family dp_datapath_genl_family __ro_after_init = {
1867ccb1352eSJesse Gross 	.hdrsize = sizeof(struct ovs_header),
18680c200ef9SPravin B Shelar 	.name = OVS_DATAPATH_FAMILY,
18690c200ef9SPravin B Shelar 	.version = OVS_DATAPATH_VERSION,
18700c200ef9SPravin B Shelar 	.maxattr = OVS_DP_ATTR_MAX,
18713b0f31f2SJohannes Berg 	.policy = datapath_policy,
18723a4e0d6aSPravin B Shelar 	.netnsok = true,
18733a4e0d6aSPravin B Shelar 	.parallel_ops = true,
18740c200ef9SPravin B Shelar 	.ops = dp_datapath_genl_ops,
18750c200ef9SPravin B Shelar 	.n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
18760c200ef9SPravin B Shelar 	.mcgrps = &ovs_dp_datapath_multicast_group,
18770c200ef9SPravin B Shelar 	.n_mcgrps = 1,
1878489111e5SJohannes Berg 	.module = THIS_MODULE,
1879ccb1352eSJesse Gross };
1880ccb1352eSJesse Gross 
18818e4e1713SPravin B Shelar /* Called with ovs_mutex or RCU read lock. */
1882ccb1352eSJesse Gross static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
18839354d452SJiri Benc 				   struct net *net, u32 portid, u32 seq,
18849354d452SJiri Benc 				   u32 flags, u8 cmd)
1885ccb1352eSJesse Gross {
1886ccb1352eSJesse Gross 	struct ovs_header *ovs_header;
1887ccb1352eSJesse Gross 	struct ovs_vport_stats vport_stats;
1888ccb1352eSJesse Gross 	int err;
1889ccb1352eSJesse Gross 
189015e47304SEric W. Biederman 	ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family,
1891ccb1352eSJesse Gross 				 flags, cmd);
1892ccb1352eSJesse Gross 	if (!ovs_header)
1893ccb1352eSJesse Gross 		return -EMSGSIZE;
1894ccb1352eSJesse Gross 
1895ccb1352eSJesse Gross 	ovs_header->dp_ifindex = get_dpifindex(vport->dp);
1896ccb1352eSJesse Gross 
1897028d6a67SDavid S. Miller 	if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) ||
1898028d6a67SDavid S. Miller 	    nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) ||
18995cd667b0SAlex Wang 	    nla_put_string(skb, OVS_VPORT_ATTR_NAME,
19009354d452SJiri Benc 			   ovs_vport_name(vport)) ||
19019354d452SJiri Benc 	    nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex))
1902028d6a67SDavid S. Miller 		goto nla_put_failure;
1903ccb1352eSJesse Gross 
19049354d452SJiri Benc 	if (!net_eq(net, dev_net(vport->dev))) {
19059354d452SJiri Benc 		int id = peernet2id_alloc(net, dev_net(vport->dev));
19069354d452SJiri Benc 
19079354d452SJiri Benc 		if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id))
19089354d452SJiri Benc 			goto nla_put_failure;
19099354d452SJiri Benc 	}
19109354d452SJiri Benc 
1911ccb1352eSJesse Gross 	ovs_vport_get_stats(vport, &vport_stats);
191266c7a5eeSNicolas Dichtel 	if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
191366c7a5eeSNicolas Dichtel 			  sizeof(struct ovs_vport_stats), &vport_stats,
191466c7a5eeSNicolas Dichtel 			  OVS_VPORT_ATTR_PAD))
1915028d6a67SDavid S. Miller 		goto nla_put_failure;
1916ccb1352eSJesse Gross 
19175cd667b0SAlex Wang 	if (ovs_vport_get_upcall_portids(vport, skb))
19185cd667b0SAlex Wang 		goto nla_put_failure;
19195cd667b0SAlex Wang 
1920ccb1352eSJesse Gross 	err = ovs_vport_get_options(vport, skb);
1921ccb1352eSJesse Gross 	if (err == -EMSGSIZE)
1922ccb1352eSJesse Gross 		goto error;
1923ccb1352eSJesse Gross 
1924053c095aSJohannes Berg 	genlmsg_end(skb, ovs_header);
1925053c095aSJohannes Berg 	return 0;
1926ccb1352eSJesse Gross 
1927ccb1352eSJesse Gross nla_put_failure:
1928ccb1352eSJesse Gross 	err = -EMSGSIZE;
1929ccb1352eSJesse Gross error:
1930ccb1352eSJesse Gross 	genlmsg_cancel(skb, ovs_header);
1931ccb1352eSJesse Gross 	return err;
1932ccb1352eSJesse Gross }
1933ccb1352eSJesse Gross 
19346093ae9aSJarno Rajahalme static struct sk_buff *ovs_vport_cmd_alloc_info(void)
19356093ae9aSJarno Rajahalme {
19366093ae9aSJarno Rajahalme 	return nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
19376093ae9aSJarno Rajahalme }
19386093ae9aSJarno Rajahalme 
19396093ae9aSJarno Rajahalme /* Called with ovs_mutex, only via ovs_dp_notify_wq(). */
19409354d452SJiri Benc struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, struct net *net,
19419354d452SJiri Benc 					 u32 portid, u32 seq, u8 cmd)
1942ccb1352eSJesse Gross {
1943ccb1352eSJesse Gross 	struct sk_buff *skb;
1944ccb1352eSJesse Gross 	int retval;
1945ccb1352eSJesse Gross 
1946ccb1352eSJesse Gross 	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1947ccb1352eSJesse Gross 	if (!skb)
1948ccb1352eSJesse Gross 		return ERR_PTR(-ENOMEM);
1949ccb1352eSJesse Gross 
19509354d452SJiri Benc 	retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd);
1951a9341512SJesse Gross 	BUG_ON(retval < 0);
1952a9341512SJesse Gross 
1953ccb1352eSJesse Gross 	return skb;
1954ccb1352eSJesse Gross }
1955ccb1352eSJesse Gross 
19568e4e1713SPravin B Shelar /* Called with ovs_mutex or RCU read lock. */
195746df7b81SPravin B Shelar static struct vport *lookup_vport(struct net *net,
195812eb18f7SThomas Graf 				  const struct ovs_header *ovs_header,
1959ccb1352eSJesse Gross 				  struct nlattr *a[OVS_VPORT_ATTR_MAX + 1])
1960ccb1352eSJesse Gross {
1961ccb1352eSJesse Gross 	struct datapath *dp;
1962ccb1352eSJesse Gross 	struct vport *vport;
1963ccb1352eSJesse Gross 
19649354d452SJiri Benc 	if (a[OVS_VPORT_ATTR_IFINDEX])
19659354d452SJiri Benc 		return ERR_PTR(-EOPNOTSUPP);
1966ccb1352eSJesse Gross 	if (a[OVS_VPORT_ATTR_NAME]) {
196746df7b81SPravin B Shelar 		vport = ovs_vport_locate(net, nla_data(a[OVS_VPORT_ATTR_NAME]));
1968ccb1352eSJesse Gross 		if (!vport)
1969ccb1352eSJesse Gross 			return ERR_PTR(-ENODEV);
1970651a68eaSBen Pfaff 		if (ovs_header->dp_ifindex &&
1971651a68eaSBen Pfaff 		    ovs_header->dp_ifindex != get_dpifindex(vport->dp))
1972651a68eaSBen Pfaff 			return ERR_PTR(-ENODEV);
1973ccb1352eSJesse Gross 		return vport;
1974ccb1352eSJesse Gross 	} else if (a[OVS_VPORT_ATTR_PORT_NO]) {
1975ccb1352eSJesse Gross 		u32 port_no = nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]);
1976ccb1352eSJesse Gross 
1977ccb1352eSJesse Gross 		if (port_no >= DP_MAX_PORTS)
1978ccb1352eSJesse Gross 			return ERR_PTR(-EFBIG);
1979ccb1352eSJesse Gross 
198046df7b81SPravin B Shelar 		dp = get_dp(net, ovs_header->dp_ifindex);
1981ccb1352eSJesse Gross 		if (!dp)
1982ccb1352eSJesse Gross 			return ERR_PTR(-ENODEV);
1983ccb1352eSJesse Gross 
19848e4e1713SPravin B Shelar 		vport = ovs_vport_ovsl_rcu(dp, port_no);
1985ccb1352eSJesse Gross 		if (!vport)
198614408dbaSJarno Rajahalme 			return ERR_PTR(-ENODEV);
1987ccb1352eSJesse Gross 		return vport;
1988ccb1352eSJesse Gross 	} else
1989ccb1352eSJesse Gross 		return ERR_PTR(-EINVAL);
19909354d452SJiri Benc 
1991ccb1352eSJesse Gross }
1992ccb1352eSJesse Gross 
19936b660c41STaehee Yoo static unsigned int ovs_get_max_headroom(struct datapath *dp)
19943a927bc7SPaolo Abeni {
19956b660c41STaehee Yoo 	unsigned int dev_headroom, max_headroom = 0;
19963a927bc7SPaolo Abeni 	struct net_device *dev;
19973a927bc7SPaolo Abeni 	struct vport *vport;
19983a927bc7SPaolo Abeni 	int i;
19993a927bc7SPaolo Abeni 
20003a927bc7SPaolo Abeni 	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
20013a927bc7SPaolo Abeni 		hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
20023a927bc7SPaolo Abeni 			dev = vport->dev;
20033a927bc7SPaolo Abeni 			dev_headroom = netdev_get_fwd_headroom(dev);
20043a927bc7SPaolo Abeni 			if (dev_headroom > max_headroom)
20053a927bc7SPaolo Abeni 				max_headroom = dev_headroom;
20063a927bc7SPaolo Abeni 		}
20073a927bc7SPaolo Abeni 	}
20083a927bc7SPaolo Abeni 
20096b660c41STaehee Yoo 	return max_headroom;
20106b660c41STaehee Yoo }
20116b660c41STaehee Yoo 
20126b660c41STaehee Yoo /* Called with ovs_mutex */
20136b660c41STaehee Yoo static void ovs_update_headroom(struct datapath *dp, unsigned int new_headroom)
20146b660c41STaehee Yoo {
20156b660c41STaehee Yoo 	struct vport *vport;
20166b660c41STaehee Yoo 	int i;
20176b660c41STaehee Yoo 
20186b660c41STaehee Yoo 	dp->max_headroom = new_headroom;
20193a927bc7SPaolo Abeni 	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
20203a927bc7SPaolo Abeni 		hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node)
20216b660c41STaehee Yoo 			netdev_set_rx_headroom(vport->dev, new_headroom);
20223a927bc7SPaolo Abeni }
20233a927bc7SPaolo Abeni 
2024ccb1352eSJesse Gross static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
2025ccb1352eSJesse Gross {
2026ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
2027ccb1352eSJesse Gross 	struct ovs_header *ovs_header = info->userhdr;
2028ccb1352eSJesse Gross 	struct vport_parms parms;
2029ccb1352eSJesse Gross 	struct sk_buff *reply;
2030ccb1352eSJesse Gross 	struct vport *vport;
2031ccb1352eSJesse Gross 	struct datapath *dp;
20326b660c41STaehee Yoo 	unsigned int new_headroom;
2033ccb1352eSJesse Gross 	u32 port_no;
2034ccb1352eSJesse Gross 	int err;
2035ccb1352eSJesse Gross 
2036ccb1352eSJesse Gross 	if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] ||
2037ccb1352eSJesse Gross 	    !a[OVS_VPORT_ATTR_UPCALL_PID])
20386093ae9aSJarno Rajahalme 		return -EINVAL;
20399354d452SJiri Benc 	if (a[OVS_VPORT_ATTR_IFINDEX])
20409354d452SJiri Benc 		return -EOPNOTSUPP;
20416093ae9aSJarno Rajahalme 
20426093ae9aSJarno Rajahalme 	port_no = a[OVS_VPORT_ATTR_PORT_NO]
20436093ae9aSJarno Rajahalme 		? nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]) : 0;
20446093ae9aSJarno Rajahalme 	if (port_no >= DP_MAX_PORTS)
20456093ae9aSJarno Rajahalme 		return -EFBIG;
20466093ae9aSJarno Rajahalme 
20476093ae9aSJarno Rajahalme 	reply = ovs_vport_cmd_alloc_info();
20486093ae9aSJarno Rajahalme 	if (!reply)
20496093ae9aSJarno Rajahalme 		return -ENOMEM;
2050ccb1352eSJesse Gross 
20518e4e1713SPravin B Shelar 	ovs_lock();
205262b9c8d0SThomas Graf restart:
205346df7b81SPravin B Shelar 	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
2054ccb1352eSJesse Gross 	err = -ENODEV;
2055ccb1352eSJesse Gross 	if (!dp)
20566093ae9aSJarno Rajahalme 		goto exit_unlock_free;
2057ccb1352eSJesse Gross 
20586093ae9aSJarno Rajahalme 	if (port_no) {
20598e4e1713SPravin B Shelar 		vport = ovs_vport_ovsl(dp, port_no);
2060ccb1352eSJesse Gross 		err = -EBUSY;
2061ccb1352eSJesse Gross 		if (vport)
20626093ae9aSJarno Rajahalme 			goto exit_unlock_free;
2063ccb1352eSJesse Gross 	} else {
2064ccb1352eSJesse Gross 		for (port_no = 1; ; port_no++) {
2065ccb1352eSJesse Gross 			if (port_no >= DP_MAX_PORTS) {
2066ccb1352eSJesse Gross 				err = -EFBIG;
20676093ae9aSJarno Rajahalme 				goto exit_unlock_free;
2068ccb1352eSJesse Gross 			}
20698e4e1713SPravin B Shelar 			vport = ovs_vport_ovsl(dp, port_no);
2070ccb1352eSJesse Gross 			if (!vport)
2071ccb1352eSJesse Gross 				break;
2072ccb1352eSJesse Gross 		}
2073ccb1352eSJesse Gross 	}
2074ccb1352eSJesse Gross 
2075ccb1352eSJesse Gross 	parms.name = nla_data(a[OVS_VPORT_ATTR_NAME]);
2076ccb1352eSJesse Gross 	parms.type = nla_get_u32(a[OVS_VPORT_ATTR_TYPE]);
2077ccb1352eSJesse Gross 	parms.options = a[OVS_VPORT_ATTR_OPTIONS];
2078ccb1352eSJesse Gross 	parms.dp = dp;
2079ccb1352eSJesse Gross 	parms.port_no = port_no;
20805cd667b0SAlex Wang 	parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
2081ccb1352eSJesse Gross 
2082ccb1352eSJesse Gross 	vport = new_vport(&parms);
2083ccb1352eSJesse Gross 	err = PTR_ERR(vport);
208462b9c8d0SThomas Graf 	if (IS_ERR(vport)) {
208562b9c8d0SThomas Graf 		if (err == -EAGAIN)
208662b9c8d0SThomas Graf 			goto restart;
20876093ae9aSJarno Rajahalme 		goto exit_unlock_free;
208862b9c8d0SThomas Graf 	}
2089ccb1352eSJesse Gross 
20909354d452SJiri Benc 	err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
20919354d452SJiri Benc 				      info->snd_portid, info->snd_seq, 0,
20929354d452SJiri Benc 				      OVS_VPORT_CMD_NEW);
20933a927bc7SPaolo Abeni 
20946b660c41STaehee Yoo 	new_headroom = netdev_get_fwd_headroom(vport->dev);
20956b660c41STaehee Yoo 
20966b660c41STaehee Yoo 	if (new_headroom > dp->max_headroom)
20976b660c41STaehee Yoo 		ovs_update_headroom(dp, new_headroom);
20983a927bc7SPaolo Abeni 	else
20993a927bc7SPaolo Abeni 		netdev_set_rx_headroom(vport->dev, dp->max_headroom);
21003a927bc7SPaolo Abeni 
21016093ae9aSJarno Rajahalme 	BUG_ON(err < 0);
21026093ae9aSJarno Rajahalme 	ovs_unlock();
2103ed661185SThomas Graf 
21042a94fe48SJohannes Berg 	ovs_notify(&dp_vport_genl_family, reply, info);
21056093ae9aSJarno Rajahalme 	return 0;
2106ccb1352eSJesse Gross 
21076093ae9aSJarno Rajahalme exit_unlock_free:
21088e4e1713SPravin B Shelar 	ovs_unlock();
21096093ae9aSJarno Rajahalme 	kfree_skb(reply);
2110ccb1352eSJesse Gross 	return err;
2111ccb1352eSJesse Gross }
2112ccb1352eSJesse Gross 
2113ccb1352eSJesse Gross static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
2114ccb1352eSJesse Gross {
2115ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
2116ccb1352eSJesse Gross 	struct sk_buff *reply;
2117ccb1352eSJesse Gross 	struct vport *vport;
2118ccb1352eSJesse Gross 	int err;
2119ccb1352eSJesse Gross 
21206093ae9aSJarno Rajahalme 	reply = ovs_vport_cmd_alloc_info();
21216093ae9aSJarno Rajahalme 	if (!reply)
21226093ae9aSJarno Rajahalme 		return -ENOMEM;
21236093ae9aSJarno Rajahalme 
21248e4e1713SPravin B Shelar 	ovs_lock();
212546df7b81SPravin B Shelar 	vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
2126ccb1352eSJesse Gross 	err = PTR_ERR(vport);
2127ccb1352eSJesse Gross 	if (IS_ERR(vport))
21286093ae9aSJarno Rajahalme 		goto exit_unlock_free;
2129ccb1352eSJesse Gross 
2130ccb1352eSJesse Gross 	if (a[OVS_VPORT_ATTR_TYPE] &&
2131f44f3408SJesse Gross 	    nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) {
2132ccb1352eSJesse Gross 		err = -EINVAL;
21336093ae9aSJarno Rajahalme 		goto exit_unlock_free;
2134a9341512SJesse Gross 	}
2135a9341512SJesse Gross 
2136f44f3408SJesse Gross 	if (a[OVS_VPORT_ATTR_OPTIONS]) {
2137ccb1352eSJesse Gross 		err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
213803fbf8b3SAnsis Atteka 		if (err)
21396093ae9aSJarno Rajahalme 			goto exit_unlock_free;
2140f44f3408SJesse Gross 	}
2141a9341512SJesse Gross 
21425cd667b0SAlex Wang 
21435cd667b0SAlex Wang 	if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
21445cd667b0SAlex Wang 		struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID];
21455cd667b0SAlex Wang 
21465cd667b0SAlex Wang 		err = ovs_vport_set_upcall_portids(vport, ids);
21475cd667b0SAlex Wang 		if (err)
21485cd667b0SAlex Wang 			goto exit_unlock_free;
21495cd667b0SAlex Wang 	}
2150ccb1352eSJesse Gross 
21519354d452SJiri Benc 	err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
21529354d452SJiri Benc 				      info->snd_portid, info->snd_seq, 0,
2153804fe108SYifeng Sun 				      OVS_VPORT_CMD_SET);
2154a9341512SJesse Gross 	BUG_ON(err < 0);
2155ccb1352eSJesse Gross 
21568e4e1713SPravin B Shelar 	ovs_unlock();
21572a94fe48SJohannes Berg 	ovs_notify(&dp_vport_genl_family, reply, info);
21588e4e1713SPravin B Shelar 	return 0;
2159ccb1352eSJesse Gross 
21606093ae9aSJarno Rajahalme exit_unlock_free:
21618e4e1713SPravin B Shelar 	ovs_unlock();
21626093ae9aSJarno Rajahalme 	kfree_skb(reply);
2163ccb1352eSJesse Gross 	return err;
2164ccb1352eSJesse Gross }
2165ccb1352eSJesse Gross 
2166ccb1352eSJesse Gross static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
2167ccb1352eSJesse Gross {
21686b660c41STaehee Yoo 	bool update_headroom = false;
2169ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
2170ccb1352eSJesse Gross 	struct sk_buff *reply;
21713a927bc7SPaolo Abeni 	struct datapath *dp;
2172ccb1352eSJesse Gross 	struct vport *vport;
21736b660c41STaehee Yoo 	unsigned int new_headroom;
2174ccb1352eSJesse Gross 	int err;
2175ccb1352eSJesse Gross 
21766093ae9aSJarno Rajahalme 	reply = ovs_vport_cmd_alloc_info();
21776093ae9aSJarno Rajahalme 	if (!reply)
21786093ae9aSJarno Rajahalme 		return -ENOMEM;
21796093ae9aSJarno Rajahalme 
21808e4e1713SPravin B Shelar 	ovs_lock();
218146df7b81SPravin B Shelar 	vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
2182ccb1352eSJesse Gross 	err = PTR_ERR(vport);
2183ccb1352eSJesse Gross 	if (IS_ERR(vport))
21846093ae9aSJarno Rajahalme 		goto exit_unlock_free;
2185ccb1352eSJesse Gross 
2186ccb1352eSJesse Gross 	if (vport->port_no == OVSP_LOCAL) {
2187ccb1352eSJesse Gross 		err = -EINVAL;
21886093ae9aSJarno Rajahalme 		goto exit_unlock_free;
2189ccb1352eSJesse Gross 	}
2190ccb1352eSJesse Gross 
21919354d452SJiri Benc 	err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
21929354d452SJiri Benc 				      info->snd_portid, info->snd_seq, 0,
21939354d452SJiri Benc 				      OVS_VPORT_CMD_DEL);
21946093ae9aSJarno Rajahalme 	BUG_ON(err < 0);
21953a927bc7SPaolo Abeni 
21963a927bc7SPaolo Abeni 	/* the vport deletion may trigger dp headroom update */
21973a927bc7SPaolo Abeni 	dp = vport->dp;
21983a927bc7SPaolo Abeni 	if (netdev_get_fwd_headroom(vport->dev) == dp->max_headroom)
21996b660c41STaehee Yoo 		update_headroom = true;
22006b660c41STaehee Yoo 
22013a927bc7SPaolo Abeni 	netdev_reset_rx_headroom(vport->dev);
2202ccb1352eSJesse Gross 	ovs_dp_detach_port(vport);
22033a927bc7SPaolo Abeni 
22046b660c41STaehee Yoo 	if (update_headroom) {
22056b660c41STaehee Yoo 		new_headroom = ovs_get_max_headroom(dp);
22066b660c41STaehee Yoo 
22076b660c41STaehee Yoo 		if (new_headroom < dp->max_headroom)
22086b660c41STaehee Yoo 			ovs_update_headroom(dp, new_headroom);
22096b660c41STaehee Yoo 	}
22106093ae9aSJarno Rajahalme 	ovs_unlock();
2211ccb1352eSJesse Gross 
22122a94fe48SJohannes Berg 	ovs_notify(&dp_vport_genl_family, reply, info);
22136093ae9aSJarno Rajahalme 	return 0;
2214ccb1352eSJesse Gross 
22156093ae9aSJarno Rajahalme exit_unlock_free:
22168e4e1713SPravin B Shelar 	ovs_unlock();
22176093ae9aSJarno Rajahalme 	kfree_skb(reply);
2218ccb1352eSJesse Gross 	return err;
2219ccb1352eSJesse Gross }
2220ccb1352eSJesse Gross 
2221ccb1352eSJesse Gross static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
2222ccb1352eSJesse Gross {
2223ccb1352eSJesse Gross 	struct nlattr **a = info->attrs;
2224ccb1352eSJesse Gross 	struct ovs_header *ovs_header = info->userhdr;
2225ccb1352eSJesse Gross 	struct sk_buff *reply;
2226ccb1352eSJesse Gross 	struct vport *vport;
2227ccb1352eSJesse Gross 	int err;
2228ccb1352eSJesse Gross 
22296093ae9aSJarno Rajahalme 	reply = ovs_vport_cmd_alloc_info();
22306093ae9aSJarno Rajahalme 	if (!reply)
22316093ae9aSJarno Rajahalme 		return -ENOMEM;
22326093ae9aSJarno Rajahalme 
2233ccb1352eSJesse Gross 	rcu_read_lock();
223446df7b81SPravin B Shelar 	vport = lookup_vport(sock_net(skb->sk), ovs_header, a);
2235ccb1352eSJesse Gross 	err = PTR_ERR(vport);
2236ccb1352eSJesse Gross 	if (IS_ERR(vport))
22376093ae9aSJarno Rajahalme 		goto exit_unlock_free;
22389354d452SJiri Benc 	err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
22399354d452SJiri Benc 				      info->snd_portid, info->snd_seq, 0,
2240804fe108SYifeng Sun 				      OVS_VPORT_CMD_GET);
22416093ae9aSJarno Rajahalme 	BUG_ON(err < 0);
2242ccb1352eSJesse Gross 	rcu_read_unlock();
2243ccb1352eSJesse Gross 
2244ccb1352eSJesse Gross 	return genlmsg_reply(reply, info);
2245ccb1352eSJesse Gross 
22466093ae9aSJarno Rajahalme exit_unlock_free:
2247ccb1352eSJesse Gross 	rcu_read_unlock();
22486093ae9aSJarno Rajahalme 	kfree_skb(reply);
2249ccb1352eSJesse Gross 	return err;
2250ccb1352eSJesse Gross }
2251ccb1352eSJesse Gross 
2252ccb1352eSJesse Gross static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
2253ccb1352eSJesse Gross {
2254ccb1352eSJesse Gross 	struct ovs_header *ovs_header = genlmsg_data(nlmsg_data(cb->nlh));
2255ccb1352eSJesse Gross 	struct datapath *dp;
225615eac2a7SPravin B Shelar 	int bucket = cb->args[0], skip = cb->args[1];
225715eac2a7SPravin B Shelar 	int i, j = 0;
2258ccb1352eSJesse Gross 
2259ccb1352eSJesse Gross 	rcu_read_lock();
2260cc3a5ae6SAndy Zhou 	dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
226142ee19e2SJarno Rajahalme 	if (!dp) {
226242ee19e2SJarno Rajahalme 		rcu_read_unlock();
226342ee19e2SJarno Rajahalme 		return -ENODEV;
226442ee19e2SJarno Rajahalme 	}
226515eac2a7SPravin B Shelar 	for (i = bucket; i < DP_VPORT_HASH_BUCKETS; i++) {
2266ccb1352eSJesse Gross 		struct vport *vport;
2267ccb1352eSJesse Gross 
226815eac2a7SPravin B Shelar 		j = 0;
2269b67bfe0dSSasha Levin 		hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
227015eac2a7SPravin B Shelar 			if (j >= skip &&
227115eac2a7SPravin B Shelar 			    ovs_vport_cmd_fill_info(vport, skb,
22729354d452SJiri Benc 						    sock_net(skb->sk),
227315e47304SEric W. Biederman 						    NETLINK_CB(cb->skb).portid,
227415eac2a7SPravin B Shelar 						    cb->nlh->nlmsg_seq,
227515eac2a7SPravin B Shelar 						    NLM_F_MULTI,
2276804fe108SYifeng Sun 						    OVS_VPORT_CMD_GET) < 0)
227715eac2a7SPravin B Shelar 				goto out;
227815eac2a7SPravin B Shelar 
227915eac2a7SPravin B Shelar 			j++;
2280ccb1352eSJesse Gross 		}
228115eac2a7SPravin B Shelar 		skip = 0;
228215eac2a7SPravin B Shelar 	}
228315eac2a7SPravin B Shelar out:
2284ccb1352eSJesse Gross 	rcu_read_unlock();
2285ccb1352eSJesse Gross 
228615eac2a7SPravin B Shelar 	cb->args[0] = i;
228715eac2a7SPravin B Shelar 	cb->args[1] = j;
2288ccb1352eSJesse Gross 
228915eac2a7SPravin B Shelar 	return skb->len;
2290ccb1352eSJesse Gross }
2291ccb1352eSJesse Gross 
22920c200ef9SPravin B Shelar static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
22930c200ef9SPravin B Shelar 	[OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
22940c200ef9SPravin B Shelar 	[OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
22950c200ef9SPravin B Shelar 	[OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
22960c200ef9SPravin B Shelar 	[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
2297*ea8564c8SLi RongQing 	[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_UNSPEC },
22980c200ef9SPravin B Shelar 	[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
22999354d452SJiri Benc 	[OVS_VPORT_ATTR_IFINDEX] = { .type = NLA_U32 },
23009354d452SJiri Benc 	[OVS_VPORT_ATTR_NETNSID] = { .type = NLA_S32 },
23010c200ef9SPravin B Shelar };
23020c200ef9SPravin B Shelar 
230348e48a70Sstephen hemminger static const struct genl_ops dp_vport_genl_ops[] = {
2304ccb1352eSJesse Gross 	{ .cmd = OVS_VPORT_CMD_NEW,
2305ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
23064a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
2307ccb1352eSJesse Gross 	  .doit = ovs_vport_cmd_new
2308ccb1352eSJesse Gross 	},
2309ccb1352eSJesse Gross 	{ .cmd = OVS_VPORT_CMD_DEL,
2310ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
23114a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
2312ccb1352eSJesse Gross 	  .doit = ovs_vport_cmd_del
2313ccb1352eSJesse Gross 	},
2314ccb1352eSJesse Gross 	{ .cmd = OVS_VPORT_CMD_GET,
2315ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2316ccb1352eSJesse Gross 	  .flags = 0,		    /* OK for unprivileged users. */
2317ccb1352eSJesse Gross 	  .doit = ovs_vport_cmd_get,
2318ccb1352eSJesse Gross 	  .dumpit = ovs_vport_cmd_dump
2319ccb1352eSJesse Gross 	},
2320ccb1352eSJesse Gross 	{ .cmd = OVS_VPORT_CMD_SET,
2321ef6243acSJohannes Berg 	  .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
23224a92602aSTycho Andersen 	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
2323ccb1352eSJesse Gross 	  .doit = ovs_vport_cmd_set,
2324ccb1352eSJesse Gross 	},
2325ccb1352eSJesse Gross };
2326ccb1352eSJesse Gross 
232756989f6dSJohannes Berg struct genl_family dp_vport_genl_family __ro_after_init = {
23280c200ef9SPravin B Shelar 	.hdrsize = sizeof(struct ovs_header),
23290c200ef9SPravin B Shelar 	.name = OVS_VPORT_FAMILY,
23300c200ef9SPravin B Shelar 	.version = OVS_VPORT_VERSION,
23310c200ef9SPravin B Shelar 	.maxattr = OVS_VPORT_ATTR_MAX,
23323b0f31f2SJohannes Berg 	.policy = vport_policy,
23330c200ef9SPravin B Shelar 	.netnsok = true,
23340c200ef9SPravin B Shelar 	.parallel_ops = true,
23350c200ef9SPravin B Shelar 	.ops = dp_vport_genl_ops,
23360c200ef9SPravin B Shelar 	.n_ops = ARRAY_SIZE(dp_vport_genl_ops),
23370c200ef9SPravin B Shelar 	.mcgrps = &ovs_dp_vport_multicast_group,
23380c200ef9SPravin B Shelar 	.n_mcgrps = 1,
2339489111e5SJohannes Berg 	.module = THIS_MODULE,
2340ccb1352eSJesse Gross };
2341ccb1352eSJesse Gross 
23420c200ef9SPravin B Shelar static struct genl_family * const dp_genl_families[] = {
23430c200ef9SPravin B Shelar 	&dp_datapath_genl_family,
23440c200ef9SPravin B Shelar 	&dp_vport_genl_family,
23450c200ef9SPravin B Shelar 	&dp_flow_genl_family,
23460c200ef9SPravin B Shelar 	&dp_packet_genl_family,
234796fbc13dSAndy Zhou 	&dp_meter_genl_family,
234811efd5cbSYi-Hung Wei #if	IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
234911efd5cbSYi-Hung Wei 	&dp_ct_limit_genl_family,
235011efd5cbSYi-Hung Wei #endif
2351ccb1352eSJesse Gross };
2352ccb1352eSJesse Gross 
2353ccb1352eSJesse Gross static void dp_unregister_genl(int n_families)
2354ccb1352eSJesse Gross {
2355ccb1352eSJesse Gross 	int i;
2356ccb1352eSJesse Gross 
2357ccb1352eSJesse Gross 	for (i = 0; i < n_families; i++)
23580c200ef9SPravin B Shelar 		genl_unregister_family(dp_genl_families[i]);
2359ccb1352eSJesse Gross }
2360ccb1352eSJesse Gross 
236156989f6dSJohannes Berg static int __init dp_register_genl(void)
2362ccb1352eSJesse Gross {
2363ccb1352eSJesse Gross 	int err;
2364ccb1352eSJesse Gross 	int i;
2365ccb1352eSJesse Gross 
2366ccb1352eSJesse Gross 	for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
2367ccb1352eSJesse Gross 
23680c200ef9SPravin B Shelar 		err = genl_register_family(dp_genl_families[i]);
2369ccb1352eSJesse Gross 		if (err)
2370ccb1352eSJesse Gross 			goto error;
2371ccb1352eSJesse Gross 	}
2372ccb1352eSJesse Gross 
2373ccb1352eSJesse Gross 	return 0;
2374ccb1352eSJesse Gross 
2375ccb1352eSJesse Gross error:
23760c200ef9SPravin B Shelar 	dp_unregister_genl(i);
2377ccb1352eSJesse Gross 	return err;
2378ccb1352eSJesse Gross }
2379ccb1352eSJesse Gross 
238046df7b81SPravin B Shelar static int __net_init ovs_init_net(struct net *net)
238146df7b81SPravin B Shelar {
238246df7b81SPravin B Shelar 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
238346df7b81SPravin B Shelar 
238446df7b81SPravin B Shelar 	INIT_LIST_HEAD(&ovs_net->dps);
23858e4e1713SPravin B Shelar 	INIT_WORK(&ovs_net->dp_notify_work, ovs_dp_notify_wq);
238611efd5cbSYi-Hung Wei 	return ovs_ct_init(net);
238746df7b81SPravin B Shelar }
238846df7b81SPravin B Shelar 
23897b4577a9SPravin B Shelar static void __net_exit list_vports_from_net(struct net *net, struct net *dnet,
23907b4577a9SPravin B Shelar 					    struct list_head *head)
23917b4577a9SPravin B Shelar {
23927b4577a9SPravin B Shelar 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
23937b4577a9SPravin B Shelar 	struct datapath *dp;
23947b4577a9SPravin B Shelar 
23957b4577a9SPravin B Shelar 	list_for_each_entry(dp, &ovs_net->dps, list_node) {
23967b4577a9SPravin B Shelar 		int i;
23977b4577a9SPravin B Shelar 
23987b4577a9SPravin B Shelar 		for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
23997b4577a9SPravin B Shelar 			struct vport *vport;
24007b4577a9SPravin B Shelar 
24017b4577a9SPravin B Shelar 			hlist_for_each_entry(vport, &dp->ports[i], dp_hash_node) {
24027b4577a9SPravin B Shelar 				if (vport->ops->type != OVS_VPORT_TYPE_INTERNAL)
24037b4577a9SPravin B Shelar 					continue;
24047b4577a9SPravin B Shelar 
2405be4ace6eSThomas Graf 				if (dev_net(vport->dev) == dnet)
24067b4577a9SPravin B Shelar 					list_add(&vport->detach_list, head);
24077b4577a9SPravin B Shelar 			}
24087b4577a9SPravin B Shelar 		}
24097b4577a9SPravin B Shelar 	}
24107b4577a9SPravin B Shelar }
24117b4577a9SPravin B Shelar 
24127b4577a9SPravin B Shelar static void __net_exit ovs_exit_net(struct net *dnet)
241346df7b81SPravin B Shelar {
241446df7b81SPravin B Shelar 	struct datapath *dp, *dp_next;
24157b4577a9SPravin B Shelar 	struct ovs_net *ovs_net = net_generic(dnet, ovs_net_id);
24167b4577a9SPravin B Shelar 	struct vport *vport, *vport_next;
24177b4577a9SPravin B Shelar 	struct net *net;
24187b4577a9SPravin B Shelar 	LIST_HEAD(head);
241946df7b81SPravin B Shelar 
2420c2ac6673SJoe Stringer 	ovs_ct_exit(dnet);
24218e4e1713SPravin B Shelar 	ovs_lock();
242246df7b81SPravin B Shelar 	list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
242346df7b81SPravin B Shelar 		__dp_destroy(dp);
24247b4577a9SPravin B Shelar 
2425f0b07bb1SKirill Tkhai 	down_read(&net_rwsem);
24267b4577a9SPravin B Shelar 	for_each_net(net)
24277b4577a9SPravin B Shelar 		list_vports_from_net(net, dnet, &head);
2428f0b07bb1SKirill Tkhai 	up_read(&net_rwsem);
24297b4577a9SPravin B Shelar 
24307b4577a9SPravin B Shelar 	/* Detach all vports from given namespace. */
24317b4577a9SPravin B Shelar 	list_for_each_entry_safe(vport, vport_next, &head, detach_list) {
24327b4577a9SPravin B Shelar 		list_del(&vport->detach_list);
24337b4577a9SPravin B Shelar 		ovs_dp_detach_port(vport);
24347b4577a9SPravin B Shelar 	}
24357b4577a9SPravin B Shelar 
24368e4e1713SPravin B Shelar 	ovs_unlock();
24378e4e1713SPravin B Shelar 
24388e4e1713SPravin B Shelar 	cancel_work_sync(&ovs_net->dp_notify_work);
243946df7b81SPravin B Shelar }
244046df7b81SPravin B Shelar 
244146df7b81SPravin B Shelar static struct pernet_operations ovs_net_ops = {
244246df7b81SPravin B Shelar 	.init = ovs_init_net,
244346df7b81SPravin B Shelar 	.exit = ovs_exit_net,
244446df7b81SPravin B Shelar 	.id   = &ovs_net_id,
244546df7b81SPravin B Shelar 	.size = sizeof(struct ovs_net),
244646df7b81SPravin B Shelar };
244746df7b81SPravin B Shelar 
2448ccb1352eSJesse Gross static int __init dp_init(void)
2449ccb1352eSJesse Gross {
2450ccb1352eSJesse Gross 	int err;
2451ccb1352eSJesse Gross 
24523523b29bSYOSHIFUJI Hideaki / 吉藤英明 	BUILD_BUG_ON(sizeof(struct ovs_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
2453ccb1352eSJesse Gross 
2454ccb1352eSJesse Gross 	pr_info("Open vSwitch switching datapath\n");
2455ccb1352eSJesse Gross 
2456971427f3SAndy Zhou 	err = action_fifos_init();
2457ccb1352eSJesse Gross 	if (err)
2458ccb1352eSJesse Gross 		goto error;
2459ccb1352eSJesse Gross 
2460971427f3SAndy Zhou 	err = ovs_internal_dev_rtnl_link_register();
2461971427f3SAndy Zhou 	if (err)
2462971427f3SAndy Zhou 		goto error_action_fifos_exit;
2463971427f3SAndy Zhou 
24645b9e7e16SJiri Pirko 	err = ovs_flow_init();
24655b9e7e16SJiri Pirko 	if (err)
24665b9e7e16SJiri Pirko 		goto error_unreg_rtnl_link;
24675b9e7e16SJiri Pirko 
2468ccb1352eSJesse Gross 	err = ovs_vport_init();
2469ccb1352eSJesse Gross 	if (err)
2470ccb1352eSJesse Gross 		goto error_flow_exit;
2471ccb1352eSJesse Gross 
247246df7b81SPravin B Shelar 	err = register_pernet_device(&ovs_net_ops);
2473ccb1352eSJesse Gross 	if (err)
2474ccb1352eSJesse Gross 		goto error_vport_exit;
2475ccb1352eSJesse Gross 
247646df7b81SPravin B Shelar 	err = register_netdevice_notifier(&ovs_dp_device_notifier);
247746df7b81SPravin B Shelar 	if (err)
247846df7b81SPravin B Shelar 		goto error_netns_exit;
247946df7b81SPravin B Shelar 
248062b9c8d0SThomas Graf 	err = ovs_netdev_init();
248162b9c8d0SThomas Graf 	if (err)
248262b9c8d0SThomas Graf 		goto error_unreg_notifier;
248362b9c8d0SThomas Graf 
2484ccb1352eSJesse Gross 	err = dp_register_genl();
2485ccb1352eSJesse Gross 	if (err < 0)
248662b9c8d0SThomas Graf 		goto error_unreg_netdev;
2487ccb1352eSJesse Gross 
2488ccb1352eSJesse Gross 	return 0;
2489ccb1352eSJesse Gross 
249062b9c8d0SThomas Graf error_unreg_netdev:
249162b9c8d0SThomas Graf 	ovs_netdev_exit();
2492ccb1352eSJesse Gross error_unreg_notifier:
2493ccb1352eSJesse Gross 	unregister_netdevice_notifier(&ovs_dp_device_notifier);
249446df7b81SPravin B Shelar error_netns_exit:
249546df7b81SPravin B Shelar 	unregister_pernet_device(&ovs_net_ops);
2496ccb1352eSJesse Gross error_vport_exit:
2497ccb1352eSJesse Gross 	ovs_vport_exit();
2498ccb1352eSJesse Gross error_flow_exit:
2499ccb1352eSJesse Gross 	ovs_flow_exit();
25005b9e7e16SJiri Pirko error_unreg_rtnl_link:
25015b9e7e16SJiri Pirko 	ovs_internal_dev_rtnl_link_unregister();
2502971427f3SAndy Zhou error_action_fifos_exit:
2503971427f3SAndy Zhou 	action_fifos_exit();
2504ccb1352eSJesse Gross error:
2505ccb1352eSJesse Gross 	return err;
2506ccb1352eSJesse Gross }
2507ccb1352eSJesse Gross 
2508ccb1352eSJesse Gross static void dp_cleanup(void)
2509ccb1352eSJesse Gross {
2510ccb1352eSJesse Gross 	dp_unregister_genl(ARRAY_SIZE(dp_genl_families));
251162b9c8d0SThomas Graf 	ovs_netdev_exit();
2512ccb1352eSJesse Gross 	unregister_netdevice_notifier(&ovs_dp_device_notifier);
251346df7b81SPravin B Shelar 	unregister_pernet_device(&ovs_net_ops);
251446df7b81SPravin B Shelar 	rcu_barrier();
2515ccb1352eSJesse Gross 	ovs_vport_exit();
2516ccb1352eSJesse Gross 	ovs_flow_exit();
25175b9e7e16SJiri Pirko 	ovs_internal_dev_rtnl_link_unregister();
2518971427f3SAndy Zhou 	action_fifos_exit();
2519ccb1352eSJesse Gross }
2520ccb1352eSJesse Gross 
2521ccb1352eSJesse Gross module_init(dp_init);
2522ccb1352eSJesse Gross module_exit(dp_cleanup);
2523ccb1352eSJesse Gross 
2524ccb1352eSJesse Gross MODULE_DESCRIPTION("Open vSwitch switching datapath");
2525ccb1352eSJesse Gross MODULE_LICENSE("GPL");
2526ed227099SThadeu Lima de Souza Cascardo MODULE_ALIAS_GENL_FAMILY(OVS_DATAPATH_FAMILY);
2527ed227099SThadeu Lima de Souza Cascardo MODULE_ALIAS_GENL_FAMILY(OVS_VPORT_FAMILY);
2528ed227099SThadeu Lima de Souza Cascardo MODULE_ALIAS_GENL_FAMILY(OVS_FLOW_FAMILY);
2529ed227099SThadeu Lima de Souza Cascardo MODULE_ALIAS_GENL_FAMILY(OVS_PACKET_FAMILY);
253096fbc13dSAndy Zhou MODULE_ALIAS_GENL_FAMILY(OVS_METER_FAMILY);
253111efd5cbSYi-Hung Wei MODULE_ALIAS_GENL_FAMILY(OVS_CT_LIMIT_FAMILY);
2532