Merge branch 'fixes-for-arm-soc' of git://sources.calxeda.com/kernel/linux into fixes
[cascardo/linux.git] / include / linux / if_team.h
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 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 hash list */
32         struct list_head list; /* node in ordinary list */
33         struct team *team;
34         int index;
35
36         /*
37          * A place for storing original values of the device before it
38          * become a port.
39          */
40         struct {
41                 unsigned char dev_addr[MAX_ADDR_LEN];
42                 unsigned int mtu;
43         } orig;
44
45         bool linkup;
46         u32 speed;
47         u8 duplex;
48
49         struct rcu_head rcu;
50 };
51
52 struct team_mode_ops {
53         int (*init)(struct team *team);
54         void (*exit)(struct team *team);
55         rx_handler_result_t (*receive)(struct team *team,
56                                        struct team_port *port,
57                                        struct sk_buff *skb);
58         bool (*transmit)(struct team *team, struct sk_buff *skb);
59         int (*port_enter)(struct team *team, struct team_port *port);
60         void (*port_leave)(struct team *team, struct team_port *port);
61         void (*port_change_mac)(struct team *team, struct team_port *port);
62 };
63
64 enum team_option_type {
65         TEAM_OPTION_TYPE_U32,
66         TEAM_OPTION_TYPE_STRING,
67 };
68
69 struct team_option {
70         struct list_head list;
71         const char *name;
72         enum team_option_type type;
73         int (*getter)(struct team *team, void *arg);
74         int (*setter)(struct team *team, void *arg);
75 };
76
77 struct team_mode {
78         struct list_head list;
79         const char *kind;
80         struct module *owner;
81         size_t priv_size;
82         const struct team_mode_ops *ops;
83 };
84
85 #define TEAM_PORT_HASHBITS 4
86 #define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS)
87
88 #define TEAM_MODE_PRIV_LONGS 4
89 #define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS)
90
91 struct team {
92         struct net_device *dev; /* associated netdevice */
93         struct team_pcpu_stats __percpu *pcpu_stats;
94
95         struct mutex lock; /* used for overall locking, e.g. port lists write */
96
97         /*
98          * port lists with port count
99          */
100         int port_count;
101         struct hlist_head port_hlist[TEAM_PORT_HASHENTRIES];
102         struct list_head port_list;
103
104         struct list_head option_list;
105
106         const struct team_mode *mode;
107         struct team_mode_ops ops;
108         long mode_priv[TEAM_MODE_PRIV_LONGS];
109 };
110
111 static inline struct hlist_head *team_port_index_hash(struct team *team,
112                                                       int port_index)
113 {
114         return &team->port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)];
115 }
116
117 static inline struct team_port *team_get_port_by_index(struct team *team,
118                                                        int port_index)
119 {
120         struct hlist_node *p;
121         struct team_port *port;
122         struct hlist_head *head = team_port_index_hash(team, port_index);
123
124         hlist_for_each_entry(port, p, head, hlist)
125                 if (port->index == port_index)
126                         return port;
127         return NULL;
128 }
129 static inline struct team_port *team_get_port_by_index_rcu(struct team *team,
130                                                            int port_index)
131 {
132         struct hlist_node *p;
133         struct team_port *port;
134         struct hlist_head *head = team_port_index_hash(team, port_index);
135
136         hlist_for_each_entry_rcu(port, p, head, hlist)
137                 if (port->index == port_index)
138                         return port;
139         return NULL;
140 }
141
142 extern int team_port_set_team_mac(struct team_port *port);
143 extern int team_options_register(struct team *team,
144                                  const struct team_option *option,
145                                  size_t option_count);
146 extern void team_options_unregister(struct team *team,
147                                     const struct team_option *option,
148                                     size_t option_count);
149 extern int team_mode_register(struct team_mode *mode);
150 extern int team_mode_unregister(struct team_mode *mode);
151
152 #endif /* __KERNEL__ */
153
154 #define TEAM_STRING_MAX_LEN 32
155
156 /**********************************
157  * NETLINK_GENERIC netlink family.
158  **********************************/
159
160 enum {
161         TEAM_CMD_NOOP,
162         TEAM_CMD_OPTIONS_SET,
163         TEAM_CMD_OPTIONS_GET,
164         TEAM_CMD_PORT_LIST_GET,
165
166         __TEAM_CMD_MAX,
167         TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1),
168 };
169
170 enum {
171         TEAM_ATTR_UNSPEC,
172         TEAM_ATTR_TEAM_IFINDEX,         /* u32 */
173         TEAM_ATTR_LIST_OPTION,          /* nest */
174         TEAM_ATTR_LIST_PORT,            /* nest */
175
176         __TEAM_ATTR_MAX,
177         TEAM_ATTR_MAX = __TEAM_ATTR_MAX - 1,
178 };
179
180 /* Nested layout of get/set msg:
181  *
182  *      [TEAM_ATTR_LIST_OPTION]
183  *              [TEAM_ATTR_ITEM_OPTION]
184  *                      [TEAM_ATTR_OPTION_*], ...
185  *              [TEAM_ATTR_ITEM_OPTION]
186  *                      [TEAM_ATTR_OPTION_*], ...
187  *              ...
188  *      [TEAM_ATTR_LIST_PORT]
189  *              [TEAM_ATTR_ITEM_PORT]
190  *                      [TEAM_ATTR_PORT_*], ...
191  *              [TEAM_ATTR_ITEM_PORT]
192  *                      [TEAM_ATTR_PORT_*], ...
193  *              ...
194  */
195
196 enum {
197         TEAM_ATTR_ITEM_OPTION_UNSPEC,
198         TEAM_ATTR_ITEM_OPTION,          /* nest */
199
200         __TEAM_ATTR_ITEM_OPTION_MAX,
201         TEAM_ATTR_ITEM_OPTION_MAX = __TEAM_ATTR_ITEM_OPTION_MAX - 1,
202 };
203
204 enum {
205         TEAM_ATTR_OPTION_UNSPEC,
206         TEAM_ATTR_OPTION_NAME,          /* string */
207         TEAM_ATTR_OPTION_CHANGED,       /* flag */
208         TEAM_ATTR_OPTION_TYPE,          /* u8 */
209         TEAM_ATTR_OPTION_DATA,          /* dynamic */
210
211         __TEAM_ATTR_OPTION_MAX,
212         TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1,
213 };
214
215 enum {
216         TEAM_ATTR_ITEM_PORT_UNSPEC,
217         TEAM_ATTR_ITEM_PORT,            /* nest */
218
219         __TEAM_ATTR_ITEM_PORT_MAX,
220         TEAM_ATTR_ITEM_PORT_MAX = __TEAM_ATTR_ITEM_PORT_MAX - 1,
221 };
222
223 enum {
224         TEAM_ATTR_PORT_UNSPEC,
225         TEAM_ATTR_PORT_IFINDEX,         /* u32 */
226         TEAM_ATTR_PORT_CHANGED,         /* flag */
227         TEAM_ATTR_PORT_LINKUP,          /* flag */
228         TEAM_ATTR_PORT_SPEED,           /* u32 */
229         TEAM_ATTR_PORT_DUPLEX,          /* u8 */
230
231         __TEAM_ATTR_PORT_MAX,
232         TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1,
233 };
234
235 /*
236  * NETLINK_GENERIC related info
237  */
238 #define TEAM_GENL_NAME "team"
239 #define TEAM_GENL_VERSION 0x1
240 #define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event"
241
242 #endif /* _LINUX_IF_TEAM_H_ */