Blame view

net/openvswitch/vport.c 10 KB
ccb1352e7   Jesse Gross   net: Add Open vSw...
1
  /*
caf2ee14b   Raju Subramanian   openvswitch: Repl...
2
   * Copyright (c) 2007-2012 Nicira, Inc.
ccb1352e7   Jesse Gross   net: Add Open vSw...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * 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
   */
ccb1352e7   Jesse Gross   net: Add Open vSw...
18
19
20
  #include <linux/etherdevice.h>
  #include <linux/if.h>
  #include <linux/if_vlan.h>
46df7b814   Pravin B Shelar   openvswitch: Add ...
21
  #include <linux/jhash.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
22
23
24
25
26
27
28
  #include <linux/kernel.h>
  #include <linux/list.h>
  #include <linux/mutex.h>
  #include <linux/percpu.h>
  #include <linux/rcupdate.h>
  #include <linux/rtnetlink.h>
  #include <linux/compat.h>
46df7b814   Pravin B Shelar   openvswitch: Add ...
29
  #include <net/net_namespace.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
30

46df7b814   Pravin B Shelar   openvswitch: Add ...
31
  #include "datapath.h"
ccb1352e7   Jesse Gross   net: Add Open vSw...
32
33
34
35
36
37
38
39
40
  #include "vport.h"
  #include "vport-internal_dev.h"
  
  /* List of statically compiled vport implementations.  Don't forget to also
   * add yours to the list at the bottom of vport.h. */
  static const struct vport_ops *vport_ops_list[] = {
  	&ovs_netdev_vport_ops,
  	&ovs_internal_vport_ops,
  };
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
41
  /* Protected by RCU read lock for reading, ovs_mutex for writing. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  static struct hlist_head *dev_table;
  #define VPORT_HASH_BUCKETS 1024
  
  /**
   *	ovs_vport_init - initialize vport subsystem
   *
   * Called at module load time to initialize the vport subsystem.
   */
  int ovs_vport_init(void)
  {
  	dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
  			    GFP_KERNEL);
  	if (!dev_table)
  		return -ENOMEM;
  
  	return 0;
  }
  
  /**
   *	ovs_vport_exit - shutdown vport subsystem
   *
   * Called at module exit time to shutdown the vport subsystem.
   */
  void ovs_vport_exit(void)
  {
  	kfree(dev_table);
  }
46df7b814   Pravin B Shelar   openvswitch: Add ...
69
  static struct hlist_head *hash_bucket(struct net *net, const char *name)
ccb1352e7   Jesse Gross   net: Add Open vSw...
70
  {
46df7b814   Pravin B Shelar   openvswitch: Add ...
71
  	unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
ccb1352e7   Jesse Gross   net: Add Open vSw...
72
73
74
75
76
77
78
79
  	return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
  }
  
  /**
   *	ovs_vport_locate - find a port that has already been created
   *
   * @name: name of port to find
   *
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
80
   * Must be called with ovs or RCU read lock.
ccb1352e7   Jesse Gross   net: Add Open vSw...
81
   */
46df7b814   Pravin B Shelar   openvswitch: Add ...
82
  struct vport *ovs_vport_locate(struct net *net, const char *name)
ccb1352e7   Jesse Gross   net: Add Open vSw...
83
  {
46df7b814   Pravin B Shelar   openvswitch: Add ...
84
  	struct hlist_head *bucket = hash_bucket(net, name);
ccb1352e7   Jesse Gross   net: Add Open vSw...
85
  	struct vport *vport;
ccb1352e7   Jesse Gross   net: Add Open vSw...
86

b67bfe0d4   Sasha Levin   hlist: drop the n...
87
  	hlist_for_each_entry_rcu(vport, bucket, hash_node)
46df7b814   Pravin B Shelar   openvswitch: Add ...
88
89
  		if (!strcmp(name, vport->ops->get_name(vport)) &&
  		    net_eq(ovs_dp_get_net(vport->dp), net))
ccb1352e7   Jesse Gross   net: Add Open vSw...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  			return vport;
  
  	return NULL;
  }
  
  /**
   *	ovs_vport_alloc - allocate and initialize new vport
   *
   * @priv_size: Size of private data area to allocate.
   * @ops: vport device ops
   *
   * Allocate and initialize a new vport defined by @ops.  The vport will contain
   * a private data area of size @priv_size that can be accessed using
   * vport_priv().  vports that are no longer needed should be released with
   * vport_free().
   */
  struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
  			  const struct vport_parms *parms)
  {
  	struct vport *vport;
  	size_t alloc_size;
  
  	alloc_size = sizeof(struct vport);
  	if (priv_size) {
  		alloc_size = ALIGN(alloc_size, VPORT_ALIGN);
  		alloc_size += priv_size;
  	}
  
  	vport = kzalloc(alloc_size, GFP_KERNEL);
  	if (!vport)
  		return ERR_PTR(-ENOMEM);
  
  	vport->dp = parms->dp;
  	vport->port_no = parms->port_no;
15e473046   Eric W. Biederman   netlink: Rename p...
124
  	vport->upcall_portid = parms->upcall_portid;
ccb1352e7   Jesse Gross   net: Add Open vSw...
125
  	vport->ops = ops;
15eac2a74   Pravin B Shelar   openvswitch: Incr...
126
  	INIT_HLIST_NODE(&vport->dp_hash_node);
ccb1352e7   Jesse Gross   net: Add Open vSw...
127

e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
128
  	vport->percpu_stats = alloc_percpu(struct pcpu_tstats);
f0a98ae8d   Dan Carpenter   openvswitch: smal...
129
130
  	if (!vport->percpu_stats) {
  		kfree(vport);
ccb1352e7   Jesse Gross   net: Add Open vSw...
131
  		return ERR_PTR(-ENOMEM);
f0a98ae8d   Dan Carpenter   openvswitch: smal...
132
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  
  	spin_lock_init(&vport->stats_lock);
  
  	return vport;
  }
  
  /**
   *	ovs_vport_free - uninitialize and free vport
   *
   * @vport: vport to free
   *
   * Frees a vport allocated with vport_alloc() when it is no longer needed.
   *
   * The caller must ensure that an RCU grace period has passed since the last
   * time @vport was in a datapath.
   */
  void ovs_vport_free(struct vport *vport)
  {
  	free_percpu(vport->percpu_stats);
  	kfree(vport);
  }
  
  /**
   *	ovs_vport_add - add vport device (for kernel callers)
   *
   * @parms: Information about new vport.
   *
   * Creates a new vport with the specified configuration (which is dependent on
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
161
   * device type).  ovs_mutex must be held.
ccb1352e7   Jesse Gross   net: Add Open vSw...
162
163
164
165
166
167
   */
  struct vport *ovs_vport_add(const struct vport_parms *parms)
  {
  	struct vport *vport;
  	int err = 0;
  	int i;
ccb1352e7   Jesse Gross   net: Add Open vSw...
168
169
  	for (i = 0; i < ARRAY_SIZE(vport_ops_list); i++) {
  		if (vport_ops_list[i]->type == parms->type) {
46df7b814   Pravin B Shelar   openvswitch: Add ...
170
  			struct hlist_head *bucket;
ccb1352e7   Jesse Gross   net: Add Open vSw...
171
172
173
174
175
  			vport = vport_ops_list[i]->create(parms);
  			if (IS_ERR(vport)) {
  				err = PTR_ERR(vport);
  				goto out;
  			}
46df7b814   Pravin B Shelar   openvswitch: Add ...
176
177
178
  			bucket = hash_bucket(ovs_dp_get_net(vport->dp),
  					     vport->ops->get_name(vport));
  			hlist_add_head_rcu(&vport->hash_node, bucket);
ccb1352e7   Jesse Gross   net: Add Open vSw...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  			return vport;
  		}
  	}
  
  	err = -EAFNOSUPPORT;
  
  out:
  	return ERR_PTR(err);
  }
  
  /**
   *	ovs_vport_set_options - modify existing vport device (for kernel callers)
   *
   * @vport: vport to modify.
   * @port: New configuration.
   *
   * Modifies an existing device with the specified configuration (which is
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
196
   * dependent on device type).  ovs_mutex must be held.
ccb1352e7   Jesse Gross   net: Add Open vSw...
197
198
199
   */
  int ovs_vport_set_options(struct vport *vport, struct nlattr *options)
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
200
201
202
203
204
205
206
207
208
209
210
  	if (!vport->ops->set_options)
  		return -EOPNOTSUPP;
  	return vport->ops->set_options(vport, options);
  }
  
  /**
   *	ovs_vport_del - delete existing vport device
   *
   * @vport: vport to delete.
   *
   * Detaches @vport from its datapath and destroys it.  It is possible to fail
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
211
   * for reasons such as lack of memory.  ovs_mutex must be held.
ccb1352e7   Jesse Gross   net: Add Open vSw...
212
213
214
   */
  void ovs_vport_del(struct vport *vport)
  {
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
215
  	ASSERT_OVSL();
ccb1352e7   Jesse Gross   net: Add Open vSw...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  
  	hlist_del_rcu(&vport->hash_node);
  
  	vport->ops->destroy(vport);
  }
  
  /**
   *	ovs_vport_get_stats - retrieve device stats
   *
   * @vport: vport from which to retrieve the stats
   * @stats: location to store stats
   *
   * Retrieves transmit, receive, and error stats for the given device.
   *
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
230
   * Must be called with ovs_mutex or rcu_read_lock.
ccb1352e7   Jesse Gross   net: Add Open vSw...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
   */
  void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
  {
  	int i;
  
  	memset(stats, 0, sizeof(*stats));
  
  	/* We potentially have 2 sources of stats that need to be combined:
  	 * those we have collected (split into err_stats and percpu_stats) from
  	 * set_stats() and device error stats from netdev->get_stats() (for
  	 * errors that happen  downstream and therefore aren't reported through
  	 * our vport_record_error() function).
  	 * Stats from first source are reported by ovs (OVS_VPORT_ATTR_STATS).
  	 * netdev-stats can be directly read over netlink-ioctl.
  	 */
  
  	spin_lock_bh(&vport->stats_lock);
  
  	stats->rx_errors	= vport->err_stats.rx_errors;
  	stats->tx_errors	= vport->err_stats.tx_errors;
  	stats->tx_dropped	= vport->err_stats.tx_dropped;
  	stats->rx_dropped	= vport->err_stats.rx_dropped;
  
  	spin_unlock_bh(&vport->stats_lock);
  
  	for_each_possible_cpu(i) {
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
257
258
  		const struct pcpu_tstats *percpu_stats;
  		struct pcpu_tstats local_stats;
ccb1352e7   Jesse Gross   net: Add Open vSw...
259
260
261
262
263
  		unsigned int start;
  
  		percpu_stats = per_cpu_ptr(vport->percpu_stats, i);
  
  		do {
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
264
  			start = u64_stats_fetch_begin_bh(&percpu_stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
265
  			local_stats = *percpu_stats;
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
266
  		} while (u64_stats_fetch_retry_bh(&percpu_stats->syncp, start));
ccb1352e7   Jesse Gross   net: Add Open vSw...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  
  		stats->rx_bytes		+= local_stats.rx_bytes;
  		stats->rx_packets	+= local_stats.rx_packets;
  		stats->tx_bytes		+= local_stats.tx_bytes;
  		stats->tx_packets	+= local_stats.tx_packets;
  	}
  }
  
  /**
   *	ovs_vport_get_options - retrieve device options
   *
   * @vport: vport from which to retrieve the options.
   * @skb: sk_buff where options should be appended.
   *
   * Retrieves the configuration of the given device, appending an
   * %OVS_VPORT_ATTR_OPTIONS attribute that in turn contains nested
   * vport-specific attributes to @skb.
   *
   * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room, or another
   * negative error code if a real error occurred.  If an error occurs, @skb is
   * left unmodified.
   *
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
289
   * Must be called with ovs_mutex or rcu_read_lock.
ccb1352e7   Jesse Gross   net: Add Open vSw...
290
291
292
293
   */
  int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
  {
  	struct nlattr *nla;
5d9633523   Thomas Graf   openvswitch: Don'...
294
295
296
297
  	int err;
  
  	if (!vport->ops->get_options)
  		return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
298
299
300
301
  
  	nla = nla_nest_start(skb, OVS_VPORT_ATTR_OPTIONS);
  	if (!nla)
  		return -EMSGSIZE;
5d9633523   Thomas Graf   openvswitch: Don'...
302
303
304
305
  	err = vport->ops->get_options(vport, skb);
  	if (err) {
  		nla_nest_cancel(skb, nla);
  		return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
306
307
308
309
310
311
312
313
314
315
316
317
318
  	}
  
  	nla_nest_end(skb, nla);
  	return 0;
  }
  
  /**
   *	ovs_vport_receive - pass up received packet to the datapath for processing
   *
   * @vport: vport that received the packet
   * @skb: skb that was received
   *
   * Must be called with rcu_read_lock.  The packet cannot be shared and
d176ca2a4   Cong Wang   openvswitch: remo...
319
   * skb->data should point to the Ethernet header.
ccb1352e7   Jesse Gross   net: Add Open vSw...
320
321
322
   */
  void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
  {
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
323
  	struct pcpu_tstats *stats;
ccb1352e7   Jesse Gross   net: Add Open vSw...
324

404f2f101   Shan Wei   net: openvswitch:...
325
  	stats = this_cpu_ptr(vport->percpu_stats);
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
326
  	u64_stats_update_begin(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
327
328
  	stats->rx_packets++;
  	stats->rx_bytes += skb->len;
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
329
  	u64_stats_update_end(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
330
331
332
333
334
335
336
337
338
339
  
  	ovs_dp_process_received_packet(vport, skb);
  }
  
  /**
   *	ovs_vport_send - send a packet on a device
   *
   * @vport: vport on which to send the packet
   * @skb: skb to send
   *
8e4e1713e   Pravin B Shelar   openvswitch: Simp...
340
   * Sends the given packet and returns the length of data sent.  Either ovs
ccb1352e7   Jesse Gross   net: Add Open vSw...
341
342
343
344
345
346
347
   * lock or rcu_read_lock must be held.
   */
  int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
  {
  	int sent = vport->ops->send(vport, skb);
  
  	if (likely(sent)) {
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
348
  		struct pcpu_tstats *stats;
ccb1352e7   Jesse Gross   net: Add Open vSw...
349

404f2f101   Shan Wei   net: openvswitch:...
350
  		stats = this_cpu_ptr(vport->percpu_stats);
ccb1352e7   Jesse Gross   net: Add Open vSw...
351

e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
352
  		u64_stats_update_begin(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
353
354
  		stats->tx_packets++;
  		stats->tx_bytes += sent;
e0f0ecf33   Pravin B Shelar   openvswitch: Use ...
355
  		u64_stats_update_end(&stats->syncp);
ccb1352e7   Jesse Gross   net: Add Open vSw...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
  	}
  	return sent;
  }
  
  /**
   *	ovs_vport_record_error - indicate device error to generic stats layer
   *
   * @vport: vport that encountered the error
   * @err_type: one of enum vport_err_type types to indicate the error type
   *
   * If using the vport generic stats layer indicate that an error of the given
   * type has occured.
   */
  void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type)
  {
  	spin_lock(&vport->stats_lock);
  
  	switch (err_type) {
  	case VPORT_E_RX_DROPPED:
  		vport->err_stats.rx_dropped++;
  		break;
  
  	case VPORT_E_RX_ERROR:
  		vport->err_stats.rx_errors++;
  		break;
  
  	case VPORT_E_TX_DROPPED:
  		vport->err_stats.tx_dropped++;
  		break;
  
  	case VPORT_E_TX_ERROR:
  		vport->err_stats.tx_errors++;
  		break;
a2bf91b5b   Peter Senna Tschudin   net/openvswitch/v...
389
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
390
391
392
  
  	spin_unlock(&vport->stats_lock);
  }