xref: /openbmc/linux/net/openvswitch/vport.c (revision fed48423)
1c9422999SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ccb1352eSJesse Gross /*
383c8df26SPravin B Shelar  * Copyright (c) 2007-2014 Nicira, Inc.
4ccb1352eSJesse Gross  */
5ccb1352eSJesse Gross 
6ccb1352eSJesse Gross #include <linux/etherdevice.h>
7ccb1352eSJesse Gross #include <linux/if.h>
8ccb1352eSJesse Gross #include <linux/if_vlan.h>
946df7b81SPravin B Shelar #include <linux/jhash.h>
10ccb1352eSJesse Gross #include <linux/kernel.h>
11ccb1352eSJesse Gross #include <linux/list.h>
12ccb1352eSJesse Gross #include <linux/mutex.h>
13ccb1352eSJesse Gross #include <linux/percpu.h>
14ccb1352eSJesse Gross #include <linux/rcupdate.h>
15ccb1352eSJesse Gross #include <linux/rtnetlink.h>
16ccb1352eSJesse Gross #include <linux/compat.h>
1746df7b81SPravin B Shelar #include <net/net_namespace.h>
1862b9c8d0SThomas Graf #include <linux/module.h>
19ccb1352eSJesse Gross 
2046df7b81SPravin B Shelar #include "datapath.h"
21ccb1352eSJesse Gross #include "vport.h"
22ccb1352eSJesse Gross #include "vport-internal_dev.h"
23ccb1352eSJesse Gross 
2462b9c8d0SThomas Graf static LIST_HEAD(vport_ops_list);
25ccb1352eSJesse Gross 
268e4e1713SPravin B Shelar /* Protected by RCU read lock for reading, ovs_mutex for writing. */
27ccb1352eSJesse Gross static struct hlist_head *dev_table;
28ccb1352eSJesse Gross #define VPORT_HASH_BUCKETS 1024
29ccb1352eSJesse Gross 
30ccb1352eSJesse Gross /**
31ccb1352eSJesse Gross  *	ovs_vport_init - initialize vport subsystem
32ccb1352eSJesse Gross  *
33ccb1352eSJesse Gross  * Called at module load time to initialize the vport subsystem.
34ccb1352eSJesse Gross  */
35ccb1352eSJesse Gross int ovs_vport_init(void)
36ccb1352eSJesse Gross {
376396bb22SKees Cook 	dev_table = kcalloc(VPORT_HASH_BUCKETS, sizeof(struct hlist_head),
38ccb1352eSJesse Gross 			    GFP_KERNEL);
39ccb1352eSJesse Gross 	if (!dev_table)
40ccb1352eSJesse Gross 		return -ENOMEM;
41ccb1352eSJesse Gross 
42ccb1352eSJesse Gross 	return 0;
43ccb1352eSJesse Gross }
44ccb1352eSJesse Gross 
45ccb1352eSJesse Gross /**
46ccb1352eSJesse Gross  *	ovs_vport_exit - shutdown vport subsystem
47ccb1352eSJesse Gross  *
48ccb1352eSJesse Gross  * Called at module exit time to shutdown the vport subsystem.
49ccb1352eSJesse Gross  */
50ccb1352eSJesse Gross void ovs_vport_exit(void)
51ccb1352eSJesse Gross {
52ccb1352eSJesse Gross 	kfree(dev_table);
53ccb1352eSJesse Gross }
54ccb1352eSJesse Gross 
5512eb18f7SThomas Graf static struct hlist_head *hash_bucket(const struct net *net, const char *name)
56ccb1352eSJesse Gross {
5746df7b81SPravin B Shelar 	unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
58ccb1352eSJesse Gross 	return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
59ccb1352eSJesse Gross }
60ccb1352eSJesse Gross 
6183e4bf7aSPaolo Abeni int __ovs_vport_ops_register(struct vport_ops *ops)
6262b9c8d0SThomas Graf {
6362b9c8d0SThomas Graf 	int err = -EEXIST;
6462b9c8d0SThomas Graf 	struct vport_ops *o;
6562b9c8d0SThomas Graf 
6662b9c8d0SThomas Graf 	ovs_lock();
6762b9c8d0SThomas Graf 	list_for_each_entry(o, &vport_ops_list, list)
6862b9c8d0SThomas Graf 		if (ops->type == o->type)
6962b9c8d0SThomas Graf 			goto errout;
7062b9c8d0SThomas Graf 
7162b9c8d0SThomas Graf 	list_add_tail(&ops->list, &vport_ops_list);
7262b9c8d0SThomas Graf 	err = 0;
7362b9c8d0SThomas Graf errout:
7462b9c8d0SThomas Graf 	ovs_unlock();
7562b9c8d0SThomas Graf 	return err;
7662b9c8d0SThomas Graf }
7783e4bf7aSPaolo Abeni EXPORT_SYMBOL_GPL(__ovs_vport_ops_register);
7862b9c8d0SThomas Graf 
7962b9c8d0SThomas Graf void ovs_vport_ops_unregister(struct vport_ops *ops)
8062b9c8d0SThomas Graf {
8162b9c8d0SThomas Graf 	ovs_lock();
8262b9c8d0SThomas Graf 	list_del(&ops->list);
8362b9c8d0SThomas Graf 	ovs_unlock();
8462b9c8d0SThomas Graf }
859ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_ops_unregister);
8662b9c8d0SThomas Graf 
87ccb1352eSJesse Gross /**
88ccb1352eSJesse Gross  *	ovs_vport_locate - find a port that has already been created
89ccb1352eSJesse Gross  *
90ccb1352eSJesse Gross  * @name: name of port to find
91ccb1352eSJesse Gross  *
928e4e1713SPravin B Shelar  * Must be called with ovs or RCU read lock.
93ccb1352eSJesse Gross  */
9412eb18f7SThomas Graf struct vport *ovs_vport_locate(const struct net *net, const char *name)
95ccb1352eSJesse Gross {
9646df7b81SPravin B Shelar 	struct hlist_head *bucket = hash_bucket(net, name);
97ccb1352eSJesse Gross 	struct vport *vport;
98ccb1352eSJesse Gross 
99fed48423SMadhuparna Bhowmik 	hlist_for_each_entry_rcu(vport, bucket, hash_node,
100fed48423SMadhuparna Bhowmik 				lockdep_ovsl_is_held())
101c9db965cSThomas Graf 		if (!strcmp(name, ovs_vport_name(vport)) &&
10246df7b81SPravin B Shelar 		    net_eq(ovs_dp_get_net(vport->dp), net))
103ccb1352eSJesse Gross 			return vport;
104ccb1352eSJesse Gross 
105ccb1352eSJesse Gross 	return NULL;
106ccb1352eSJesse Gross }
107ccb1352eSJesse Gross 
108ccb1352eSJesse Gross /**
109ccb1352eSJesse Gross  *	ovs_vport_alloc - allocate and initialize new vport
110ccb1352eSJesse Gross  *
111ccb1352eSJesse Gross  * @priv_size: Size of private data area to allocate.
112ccb1352eSJesse Gross  * @ops: vport device ops
113ccb1352eSJesse Gross  *
114ccb1352eSJesse Gross  * Allocate and initialize a new vport defined by @ops.  The vport will contain
115ccb1352eSJesse Gross  * a private data area of size @priv_size that can be accessed using
116ccb1352eSJesse Gross  * vport_priv().  vports that are no longer needed should be released with
117ccb1352eSJesse Gross  * vport_free().
118ccb1352eSJesse Gross  */
119ccb1352eSJesse Gross struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
120ccb1352eSJesse Gross 			  const struct vport_parms *parms)
121ccb1352eSJesse Gross {
122ccb1352eSJesse Gross 	struct vport *vport;
123ccb1352eSJesse Gross 	size_t alloc_size;
124ccb1352eSJesse Gross 
125ccb1352eSJesse Gross 	alloc_size = sizeof(struct vport);
126ccb1352eSJesse Gross 	if (priv_size) {
127ccb1352eSJesse Gross 		alloc_size = ALIGN(alloc_size, VPORT_ALIGN);
128ccb1352eSJesse Gross 		alloc_size += priv_size;
129ccb1352eSJesse Gross 	}
130ccb1352eSJesse Gross 
131ccb1352eSJesse Gross 	vport = kzalloc(alloc_size, GFP_KERNEL);
132ccb1352eSJesse Gross 	if (!vport)
133ccb1352eSJesse Gross 		return ERR_PTR(-ENOMEM);
134ccb1352eSJesse Gross 
135ccb1352eSJesse Gross 	vport->dp = parms->dp;
136ccb1352eSJesse Gross 	vport->port_no = parms->port_no;
137ccb1352eSJesse Gross 	vport->ops = ops;
13815eac2a7SPravin B Shelar 	INIT_HLIST_NODE(&vport->dp_hash_node);
139ccb1352eSJesse Gross 
1403791b3f6SChristoph Jaeger 	if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids)) {
1413791b3f6SChristoph Jaeger 		kfree(vport);
1425cd667b0SAlex Wang 		return ERR_PTR(-EINVAL);
1433791b3f6SChristoph Jaeger 	}
1445cd667b0SAlex Wang 
145ccb1352eSJesse Gross 	return vport;
146ccb1352eSJesse Gross }
1479ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_alloc);
148ccb1352eSJesse Gross 
149ccb1352eSJesse Gross /**
150ccb1352eSJesse Gross  *	ovs_vport_free - uninitialize and free vport
151ccb1352eSJesse Gross  *
152ccb1352eSJesse Gross  * @vport: vport to free
153ccb1352eSJesse Gross  *
154ccb1352eSJesse Gross  * Frees a vport allocated with vport_alloc() when it is no longer needed.
155ccb1352eSJesse Gross  *
156ccb1352eSJesse Gross  * The caller must ensure that an RCU grace period has passed since the last
157ccb1352eSJesse Gross  * time @vport was in a datapath.
158ccb1352eSJesse Gross  */
159ccb1352eSJesse Gross void ovs_vport_free(struct vport *vport)
160ccb1352eSJesse Gross {
1615cd667b0SAlex Wang 	/* vport is freed from RCU callback or error path, Therefore
1625cd667b0SAlex Wang 	 * it is safe to use raw dereference.
1635cd667b0SAlex Wang 	 */
1645cd667b0SAlex Wang 	kfree(rcu_dereference_raw(vport->upcall_portids));
165ccb1352eSJesse Gross 	kfree(vport);
166ccb1352eSJesse Gross }
1679ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_free);
16862b9c8d0SThomas Graf 
16962b9c8d0SThomas Graf static struct vport_ops *ovs_vport_lookup(const struct vport_parms *parms)
17062b9c8d0SThomas Graf {
17162b9c8d0SThomas Graf 	struct vport_ops *ops;
17262b9c8d0SThomas Graf 
17362b9c8d0SThomas Graf 	list_for_each_entry(ops, &vport_ops_list, list)
17462b9c8d0SThomas Graf 		if (ops->type == parms->type)
17562b9c8d0SThomas Graf 			return ops;
17662b9c8d0SThomas Graf 
17762b9c8d0SThomas Graf 	return NULL;
17862b9c8d0SThomas Graf }
179ccb1352eSJesse Gross 
180ccb1352eSJesse Gross /**
181ccb1352eSJesse Gross  *	ovs_vport_add - add vport device (for kernel callers)
182ccb1352eSJesse Gross  *
183ccb1352eSJesse Gross  * @parms: Information about new vport.
184ccb1352eSJesse Gross  *
185ccb1352eSJesse Gross  * Creates a new vport with the specified configuration (which is dependent on
1868e4e1713SPravin B Shelar  * device type).  ovs_mutex must be held.
187ccb1352eSJesse Gross  */
188ccb1352eSJesse Gross struct vport *ovs_vport_add(const struct vport_parms *parms)
189ccb1352eSJesse Gross {
19062b9c8d0SThomas Graf 	struct vport_ops *ops;
191ccb1352eSJesse Gross 	struct vport *vport;
192ccb1352eSJesse Gross 
19362b9c8d0SThomas Graf 	ops = ovs_vport_lookup(parms);
19462b9c8d0SThomas Graf 	if (ops) {
19546df7b81SPravin B Shelar 		struct hlist_head *bucket;
19646df7b81SPravin B Shelar 
19762b9c8d0SThomas Graf 		if (!try_module_get(ops->owner))
19862b9c8d0SThomas Graf 			return ERR_PTR(-EAFNOSUPPORT);
19962b9c8d0SThomas Graf 
20062b9c8d0SThomas Graf 		vport = ops->create(parms);
201ccb1352eSJesse Gross 		if (IS_ERR(vport)) {
20262b9c8d0SThomas Graf 			module_put(ops->owner);
20362b9c8d0SThomas Graf 			return vport;
204ccb1352eSJesse Gross 		}
205ccb1352eSJesse Gross 
20646df7b81SPravin B Shelar 		bucket = hash_bucket(ovs_dp_get_net(vport->dp),
207c9db965cSThomas Graf 				     ovs_vport_name(vport));
20846df7b81SPravin B Shelar 		hlist_add_head_rcu(&vport->hash_node, bucket);
209ccb1352eSJesse Gross 		return vport;
210ccb1352eSJesse Gross 	}
211ccb1352eSJesse Gross 
21262b9c8d0SThomas Graf 	/* Unlock to attempt module load and return -EAGAIN if load
21362b9c8d0SThomas Graf 	 * was successful as we need to restart the port addition
21462b9c8d0SThomas Graf 	 * workflow.
21562b9c8d0SThomas Graf 	 */
21662b9c8d0SThomas Graf 	ovs_unlock();
21762b9c8d0SThomas Graf 	request_module("vport-type-%d", parms->type);
21862b9c8d0SThomas Graf 	ovs_lock();
219ccb1352eSJesse Gross 
22062b9c8d0SThomas Graf 	if (!ovs_vport_lookup(parms))
22162b9c8d0SThomas Graf 		return ERR_PTR(-EAFNOSUPPORT);
22262b9c8d0SThomas Graf 	else
22362b9c8d0SThomas Graf 		return ERR_PTR(-EAGAIN);
224ccb1352eSJesse Gross }
225ccb1352eSJesse Gross 
226ccb1352eSJesse Gross /**
227ccb1352eSJesse Gross  *	ovs_vport_set_options - modify existing vport device (for kernel callers)
228ccb1352eSJesse Gross  *
229ccb1352eSJesse Gross  * @vport: vport to modify.
2302694838dSJustin Pettit  * @options: New configuration.
231ccb1352eSJesse Gross  *
232ccb1352eSJesse Gross  * Modifies an existing device with the specified configuration (which is
2338e4e1713SPravin B Shelar  * dependent on device type).  ovs_mutex must be held.
234ccb1352eSJesse Gross  */
235ccb1352eSJesse Gross int ovs_vport_set_options(struct vport *vport, struct nlattr *options)
236ccb1352eSJesse Gross {
237ccb1352eSJesse Gross 	if (!vport->ops->set_options)
238ccb1352eSJesse Gross 		return -EOPNOTSUPP;
239ccb1352eSJesse Gross 	return vport->ops->set_options(vport, options);
240ccb1352eSJesse Gross }
241ccb1352eSJesse Gross 
242ccb1352eSJesse Gross /**
243ccb1352eSJesse Gross  *	ovs_vport_del - delete existing vport device
244ccb1352eSJesse Gross  *
245ccb1352eSJesse Gross  * @vport: vport to delete.
246ccb1352eSJesse Gross  *
24720f79566SAaron Conole  * Detaches @vport from its datapath and destroys it.  ovs_mutex must
24820f79566SAaron Conole  * be held.
249ccb1352eSJesse Gross  */
250ccb1352eSJesse Gross void ovs_vport_del(struct vport *vport)
251ccb1352eSJesse Gross {
252ccb1352eSJesse Gross 	hlist_del_rcu(&vport->hash_node);
25362b9c8d0SThomas Graf 	module_put(vport->ops->owner);
254fa2d8ff4SThomas Graf 	vport->ops->destroy(vport);
255ccb1352eSJesse Gross }
256ccb1352eSJesse Gross 
257ccb1352eSJesse Gross /**
258ccb1352eSJesse Gross  *	ovs_vport_get_stats - retrieve device stats
259ccb1352eSJesse Gross  *
260ccb1352eSJesse Gross  * @vport: vport from which to retrieve the stats
261ccb1352eSJesse Gross  * @stats: location to store stats
262ccb1352eSJesse Gross  *
263ccb1352eSJesse Gross  * Retrieves transmit, receive, and error stats for the given device.
264ccb1352eSJesse Gross  *
2658e4e1713SPravin B Shelar  * Must be called with ovs_mutex or rcu_read_lock.
266ccb1352eSJesse Gross  */
267ccb1352eSJesse Gross void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
268ccb1352eSJesse Gross {
26983ffe99fSPravin B Shelar 	const struct rtnl_link_stats64 *dev_stats;
27083ffe99fSPravin B Shelar 	struct rtnl_link_stats64 temp;
271ccb1352eSJesse Gross 
27283ffe99fSPravin B Shelar 	dev_stats = dev_get_stats(vport->dev, &temp);
27383ffe99fSPravin B Shelar 	stats->rx_errors  = dev_stats->rx_errors;
27483ffe99fSPravin B Shelar 	stats->tx_errors  = dev_stats->tx_errors;
27583ffe99fSPravin B Shelar 	stats->tx_dropped = dev_stats->tx_dropped;
27683ffe99fSPravin B Shelar 	stats->rx_dropped = dev_stats->rx_dropped;
277ccb1352eSJesse Gross 
27883ffe99fSPravin B Shelar 	stats->rx_bytes	  = dev_stats->rx_bytes;
27983ffe99fSPravin B Shelar 	stats->rx_packets = dev_stats->rx_packets;
28083ffe99fSPravin B Shelar 	stats->tx_bytes	  = dev_stats->tx_bytes;
28183ffe99fSPravin B Shelar 	stats->tx_packets = dev_stats->tx_packets;
282ccb1352eSJesse Gross }
283ccb1352eSJesse Gross 
284ccb1352eSJesse Gross /**
285ccb1352eSJesse Gross  *	ovs_vport_get_options - retrieve device options
286ccb1352eSJesse Gross  *
287ccb1352eSJesse Gross  * @vport: vport from which to retrieve the options.
288ccb1352eSJesse Gross  * @skb: sk_buff where options should be appended.
289ccb1352eSJesse Gross  *
290ccb1352eSJesse Gross  * Retrieves the configuration of the given device, appending an
291ccb1352eSJesse Gross  * %OVS_VPORT_ATTR_OPTIONS attribute that in turn contains nested
292ccb1352eSJesse Gross  * vport-specific attributes to @skb.
293ccb1352eSJesse Gross  *
294ccb1352eSJesse Gross  * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room, or another
295ccb1352eSJesse Gross  * negative error code if a real error occurred.  If an error occurs, @skb is
296ccb1352eSJesse Gross  * left unmodified.
297ccb1352eSJesse Gross  *
2988e4e1713SPravin B Shelar  * Must be called with ovs_mutex or rcu_read_lock.
299ccb1352eSJesse Gross  */
300ccb1352eSJesse Gross int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
301ccb1352eSJesse Gross {
302ccb1352eSJesse Gross 	struct nlattr *nla;
3035d963352SThomas Graf 	int err;
3045d963352SThomas Graf 
3055d963352SThomas Graf 	if (!vport->ops->get_options)
3065d963352SThomas Graf 		return 0;
307ccb1352eSJesse Gross 
308ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, OVS_VPORT_ATTR_OPTIONS);
309ccb1352eSJesse Gross 	if (!nla)
310ccb1352eSJesse Gross 		return -EMSGSIZE;
311ccb1352eSJesse Gross 
3125d963352SThomas Graf 	err = vport->ops->get_options(vport, skb);
313ccb1352eSJesse Gross 	if (err) {
314ccb1352eSJesse Gross 		nla_nest_cancel(skb, nla);
315ccb1352eSJesse Gross 		return err;
316ccb1352eSJesse Gross 	}
317ccb1352eSJesse Gross 
318ccb1352eSJesse Gross 	nla_nest_end(skb, nla);
319ccb1352eSJesse Gross 	return 0;
320ccb1352eSJesse Gross }
321ccb1352eSJesse Gross 
322ccb1352eSJesse Gross /**
3235cd667b0SAlex Wang  *	ovs_vport_set_upcall_portids - set upcall portids of @vport.
3245cd667b0SAlex Wang  *
3255cd667b0SAlex Wang  * @vport: vport to modify.
3265cd667b0SAlex Wang  * @ids: new configuration, an array of port ids.
3275cd667b0SAlex Wang  *
3285cd667b0SAlex Wang  * Sets the vport's upcall_portids to @ids.
3295cd667b0SAlex Wang  *
3305cd667b0SAlex Wang  * Returns 0 if successful, -EINVAL if @ids is zero length or cannot be parsed
3315cd667b0SAlex Wang  * as an array of U32.
3325cd667b0SAlex Wang  *
3335cd667b0SAlex Wang  * Must be called with ovs_mutex.
3345cd667b0SAlex Wang  */
33512eb18f7SThomas Graf int ovs_vport_set_upcall_portids(struct vport *vport, const struct nlattr *ids)
3365cd667b0SAlex Wang {
3375cd667b0SAlex Wang 	struct vport_portids *old, *vport_portids;
3385cd667b0SAlex Wang 
3395cd667b0SAlex Wang 	if (!nla_len(ids) || nla_len(ids) % sizeof(u32))
3405cd667b0SAlex Wang 		return -EINVAL;
3415cd667b0SAlex Wang 
3425cd667b0SAlex Wang 	old = ovsl_dereference(vport->upcall_portids);
3435cd667b0SAlex Wang 
3445cd667b0SAlex Wang 	vport_portids = kmalloc(sizeof(*vport_portids) + nla_len(ids),
3455cd667b0SAlex Wang 				GFP_KERNEL);
3465cd667b0SAlex Wang 	if (!vport_portids)
3475cd667b0SAlex Wang 		return -ENOMEM;
3485cd667b0SAlex Wang 
3495cd667b0SAlex Wang 	vport_portids->n_ids = nla_len(ids) / sizeof(u32);
3505cd667b0SAlex Wang 	vport_portids->rn_ids = reciprocal_value(vport_portids->n_ids);
3515cd667b0SAlex Wang 	nla_memcpy(vport_portids->ids, ids, nla_len(ids));
3525cd667b0SAlex Wang 
3535cd667b0SAlex Wang 	rcu_assign_pointer(vport->upcall_portids, vport_portids);
3545cd667b0SAlex Wang 
3555cd667b0SAlex Wang 	if (old)
3565cd667b0SAlex Wang 		kfree_rcu(old, rcu);
3575cd667b0SAlex Wang 	return 0;
3585cd667b0SAlex Wang }
3595cd667b0SAlex Wang 
3605cd667b0SAlex Wang /**
3615cd667b0SAlex Wang  *	ovs_vport_get_upcall_portids - get the upcall_portids of @vport.
3625cd667b0SAlex Wang  *
3635cd667b0SAlex Wang  * @vport: vport from which to retrieve the portids.
3645cd667b0SAlex Wang  * @skb: sk_buff where portids should be appended.
3655cd667b0SAlex Wang  *
3665cd667b0SAlex Wang  * Retrieves the configuration of the given vport, appending the
3675cd667b0SAlex Wang  * %OVS_VPORT_ATTR_UPCALL_PID attribute which is the array of upcall
3685cd667b0SAlex Wang  * portids to @skb.
3695cd667b0SAlex Wang  *
3705cd667b0SAlex Wang  * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room.
3715cd667b0SAlex Wang  * If an error occurs, @skb is left unmodified.  Must be called with
3725cd667b0SAlex Wang  * ovs_mutex or rcu_read_lock.
3735cd667b0SAlex Wang  */
3745cd667b0SAlex Wang int ovs_vport_get_upcall_portids(const struct vport *vport,
3755cd667b0SAlex Wang 				 struct sk_buff *skb)
3765cd667b0SAlex Wang {
3775cd667b0SAlex Wang 	struct vport_portids *ids;
3785cd667b0SAlex Wang 
3795cd667b0SAlex Wang 	ids = rcu_dereference_ovsl(vport->upcall_portids);
3805cd667b0SAlex Wang 
3815cd667b0SAlex Wang 	if (vport->dp->user_features & OVS_DP_F_VPORT_PIDS)
3825cd667b0SAlex Wang 		return nla_put(skb, OVS_VPORT_ATTR_UPCALL_PID,
3835cd667b0SAlex Wang 			       ids->n_ids * sizeof(u32), (void *)ids->ids);
3845cd667b0SAlex Wang 	else
3855cd667b0SAlex Wang 		return nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, ids->ids[0]);
3865cd667b0SAlex Wang }
3875cd667b0SAlex Wang 
3885cd667b0SAlex Wang /**
3895cd667b0SAlex Wang  *	ovs_vport_find_upcall_portid - find the upcall portid to send upcall.
3905cd667b0SAlex Wang  *
3915cd667b0SAlex Wang  * @vport: vport from which the missed packet is received.
3925cd667b0SAlex Wang  * @skb: skb that the missed packet was received.
3935cd667b0SAlex Wang  *
3945cd667b0SAlex Wang  * Uses the skb_get_hash() to select the upcall portid to send the
3955cd667b0SAlex Wang  * upcall.
3965cd667b0SAlex Wang  *
3975cd667b0SAlex Wang  * Returns the portid of the target socket.  Must be called with rcu_read_lock.
3985cd667b0SAlex Wang  */
3994e8febd0SFabian Frederick u32 ovs_vport_find_upcall_portid(const struct vport *vport, struct sk_buff *skb)
4005cd667b0SAlex Wang {
4015cd667b0SAlex Wang 	struct vport_portids *ids;
4025cd667b0SAlex Wang 	u32 ids_index;
4035cd667b0SAlex Wang 	u32 hash;
4045cd667b0SAlex Wang 
4054e8febd0SFabian Frederick 	ids = rcu_dereference(vport->upcall_portids);
4065cd667b0SAlex Wang 
40790ce9f23STonghao Zhang 	/* If there is only one portid, select it in the fast-path. */
40890ce9f23STonghao Zhang 	if (ids->n_ids == 1)
40990ce9f23STonghao Zhang 		return ids->ids[0];
4105cd667b0SAlex Wang 
4115cd667b0SAlex Wang 	hash = skb_get_hash(skb);
4125cd667b0SAlex Wang 	ids_index = hash - ids->n_ids * reciprocal_divide(hash, ids->rn_ids);
4135cd667b0SAlex Wang 	return ids->ids[ids_index];
4145cd667b0SAlex Wang }
4155cd667b0SAlex Wang 
4165cd667b0SAlex Wang /**
417ccb1352eSJesse Gross  *	ovs_vport_receive - pass up received packet to the datapath for processing
418ccb1352eSJesse Gross  *
419ccb1352eSJesse Gross  * @vport: vport that received the packet
420ccb1352eSJesse Gross  * @skb: skb that was received
4212694838dSJustin Pettit  * @tun_key: tunnel (if any) that carried packet
422ccb1352eSJesse Gross  *
423ccb1352eSJesse Gross  * Must be called with rcu_read_lock.  The packet cannot be shared and
424d176ca2aSCong Wang  * skb->data should point to the Ethernet header.
425ccb1352eSJesse Gross  */
4268c876639SPravin B Shelar int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
4271d8fff90SThomas Graf 		      const struct ip_tunnel_info *tun_info)
428ccb1352eSJesse Gross {
4298c8b1b83SPravin B Shelar 	struct sw_flow_key key;
4308c8b1b83SPravin B Shelar 	int error;
431ccb1352eSJesse Gross 
43283c8df26SPravin B Shelar 	OVS_CB(skb)->input_vport = vport;
4337f8a436eSJoe Stringer 	OVS_CB(skb)->mru = 0;
434f2a4d086SWilliam Tu 	OVS_CB(skb)->cutlen = 0;
435740dbc28SJoe Stringer 	if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
436740dbc28SJoe Stringer 		u32 mark;
437740dbc28SJoe Stringer 
438740dbc28SJoe Stringer 		mark = skb->mark;
439740dbc28SJoe Stringer 		skb_scrub_packet(skb, true);
440740dbc28SJoe Stringer 		skb->mark = mark;
441740dbc28SJoe Stringer 		tun_info = NULL;
442740dbc28SJoe Stringer 	}
443740dbc28SJoe Stringer 
4448c8b1b83SPravin B Shelar 	/* Extract flow from 'skb' into 'key'. */
445f0b128c1SJesse Gross 	error = ovs_flow_key_extract(tun_info, skb, &key);
4468c8b1b83SPravin B Shelar 	if (unlikely(error)) {
4478c8b1b83SPravin B Shelar 		kfree_skb(skb);
4488c876639SPravin B Shelar 		return error;
4498c8b1b83SPravin B Shelar 	}
4508c8b1b83SPravin B Shelar 	ovs_dp_process_packet(skb, &key);
4518c876639SPravin B Shelar 	return 0;
452ccb1352eSJesse Gross }
453ccb1352eSJesse Gross 
45446e371f0SWilliam Tu static int packet_length(const struct sk_buff *skb,
455738314a0SJiri Benc 			 struct net_device *dev)
456aec15924SPravin B Shelar {
45746e371f0SWilliam Tu 	int length = skb->len - dev->hard_header_len;
458aec15924SPravin B Shelar 
45972ec108dSJiri Benc 	if (!skb_vlan_tag_present(skb) &&
46072ec108dSJiri Benc 	    eth_type_vlan(skb->protocol))
461aec15924SPravin B Shelar 		length -= VLAN_HLEN;
462aec15924SPravin B Shelar 
463018c1ddaSEric Garver 	/* Don't subtract for multiple VLAN tags. Most (all?) drivers allow
464018c1ddaSEric Garver 	 * (ETH_LEN + VLAN_HLEN) in addition to the mtu value, but almost none
465018c1ddaSEric Garver 	 * account for 802.1ad. e.g. is_skb_forwardable().
466018c1ddaSEric Garver 	 */
467018c1ddaSEric Garver 
46846e371f0SWilliam Tu 	return length > 0 ? length : 0;
469aec15924SPravin B Shelar }
470aec15924SPravin B Shelar 
471e2d9d835SJiri Benc void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto)
472aec15924SPravin B Shelar {
473aec15924SPravin B Shelar 	int mtu = vport->dev->mtu;
474aec15924SPravin B Shelar 
4755108bbadSJiri Benc 	switch (vport->dev->type) {
4765108bbadSJiri Benc 	case ARPHRD_NONE:
4775108bbadSJiri Benc 		if (mac_proto == MAC_PROTO_ETHERNET) {
4785108bbadSJiri Benc 			skb_reset_network_header(skb);
4795108bbadSJiri Benc 			skb_reset_mac_len(skb);
4805108bbadSJiri Benc 			skb->protocol = htons(ETH_P_TEB);
4815108bbadSJiri Benc 		} else if (mac_proto != MAC_PROTO_NONE) {
4825108bbadSJiri Benc 			WARN_ON_ONCE(1);
4835108bbadSJiri Benc 			goto drop;
4845108bbadSJiri Benc 		}
4855108bbadSJiri Benc 		break;
4865108bbadSJiri Benc 	case ARPHRD_ETHER:
4875108bbadSJiri Benc 		if (mac_proto != MAC_PROTO_ETHERNET)
4885108bbadSJiri Benc 			goto drop;
4895108bbadSJiri Benc 		break;
4905108bbadSJiri Benc 	default:
4915108bbadSJiri Benc 		goto drop;
4925108bbadSJiri Benc 	}
4935108bbadSJiri Benc 
494738314a0SJiri Benc 	if (unlikely(packet_length(skb, vport->dev) > mtu &&
495738314a0SJiri Benc 		     !skb_is_gso(skb))) {
496aec15924SPravin B Shelar 		net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
497aec15924SPravin B Shelar 				     vport->dev->name,
498738314a0SJiri Benc 				     packet_length(skb, vport->dev), mtu);
499aec15924SPravin B Shelar 		vport->dev->stats.tx_errors++;
500aec15924SPravin B Shelar 		goto drop;
501aec15924SPravin B Shelar 	}
502aec15924SPravin B Shelar 
503aec15924SPravin B Shelar 	skb->dev = vport->dev;
504aec15924SPravin B Shelar 	vport->ops->send(skb);
505aec15924SPravin B Shelar 	return;
506aec15924SPravin B Shelar 
507aec15924SPravin B Shelar drop:
508aec15924SPravin B Shelar 	kfree_skb(skb);
509aec15924SPravin B Shelar }
510