Blame view

net/openvswitch/datapath.c 59 KB
ccb1352e7   Jesse Gross   net: Add Open vSw...
1
  /*
ad5520073   Ben Pfaff   openvswitch: Fix ...
2
   * Copyright (c) 2007-2014 Nicira, Inc.
ccb1352e7   Jesse Gross   net: Add Open vSw...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of version 2 of the GNU General Public
   * License as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301, USA
   */
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/if_arp.h>
  #include <linux/if_vlan.h>
  #include <linux/in.h>
  #include <linux/ip.h>
  #include <linux/jhash.h>
  #include <linux/delay.h>
  #include <linux/time.h>
  #include <linux/etherdevice.h>
  #include <linux/genetlink.h>
  #include <linux/kernel.h>
  #include <linux/kthread.h>
  #include <linux/mutex.h>
  #include <linux/percpu.h>
  #include <linux/rcupdate.h>
  #include <linux/tcp.h>
  #include <linux/udp.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
39
40
  #include <linux/ethtool.h>
  #include <linux/wait.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
41
42
43
44
45
46
47
48
49
  #include <asm/div64.h>
  #include <linux/highmem.h>
  #include <linux/netfilter_bridge.h>
  #include <linux/netfilter_ipv4.h>
  #include <linux/inetdevice.h>
  #include <linux/list.h>
  #include <linux/openvswitch.h>
  #include <linux/rculist.h>
  #include <linux/dmi.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
50
  #include <net/genetlink.h>
46df7b814   Pravin B Shelar   openvswitch: Add ...
51
52
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
53
54
55
  
  #include "datapath.h"
  #include "flow.h"
e80857cce   Andy Zhou   openvswitch: Fix ...
56
  #include "flow_table.h"
e64457191   Pravin B Shelar   openvswitch: Rest...
57
  #include "flow_netlink.h"
ccb1352e7   Jesse Gross   net: Add Open vSw...
58
  #include "vport-internal_dev.h"
cff63a529   Thomas Graf   openvswitch: Remo...
59
  #include "vport-netdev.h"
ccb1352e7   Jesse Gross   net: Add Open vSw...
60

8e4e1713e   Pravin B Shelar   openvswitch: Simp...
61
  int ovs_net_id __read_mostly;
9ba559d9c   Pravin B Shelar   openvswitch: Expo...
62
  EXPORT_SYMBOL_GPL(ovs_net_id);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
63

0c200ef94   Pravin B Shelar   openvswitch: Simp...
64
65
66
  static struct genl_family dp_packet_genl_family;
  static struct genl_family dp_flow_genl_family;
  static struct genl_family dp_datapath_genl_family;
74ed7ab92   Joe Stringer   openvswitch: Add ...
67
  static const struct nla_policy flow_policy[];
48e48a70c   stephen hemminger   openvswitch: make...
68
69
  static const struct genl_multicast_group ovs_dp_flow_multicast_group = {
  	.name = OVS_FLOW_MCGROUP,
0c200ef94   Pravin B Shelar   openvswitch: Simp...
70
  };
48e48a70c   stephen hemminger   openvswitch: make...
71
72
  static const struct genl_multicast_group ovs_dp_datapath_multicast_group = {
  	.name = OVS_DATAPATH_MCGROUP,
0c200ef94   Pravin B Shelar   openvswitch: Simp...
73
  };
48e48a70c   stephen hemminger   openvswitch: make...
74
75
  static const struct genl_multicast_group ovs_dp_vport_multicast_group = {
  	.name = OVS_VPORT_MCGROUP,
0c200ef94   Pravin B Shelar   openvswitch: Simp...
76
  };
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
77
78
  /* Check if need to build a reply message.
   * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
9b67aa4a8   Samuel Gauthier   openvswitch: rest...
79
80
  static bool ovs_must_notify(struct genl_family *family, struct genl_info *info,
  			    unsigned int group)
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
81
82
  {
  	return info->nlhdr->nlmsg_flags & NLM_F_ECHO ||
f8403a2e4   Johannes Berg   genetlink: pass o...
83
  	       genl_has_listeners(family, genl_info_net(info), group);
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
84
  }
68eb55031   Johannes Berg   genetlink: pass f...
85
  static void ovs_notify(struct genl_family *family,
2a94fe48f   Johannes Berg   genetlink: make m...
86
  		       struct sk_buff *skb, struct genl_info *info)
ed6611858   Thomas Graf   openvswitch: Move...
87
  {
92c14d9b5   Jiri Benc   genetlink: simpli...
88
  	genl_notify(family, skb, info, 0, GFP_KERNEL);
ed6611858   Thomas Graf   openvswitch: Move...
89
  }
46df7b814   Pravin B Shelar   openvswitch: Add ...
90
  /**
ccb1352e7   Jesse Gross   net: Add Open vSw...
91
92
   * DOC: Locking:
   *
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
93
94
95
96
   * All writes e.g. Writes to device state (add/remove datapath, port, set
   * operations on vports, etc.), Writes to other state (flow table
   * modifications, set miscellaneous datapath parameters, etc.) are protected
   * by ovs_lock.
ccb1352e7   Jesse Gross   net: Add Open vSw...
97
98
99
100
101
102
   *
   * Reads are protected by RCU.
   *
   * There are a few special cases (mostly stats) that have their own
   * synchronization but they nest under all of above and don't interact with
   * each other.
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
103
104
   *
   * The RTNL lock nests inside ovs_mutex.
ccb1352e7   Jesse Gross   net: Add Open vSw...
105
   */
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  static DEFINE_MUTEX(ovs_mutex);
  
  void ovs_lock(void)
  {
  	mutex_lock(&ovs_mutex);
  }
  
  void ovs_unlock(void)
  {
  	mutex_unlock(&ovs_mutex);
  }
  
  #ifdef CONFIG_LOCKDEP
  int lockdep_ovsl_is_held(void)
  {
  	if (debug_locks)
  		return lockdep_is_held(&ovs_mutex);
  	else
  		return 1;
  }
9ba559d9c   Pravin B Shelar   openvswitch: Expo...
126
  EXPORT_SYMBOL_GPL(lockdep_ovsl_is_held);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
127
  #endif
ccb1352e7   Jesse Gross   net: Add Open vSw...
128
  static struct vport *new_vport(const struct vport_parms *);
8055a89cf   Thomas Graf   openvswitch: Pass...
129
  static int queue_gso_packets(struct datapath *dp, struct sk_buff *,
e8eedb85b   Pravin B Shelar   openvswitch: Remo...
130
  			     const struct sw_flow_key *,
f2a4d086e   William Tu   openvswitch: Add ...
131
132
  			     const struct dp_upcall_info *,
  			     uint32_t cutlen);
8055a89cf   Thomas Graf   openvswitch: Pass...
133
  static int queue_userspace_packet(struct datapath *dp, struct sk_buff *,
e8eedb85b   Pravin B Shelar   openvswitch: Remo...
134
  				  const struct sw_flow_key *,
f2a4d086e   William Tu   openvswitch: Add ...
135
136
  				  const struct dp_upcall_info *,
  				  uint32_t cutlen);
ccb1352e7   Jesse Gross   net: Add Open vSw...
137

cc3a5ae6f   Andy Zhou   openvswitch: Refa...
138
139
  /* Must be called with rcu_read_lock. */
  static struct datapath *get_dp_rcu(struct net *net, int dp_ifindex)
ccb1352e7   Jesse Gross   net: Add Open vSw...
140
  {
cc3a5ae6f   Andy Zhou   openvswitch: Refa...
141
  	struct net_device *dev = dev_get_by_index_rcu(net, dp_ifindex);
ccb1352e7   Jesse Gross   net: Add Open vSw...
142

ccb1352e7   Jesse Gross   net: Add Open vSw...
143
144
145
  	if (dev) {
  		struct vport *vport = ovs_internal_dev_get_vport(dev);
  		if (vport)
cc3a5ae6f   Andy Zhou   openvswitch: Refa...
146
  			return vport->dp;
ccb1352e7   Jesse Gross   net: Add Open vSw...
147
  	}
cc3a5ae6f   Andy Zhou   openvswitch: Refa...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  
  	return NULL;
  }
  
  /* The caller must hold either ovs_mutex or rcu_read_lock to keep the
   * returned dp pointer valid.
   */
  static inline struct datapath *get_dp(struct net *net, int dp_ifindex)
  {
  	struct datapath *dp;
  
  	WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_ovsl_is_held());
  	rcu_read_lock();
  	dp = get_dp_rcu(net, dp_ifindex);
ccb1352e7   Jesse Gross   net: Add Open vSw...
162
163
164
165
  	rcu_read_unlock();
  
  	return dp;
  }
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
166
  /* Must be called with rcu_read_lock or ovs_mutex. */
971427f35   Andy Zhou   openvswitch: Add ...
167
  const char *ovs_dp_name(const struct datapath *dp)
ccb1352e7   Jesse Gross   net: Add Open vSw...
168
  {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
169
  	struct vport *vport = ovs_vport_ovsl_rcu(dp, OVSP_LOCAL);
c9db965c5   Thomas Graf   openvswitch: Abst...
170
  	return ovs_vport_name(vport);
ccb1352e7   Jesse Gross   net: Add Open vSw...
171
  }
12eb18f71   Thomas Graf   openvswitch: Cons...
172
  static int get_dpifindex(const struct datapath *dp)
ccb1352e7   Jesse Gross   net: Add Open vSw...
173
174
175
176
177
  {
  	struct vport *local;
  	int ifindex;
  
  	rcu_read_lock();
15eac2a74   Pravin B Shelar   openvswitch: Incr...
178
  	local = ovs_vport_rcu(dp, OVSP_LOCAL);
ccb1352e7   Jesse Gross   net: Add Open vSw...
179
  	if (local)
be4ace6e6   Thomas Graf   openvswitch: Move...
180
  		ifindex = local->dev->ifindex;
ccb1352e7   Jesse Gross   net: Add Open vSw...
181
182
183
184
185
186
187
188
189
190
191
  	else
  		ifindex = 0;
  
  	rcu_read_unlock();
  
  	return ifindex;
  }
  
  static void destroy_dp_rcu(struct rcu_head *rcu)
  {
  	struct datapath *dp = container_of(rcu, struct datapath, rcu);
9b996e544   Pravin B Shelar   openvswitch: Move...
192
  	ovs_flow_tbl_destroy(&dp->table);
ccb1352e7   Jesse Gross   net: Add Open vSw...
193
  	free_percpu(dp->stats_percpu);
15eac2a74   Pravin B Shelar   openvswitch: Incr...
194
  	kfree(dp->ports);
ccb1352e7   Jesse Gross   net: Add Open vSw...
195
196
  	kfree(dp);
  }
15eac2a74   Pravin B Shelar   openvswitch: Incr...
197
198
199
200
201
  static struct hlist_head *vport_hash_bucket(const struct datapath *dp,
  					    u16 port_no)
  {
  	return &dp->ports[port_no & (DP_VPORT_HASH_BUCKETS - 1)];
  }
bb6f9a708   Jarno Rajahalme   openvswitch: Clar...
202
  /* Called with ovs_mutex or RCU read lock. */
15eac2a74   Pravin B Shelar   openvswitch: Incr...
203
204
205
  struct vport *ovs_lookup_vport(const struct datapath *dp, u16 port_no)
  {
  	struct vport *vport;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
206
207
208
  	struct hlist_head *head;
  
  	head = vport_hash_bucket(dp, port_no);
b67bfe0d4   Sasha Levin   hlist: drop the n...
209
  	hlist_for_each_entry_rcu(vport, head, dp_hash_node) {
15eac2a74   Pravin B Shelar   openvswitch: Incr...
210
211
212
213
214
  		if (vport->port_no == port_no)
  			return vport;
  	}
  	return NULL;
  }
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
215
  /* Called with ovs_mutex. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
216
217
218
219
220
221
222
  static struct vport *new_vport(const struct vport_parms *parms)
  {
  	struct vport *vport;
  
  	vport = ovs_vport_add(parms);
  	if (!IS_ERR(vport)) {
  		struct datapath *dp = parms->dp;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
223
  		struct hlist_head *head = vport_hash_bucket(dp, vport->port_no);
ccb1352e7   Jesse Gross   net: Add Open vSw...
224

15eac2a74   Pravin B Shelar   openvswitch: Incr...
225
  		hlist_add_head_rcu(&vport->dp_hash_node, head);
ccb1352e7   Jesse Gross   net: Add Open vSw...
226
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
227
228
  	return vport;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
229
230
  void ovs_dp_detach_port(struct vport *p)
  {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
231
  	ASSERT_OVSL();
ccb1352e7   Jesse Gross   net: Add Open vSw...
232
233
  
  	/* First drop references to device. */
15eac2a74   Pravin B Shelar   openvswitch: Incr...
234
  	hlist_del_rcu(&p->dp_hash_node);
ccb1352e7   Jesse Gross   net: Add Open vSw...
235
236
237
238
239
240
  
  	/* Then destroy it. */
  	ovs_vport_del(p);
  }
  
  /* Must be called with rcu_read_lock. */
8c8b1b83f   Pravin B Shelar   openvswitch: Use ...
241
  void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
242
  {
83c8df26a   Pravin B Shelar   openvswitch: refa...
243
  	const struct vport *p = OVS_CB(skb)->input_vport;
ccb1352e7   Jesse Gross   net: Add Open vSw...
244
245
  	struct datapath *dp = p->dp;
  	struct sw_flow *flow;
d98612b8c   Lorand Jakab   openvswitch: Remo...
246
  	struct sw_flow_actions *sf_acts;
ccb1352e7   Jesse Gross   net: Add Open vSw...
247
  	struct dp_stats_percpu *stats;
ccb1352e7   Jesse Gross   net: Add Open vSw...
248
  	u64 *stats_counter;
1bd7116f1   Andy Zhou   openvswitch: coll...
249
  	u32 n_mask_hit;
ccb1352e7   Jesse Gross   net: Add Open vSw...
250

404f2f101   Shan Wei   net: openvswitch:...
251
  	stats = this_cpu_ptr(dp->stats_percpu);
ccb1352e7   Jesse Gross   net: Add Open vSw...
252

ccb1352e7   Jesse Gross   net: Add Open vSw...
253
  	/* Look up flow. */
8c8b1b83f   Pravin B Shelar   openvswitch: Use ...
254
  	flow = ovs_flow_tbl_lookup_stats(&dp->table, key, &n_mask_hit);
ccb1352e7   Jesse Gross   net: Add Open vSw...
255
256
  	if (unlikely(!flow)) {
  		struct dp_upcall_info upcall;
8c8b1b83f   Pravin B Shelar   openvswitch: Use ...
257
  		int error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
258

ccea74457   Neil McKee   openvswitch: incl...
259
  		memset(&upcall, 0, sizeof(upcall));
ccb1352e7   Jesse Gross   net: Add Open vSw...
260
  		upcall.cmd = OVS_PACKET_CMD_MISS;
5cd667b0a   Alex Wang   openvswitch: Allo...
261
  		upcall.portid = ovs_vport_find_upcall_portid(p, skb);
7f8a436ea   Joe Stringer   openvswitch: Add ...
262
  		upcall.mru = OVS_CB(skb)->mru;
f2a4d086e   William Tu   openvswitch: Add ...
263
  		error = ovs_dp_upcall(dp, skb, key, &upcall, 0);
c5eba0b6f   Li RongQing   openvswitch: dist...
264
265
266
267
  		if (unlikely(error))
  			kfree_skb(skb);
  		else
  			consume_skb(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
268
269
270
  		stats_counter = &stats->n_missed;
  		goto out;
  	}
d98612b8c   Lorand Jakab   openvswitch: Remo...
271
272
273
  	ovs_flow_stats_update(flow, key->tp.flags, skb);
  	sf_acts = rcu_dereference(flow->sf_acts);
  	ovs_execute_actions(dp, skb, sf_acts, key);
ccb1352e7   Jesse Gross   net: Add Open vSw...
274

e298e5057   Pravin B Shelar   openvswitch: Per ...
275
  	stats_counter = &stats->n_hit;
ccb1352e7   Jesse Gross   net: Add Open vSw...
276
277
278
  
  out:
  	/* Update datapath statistics. */
df9d9fdf8   WANG Cong   openvswitch: rena...
279
  	u64_stats_update_begin(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
280
  	(*stats_counter)++;
1bd7116f1   Andy Zhou   openvswitch: coll...
281
  	stats->n_mask_hit += n_mask_hit;
df9d9fdf8   WANG Cong   openvswitch: rena...
282
  	u64_stats_update_end(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
283
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
284
  int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
e8eedb85b   Pravin B Shelar   openvswitch: Remo...
285
  		  const struct sw_flow_key *key,
f2a4d086e   William Tu   openvswitch: Add ...
286
287
  		  const struct dp_upcall_info *upcall_info,
  		  uint32_t cutlen)
ccb1352e7   Jesse Gross   net: Add Open vSw...
288
289
  {
  	struct dp_stats_percpu *stats;
ccb1352e7   Jesse Gross   net: Add Open vSw...
290
  	int err;
15e473046   Eric W. Biederman   netlink: Rename p...
291
  	if (upcall_info->portid == 0) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
292
293
294
  		err = -ENOTCONN;
  		goto err;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
295
  	if (!skb_is_gso(skb))
f2a4d086e   William Tu   openvswitch: Add ...
296
  		err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen);
ccb1352e7   Jesse Gross   net: Add Open vSw...
297
  	else
f2a4d086e   William Tu   openvswitch: Add ...
298
  		err = queue_gso_packets(dp, skb, key, upcall_info, cutlen);
ccb1352e7   Jesse Gross   net: Add Open vSw...
299
300
301
302
303
304
  	if (err)
  		goto err;
  
  	return 0;
  
  err:
404f2f101   Shan Wei   net: openvswitch:...
305
  	stats = this_cpu_ptr(dp->stats_percpu);
ccb1352e7   Jesse Gross   net: Add Open vSw...
306

df9d9fdf8   WANG Cong   openvswitch: rena...
307
  	u64_stats_update_begin(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
308
  	stats->n_lost++;
df9d9fdf8   WANG Cong   openvswitch: rena...
309
  	u64_stats_update_end(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
310
311
312
  
  	return err;
  }
8055a89cf   Thomas Graf   openvswitch: Pass...
313
  static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
e8eedb85b   Pravin B Shelar   openvswitch: Remo...
314
  			     const struct sw_flow_key *key,
f2a4d086e   William Tu   openvswitch: Add ...
315
316
  			     const struct dp_upcall_info *upcall_info,
  				 uint32_t cutlen)
ccb1352e7   Jesse Gross   net: Add Open vSw...
317
  {
a1b5d0dd2   Ben Pfaff   openvswitch: Chec...
318
  	unsigned short gso_type = skb_shinfo(skb)->gso_type;
ccb1352e7   Jesse Gross   net: Add Open vSw...
319
320
321
  	struct sw_flow_key later_key;
  	struct sk_buff *segs, *nskb;
  	int err;
9207f9d45   Konstantin Khlebnikov   net: preserve IP ...
322
  	BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_SGO_CB_OFFSET);
09c5e6054   Thomas Graf   openvswitch: Comp...
323
  	segs = __skb_gso_segment(skb, NETIF_F_SG, false);
92e5dfc34   Pravin B Shelar   openvswitch: Chec...
324
325
  	if (IS_ERR(segs))
  		return PTR_ERR(segs);
330966e50   Florian Westphal   net: make skb_gso...
326
327
  	if (segs == NULL)
  		return -EINVAL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
328

e8eedb85b   Pravin B Shelar   openvswitch: Remo...
329
330
331
332
333
334
335
336
  	if (gso_type & SKB_GSO_UDP) {
  		/* The initial flow key extracted by ovs_flow_key_extract()
  		 * in this case is for a first fragment, so we need to
  		 * properly mark later fragments.
  		 */
  		later_key = *key;
  		later_key.ip.frag = OVS_FRAG_TYPE_LATER;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
337
338
339
  	/* Queue all of the segments. */
  	skb = segs;
  	do {
e8eedb85b   Pravin B Shelar   openvswitch: Remo...
340
341
  		if (gso_type & SKB_GSO_UDP && skb != segs)
  			key = &later_key;
f2a4d086e   William Tu   openvswitch: Add ...
342
  		err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen);
ccb1352e7   Jesse Gross   net: Add Open vSw...
343
344
  		if (err)
  			break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
345
346
347
348
349
350
351
352
353
354
355
356
357
  	} while ((skb = skb->next));
  
  	/* Free all of the segments. */
  	skb = segs;
  	do {
  		nskb = skb->next;
  		if (err)
  			kfree_skb(skb);
  		else
  			consume_skb(skb);
  	} while ((skb = nskb));
  	return err;
  }
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
358
  static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
bda56f143   Thomas Graf   openvswitch: Use ...
359
  			      unsigned int hdrlen)
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
360
361
  {
  	size_t size = NLMSG_ALIGN(sizeof(struct ovs_header))
bda56f143   Thomas Graf   openvswitch: Use ...
362
  		+ nla_total_size(hdrlen) /* OVS_PACKET_ATTR_PACKET */
b95e5928f   William Tu   openvswitch: Add ...
363
364
  		+ nla_total_size(ovs_key_attr_size()) /* OVS_PACKET_ATTR_KEY */
  		+ nla_total_size(sizeof(unsigned int)); /* OVS_PACKET_ATTR_LEN */
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
365
366
  
  	/* OVS_PACKET_ATTR_USERDATA */
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
367
368
369
370
371
372
  	if (upcall_info->userdata)
  		size += NLA_ALIGN(upcall_info->userdata->nla_len);
  
  	/* OVS_PACKET_ATTR_EGRESS_TUN_KEY */
  	if (upcall_info->egress_tun_info)
  		size += nla_total_size(ovs_tun_key_attr_size());
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
373

ccea74457   Neil McKee   openvswitch: incl...
374
375
376
  	/* OVS_PACKET_ATTR_ACTIONS */
  	if (upcall_info->actions_len)
  		size += nla_total_size(upcall_info->actions_len);
7f8a436ea   Joe Stringer   openvswitch: Add ...
377
378
379
  	/* OVS_PACKET_ATTR_MRU */
  	if (upcall_info->mru)
  		size += nla_total_size(sizeof(upcall_info->mru));
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
380
381
  	return size;
  }
7f8a436ea   Joe Stringer   openvswitch: Add ...
382
383
384
385
386
387
388
389
390
  static void pad_packet(struct datapath *dp, struct sk_buff *skb)
  {
  	if (!(dp->user_features & OVS_DP_F_UNALIGNED)) {
  		size_t plen = NLA_ALIGN(skb->len) - skb->len;
  
  		if (plen > 0)
  			memset(skb_put(skb, plen), 0, plen);
  	}
  }
8055a89cf   Thomas Graf   openvswitch: Pass...
391
  static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
e8eedb85b   Pravin B Shelar   openvswitch: Remo...
392
  				  const struct sw_flow_key *key,
f2a4d086e   William Tu   openvswitch: Add ...
393
394
  				  const struct dp_upcall_info *upcall_info,
  				  uint32_t cutlen)
ccb1352e7   Jesse Gross   net: Add Open vSw...
395
396
397
  {
  	struct ovs_header *upcall;
  	struct sk_buff *nskb = NULL;
4ee45ea05   Li RongQing   openvswitch: fix ...
398
  	struct sk_buff *user_skb = NULL; /* to be queued to userspace */
ccb1352e7   Jesse Gross   net: Add Open vSw...
399
  	struct nlattr *nla;
795449d8b   Thomas Graf   openvswitch: Enab...
400
  	size_t len;
bda56f143   Thomas Graf   openvswitch: Use ...
401
  	unsigned int hlen;
8055a89cf   Thomas Graf   openvswitch: Pass...
402
403
404
405
406
  	int err, dp_ifindex;
  
  	dp_ifindex = get_dpifindex(dp);
  	if (!dp_ifindex)
  		return -ENODEV;
ccb1352e7   Jesse Gross   net: Add Open vSw...
407

df8a39def   Jiri Pirko   net: rename vlan_...
408
  	if (skb_vlan_tag_present(skb)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
409
410
411
  		nskb = skb_clone(skb, GFP_ATOMIC);
  		if (!nskb)
  			return -ENOMEM;
5968250c8   Jiri Pirko   vlan: introduce *...
412
  		nskb = __vlan_hwaccel_push_inside(nskb);
8aa51d64c   Dan Carpenter   openvswitch: chec...
413
  		if (!nskb)
ccb1352e7   Jesse Gross   net: Add Open vSw...
414
  			return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
415
416
417
418
419
420
421
  		skb = nskb;
  	}
  
  	if (nla_attr_size(skb->len) > USHRT_MAX) {
  		err = -EFBIG;
  		goto out;
  	}
bda56f143   Thomas Graf   openvswitch: Use ...
422
423
424
425
426
427
428
429
430
431
432
433
434
  	/* Complete checksum if needed */
  	if (skb->ip_summed == CHECKSUM_PARTIAL &&
  	    (err = skb_checksum_help(skb)))
  		goto out;
  
  	/* Older versions of OVS user space enforce alignment of the last
  	 * Netlink attribute to NLA_ALIGNTO which would require extensive
  	 * padding logic. Only perform zerocopy if padding is not required.
  	 */
  	if (dp->user_features & OVS_DP_F_UNALIGNED)
  		hlen = skb_zerocopy_headlen(skb);
  	else
  		hlen = skb->len;
f2a4d086e   William Tu   openvswitch: Add ...
435
  	len = upcall_msg_size(upcall_info, hlen - cutlen);
551ddc057   Florian Westphal   openvswitch: Reve...
436
  	user_skb = genlmsg_new(len, GFP_ATOMIC);
ccb1352e7   Jesse Gross   net: Add Open vSw...
437
438
439
440
441
442
443
444
  	if (!user_skb) {
  		err = -ENOMEM;
  		goto out;
  	}
  
  	upcall = genlmsg_put(user_skb, 0, 0, &dp_packet_genl_family,
  			     0, upcall_info->cmd);
  	upcall->dp_ifindex = dp_ifindex;
5b4237bbc   Joe Stringer   openvswitch: Refa...
445
  	err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, user_skb);
f53e38317   Andy Zhou   openvswitch: Avoi...
446
  	BUG_ON(err);
ccb1352e7   Jesse Gross   net: Add Open vSw...
447
448
  
  	if (upcall_info->userdata)
4490108b4   Ben Pfaff   openvswitch: Allo...
449
450
451
  		__nla_put(user_skb, OVS_PACKET_ATTR_USERDATA,
  			  nla_len(upcall_info->userdata),
  			  nla_data(upcall_info->userdata));
ccb1352e7   Jesse Gross   net: Add Open vSw...
452

8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
453
454
  	if (upcall_info->egress_tun_info) {
  		nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
455
456
  		err = ovs_nla_put_tunnel_info(user_skb,
  					      upcall_info->egress_tun_info);
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
457
458
459
  		BUG_ON(err);
  		nla_nest_end(user_skb, nla);
  	}
ccea74457   Neil McKee   openvswitch: incl...
460
461
462
463
464
465
466
467
468
469
  	if (upcall_info->actions_len) {
  		nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_ACTIONS);
  		err = ovs_nla_put_actions(upcall_info->actions,
  					  upcall_info->actions_len,
  					  user_skb);
  		if (!err)
  			nla_nest_end(user_skb, nla);
  		else
  			nla_nest_cancel(user_skb, nla);
  	}
7f8a436ea   Joe Stringer   openvswitch: Add ...
470
471
472
473
474
475
476
477
478
  	/* Add OVS_PACKET_ATTR_MRU */
  	if (upcall_info->mru) {
  		if (nla_put_u16(user_skb, OVS_PACKET_ATTR_MRU,
  				upcall_info->mru)) {
  			err = -ENOBUFS;
  			goto out;
  		}
  		pad_packet(dp, user_skb);
  	}
b95e5928f   William Tu   openvswitch: Add ...
479
480
481
482
483
484
485
486
487
  	/* Add OVS_PACKET_ATTR_LEN when packet is truncated */
  	if (cutlen > 0) {
  		if (nla_put_u32(user_skb, OVS_PACKET_ATTR_LEN,
  				skb->len)) {
  			err = -ENOBUFS;
  			goto out;
  		}
  		pad_packet(dp, user_skb);
  	}
bda56f143   Thomas Graf   openvswitch: Use ...
488
489
490
491
492
493
  	/* Only reserve room for attribute header, packet data is added
  	 * in skb_zerocopy() */
  	if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) {
  		err = -ENOBUFS;
  		goto out;
  	}
f2a4d086e   William Tu   openvswitch: Add ...
494
  	nla->nla_len = nla_attr_size(skb->len - cutlen);
ccb1352e7   Jesse Gross   net: Add Open vSw...
495

f2a4d086e   William Tu   openvswitch: Add ...
496
  	err = skb_zerocopy(user_skb, skb, skb->len - cutlen, hlen);
36d5fe6a0   Zoltan Kiss   core, nfqueue, op...
497
498
  	if (err)
  		goto out;
ccb1352e7   Jesse Gross   net: Add Open vSw...
499

aea0bb4f8   Thomas Graf   openvswitch: Pad ...
500
  	/* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */
7f8a436ea   Joe Stringer   openvswitch: Add ...
501
  	pad_packet(dp, user_skb);
aea0bb4f8   Thomas Graf   openvswitch: Pad ...
502

bda56f143   Thomas Graf   openvswitch: Use ...
503
  	((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len;
ccb1352e7   Jesse Gross   net: Add Open vSw...
504

bda56f143   Thomas Graf   openvswitch: Use ...
505
  	err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);
4ee45ea05   Li RongQing   openvswitch: fix ...
506
  	user_skb = NULL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
507
  out:
36d5fe6a0   Zoltan Kiss   core, nfqueue, op...
508
509
  	if (err)
  		skb_tx_error(skb);
4ee45ea05   Li RongQing   openvswitch: fix ...
510
  	kfree_skb(user_skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
511
512
513
  	kfree_skb(nskb);
  	return err;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
514
515
516
  static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
  {
  	struct ovs_header *ovs_header = info->userhdr;
7f8a436ea   Joe Stringer   openvswitch: Add ...
517
  	struct net *net = sock_net(skb->sk);
ccb1352e7   Jesse Gross   net: Add Open vSw...
518
519
520
521
  	struct nlattr **a = info->attrs;
  	struct sw_flow_actions *acts;
  	struct sk_buff *packet;
  	struct sw_flow *flow;
d98612b8c   Lorand Jakab   openvswitch: Remo...
522
  	struct sw_flow_actions *sf_acts;
ccb1352e7   Jesse Gross   net: Add Open vSw...
523
524
  	struct datapath *dp;
  	struct ethhdr *eth;
83c8df26a   Pravin B Shelar   openvswitch: refa...
525
  	struct vport *input_vport;
7f8a436ea   Joe Stringer   openvswitch: Add ...
526
  	u16 mru = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
527
528
  	int len;
  	int err;
1ba398041   Thomas Graf   openvswitch: pack...
529
  	bool log = !a[OVS_PACKET_ATTR_PROBE];
ccb1352e7   Jesse Gross   net: Add Open vSw...
530
531
532
  
  	err = -EINVAL;
  	if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] ||
dded45fc1   Thomas Graf   openvswitch: Spec...
533
  	    !a[OVS_PACKET_ATTR_ACTIONS])
ccb1352e7   Jesse Gross   net: Add Open vSw...
534
535
536
537
538
539
540
541
  		goto err;
  
  	len = nla_len(a[OVS_PACKET_ATTR_PACKET]);
  	packet = __dev_alloc_skb(NET_IP_ALIGN + len, GFP_KERNEL);
  	err = -ENOMEM;
  	if (!packet)
  		goto err;
  	skb_reserve(packet, NET_IP_ALIGN);
32686a9d2   Thomas Graf   openvswitch: Use ...
542
  	nla_memcpy(__skb_put(packet, len), a[OVS_PACKET_ATTR_PACKET], len);
ccb1352e7   Jesse Gross   net: Add Open vSw...
543
544
545
546
547
548
549
  
  	skb_reset_mac_header(packet);
  	eth = eth_hdr(packet);
  
  	/* Normally, setting the skb 'protocol' field would be handled by a
  	 * call to eth_type_trans(), but it assumes there's a sending
  	 * device, which we may not have. */
6713fc9b8   Alexander Duyck   openvswitch: Use ...
550
  	if (eth_proto_is_802_3(eth->h_proto))
ccb1352e7   Jesse Gross   net: Add Open vSw...
551
552
553
  		packet->protocol = eth->h_proto;
  	else
  		packet->protocol = htons(ETH_P_802_2);
7f8a436ea   Joe Stringer   openvswitch: Add ...
554
555
556
557
558
559
  	/* Set packet's mru */
  	if (a[OVS_PACKET_ATTR_MRU]) {
  		mru = nla_get_u16(a[OVS_PACKET_ATTR_MRU]);
  		packet->ignore_df = 1;
  	}
  	OVS_CB(packet)->mru = mru;
ccb1352e7   Jesse Gross   net: Add Open vSw...
560
  	/* Build an sw_flow for sending this packet. */
23dabf88a   Jarno Rajahalme   openvswitch: Remo...
561
  	flow = ovs_flow_alloc();
ccb1352e7   Jesse Gross   net: Add Open vSw...
562
563
564
  	err = PTR_ERR(flow);
  	if (IS_ERR(flow))
  		goto err_kfree_skb;
c2ac66735   Joe Stringer   openvswitch: Allo...
565
566
  	err = ovs_flow_key_extract_userspace(net, a[OVS_PACKET_ATTR_KEY],
  					     packet, &flow->key, log);
ccb1352e7   Jesse Gross   net: Add Open vSw...
567
568
  	if (err)
  		goto err_flow_free;
7f8a436ea   Joe Stringer   openvswitch: Add ...
569
  	err = ovs_nla_copy_actions(net, a[OVS_PACKET_ATTR_ACTIONS],
05da5898a   Jarno Rajahalme   openvswitch: Add ...
570
  				   &flow->key, &acts, log);
74f84a572   Pravin B Shelar   openvswitch: Copy...
571
572
  	if (err)
  		goto err_flow_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
573

f57966840   Jesse Gross   openvswitch: Add ...
574
  	rcu_assign_pointer(flow->sf_acts, acts);
ccb1352e7   Jesse Gross   net: Add Open vSw...
575
  	packet->priority = flow->key.phy.priority;
39c7caebc   Ansis Atteka   openvswitch: add ...
576
  	packet->mark = flow->key.phy.skb_mark;
ccb1352e7   Jesse Gross   net: Add Open vSw...
577
578
  
  	rcu_read_lock();
7f8a436ea   Joe Stringer   openvswitch: Add ...
579
  	dp = get_dp_rcu(net, ovs_header->dp_ifindex);
ccb1352e7   Jesse Gross   net: Add Open vSw...
580
581
582
  	err = -ENODEV;
  	if (!dp)
  		goto err_unlock;
83c8df26a   Pravin B Shelar   openvswitch: refa...
583
584
585
586
587
588
  	input_vport = ovs_vport_rcu(dp, flow->key.phy.in_port);
  	if (!input_vport)
  		input_vport = ovs_vport_rcu(dp, OVSP_LOCAL);
  
  	if (!input_vport)
  		goto err_unlock;
7f8a436ea   Joe Stringer   openvswitch: Add ...
589
  	packet->dev = input_vport->dev;
83c8df26a   Pravin B Shelar   openvswitch: refa...
590
  	OVS_CB(packet)->input_vport = input_vport;
d98612b8c   Lorand Jakab   openvswitch: Remo...
591
  	sf_acts = rcu_dereference(flow->sf_acts);
83c8df26a   Pravin B Shelar   openvswitch: refa...
592

ccb1352e7   Jesse Gross   net: Add Open vSw...
593
  	local_bh_disable();
d98612b8c   Lorand Jakab   openvswitch: Remo...
594
  	err = ovs_execute_actions(dp, packet, sf_acts, &flow->key);
ccb1352e7   Jesse Gross   net: Add Open vSw...
595
596
  	local_bh_enable();
  	rcu_read_unlock();
03f0d916a   Andy Zhou   openvswitch: Mega...
597
  	ovs_flow_free(flow, false);
ccb1352e7   Jesse Gross   net: Add Open vSw...
598
599
600
601
602
  	return err;
  
  err_unlock:
  	rcu_read_unlock();
  err_flow_free:
03f0d916a   Andy Zhou   openvswitch: Mega...
603
  	ovs_flow_free(flow, false);
ccb1352e7   Jesse Gross   net: Add Open vSw...
604
605
606
607
608
609
610
  err_kfree_skb:
  	kfree_skb(packet);
  err:
  	return err;
  }
  
  static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = {
dded45fc1   Thomas Graf   openvswitch: Spec...
611
  	[OVS_PACKET_ATTR_PACKET] = { .len = ETH_HLEN },
ccb1352e7   Jesse Gross   net: Add Open vSw...
612
613
  	[OVS_PACKET_ATTR_KEY] = { .type = NLA_NESTED },
  	[OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED },
1ba398041   Thomas Graf   openvswitch: pack...
614
  	[OVS_PACKET_ATTR_PROBE] = { .type = NLA_FLAG },
7f8a436ea   Joe Stringer   openvswitch: Add ...
615
  	[OVS_PACKET_ATTR_MRU] = { .type = NLA_U16 },
ccb1352e7   Jesse Gross   net: Add Open vSw...
616
  };
4534de830   Johannes Berg   genetlink: make a...
617
  static const struct genl_ops dp_packet_genl_ops[] = {
ccb1352e7   Jesse Gross   net: Add Open vSw...
618
  	{ .cmd = OVS_PACKET_CMD_EXECUTE,
4a92602aa   Tycho Andersen   openvswitch: allo...
619
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
620
621
622
623
  	  .policy = packet_policy,
  	  .doit = ovs_packet_cmd_execute
  	}
  };
0c200ef94   Pravin B Shelar   openvswitch: Simp...
624
625
626
627
628
629
630
631
632
633
634
  static struct genl_family dp_packet_genl_family = {
  	.id = GENL_ID_GENERATE,
  	.hdrsize = sizeof(struct ovs_header),
  	.name = OVS_PACKET_FAMILY,
  	.version = OVS_PACKET_VERSION,
  	.maxattr = OVS_PACKET_ATTR_MAX,
  	.netnsok = true,
  	.parallel_ops = true,
  	.ops = dp_packet_genl_ops,
  	.n_ops = ARRAY_SIZE(dp_packet_genl_ops),
  };
12eb18f71   Thomas Graf   openvswitch: Cons...
635
  static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
1bd7116f1   Andy Zhou   openvswitch: coll...
636
  			 struct ovs_dp_megaflow_stats *mega_stats)
ccb1352e7   Jesse Gross   net: Add Open vSw...
637
638
  {
  	int i;
ccb1352e7   Jesse Gross   net: Add Open vSw...
639

1bd7116f1   Andy Zhou   openvswitch: coll...
640
  	memset(mega_stats, 0, sizeof(*mega_stats));
b637e4988   Pravin B Shelar   openvswitch: Move...
641
  	stats->n_flows = ovs_flow_tbl_count(&dp->table);
1bd7116f1   Andy Zhou   openvswitch: coll...
642
  	mega_stats->n_masks = ovs_flow_tbl_num_masks(&dp->table);
ccb1352e7   Jesse Gross   net: Add Open vSw...
643
644
  
  	stats->n_hit = stats->n_missed = stats->n_lost = 0;
1bd7116f1   Andy Zhou   openvswitch: coll...
645

ccb1352e7   Jesse Gross   net: Add Open vSw...
646
647
648
649
650
651
652
653
  	for_each_possible_cpu(i) {
  		const struct dp_stats_percpu *percpu_stats;
  		struct dp_stats_percpu local_stats;
  		unsigned int start;
  
  		percpu_stats = per_cpu_ptr(dp->stats_percpu, i);
  
  		do {
57a7744e0   Eric W. Biederman   net: Replace u64_...
654
  			start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
655
  			local_stats = *percpu_stats;
57a7744e0   Eric W. Biederman   net: Replace u64_...
656
  		} while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
ccb1352e7   Jesse Gross   net: Add Open vSw...
657
658
659
660
  
  		stats->n_hit += local_stats.n_hit;
  		stats->n_missed += local_stats.n_missed;
  		stats->n_lost += local_stats.n_lost;
1bd7116f1   Andy Zhou   openvswitch: coll...
661
  		mega_stats->n_mask_hit += local_stats.n_mask_hit;
ccb1352e7   Jesse Gross   net: Add Open vSw...
662
663
  	}
  }
74ed7ab92   Joe Stringer   openvswitch: Add ...
664
665
666
667
668
669
670
671
672
673
674
675
  static bool should_fill_key(const struct sw_flow_id *sfid, uint32_t ufid_flags)
  {
  	return ovs_identifier_is_ufid(sfid) &&
  	       !(ufid_flags & OVS_UFID_F_OMIT_KEY);
  }
  
  static bool should_fill_mask(uint32_t ufid_flags)
  {
  	return !(ufid_flags & OVS_UFID_F_OMIT_MASK);
  }
  
  static bool should_fill_actions(uint32_t ufid_flags)
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
676
  {
74ed7ab92   Joe Stringer   openvswitch: Add ...
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  	return !(ufid_flags & OVS_UFID_F_OMIT_ACTIONS);
  }
  
  static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts,
  				    const struct sw_flow_id *sfid,
  				    uint32_t ufid_flags)
  {
  	size_t len = NLMSG_ALIGN(sizeof(struct ovs_header));
  
  	/* OVS_FLOW_ATTR_UFID */
  	if (sfid && ovs_identifier_is_ufid(sfid))
  		len += nla_total_size(sfid->ufid_len);
  
  	/* OVS_FLOW_ATTR_KEY */
  	if (!sfid || should_fill_key(sfid, ufid_flags))
  		len += nla_total_size(ovs_key_attr_size());
  
  	/* OVS_FLOW_ATTR_MASK */
  	if (should_fill_mask(ufid_flags))
  		len += nla_total_size(ovs_key_attr_size());
  
  	/* OVS_FLOW_ATTR_ACTIONS */
  	if (should_fill_actions(ufid_flags))
8e2fed1c0   Joe Stringer   openvswitch: Seri...
700
  		len += nla_total_size(acts->orig_len);
74ed7ab92   Joe Stringer   openvswitch: Add ...
701
702
  
  	return len
66c7a5ee1   Nicolas Dichtel   ovs: align nlattr...
703
  		+ nla_total_size_64bit(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
704
  		+ nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */
66c7a5ee1   Nicolas Dichtel   ovs: align nlattr...
705
  		+ nla_total_size_64bit(8); /* OVS_FLOW_ATTR_USED */
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
706
  }
bb6f9a708   Jarno Rajahalme   openvswitch: Clar...
707
  /* Called with ovs_mutex or RCU read lock. */
ca7105f27   Joe Stringer   openvswitch: Refa...
708
709
710
711
712
713
  static int ovs_flow_cmd_fill_stats(const struct sw_flow *flow,
  				   struct sk_buff *skb)
  {
  	struct ovs_flow_stats stats;
  	__be16 tcp_flags;
  	unsigned long used;
ccb1352e7   Jesse Gross   net: Add Open vSw...
714

e298e5057   Pravin B Shelar   openvswitch: Per ...
715
  	ovs_flow_stats_get(flow, &stats, &used, &tcp_flags);
0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
716

028d6a676   David S. Miller   openvswitch: Stop...
717
  	if (used &&
0238b7204   Nicolas Dichtel   ovs: use nla_put_...
718
719
  	    nla_put_u64_64bit(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used),
  			      OVS_FLOW_ATTR_PAD))
ca7105f27   Joe Stringer   openvswitch: Refa...
720
  		return -EMSGSIZE;
ccb1352e7   Jesse Gross   net: Add Open vSw...
721

028d6a676   David S. Miller   openvswitch: Stop...
722
  	if (stats.n_packets &&
66c7a5ee1   Nicolas Dichtel   ovs: align nlattr...
723
724
725
  	    nla_put_64bit(skb, OVS_FLOW_ATTR_STATS,
  			  sizeof(struct ovs_flow_stats), &stats,
  			  OVS_FLOW_ATTR_PAD))
ca7105f27   Joe Stringer   openvswitch: Refa...
726
  		return -EMSGSIZE;
ccb1352e7   Jesse Gross   net: Add Open vSw...
727

e298e5057   Pravin B Shelar   openvswitch: Per ...
728
729
  	if ((u8)ntohs(tcp_flags) &&
  	     nla_put_u8(skb, OVS_FLOW_ATTR_TCP_FLAGS, (u8)ntohs(tcp_flags)))
ca7105f27   Joe Stringer   openvswitch: Refa...
730
731
732
733
734
735
736
737
738
739
740
  		return -EMSGSIZE;
  
  	return 0;
  }
  
  /* Called with ovs_mutex or RCU read lock. */
  static int ovs_flow_cmd_fill_actions(const struct sw_flow *flow,
  				     struct sk_buff *skb, int skb_orig_len)
  {
  	struct nlattr *start;
  	int err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
741
742
743
744
745
746
747
748
749
750
751
  
  	/* If OVS_FLOW_ATTR_ACTIONS doesn't fit, skip dumping the actions if
  	 * this is the first flow to be dumped into 'skb'.  This is unusual for
  	 * Netlink but individual action lists can be longer than
  	 * NLMSG_GOODSIZE and thus entirely undumpable if we didn't do this.
  	 * The userspace caller can always fetch the actions separately if it
  	 * really wants them.  (Most userspace callers in fact don't care.)
  	 *
  	 * This can only fail for dump operations because the skb is always
  	 * properly sized for single flows.
  	 */
74f84a572   Pravin B Shelar   openvswitch: Copy...
752
753
  	start = nla_nest_start(skb, OVS_FLOW_ATTR_ACTIONS);
  	if (start) {
d57170b1b   Pravin B Shelar   openvswitch: Use ...
754
  		const struct sw_flow_actions *sf_acts;
663efa369   Jesse Gross   openvswitch: Sile...
755
  		sf_acts = rcu_dereference_ovsl(flow->sf_acts);
e64457191   Pravin B Shelar   openvswitch: Rest...
756
757
  		err = ovs_nla_put_actions(sf_acts->actions,
  					  sf_acts->actions_len, skb);
0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
758

74f84a572   Pravin B Shelar   openvswitch: Copy...
759
760
761
762
  		if (!err)
  			nla_nest_end(skb, start);
  		else {
  			if (skb_orig_len)
ca7105f27   Joe Stringer   openvswitch: Refa...
763
  				return err;
74f84a572   Pravin B Shelar   openvswitch: Copy...
764
765
766
  
  			nla_nest_cancel(skb, start);
  		}
ca7105f27   Joe Stringer   openvswitch: Refa...
767
768
769
770
771
772
773
774
775
776
  	} else if (skb_orig_len) {
  		return -EMSGSIZE;
  	}
  
  	return 0;
  }
  
  /* Called with ovs_mutex or RCU read lock. */
  static int ovs_flow_cmd_fill_info(const struct sw_flow *flow, int dp_ifindex,
  				  struct sk_buff *skb, u32 portid,
74ed7ab92   Joe Stringer   openvswitch: Add ...
777
  				  u32 seq, u32 flags, u8 cmd, u32 ufid_flags)
ca7105f27   Joe Stringer   openvswitch: Refa...
778
779
780
781
782
783
784
785
786
787
788
  {
  	const int skb_orig_len = skb->len;
  	struct ovs_header *ovs_header;
  	int err;
  
  	ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family,
  				 flags, cmd);
  	if (!ovs_header)
  		return -EMSGSIZE;
  
  	ovs_header->dp_ifindex = dp_ifindex;
74ed7ab92   Joe Stringer   openvswitch: Add ...
789
  	err = ovs_nla_put_identifier(flow, skb);
5b4237bbc   Joe Stringer   openvswitch: Refa...
790
791
  	if (err)
  		goto error;
74ed7ab92   Joe Stringer   openvswitch: Add ...
792
793
794
795
796
797
798
799
800
801
802
  	if (should_fill_key(&flow->id, ufid_flags)) {
  		err = ovs_nla_put_masked_key(flow, skb);
  		if (err)
  			goto error;
  	}
  
  	if (should_fill_mask(ufid_flags)) {
  		err = ovs_nla_put_mask(flow, skb);
  		if (err)
  			goto error;
  	}
ca7105f27   Joe Stringer   openvswitch: Refa...
803
804
805
806
  
  	err = ovs_flow_cmd_fill_stats(flow, skb);
  	if (err)
  		goto error;
74ed7ab92   Joe Stringer   openvswitch: Add ...
807
808
809
810
811
  	if (should_fill_actions(ufid_flags)) {
  		err = ovs_flow_cmd_fill_actions(flow, skb, skb_orig_len);
  		if (err)
  			goto error;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
812

053c095a8   Johannes Berg   netlink: make nlm...
813
814
  	genlmsg_end(skb, ovs_header);
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
815

ccb1352e7   Jesse Gross   net: Add Open vSw...
816
817
818
819
  error:
  	genlmsg_cancel(skb, ovs_header);
  	return err;
  }
0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
820
821
  /* May not be called with RCU read lock. */
  static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *acts,
74ed7ab92   Joe Stringer   openvswitch: Add ...
822
  					       const struct sw_flow_id *sfid,
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
823
  					       struct genl_info *info,
74ed7ab92   Joe Stringer   openvswitch: Add ...
824
825
  					       bool always,
  					       uint32_t ufid_flags)
ccb1352e7   Jesse Gross   net: Add Open vSw...
826
  {
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
827
  	struct sk_buff *skb;
74ed7ab92   Joe Stringer   openvswitch: Add ...
828
  	size_t len;
ccb1352e7   Jesse Gross   net: Add Open vSw...
829

9b67aa4a8   Samuel Gauthier   openvswitch: rest...
830
  	if (!always && !ovs_must_notify(&dp_flow_genl_family, info, 0))
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
831
  		return NULL;
74ed7ab92   Joe Stringer   openvswitch: Add ...
832
  	len = ovs_flow_cmd_msg_size(acts, sfid, ufid_flags);
551ddc057   Florian Westphal   openvswitch: Reve...
833
  	skb = genlmsg_new(len, GFP_KERNEL);
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
834
835
836
837
  	if (!skb)
  		return ERR_PTR(-ENOMEM);
  
  	return skb;
ccb1352e7   Jesse Gross   net: Add Open vSw...
838
  }
0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
839
840
841
842
  /* Called with ovs_mutex. */
  static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow,
  					       int dp_ifindex,
  					       struct genl_info *info, u8 cmd,
74ed7ab92   Joe Stringer   openvswitch: Add ...
843
  					       bool always, u32 ufid_flags)
ccb1352e7   Jesse Gross   net: Add Open vSw...
844
845
846
  {
  	struct sk_buff *skb;
  	int retval;
74ed7ab92   Joe Stringer   openvswitch: Add ...
847
848
  	skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts),
  				      &flow->id, info, always, ufid_flags);
d0e992aa0   Himangi Saraogi   openvswitch: Use ...
849
  	if (IS_ERR_OR_NULL(skb))
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
850
  		return skb;
ccb1352e7   Jesse Gross   net: Add Open vSw...
851

0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
852
853
  	retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb,
  					info->snd_portid, info->snd_seq, 0,
74ed7ab92   Joe Stringer   openvswitch: Add ...
854
  					cmd, ufid_flags);
ccb1352e7   Jesse Gross   net: Add Open vSw...
855
856
857
  	BUG_ON(retval < 0);
  	return skb;
  }
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
858
  static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
ccb1352e7   Jesse Gross   net: Add Open vSw...
859
  {
7f8a436ea   Joe Stringer   openvswitch: Add ...
860
  	struct net *net = sock_net(skb->sk);
ccb1352e7   Jesse Gross   net: Add Open vSw...
861
862
  	struct nlattr **a = info->attrs;
  	struct ovs_header *ovs_header = info->userhdr;
74ed7ab92   Joe Stringer   openvswitch: Add ...
863
  	struct sw_flow *flow = NULL, *new_flow;
03f0d916a   Andy Zhou   openvswitch: Mega...
864
  	struct sw_flow_mask mask;
ccb1352e7   Jesse Gross   net: Add Open vSw...
865
866
  	struct sk_buff *reply;
  	struct datapath *dp;
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
867
  	struct sw_flow_actions *acts;
03f0d916a   Andy Zhou   openvswitch: Mega...
868
  	struct sw_flow_match match;
74ed7ab92   Joe Stringer   openvswitch: Add ...
869
  	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
870
  	int error;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
871
  	bool log = !a[OVS_FLOW_ATTR_PROBE];
ccb1352e7   Jesse Gross   net: Add Open vSw...
872

893f139b9   Jarno Rajahalme   openvswitch: Mini...
873
  	/* Must have key and actions. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
874
  	error = -EINVAL;
426cda5cc   Jesse Gross   openvswitch: Addi...
875
  	if (!a[OVS_FLOW_ATTR_KEY]) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
876
  		OVS_NLERR(log, "Flow key attr not present in new flow.");
ccb1352e7   Jesse Gross   net: Add Open vSw...
877
  		goto error;
426cda5cc   Jesse Gross   openvswitch: Addi...
878
879
  	}
  	if (!a[OVS_FLOW_ATTR_ACTIONS]) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
880
  		OVS_NLERR(log, "Flow actions attr not present in new flow.");
893f139b9   Jarno Rajahalme   openvswitch: Mini...
881
  		goto error;
426cda5cc   Jesse Gross   openvswitch: Addi...
882
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
883

893f139b9   Jarno Rajahalme   openvswitch: Mini...
884
885
886
887
888
889
890
891
892
893
  	/* Most of the time we need to allocate a new flow, do it before
  	 * locking.
  	 */
  	new_flow = ovs_flow_alloc();
  	if (IS_ERR(new_flow)) {
  		error = PTR_ERR(new_flow);
  		goto error;
  	}
  
  	/* Extract key. */
2279994d0   pravin shelar   openvswitch: avoi...
894
  	ovs_match_init(&match, &new_flow->key, false, &mask);
c2ac66735   Joe Stringer   openvswitch: Allo...
895
  	error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
05da5898a   Jarno Rajahalme   openvswitch: Add ...
896
  				  a[OVS_FLOW_ATTR_MASK], log);
ccb1352e7   Jesse Gross   net: Add Open vSw...
897
  	if (error)
893f139b9   Jarno Rajahalme   openvswitch: Mini...
898
  		goto err_kfree_flow;
ccb1352e7   Jesse Gross   net: Add Open vSw...
899

74ed7ab92   Joe Stringer   openvswitch: Add ...
900
901
  	/* Extract flow identifier. */
  	error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
190aa3e77   pravin shelar   openvswitch: Fix ...
902
  				       &new_flow->key, log);
74ed7ab92   Joe Stringer   openvswitch: Add ...
903
904
  	if (error)
  		goto err_kfree_flow;
74f84a572   Pravin B Shelar   openvswitch: Copy...
905

190aa3e77   pravin shelar   openvswitch: Fix ...
906
907
908
909
910
  	/* unmasked key is needed to match when ufid is not used. */
  	if (ovs_identifier_is_key(&new_flow->id))
  		match.key = new_flow->id.unmasked_key;
  
  	ovs_flow_mask_key(&new_flow->key, &new_flow->key, true, &mask);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
911
  	/* Validate actions. */
7f8a436ea   Joe Stringer   openvswitch: Add ...
912
913
  	error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
  				     &new_flow->key, &acts, log);
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
914
  	if (error) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
915
  		OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
2fdb957d6   Pravin B Shelar   openvswitch: Refa...
916
  		goto err_kfree_flow;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
917
  	}
74ed7ab92   Joe Stringer   openvswitch: Add ...
918
919
  	reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
  					ufid_flags);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
920
921
922
  	if (IS_ERR(reply)) {
  		error = PTR_ERR(reply);
  		goto err_kfree_acts;
ccb1352e7   Jesse Gross   net: Add Open vSw...
923
  	}
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
924
  	ovs_lock();
7f8a436ea   Joe Stringer   openvswitch: Add ...
925
  	dp = get_dp(net, ovs_header->dp_ifindex);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
926
927
  	if (unlikely(!dp)) {
  		error = -ENODEV;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
928
  		goto err_unlock_ovs;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
929
  	}
74ed7ab92   Joe Stringer   openvswitch: Add ...
930

03f0d916a   Andy Zhou   openvswitch: Mega...
931
  	/* Check if this is a duplicate flow */
74ed7ab92   Joe Stringer   openvswitch: Add ...
932
933
934
  	if (ovs_identifier_is_ufid(&new_flow->id))
  		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);
  	if (!flow)
190aa3e77   pravin shelar   openvswitch: Fix ...
935
  		flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->key);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
936
937
  	if (likely(!flow)) {
  		rcu_assign_pointer(new_flow->sf_acts, acts);
ccb1352e7   Jesse Gross   net: Add Open vSw...
938
939
  
  		/* Put flow in bucket. */
893f139b9   Jarno Rajahalme   openvswitch: Mini...
940
941
  		error = ovs_flow_tbl_insert(&dp->table, new_flow, &mask);
  		if (unlikely(error)) {
618ed0c80   Pravin B Shelar   openvswitch: Simp...
942
  			acts = NULL;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
943
944
945
946
947
948
949
950
  			goto err_unlock_ovs;
  		}
  
  		if (unlikely(reply)) {
  			error = ovs_flow_cmd_fill_info(new_flow,
  						       ovs_header->dp_ifindex,
  						       reply, info->snd_portid,
  						       info->snd_seq, 0,
74ed7ab92   Joe Stringer   openvswitch: Add ...
951
952
  						       OVS_FLOW_CMD_NEW,
  						       ufid_flags);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
953
  			BUG_ON(error < 0);
618ed0c80   Pravin B Shelar   openvswitch: Simp...
954
  		}
893f139b9   Jarno Rajahalme   openvswitch: Mini...
955
  		ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
956
  	} else {
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
957
  		struct sw_flow_actions *old_acts;
ccb1352e7   Jesse Gross   net: Add Open vSw...
958
959
960
961
962
963
  		/* Bail out if we're not allowed to modify an existing flow.
  		 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
  		 * because Generic Netlink treats the latter as a dump
  		 * request.  We also accept NLM_F_EXCL in case that bug ever
  		 * gets fixed.
  		 */
893f139b9   Jarno Rajahalme   openvswitch: Mini...
964
965
966
  		if (unlikely(info->nlhdr->nlmsg_flags & (NLM_F_CREATE
  							 | NLM_F_EXCL))) {
  			error = -EEXIST;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
967
  			goto err_unlock_ovs;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
968
  		}
74ed7ab92   Joe Stringer   openvswitch: Add ...
969
970
971
972
973
974
975
976
977
  		/* The flow identifier has to be the same for flow updates.
  		 * Look for any overlapping flow.
  		 */
  		if (unlikely(!ovs_flow_cmp(flow, &match))) {
  			if (ovs_identifier_is_key(&flow->id))
  				flow = ovs_flow_tbl_lookup_exact(&dp->table,
  								 &match);
  			else /* UFID matches but key is different */
  				flow = NULL;
4a46b24e1   Alex Wang   openvswitch: Use ...
978
979
980
981
  			if (!flow) {
  				error = -ENOENT;
  				goto err_unlock_ovs;
  			}
893f139b9   Jarno Rajahalme   openvswitch: Mini...
982
  		}
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
983
984
985
  		/* Update actions. */
  		old_acts = ovsl_dereference(flow->sf_acts);
  		rcu_assign_pointer(flow->sf_acts, acts);
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
986

893f139b9   Jarno Rajahalme   openvswitch: Mini...
987
988
989
990
991
  		if (unlikely(reply)) {
  			error = ovs_flow_cmd_fill_info(flow,
  						       ovs_header->dp_ifindex,
  						       reply, info->snd_portid,
  						       info->snd_seq, 0,
74ed7ab92   Joe Stringer   openvswitch: Add ...
992
993
  						       OVS_FLOW_CMD_NEW,
  						       ufid_flags);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
994
995
996
  			BUG_ON(error < 0);
  		}
  		ovs_unlock();
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
997

34ae932a4   Thomas Graf   openvswitch: Make...
998
  		ovs_nla_free_flow_actions_rcu(old_acts);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
999
  		ovs_flow_free(new_flow, false);
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1000
  	}
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1001
1002
1003
  
  	if (reply)
  		ovs_notify(&dp_flow_genl_family, reply, info);
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1004
  	return 0;
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1005
1006
  err_unlock_ovs:
  	ovs_unlock();
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1007
1008
  	kfree_skb(reply);
  err_kfree_acts:
34ae932a4   Thomas Graf   openvswitch: Make...
1009
  	ovs_nla_free_flow_actions(acts);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1010
1011
  err_kfree_flow:
  	ovs_flow_free(new_flow, false);
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1012
1013
1014
  error:
  	return error;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
1015

2fdb957d6   Pravin B Shelar   openvswitch: Refa...
1016
  /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */
7f8a436ea   Joe Stringer   openvswitch: Add ...
1017
1018
  static struct sw_flow_actions *get_flow_actions(struct net *net,
  						const struct nlattr *a,
6b205b2ca   Jesse Gross   openvswitch: Fact...
1019
  						const struct sw_flow_key *key,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1020
1021
  						const struct sw_flow_mask *mask,
  						bool log)
6b205b2ca   Jesse Gross   openvswitch: Fact...
1022
1023
1024
1025
  {
  	struct sw_flow_actions *acts;
  	struct sw_flow_key masked_key;
  	int error;
ae5f2fb1d   Jesse Gross   openvswitch: Zero...
1026
  	ovs_flow_mask_key(&masked_key, key, true, mask);
7f8a436ea   Joe Stringer   openvswitch: Add ...
1027
  	error = ovs_nla_copy_actions(net, a, &masked_key, &acts, log);
6b205b2ca   Jesse Gross   openvswitch: Fact...
1028
  	if (error) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1029
1030
  		OVS_NLERR(log,
  			  "Actions may not be safe on all matching packets");
6b205b2ca   Jesse Gross   openvswitch: Fact...
1031
1032
1033
1034
1035
  		return ERR_PTR(error);
  	}
  
  	return acts;
  }
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1036
1037
  static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
  {
7f8a436ea   Joe Stringer   openvswitch: Add ...
1038
  	struct net *net = sock_net(skb->sk);
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1039
1040
  	struct nlattr **a = info->attrs;
  	struct ovs_header *ovs_header = info->userhdr;
6b205b2ca   Jesse Gross   openvswitch: Fact...
1041
  	struct sw_flow_key key;
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1042
1043
1044
1045
  	struct sw_flow *flow;
  	struct sw_flow_mask mask;
  	struct sk_buff *reply = NULL;
  	struct datapath *dp;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1046
  	struct sw_flow_actions *old_acts = NULL, *acts = NULL;
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1047
  	struct sw_flow_match match;
74ed7ab92   Joe Stringer   openvswitch: Add ...
1048
1049
  	struct sw_flow_id sfid;
  	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
6f15cdbf8   Samuel Gauthier   ovs: allow nl 'fl...
1050
  	int error = 0;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1051
  	bool log = !a[OVS_FLOW_ATTR_PROBE];
74ed7ab92   Joe Stringer   openvswitch: Add ...
1052
  	bool ufid_present;
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1053

74ed7ab92   Joe Stringer   openvswitch: Add ...
1054
  	ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log);
6f15cdbf8   Samuel Gauthier   ovs: allow nl 'fl...
1055
  	if (a[OVS_FLOW_ATTR_KEY]) {
2279994d0   pravin shelar   openvswitch: avoi...
1056
  		ovs_match_init(&match, &key, true, &mask);
6f15cdbf8   Samuel Gauthier   ovs: allow nl 'fl...
1057
1058
1059
1060
1061
1062
1063
  		error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
  					  a[OVS_FLOW_ATTR_MASK], log);
  	} else if (!ufid_present) {
  		OVS_NLERR(log,
  			  "Flow set message rejected, Key attribute missing.");
  		error = -EINVAL;
  	}
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1064
1065
1066
1067
1068
  	if (error)
  		goto error;
  
  	/* Validate actions. */
  	if (a[OVS_FLOW_ATTR_ACTIONS]) {
6f15cdbf8   Samuel Gauthier   ovs: allow nl 'fl...
1069
1070
1071
1072
1073
1074
  		if (!a[OVS_FLOW_ATTR_KEY]) {
  			OVS_NLERR(log,
  				  "Flow key attribute not present in set flow.");
  			error = -EINVAL;
  			goto error;
  		}
7f8a436ea   Joe Stringer   openvswitch: Add ...
1075
1076
  		acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], &key,
  					&mask, log);
6b205b2ca   Jesse Gross   openvswitch: Fact...
1077
1078
  		if (IS_ERR(acts)) {
  			error = PTR_ERR(acts);
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1079
  			goto error;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1080
  		}
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1081

2fdb957d6   Pravin B Shelar   openvswitch: Refa...
1082
  		/* Can allocate before locking if have acts. */
74ed7ab92   Joe Stringer   openvswitch: Add ...
1083
1084
  		reply = ovs_flow_cmd_alloc_info(acts, &sfid, info, false,
  						ufid_flags);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1085
1086
1087
  		if (IS_ERR(reply)) {
  			error = PTR_ERR(reply);
  			goto err_kfree_acts;
be52c9e96   Jarno Rajahalme   openvswitch: Avoi...
1088
  		}
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1089
  	}
0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
1090

37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1091
  	ovs_lock();
7f8a436ea   Joe Stringer   openvswitch: Add ...
1092
  	dp = get_dp(net, ovs_header->dp_ifindex);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1093
1094
  	if (unlikely(!dp)) {
  		error = -ENODEV;
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1095
  		goto err_unlock_ovs;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1096
  	}
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1097
  	/* Check that the flow exists. */
74ed7ab92   Joe Stringer   openvswitch: Add ...
1098
1099
1100
1101
  	if (ufid_present)
  		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &sfid);
  	else
  		flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1102
1103
  	if (unlikely(!flow)) {
  		error = -ENOENT;
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1104
  		goto err_unlock_ovs;
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1105
  	}
4a46b24e1   Alex Wang   openvswitch: Use ...
1106

37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1107
  	/* Update actions, if present. */
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1108
  	if (likely(acts)) {
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1109
1110
  		old_acts = ovsl_dereference(flow->sf_acts);
  		rcu_assign_pointer(flow->sf_acts, acts);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1111
1112
1113
1114
1115
1116
  
  		if (unlikely(reply)) {
  			error = ovs_flow_cmd_fill_info(flow,
  						       ovs_header->dp_ifindex,
  						       reply, info->snd_portid,
  						       info->snd_seq, 0,
74ed7ab92   Joe Stringer   openvswitch: Add ...
1117
1118
  						       OVS_FLOW_CMD_NEW,
  						       ufid_flags);
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1119
1120
1121
1122
1123
  			BUG_ON(error < 0);
  		}
  	} else {
  		/* Could not alloc without acts before locking. */
  		reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
74ed7ab92   Joe Stringer   openvswitch: Add ...
1124
1125
  						info, OVS_FLOW_CMD_NEW, false,
  						ufid_flags);
b5ffe6344   Viresh Kumar   net: Drop unlikel...
1126
  		if (IS_ERR(reply)) {
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1127
1128
1129
  			error = PTR_ERR(reply);
  			goto err_unlock_ovs;
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1130
  	}
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1131

37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1132
1133
1134
  	/* Clear stats. */
  	if (a[OVS_FLOW_ATTR_CLEAR])
  		ovs_flow_stats_clear(flow);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1135
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1136

893f139b9   Jarno Rajahalme   openvswitch: Mini...
1137
1138
1139
  	if (reply)
  		ovs_notify(&dp_flow_genl_family, reply, info);
  	if (old_acts)
34ae932a4   Thomas Graf   openvswitch: Make...
1140
  		ovs_nla_free_flow_actions_rcu(old_acts);
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
1141

ccb1352e7   Jesse Gross   net: Add Open vSw...
1142
  	return 0;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1143
1144
  err_unlock_ovs:
  	ovs_unlock();
893f139b9   Jarno Rajahalme   openvswitch: Mini...
1145
1146
  	kfree_skb(reply);
  err_kfree_acts:
34ae932a4   Thomas Graf   openvswitch: Make...
1147
  	ovs_nla_free_flow_actions(acts);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1148
1149
1150
1151
1152
1153
1154
1155
  error:
  	return error;
  }
  
  static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
  {
  	struct nlattr **a = info->attrs;
  	struct ovs_header *ovs_header = info->userhdr;
c2ac66735   Joe Stringer   openvswitch: Allo...
1156
  	struct net *net = sock_net(skb->sk);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1157
1158
1159
1160
  	struct sw_flow_key key;
  	struct sk_buff *reply;
  	struct sw_flow *flow;
  	struct datapath *dp;
03f0d916a   Andy Zhou   openvswitch: Mega...
1161
  	struct sw_flow_match match;
74ed7ab92   Joe Stringer   openvswitch: Add ...
1162
1163
1164
  	struct sw_flow_id ufid;
  	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
  	int err = 0;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1165
  	bool log = !a[OVS_FLOW_ATTR_PROBE];
74ed7ab92   Joe Stringer   openvswitch: Add ...
1166
  	bool ufid_present;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1167

74ed7ab92   Joe Stringer   openvswitch: Add ...
1168
1169
  	ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
  	if (a[OVS_FLOW_ATTR_KEY]) {
2279994d0   pravin shelar   openvswitch: avoi...
1170
  		ovs_match_init(&match, &key, true, NULL);
c2ac66735   Joe Stringer   openvswitch: Allo...
1171
  		err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], NULL,
74ed7ab92   Joe Stringer   openvswitch: Add ...
1172
1173
  					log);
  	} else if (!ufid_present) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1174
1175
  		OVS_NLERR(log,
  			  "Flow get message rejected, Key attribute missing.");
74ed7ab92   Joe Stringer   openvswitch: Add ...
1176
  		err = -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1177
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1178
1179
  	if (err)
  		return err;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1180
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
1181
  	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1182
1183
1184
1185
  	if (!dp) {
  		err = -ENODEV;
  		goto unlock;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1186

74ed7ab92   Joe Stringer   openvswitch: Add ...
1187
1188
1189
1190
  	if (ufid_present)
  		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &ufid);
  	else
  		flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
4a46b24e1   Alex Wang   openvswitch: Use ...
1191
  	if (!flow) {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1192
1193
1194
  		err = -ENOENT;
  		goto unlock;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1195

0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
1196
  	reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, info,
74ed7ab92   Joe Stringer   openvswitch: Add ...
1197
  					OVS_FLOW_CMD_NEW, true, ufid_flags);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1198
1199
1200
1201
  	if (IS_ERR(reply)) {
  		err = PTR_ERR(reply);
  		goto unlock;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1202

8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1203
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1204
  	return genlmsg_reply(reply, info);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1205
1206
1207
  unlock:
  	ovs_unlock();
  	return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1208
1209
1210
1211
1212
1213
  }
  
  static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
  {
  	struct nlattr **a = info->attrs;
  	struct ovs_header *ovs_header = info->userhdr;
c2ac66735   Joe Stringer   openvswitch: Allo...
1214
  	struct net *net = sock_net(skb->sk);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1215
1216
  	struct sw_flow_key key;
  	struct sk_buff *reply;
74ed7ab92   Joe Stringer   openvswitch: Add ...
1217
  	struct sw_flow *flow = NULL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1218
  	struct datapath *dp;
03f0d916a   Andy Zhou   openvswitch: Mega...
1219
  	struct sw_flow_match match;
74ed7ab92   Joe Stringer   openvswitch: Add ...
1220
1221
  	struct sw_flow_id ufid;
  	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1222
  	int err;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1223
  	bool log = !a[OVS_FLOW_ATTR_PROBE];
74ed7ab92   Joe Stringer   openvswitch: Add ...
1224
  	bool ufid_present;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1225

74ed7ab92   Joe Stringer   openvswitch: Add ...
1226
1227
  	ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
  	if (a[OVS_FLOW_ATTR_KEY]) {
2279994d0   pravin shelar   openvswitch: avoi...
1228
  		ovs_match_init(&match, &key, true, NULL);
c2ac66735   Joe Stringer   openvswitch: Allo...
1229
1230
  		err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
  					NULL, log);
aed067783   Jarno Rajahalme   openvswitch: Mini...
1231
1232
1233
  		if (unlikely(err))
  			return err;
  	}
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1234
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
1235
  	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
aed067783   Jarno Rajahalme   openvswitch: Mini...
1236
  	if (unlikely(!dp)) {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1237
1238
1239
  		err = -ENODEV;
  		goto unlock;
  	}
46df7b814   Pravin B Shelar   openvswitch: Add ...
1240

74ed7ab92   Joe Stringer   openvswitch: Add ...
1241
  	if (unlikely(!a[OVS_FLOW_ATTR_KEY] && !ufid_present)) {
b637e4988   Pravin B Shelar   openvswitch: Move...
1242
  		err = ovs_flow_tbl_flush(&dp->table);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1243
1244
  		goto unlock;
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1245

74ed7ab92   Joe Stringer   openvswitch: Add ...
1246
1247
1248
1249
  	if (ufid_present)
  		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &ufid);
  	else
  		flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
4a46b24e1   Alex Wang   openvswitch: Use ...
1250
  	if (unlikely(!flow)) {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1251
1252
1253
  		err = -ENOENT;
  		goto unlock;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1254

b637e4988   Pravin B Shelar   openvswitch: Move...
1255
  	ovs_flow_tbl_remove(&dp->table, flow);
aed067783   Jarno Rajahalme   openvswitch: Mini...
1256
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1257

aed067783   Jarno Rajahalme   openvswitch: Mini...
1258
  	reply = ovs_flow_cmd_alloc_info((const struct sw_flow_actions __force *) flow->sf_acts,
74ed7ab92   Joe Stringer   openvswitch: Add ...
1259
  					&flow->id, info, false, ufid_flags);
aed067783   Jarno Rajahalme   openvswitch: Mini...
1260
1261
1262
1263
1264
1265
  	if (likely(reply)) {
  		if (likely(!IS_ERR(reply))) {
  			rcu_read_lock();	/*To keep RCU checker happy. */
  			err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
  						     reply, info->snd_portid,
  						     info->snd_seq, 0,
74ed7ab92   Joe Stringer   openvswitch: Add ...
1266
1267
  						     OVS_FLOW_CMD_DEL,
  						     ufid_flags);
aed067783   Jarno Rajahalme   openvswitch: Mini...
1268
1269
1270
1271
1272
1273
1274
  			rcu_read_unlock();
  			BUG_ON(err < 0);
  
  			ovs_notify(&dp_flow_genl_family, reply, info);
  		} else {
  			netlink_set_err(sock_net(skb->sk)->genl_sock, 0, 0, PTR_ERR(reply));
  		}
fb5d1e9e1   Jarno Rajahalme   openvswitch: Buil...
1275
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1276

aed067783   Jarno Rajahalme   openvswitch: Mini...
1277
  	ovs_flow_free(flow, true);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1278
  	return 0;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1279
1280
1281
  unlock:
  	ovs_unlock();
  	return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1282
1283
1284
1285
  }
  
  static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
74ed7ab92   Joe Stringer   openvswitch: Add ...
1286
  	struct nlattr *a[__OVS_FLOW_ATTR_MAX];
ccb1352e7   Jesse Gross   net: Add Open vSw...
1287
  	struct ovs_header *ovs_header = genlmsg_data(nlmsg_data(cb->nlh));
b637e4988   Pravin B Shelar   openvswitch: Move...
1288
  	struct table_instance *ti;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1289
  	struct datapath *dp;
74ed7ab92   Joe Stringer   openvswitch: Add ...
1290
1291
1292
1293
1294
1295
1296
1297
  	u32 ufid_flags;
  	int err;
  
  	err = genlmsg_parse(cb->nlh, &dp_flow_genl_family, a,
  			    OVS_FLOW_ATTR_MAX, flow_policy);
  	if (err)
  		return err;
  	ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1298

d57170b1b   Pravin B Shelar   openvswitch: Use ...
1299
  	rcu_read_lock();
cc3a5ae6f   Andy Zhou   openvswitch: Refa...
1300
  	dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1301
  	if (!dp) {
d57170b1b   Pravin B Shelar   openvswitch: Use ...
1302
  		rcu_read_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1303
  		return -ENODEV;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1304
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1305

b637e4988   Pravin B Shelar   openvswitch: Move...
1306
  	ti = rcu_dereference(dp->table.ti);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1307
1308
1309
1310
1311
1312
  	for (;;) {
  		struct sw_flow *flow;
  		u32 bucket, obj;
  
  		bucket = cb->args[0];
  		obj = cb->args[1];
b637e4988   Pravin B Shelar   openvswitch: Move...
1313
  		flow = ovs_flow_tbl_dump_next(ti, &bucket, &obj);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1314
1315
  		if (!flow)
  			break;
0e9796b4a   Jarno Rajahalme   openvswitch: Redu...
1316
  		if (ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex, skb,
15e473046   Eric W. Biederman   netlink: Rename p...
1317
  					   NETLINK_CB(cb->skb).portid,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1318
  					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
74ed7ab92   Joe Stringer   openvswitch: Add ...
1319
  					   OVS_FLOW_CMD_NEW, ufid_flags) < 0)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1320
1321
1322
1323
1324
  			break;
  
  		cb->args[0] = bucket;
  		cb->args[1] = obj;
  	}
d57170b1b   Pravin B Shelar   openvswitch: Use ...
1325
  	rcu_read_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1326
1327
  	return skb->len;
  }
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1328
1329
  static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
  	[OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1330
  	[OVS_FLOW_ATTR_MASK] = { .type = NLA_NESTED },
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1331
1332
  	[OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
  	[OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1333
  	[OVS_FLOW_ATTR_PROBE] = { .type = NLA_FLAG },
74ed7ab92   Joe Stringer   openvswitch: Add ...
1334
1335
  	[OVS_FLOW_ATTR_UFID] = { .type = NLA_UNSPEC, .len = 1 },
  	[OVS_FLOW_ATTR_UFID_FLAGS] = { .type = NLA_U32 },
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1336
  };
48e48a70c   stephen hemminger   openvswitch: make...
1337
  static const struct genl_ops dp_flow_genl_ops[] = {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1338
  	{ .cmd = OVS_FLOW_CMD_NEW,
4a92602aa   Tycho Andersen   openvswitch: allo...
1339
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1340
  	  .policy = flow_policy,
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1341
  	  .doit = ovs_flow_cmd_new
ccb1352e7   Jesse Gross   net: Add Open vSw...
1342
1343
  	},
  	{ .cmd = OVS_FLOW_CMD_DEL,
4a92602aa   Tycho Andersen   openvswitch: allo...
1344
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
  	  .policy = flow_policy,
  	  .doit = ovs_flow_cmd_del
  	},
  	{ .cmd = OVS_FLOW_CMD_GET,
  	  .flags = 0,		    /* OK for unprivileged users. */
  	  .policy = flow_policy,
  	  .doit = ovs_flow_cmd_get,
  	  .dumpit = ovs_flow_cmd_dump
  	},
  	{ .cmd = OVS_FLOW_CMD_SET,
4a92602aa   Tycho Andersen   openvswitch: allo...
1355
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1356
  	  .policy = flow_policy,
37bdc87ba   Jarno Rajahalme   openvswitch: Spli...
1357
  	  .doit = ovs_flow_cmd_set,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1358
1359
  	},
  };
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1360
  static struct genl_family dp_flow_genl_family = {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1361
1362
  	.id = GENL_ID_GENERATE,
  	.hdrsize = sizeof(struct ovs_header),
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1363
1364
1365
  	.name = OVS_FLOW_FAMILY,
  	.version = OVS_FLOW_VERSION,
  	.maxattr = OVS_FLOW_ATTR_MAX,
3a4e0d6a9   Pravin B Shelar   openvswitch: Use ...
1366
1367
  	.netnsok = true,
  	.parallel_ops = true,
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1368
1369
1370
1371
  	.ops = dp_flow_genl_ops,
  	.n_ops = ARRAY_SIZE(dp_flow_genl_ops),
  	.mcgrps = &ovs_dp_flow_multicast_group,
  	.n_mcgrps = 1,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1372
  };
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
1373
1374
1375
1376
1377
  static size_t ovs_dp_cmd_msg_size(void)
  {
  	size_t msgsize = NLMSG_ALIGN(sizeof(struct ovs_header));
  
  	msgsize += nla_total_size(IFNAMSIZ);
66c7a5ee1   Nicolas Dichtel   ovs: align nlattr...
1378
1379
  	msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_stats));
  	msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_megaflow_stats));
45fb9c35b   Daniele Di Proietto   openvswitch: Fix ...
1380
  	msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */
c3ff8cfe3   Thomas Graf   openvswitch: Refi...
1381
1382
1383
  
  	return msgsize;
  }
8ec609d8b   Pravin B Shelar   openvswitch: Conv...
1384
  /* Called with ovs_mutex. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1385
  static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
15e473046   Eric W. Biederman   netlink: Rename p...
1386
  				u32 portid, u32 seq, u32 flags, u8 cmd)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1387
1388
1389
  {
  	struct ovs_header *ovs_header;
  	struct ovs_dp_stats dp_stats;
1bd7116f1   Andy Zhou   openvswitch: coll...
1390
  	struct ovs_dp_megaflow_stats dp_megaflow_stats;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1391
  	int err;
15e473046   Eric W. Biederman   netlink: Rename p...
1392
  	ovs_header = genlmsg_put(skb, portid, seq, &dp_datapath_genl_family,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1393
1394
1395
1396
1397
  				   flags, cmd);
  	if (!ovs_header)
  		goto error;
  
  	ovs_header->dp_ifindex = get_dpifindex(dp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1398
  	err = nla_put_string(skb, OVS_DP_ATTR_NAME, ovs_dp_name(dp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1399
1400
  	if (err)
  		goto nla_put_failure;
1bd7116f1   Andy Zhou   openvswitch: coll...
1401
  	get_dp_stats(dp, &dp_stats, &dp_megaflow_stats);
66c7a5ee1   Nicolas Dichtel   ovs: align nlattr...
1402
1403
  	if (nla_put_64bit(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats),
  			  &dp_stats, OVS_DP_ATTR_PAD))
1bd7116f1   Andy Zhou   openvswitch: coll...
1404
  		goto nla_put_failure;
66c7a5ee1   Nicolas Dichtel   ovs: align nlattr...
1405
1406
1407
  	if (nla_put_64bit(skb, OVS_DP_ATTR_MEGAFLOW_STATS,
  			  sizeof(struct ovs_dp_megaflow_stats),
  			  &dp_megaflow_stats, OVS_DP_ATTR_PAD))
028d6a676   David S. Miller   openvswitch: Stop...
1408
  		goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1409

43d4be9cb   Thomas Graf   openvswitch: Allo...
1410
1411
  	if (nla_put_u32(skb, OVS_DP_ATTR_USER_FEATURES, dp->user_features))
  		goto nla_put_failure;
053c095a8   Johannes Berg   netlink: make nlm...
1412
1413
  	genlmsg_end(skb, ovs_header);
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1414
1415
1416
1417
1418
1419
  
  nla_put_failure:
  	genlmsg_cancel(skb, ovs_header);
  error:
  	return -EMSGSIZE;
  }
263ea0908   Florian Westphal   Revert "genl: Add...
1420
  static struct sk_buff *ovs_dp_cmd_alloc_info(void)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1421
  {
551ddc057   Florian Westphal   openvswitch: Reve...
1422
  	return genlmsg_new(ovs_dp_cmd_msg_size(), GFP_KERNEL);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1423
  }
bb6f9a708   Jarno Rajahalme   openvswitch: Clar...
1424
  /* Called with rcu_read_lock or ovs_mutex. */
46df7b814   Pravin B Shelar   openvswitch: Add ...
1425
  static struct datapath *lookup_datapath(struct net *net,
12eb18f71   Thomas Graf   openvswitch: Cons...
1426
  					const struct ovs_header *ovs_header,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1427
1428
1429
1430
1431
  					struct nlattr *a[OVS_DP_ATTR_MAX + 1])
  {
  	struct datapath *dp;
  
  	if (!a[OVS_DP_ATTR_NAME])
46df7b814   Pravin B Shelar   openvswitch: Add ...
1432
  		dp = get_dp(net, ovs_header->dp_ifindex);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1433
1434
  	else {
  		struct vport *vport;
46df7b814   Pravin B Shelar   openvswitch: Add ...
1435
  		vport = ovs_vport_locate(net, nla_data(a[OVS_DP_ATTR_NAME]));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1436
  		dp = vport && vport->port_no == OVSP_LOCAL ? vport->dp : NULL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1437
1438
1439
  	}
  	return dp ? dp : ERR_PTR(-ENODEV);
  }
44da5ae5f   Thomas Graf   openvswitch: Drop...
1440
1441
1442
1443
1444
  static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *info)
  {
  	struct datapath *dp;
  
  	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
3c7eacfc8   Jiri Pirko   ovs: fix dp check...
1445
  	if (IS_ERR(dp))
44da5ae5f   Thomas Graf   openvswitch: Drop...
1446
1447
1448
1449
1450
1451
  		return;
  
  	WARN(dp->user_features, "Dropping previously announced user features
  ");
  	dp->user_features = 0;
  }
12eb18f71   Thomas Graf   openvswitch: Cons...
1452
  static void ovs_dp_change(struct datapath *dp, struct nlattr *a[])
43d4be9cb   Thomas Graf   openvswitch: Allo...
1453
1454
1455
1456
  {
  	if (a[OVS_DP_ATTR_USER_FEATURES])
  		dp->user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]);
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
1457
1458
1459
1460
1461
1462
1463
  static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
  {
  	struct nlattr **a = info->attrs;
  	struct vport_parms parms;
  	struct sk_buff *reply;
  	struct datapath *dp;
  	struct vport *vport;
46df7b814   Pravin B Shelar   openvswitch: Add ...
1464
  	struct ovs_net *ovs_net;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1465
  	int err, i;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1466
1467
1468
1469
  
  	err = -EINVAL;
  	if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID])
  		goto err;
263ea0908   Florian Westphal   Revert "genl: Add...
1470
  	reply = ovs_dp_cmd_alloc_info();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1471
1472
  	if (!reply)
  		return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1473
1474
1475
1476
  
  	err = -ENOMEM;
  	dp = kzalloc(sizeof(*dp), GFP_KERNEL);
  	if (dp == NULL)
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1477
  		goto err_free_reply;
46df7b814   Pravin B Shelar   openvswitch: Add ...
1478

efd7ef1c1   Eric W. Biederman   net: Kill hold_ne...
1479
  	ovs_dp_set_net(dp, sock_net(skb->sk));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1480
1481
  
  	/* Allocate table. */
b637e4988   Pravin B Shelar   openvswitch: Move...
1482
1483
  	err = ovs_flow_tbl_init(&dp->table);
  	if (err)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1484
  		goto err_free_dp;
1c213bd24   WANG Cong   net: introduce ne...
1485
  	dp->stats_percpu = netdev_alloc_pcpu_stats(struct dp_stats_percpu);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1486
1487
1488
1489
  	if (!dp->stats_percpu) {
  		err = -ENOMEM;
  		goto err_destroy_table;
  	}
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1490
  	dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
e64457191   Pravin B Shelar   openvswitch: Rest...
1491
  			    GFP_KERNEL);
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1492
1493
1494
1495
1496
1497
1498
  	if (!dp->ports) {
  		err = -ENOMEM;
  		goto err_destroy_percpu;
  	}
  
  	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
  		INIT_HLIST_HEAD(&dp->ports[i]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1499
1500
1501
1502
1503
1504
  	/* Set up our datapath device. */
  	parms.name = nla_data(a[OVS_DP_ATTR_NAME]);
  	parms.type = OVS_VPORT_TYPE_INTERNAL;
  	parms.options = NULL;
  	parms.dp = dp;
  	parms.port_no = OVSP_LOCAL;
5cd667b0a   Alex Wang   openvswitch: Allo...
1505
  	parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
ccb1352e7   Jesse Gross   net: Add Open vSw...
1506

43d4be9cb   Thomas Graf   openvswitch: Allo...
1507
  	ovs_dp_change(dp, a);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1508
1509
  	/* So far only local changes have been made, now need the lock. */
  	ovs_lock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1510
1511
1512
1513
1514
  	vport = new_vport(&parms);
  	if (IS_ERR(vport)) {
  		err = PTR_ERR(vport);
  		if (err == -EBUSY)
  			err = -EEXIST;
44da5ae5f   Thomas Graf   openvswitch: Drop...
1515
1516
1517
1518
1519
1520
1521
1522
  		if (err == -EEXIST) {
  			/* An outdated user space instance that does not understand
  			 * the concept of user_features has attempted to create a new
  			 * datapath and is likely to reuse it. Drop all user features.
  			 */
  			if (info->genlhdr->version < OVS_DP_VER_FEATURES)
  				ovs_dp_reset_user_features(skb, info);
  		}
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1523
  		goto err_destroy_ports_array;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1524
  	}
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1525
1526
1527
  	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
  				   info->snd_seq, 0, OVS_DP_CMD_NEW);
  	BUG_ON(err < 0);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1528

46df7b814   Pravin B Shelar   openvswitch: Add ...
1529
  	ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
59a35d60a   Pravin B Shelar   openvswitch: Use ...
1530
  	list_add_tail_rcu(&dp->list_node, &ovs_net->dps);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1531
1532
  
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1533

2a94fe48f   Johannes Berg   genetlink: make m...
1534
  	ovs_notify(&dp_datapath_genl_family, reply, info);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1535
  	return 0;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1536
  err_destroy_ports_array:
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1537
  	ovs_unlock();
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1538
  	kfree(dp->ports);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1539
1540
1541
  err_destroy_percpu:
  	free_percpu(dp->stats_percpu);
  err_destroy_table:
9b996e544   Pravin B Shelar   openvswitch: Move...
1542
  	ovs_flow_tbl_destroy(&dp->table);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1543
1544
  err_free_dp:
  	kfree(dp);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1545
1546
  err_free_reply:
  	kfree_skb(reply);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1547
1548
1549
  err:
  	return err;
  }
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1550
  /* Called with ovs_mutex. */
46df7b814   Pravin B Shelar   openvswitch: Add ...
1551
  static void __dp_destroy(struct datapath *dp)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1552
  {
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1553
  	int i;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1554

15eac2a74   Pravin B Shelar   openvswitch: Incr...
1555
1556
  	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
  		struct vport *vport;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1557
  		struct hlist_node *n;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1558

b67bfe0d4   Sasha Levin   hlist: drop the n...
1559
  		hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node)
15eac2a74   Pravin B Shelar   openvswitch: Incr...
1560
1561
1562
  			if (vport->port_no != OVSP_LOCAL)
  				ovs_dp_detach_port(vport);
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1563

59a35d60a   Pravin B Shelar   openvswitch: Use ...
1564
  	list_del_rcu(&dp->list_node);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1565

8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1566
  	/* OVSP_LOCAL is datapath internal port. We need to make sure that
e80857cce   Andy Zhou   openvswitch: Fix ...
1567
  	 * all ports in datapath are destroyed first before freeing datapath.
ccb1352e7   Jesse Gross   net: Add Open vSw...
1568
  	 */
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1569
  	ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1570

e80857cce   Andy Zhou   openvswitch: Fix ...
1571
  	/* RCU destroy the flow table */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1572
  	call_rcu(&dp->rcu, destroy_dp_rcu);
46df7b814   Pravin B Shelar   openvswitch: Add ...
1573
1574
1575
1576
1577
1578
1579
  }
  
  static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
  {
  	struct sk_buff *reply;
  	struct datapath *dp;
  	int err;
263ea0908   Florian Westphal   Revert "genl: Add...
1580
  	reply = ovs_dp_cmd_alloc_info();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1581
1582
  	if (!reply)
  		return -ENOMEM;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1583
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
1584
1585
1586
  	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
  	err = PTR_ERR(dp);
  	if (IS_ERR(dp))
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1587
  		goto err_unlock_free;
46df7b814   Pravin B Shelar   openvswitch: Add ...
1588

6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1589
1590
1591
  	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
  				   info->snd_seq, 0, OVS_DP_CMD_DEL);
  	BUG_ON(err < 0);
46df7b814   Pravin B Shelar   openvswitch: Add ...
1592
1593
  
  	__dp_destroy(dp);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1594
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1595

2a94fe48f   Johannes Berg   genetlink: make m...
1596
  	ovs_notify(&dp_datapath_genl_family, reply, info);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1597
1598
  
  	return 0;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1599
1600
  
  err_unlock_free:
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1601
  	ovs_unlock();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1602
  	kfree_skb(reply);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1603
  	return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1604
1605
1606
1607
1608
1609
1610
  }
  
  static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
  {
  	struct sk_buff *reply;
  	struct datapath *dp;
  	int err;
263ea0908   Florian Westphal   Revert "genl: Add...
1611
  	reply = ovs_dp_cmd_alloc_info();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1612
1613
  	if (!reply)
  		return -ENOMEM;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1614
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
1615
  	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1616
  	err = PTR_ERR(dp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1617
  	if (IS_ERR(dp))
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1618
  		goto err_unlock_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1619

43d4be9cb   Thomas Graf   openvswitch: Allo...
1620
  	ovs_dp_change(dp, info->attrs);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1621
1622
1623
  	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
  				   info->snd_seq, 0, OVS_DP_CMD_NEW);
  	BUG_ON(err < 0);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1624

8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1625
  	ovs_unlock();
2a94fe48f   Johannes Berg   genetlink: make m...
1626
  	ovs_notify(&dp_datapath_genl_family, reply, info);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1627
1628
  
  	return 0;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1629
1630
  
  err_unlock_free:
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1631
  	ovs_unlock();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1632
  	kfree_skb(reply);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1633
  	return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1634
1635
1636
1637
1638
1639
  }
  
  static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
  {
  	struct sk_buff *reply;
  	struct datapath *dp;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1640
  	int err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1641

263ea0908   Florian Westphal   Revert "genl: Add...
1642
  	reply = ovs_dp_cmd_alloc_info();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1643
1644
  	if (!reply)
  		return -ENOMEM;
8ec609d8b   Pravin B Shelar   openvswitch: Conv...
1645
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
1646
  	dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1647
1648
  	if (IS_ERR(dp)) {
  		err = PTR_ERR(dp);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1649
  		goto err_unlock_free;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1650
  	}
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1651
1652
1653
  	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
  				   info->snd_seq, 0, OVS_DP_CMD_NEW);
  	BUG_ON(err < 0);
8ec609d8b   Pravin B Shelar   openvswitch: Conv...
1654
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1655
1656
  
  	return genlmsg_reply(reply, info);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1657

6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1658
  err_unlock_free:
8ec609d8b   Pravin B Shelar   openvswitch: Conv...
1659
  	ovs_unlock();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1660
  	kfree_skb(reply);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1661
  	return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1662
1663
1664
1665
  }
  
  static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
46df7b814   Pravin B Shelar   openvswitch: Add ...
1666
  	struct ovs_net *ovs_net = net_generic(sock_net(skb->sk), ovs_net_id);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1667
1668
1669
  	struct datapath *dp;
  	int skip = cb->args[0];
  	int i = 0;
8ec609d8b   Pravin B Shelar   openvswitch: Conv...
1670
1671
  	ovs_lock();
  	list_for_each_entry(dp, &ovs_net->dps, list_node) {
77676fdbd   Ben Pfaff   openvswitch: Fix ...
1672
  		if (i >= skip &&
15e473046   Eric W. Biederman   netlink: Rename p...
1673
  		    ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1674
1675
1676
1677
1678
  					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
  					 OVS_DP_CMD_NEW) < 0)
  			break;
  		i++;
  	}
8ec609d8b   Pravin B Shelar   openvswitch: Conv...
1679
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
1680
1681
1682
1683
1684
  
  	cb->args[0] = i;
  
  	return skb->len;
  }
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1685
1686
1687
1688
1689
  static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
  	[OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
  	[OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
  	[OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
  };
48e48a70c   stephen hemminger   openvswitch: make...
1690
  static const struct genl_ops dp_datapath_genl_ops[] = {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1691
  	{ .cmd = OVS_DP_CMD_NEW,
4a92602aa   Tycho Andersen   openvswitch: allo...
1692
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1693
1694
1695
1696
  	  .policy = datapath_policy,
  	  .doit = ovs_dp_cmd_new
  	},
  	{ .cmd = OVS_DP_CMD_DEL,
4a92602aa   Tycho Andersen   openvswitch: allo...
1697
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
  	  .policy = datapath_policy,
  	  .doit = ovs_dp_cmd_del
  	},
  	{ .cmd = OVS_DP_CMD_GET,
  	  .flags = 0,		    /* OK for unprivileged users. */
  	  .policy = datapath_policy,
  	  .doit = ovs_dp_cmd_get,
  	  .dumpit = ovs_dp_cmd_dump
  	},
  	{ .cmd = OVS_DP_CMD_SET,
4a92602aa   Tycho Andersen   openvswitch: allo...
1708
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1709
1710
1711
1712
  	  .policy = datapath_policy,
  	  .doit = ovs_dp_cmd_set,
  	},
  };
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1713
  static struct genl_family dp_datapath_genl_family = {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1714
1715
  	.id = GENL_ID_GENERATE,
  	.hdrsize = sizeof(struct ovs_header),
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1716
1717
1718
  	.name = OVS_DATAPATH_FAMILY,
  	.version = OVS_DATAPATH_VERSION,
  	.maxattr = OVS_DP_ATTR_MAX,
3a4e0d6a9   Pravin B Shelar   openvswitch: Use ...
1719
1720
  	.netnsok = true,
  	.parallel_ops = true,
0c200ef94   Pravin B Shelar   openvswitch: Simp...
1721
1722
1723
1724
  	.ops = dp_datapath_genl_ops,
  	.n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
  	.mcgrps = &ovs_dp_datapath_multicast_group,
  	.n_mcgrps = 1,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1725
  };
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1726
  /* Called with ovs_mutex or RCU read lock. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
1727
  static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
15e473046   Eric W. Biederman   netlink: Rename p...
1728
  				   u32 portid, u32 seq, u32 flags, u8 cmd)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1729
1730
1731
1732
  {
  	struct ovs_header *ovs_header;
  	struct ovs_vport_stats vport_stats;
  	int err;
15e473046   Eric W. Biederman   netlink: Rename p...
1733
  	ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1734
1735
1736
1737
1738
  				 flags, cmd);
  	if (!ovs_header)
  		return -EMSGSIZE;
  
  	ovs_header->dp_ifindex = get_dpifindex(vport->dp);
028d6a676   David S. Miller   openvswitch: Stop...
1739
1740
  	if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) ||
  	    nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) ||
5cd667b0a   Alex Wang   openvswitch: Allo...
1741
  	    nla_put_string(skb, OVS_VPORT_ATTR_NAME,
c9db965c5   Thomas Graf   openvswitch: Abst...
1742
  			   ovs_vport_name(vport)))
028d6a676   David S. Miller   openvswitch: Stop...
1743
  		goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1744
1745
  
  	ovs_vport_get_stats(vport, &vport_stats);
66c7a5ee1   Nicolas Dichtel   ovs: align nlattr...
1746
1747
1748
  	if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
  			  sizeof(struct ovs_vport_stats), &vport_stats,
  			  OVS_VPORT_ATTR_PAD))
028d6a676   David S. Miller   openvswitch: Stop...
1749
  		goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1750

5cd667b0a   Alex Wang   openvswitch: Allo...
1751
1752
  	if (ovs_vport_get_upcall_portids(vport, skb))
  		goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1753
1754
1755
  	err = ovs_vport_get_options(vport, skb);
  	if (err == -EMSGSIZE)
  		goto error;
053c095a8   Johannes Berg   netlink: make nlm...
1756
1757
  	genlmsg_end(skb, ovs_header);
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1758
1759
1760
1761
1762
1763
1764
  
  nla_put_failure:
  	err = -EMSGSIZE;
  error:
  	genlmsg_cancel(skb, ovs_header);
  	return err;
  }
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1765
1766
1767
1768
1769
1770
  static struct sk_buff *ovs_vport_cmd_alloc_info(void)
  {
  	return nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  }
  
  /* Called with ovs_mutex, only via ovs_dp_notify_wq(). */
15e473046   Eric W. Biederman   netlink: Rename p...
1771
  struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1772
1773
1774
1775
1776
1777
1778
1779
  					 u32 seq, u8 cmd)
  {
  	struct sk_buff *skb;
  	int retval;
  
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  	if (!skb)
  		return ERR_PTR(-ENOMEM);
15e473046   Eric W. Biederman   netlink: Rename p...
1780
  	retval = ovs_vport_cmd_fill_info(vport, skb, portid, seq, 0, cmd);
a9341512c   Jesse Gross   openvswitch: Prea...
1781
  	BUG_ON(retval < 0);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1782
1783
  	return skb;
  }
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1784
  /* Called with ovs_mutex or RCU read lock. */
46df7b814   Pravin B Shelar   openvswitch: Add ...
1785
  static struct vport *lookup_vport(struct net *net,
12eb18f71   Thomas Graf   openvswitch: Cons...
1786
  				  const struct ovs_header *ovs_header,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1787
1788
1789
1790
1791
1792
  				  struct nlattr *a[OVS_VPORT_ATTR_MAX + 1])
  {
  	struct datapath *dp;
  	struct vport *vport;
  
  	if (a[OVS_VPORT_ATTR_NAME]) {
46df7b814   Pravin B Shelar   openvswitch: Add ...
1793
  		vport = ovs_vport_locate(net, nla_data(a[OVS_VPORT_ATTR_NAME]));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1794
1795
  		if (!vport)
  			return ERR_PTR(-ENODEV);
651a68ea2   Ben Pfaff   openvswitch: Hono...
1796
1797
1798
  		if (ovs_header->dp_ifindex &&
  		    ovs_header->dp_ifindex != get_dpifindex(vport->dp))
  			return ERR_PTR(-ENODEV);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1799
1800
1801
1802
1803
1804
  		return vport;
  	} else if (a[OVS_VPORT_ATTR_PORT_NO]) {
  		u32 port_no = nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]);
  
  		if (port_no >= DP_MAX_PORTS)
  			return ERR_PTR(-EFBIG);
46df7b814   Pravin B Shelar   openvswitch: Add ...
1805
  		dp = get_dp(net, ovs_header->dp_ifindex);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1806
1807
  		if (!dp)
  			return ERR_PTR(-ENODEV);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1808
  		vport = ovs_vport_ovsl_rcu(dp, port_no);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1809
  		if (!vport)
14408dba8   Jarno Rajahalme   openvswitch: Chan...
1810
  			return ERR_PTR(-ENODEV);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1811
1812
1813
1814
  		return vport;
  	} else
  		return ERR_PTR(-EINVAL);
  }
3a927bc7c   Paolo Abeni   ovs: propagate pe...
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
  /* Called with ovs_mutex */
  static void update_headroom(struct datapath *dp)
  {
  	unsigned dev_headroom, max_headroom = 0;
  	struct net_device *dev;
  	struct vport *vport;
  	int i;
  
  	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
  		hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
  			dev = vport->dev;
  			dev_headroom = netdev_get_fwd_headroom(dev);
  			if (dev_headroom > max_headroom)
  				max_headroom = dev_headroom;
  		}
  	}
  
  	dp->max_headroom = max_headroom;
  	for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
  		hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node)
  			netdev_set_rx_headroom(vport->dev, max_headroom);
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
  static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
  {
  	struct nlattr **a = info->attrs;
  	struct ovs_header *ovs_header = info->userhdr;
  	struct vport_parms parms;
  	struct sk_buff *reply;
  	struct vport *vport;
  	struct datapath *dp;
  	u32 port_no;
  	int err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1847
1848
  	if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] ||
  	    !a[OVS_VPORT_ATTR_UPCALL_PID])
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
  		return -EINVAL;
  
  	port_no = a[OVS_VPORT_ATTR_PORT_NO]
  		? nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]) : 0;
  	if (port_no >= DP_MAX_PORTS)
  		return -EFBIG;
  
  	reply = ovs_vport_cmd_alloc_info();
  	if (!reply)
  		return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1859

8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1860
  	ovs_lock();
62b9c8d03   Thomas Graf   ovs: Turn vports ...
1861
  restart:
46df7b814   Pravin B Shelar   openvswitch: Add ...
1862
  	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1863
1864
  	err = -ENODEV;
  	if (!dp)
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1865
  		goto exit_unlock_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1866

6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1867
  	if (port_no) {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1868
  		vport = ovs_vport_ovsl(dp, port_no);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1869
1870
  		err = -EBUSY;
  		if (vport)
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1871
  			goto exit_unlock_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1872
1873
1874
1875
  	} else {
  		for (port_no = 1; ; port_no++) {
  			if (port_no >= DP_MAX_PORTS) {
  				err = -EFBIG;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1876
  				goto exit_unlock_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1877
  			}
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1878
  			vport = ovs_vport_ovsl(dp, port_no);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
  			if (!vport)
  				break;
  		}
  	}
  
  	parms.name = nla_data(a[OVS_VPORT_ATTR_NAME]);
  	parms.type = nla_get_u32(a[OVS_VPORT_ATTR_TYPE]);
  	parms.options = a[OVS_VPORT_ATTR_OPTIONS];
  	parms.dp = dp;
  	parms.port_no = port_no;
5cd667b0a   Alex Wang   openvswitch: Allo...
1889
  	parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
ccb1352e7   Jesse Gross   net: Add Open vSw...
1890
1891
1892
  
  	vport = new_vport(&parms);
  	err = PTR_ERR(vport);
62b9c8d03   Thomas Graf   ovs: Turn vports ...
1893
1894
1895
  	if (IS_ERR(vport)) {
  		if (err == -EAGAIN)
  			goto restart;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1896
  		goto exit_unlock_free;
62b9c8d03   Thomas Graf   ovs: Turn vports ...
1897
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1898

6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1899
1900
  	err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
  				      info->snd_seq, 0, OVS_VPORT_CMD_NEW);
3a927bc7c   Paolo Abeni   ovs: propagate pe...
1901
1902
1903
1904
1905
  
  	if (netdev_get_fwd_headroom(vport->dev) > dp->max_headroom)
  		update_headroom(dp);
  	else
  		netdev_set_rx_headroom(vport->dev, dp->max_headroom);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1906
1907
  	BUG_ON(err < 0);
  	ovs_unlock();
ed6611858   Thomas Graf   openvswitch: Move...
1908

2a94fe48f   Johannes Berg   genetlink: make m...
1909
  	ovs_notify(&dp_vport_genl_family, reply, info);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1910
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1911

6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1912
  exit_unlock_free:
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1913
  	ovs_unlock();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1914
  	kfree_skb(reply);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1915
1916
1917
1918
1919
1920
1921
1922
1923
  	return err;
  }
  
  static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
  {
  	struct nlattr **a = info->attrs;
  	struct sk_buff *reply;
  	struct vport *vport;
  	int err;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1924
1925
1926
  	reply = ovs_vport_cmd_alloc_info();
  	if (!reply)
  		return -ENOMEM;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1927
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
1928
  	vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1929
1930
  	err = PTR_ERR(vport);
  	if (IS_ERR(vport))
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1931
  		goto exit_unlock_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1932

ccb1352e7   Jesse Gross   net: Add Open vSw...
1933
  	if (a[OVS_VPORT_ATTR_TYPE] &&
f44f34088   Jesse Gross   openvswitch: Imme...
1934
  	    nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1935
  		err = -EINVAL;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1936
  		goto exit_unlock_free;
a9341512c   Jesse Gross   openvswitch: Prea...
1937
  	}
f44f34088   Jesse Gross   openvswitch: Imme...
1938
  	if (a[OVS_VPORT_ATTR_OPTIONS]) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1939
  		err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
f44f34088   Jesse Gross   openvswitch: Imme...
1940
  		if (err)
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1941
  			goto exit_unlock_free;
f44f34088   Jesse Gross   openvswitch: Imme...
1942
  	}
a9341512c   Jesse Gross   openvswitch: Prea...
1943

5cd667b0a   Alex Wang   openvswitch: Allo...
1944
1945
1946
1947
1948
1949
1950
1951
  
  	if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
  		struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID];
  
  		err = ovs_vport_set_upcall_portids(vport, ids);
  		if (err)
  			goto exit_unlock_free;
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1952

a9341512c   Jesse Gross   openvswitch: Prea...
1953
1954
1955
  	err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
  				      info->snd_seq, 0, OVS_VPORT_CMD_NEW);
  	BUG_ON(err < 0);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1956

8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1957
  	ovs_unlock();
2a94fe48f   Johannes Berg   genetlink: make m...
1958
  	ovs_notify(&dp_vport_genl_family, reply, info);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1959
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1960

6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1961
  exit_unlock_free:
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1962
  	ovs_unlock();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1963
  	kfree_skb(reply);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1964
1965
1966
1967
1968
  	return err;
  }
  
  static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
  {
3a927bc7c   Paolo Abeni   ovs: propagate pe...
1969
  	bool must_update_headroom = false;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1970
1971
  	struct nlattr **a = info->attrs;
  	struct sk_buff *reply;
3a927bc7c   Paolo Abeni   ovs: propagate pe...
1972
  	struct datapath *dp;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1973
1974
  	struct vport *vport;
  	int err;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1975
1976
1977
  	reply = ovs_vport_cmd_alloc_info();
  	if (!reply)
  		return -ENOMEM;
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
1978
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
1979
  	vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1980
1981
  	err = PTR_ERR(vport);
  	if (IS_ERR(vport))
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1982
  		goto exit_unlock_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1983
1984
1985
  
  	if (vport->port_no == OVSP_LOCAL) {
  		err = -EINVAL;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1986
  		goto exit_unlock_free;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1987
  	}
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
1988
1989
1990
  	err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
  				      info->snd_seq, 0, OVS_VPORT_CMD_DEL);
  	BUG_ON(err < 0);
3a927bc7c   Paolo Abeni   ovs: propagate pe...
1991
1992
1993
1994
1995
1996
  
  	/* the vport deletion may trigger dp headroom update */
  	dp = vport->dp;
  	if (netdev_get_fwd_headroom(vport->dev) == dp->max_headroom)
  		must_update_headroom = true;
  	netdev_reset_rx_headroom(vport->dev);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1997
  	ovs_dp_detach_port(vport);
3a927bc7c   Paolo Abeni   ovs: propagate pe...
1998
1999
2000
  
  	if (must_update_headroom)
  		update_headroom(dp);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2001
  	ovs_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2002

2a94fe48f   Johannes Berg   genetlink: make m...
2003
  	ovs_notify(&dp_vport_genl_family, reply, info);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2004
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2005

6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2006
  exit_unlock_free:
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
2007
  	ovs_unlock();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2008
  	kfree_skb(reply);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
  	return err;
  }
  
  static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
  {
  	struct nlattr **a = info->attrs;
  	struct ovs_header *ovs_header = info->userhdr;
  	struct sk_buff *reply;
  	struct vport *vport;
  	int err;
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2019
2020
2021
  	reply = ovs_vport_cmd_alloc_info();
  	if (!reply)
  		return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2022
  	rcu_read_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
2023
  	vport = lookup_vport(sock_net(skb->sk), ovs_header, a);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2024
2025
  	err = PTR_ERR(vport);
  	if (IS_ERR(vport))
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2026
2027
2028
2029
  		goto exit_unlock_free;
  	err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
  				      info->snd_seq, 0, OVS_VPORT_CMD_NEW);
  	BUG_ON(err < 0);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2030
2031
2032
  	rcu_read_unlock();
  
  	return genlmsg_reply(reply, info);
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2033
  exit_unlock_free:
ccb1352e7   Jesse Gross   net: Add Open vSw...
2034
  	rcu_read_unlock();
6093ae9ab   Jarno Rajahalme   openvswitch: Mini...
2035
  	kfree_skb(reply);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2036
2037
2038
2039
2040
2041
2042
  	return err;
  }
  
  static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	struct ovs_header *ovs_header = genlmsg_data(nlmsg_data(cb->nlh));
  	struct datapath *dp;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
2043
2044
  	int bucket = cb->args[0], skip = cb->args[1];
  	int i, j = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2045

42ee19e29   Jarno Rajahalme   openvswitch: Fix ...
2046
  	rcu_read_lock();
cc3a5ae6f   Andy Zhou   openvswitch: Refa...
2047
  	dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
42ee19e29   Jarno Rajahalme   openvswitch: Fix ...
2048
2049
  	if (!dp) {
  		rcu_read_unlock();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2050
  		return -ENODEV;
42ee19e29   Jarno Rajahalme   openvswitch: Fix ...
2051
  	}
15eac2a74   Pravin B Shelar   openvswitch: Incr...
2052
  	for (i = bucket; i < DP_VPORT_HASH_BUCKETS; i++) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
2053
  		struct vport *vport;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
2054
2055
  
  		j = 0;
b67bfe0d4   Sasha Levin   hlist: drop the n...
2056
  		hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
15eac2a74   Pravin B Shelar   openvswitch: Incr...
2057
2058
  			if (j >= skip &&
  			    ovs_vport_cmd_fill_info(vport, skb,
15e473046   Eric W. Biederman   netlink: Rename p...
2059
  						    NETLINK_CB(cb->skb).portid,
15eac2a74   Pravin B Shelar   openvswitch: Incr...
2060
2061
2062
2063
2064
2065
2066
2067
  						    cb->nlh->nlmsg_seq,
  						    NLM_F_MULTI,
  						    OVS_VPORT_CMD_NEW) < 0)
  				goto out;
  
  			j++;
  		}
  		skip = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2068
  	}
15eac2a74   Pravin B Shelar   openvswitch: Incr...
2069
  out:
ccb1352e7   Jesse Gross   net: Add Open vSw...
2070
  	rcu_read_unlock();
15eac2a74   Pravin B Shelar   openvswitch: Incr...
2071
2072
  	cb->args[0] = i;
  	cb->args[1] = j;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2073

15eac2a74   Pravin B Shelar   openvswitch: Incr...
2074
  	return skb->len;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2075
  }
0c200ef94   Pravin B Shelar   openvswitch: Simp...
2076
2077
2078
2079
2080
2081
2082
2083
  static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
  	[OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
  	[OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
  	[OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
  	[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
  	[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 },
  	[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
  };
48e48a70c   stephen hemminger   openvswitch: make...
2084
  static const struct genl_ops dp_vport_genl_ops[] = {
ccb1352e7   Jesse Gross   net: Add Open vSw...
2085
  	{ .cmd = OVS_VPORT_CMD_NEW,
4a92602aa   Tycho Andersen   openvswitch: allo...
2086
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
2087
2088
2089
2090
  	  .policy = vport_policy,
  	  .doit = ovs_vport_cmd_new
  	},
  	{ .cmd = OVS_VPORT_CMD_DEL,
4a92602aa   Tycho Andersen   openvswitch: allo...
2091
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
  	  .policy = vport_policy,
  	  .doit = ovs_vport_cmd_del
  	},
  	{ .cmd = OVS_VPORT_CMD_GET,
  	  .flags = 0,		    /* OK for unprivileged users. */
  	  .policy = vport_policy,
  	  .doit = ovs_vport_cmd_get,
  	  .dumpit = ovs_vport_cmd_dump
  	},
  	{ .cmd = OVS_VPORT_CMD_SET,
4a92602aa   Tycho Andersen   openvswitch: allo...
2102
  	  .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
2103
2104
2105
2106
  	  .policy = vport_policy,
  	  .doit = ovs_vport_cmd_set,
  	},
  };
0c200ef94   Pravin B Shelar   openvswitch: Simp...
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
  struct genl_family dp_vport_genl_family = {
  	.id = GENL_ID_GENERATE,
  	.hdrsize = sizeof(struct ovs_header),
  	.name = OVS_VPORT_FAMILY,
  	.version = OVS_VPORT_VERSION,
  	.maxattr = OVS_VPORT_ATTR_MAX,
  	.netnsok = true,
  	.parallel_ops = true,
  	.ops = dp_vport_genl_ops,
  	.n_ops = ARRAY_SIZE(dp_vport_genl_ops),
  	.mcgrps = &ovs_dp_vport_multicast_group,
  	.n_mcgrps = 1,
ccb1352e7   Jesse Gross   net: Add Open vSw...
2119
  };
0c200ef94   Pravin B Shelar   openvswitch: Simp...
2120
2121
2122
2123
2124
  static struct genl_family * const dp_genl_families[] = {
  	&dp_datapath_genl_family,
  	&dp_vport_genl_family,
  	&dp_flow_genl_family,
  	&dp_packet_genl_family,
ccb1352e7   Jesse Gross   net: Add Open vSw...
2125
2126
2127
2128
2129
2130
2131
  };
  
  static void dp_unregister_genl(int n_families)
  {
  	int i;
  
  	for (i = 0; i < n_families; i++)
0c200ef94   Pravin B Shelar   openvswitch: Simp...
2132
  		genl_unregister_family(dp_genl_families[i]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2133
2134
2135
2136
  }
  
  static int dp_register_genl(void)
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
2137
2138
  	int err;
  	int i;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2139
  	for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
2140

0c200ef94   Pravin B Shelar   openvswitch: Simp...
2141
  		err = genl_register_family(dp_genl_families[i]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2142
2143
  		if (err)
  			goto error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2144
2145
2146
2147
2148
  	}
  
  	return 0;
  
  error:
0c200ef94   Pravin B Shelar   openvswitch: Simp...
2149
  	dp_unregister_genl(i);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2150
2151
  	return err;
  }
46df7b814   Pravin B Shelar   openvswitch: Add ...
2152
2153
2154
2155
2156
  static int __net_init ovs_init_net(struct net *net)
  {
  	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
  
  	INIT_LIST_HEAD(&ovs_net->dps);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
2157
  	INIT_WORK(&ovs_net->dp_notify_work, ovs_dp_notify_wq);
c2ac66735   Joe Stringer   openvswitch: Allo...
2158
  	ovs_ct_init(net);
46df7b814   Pravin B Shelar   openvswitch: Add ...
2159
2160
  	return 0;
  }
7b4577a9d   Pravin B Shelar   openvswitch: Fix ...
2161
2162
  static void __net_exit list_vports_from_net(struct net *net, struct net *dnet,
  					    struct list_head *head)
46df7b814   Pravin B Shelar   openvswitch: Add ...
2163
  {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
2164
  	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
7b4577a9d   Pravin B Shelar   openvswitch: Fix ...
2165
2166
2167
2168
2169
2170
2171
2172
2173
  	struct datapath *dp;
  
  	list_for_each_entry(dp, &ovs_net->dps, list_node) {
  		int i;
  
  		for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
  			struct vport *vport;
  
  			hlist_for_each_entry(vport, &dp->ports[i], dp_hash_node) {
7b4577a9d   Pravin B Shelar   openvswitch: Fix ...
2174
2175
  				if (vport->ops->type != OVS_VPORT_TYPE_INTERNAL)
  					continue;
be4ace6e6   Thomas Graf   openvswitch: Move...
2176
  				if (dev_net(vport->dev) == dnet)
7b4577a9d   Pravin B Shelar   openvswitch: Fix ...
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
  					list_add(&vport->detach_list, head);
  			}
  		}
  	}
  }
  
  static void __net_exit ovs_exit_net(struct net *dnet)
  {
  	struct datapath *dp, *dp_next;
  	struct ovs_net *ovs_net = net_generic(dnet, ovs_net_id);
  	struct vport *vport, *vport_next;
  	struct net *net;
  	LIST_HEAD(head);
46df7b814   Pravin B Shelar   openvswitch: Add ...
2190

c2ac66735   Joe Stringer   openvswitch: Allo...
2191
  	ovs_ct_exit(dnet);
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
2192
  	ovs_lock();
46df7b814   Pravin B Shelar   openvswitch: Add ...
2193
2194
  	list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
  		__dp_destroy(dp);
7b4577a9d   Pravin B Shelar   openvswitch: Fix ...
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
  
  	rtnl_lock();
  	for_each_net(net)
  		list_vports_from_net(net, dnet, &head);
  	rtnl_unlock();
  
  	/* Detach all vports from given namespace. */
  	list_for_each_entry_safe(vport, vport_next, &head, detach_list) {
  		list_del(&vport->detach_list);
  		ovs_dp_detach_port(vport);
  	}
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
2206
2207
2208
  	ovs_unlock();
  
  	cancel_work_sync(&ovs_net->dp_notify_work);
46df7b814   Pravin B Shelar   openvswitch: Add ...
2209
2210
2211
2212
2213
2214
2215
2216
  }
  
  static struct pernet_operations ovs_net_ops = {
  	.init = ovs_init_net,
  	.exit = ovs_exit_net,
  	.id   = &ovs_net_id,
  	.size = sizeof(struct ovs_net),
  };
ccb1352e7   Jesse Gross   net: Add Open vSw...
2217
2218
  static int __init dp_init(void)
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
2219
  	int err;
3523b29bd   YOSHIFUJI Hideaki / 吉藤英明   openvswitch: Use ...
2220
  	BUILD_BUG_ON(sizeof(struct ovs_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
ccb1352e7   Jesse Gross   net: Add Open vSw...
2221
2222
2223
  
  	pr_info("Open vSwitch switching datapath
  ");
971427f35   Andy Zhou   openvswitch: Add ...
2224
  	err = action_fifos_init();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2225
2226
  	if (err)
  		goto error;
971427f35   Andy Zhou   openvswitch: Add ...
2227
2228
2229
  	err = ovs_internal_dev_rtnl_link_register();
  	if (err)
  		goto error_action_fifos_exit;
5b9e7e160   Jiri Pirko   openvswitch: intr...
2230
2231
2232
  	err = ovs_flow_init();
  	if (err)
  		goto error_unreg_rtnl_link;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2233
2234
2235
  	err = ovs_vport_init();
  	if (err)
  		goto error_flow_exit;
46df7b814   Pravin B Shelar   openvswitch: Add ...
2236
  	err = register_pernet_device(&ovs_net_ops);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2237
2238
  	if (err)
  		goto error_vport_exit;
46df7b814   Pravin B Shelar   openvswitch: Add ...
2239
2240
2241
  	err = register_netdevice_notifier(&ovs_dp_device_notifier);
  	if (err)
  		goto error_netns_exit;
62b9c8d03   Thomas Graf   ovs: Turn vports ...
2242
2243
2244
  	err = ovs_netdev_init();
  	if (err)
  		goto error_unreg_notifier;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2245
2246
  	err = dp_register_genl();
  	if (err < 0)
62b9c8d03   Thomas Graf   ovs: Turn vports ...
2247
  		goto error_unreg_netdev;
ccb1352e7   Jesse Gross   net: Add Open vSw...
2248

ccb1352e7   Jesse Gross   net: Add Open vSw...
2249
  	return 0;
62b9c8d03   Thomas Graf   ovs: Turn vports ...
2250
2251
  error_unreg_netdev:
  	ovs_netdev_exit();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2252
2253
  error_unreg_notifier:
  	unregister_netdevice_notifier(&ovs_dp_device_notifier);
46df7b814   Pravin B Shelar   openvswitch: Add ...
2254
2255
  error_netns_exit:
  	unregister_pernet_device(&ovs_net_ops);
ccb1352e7   Jesse Gross   net: Add Open vSw...
2256
2257
2258
2259
  error_vport_exit:
  	ovs_vport_exit();
  error_flow_exit:
  	ovs_flow_exit();
5b9e7e160   Jiri Pirko   openvswitch: intr...
2260
2261
  error_unreg_rtnl_link:
  	ovs_internal_dev_rtnl_link_unregister();
971427f35   Andy Zhou   openvswitch: Add ...
2262
2263
  error_action_fifos_exit:
  	action_fifos_exit();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2264
2265
2266
2267
2268
2269
  error:
  	return err;
  }
  
  static void dp_cleanup(void)
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
2270
  	dp_unregister_genl(ARRAY_SIZE(dp_genl_families));
62b9c8d03   Thomas Graf   ovs: Turn vports ...
2271
  	ovs_netdev_exit();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2272
  	unregister_netdevice_notifier(&ovs_dp_device_notifier);
46df7b814   Pravin B Shelar   openvswitch: Add ...
2273
2274
  	unregister_pernet_device(&ovs_net_ops);
  	rcu_barrier();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2275
2276
  	ovs_vport_exit();
  	ovs_flow_exit();
5b9e7e160   Jiri Pirko   openvswitch: intr...
2277
  	ovs_internal_dev_rtnl_link_unregister();
971427f35   Andy Zhou   openvswitch: Add ...
2278
  	action_fifos_exit();
ccb1352e7   Jesse Gross   net: Add Open vSw...
2279
2280
2281
2282
2283
2284
2285
  }
  
  module_init(dp_init);
  module_exit(dp_cleanup);
  
  MODULE_DESCRIPTION("Open vSwitch switching datapath");
  MODULE_LICENSE("GPL");
ed227099d   Thadeu Lima de Souza Cascardo   openvswitch: use ...
2286
2287
2288
2289
  MODULE_ALIAS_GENL_FAMILY(OVS_DATAPATH_FAMILY);
  MODULE_ALIAS_GENL_FAMILY(OVS_VPORT_FAMILY);
  MODULE_ALIAS_GENL_FAMILY(OVS_FLOW_FAMILY);
  MODULE_ALIAS_GENL_FAMILY(OVS_PACKET_FAMILY);