at v3.10 7.1 kB view raw
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 14#include <linux/netpoll.h> 15#include <net/sch_generic.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 long mode_priv[0]; 73}; 74 75static inline bool team_port_enabled(struct team_port *port) 76{ 77 return port->index != -1; 78} 79 80static inline bool team_port_txable(struct team_port *port) 81{ 82 return port->linkup && team_port_enabled(port); 83} 84 85#ifdef CONFIG_NET_POLL_CONTROLLER 86static inline void team_netpoll_send_skb(struct team_port *port, 87 struct sk_buff *skb) 88{ 89 struct netpoll *np = port->np; 90 91 if (np) 92 netpoll_send_skb(np, skb); 93} 94#else 95static inline void team_netpoll_send_skb(struct team_port *port, 96 struct sk_buff *skb) 97{ 98} 99#endif 100 101struct team_mode_ops { 102 int (*init)(struct team *team); 103 void (*exit)(struct team *team); 104 rx_handler_result_t (*receive)(struct team *team, 105 struct team_port *port, 106 struct sk_buff *skb); 107 bool (*transmit)(struct team *team, struct sk_buff *skb); 108 int (*port_enter)(struct team *team, struct team_port *port); 109 void (*port_leave)(struct team *team, struct team_port *port); 110 void (*port_change_dev_addr)(struct team *team, struct team_port *port); 111 void (*port_enabled)(struct team *team, struct team_port *port); 112 void (*port_disabled)(struct team *team, struct team_port *port); 113}; 114 115extern int team_modeop_port_enter(struct team *team, struct team_port *port); 116extern void team_modeop_port_change_dev_addr(struct team *team, 117 struct team_port *port); 118 119enum team_option_type { 120 TEAM_OPTION_TYPE_U32, 121 TEAM_OPTION_TYPE_STRING, 122 TEAM_OPTION_TYPE_BINARY, 123 TEAM_OPTION_TYPE_BOOL, 124 TEAM_OPTION_TYPE_S32, 125}; 126 127struct team_option_inst_info { 128 u32 array_index; 129 struct team_port *port; /* != NULL if per-port */ 130}; 131 132struct team_gsetter_ctx { 133 union { 134 u32 u32_val; 135 const char *str_val; 136 struct { 137 const void *ptr; 138 u32 len; 139 } bin_val; 140 bool bool_val; 141 s32 s32_val; 142 } data; 143 struct team_option_inst_info *info; 144}; 145 146struct team_option { 147 struct list_head list; 148 const char *name; 149 bool per_port; 150 unsigned int array_size; /* != 0 means the option is array */ 151 enum team_option_type type; 152 int (*init)(struct team *team, struct team_option_inst_info *info); 153 int (*getter)(struct team *team, struct team_gsetter_ctx *ctx); 154 int (*setter)(struct team *team, struct team_gsetter_ctx *ctx); 155}; 156 157extern void team_option_inst_set_change(struct team_option_inst_info *opt_inst_info); 158extern void team_options_change_check(struct team *team); 159 160struct team_mode { 161 const char *kind; 162 struct module *owner; 163 size_t priv_size; 164 size_t port_priv_size; 165 const struct team_mode_ops *ops; 166}; 167 168#define TEAM_PORT_HASHBITS 4 169#define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS) 170 171#define TEAM_MODE_PRIV_LONGS 4 172#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS) 173 174struct team { 175 struct net_device *dev; /* associated netdevice */ 176 struct team_pcpu_stats __percpu *pcpu_stats; 177 178 struct mutex lock; /* used for overall locking, e.g. port lists write */ 179 180 /* 181 * List of enabled ports and their count 182 */ 183 int en_port_count; 184 struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES]; 185 186 struct list_head port_list; /* list of all ports */ 187 188 struct list_head option_list; 189 struct list_head option_inst_list; /* list of option instances */ 190 191 const struct team_mode *mode; 192 struct team_mode_ops ops; 193 bool user_carrier_enabled; 194 bool queue_override_enabled; 195 struct list_head *qom_lists; /* array of queue override mapping lists */ 196 long mode_priv[TEAM_MODE_PRIV_LONGS]; 197}; 198 199static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, 200 struct sk_buff *skb) 201{ 202 BUILD_BUG_ON(sizeof(skb->queue_mapping) != 203 sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); 204 skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); 205 206 skb->dev = port->dev; 207 if (unlikely(netpoll_tx_running(team->dev))) { 208 team_netpoll_send_skb(port, skb); 209 return 0; 210 } 211 return dev_queue_xmit(skb); 212} 213 214static inline struct hlist_head *team_port_index_hash(struct team *team, 215 int port_index) 216{ 217 return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; 218} 219 220static inline struct team_port *team_get_port_by_index(struct team *team, 221 int port_index) 222{ 223 struct team_port *port; 224 struct hlist_head *head = team_port_index_hash(team, port_index); 225 226 hlist_for_each_entry(port, head, hlist) 227 if (port->index == port_index) 228 return port; 229 return NULL; 230} 231static inline struct team_port *team_get_port_by_index_rcu(struct team *team, 232 int port_index) 233{ 234 struct team_port *port; 235 struct hlist_head *head = team_port_index_hash(team, port_index); 236 237 hlist_for_each_entry_rcu(port, head, hlist) 238 if (port->index == port_index) 239 return port; 240 return NULL; 241} 242 243static inline struct team_port * 244team_get_first_port_txable_rcu(struct team *team, struct team_port *port) 245{ 246 struct team_port *cur; 247 248 if (likely(team_port_txable(port))) 249 return port; 250 cur = port; 251 list_for_each_entry_continue_rcu(cur, &team->port_list, list) 252 if (team_port_txable(cur)) 253 return cur; 254 list_for_each_entry_rcu(cur, &team->port_list, list) { 255 if (cur == port) 256 break; 257 if (team_port_txable(cur)) 258 return cur; 259 } 260 return NULL; 261} 262 263extern int team_options_register(struct team *team, 264 const struct team_option *option, 265 size_t option_count); 266extern void team_options_unregister(struct team *team, 267 const struct team_option *option, 268 size_t option_count); 269extern int team_mode_register(const struct team_mode *mode); 270extern void team_mode_unregister(const struct team_mode *mode); 271 272#define TEAM_DEFAULT_NUM_TX_QUEUES 16 273#define TEAM_DEFAULT_NUM_RX_QUEUES 16 274 275#endif /* _LINUX_IF_TEAM_H_ */