linux/drivers/net/team/team_core.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * drivers/net/team/team.c - Network team device driver
 * Copyright (c) 2011 Jiri Pirko <[email protected]>
 */

#include <linux/ethtool.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/rcupdate.h>
#include <linux/errno.h>
#include <linux/ctype.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
#include <linux/netpoll.h>
#include <linux/if_vlan.h>
#include <linux/if_arp.h>
#include <linux/socket.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <net/rtnetlink.h>
#include <net/genetlink.h>
#include <net/netlink.h>
#include <net/sch_generic.h>
#include <linux/if_team.h>

#include "team_nl.h"

#define DRV_NAME


/**********
 * Helpers
 **********/

static struct team_port *team_port_get_rtnl(const struct net_device *dev)
{}

/*
 * Since the ability to change device address for open port device is tested in
 * team_port_add, this function can be called without control of return value
 */
static int __set_port_dev_addr(struct net_device *port_dev,
			       const unsigned char *dev_addr)
{}

static int team_port_set_orig_dev_addr(struct team_port *port)
{}

static int team_port_set_team_dev_addr(struct team *team,
				       struct team_port *port)
{}

int team_modeop_port_enter(struct team *team, struct team_port *port)
{}
EXPORT_SYMBOL();

void team_modeop_port_change_dev_addr(struct team *team,
				      struct team_port *port)
{}
EXPORT_SYMBOL();

static void team_lower_state_changed(struct team_port *port)
{}

static void team_refresh_port_linkup(struct team_port *port)
{}


/*******************
 * Options handling
 *******************/

struct team_option_inst {};

static struct team_option *__team_find_option(struct team *team,
					      const char *opt_name)
{}

static void __team_option_inst_del(struct team_option_inst *opt_inst)
{}

static void __team_option_inst_del_option(struct team *team,
					  struct team_option *option)
{}

static int __team_option_inst_add(struct team *team, struct team_option *option,
				  struct team_port *port)
{}

static int __team_option_inst_add_option(struct team *team,
					 struct team_option *option)
{}

static void __team_option_inst_mark_removed_option(struct team *team,
						   struct team_option *option)
{}

static void __team_option_inst_del_port(struct team *team,
					struct team_port *port)
{}

static int __team_option_inst_add_port(struct team *team,
				       struct team_port *port)
{}

static void __team_option_inst_mark_removed_port(struct team *team,
						 struct team_port *port)
{}

static int __team_options_register(struct team *team,
				   const struct team_option *option,
				   size_t option_count)
{}

static void __team_options_mark_removed(struct team *team,
					const struct team_option *option,
					size_t option_count)
{}

static void __team_options_unregister(struct team *team,
				      const struct team_option *option,
				      size_t option_count)
{}

static void __team_options_change_check(struct team *team);

int team_options_register(struct team *team,
			  const struct team_option *option,
			  size_t option_count)
{}
EXPORT_SYMBOL();

void team_options_unregister(struct team *team,
			     const struct team_option *option,
			     size_t option_count)
{}
EXPORT_SYMBOL();

static int team_option_get(struct team *team,
			   struct team_option_inst *opt_inst,
			   struct team_gsetter_ctx *ctx)
{}

static int team_option_set(struct team *team,
			   struct team_option_inst *opt_inst,
			   struct team_gsetter_ctx *ctx)
{}

void team_option_inst_set_change(struct team_option_inst_info *opt_inst_info)
{}
EXPORT_SYMBOL();

void team_options_change_check(struct team *team)
{}
EXPORT_SYMBOL();


/****************
 * Mode handling
 ****************/

static LIST_HEAD(mode_list);
static DEFINE_SPINLOCK(mode_list_lock);

struct team_mode_item {};

static struct team_mode_item *__find_mode(const char *kind)
{}

static bool is_good_mode_name(const char *name)
{}

int team_mode_register(const struct team_mode *mode)
{}
EXPORT_SYMBOL();

void team_mode_unregister(const struct team_mode *mode)
{}
EXPORT_SYMBOL();

static const struct team_mode *team_mode_get(const char *kind)
{}

static void team_mode_put(const struct team_mode *mode)
{}

static bool team_dummy_transmit(struct team *team, struct sk_buff *skb)
{}

static rx_handler_result_t team_dummy_receive(struct team *team,
					      struct team_port *port,
					      struct sk_buff *skb)
{}

static const struct team_mode __team_no_mode =;

static bool team_is_mode_set(struct team *team)
{}

static void team_set_no_mode(struct team *team)
{}

static void team_adjust_ops(struct team *team)
{}

/*
 * We can benefit from the fact that it's ensured no port is present
 * at the time of mode change. Therefore no packets are in fly so there's no
 * need to set mode operations in any special way.
 */
static int __team_change_mode(struct team *team,
			      const struct team_mode *new_mode)
{}

static int team_change_mode(struct team *team, const char *kind)
{}


/*********************
 * Peers notification
 *********************/

static void team_notify_peers_work(struct work_struct *work)
{}

static void team_notify_peers(struct team *team)
{}

static void team_notify_peers_init(struct team *team)
{}

static void team_notify_peers_fini(struct team *team)
{}


/*******************************
 * Send multicast group rejoins
 *******************************/

static void team_mcast_rejoin_work(struct work_struct *work)
{}

static void team_mcast_rejoin(struct team *team)
{}

static void team_mcast_rejoin_init(struct team *team)
{}

static void team_mcast_rejoin_fini(struct team *team)
{}


/************************
 * Rx path frame handler
 ************************/

/* note: already called with rcu_read_lock */
static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
{}


/*************************************
 * Multiqueue Tx port select override
 *************************************/

static int team_queue_override_init(struct team *team)
{}

static void team_queue_override_fini(struct team *team)
{}

static struct list_head *__team_get_qom_list(struct team *team, u16 queue_id)
{}

/*
 * note: already called with rcu_read_lock
 */
static bool team_queue_override_transmit(struct team *team, struct sk_buff *skb)
{}

static void __team_queue_override_port_del(struct team *team,
					   struct team_port *port)
{}

static bool team_queue_override_port_has_gt_prio_than(struct team_port *port,
						      struct team_port *cur)
{}

static void __team_queue_override_port_add(struct team *team,
					   struct team_port *port)
{}

static void __team_queue_override_enabled_check(struct team *team)
{}

static void team_queue_override_port_prio_changed(struct team *team,
						  struct team_port *port)
{}

static void team_queue_override_port_change_queue_id(struct team *team,
						     struct team_port *port,
						     u16 new_queue_id)
{}

static void team_queue_override_port_add(struct team *team,
					 struct team_port *port)
{}

static void team_queue_override_port_del(struct team *team,
					 struct team_port *port)
{}


/****************
 * Port handling
 ****************/

static bool team_port_find(const struct team *team,
			   const struct team_port *port)
{}

/*
 * Enable/disable port by adding to enabled port hashlist and setting
 * port->index (Might be racy so reader could see incorrect ifindex when
 * processing a flying packet, but that is not a problem). Write guarded
 * by team->lock.
 */
static void team_port_enable(struct team *team,
			     struct team_port *port)
{}

static void __reconstruct_port_hlist(struct team *team, int rm_index)
{}

static void team_port_disable(struct team *team,
			      struct team_port *port)
{}

#define TEAM_VLAN_FEATURES

#define TEAM_ENC_FEATURES

static void __team_compute_features(struct team *team)
{}

static void team_compute_features(struct team *team)
{}

static int team_port_enter(struct team *team, struct team_port *port)
{}

static void team_port_leave(struct team *team, struct team_port *port)
{}

#ifdef CONFIG_NET_POLL_CONTROLLER
static int __team_port_enable_netpoll(struct team_port *port)
{}

static int team_port_enable_netpoll(struct team_port *port)
{}

static void team_port_disable_netpoll(struct team_port *port)
{}
#else
static int team_port_enable_netpoll(struct team_port *port)
{
	return 0;
}
static void team_port_disable_netpoll(struct team_port *port)
{
}
#endif

static int team_upper_dev_link(struct team *team, struct team_port *port,
			       struct netlink_ext_ack *extack)
{}

static void team_upper_dev_unlink(struct team *team, struct team_port *port)
{}

static void __team_port_change_port_added(struct team_port *port, bool linkup);
static int team_dev_type_check_change(struct net_device *dev,
				      struct net_device *port_dev);

static int team_port_add(struct team *team, struct net_device *port_dev,
			 struct netlink_ext_ack *extack)
{}

static void __team_port_change_port_removed(struct team_port *port);

static int team_port_del(struct team *team, struct net_device *port_dev)
{}


/*****************
 * Net device ops
 *****************/

static void team_mode_option_get(struct team *team, struct team_gsetter_ctx *ctx)
{}

static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx)
{}

static void team_notify_peers_count_get(struct team *team,
					struct team_gsetter_ctx *ctx)
{}

static int team_notify_peers_count_set(struct team *team,
				       struct team_gsetter_ctx *ctx)
{}

static void team_notify_peers_interval_get(struct team *team,
					   struct team_gsetter_ctx *ctx)
{}

static int team_notify_peers_interval_set(struct team *team,
					  struct team_gsetter_ctx *ctx)
{}

static void team_mcast_rejoin_count_get(struct team *team,
					struct team_gsetter_ctx *ctx)
{}

static int team_mcast_rejoin_count_set(struct team *team,
				       struct team_gsetter_ctx *ctx)
{}

static void team_mcast_rejoin_interval_get(struct team *team,
					   struct team_gsetter_ctx *ctx)
{}

static int team_mcast_rejoin_interval_set(struct team *team,
					  struct team_gsetter_ctx *ctx)
{}

static void team_port_en_option_get(struct team *team,
				    struct team_gsetter_ctx *ctx)
{}

static int team_port_en_option_set(struct team *team,
				   struct team_gsetter_ctx *ctx)
{}

static void team_user_linkup_option_get(struct team *team,
					struct team_gsetter_ctx *ctx)
{}

static void __team_carrier_check(struct team *team);

static int team_user_linkup_option_set(struct team *team,
				       struct team_gsetter_ctx *ctx)
{}

static void team_user_linkup_en_option_get(struct team *team,
					   struct team_gsetter_ctx *ctx)
{}

static int team_user_linkup_en_option_set(struct team *team,
					  struct team_gsetter_ctx *ctx)
{}

static void team_priority_option_get(struct team *team,
				     struct team_gsetter_ctx *ctx)
{}

static int team_priority_option_set(struct team *team,
				    struct team_gsetter_ctx *ctx)
{}

static void team_queue_id_option_get(struct team *team,
				     struct team_gsetter_ctx *ctx)
{}

static int team_queue_id_option_set(struct team *team,
				    struct team_gsetter_ctx *ctx)
{}

static const struct team_option team_options[] =;


static int team_init(struct net_device *dev)
{}

static void team_uninit(struct net_device *dev)
{}

static void team_destructor(struct net_device *dev)
{}

static int team_open(struct net_device *dev)
{}

static int team_close(struct net_device *dev)
{}

/*
 * note: already called with rcu_read_lock
 */
static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
{}

static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
			     struct net_device *sb_dev)
{}

static void team_change_rx_flags(struct net_device *dev, int change)
{}

static void team_set_rx_mode(struct net_device *dev)
{}

static int team_set_mac_address(struct net_device *dev, void *p)
{}

static int team_change_mtu(struct net_device *dev, int new_mtu)
{}

static void
team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
{}

static int team_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
{}

static int team_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
{}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void team_poll_controller(struct net_device *dev)
{}

static void __team_netpoll_cleanup(struct team *team)
{}

static void team_netpoll_cleanup(struct net_device *dev)
{}

static int team_netpoll_setup(struct net_device *dev,
			      struct netpoll_info *npifo)
{}
#endif

static int team_add_slave(struct net_device *dev, struct net_device *port_dev,
			  struct netlink_ext_ack *extack)
{}

static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
{}

static netdev_features_t team_fix_features(struct net_device *dev,
					   netdev_features_t features)
{}

static int team_change_carrier(struct net_device *dev, bool new_carrier)
{}

static const struct net_device_ops team_netdev_ops =;

/***********************
 * ethtool interface
 ***********************/

static void team_ethtool_get_drvinfo(struct net_device *dev,
				     struct ethtool_drvinfo *drvinfo)
{}

static int team_ethtool_get_link_ksettings(struct net_device *dev,
					   struct ethtool_link_ksettings *cmd)
{}

static const struct ethtool_ops team_ethtool_ops =;

/***********************
 * rt netlink interface
 ***********************/

static void team_setup_by_port(struct net_device *dev,
			       struct net_device *port_dev)
{}

static int team_dev_type_check_change(struct net_device *dev,
				      struct net_device *port_dev)
{}

static void team_setup(struct net_device *dev)
{}

static int team_newlink(struct net *src_net, struct net_device *dev,
			struct nlattr *tb[], struct nlattr *data[],
			struct netlink_ext_ack *extack)
{}

static int team_validate(struct nlattr *tb[], struct nlattr *data[],
			 struct netlink_ext_ack *extack)
{}

static unsigned int team_get_num_tx_queues(void)
{}

static unsigned int team_get_num_rx_queues(void)
{}

static struct rtnl_link_ops team_link_ops __read_mostly =;


/***********************************
 * Generic netlink custom interface
 ***********************************/

static struct genl_family team_nl_family;

int team_nl_noop_doit(struct sk_buff *skb, struct genl_info *info)
{}

/*
 * Netlink cmd functions should be locked by following two functions.
 * Since dev gets held here, that ensures dev won't disappear in between.
 */
static struct team *team_nl_team_get(struct genl_info *info)
{}

static void team_nl_team_put(struct team *team)
{}

team_nl_send_func_t;

static int team_nl_send_unicast(struct sk_buff *skb, struct team *team, u32 portid)
{}

static int team_nl_fill_one_option_get(struct sk_buff *skb, struct team *team,
				       struct team_option_inst *opt_inst)
{}

static int __send_and_alloc_skb(struct sk_buff **pskb,
				struct team *team, u32 portid,
				team_nl_send_func_t *send_func)
{}

static int team_nl_send_options_get(struct team *team, u32 portid, u32 seq,
				    int flags, team_nl_send_func_t *send_func,
				    struct list_head *sel_opt_inst_list)
{}

int team_nl_options_get_doit(struct sk_buff *skb, struct genl_info *info)
{}

static int team_nl_send_event_options_get(struct team *team,
					  struct list_head *sel_opt_inst_list);

int team_nl_options_set_doit(struct sk_buff *skb, struct genl_info *info)
{}

static int team_nl_fill_one_port_get(struct sk_buff *skb,
				     struct team_port *port)
{}

static int team_nl_send_port_list_get(struct team *team, u32 portid, u32 seq,
				      int flags, team_nl_send_func_t *send_func,
				      struct team_port *one_port)
{}

int team_nl_port_list_get_doit(struct sk_buff *skb,
			       struct genl_info *info)
{}

static const struct genl_multicast_group team_nl_mcgrps[] =;

static struct genl_family team_nl_family __ro_after_init =;

static int team_nl_send_multicast(struct sk_buff *skb,
				  struct team *team, u32 portid)
{}

static int team_nl_send_event_options_get(struct team *team,
					  struct list_head *sel_opt_inst_list)
{}

static int team_nl_send_event_port_get(struct team *team,
				       struct team_port *port)
{}

static int __init team_nl_init(void)
{}

static void __exit team_nl_fini(void)
{}


/******************
 * Change checkers
 ******************/

static void __team_options_change_check(struct team *team)
{}

/* rtnl lock is held */

static void __team_port_change_send(struct team_port *port, bool linkup)
{}

static void __team_carrier_check(struct team *team)
{}

static void __team_port_change_check(struct team_port *port, bool linkup)
{}

static void __team_port_change_port_added(struct team_port *port, bool linkup)
{}

static void __team_port_change_port_removed(struct team_port *port)
{}

static void team_port_change_check(struct team_port *port, bool linkup)
{}


/************************************
 * Net device notifier event handler
 ************************************/

static int team_device_event(struct notifier_block *unused,
			     unsigned long event, void *ptr)
{}

static struct notifier_block team_notifier_block __read_mostly =;


/***********************
 * Module init and exit
 ***********************/

static int __init team_module_init(void)
{}

static void __exit team_module_exit(void)
{}

module_init();
module_exit(team_module_exit);

MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_ALIAS_RTNL_LINK();