linux/net/openvswitch/vport.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2007-2012 Nicira, Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of version 2 of the GNU General Public
   6 * License as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful, but
   9 * WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11 * General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software
  15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16 * 02110-1301, USA
  17 */
  18
  19#include <linux/etherdevice.h>
  20#include <linux/if.h>
  21#include <linux/if_vlan.h>
  22#include <linux/jhash.h>
  23#include <linux/kernel.h>
  24#include <linux/list.h>
  25#include <linux/mutex.h>
  26#include <linux/percpu.h>
  27#include <linux/rcupdate.h>
  28#include <linux/rtnetlink.h>
  29#include <linux/compat.h>
  30#include <net/net_namespace.h>
  31
  32#include "datapath.h"
  33#include "vport.h"
  34#include "vport-internal_dev.h"
  35
  36/* List of statically compiled vport implementations.  Don't forget to also
  37 * add yours to the list at the bottom of vport.h. */
  38static const struct vport_ops *vport_ops_list[] = {
  39        &ovs_netdev_vport_ops,
  40        &ovs_internal_vport_ops,
  41};
  42
  43/* Protected by RCU read lock for reading, RTNL lock for writing. */
  44static struct hlist_head *dev_table;
  45#define VPORT_HASH_BUCKETS 1024
  46
  47/**
  48 *      ovs_vport_init - initialize vport subsystem
  49 *
  50 * Called at module load time to initialize the vport subsystem.
  51 */
  52int ovs_vport_init(void)
  53{
  54        dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
  55                            GFP_KERNEL);
  56        if (!dev_table)
  57                return -ENOMEM;
  58
  59        return 0;
  60}
  61
  62/**
  63 *      ovs_vport_exit - shutdown vport subsystem
  64 *
  65 * Called at module exit time to shutdown the vport subsystem.
  66 */
  67void ovs_vport_exit(void)
  68{
  69        kfree(dev_table);
  70}
  71
  72static struct hlist_head *hash_bucket(struct net *net, const char *name)
  73{
  74        unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
  75        return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
  76}
  77
  78/**
  79 *      ovs_vport_locate - find a port that has already been created
  80 *
  81 * @name: name of port to find
  82 *
  83 * Must be called with RTNL or RCU read lock.
  84 */
  85struct vport *ovs_vport_locate(struct net *net, const char *name)
  86{
  87        struct hlist_head *bucket = hash_bucket(net, name);
  88        struct vport *vport;
  89        struct hlist_node *node;
  90
  91        hlist_for_each_entry_rcu(vport, node, bucket, hash_node)
  92                if (!strcmp(name, vport->ops->get_name(vport)) &&
  93                    net_eq(ovs_dp_get_net(vport->dp), net))
  94                        return vport;
  95
  96        return NULL;
  97}
  98
  99/**
 100 *      ovs_vport_alloc - allocate and initialize new vport
 101 *
 102 * @priv_size: Size of private data area to allocate.
 103 * @ops: vport device ops
 104 *
 105 * Allocate and initialize a new vport defined by @ops.  The vport will contain
 106 * a private data area of size @priv_size that can be accessed using
 107 * vport_priv().  vports that are no longer needed should be released with
 108 * vport_free().
 109 */
 110struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
 111                          const struct vport_parms *parms)
 112{
 113        struct vport *vport;
 114        size_t alloc_size;
 115
 116        alloc_size = sizeof(struct vport);
 117        if (priv_size) {
 118                alloc_size = ALIGN(alloc_size, VPORT_ALIGN);
 119                alloc_size += priv_size;
 120        }
 121
 122        vport = kzalloc(alloc_size, GFP_KERNEL);
 123        if (!vport)
 124                return ERR_PTR(-ENOMEM);
 125
 126        vport->dp = parms->dp;
 127        vport->port_no = parms->port_no;
 128        vport->upcall_portid = parms->upcall_portid;
 129        vport->ops = ops;
 130        INIT_HLIST_NODE(&vport->dp_hash_node);
 131
 132        vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
 133        if (!vport->percpu_stats) {
 134                kfree(vport);
 135                return ERR_PTR(-ENOMEM);
 136        }
 137
 138        spin_lock_init(&vport->stats_lock);
 139
 140        return vport;
 141}
 142
 143/**
 144 *      ovs_vport_free - uninitialize and free vport
 145 *
 146 * @vport: vport to free
 147 *
 148 * Frees a vport allocated with vport_alloc() when it is no longer needed.
 149 *
 150 * The caller must ensure that an RCU grace period has passed since the last
 151 * time @vport was in a datapath.
 152 */
 153void ovs_vport_free(struct vport *vport)
 154{
 155        free_percpu(vport->percpu_stats);
 156        kfree(vport);
 157}
 158
 159/**
 160 *      ovs_vport_add - add vport device (for kernel callers)
 161 *
 162 * @parms: Information about new vport.
 163 *
 164 * Creates a new vport with the specified configuration (which is dependent on
 165 * device type).  RTNL lock must be held.
 166 */
 167struct vport *ovs_vport_add(const struct vport_parms *parms)
 168{
 169        struct vport *vport;
 170        int err = 0;
 171        int i;
 172
 173        ASSERT_RTNL();
 174
 175        for (i = 0; i < ARRAY_SIZE(vport_ops_list); i++) {
 176                if (vport_ops_list[i]->type == parms->type) {
 177                        struct hlist_head *bucket;
 178
 179                        vport = vport_ops_list[i]->create(parms);
 180                        if (IS_ERR(vport)) {
 181                                err = PTR_ERR(vport);
 182                                goto out;
 183                        }
 184
 185                        bucket = hash_bucket(ovs_dp_get_net(vport->dp),
 186                                             vport->ops->get_name(vport));
 187                        hlist_add_head_rcu(&vport->hash_node, bucket);
 188                        return vport;
 189                }
 190        }
 191
 192        err = -EAFNOSUPPORT;
 193
 194out:
 195        return ERR_PTR(err);
 196}
 197
 198/**
 199 *      ovs_vport_set_options - modify existing vport device (for kernel callers)
 200 *
 201 * @vport: vport to modify.
 202 * @port: New configuration.
 203 *
 204 * Modifies an existing device with the specified configuration (which is
 205 * dependent on device type).  RTNL lock must be held.
 206 */
 207int ovs_vport_set_options(struct vport *vport, struct nlattr *options)
 208{
 209        ASSERT_RTNL();
 210
 211        if (!vport->ops->set_options)
 212                return -EOPNOTSUPP;
 213        return vport->ops->set_options(vport, options);
 214}
 215
 216/**
 217 *      ovs_vport_del - delete existing vport device
 218 *
 219 * @vport: vport to delete.
 220 *
 221 * Detaches @vport from its datapath and destroys it.  It is possible to fail
 222 * for reasons such as lack of memory.  RTNL lock must be held.
 223 */
 224void ovs_vport_del(struct vport *vport)
 225{
 226        ASSERT_RTNL();
 227
 228        hlist_del_rcu(&vport->hash_node);
 229
 230        vport->ops->destroy(vport);
 231}
 232
 233/**
 234 *      ovs_vport_get_stats - retrieve device stats
 235 *
 236 * @vport: vport from which to retrieve the stats
 237 * @stats: location to store stats
 238 *
 239 * Retrieves transmit, receive, and error stats for the given device.
 240 *
 241 * Must be called with RTNL lock or rcu_read_lock.
 242 */
 243void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
 244{
 245        int i;
 246
 247        memset(stats, 0, sizeof(*stats));
 248
 249        /* We potentially have 2 sources of stats that need to be combined:
 250         * those we have collected (split into err_stats and percpu_stats) from
 251         * set_stats() and device error stats from netdev->get_stats() (for
 252         * errors that happen  downstream and therefore aren't reported through
 253         * our vport_record_error() function).
 254         * Stats from first source are reported by ovs (OVS_VPORT_ATTR_STATS).
 255         * netdev-stats can be directly read over netlink-ioctl.
 256         */
 257
 258        spin_lock_bh(&vport->stats_lock);
 259
 260        stats->rx_errors        = vport->err_stats.rx_errors;
 261        stats->tx_errors        = vport->err_stats.tx_errors;
 262        stats->tx_dropped       = vport->err_stats.tx_dropped;
 263        stats->rx_dropped       = vport->err_stats.rx_dropped;
 264
 265        spin_unlock_bh(&vport->stats_lock);
 266
 267        for_each_possible_cpu(i) {
 268                const struct vport_percpu_stats *percpu_stats;
 269                struct vport_percpu_stats local_stats;
 270                unsigned int start;
 271
 272                percpu_stats = per_cpu_ptr(vport->percpu_stats, i);
 273
 274                do {
 275                        start = u64_stats_fetch_begin_bh(&percpu_stats->sync);
 276                        local_stats = *percpu_stats;
 277                } while (u64_stats_fetch_retry_bh(&percpu_stats->sync, start));
 278
 279                stats->rx_bytes         += local_stats.rx_bytes;
 280                stats->rx_packets       += local_stats.rx_packets;
 281                stats->tx_bytes         += local_stats.tx_bytes;
 282                stats->tx_packets       += local_stats.tx_packets;
 283        }
 284}
 285
 286/**
 287 *      ovs_vport_get_options - retrieve device options
 288 *
 289 * @vport: vport from which to retrieve the options.
 290 * @skb: sk_buff where options should be appended.
 291 *
 292 * Retrieves the configuration of the given device, appending an
 293 * %OVS_VPORT_ATTR_OPTIONS attribute that in turn contains nested
 294 * vport-specific attributes to @skb.
 295 *
 296 * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room, or another
 297 * negative error code if a real error occurred.  If an error occurs, @skb is
 298 * left unmodified.
 299 *
 300 * Must be called with RTNL lock or rcu_read_lock.
 301 */
 302int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
 303{
 304        struct nlattr *nla;
 305
 306        nla = nla_nest_start(skb, OVS_VPORT_ATTR_OPTIONS);
 307        if (!nla)
 308                return -EMSGSIZE;
 309
 310        if (vport->ops->get_options) {
 311                int err = vport->ops->get_options(vport, skb);
 312                if (err) {
 313                        nla_nest_cancel(skb, nla);
 314                        return err;
 315                }
 316        }
 317
 318        nla_nest_end(skb, nla);
 319        return 0;
 320}
 321
 322/**
 323 *      ovs_vport_receive - pass up received packet to the datapath for processing
 324 *
 325 * @vport: vport that received the packet
 326 * @skb: skb that was received
 327 *
 328 * Must be called with rcu_read_lock.  The packet cannot be shared and
 329 * skb->data should point to the Ethernet header.  The caller must have already
 330 * called compute_ip_summed() to initialize the checksumming fields.
 331 */
 332void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
 333{
 334        struct vport_percpu_stats *stats;
 335
 336        stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
 337
 338        u64_stats_update_begin(&stats->sync);
 339        stats->rx_packets++;
 340        stats->rx_bytes += skb->len;
 341        u64_stats_update_end(&stats->sync);
 342
 343        ovs_dp_process_received_packet(vport, skb);
 344}
 345
 346/**
 347 *      ovs_vport_send - send a packet on a device
 348 *
 349 * @vport: vport on which to send the packet
 350 * @skb: skb to send
 351 *
 352 * Sends the given packet and returns the length of data sent.  Either RTNL
 353 * lock or rcu_read_lock must be held.
 354 */
 355int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
 356{
 357        int sent = vport->ops->send(vport, skb);
 358
 359        if (likely(sent)) {
 360                struct vport_percpu_stats *stats;
 361
 362                stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
 363
 364                u64_stats_update_begin(&stats->sync);
 365                stats->tx_packets++;
 366                stats->tx_bytes += sent;
 367                u64_stats_update_end(&stats->sync);
 368        }
 369        return sent;
 370}
 371
 372/**
 373 *      ovs_vport_record_error - indicate device error to generic stats layer
 374 *
 375 * @vport: vport that encountered the error
 376 * @err_type: one of enum vport_err_type types to indicate the error type
 377 *
 378 * If using the vport generic stats layer indicate that an error of the given
 379 * type has occured.
 380 */
 381void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type)
 382{
 383        spin_lock(&vport->stats_lock);
 384
 385        switch (err_type) {
 386        case VPORT_E_RX_DROPPED:
 387                vport->err_stats.rx_dropped++;
 388                break;
 389
 390        case VPORT_E_RX_ERROR:
 391                vport->err_stats.rx_errors++;
 392                break;
 393
 394        case VPORT_E_TX_DROPPED:
 395                vport->err_stats.tx_dropped++;
 396                break;
 397
 398        case VPORT_E_TX_ERROR:
 399                vport->err_stats.tx_errors++;
 400                break;
 401        }
 402
 403        spin_unlock(&vport->stats_lock);
 404}
 405
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.