13d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko/*
23d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko * include/linux/if_team.h - Network team device driver header
33d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
43d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko *
53d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko * This program is free software; you can redistribute it and/or modify
63d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko * it under the terms of the GNU General Public License as published by
73d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko * the Free Software Foundation; either version 2 of the License, or
83d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko * (at your option) any later version.
93d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko */
103d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko#ifndef _LINUX_IF_TEAM_H_
113d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko#define _LINUX_IF_TEAM_H_
123d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
13bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko#include <linux/netpoll.h>
146c85f2bdda2086d804e198a3f31b685bc2f86b04Jiri Pirko#include <net/sch_generic.h>
15fc423ff00df3a19554414eed80aef9de9b50313eJiri Pirko#include <linux/types.h>
16607ca46e97a1b6594b29647d98a32d545c24bdffDavid Howells#include <uapi/linux/if_team.h>
17bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko
183d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostruct team_pcpu_stats {
193d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	u64			rx_packets;
203d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	u64			rx_bytes;
213d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	u64			rx_multicast;
223d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	u64			tx_packets;
233d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	u64			tx_bytes;
243d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct u64_stats_sync	syncp;
253d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	u32			rx_dropped;
263d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	u32			tx_dropped;
273d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko};
283d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
293d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostruct team;
303d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
313d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostruct team_port {
323d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct net_device *dev;
3319a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko	struct hlist_node hlist; /* node in enabled ports hash list */
343d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct list_head list; /* node in ordinary list */
353d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct team *team;
3619a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko	int index; /* index of enabled port. If disabled, it's set to -1 */
373d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
3871472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	bool linkup; /* either state.linkup or user.linkup */
3971472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko
4071472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	struct {
4171472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko		bool linkup;
4271472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko		u32 speed;
4371472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko		u8 duplex;
4471472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	} state;
4571472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko
4671472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	/* Values set by userspace */
4771472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	struct {
4871472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko		bool linkup;
4971472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko		bool linkup_enabled;
5071472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	} user;
5171472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko
5271472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	/* Custom gennetlink interface related flags */
5371472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	bool changed;
5471472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko	bool removed;
5571472ec12c61dd305ab4d11822af7ecc4f9717f9Jiri Pirko
563d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	/*
573d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	 * A place for storing original values of the device before it
583d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	 * become a port.
593d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	 */
603d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct {
613d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko		unsigned char dev_addr[MAX_ADDR_LEN];
623d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko		unsigned int mtu;
633d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	} orig;
643d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
65bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko#ifdef CONFIG_NET_POLL_CONTROLLER
66bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko	struct netpoll *np;
67bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko#endif
68bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko
69a86fc6b7d603992070c04bd7a8c217d55688b077Jiri Pirko	s32 priority; /* lower number ~ higher priority */
708ff5105a2b9dd0ba596719b165c1827d101e5f1aJiri Pirko	u16 queue_id;
718ff5105a2b9dd0ba596719b165c1827d101e5f1aJiri Pirko	struct list_head qom_list; /* node in queue override mapping list */
72d80b35beac78b52faad2359adf6a6b14e2725e51Jiri Pirko	struct rcu_head	rcu;
735149ee58385bdfef260fb07a89a8ff0913be6b25Jiri Pirko	long mode_priv[0];
743d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko};
753d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
7668c450426ae665653b06f62539e48727b696496fJiri Pirkostatic inline bool team_port_enabled(struct team_port *port)
7768c450426ae665653b06f62539e48727b696496fJiri Pirko{
7868c450426ae665653b06f62539e48727b696496fJiri Pirko	return port->index != -1;
7968c450426ae665653b06f62539e48727b696496fJiri Pirko}
8068c450426ae665653b06f62539e48727b696496fJiri Pirko
8168c450426ae665653b06f62539e48727b696496fJiri Pirkostatic inline bool team_port_txable(struct team_port *port)
8268c450426ae665653b06f62539e48727b696496fJiri Pirko{
8368c450426ae665653b06f62539e48727b696496fJiri Pirko	return port->linkup && team_port_enabled(port);
8468c450426ae665653b06f62539e48727b696496fJiri Pirko}
8552a4fd77808662a16cd17ad3b0e1ad75e0162d8bJiri Pirko
86bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko#ifdef CONFIG_NET_POLL_CONTROLLER
87bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirkostatic inline void team_netpoll_send_skb(struct team_port *port,
88bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko					 struct sk_buff *skb)
89bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko{
90bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko	struct netpoll *np = port->np;
91bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko
92bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko	if (np)
93bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko		netpoll_send_skb(np, skb);
94bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko}
95bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko#else
96bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirkostatic inline void team_netpoll_send_skb(struct team_port *port,
97bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko					 struct sk_buff *skb)
98bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko{
99bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko}
100bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko#endif
101bd2d0837abc0206ecdd3f6b9fc8c25b55b63c96bJiri Pirko
1023d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostruct team_mode_ops {
1033d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	int (*init)(struct team *team);
1043d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	void (*exit)(struct team *team);
1053d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	rx_handler_result_t (*receive)(struct team *team,
1063d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko				       struct team_port *port,
1073d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko				       struct sk_buff *skb);
1083d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	bool (*transmit)(struct team *team, struct sk_buff *skb);
1093d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	int (*port_enter)(struct team *team, struct team_port *port);
1103d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	void (*port_leave)(struct team *team, struct team_port *port);
1111d76efe1577b4323609b1bcbfafa8b731eda071aJiri Pirko	void (*port_change_dev_addr)(struct team *team, struct team_port *port);
1124bccfd17e1f77593e99d5321c48c704a0a43ab68Jiri Pirko	void (*port_enabled)(struct team *team, struct team_port *port);
1134bccfd17e1f77593e99d5321c48c704a0a43ab68Jiri Pirko	void (*port_disabled)(struct team *team, struct team_port *port);
1143d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko};
1153d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
116acbba0d0f88e2577b9d92b61b136d13f65831a52Jiri Pirkoextern int team_modeop_port_enter(struct team *team, struct team_port *port);
117acbba0d0f88e2577b9d92b61b136d13f65831a52Jiri Pirkoextern void team_modeop_port_change_dev_addr(struct team *team,
118acbba0d0f88e2577b9d92b61b136d13f65831a52Jiri Pirko					     struct team_port *port);
119acbba0d0f88e2577b9d92b61b136d13f65831a52Jiri Pirko
1203d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkoenum team_option_type {
1213d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	TEAM_OPTION_TYPE_U32,
1223d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	TEAM_OPTION_TYPE_STRING,
1232615598fc100451c71b83d06bdf5faead619a40eJiri Pirko	TEAM_OPTION_TYPE_BINARY,
12414f066bab19946545130a7379f420af860a02ae8Jiri Pirko	TEAM_OPTION_TYPE_BOOL,
12569821638b27407d8648cb04de01b06b30a291bdeJiri Pirko	TEAM_OPTION_TYPE_S32,
1263d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko};
1273d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
12885d59a87248de90e3266e10dce99477b60f524c0Jiri Pirkostruct team_option_inst_info {
12985d59a87248de90e3266e10dce99477b60f524c0Jiri Pirko	u32 array_index;
13085d59a87248de90e3266e10dce99477b60f524c0Jiri Pirko	struct team_port *port; /* != NULL if per-port */
13185d59a87248de90e3266e10dce99477b60f524c0Jiri Pirko};
13285d59a87248de90e3266e10dce99477b60f524c0Jiri Pirko
13380f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirkostruct team_gsetter_ctx {
13480f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko	union {
13580f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko		u32 u32_val;
13680f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko		const char *str_val;
13780f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko		struct {
13880f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko			const void *ptr;
13980f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko			u32 len;
14080f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko		} bin_val;
14114f066bab19946545130a7379f420af860a02ae8Jiri Pirko		bool bool_val;
14269821638b27407d8648cb04de01b06b30a291bdeJiri Pirko		s32 s32_val;
14380f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko	} data;
14485d59a87248de90e3266e10dce99477b60f524c0Jiri Pirko	struct team_option_inst_info *info;
14580f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko};
14680f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko
1473d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostruct team_option {
1483d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct list_head list;
1493d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	const char *name;
15080f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko	bool per_port;
151b13033262d2496e271444d5a09226a2be5ceb989Jiri Pirko	unsigned int array_size; /* != 0 means the option is array */
1523d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	enum team_option_type type;
15385d59a87248de90e3266e10dce99477b60f524c0Jiri Pirko	int (*init)(struct team *team, struct team_option_inst_info *info);
15480f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko	int (*getter)(struct team *team, struct team_gsetter_ctx *ctx);
15580f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko	int (*setter)(struct team *team, struct team_gsetter_ctx *ctx);
1563d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko};
1573d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
1580f1aad2b7f01d88782fbf4ab08b13a7d92b9b6b2Jiri Pirkoextern void team_option_inst_set_change(struct team_option_inst_info *opt_inst_info);
1590f1aad2b7f01d88782fbf4ab08b13a7d92b9b6b2Jiri Pirkoextern void team_options_change_check(struct team *team);
1600f1aad2b7f01d88782fbf4ab08b13a7d92b9b6b2Jiri Pirko
1613d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostruct team_mode {
1623d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	const char *kind;
1633d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct module *owner;
1643d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	size_t priv_size;
1655149ee58385bdfef260fb07a89a8ff0913be6b25Jiri Pirko	size_t port_priv_size;
1663d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	const struct team_mode_ops *ops;
1673d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko};
1683d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
1693d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko#define TEAM_PORT_HASHBITS 4
1703d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko#define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS)
1713d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
1723d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko#define TEAM_MODE_PRIV_LONGS 4
1733d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS)
1743d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
1753d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostruct team {
1763d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct net_device *dev; /* associated netdevice */
1773d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct team_pcpu_stats __percpu *pcpu_stats;
1783d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
17961dc3461b9549bc10a2f16d254250680cadafcceJiri Pirko	struct mutex lock; /* used for overall locking, e.g. port lists write */
1803d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
1813d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	/*
18219a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko	 * List of enabled ports and their count
1833d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	 */
18419a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko	int en_port_count;
18519a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko	struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES];
18619a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko
18719a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko	struct list_head port_list; /* list of all ports */
1883d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
1893d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct list_head option_list;
19080f7c6683fe0e891ef1db7c967d538b5fdddd22cJiri Pirko	struct list_head option_inst_list; /* list of option instances */
1913d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
1923d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	const struct team_mode *mode;
1933d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct team_mode_ops ops;
194e185483e6b84c127d0b1c890b6b703701ae52d35Flavio Leitner	bool user_carrier_enabled;
1958ff5105a2b9dd0ba596719b165c1827d101e5f1aJiri Pirko	bool queue_override_enabled;
1968ff5105a2b9dd0ba596719b165c1827d101e5f1aJiri Pirko	struct list_head *qom_lists; /* array of queue override mapping lists */
1979d0d68faea6962d62dd501cd6e71ce5cc8ed262bJiri Pirko	bool port_mtu_change_allowed;
198fc423ff00df3a19554414eed80aef9de9b50313eJiri Pirko	struct {
199fc423ff00df3a19554414eed80aef9de9b50313eJiri Pirko		unsigned int count;
200fc423ff00df3a19554414eed80aef9de9b50313eJiri Pirko		unsigned int interval; /* in ms */
201fc423ff00df3a19554414eed80aef9de9b50313eJiri Pirko		atomic_t count_pending;
202fc423ff00df3a19554414eed80aef9de9b50313eJiri Pirko		struct delayed_work dw;
203fc423ff00df3a19554414eed80aef9de9b50313eJiri Pirko	} notify_peers;
204492b200efdd20b8fcfdac873f3cd8d4902386581Jiri Pirko	struct {
205492b200efdd20b8fcfdac873f3cd8d4902386581Jiri Pirko		unsigned int count;
206492b200efdd20b8fcfdac873f3cd8d4902386581Jiri Pirko		unsigned int interval; /* in ms */
207492b200efdd20b8fcfdac873f3cd8d4902386581Jiri Pirko		atomic_t count_pending;
208492b200efdd20b8fcfdac873f3cd8d4902386581Jiri Pirko		struct delayed_work dw;
209492b200efdd20b8fcfdac873f3cd8d4902386581Jiri Pirko	} mcast_rejoin;
2103d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	long mode_priv[TEAM_MODE_PRIV_LONGS];
2113d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko};
2123d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
213e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wangstatic inline int team_dev_queue_xmit(struct team *team, struct team_port *port,
214e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang				      struct sk_buff *skb)
215e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang{
216e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang	BUILD_BUG_ON(sizeof(skb->queue_mapping) !=
217e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang		     sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping));
218e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang	skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping);
219e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang
220e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang	skb->dev = port->dev;
221e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang	if (unlikely(netpoll_tx_running(team->dev))) {
222e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang		team_netpoll_send_skb(port, skb);
223e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang		return 0;
224e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang	}
225e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang	return dev_queue_xmit(skb);
226e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang}
227e15c3c2294605f09f9b336b2f3b97086ab4b8145Amerigo Wang
2283d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostatic inline struct hlist_head *team_port_index_hash(struct team *team,
2293d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko						      int port_index)
2303d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko{
23119a0b58e506b06fd41659d8734bba6a3e87980f4Jiri Pirko	return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)];
2323d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko}
2333d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
2343d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostatic inline struct team_port *team_get_port_by_index(struct team *team,
2353d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko						       int port_index)
2363d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko{
2373d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct team_port *port;
2383d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct hlist_head *head = team_port_index_hash(team, port_index);
2393d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
240b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin	hlist_for_each_entry(port, head, hlist)
2413d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko		if (port->index == port_index)
2423d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko			return port;
2433d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	return NULL;
2443d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko}
245735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko
246735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirkostatic inline int team_num_to_port_index(struct team *team, int num)
247735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko{
248735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko	int en_port_count = ACCESS_ONCE(team->en_port_count);
249735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko
250735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko	if (unlikely(!en_port_count))
251735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko		return 0;
252735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko	return num % en_port_count;
253735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko}
254735d381fa57c573935d35a24ea271ec99897ac63Jiri Pirko
2553d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkostatic inline struct team_port *team_get_port_by_index_rcu(struct team *team,
2563d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko							   int port_index)
2573d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko{
2583d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct team_port *port;
2593d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	struct hlist_head *head = team_port_index_hash(team, port_index);
2603d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
261b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin	hlist_for_each_entry_rcu(port, head, hlist)
2623d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko		if (port->index == port_index)
2633d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko			return port;
2643d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko	return NULL;
2653d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko}
2663d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
267753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirkostatic inline struct team_port *
268753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirkoteam_get_first_port_txable_rcu(struct team *team, struct team_port *port)
269753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko{
270753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko	struct team_port *cur;
271753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko
272753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko	if (likely(team_port_txable(port)))
273753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko		return port;
274753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko	cur = port;
275753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko	list_for_each_entry_continue_rcu(cur, &team->port_list, list)
276b79462a8b9f9a452edc20c64a70a89ba3b0a6a88Jiri Pirko		if (team_port_txable(cur))
277753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko			return cur;
278753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko	list_for_each_entry_rcu(cur, &team->port_list, list) {
279753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko		if (cur == port)
280753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko			break;
281b79462a8b9f9a452edc20c64a70a89ba3b0a6a88Jiri Pirko		if (team_port_txable(cur))
282753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko			return cur;
283753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko	}
284753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko	return NULL;
285753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko}
286753f993911b32e479b4fab5d228dc07c11d1e7e7Jiri Pirko
287358b838291f618278080bbed435b755f9b46748eJiri Pirkoextern int team_options_register(struct team *team,
288358b838291f618278080bbed435b755f9b46748eJiri Pirko				 const struct team_option *option,
289358b838291f618278080bbed435b755f9b46748eJiri Pirko				 size_t option_count);
2903d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirkoextern void team_options_unregister(struct team *team,
291358b838291f618278080bbed435b755f9b46748eJiri Pirko				    const struct team_option *option,
2923d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko				    size_t option_count);
2930402788a6cda4e204a805e83eaaff64fef9e4418Jiri Pirkoextern int team_mode_register(const struct team_mode *mode);
2940402788a6cda4e204a805e83eaaff64fef9e4418Jiri Pirkoextern void team_mode_unregister(const struct team_mode *mode);
2953d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko
2966c85f2bdda2086d804e198a3f31b685bc2f86b04Jiri Pirko#define TEAM_DEFAULT_NUM_TX_QUEUES 16
2976c85f2bdda2086d804e198a3f31b685bc2f86b04Jiri Pirko#define TEAM_DEFAULT_NUM_RX_QUEUES 16
2986c85f2bdda2086d804e198a3f31b685bc2f86b04Jiri Pirko
2993d249d4ca7d0ed6629a135ea1ea21c72286c0d80Jiri Pirko#endif /* _LINUX_IF_TEAM_H_ */
300