.. | .. |
---|
| 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); |
---|