1 /* 2 * include/linux/if_team.h - Network team device driver header 3 * Copyright (c) 2011 Jiri Pirko <[email protected]> 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 struct team_pcpu_stats { 17 u64 rx_packets; 18 u64 rx_bytes; 19 u64 rx_multicast; 20 u64 tx_packets; 21 u64 tx_bytes; 22 struct u64_stats_sync syncp; 23 u32 rx_dropped; 24 u32 tx_dropped; 25 }; 26 27 struct team; 28 29 struct team_port { 30 struct net_device *dev; 31 struct hlist_node hlist; /* node in enabled ports hash list */ 32 struct list_head list; /* node in ordinary list */ 33 struct team *team; 34 int index; /* index of enabled port. If disabled, it's set to -1 */ 35 36 bool linkup; /* either state.linkup or user.linkup */ 37 38 struct { 39 bool linkup; 40 u32 speed; 41 u8 duplex; 42 } state; 43 44 /* Values set by userspace */ 45 struct { 46 bool linkup; 47 bool linkup_enabled; 48 } user; 49 50 /* Custom gennetlink interface related flags */ 51 bool changed; 52 bool removed; 53 54 /* 55 * A place for storing original values of the device before it 56 * become a port. 57 */ 58 struct { 59 unsigned char dev_addr[MAX_ADDR_LEN]; 60 unsigned int mtu; 61 } orig; 62 63 struct rcu_head rcu; 64 long mode_priv[0]; 65 }; 66 67 struct team_mode_ops { 68 int (*init)(struct team *team); 69 void (*exit)(struct team *team); 70 rx_handler_result_t (*receive)(struct team *team, 71 struct team_port *port, 72 struct sk_buff *skb); 73 bool (*transmit)(struct team *team, struct sk_buff *skb); 74 int (*port_enter)(struct team *team, struct team_port *port); 75 void (*port_leave)(struct team *team, struct team_port *port); 76 void (*port_change_mac)(struct team *team, struct team_port *port); 77 void (*port_enabled)(struct team *team, struct team_port *port); 78 void (*port_disabled)(struct team *team, struct team_port *port); 79 }; 80 81 enum team_option_type { 82 TEAM_OPTION_TYPE_U32, 83 TEAM_OPTION_TYPE_STRING, 84 TEAM_OPTION_TYPE_BINARY, 85 TEAM_OPTION_TYPE_BOOL, 86 }; 87 88 struct team_option_inst_info { 89 u32 array_index; 90 struct team_port *port; /* != NULL if per-port */ 91 }; 92 93 struct team_gsetter_ctx { 94 union { 95 u32 u32_val; 96 const char *str_val; 97 struct { 98 const void *ptr; 99 u32 len; 100 } bin_val; 101 bool bool_val; 102 } data; 103 struct team_option_inst_info *info; 104 }; 105 106 struct team_option { 107 struct list_head list; 108 const char *name; 109 bool per_port; 110 unsigned int array_size; /* != 0 means the option is array */ 111 enum team_option_type type; 112 int (*init)(struct team *team, struct team_option_inst_info *info); 113 int (*getter)(struct team *team, struct team_gsetter_ctx *ctx); 114 int (*setter)(struct team *team, struct team_gsetter_ctx *ctx); 115 }; 116 117 extern void team_option_inst_set_change(struct team_option_inst_info *opt_inst_info); 118 extern void team_options_change_check(struct team *team); 119 120 struct team_mode { 121 const char *kind; 122 struct module *owner; 123 size_t priv_size; 124 size_t port_priv_size; 125 const struct team_mode_ops *ops; 126 }; 127 128 #define TEAM_PORT_HASHBITS 4 129 #define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS) 130 131 #define TEAM_MODE_PRIV_LONGS 4 132 #define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS) 133 134 struct team { 135 struct net_device *dev; /* associated netdevice */ 136 struct team_pcpu_stats __percpu *pcpu_stats; 137 138 struct mutex lock; /* used for overall locking, e.g. port lists write */ 139 140 /* 141 * List of enabled ports and their count 142 */ 143 int en_port_count; 144 struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES]; 145 146 struct list_head port_list; /* list of all ports */ 147 148 struct list_head option_list; 149 struct list_head option_inst_list; /* list of option instances */ 150 151 const struct team_mode *mode; 152 struct team_mode_ops ops; 153 long mode_priv[TEAM_MODE_PRIV_LONGS]; 154 }; 155 156 static inline struct hlist_head *team_port_index_hash(struct team *team, 157 int port_index) 158 { 159 return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; 160 } 161 162 static inline struct team_port *team_get_port_by_index(struct team *team, 163 int port_index) 164 { 165 struct hlist_node *p; 166 struct team_port *port; 167 struct hlist_head *head = team_port_index_hash(team, port_index); 168 169 hlist_for_each_entry(port, p, head, hlist) 170 if (port->index == port_index) 171 return port; 172 return NULL; 173 } 174 static inline struct team_port *team_get_port_by_index_rcu(struct team *team, 175 int port_index) 176 { 177 struct hlist_node *p; 178 struct team_port *port; 179 struct hlist_head *head = team_port_index_hash(team, port_index); 180 181 hlist_for_each_entry_rcu(port, p, head, hlist) 182 if (port->index == port_index) 183 return port; 184 return NULL; 185 } 186 187 extern int team_port_set_team_mac(struct team_port *port); 188 extern int team_options_register(struct team *team, 189 const struct team_option *option, 190 size_t option_count); 191 extern void team_options_unregister(struct team *team, 192 const struct team_option *option, 193 size_t option_count); 194 extern int team_mode_register(const struct team_mode *mode); 195 extern void team_mode_unregister(const struct team_mode *mode); 196 197 #endif /* __KERNEL__ */ 198 199 #define TEAM_STRING_MAX_LEN 32 200 201 /********************************** 202 * NETLINK_GENERIC netlink family. 203 **********************************/ 204 205 enum { 206 TEAM_CMD_NOOP, 207 TEAM_CMD_OPTIONS_SET, 208 TEAM_CMD_OPTIONS_GET, 209 TEAM_CMD_PORT_LIST_GET, 210 211 __TEAM_CMD_MAX, 212 TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1), 213 }; 214 215 enum { 216 TEAM_ATTR_UNSPEC, 217 TEAM_ATTR_TEAM_IFINDEX, /* u32 */ 218 TEAM_ATTR_LIST_OPTION, /* nest */ 219 TEAM_ATTR_LIST_PORT, /* nest */ 220 221 __TEAM_ATTR_MAX, 222 TEAM_ATTR_MAX = __TEAM_ATTR_MAX - 1, 223 }; 224 225 /* Nested layout of get/set msg: 226 * 227 * [TEAM_ATTR_LIST_OPTION] 228 * [TEAM_ATTR_ITEM_OPTION] 229 * [TEAM_ATTR_OPTION_*], ... 230 * [TEAM_ATTR_ITEM_OPTION] 231 * [TEAM_ATTR_OPTION_*], ... 232 * ... 233 * [TEAM_ATTR_LIST_PORT] 234 * [TEAM_ATTR_ITEM_PORT] 235 * [TEAM_ATTR_PORT_*], ... 236 * [TEAM_ATTR_ITEM_PORT] 237 * [TEAM_ATTR_PORT_*], ... 238 * ... 239 */ 240 241 enum { 242 TEAM_ATTR_ITEM_OPTION_UNSPEC, 243 TEAM_ATTR_ITEM_OPTION, /* nest */ 244 245 __TEAM_ATTR_ITEM_OPTION_MAX, 246 TEAM_ATTR_ITEM_OPTION_MAX = __TEAM_ATTR_ITEM_OPTION_MAX - 1, 247 }; 248 249 enum { 250 TEAM_ATTR_OPTION_UNSPEC, 251 TEAM_ATTR_OPTION_NAME, /* string */ 252 TEAM_ATTR_OPTION_CHANGED, /* flag */ 253 TEAM_ATTR_OPTION_TYPE, /* u8 */ 254 TEAM_ATTR_OPTION_DATA, /* dynamic */ 255 TEAM_ATTR_OPTION_REMOVED, /* flag */ 256 TEAM_ATTR_OPTION_PORT_IFINDEX, /* u32 */ /* for per-port options */ 257 TEAM_ATTR_OPTION_ARRAY_INDEX, /* u32 */ /* for array options */ 258 259 __TEAM_ATTR_OPTION_MAX, 260 TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, 261 }; 262 263 enum { 264 TEAM_ATTR_ITEM_PORT_UNSPEC, 265 TEAM_ATTR_ITEM_PORT, /* nest */ 266 267 __TEAM_ATTR_ITEM_PORT_MAX, 268 TEAM_ATTR_ITEM_PORT_MAX = __TEAM_ATTR_ITEM_PORT_MAX - 1, 269 }; 270 271 enum { 272 TEAM_ATTR_PORT_UNSPEC, 273 TEAM_ATTR_PORT_IFINDEX, /* u32 */ 274 TEAM_ATTR_PORT_CHANGED, /* flag */ 275 TEAM_ATTR_PORT_LINKUP, /* flag */ 276 TEAM_ATTR_PORT_SPEED, /* u32 */ 277 TEAM_ATTR_PORT_DUPLEX, /* u8 */ 278 TEAM_ATTR_PORT_REMOVED, /* flag */ 279 280 __TEAM_ATTR_PORT_MAX, 281 TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1, 282 }; 283 284 /* 285 * NETLINK_GENERIC related info 286 */ 287 #define TEAM_GENL_NAME "team" 288 #define TEAM_GENL_VERSION 0x1 289 #define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event" 290 291 #endif /* _LINUX_IF_TEAM_H_ */ 292