linux/include/linux/if_team.h
<<
>>
Prefs
   1/*
   2 * include/linux/if_team.h - Network team device driver header
   3 * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 */
  10#ifndef _LINUX_IF_TEAM_H_
  11#define _LINUX_IF_TEAM_H_
  12
  13#include <linux/netpoll.h>
  14#include <net/sch_generic.h>
  15#include <linux/types.h>
  16#include <uapi/linux/if_team.h>
  17
  18struct team_pcpu_stats {
  19        u64                     rx_packets;
  20        u64                     rx_bytes;
  21        u64                     rx_multicast;
  22        u64                     tx_packets;
  23        u64                     tx_bytes;
  24        struct u64_stats_sync   syncp;
  25        u32                     rx_dropped;
  26        u32                     tx_dropped;
  27};
  28
  29struct team;
  30
  31struct team_port {
  32        struct net_device *dev;
  33        struct hlist_node hlist; /* node in enabled ports hash list */
  34        struct list_head list; /* node in ordinary list */
  35        struct team *team;
  36        int index; /* index of enabled port. If disabled, it's set to -1 */
  37
  38        bool linkup; /* either state.linkup or user.linkup */
  39
  40        struct {
  41                bool linkup;
  42                u32 speed;
  43                u8 duplex;
  44        } state;
  45
  46        /* Values set by userspace */
  47        struct {
  48                bool linkup;
  49                bool linkup_enabled;
  50        } user;
  51
  52        /* Custom gennetlink interface related flags */
  53        bool changed;
  54        bool removed;
  55
  56        /*
  57         * A place for storing original values of the device before it
  58         * become a port.
  59         */
  60        struct {
  61                unsigned char dev_addr[MAX_ADDR_LEN];
  62                unsigned int mtu;
  63        } orig;
  64
  65#ifdef CONFIG_NET_POLL_CONTROLLER
  66        struct netpoll *np;
  67#endif
  68
  69        s32 priority; /* lower number ~ higher priority */
  70        u16 queue_id;
  71        struct list_head qom_list; /* node in queue override mapping list */
  72        struct rcu_head rcu;
  73        long mode_priv[0];
  74};
  75
  76static inline bool team_port_enabled(struct team_port *port)
  77{
  78        return port->index != -1;
  79}
  80
  81static inline bool team_port_txable(struct team_port *port)
  82{
  83        return port->linkup && team_port_enabled(port);
  84}
  85
  86#ifdef CONFIG_NET_POLL_CONTROLLER
  87static inline void team_netpoll_send_skb(struct team_port *port,
  88                                         struct sk_buff *skb)
  89{
  90        struct netpoll *np = port->np;
  91
  92        if (np)
  93                netpoll_send_skb(np, skb);
  94}
  95#else
  96static inline void team_netpoll_send_skb(struct team_port *port,
  97                                         struct sk_buff *skb)
  98{
  99}
 100#endif
 101
 102struct team_mode_ops {
 103        int (*init)(struct team *team);
 104        void (*exit)(struct team *team);
 105        rx_handler_result_t (*receive)(struct team *team,
 106                                       struct team_port *port,
 107                                       struct sk_buff *skb);
 108        bool (*transmit)(struct team *team, struct sk_buff *skb);
 109        int (*port_enter)(struct team *team, struct team_port *port);
 110        void (*port_leave)(struct team *team, struct team_port *port);
 111        void (*port_change_dev_addr)(struct team *team, struct team_port *port);
 112        void (*port_enabled)(struct team *team, struct team_port *port);
 113        void (*port_disabled)(struct team *team, struct team_port *port);
 114};
 115
 116extern int team_modeop_port_enter(struct team *team, struct team_port *port);
 117extern void team_modeop_port_change_dev_addr(struct team *team,
 118                                             struct team_port *port);
 119
 120enum team_option_type {
 121        TEAM_OPTION_TYPE_U32,
 122        TEAM_OPTION_TYPE_STRING,
 123        TEAM_OPTION_TYPE_BINARY,
 124        TEAM_OPTION_TYPE_BOOL,
 125        TEAM_OPTION_TYPE_S32,
 126};
 127
 128struct team_option_inst_info {
 129        u32 array_index;
 130        struct team_port *port; /* != NULL if per-port */
 131};
 132
 133struct team_gsetter_ctx {
 134        union {
 135                u32 u32_val;
 136                const char *str_val;
 137                struct {
 138                        const void *ptr;
 139                        u32 len;
 140                } bin_val;
 141                bool bool_val;
 142                s32 s32_val;
 143        } data;
 144        struct team_option_inst_info *info;
 145};
 146
 147struct team_option {
 148        struct list_head list;
 149        const char *name;
 150        bool per_port;
 151        unsigned int array_size; /* != 0 means the option is array */
 152        enum team_option_type type;
 153        int (*init)(struct team *team, struct team_option_inst_info *info);
 154        int (*getter)(struct team *team, struct team_gsetter_ctx *ctx);
 155        int (*setter)(struct team *team, struct team_gsetter_ctx *ctx);
 156};
 157
 158extern void team_option_inst_set_change(struct team_option_inst_info *opt_inst_info);
 159extern void team_options_change_check(struct team *team);
 160
 161struct team_mode {
 162        const char *kind;
 163        struct module *owner;
 164        size_t priv_size;
 165        size_t port_priv_size;
 166        const struct team_mode_ops *ops;
 167};
 168
 169#define TEAM_PORT_HASHBITS 4
 170#define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS)
 171
 172#define TEAM_MODE_PRIV_LONGS 4
 173#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS)
 174
 175struct team {
 176        struct net_device *dev; /* associated netdevice */
 177        struct team_pcpu_stats __percpu *pcpu_stats;
 178
 179        struct mutex lock; /* used for overall locking, e.g. port lists write */
 180
 181        /*
 182         * List of enabled ports and their count
 183         */
 184        int en_port_count;
 185        struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES];
 186
 187        struct list_head port_list; /* list of all ports */
 188
 189        struct list_head option_list;
 190        struct list_head option_inst_list; /* list of option instances */
 191
 192        const struct team_mode *mode;
 193        struct team_mode_ops ops;
 194        bool user_carrier_enabled;
 195        bool queue_override_enabled;
 196        struct list_head *qom_lists; /* array of queue override mapping lists */
 197        struct {
 198                unsigned int count;
 199                unsigned int interval; /* in ms */
 200                atomic_t count_pending;
 201                struct delayed_work dw;
 202        } notify_peers;
 203        struct {
 204                unsigned int count;
 205                unsigned int interval; /* in ms */
 206                atomic_t count_pending;
 207                struct delayed_work dw;
 208        } mcast_rejoin;
 209        long mode_priv[TEAM_MODE_PRIV_LONGS];
 210};
 211
 212static inline int team_dev_queue_xmit(struct team *team, struct team_port *port,
 213                                      struct sk_buff *skb)
 214{
 215        BUILD_BUG_ON(sizeof(skb->queue_mapping) !=
 216                     sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping));
 217        skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping);
 218
 219        skb->dev = port->dev;
 220        if (unlikely(netpoll_tx_running(team->dev))) {
 221                team_netpoll_send_skb(port, skb);
 222                return 0;
 223        }
 224        return dev_queue_xmit(skb);
 225}
 226
 227static inline struct hlist_head *team_port_index_hash(struct team *team,
 228                                                      int port_index)
 229{
 230        return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)];
 231}
 232
 233static inline struct team_port *team_get_port_by_index(struct team *team,
 234                                                       int port_index)
 235{
 236        struct team_port *port;
 237        struct hlist_head *head = team_port_index_hash(team, port_index);
 238
 239        hlist_for_each_entry(port, head, hlist)
 240                if (port->index == port_index)
 241                        return port;
 242        return NULL;
 243}
 244
 245static inline int team_num_to_port_index(struct team *team, int num)
 246{
 247        int en_port_count = ACCESS_ONCE(team->en_port_count);
 248
 249        if (unlikely(!en_port_count))
 250                return 0;
 251        return num % en_port_count;
 252}
 253
 254static inline struct team_port *team_get_port_by_index_rcu(struct team *team,
 255                                                           int port_index)
 256{
 257        struct team_port *port;
 258        struct hlist_head *head = team_port_index_hash(team, port_index);
 259
 260        hlist_for_each_entry_rcu(port, head, hlist)
 261                if (port->index == port_index)
 262                        return port;
 263        return NULL;
 264}
 265
 266static inline struct team_port *
 267team_get_first_port_txable_rcu(struct team *team, struct team_port *port)
 268{
 269        struct team_port *cur;
 270
 271        if (likely(team_port_txable(port)))
 272                return port;
 273        cur = port;
 274        list_for_each_entry_continue_rcu(cur, &team->port_list, list)
 275                if (team_port_txable(cur))
 276                        return cur;
 277        list_for_each_entry_rcu(cur, &team->port_list, list) {
 278                if (cur == port)
 279                        break;
 280                if (team_port_txable(cur))
 281                        return cur;
 282        }
 283        return NULL;
 284}
 285
 286extern int team_options_register(struct team *team,
 287                                 const struct team_option *option,
 288                                 size_t option_count);
 289extern void team_options_unregister(struct team *team,
 290                                    const struct team_option *option,
 291                                    size_t option_count);
 292extern int team_mode_register(const struct team_mode *mode);
 293extern void team_mode_unregister(const struct team_mode *mode);
 294
 295#define TEAM_DEFAULT_NUM_TX_QUEUES 16
 296#define TEAM_DEFAULT_NUM_RX_QUEUES 16
 297
 298#endif /* _LINUX_IF_TEAM_H_ */
 299