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