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