| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 5 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 6 | | - * Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 10 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|---|
| 11 | | - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|---|
| 12 | | - * for more details. |
|---|
| 13 | | - * |
|---|
| 14 | | - * You should have received a copy of the GNU General Public License along |
|---|
| 15 | | - * with this program; if not, see <http://www.gnu.org/licenses/>. |
|---|
| 16 | | - * |
|---|
| 17 | | - * The full GNU General Public License is included in this distribution in the |
|---|
| 18 | | - * file called LICENSE. |
|---|
| 19 | | - * |
|---|
| 20 | 4 | */ |
|---|
| 21 | 5 | |
|---|
| 22 | 6 | #include <linux/skbuff.h> |
|---|
| .. | .. |
|---|
| 311 | 295 | if (arp->op_code == htons(ARPOP_REPLY)) { |
|---|
| 312 | 296 | /* update rx hash table for this ARP */ |
|---|
| 313 | 297 | rlb_update_entry_from_arp(bond, arp); |
|---|
| 314 | | - netdev_dbg(bond->dev, "Server received an ARP Reply from client\n"); |
|---|
| 298 | + slave_dbg(bond->dev, slave->dev, "Server received an ARP Reply from client\n"); |
|---|
| 315 | 299 | } |
|---|
| 316 | 300 | out: |
|---|
| 317 | 301 | return RX_HANDLER_ANOTHER; |
|---|
| .. | .. |
|---|
| 453 | 437 | client_info->slave->dev->dev_addr, |
|---|
| 454 | 438 | client_info->mac_dst); |
|---|
| 455 | 439 | if (!skb) { |
|---|
| 456 | | - netdev_err(client_info->slave->bond->dev, |
|---|
| 457 | | - "failed to create an ARP packet\n"); |
|---|
| 440 | + slave_err(client_info->slave->bond->dev, |
|---|
| 441 | + client_info->slave->dev, |
|---|
| 442 | + "failed to create an ARP packet\n"); |
|---|
| 458 | 443 | continue; |
|---|
| 459 | 444 | } |
|---|
| 460 | 445 | |
|---|
| .. | .. |
|---|
| 671 | 656 | return NULL; |
|---|
| 672 | 657 | arp = (struct arp_pkt *)skb_network_header(skb); |
|---|
| 673 | 658 | |
|---|
| 674 | | - /* Don't modify or load balance ARPs that do not originate locally |
|---|
| 675 | | - * (e.g.,arrive via a bridge). |
|---|
| 659 | + /* Don't modify or load balance ARPs that do not originate |
|---|
| 660 | + * from the bond itself or a VLAN directly above the bond. |
|---|
| 676 | 661 | */ |
|---|
| 677 | | - if (!bond_slave_has_mac_rx(bond, arp->mac_src)) |
|---|
| 662 | + if (!bond_slave_has_mac_rcu(bond, arp->mac_src)) |
|---|
| 678 | 663 | return NULL; |
|---|
| 679 | 664 | |
|---|
| 680 | 665 | if (arp->op_code == htons(ARPOP_REPLY)) { |
|---|
| .. | .. |
|---|
| 683 | 668 | if (tx_slave) |
|---|
| 684 | 669 | bond_hw_addr_copy(arp->mac_src, tx_slave->dev->dev_addr, |
|---|
| 685 | 670 | tx_slave->dev->addr_len); |
|---|
| 686 | | - netdev_dbg(bond->dev, "Server sent ARP Reply packet\n"); |
|---|
| 671 | + netdev_dbg(bond->dev, "(slave %s): Server sent ARP Reply packet\n", |
|---|
| 672 | + tx_slave ? tx_slave->dev->name : "NULL"); |
|---|
| 687 | 673 | } else if (arp->op_code == htons(ARPOP_REQUEST)) { |
|---|
| 688 | 674 | /* Create an entry in the rx_hashtbl for this client as a |
|---|
| 689 | 675 | * place holder. |
|---|
| 690 | 676 | * When the arp reply is received the entry will be updated |
|---|
| 691 | 677 | * with the correct unicast address of the client. |
|---|
| 692 | 678 | */ |
|---|
| 693 | | - rlb_choose_channel(skb, bond, arp); |
|---|
| 679 | + tx_slave = rlb_choose_channel(skb, bond, arp); |
|---|
| 694 | 680 | |
|---|
| 695 | 681 | /* The ARP reply packets must be delayed so that |
|---|
| 696 | 682 | * they can cancel out the influence of the ARP request. |
|---|
| .. | .. |
|---|
| 703 | 689 | * updated with their assigned mac. |
|---|
| 704 | 690 | */ |
|---|
| 705 | 691 | rlb_req_update_subnet_clients(bond, arp->ip_src); |
|---|
| 706 | | - netdev_dbg(bond->dev, "Server sent ARP Request packet\n"); |
|---|
| 692 | + netdev_dbg(bond->dev, "(slave %s): Server sent ARP Request packet\n", |
|---|
| 693 | + tx_slave ? tx_slave->dev->name : "NULL"); |
|---|
| 707 | 694 | } |
|---|
| 708 | 695 | |
|---|
| 709 | 696 | return tx_slave; |
|---|
| .. | .. |
|---|
| 939 | 926 | skb->priority = TC_PRIO_CONTROL; |
|---|
| 940 | 927 | skb->dev = slave->dev; |
|---|
| 941 | 928 | |
|---|
| 942 | | - netdev_dbg(slave->bond->dev, |
|---|
| 943 | | - "Send learning packet: dev %s mac %pM vlan %d\n", |
|---|
| 944 | | - slave->dev->name, mac_addr, vid); |
|---|
| 929 | + slave_dbg(slave->bond->dev, slave->dev, |
|---|
| 930 | + "Send learning packet: mac %pM vlan %d\n", mac_addr, vid); |
|---|
| 945 | 931 | |
|---|
| 946 | 932 | if (vid) |
|---|
| 947 | 933 | __vlan_hwaccel_put_tag(skb, vlan_proto, vid); |
|---|
| .. | .. |
|---|
| 956 | 942 | bool strict_match; |
|---|
| 957 | 943 | }; |
|---|
| 958 | 944 | |
|---|
| 959 | | -static int alb_upper_dev_walk(struct net_device *upper, void *_data) |
|---|
| 945 | +static int alb_upper_dev_walk(struct net_device *upper, |
|---|
| 946 | + struct netdev_nested_priv *priv) |
|---|
| 960 | 947 | { |
|---|
| 961 | | - struct alb_walk_data *data = _data; |
|---|
| 948 | + struct alb_walk_data *data = (struct alb_walk_data *)priv->data; |
|---|
| 962 | 949 | bool strict_match = data->strict_match; |
|---|
| 963 | 950 | struct bonding *bond = data->bond; |
|---|
| 964 | 951 | struct slave *slave = data->slave; |
|---|
| .. | .. |
|---|
| 966 | 953 | struct bond_vlan_tag *tags; |
|---|
| 967 | 954 | |
|---|
| 968 | 955 | if (is_vlan_dev(upper) && |
|---|
| 969 | | - bond->nest_level == vlan_get_encap_level(upper) - 1) { |
|---|
| 956 | + bond->dev->lower_level == upper->lower_level - 1) { |
|---|
| 970 | 957 | if (upper->addr_assign_type == NET_ADDR_STOLEN) { |
|---|
| 971 | 958 | alb_send_lp_vid(slave, mac_addr, |
|---|
| 972 | 959 | vlan_dev_vlan_proto(upper), |
|---|
| .. | .. |
|---|
| 997 | 984 | bool strict_match) |
|---|
| 998 | 985 | { |
|---|
| 999 | 986 | struct bonding *bond = bond_get_bond_by_slave(slave); |
|---|
| 987 | + struct netdev_nested_priv priv; |
|---|
| 1000 | 988 | struct alb_walk_data data = { |
|---|
| 1001 | 989 | .strict_match = strict_match, |
|---|
| 1002 | 990 | .mac_addr = mac_addr, |
|---|
| .. | .. |
|---|
| 1004 | 992 | .bond = bond, |
|---|
| 1005 | 993 | }; |
|---|
| 1006 | 994 | |
|---|
| 995 | + priv.data = (void *)&data; |
|---|
| 1007 | 996 | /* send untagged */ |
|---|
| 1008 | 997 | alb_send_lp_vid(slave, mac_addr, 0, 0); |
|---|
| 1009 | 998 | |
|---|
| .. | .. |
|---|
| 1011 | 1000 | * for that device. |
|---|
| 1012 | 1001 | */ |
|---|
| 1013 | 1002 | rcu_read_lock(); |
|---|
| 1014 | | - netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &data); |
|---|
| 1003 | + netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &priv); |
|---|
| 1015 | 1004 | rcu_read_unlock(); |
|---|
| 1016 | 1005 | } |
|---|
| 1017 | 1006 | |
|---|
| .. | .. |
|---|
| 1031 | 1020 | */ |
|---|
| 1032 | 1021 | memcpy(ss.__data, addr, len); |
|---|
| 1033 | 1022 | ss.ss_family = dev->type; |
|---|
| 1034 | | - if (dev_set_mac_address(dev, (struct sockaddr *)&ss)) { |
|---|
| 1035 | | - netdev_err(slave->bond->dev, "dev_set_mac_address of dev %s failed! ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n", |
|---|
| 1036 | | - dev->name); |
|---|
| 1023 | + if (dev_set_mac_address(dev, (struct sockaddr *)&ss, NULL)) { |
|---|
| 1024 | + slave_err(slave->bond->dev, dev, "dev_set_mac_address on slave failed! ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n"); |
|---|
| 1037 | 1025 | return -EOPNOTSUPP; |
|---|
| 1038 | 1026 | } |
|---|
| 1039 | 1027 | return 0; |
|---|
| .. | .. |
|---|
| 1208 | 1196 | alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr, |
|---|
| 1209 | 1197 | free_mac_slave->dev->addr_len); |
|---|
| 1210 | 1198 | |
|---|
| 1211 | | - netdev_warn(bond->dev, "the hw address of slave %s is in use by the bond; giving it the hw address of %s\n", |
|---|
| 1212 | | - slave->dev->name, free_mac_slave->dev->name); |
|---|
| 1199 | + slave_warn(bond->dev, slave->dev, "the slave hw address is in use by the bond; giving it the hw address of %s\n", |
|---|
| 1200 | + free_mac_slave->dev->name); |
|---|
| 1213 | 1201 | |
|---|
| 1214 | 1202 | } else if (has_bond_addr) { |
|---|
| 1215 | | - netdev_err(bond->dev, "the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n", |
|---|
| 1216 | | - slave->dev->name); |
|---|
| 1203 | + slave_err(bond->dev, slave->dev, "the slave hw address is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n"); |
|---|
| 1217 | 1204 | return -EFAULT; |
|---|
| 1218 | 1205 | } |
|---|
| 1219 | 1206 | |
|---|
| .. | .. |
|---|
| 1222 | 1209 | |
|---|
| 1223 | 1210 | /** |
|---|
| 1224 | 1211 | * alb_set_mac_address |
|---|
| 1225 | | - * @bond: |
|---|
| 1226 | | - * @addr: |
|---|
| 1212 | + * @bond: bonding we're working on |
|---|
| 1213 | + * @addr: MAC address to set |
|---|
| 1227 | 1214 | * |
|---|
| 1228 | 1215 | * In TLB mode all slaves are configured to the bond's hw address, but set |
|---|
| 1229 | 1216 | * their dev_addr field to different addresses (based on their permanent hw |
|---|
| .. | .. |
|---|
| 1250 | 1237 | bond_hw_addr_copy(tmp_addr, slave->dev->dev_addr, |
|---|
| 1251 | 1238 | slave->dev->addr_len); |
|---|
| 1252 | 1239 | |
|---|
| 1253 | | - res = dev_set_mac_address(slave->dev, addr); |
|---|
| 1240 | + res = dev_set_mac_address(slave->dev, addr, NULL); |
|---|
| 1254 | 1241 | |
|---|
| 1255 | 1242 | /* restore net_device's hw address */ |
|---|
| 1256 | 1243 | bond_hw_addr_copy(slave->dev->dev_addr, tmp_addr, |
|---|
| .. | .. |
|---|
| 1273 | 1260 | bond_hw_addr_copy(tmp_addr, rollback_slave->dev->dev_addr, |
|---|
| 1274 | 1261 | rollback_slave->dev->addr_len); |
|---|
| 1275 | 1262 | dev_set_mac_address(rollback_slave->dev, |
|---|
| 1276 | | - (struct sockaddr *)&ss); |
|---|
| 1263 | + (struct sockaddr *)&ss, NULL); |
|---|
| 1277 | 1264 | bond_hw_addr_copy(rollback_slave->dev->dev_addr, tmp_addr, |
|---|
| 1278 | 1265 | rollback_slave->dev->addr_len); |
|---|
| 1279 | 1266 | } |
|---|
| .. | .. |
|---|
| 1292 | 1279 | return res; |
|---|
| 1293 | 1280 | |
|---|
| 1294 | 1281 | if (rlb_enabled) { |
|---|
| 1295 | | - bond->alb_info.rlb_enabled = 1; |
|---|
| 1296 | 1282 | res = rlb_initialize(bond); |
|---|
| 1297 | 1283 | if (res) { |
|---|
| 1298 | 1284 | tlb_deinitialize(bond); |
|---|
| 1299 | 1285 | return res; |
|---|
| 1300 | 1286 | } |
|---|
| 1287 | + bond->alb_info.rlb_enabled = 1; |
|---|
| 1301 | 1288 | } else { |
|---|
| 1302 | 1289 | bond->alb_info.rlb_enabled = 0; |
|---|
| 1303 | 1290 | } |
|---|
| .. | .. |
|---|
| 1334 | 1321 | tx_slave->dev->dev_addr); |
|---|
| 1335 | 1322 | } |
|---|
| 1336 | 1323 | |
|---|
| 1337 | | - bond_dev_queue_xmit(bond, skb, tx_slave->dev); |
|---|
| 1338 | | - goto out; |
|---|
| 1324 | + return bond_dev_queue_xmit(bond, skb, tx_slave->dev); |
|---|
| 1339 | 1325 | } |
|---|
| 1340 | 1326 | |
|---|
| 1341 | 1327 | if (tx_slave && bond->params.tlb_dynamic_lb) { |
|---|
| .. | .. |
|---|
| 1345 | 1331 | } |
|---|
| 1346 | 1332 | |
|---|
| 1347 | 1333 | /* no suitable interface, frame not sent */ |
|---|
| 1348 | | - bond_tx_drop(bond->dev, skb); |
|---|
| 1349 | | -out: |
|---|
| 1350 | | - return NETDEV_TX_OK; |
|---|
| 1334 | + return bond_tx_drop(bond->dev, skb); |
|---|
| 1351 | 1335 | } |
|---|
| 1352 | 1336 | |
|---|
| 1353 | | -netdev_tx_t bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev) |
|---|
| 1337 | +struct slave *bond_xmit_tlb_slave_get(struct bonding *bond, |
|---|
| 1338 | + struct sk_buff *skb) |
|---|
| 1354 | 1339 | { |
|---|
| 1355 | | - struct bonding *bond = netdev_priv(bond_dev); |
|---|
| 1356 | | - struct ethhdr *eth_data; |
|---|
| 1357 | 1340 | struct slave *tx_slave = NULL; |
|---|
| 1341 | + struct ethhdr *eth_data; |
|---|
| 1358 | 1342 | u32 hash_index; |
|---|
| 1359 | 1343 | |
|---|
| 1360 | 1344 | skb_reset_mac_header(skb); |
|---|
| .. | .. |
|---|
| 1376 | 1360 | struct bond_up_slave *slaves; |
|---|
| 1377 | 1361 | unsigned int count; |
|---|
| 1378 | 1362 | |
|---|
| 1379 | | - slaves = rcu_dereference(bond->slave_arr); |
|---|
| 1363 | + slaves = rcu_dereference(bond->usable_slaves); |
|---|
| 1380 | 1364 | count = slaves ? READ_ONCE(slaves->count) : 0; |
|---|
| 1381 | 1365 | if (likely(count)) |
|---|
| 1382 | 1366 | tx_slave = slaves->arr[hash_index % |
|---|
| .. | .. |
|---|
| 1385 | 1369 | break; |
|---|
| 1386 | 1370 | } |
|---|
| 1387 | 1371 | } |
|---|
| 1372 | + return tx_slave; |
|---|
| 1373 | +} |
|---|
| 1374 | + |
|---|
| 1375 | +netdev_tx_t bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev) |
|---|
| 1376 | +{ |
|---|
| 1377 | + struct bonding *bond = netdev_priv(bond_dev); |
|---|
| 1378 | + struct slave *tx_slave; |
|---|
| 1379 | + |
|---|
| 1380 | + tx_slave = bond_xmit_tlb_slave_get(bond, skb); |
|---|
| 1388 | 1381 | return bond_do_alb_xmit(skb, bond, tx_slave); |
|---|
| 1389 | 1382 | } |
|---|
| 1390 | 1383 | |
|---|
| 1391 | | -netdev_tx_t bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) |
|---|
| 1384 | +struct slave *bond_xmit_alb_slave_get(struct bonding *bond, |
|---|
| 1385 | + struct sk_buff *skb) |
|---|
| 1392 | 1386 | { |
|---|
| 1393 | | - struct bonding *bond = netdev_priv(bond_dev); |
|---|
| 1394 | | - struct ethhdr *eth_data; |
|---|
| 1395 | 1387 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); |
|---|
| 1396 | | - struct slave *tx_slave = NULL; |
|---|
| 1397 | 1388 | static const __be32 ip_bcast = htonl(0xffffffff); |
|---|
| 1398 | | - int hash_size = 0; |
|---|
| 1399 | | - bool do_tx_balance = true; |
|---|
| 1400 | | - u32 hash_index = 0; |
|---|
| 1389 | + struct slave *tx_slave = NULL; |
|---|
| 1401 | 1390 | const u8 *hash_start = NULL; |
|---|
| 1391 | + bool do_tx_balance = true; |
|---|
| 1392 | + struct ethhdr *eth_data; |
|---|
| 1393 | + u32 hash_index = 0; |
|---|
| 1394 | + int hash_size = 0; |
|---|
| 1402 | 1395 | |
|---|
| 1403 | 1396 | skb_reset_mac_header(skb); |
|---|
| 1404 | 1397 | eth_data = eth_hdr(skb); |
|---|
| .. | .. |
|---|
| 1510 | 1503 | struct bond_up_slave *slaves; |
|---|
| 1511 | 1504 | unsigned int count; |
|---|
| 1512 | 1505 | |
|---|
| 1513 | | - slaves = rcu_dereference(bond->slave_arr); |
|---|
| 1506 | + slaves = rcu_dereference(bond->usable_slaves); |
|---|
| 1514 | 1507 | count = slaves ? READ_ONCE(slaves->count) : 0; |
|---|
| 1515 | 1508 | if (likely(count)) |
|---|
| 1516 | 1509 | tx_slave = slaves->arr[bond_xmit_hash(bond, skb) % |
|---|
| 1517 | 1510 | count]; |
|---|
| 1518 | 1511 | } |
|---|
| 1519 | 1512 | } |
|---|
| 1513 | + return tx_slave; |
|---|
| 1514 | +} |
|---|
| 1520 | 1515 | |
|---|
| 1516 | +netdev_tx_t bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) |
|---|
| 1517 | +{ |
|---|
| 1518 | + struct bonding *bond = netdev_priv(bond_dev); |
|---|
| 1519 | + struct slave *tx_slave = NULL; |
|---|
| 1520 | + |
|---|
| 1521 | + tx_slave = bond_xmit_alb_slave_get(bond, skb); |
|---|
| 1521 | 1522 | return bond_do_alb_xmit(skb, bond, tx_slave); |
|---|
| 1522 | 1523 | } |
|---|
| 1523 | 1524 | |
|---|
| .. | .. |
|---|
| 1754 | 1755 | bond->dev->addr_len); |
|---|
| 1755 | 1756 | ss.ss_family = bond->dev->type; |
|---|
| 1756 | 1757 | /* we don't care if it can't change its mac, best effort */ |
|---|
| 1757 | | - dev_set_mac_address(new_slave->dev, (struct sockaddr *)&ss); |
|---|
| 1758 | + dev_set_mac_address(new_slave->dev, (struct sockaddr *)&ss, |
|---|
| 1759 | + NULL); |
|---|
| 1758 | 1760 | |
|---|
| 1759 | 1761 | bond_hw_addr_copy(new_slave->dev->dev_addr, tmp_addr, |
|---|
| 1760 | 1762 | new_slave->dev->addr_len); |
|---|