1ccb1352eSJesse Gross /* 283c8df26SPravin B Shelar * Copyright (c) 2007-2014 Nicira, Inc. 3ccb1352eSJesse Gross * 4ccb1352eSJesse Gross * This program is free software; you can redistribute it and/or 5ccb1352eSJesse Gross * modify it under the terms of version 2 of the GNU General Public 6ccb1352eSJesse Gross * License as published by the Free Software Foundation. 7ccb1352eSJesse Gross * 8ccb1352eSJesse Gross * This program is distributed in the hope that it will be useful, but 9ccb1352eSJesse Gross * WITHOUT ANY WARRANTY; without even the implied warranty of 10ccb1352eSJesse Gross * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11ccb1352eSJesse Gross * General Public License for more details. 12ccb1352eSJesse Gross * 13ccb1352eSJesse Gross * You should have received a copy of the GNU General Public License 14ccb1352eSJesse Gross * along with this program; if not, write to the Free Software 15ccb1352eSJesse Gross * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16ccb1352eSJesse Gross * 02110-1301, USA 17ccb1352eSJesse Gross */ 18ccb1352eSJesse Gross 19ccb1352eSJesse Gross #include <linux/etherdevice.h> 20ccb1352eSJesse Gross #include <linux/if.h> 21ccb1352eSJesse Gross #include <linux/if_vlan.h> 2246df7b81SPravin B Shelar #include <linux/jhash.h> 23ccb1352eSJesse Gross #include <linux/kernel.h> 24ccb1352eSJesse Gross #include <linux/list.h> 25ccb1352eSJesse Gross #include <linux/mutex.h> 26ccb1352eSJesse Gross #include <linux/percpu.h> 27ccb1352eSJesse Gross #include <linux/rcupdate.h> 28ccb1352eSJesse Gross #include <linux/rtnetlink.h> 29ccb1352eSJesse Gross #include <linux/compat.h> 3046df7b81SPravin B Shelar #include <net/net_namespace.h> 3162b9c8d0SThomas Graf #include <linux/module.h> 32ccb1352eSJesse Gross 3346df7b81SPravin B Shelar #include "datapath.h" 34ccb1352eSJesse Gross #include "vport.h" 35ccb1352eSJesse Gross #include "vport-internal_dev.h" 36ccb1352eSJesse Gross 3762b9c8d0SThomas Graf static LIST_HEAD(vport_ops_list); 38ccb1352eSJesse Gross 398e4e1713SPravin B Shelar /* Protected by RCU read lock for reading, ovs_mutex for writing. */ 40ccb1352eSJesse Gross static struct hlist_head *dev_table; 41ccb1352eSJesse Gross #define VPORT_HASH_BUCKETS 1024 42ccb1352eSJesse Gross 43ccb1352eSJesse Gross /** 44ccb1352eSJesse Gross * ovs_vport_init - initialize vport subsystem 45ccb1352eSJesse Gross * 46ccb1352eSJesse Gross * Called at module load time to initialize the vport subsystem. 47ccb1352eSJesse Gross */ 48ccb1352eSJesse Gross int ovs_vport_init(void) 49ccb1352eSJesse Gross { 50ccb1352eSJesse Gross dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head), 51ccb1352eSJesse Gross GFP_KERNEL); 52ccb1352eSJesse Gross if (!dev_table) 53ccb1352eSJesse Gross return -ENOMEM; 54ccb1352eSJesse Gross 55ccb1352eSJesse Gross return 0; 56ccb1352eSJesse Gross } 57ccb1352eSJesse Gross 58ccb1352eSJesse Gross /** 59ccb1352eSJesse Gross * ovs_vport_exit - shutdown vport subsystem 60ccb1352eSJesse Gross * 61ccb1352eSJesse Gross * Called at module exit time to shutdown the vport subsystem. 62ccb1352eSJesse Gross */ 63ccb1352eSJesse Gross void ovs_vport_exit(void) 64ccb1352eSJesse Gross { 65ccb1352eSJesse Gross kfree(dev_table); 66ccb1352eSJesse Gross } 67ccb1352eSJesse Gross 6812eb18f7SThomas Graf static struct hlist_head *hash_bucket(const struct net *net, const char *name) 69ccb1352eSJesse Gross { 7046df7b81SPravin B Shelar unsigned int hash = jhash(name, strlen(name), (unsigned long) net); 71ccb1352eSJesse Gross return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)]; 72ccb1352eSJesse Gross } 73ccb1352eSJesse Gross 7462b9c8d0SThomas Graf int ovs_vport_ops_register(struct vport_ops *ops) 7562b9c8d0SThomas Graf { 7662b9c8d0SThomas Graf int err = -EEXIST; 7762b9c8d0SThomas Graf struct vport_ops *o; 7862b9c8d0SThomas Graf 7962b9c8d0SThomas Graf ovs_lock(); 8062b9c8d0SThomas Graf list_for_each_entry(o, &vport_ops_list, list) 8162b9c8d0SThomas Graf if (ops->type == o->type) 8262b9c8d0SThomas Graf goto errout; 8362b9c8d0SThomas Graf 8462b9c8d0SThomas Graf list_add_tail(&ops->list, &vport_ops_list); 8562b9c8d0SThomas Graf err = 0; 8662b9c8d0SThomas Graf errout: 8762b9c8d0SThomas Graf ovs_unlock(); 8862b9c8d0SThomas Graf return err; 8962b9c8d0SThomas Graf } 909ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_ops_register); 9162b9c8d0SThomas Graf 9262b9c8d0SThomas Graf void ovs_vport_ops_unregister(struct vport_ops *ops) 9362b9c8d0SThomas Graf { 9462b9c8d0SThomas Graf ovs_lock(); 9562b9c8d0SThomas Graf list_del(&ops->list); 9662b9c8d0SThomas Graf ovs_unlock(); 9762b9c8d0SThomas Graf } 989ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_ops_unregister); 9962b9c8d0SThomas Graf 100ccb1352eSJesse Gross /** 101ccb1352eSJesse Gross * ovs_vport_locate - find a port that has already been created 102ccb1352eSJesse Gross * 103ccb1352eSJesse Gross * @name: name of port to find 104ccb1352eSJesse Gross * 1058e4e1713SPravin B Shelar * Must be called with ovs or RCU read lock. 106ccb1352eSJesse Gross */ 10712eb18f7SThomas Graf struct vport *ovs_vport_locate(const struct net *net, const char *name) 108ccb1352eSJesse Gross { 10946df7b81SPravin B Shelar struct hlist_head *bucket = hash_bucket(net, name); 110ccb1352eSJesse Gross struct vport *vport; 111ccb1352eSJesse Gross 112b67bfe0dSSasha Levin hlist_for_each_entry_rcu(vport, bucket, hash_node) 113c9db965cSThomas Graf if (!strcmp(name, ovs_vport_name(vport)) && 11446df7b81SPravin B Shelar net_eq(ovs_dp_get_net(vport->dp), net)) 115ccb1352eSJesse Gross return vport; 116ccb1352eSJesse Gross 117ccb1352eSJesse Gross return NULL; 118ccb1352eSJesse Gross } 119ccb1352eSJesse Gross 120ccb1352eSJesse Gross /** 121ccb1352eSJesse Gross * ovs_vport_alloc - allocate and initialize new vport 122ccb1352eSJesse Gross * 123ccb1352eSJesse Gross * @priv_size: Size of private data area to allocate. 124ccb1352eSJesse Gross * @ops: vport device ops 125ccb1352eSJesse Gross * 126ccb1352eSJesse Gross * Allocate and initialize a new vport defined by @ops. The vport will contain 127ccb1352eSJesse Gross * a private data area of size @priv_size that can be accessed using 128ccb1352eSJesse Gross * vport_priv(). vports that are no longer needed should be released with 129ccb1352eSJesse Gross * vport_free(). 130ccb1352eSJesse Gross */ 131ccb1352eSJesse Gross struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops, 132ccb1352eSJesse Gross const struct vport_parms *parms) 133ccb1352eSJesse Gross { 134ccb1352eSJesse Gross struct vport *vport; 135ccb1352eSJesse Gross size_t alloc_size; 136ccb1352eSJesse Gross 137ccb1352eSJesse Gross alloc_size = sizeof(struct vport); 138ccb1352eSJesse Gross if (priv_size) { 139ccb1352eSJesse Gross alloc_size = ALIGN(alloc_size, VPORT_ALIGN); 140ccb1352eSJesse Gross alloc_size += priv_size; 141ccb1352eSJesse Gross } 142ccb1352eSJesse Gross 143ccb1352eSJesse Gross vport = kzalloc(alloc_size, GFP_KERNEL); 144ccb1352eSJesse Gross if (!vport) 145ccb1352eSJesse Gross return ERR_PTR(-ENOMEM); 146ccb1352eSJesse Gross 147ccb1352eSJesse Gross vport->dp = parms->dp; 148ccb1352eSJesse Gross vport->port_no = parms->port_no; 149ccb1352eSJesse Gross vport->ops = ops; 15015eac2a7SPravin B Shelar INIT_HLIST_NODE(&vport->dp_hash_node); 151ccb1352eSJesse Gross 1523791b3f6SChristoph Jaeger if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids)) { 1533791b3f6SChristoph Jaeger kfree(vport); 1545cd667b0SAlex Wang return ERR_PTR(-EINVAL); 1553791b3f6SChristoph Jaeger } 1565cd667b0SAlex Wang 157ccb1352eSJesse Gross return vport; 158ccb1352eSJesse Gross } 1599ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_alloc); 160ccb1352eSJesse Gross 161ccb1352eSJesse Gross /** 162ccb1352eSJesse Gross * ovs_vport_free - uninitialize and free vport 163ccb1352eSJesse Gross * 164ccb1352eSJesse Gross * @vport: vport to free 165ccb1352eSJesse Gross * 166ccb1352eSJesse Gross * Frees a vport allocated with vport_alloc() when it is no longer needed. 167ccb1352eSJesse Gross * 168ccb1352eSJesse Gross * The caller must ensure that an RCU grace period has passed since the last 169ccb1352eSJesse Gross * time @vport was in a datapath. 170ccb1352eSJesse Gross */ 171ccb1352eSJesse Gross void ovs_vport_free(struct vport *vport) 172ccb1352eSJesse Gross { 1735cd667b0SAlex Wang /* vport is freed from RCU callback or error path, Therefore 1745cd667b0SAlex Wang * it is safe to use raw dereference. 1755cd667b0SAlex Wang */ 1765cd667b0SAlex Wang kfree(rcu_dereference_raw(vport->upcall_portids)); 177ccb1352eSJesse Gross kfree(vport); 178ccb1352eSJesse Gross } 1799ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_free); 18062b9c8d0SThomas Graf 18162b9c8d0SThomas Graf static struct vport_ops *ovs_vport_lookup(const struct vport_parms *parms) 18262b9c8d0SThomas Graf { 18362b9c8d0SThomas Graf struct vport_ops *ops; 18462b9c8d0SThomas Graf 18562b9c8d0SThomas Graf list_for_each_entry(ops, &vport_ops_list, list) 18662b9c8d0SThomas Graf if (ops->type == parms->type) 18762b9c8d0SThomas Graf return ops; 18862b9c8d0SThomas Graf 18962b9c8d0SThomas Graf return NULL; 19062b9c8d0SThomas Graf } 191ccb1352eSJesse Gross 192ccb1352eSJesse Gross /** 193ccb1352eSJesse Gross * ovs_vport_add - add vport device (for kernel callers) 194ccb1352eSJesse Gross * 195ccb1352eSJesse Gross * @parms: Information about new vport. 196ccb1352eSJesse Gross * 197ccb1352eSJesse Gross * Creates a new vport with the specified configuration (which is dependent on 1988e4e1713SPravin B Shelar * device type). ovs_mutex must be held. 199ccb1352eSJesse Gross */ 200ccb1352eSJesse Gross struct vport *ovs_vport_add(const struct vport_parms *parms) 201ccb1352eSJesse Gross { 20262b9c8d0SThomas Graf struct vport_ops *ops; 203ccb1352eSJesse Gross struct vport *vport; 204ccb1352eSJesse Gross 20562b9c8d0SThomas Graf ops = ovs_vport_lookup(parms); 20662b9c8d0SThomas Graf if (ops) { 20746df7b81SPravin B Shelar struct hlist_head *bucket; 20846df7b81SPravin B Shelar 20962b9c8d0SThomas Graf if (!try_module_get(ops->owner)) 21062b9c8d0SThomas Graf return ERR_PTR(-EAFNOSUPPORT); 21162b9c8d0SThomas Graf 21262b9c8d0SThomas Graf vport = ops->create(parms); 213ccb1352eSJesse Gross if (IS_ERR(vport)) { 21462b9c8d0SThomas Graf module_put(ops->owner); 21562b9c8d0SThomas Graf return vport; 216ccb1352eSJesse Gross } 217ccb1352eSJesse Gross 21846df7b81SPravin B Shelar bucket = hash_bucket(ovs_dp_get_net(vport->dp), 219c9db965cSThomas Graf ovs_vport_name(vport)); 22046df7b81SPravin B Shelar hlist_add_head_rcu(&vport->hash_node, bucket); 221ccb1352eSJesse Gross return vport; 222ccb1352eSJesse Gross } 223ccb1352eSJesse Gross 22462b9c8d0SThomas Graf /* Unlock to attempt module load and return -EAGAIN if load 22562b9c8d0SThomas Graf * was successful as we need to restart the port addition 22662b9c8d0SThomas Graf * workflow. 22762b9c8d0SThomas Graf */ 22862b9c8d0SThomas Graf ovs_unlock(); 22962b9c8d0SThomas Graf request_module("vport-type-%d", parms->type); 23062b9c8d0SThomas Graf ovs_lock(); 231ccb1352eSJesse Gross 23262b9c8d0SThomas Graf if (!ovs_vport_lookup(parms)) 23362b9c8d0SThomas Graf return ERR_PTR(-EAFNOSUPPORT); 23462b9c8d0SThomas Graf else 23562b9c8d0SThomas Graf return ERR_PTR(-EAGAIN); 236ccb1352eSJesse Gross } 237ccb1352eSJesse Gross 238ccb1352eSJesse Gross /** 239ccb1352eSJesse Gross * ovs_vport_set_options - modify existing vport device (for kernel callers) 240ccb1352eSJesse Gross * 241ccb1352eSJesse Gross * @vport: vport to modify. 2422694838dSJustin Pettit * @options: New configuration. 243ccb1352eSJesse Gross * 244ccb1352eSJesse Gross * Modifies an existing device with the specified configuration (which is 2458e4e1713SPravin B Shelar * dependent on device type). ovs_mutex must be held. 246ccb1352eSJesse Gross */ 247ccb1352eSJesse Gross int ovs_vport_set_options(struct vport *vport, struct nlattr *options) 248ccb1352eSJesse Gross { 249ccb1352eSJesse Gross if (!vport->ops->set_options) 250ccb1352eSJesse Gross return -EOPNOTSUPP; 251ccb1352eSJesse Gross return vport->ops->set_options(vport, options); 252ccb1352eSJesse Gross } 253ccb1352eSJesse Gross 254ccb1352eSJesse Gross /** 255ccb1352eSJesse Gross * ovs_vport_del - delete existing vport device 256ccb1352eSJesse Gross * 257ccb1352eSJesse Gross * @vport: vport to delete. 258ccb1352eSJesse Gross * 259ccb1352eSJesse Gross * Detaches @vport from its datapath and destroys it. It is possible to fail 2608e4e1713SPravin B Shelar * for reasons such as lack of memory. ovs_mutex must be held. 261ccb1352eSJesse Gross */ 262ccb1352eSJesse Gross void ovs_vport_del(struct vport *vport) 263ccb1352eSJesse Gross { 2648e4e1713SPravin B Shelar ASSERT_OVSL(); 265ccb1352eSJesse Gross 266ccb1352eSJesse Gross hlist_del_rcu(&vport->hash_node); 26762b9c8d0SThomas Graf module_put(vport->ops->owner); 268fa2d8ff4SThomas Graf vport->ops->destroy(vport); 269ccb1352eSJesse Gross } 270ccb1352eSJesse Gross 271ccb1352eSJesse Gross /** 272ccb1352eSJesse Gross * ovs_vport_get_stats - retrieve device stats 273ccb1352eSJesse Gross * 274ccb1352eSJesse Gross * @vport: vport from which to retrieve the stats 275ccb1352eSJesse Gross * @stats: location to store stats 276ccb1352eSJesse Gross * 277ccb1352eSJesse Gross * Retrieves transmit, receive, and error stats for the given device. 278ccb1352eSJesse Gross * 2798e4e1713SPravin B Shelar * Must be called with ovs_mutex or rcu_read_lock. 280ccb1352eSJesse Gross */ 281ccb1352eSJesse Gross void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats) 282ccb1352eSJesse Gross { 28383ffe99fSPravin B Shelar const struct rtnl_link_stats64 *dev_stats; 28483ffe99fSPravin B Shelar struct rtnl_link_stats64 temp; 285ccb1352eSJesse Gross 28683ffe99fSPravin B Shelar dev_stats = dev_get_stats(vport->dev, &temp); 28783ffe99fSPravin B Shelar stats->rx_errors = dev_stats->rx_errors; 28883ffe99fSPravin B Shelar stats->tx_errors = dev_stats->tx_errors; 28983ffe99fSPravin B Shelar stats->tx_dropped = dev_stats->tx_dropped; 29083ffe99fSPravin B Shelar stats->rx_dropped = dev_stats->rx_dropped; 291ccb1352eSJesse Gross 29283ffe99fSPravin B Shelar stats->rx_bytes = dev_stats->rx_bytes; 29383ffe99fSPravin B Shelar stats->rx_packets = dev_stats->rx_packets; 29483ffe99fSPravin B Shelar stats->tx_bytes = dev_stats->tx_bytes; 29583ffe99fSPravin B Shelar stats->tx_packets = dev_stats->tx_packets; 296ccb1352eSJesse Gross } 297ccb1352eSJesse Gross 298ccb1352eSJesse Gross /** 299ccb1352eSJesse Gross * ovs_vport_get_options - retrieve device options 300ccb1352eSJesse Gross * 301ccb1352eSJesse Gross * @vport: vport from which to retrieve the options. 302ccb1352eSJesse Gross * @skb: sk_buff where options should be appended. 303ccb1352eSJesse Gross * 304ccb1352eSJesse Gross * Retrieves the configuration of the given device, appending an 305ccb1352eSJesse Gross * %OVS_VPORT_ATTR_OPTIONS attribute that in turn contains nested 306ccb1352eSJesse Gross * vport-specific attributes to @skb. 307ccb1352eSJesse Gross * 308ccb1352eSJesse Gross * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room, or another 309ccb1352eSJesse Gross * negative error code if a real error occurred. If an error occurs, @skb is 310ccb1352eSJesse Gross * left unmodified. 311ccb1352eSJesse Gross * 3128e4e1713SPravin B Shelar * Must be called with ovs_mutex or rcu_read_lock. 313ccb1352eSJesse Gross */ 314ccb1352eSJesse Gross int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb) 315ccb1352eSJesse Gross { 316ccb1352eSJesse Gross struct nlattr *nla; 3175d963352SThomas Graf int err; 3185d963352SThomas Graf 3195d963352SThomas Graf if (!vport->ops->get_options) 3205d963352SThomas Graf return 0; 321ccb1352eSJesse Gross 322ccb1352eSJesse Gross nla = nla_nest_start(skb, OVS_VPORT_ATTR_OPTIONS); 323ccb1352eSJesse Gross if (!nla) 324ccb1352eSJesse Gross return -EMSGSIZE; 325ccb1352eSJesse Gross 3265d963352SThomas Graf err = vport->ops->get_options(vport, skb); 327ccb1352eSJesse Gross if (err) { 328ccb1352eSJesse Gross nla_nest_cancel(skb, nla); 329ccb1352eSJesse Gross return err; 330ccb1352eSJesse Gross } 331ccb1352eSJesse Gross 332ccb1352eSJesse Gross nla_nest_end(skb, nla); 333ccb1352eSJesse Gross return 0; 334ccb1352eSJesse Gross } 335ccb1352eSJesse Gross 336ccb1352eSJesse Gross /** 3375cd667b0SAlex Wang * ovs_vport_set_upcall_portids - set upcall portids of @vport. 3385cd667b0SAlex Wang * 3395cd667b0SAlex Wang * @vport: vport to modify. 3405cd667b0SAlex Wang * @ids: new configuration, an array of port ids. 3415cd667b0SAlex Wang * 3425cd667b0SAlex Wang * Sets the vport's upcall_portids to @ids. 3435cd667b0SAlex Wang * 3445cd667b0SAlex Wang * Returns 0 if successful, -EINVAL if @ids is zero length or cannot be parsed 3455cd667b0SAlex Wang * as an array of U32. 3465cd667b0SAlex Wang * 3475cd667b0SAlex Wang * Must be called with ovs_mutex. 3485cd667b0SAlex Wang */ 34912eb18f7SThomas Graf int ovs_vport_set_upcall_portids(struct vport *vport, const struct nlattr *ids) 3505cd667b0SAlex Wang { 3515cd667b0SAlex Wang struct vport_portids *old, *vport_portids; 3525cd667b0SAlex Wang 3535cd667b0SAlex Wang if (!nla_len(ids) || nla_len(ids) % sizeof(u32)) 3545cd667b0SAlex Wang return -EINVAL; 3555cd667b0SAlex Wang 3565cd667b0SAlex Wang old = ovsl_dereference(vport->upcall_portids); 3575cd667b0SAlex Wang 3585cd667b0SAlex Wang vport_portids = kmalloc(sizeof(*vport_portids) + nla_len(ids), 3595cd667b0SAlex Wang GFP_KERNEL); 3605cd667b0SAlex Wang if (!vport_portids) 3615cd667b0SAlex Wang return -ENOMEM; 3625cd667b0SAlex Wang 3635cd667b0SAlex Wang vport_portids->n_ids = nla_len(ids) / sizeof(u32); 3645cd667b0SAlex Wang vport_portids->rn_ids = reciprocal_value(vport_portids->n_ids); 3655cd667b0SAlex Wang nla_memcpy(vport_portids->ids, ids, nla_len(ids)); 3665cd667b0SAlex Wang 3675cd667b0SAlex Wang rcu_assign_pointer(vport->upcall_portids, vport_portids); 3685cd667b0SAlex Wang 3695cd667b0SAlex Wang if (old) 3705cd667b0SAlex Wang kfree_rcu(old, rcu); 3715cd667b0SAlex Wang return 0; 3725cd667b0SAlex Wang } 3735cd667b0SAlex Wang 3745cd667b0SAlex Wang /** 3755cd667b0SAlex Wang * ovs_vport_get_upcall_portids - get the upcall_portids of @vport. 3765cd667b0SAlex Wang * 3775cd667b0SAlex Wang * @vport: vport from which to retrieve the portids. 3785cd667b0SAlex Wang * @skb: sk_buff where portids should be appended. 3795cd667b0SAlex Wang * 3805cd667b0SAlex Wang * Retrieves the configuration of the given vport, appending the 3815cd667b0SAlex Wang * %OVS_VPORT_ATTR_UPCALL_PID attribute which is the array of upcall 3825cd667b0SAlex Wang * portids to @skb. 3835cd667b0SAlex Wang * 3845cd667b0SAlex Wang * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room. 3855cd667b0SAlex Wang * If an error occurs, @skb is left unmodified. Must be called with 3865cd667b0SAlex Wang * ovs_mutex or rcu_read_lock. 3875cd667b0SAlex Wang */ 3885cd667b0SAlex Wang int ovs_vport_get_upcall_portids(const struct vport *vport, 3895cd667b0SAlex Wang struct sk_buff *skb) 3905cd667b0SAlex Wang { 3915cd667b0SAlex Wang struct vport_portids *ids; 3925cd667b0SAlex Wang 3935cd667b0SAlex Wang ids = rcu_dereference_ovsl(vport->upcall_portids); 3945cd667b0SAlex Wang 3955cd667b0SAlex Wang if (vport->dp->user_features & OVS_DP_F_VPORT_PIDS) 3965cd667b0SAlex Wang return nla_put(skb, OVS_VPORT_ATTR_UPCALL_PID, 3975cd667b0SAlex Wang ids->n_ids * sizeof(u32), (void *)ids->ids); 3985cd667b0SAlex Wang else 3995cd667b0SAlex Wang return nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, ids->ids[0]); 4005cd667b0SAlex Wang } 4015cd667b0SAlex Wang 4025cd667b0SAlex Wang /** 4035cd667b0SAlex Wang * ovs_vport_find_upcall_portid - find the upcall portid to send upcall. 4045cd667b0SAlex Wang * 4055cd667b0SAlex Wang * @vport: vport from which the missed packet is received. 4065cd667b0SAlex Wang * @skb: skb that the missed packet was received. 4075cd667b0SAlex Wang * 4085cd667b0SAlex Wang * Uses the skb_get_hash() to select the upcall portid to send the 4095cd667b0SAlex Wang * upcall. 4105cd667b0SAlex Wang * 4115cd667b0SAlex Wang * Returns the portid of the target socket. Must be called with rcu_read_lock. 4125cd667b0SAlex Wang */ 4134e8febd0SFabian Frederick u32 ovs_vport_find_upcall_portid(const struct vport *vport, struct sk_buff *skb) 4145cd667b0SAlex Wang { 4155cd667b0SAlex Wang struct vport_portids *ids; 4165cd667b0SAlex Wang u32 ids_index; 4175cd667b0SAlex Wang u32 hash; 4185cd667b0SAlex Wang 4194e8febd0SFabian Frederick ids = rcu_dereference(vport->upcall_portids); 4205cd667b0SAlex Wang 4215cd667b0SAlex Wang if (ids->n_ids == 1 && ids->ids[0] == 0) 4225cd667b0SAlex Wang return 0; 4235cd667b0SAlex Wang 4245cd667b0SAlex Wang hash = skb_get_hash(skb); 4255cd667b0SAlex Wang ids_index = hash - ids->n_ids * reciprocal_divide(hash, ids->rn_ids); 4265cd667b0SAlex Wang return ids->ids[ids_index]; 4275cd667b0SAlex Wang } 4285cd667b0SAlex Wang 4295cd667b0SAlex Wang /** 430ccb1352eSJesse Gross * ovs_vport_receive - pass up received packet to the datapath for processing 431ccb1352eSJesse Gross * 432ccb1352eSJesse Gross * @vport: vport that received the packet 433ccb1352eSJesse Gross * @skb: skb that was received 4342694838dSJustin Pettit * @tun_key: tunnel (if any) that carried packet 435ccb1352eSJesse Gross * 436ccb1352eSJesse Gross * Must be called with rcu_read_lock. The packet cannot be shared and 437d176ca2aSCong Wang * skb->data should point to the Ethernet header. 438ccb1352eSJesse Gross */ 4398c876639SPravin B Shelar int ovs_vport_receive(struct vport *vport, struct sk_buff *skb, 4401d8fff90SThomas Graf const struct ip_tunnel_info *tun_info) 441ccb1352eSJesse Gross { 4428c8b1b83SPravin B Shelar struct sw_flow_key key; 4438c8b1b83SPravin B Shelar int error; 444ccb1352eSJesse Gross 44583c8df26SPravin B Shelar OVS_CB(skb)->input_vport = vport; 4467f8a436eSJoe Stringer OVS_CB(skb)->mru = 0; 4478c8b1b83SPravin B Shelar /* Extract flow from 'skb' into 'key'. */ 448f0b128c1SJesse Gross error = ovs_flow_key_extract(tun_info, skb, &key); 4498c8b1b83SPravin B Shelar if (unlikely(error)) { 4508c8b1b83SPravin B Shelar kfree_skb(skb); 4518c876639SPravin B Shelar return error; 4528c8b1b83SPravin B Shelar } 4538c8b1b83SPravin B Shelar ovs_dp_process_packet(skb, &key); 4548c876639SPravin B Shelar return 0; 455ccb1352eSJesse Gross } 4569ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_receive); 457ccb1352eSJesse Gross 458aa310701SPravin B Shelar static void free_vport_rcu(struct rcu_head *rcu) 459aa310701SPravin B Shelar { 460aa310701SPravin B Shelar struct vport *vport = container_of(rcu, struct vport, rcu); 461aa310701SPravin B Shelar 462aa310701SPravin B Shelar ovs_vport_free(vport); 463aa310701SPravin B Shelar } 464aa310701SPravin B Shelar 465aa310701SPravin B Shelar void ovs_vport_deferred_free(struct vport *vport) 466aa310701SPravin B Shelar { 467aa310701SPravin B Shelar if (!vport) 468aa310701SPravin B Shelar return; 469aa310701SPravin B Shelar 470aa310701SPravin B Shelar call_rcu(&vport->rcu, free_vport_rcu); 471aa310701SPravin B Shelar } 4729ba559d9SPravin B Shelar EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); 4738f0aad6fSWenyu Zhang 4744c222798SPravin B Shelar int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, 4758f0aad6fSWenyu Zhang struct net *net, 4763eedb41fSPravin B Shelar struct sk_buff *skb, 4778f0aad6fSWenyu Zhang u8 ipproto, 4788f0aad6fSWenyu Zhang __be16 tp_src, 4798f0aad6fSWenyu Zhang __be16 tp_dst) 4808f0aad6fSWenyu Zhang { 4814c222798SPravin B Shelar struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info; 4823eedb41fSPravin B Shelar const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb); 4831d8fff90SThomas Graf const struct ip_tunnel_key *tun_key; 4843eedb41fSPravin B Shelar u32 skb_mark = skb->mark; 4858f0aad6fSWenyu Zhang struct rtable *rt; 4868f0aad6fSWenyu Zhang struct flowi4 fl; 4878f0aad6fSWenyu Zhang 4888f0aad6fSWenyu Zhang if (unlikely(!tun_info)) 4898f0aad6fSWenyu Zhang return -EINVAL; 4907f9562a1SJiri Benc if (ip_tunnel_info_af(tun_info) != AF_INET) 4917f9562a1SJiri Benc return -EINVAL; 4928f0aad6fSWenyu Zhang 4931d8fff90SThomas Graf tun_key = &tun_info->key; 4948f0aad6fSWenyu Zhang 4958f0aad6fSWenyu Zhang /* Route lookup to get srouce IP address. 4968f0aad6fSWenyu Zhang * The process may need to be changed if the corresponding process 4978f0aad6fSWenyu Zhang * in vports ops changed. 4988f0aad6fSWenyu Zhang */ 4993f4c1d87SFan Du rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto); 5008f0aad6fSWenyu Zhang if (IS_ERR(rt)) 5018f0aad6fSWenyu Zhang return PTR_ERR(rt); 5028f0aad6fSWenyu Zhang 5038f0aad6fSWenyu Zhang ip_rt_put(rt); 5048f0aad6fSWenyu Zhang 5058f0aad6fSWenyu Zhang /* Generate egress_tun_info based on tun_info, 5068f0aad6fSWenyu Zhang * saddr, tp_src and tp_dst 5078f0aad6fSWenyu Zhang */ 5084c222798SPravin B Shelar ip_tunnel_key_init(&egress_tun_info->key, 509c1ea5d67SJiri Benc fl.saddr, tun_key->u.ipv4.dst, 5107c383fb2SJiri Benc tun_key->tos, 5117c383fb2SJiri Benc tun_key->ttl, 5128f0aad6fSWenyu Zhang tp_src, tp_dst, 5138f0aad6fSWenyu Zhang tun_key->tun_id, 5144c222798SPravin B Shelar tun_key->tun_flags); 5154c222798SPravin B Shelar egress_tun_info->options_len = tun_info->options_len; 5164c222798SPravin B Shelar egress_tun_info->mode = tun_info->mode; 5174c222798SPravin B Shelar upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info); 5188f0aad6fSWenyu Zhang return 0; 5198f0aad6fSWenyu Zhang } 5208f0aad6fSWenyu Zhang EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info); 5218f0aad6fSWenyu Zhang 5228f0aad6fSWenyu Zhang int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, 5234c222798SPravin B Shelar struct dp_upcall_info *upcall) 5248f0aad6fSWenyu Zhang { 5258f0aad6fSWenyu Zhang /* get_egress_tun_info() is only implemented on tunnel ports. */ 5268f0aad6fSWenyu Zhang if (unlikely(!vport->ops->get_egress_tun_info)) 5278f0aad6fSWenyu Zhang return -EINVAL; 5288f0aad6fSWenyu Zhang 5294c222798SPravin B Shelar return vport->ops->get_egress_tun_info(vport, skb, upcall); 5308f0aad6fSWenyu Zhang } 531