File Index
Files and directories
Sign in
FILE

team_mode_activebackup.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/team/team_mode_activebackup.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * drivers/net/team/team_mode_activebackup.c - Active-backup mode for team
  4 * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
  5 */
  6
  7#include <linux/kernel.h>
  8#include <linux/types.h>
  9#include <linux/module.h>
 10#include <linux/init.h>
 11#include <linux/errno.h>
 12#include <linux/netdevice.h>
 13#include <net/rtnetlink.h>
 14#include <linux/if_team.h>
 15
 16struct ab_priv {
 17	struct team_port __rcu *active_port;
 18	struct team_option_inst_info *ap_opt_inst_info;
 19};
 20
 21static struct ab_priv *ab_priv(struct team *team)
 22{
 23	return (struct ab_priv *) &team->mode_priv;
 24}
 25
 26static rx_handler_result_t ab_receive(struct team *team, struct team_port *port,
 27				      struct sk_buff *skb) {
 28	struct team_port *active_port;
 29
 30	active_port = rcu_dereference(ab_priv(team)->active_port);
 31	if (active_port != port)
 32		return RX_HANDLER_EXACT;
 33	return RX_HANDLER_ANOTHER;
 34}
 35
 36static bool ab_transmit(struct team *team, struct sk_buff *skb)
 37{
 38	struct team_port *active_port;
 39
 40	active_port = rcu_dereference_bh(ab_priv(team)->active_port);
 41	if (unlikely(!active_port))
 42		goto drop;
 43	if (team_dev_queue_xmit(team, active_port, skb))
 44		return false;
 45	return true;
 46
 47drop:
 48	dev_kfree_skb_any(skb);
 49	return false;
 50}
 51
 52static void ab_port_leave(struct team *team, struct team_port *port)
 53{
 54	if (ab_priv(team)->active_port == port) {
 55		RCU_INIT_POINTER(ab_priv(team)->active_port, NULL);
 56		team_option_inst_set_change(ab_priv(team)->ap_opt_inst_info);
 57	}
 58}
 59
 60static void ab_active_port_init(struct team *team,
 61				struct team_option_inst_info *info)
 62{
 63	ab_priv(team)->ap_opt_inst_info = info;
 64}
 65
 66static void ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx)
 67{
 68	struct team_port *active_port;
 69
 70	active_port = rtnl_dereference(ab_priv(team)->active_port);
 71	if (active_port)
 72		ctx->data.u32_val = active_port->dev->ifindex;
 73	else
 74		ctx->data.u32_val = 0;
 75}
 76
 77static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx)
 78{
 79	struct team_port *port;
 80
 81	list_for_each_entry(port, &team->port_list, list) {
 82		if (port->dev->ifindex == ctx->data.u32_val) {
 83			rcu_assign_pointer(ab_priv(team)->active_port, port);
 84			return 0;
 85		}
 86	}
 87	return -ENOENT;
 88}
 89
 90static const struct team_option ab_options[] = {
 91	{
 92		.name = "activeport",
 93		.type = TEAM_OPTION_TYPE_U32,
 94		.init = ab_active_port_init,
 95		.getter = ab_active_port_get,
 96		.setter = ab_active_port_set,
 97	},
 98};
 99
100static int ab_init(struct team *team)
101{
102	return team_options_register(team, ab_options, ARRAY_SIZE(ab_options));
103}
104
105static void ab_exit(struct team *team)
106{
107	team_options_unregister(team, ab_options, ARRAY_SIZE(ab_options));
108}
109
110static const struct team_mode_ops ab_mode_ops = {
111	.init			= ab_init,
112	.exit			= ab_exit,
113	.receive		= ab_receive,
114	.transmit		= ab_transmit,
115	.port_leave		= ab_port_leave,
116};
117
118static const struct team_mode ab_mode = {
119	.kind		= "activebackup",
120	.owner		= THIS_MODULE,
121	.priv_size	= sizeof(struct ab_priv),
122	.ops		= &ab_mode_ops,
123	.lag_tx_type	= NETDEV_LAG_TX_TYPE_ACTIVEBACKUP,
124};
125
126static int __init ab_init_module(void)
127{
128	return team_mode_register(&ab_mode);
129}
130
131static void __exit ab_cleanup_module(void)
132{
133	team_mode_unregister(&ab_mode);
134}
135
136module_init(ab_init_module);
137module_exit(ab_cleanup_module);
138
139MODULE_LICENSE("GPL v2");
140MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
141MODULE_DESCRIPTION("Active-backup mode for team");
142MODULE_ALIAS_TEAM_MODE("activebackup");
~/ Read-only file preview.