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