Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: team: Track rx enablement separately from tx enablement

Separate the rx and tx enablement/disablement into different
functions so that it is easier to interact with them independently
later.

Although this patch changes receive and transmit paths, the actual
behavior of the teaming driver should remain unchanged, since there
is no option introduced yet to change rx or tx enablement
independently. Those options will be added in follow-up patches.

Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Marc Harvey <marcharvey@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260409-teaming-driver-internal-v7-7-f47e7589685d@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Marc Harvey and committed by
Paolo Abeni
68f0833f fa6ed31d

+100 -32
+85 -29
drivers/net/team/team_core.c
··· 87 87 struct netdev_lag_lower_state_info info; 88 88 89 89 info.link_up = port->linkup; 90 - info.tx_enabled = team_port_enabled(port); 90 + info.tx_enabled = team_port_tx_enabled(port); 91 91 netdev_lower_state_changed(port->dev, &info); 92 92 } 93 93 ··· 538 538 else 539 539 team->ops.transmit = team->mode->ops->transmit; 540 540 541 - if (!team->tx_en_port_count || !team_is_mode_set(team) || 541 + if (!team->rx_en_port_count || !team_is_mode_set(team) || 542 542 !team->mode->ops->receive) 543 543 team->ops.receive = team_dummy_receive; 544 544 else ··· 734 734 735 735 port = team_port_get_rcu(skb->dev); 736 736 team = port->team; 737 - if (!team_port_enabled(port)) { 737 + if (!team_port_rx_enabled(port)) { 738 738 if (is_link_local_ether_addr(eth_hdr(skb)->h_dest)) 739 739 /* link-local packets are mostly useful when stack receives them 740 740 * with the link they arrive on. ··· 876 876 static void team_queue_override_port_prio_changed(struct team *team, 877 877 struct team_port *port) 878 878 { 879 - if (!port->queue_id || !team_port_enabled(port)) 879 + if (!port->queue_id || !team_port_tx_enabled(port)) 880 880 return; 881 881 __team_queue_override_port_del(team, port); 882 882 __team_queue_override_port_add(team, port); ··· 887 887 struct team_port *port, 888 888 u16 new_queue_id) 889 889 { 890 - if (team_port_enabled(port)) { 890 + if (team_port_tx_enabled(port)) { 891 891 __team_queue_override_port_del(team, port); 892 892 port->queue_id = new_queue_id; 893 893 __team_queue_override_port_add(team, port); ··· 927 927 return false; 928 928 } 929 929 930 - /* 931 - * Enable/disable port by adding to enabled port hashlist and setting 932 - * port->tx_index (Might be racy so reader could see incorrect ifindex when 933 - * processing a flying packet, but that is not a problem). Write guarded 934 - * by RTNL. 935 - */ 936 - static void team_port_enable(struct team *team, 937 - struct team_port *port) 930 + static void __team_port_enable_rx(struct team *team, 931 + struct team_port *port) 938 932 { 939 - if (team_port_enabled(port)) 940 - return; 933 + team->rx_en_port_count++; 934 + WRITE_ONCE(port->rx_enabled, true); 935 + } 936 + 937 + static void __team_port_disable_rx(struct team *team, 938 + struct team_port *port) 939 + { 940 + team->rx_en_port_count--; 941 + WRITE_ONCE(port->rx_enabled, false); 942 + } 943 + 944 + /* 945 + * Enable just TX on the port by adding to tx-enabled port hashlist and 946 + * setting port->tx_index (Might be racy so reader could see incorrect 947 + * ifindex when processing a flying packet, but that is not a problem). 948 + * Write guarded by RTNL. 949 + */ 950 + static void __team_port_enable_tx(struct team *team, 951 + struct team_port *port) 952 + { 941 953 WRITE_ONCE(port->tx_index, team->tx_en_port_count); 942 954 WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count + 1); 943 955 hlist_add_head_rcu(&port->tx_hlist, 944 956 team_tx_port_index_hash(team, port->tx_index)); 945 - team_adjust_ops(team); 946 - team_queue_override_port_add(team, port); 947 - team_notify_peers(team); 948 - team_mcast_rejoin(team); 949 - team_lower_state_changed(port); 950 957 } 951 958 952 959 static void __reconstruct_port_hlist(struct team *team, int rm_index) ··· 972 965 } 973 966 } 974 967 968 + static void __team_port_disable_tx(struct team *team, 969 + struct team_port *port) 970 + { 971 + if (team->ops.port_tx_disabled) 972 + team->ops.port_tx_disabled(team, port); 973 + 974 + hlist_del_rcu(&port->tx_hlist); 975 + __reconstruct_port_hlist(team, port->tx_index); 976 + 977 + WRITE_ONCE(port->tx_index, -1); 978 + WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count - 1); 979 + } 980 + 981 + /* 982 + * Enable TX AND RX on the port. 983 + */ 984 + static void team_port_enable(struct team *team, 985 + struct team_port *port) 986 + { 987 + bool rx_was_enabled; 988 + bool tx_was_enabled; 989 + 990 + if (team_port_enabled(port)) 991 + return; 992 + 993 + rx_was_enabled = team_port_rx_enabled(port); 994 + tx_was_enabled = team_port_tx_enabled(port); 995 + 996 + if (!rx_was_enabled) 997 + __team_port_enable_rx(team, port); 998 + if (!tx_was_enabled) 999 + __team_port_enable_tx(team, port); 1000 + 1001 + team_adjust_ops(team); 1002 + if (!tx_was_enabled) 1003 + team_queue_override_port_add(team, port); 1004 + team_notify_peers(team); 1005 + if (!rx_was_enabled) 1006 + team_mcast_rejoin(team); 1007 + if (!tx_was_enabled) 1008 + team_lower_state_changed(port); 1009 + } 1010 + 975 1011 static void team_port_disable(struct team *team, 976 1012 struct team_port *port) 977 1013 { 978 - if (!team_port_enabled(port)) 1014 + bool rx_was_enabled = team_port_rx_enabled(port); 1015 + bool tx_was_enabled = team_port_tx_enabled(port); 1016 + 1017 + if (!tx_was_enabled && !rx_was_enabled) 979 1018 return; 980 - if (team->ops.port_tx_disabled) 981 - team->ops.port_tx_disabled(team, port); 982 - hlist_del_rcu(&port->tx_hlist); 983 - __reconstruct_port_hlist(team, port->tx_index); 984 - WRITE_ONCE(port->tx_index, -1); 985 - WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count - 1); 986 - team_queue_override_port_del(team, port); 1019 + 1020 + if (tx_was_enabled) { 1021 + __team_port_disable_tx(team, port); 1022 + team_queue_override_port_del(team, port); 1023 + } 1024 + if (rx_was_enabled) 1025 + __team_port_disable_rx(team, port); 1026 + 987 1027 team_adjust_ops(team); 988 - team_lower_state_changed(port); 1028 + 1029 + if (tx_was_enabled) 1030 + team_lower_state_changed(port); 989 1031 } 990 1032 991 1033 static int team_port_enter(struct team *team, struct team_port *port)
+1 -1
drivers/net/team/team_mode_loadbalance.c
··· 380 380 381 381 list_for_each_entry(port, &team->port_list, list) { 382 382 if (ctx->data.u32_val == port->dev->ifindex && 383 - team_port_enabled(port)) { 383 + team_port_tx_enabled(port)) { 384 384 rcu_assign_pointer(LB_HTPM_PORT_BY_HASH(lb_priv, hash), 385 385 port); 386 386 return 0;
+14 -2
include/linux/if_team.h
··· 31 31 struct list_head list; /* node in ordinary list */ 32 32 struct team *team; 33 33 int tx_index; /* index of tx enabled port. If disabled, -1 */ 34 + bool rx_enabled; 34 35 35 36 bool linkup; /* either state.linkup or user.linkup */ 36 37 ··· 76 75 return rcu_dereference(dev->rx_handler_data); 77 76 } 78 77 79 - static inline bool team_port_enabled(struct team_port *port) 78 + static inline bool team_port_rx_enabled(struct team_port *port) 79 + { 80 + return READ_ONCE(port->rx_enabled); 81 + } 82 + 83 + static inline bool team_port_tx_enabled(struct team_port *port) 80 84 { 81 85 return READ_ONCE(port->tx_index) != -1; 82 86 } 83 87 88 + static inline bool team_port_enabled(struct team_port *port) 89 + { 90 + return team_port_rx_enabled(port) && team_port_tx_enabled(port); 91 + } 92 + 84 93 static inline bool team_port_txable(struct team_port *port) 85 94 { 86 - return port->linkup && team_port_enabled(port); 95 + return port->linkup && team_port_tx_enabled(port); 87 96 } 88 97 89 98 static inline bool team_port_dev_txable(const struct net_device *port_dev) ··· 204 193 * List of tx-enabled ports and counts of rx and tx-enabled ports. 205 194 */ 206 195 int tx_en_port_count; 196 + int rx_en_port_count; 207 197 struct hlist_head tx_en_port_hlist[TEAM_PORT_HASHENTRIES]; 208 198 209 199 struct list_head port_list; /* list of all ports */