at v3.6 8.4 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 11#ifndef _LINUX_IF_TEAM_H_ 12#define _LINUX_IF_TEAM_H_ 13 14#ifdef __KERNEL__ 15 16#include <linux/netpoll.h> 17#include <net/sch_generic.h> 18 19struct team_pcpu_stats { 20 u64 rx_packets; 21 u64 rx_bytes; 22 u64 rx_multicast; 23 u64 tx_packets; 24 u64 tx_bytes; 25 struct u64_stats_sync syncp; 26 u32 rx_dropped; 27 u32 tx_dropped; 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 long mode_priv[0]; 71}; 72 73static inline bool team_port_enabled(struct team_port *port) 74{ 75 return port->index != -1; 76} 77 78static inline bool team_port_txable(struct team_port *port) 79{ 80 return port->linkup && team_port_enabled(port); 81} 82 83#ifdef CONFIG_NET_POLL_CONTROLLER 84static inline void team_netpoll_send_skb(struct team_port *port, 85 struct sk_buff *skb) 86{ 87 struct netpoll *np = port->np; 88 89 if (np) 90 netpoll_send_skb(np, skb); 91} 92#else 93static inline void team_netpoll_send_skb(struct team_port *port, 94 struct sk_buff *skb) 95{ 96} 97#endif 98 99struct team_mode_ops { 100 int (*init)(struct team *team); 101 void (*exit)(struct team *team); 102 rx_handler_result_t (*receive)(struct team *team, 103 struct team_port *port, 104 struct sk_buff *skb); 105 bool (*transmit)(struct team *team, struct sk_buff *skb); 106 int (*port_enter)(struct team *team, struct team_port *port); 107 void (*port_leave)(struct team *team, struct team_port *port); 108 void (*port_change_mac)(struct team *team, struct team_port *port); 109 void (*port_enabled)(struct team *team, struct team_port *port); 110 void (*port_disabled)(struct team *team, struct team_port *port); 111}; 112 113enum team_option_type { 114 TEAM_OPTION_TYPE_U32, 115 TEAM_OPTION_TYPE_STRING, 116 TEAM_OPTION_TYPE_BINARY, 117 TEAM_OPTION_TYPE_BOOL, 118}; 119 120struct team_option_inst_info { 121 u32 array_index; 122 struct team_port *port; /* != NULL if per-port */ 123}; 124 125struct team_gsetter_ctx { 126 union { 127 u32 u32_val; 128 const char *str_val; 129 struct { 130 const void *ptr; 131 u32 len; 132 } bin_val; 133 bool bool_val; 134 } data; 135 struct team_option_inst_info *info; 136}; 137 138struct team_option { 139 struct list_head list; 140 const char *name; 141 bool per_port; 142 unsigned int array_size; /* != 0 means the option is array */ 143 enum team_option_type type; 144 int (*init)(struct team *team, struct team_option_inst_info *info); 145 int (*getter)(struct team *team, struct team_gsetter_ctx *ctx); 146 int (*setter)(struct team *team, struct team_gsetter_ctx *ctx); 147}; 148 149extern void team_option_inst_set_change(struct team_option_inst_info *opt_inst_info); 150extern void team_options_change_check(struct team *team); 151 152struct team_mode { 153 const char *kind; 154 struct module *owner; 155 size_t priv_size; 156 size_t port_priv_size; 157 const struct team_mode_ops *ops; 158}; 159 160#define TEAM_PORT_HASHBITS 4 161#define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS) 162 163#define TEAM_MODE_PRIV_LONGS 4 164#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS) 165 166struct team { 167 struct net_device *dev; /* associated netdevice */ 168 struct team_pcpu_stats __percpu *pcpu_stats; 169 170 struct mutex lock; /* used for overall locking, e.g. port lists write */ 171 172 /* 173 * List of enabled ports and their count 174 */ 175 int en_port_count; 176 struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES]; 177 178 struct list_head port_list; /* list of all ports */ 179 180 struct list_head option_list; 181 struct list_head option_inst_list; /* list of option instances */ 182 183 const struct team_mode *mode; 184 struct team_mode_ops ops; 185 long mode_priv[TEAM_MODE_PRIV_LONGS]; 186}; 187 188static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, 189 struct sk_buff *skb) 190{ 191 BUILD_BUG_ON(sizeof(skb->queue_mapping) != 192 sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); 193 skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); 194 195 skb->dev = port->dev; 196 if (unlikely(netpoll_tx_running(team->dev))) { 197 team_netpoll_send_skb(port, skb); 198 return 0; 199 } 200 return dev_queue_xmit(skb); 201} 202 203static inline struct hlist_head *team_port_index_hash(struct team *team, 204 int port_index) 205{ 206 return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; 207} 208 209static inline struct team_port *team_get_port_by_index(struct team *team, 210 int port_index) 211{ 212 struct hlist_node *p; 213 struct team_port *port; 214 struct hlist_head *head = team_port_index_hash(team, port_index); 215 216 hlist_for_each_entry(port, p, head, hlist) 217 if (port->index == port_index) 218 return port; 219 return NULL; 220} 221static inline struct team_port *team_get_port_by_index_rcu(struct team *team, 222 int port_index) 223{ 224 struct hlist_node *p; 225 struct team_port *port; 226 struct hlist_head *head = team_port_index_hash(team, port_index); 227 228 hlist_for_each_entry_rcu(port, p, head, hlist) 229 if (port->index == port_index) 230 return port; 231 return NULL; 232} 233 234extern int team_port_set_team_mac(struct team_port *port); 235extern int team_options_register(struct team *team, 236 const struct team_option *option, 237 size_t option_count); 238extern void team_options_unregister(struct team *team, 239 const struct team_option *option, 240 size_t option_count); 241extern int team_mode_register(const struct team_mode *mode); 242extern void team_mode_unregister(const struct team_mode *mode); 243 244#define TEAM_DEFAULT_NUM_TX_QUEUES 16 245#define TEAM_DEFAULT_NUM_RX_QUEUES 16 246 247#endif /* __KERNEL__ */ 248 249#define TEAM_STRING_MAX_LEN 32 250 251/********************************** 252 * NETLINK_GENERIC netlink family. 253 **********************************/ 254 255enum { 256 TEAM_CMD_NOOP, 257 TEAM_CMD_OPTIONS_SET, 258 TEAM_CMD_OPTIONS_GET, 259 TEAM_CMD_PORT_LIST_GET, 260 261 __TEAM_CMD_MAX, 262 TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1), 263}; 264 265enum { 266 TEAM_ATTR_UNSPEC, 267 TEAM_ATTR_TEAM_IFINDEX, /* u32 */ 268 TEAM_ATTR_LIST_OPTION, /* nest */ 269 TEAM_ATTR_LIST_PORT, /* nest */ 270 271 __TEAM_ATTR_MAX, 272 TEAM_ATTR_MAX = __TEAM_ATTR_MAX - 1, 273}; 274 275/* Nested layout of get/set msg: 276 * 277 * [TEAM_ATTR_LIST_OPTION] 278 * [TEAM_ATTR_ITEM_OPTION] 279 * [TEAM_ATTR_OPTION_*], ... 280 * [TEAM_ATTR_ITEM_OPTION] 281 * [TEAM_ATTR_OPTION_*], ... 282 * ... 283 * [TEAM_ATTR_LIST_PORT] 284 * [TEAM_ATTR_ITEM_PORT] 285 * [TEAM_ATTR_PORT_*], ... 286 * [TEAM_ATTR_ITEM_PORT] 287 * [TEAM_ATTR_PORT_*], ... 288 * ... 289 */ 290 291enum { 292 TEAM_ATTR_ITEM_OPTION_UNSPEC, 293 TEAM_ATTR_ITEM_OPTION, /* nest */ 294 295 __TEAM_ATTR_ITEM_OPTION_MAX, 296 TEAM_ATTR_ITEM_OPTION_MAX = __TEAM_ATTR_ITEM_OPTION_MAX - 1, 297}; 298 299enum { 300 TEAM_ATTR_OPTION_UNSPEC, 301 TEAM_ATTR_OPTION_NAME, /* string */ 302 TEAM_ATTR_OPTION_CHANGED, /* flag */ 303 TEAM_ATTR_OPTION_TYPE, /* u8 */ 304 TEAM_ATTR_OPTION_DATA, /* dynamic */ 305 TEAM_ATTR_OPTION_REMOVED, /* flag */ 306 TEAM_ATTR_OPTION_PORT_IFINDEX, /* u32 */ /* for per-port options */ 307 TEAM_ATTR_OPTION_ARRAY_INDEX, /* u32 */ /* for array options */ 308 309 __TEAM_ATTR_OPTION_MAX, 310 TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, 311}; 312 313enum { 314 TEAM_ATTR_ITEM_PORT_UNSPEC, 315 TEAM_ATTR_ITEM_PORT, /* nest */ 316 317 __TEAM_ATTR_ITEM_PORT_MAX, 318 TEAM_ATTR_ITEM_PORT_MAX = __TEAM_ATTR_ITEM_PORT_MAX - 1, 319}; 320 321enum { 322 TEAM_ATTR_PORT_UNSPEC, 323 TEAM_ATTR_PORT_IFINDEX, /* u32 */ 324 TEAM_ATTR_PORT_CHANGED, /* flag */ 325 TEAM_ATTR_PORT_LINKUP, /* flag */ 326 TEAM_ATTR_PORT_SPEED, /* u32 */ 327 TEAM_ATTR_PORT_DUPLEX, /* u8 */ 328 TEAM_ATTR_PORT_REMOVED, /* flag */ 329 330 __TEAM_ATTR_PORT_MAX, 331 TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1, 332}; 333 334/* 335 * NETLINK_GENERIC related info 336 */ 337#define TEAM_GENL_NAME "team" 338#define TEAM_GENL_VERSION 0x1 339#define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event" 340 341#endif /* _LINUX_IF_TEAM_H_ */