cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

team_mode_activebackup.c (3466B)


      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 int 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	return 0;
     65}
     66
     67static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx)
     68{
     69	struct team_port *active_port;
     70
     71	active_port = rcu_dereference_protected(ab_priv(team)->active_port,
     72						lockdep_is_held(&team->lock));
     73	if (active_port)
     74		ctx->data.u32_val = active_port->dev->ifindex;
     75	else
     76		ctx->data.u32_val = 0;
     77	return 0;
     78}
     79
     80static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx)
     81{
     82	struct team_port *port;
     83
     84	list_for_each_entry(port, &team->port_list, list) {
     85		if (port->dev->ifindex == ctx->data.u32_val) {
     86			rcu_assign_pointer(ab_priv(team)->active_port, port);
     87			return 0;
     88		}
     89	}
     90	return -ENOENT;
     91}
     92
     93static const struct team_option ab_options[] = {
     94	{
     95		.name = "activeport",
     96		.type = TEAM_OPTION_TYPE_U32,
     97		.init = ab_active_port_init,
     98		.getter = ab_active_port_get,
     99		.setter = ab_active_port_set,
    100	},
    101};
    102
    103static int ab_init(struct team *team)
    104{
    105	return team_options_register(team, ab_options, ARRAY_SIZE(ab_options));
    106}
    107
    108static void ab_exit(struct team *team)
    109{
    110	team_options_unregister(team, ab_options, ARRAY_SIZE(ab_options));
    111}
    112
    113static const struct team_mode_ops ab_mode_ops = {
    114	.init			= ab_init,
    115	.exit			= ab_exit,
    116	.receive		= ab_receive,
    117	.transmit		= ab_transmit,
    118	.port_leave		= ab_port_leave,
    119};
    120
    121static const struct team_mode ab_mode = {
    122	.kind		= "activebackup",
    123	.owner		= THIS_MODULE,
    124	.priv_size	= sizeof(struct ab_priv),
    125	.ops		= &ab_mode_ops,
    126	.lag_tx_type	= NETDEV_LAG_TX_TYPE_ACTIVEBACKUP,
    127};
    128
    129static int __init ab_init_module(void)
    130{
    131	return team_mode_register(&ab_mode);
    132}
    133
    134static void __exit ab_cleanup_module(void)
    135{
    136	team_mode_unregister(&ab_mode);
    137}
    138
    139module_init(ab_init_module);
    140module_exit(ab_cleanup_module);
    141
    142MODULE_LICENSE("GPL v2");
    143MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
    144MODULE_DESCRIPTION("Active-backup mode for team");
    145MODULE_ALIAS_TEAM_MODE("activebackup");