1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
23d249d4cSJiri Pirko /*
30d572e45SJiri Pirko * drivers/net/team/team_mode_roundrobin.c - Round-robin mode for team
43d249d4cSJiri Pirko * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
53d249d4cSJiri Pirko */
63d249d4cSJiri Pirko
73d249d4cSJiri Pirko #include <linux/kernel.h>
83d249d4cSJiri Pirko #include <linux/types.h>
93d249d4cSJiri Pirko #include <linux/module.h>
103d249d4cSJiri Pirko #include <linux/init.h>
113d249d4cSJiri Pirko #include <linux/netdevice.h>
123d249d4cSJiri Pirko #include <linux/if_team.h>
133d249d4cSJiri Pirko
143d249d4cSJiri Pirko struct rr_priv {
153d249d4cSJiri Pirko unsigned int sent_packets;
163d249d4cSJiri Pirko };
173d249d4cSJiri Pirko
rr_priv(struct team * team)183d249d4cSJiri Pirko static struct rr_priv *rr_priv(struct team *team)
193d249d4cSJiri Pirko {
203d249d4cSJiri Pirko return (struct rr_priv *) &team->mode_priv;
213d249d4cSJiri Pirko }
223d249d4cSJiri Pirko
rr_transmit(struct team * team,struct sk_buff * skb)233d249d4cSJiri Pirko static bool rr_transmit(struct team *team, struct sk_buff *skb)
243d249d4cSJiri Pirko {
253d249d4cSJiri Pirko struct team_port *port;
263d249d4cSJiri Pirko int port_index;
273d249d4cSJiri Pirko
28735d381fSJiri Pirko port_index = team_num_to_port_index(team,
29735d381fSJiri Pirko rr_priv(team)->sent_packets++);
303d249d4cSJiri Pirko port = team_get_port_by_index_rcu(team, port_index);
3176c455deSJiri Pirko if (unlikely(!port))
3276c455deSJiri Pirko goto drop;
33753f9939SJiri Pirko port = team_get_first_port_txable_rcu(team, port);
343d249d4cSJiri Pirko if (unlikely(!port))
353d249d4cSJiri Pirko goto drop;
36bd2d0837SJiri Pirko if (team_dev_queue_xmit(team, port, skb))
373d249d4cSJiri Pirko return false;
383d249d4cSJiri Pirko return true;
393d249d4cSJiri Pirko
403d249d4cSJiri Pirko drop:
413d249d4cSJiri Pirko dev_kfree_skb_any(skb);
423d249d4cSJiri Pirko return false;
433d249d4cSJiri Pirko }
443d249d4cSJiri Pirko
453d249d4cSJiri Pirko static const struct team_mode_ops rr_mode_ops = {
463d249d4cSJiri Pirko .transmit = rr_transmit,
47acbba0d0SJiri Pirko .port_enter = team_modeop_port_enter,
48acbba0d0SJiri Pirko .port_change_dev_addr = team_modeop_port_change_dev_addr,
493d249d4cSJiri Pirko };
503d249d4cSJiri Pirko
510402788aSJiri Pirko static const struct team_mode rr_mode = {
523d249d4cSJiri Pirko .kind = "roundrobin",
533d249d4cSJiri Pirko .owner = THIS_MODULE,
543d249d4cSJiri Pirko .priv_size = sizeof(struct rr_priv),
553d249d4cSJiri Pirko .ops = &rr_mode_ops,
568fd72856SJiri Pirko .lag_tx_type = NETDEV_LAG_TX_TYPE_ROUNDROBIN,
573d249d4cSJiri Pirko };
583d249d4cSJiri Pirko
rr_init_module(void)593d249d4cSJiri Pirko static int __init rr_init_module(void)
603d249d4cSJiri Pirko {
613d249d4cSJiri Pirko return team_mode_register(&rr_mode);
623d249d4cSJiri Pirko }
633d249d4cSJiri Pirko
rr_cleanup_module(void)643d249d4cSJiri Pirko static void __exit rr_cleanup_module(void)
653d249d4cSJiri Pirko {
663d249d4cSJiri Pirko team_mode_unregister(&rr_mode);
673d249d4cSJiri Pirko }
683d249d4cSJiri Pirko
693d249d4cSJiri Pirko module_init(rr_init_module);
703d249d4cSJiri Pirko module_exit(rr_cleanup_module);
713d249d4cSJiri Pirko
723d249d4cSJiri Pirko MODULE_LICENSE("GPL v2");
733d249d4cSJiri Pirko MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
743d249d4cSJiri Pirko MODULE_DESCRIPTION("Round-robin mode for team");
753a5f8997SZhang Shengju MODULE_ALIAS_TEAM_MODE("roundrobin");
76