1515#include <linux/sched/signal.h>
1616
1717#include <net/bonding.h>
18+ #include <net/ndisc.h>
1819
1920static int bond_option_active_slave_set (struct bonding * bond ,
2021 const struct bond_opt_value * newval );
@@ -1234,6 +1235,68 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond,
12341235}
12351236
12361237#if IS_ENABLED (CONFIG_IPV6 )
1238+ static bool slave_can_set_ns_maddr (const struct bonding * bond , struct slave * slave )
1239+ {
1240+ return BOND_MODE (bond ) == BOND_MODE_ACTIVEBACKUP &&
1241+ !bond_is_active_slave (slave ) &&
1242+ slave -> dev -> flags & IFF_MULTICAST ;
1243+ }
1244+
1245+ static void slave_set_ns_maddrs (struct bonding * bond , struct slave * slave , bool add )
1246+ {
1247+ struct in6_addr * targets = bond -> params .ns_targets ;
1248+ char slot_maddr [MAX_ADDR_LEN ];
1249+ int i ;
1250+
1251+ if (!slave_can_set_ns_maddr (bond , slave ))
1252+ return ;
1253+
1254+ for (i = 0 ; i < BOND_MAX_NS_TARGETS ; i ++ ) {
1255+ if (ipv6_addr_any (& targets [i ]))
1256+ break ;
1257+
1258+ if (!ndisc_mc_map (& targets [i ], slot_maddr , slave -> dev , 0 )) {
1259+ if (add )
1260+ dev_mc_add (slave -> dev , slot_maddr );
1261+ else
1262+ dev_mc_del (slave -> dev , slot_maddr );
1263+ }
1264+ }
1265+ }
1266+
1267+ void bond_slave_ns_maddrs_add (struct bonding * bond , struct slave * slave )
1268+ {
1269+ if (!bond -> params .arp_validate )
1270+ return ;
1271+ slave_set_ns_maddrs (bond , slave , true);
1272+ }
1273+
1274+ void bond_slave_ns_maddrs_del (struct bonding * bond , struct slave * slave )
1275+ {
1276+ if (!bond -> params .arp_validate )
1277+ return ;
1278+ slave_set_ns_maddrs (bond , slave , false);
1279+ }
1280+
1281+ static void slave_set_ns_maddr (struct bonding * bond , struct slave * slave ,
1282+ struct in6_addr * target , struct in6_addr * slot )
1283+ {
1284+ char target_maddr [MAX_ADDR_LEN ], slot_maddr [MAX_ADDR_LEN ];
1285+
1286+ if (!bond -> params .arp_validate || !slave_can_set_ns_maddr (bond , slave ))
1287+ return ;
1288+
1289+ /* remove the previous maddr from slave */
1290+ if (!ipv6_addr_any (slot ) &&
1291+ !ndisc_mc_map (slot , slot_maddr , slave -> dev , 0 ))
1292+ dev_mc_del (slave -> dev , slot_maddr );
1293+
1294+ /* add new maddr on slave if target is set */
1295+ if (!ipv6_addr_any (target ) &&
1296+ !ndisc_mc_map (target , target_maddr , slave -> dev , 0 ))
1297+ dev_mc_add (slave -> dev , target_maddr );
1298+ }
1299+
12371300static void _bond_options_ns_ip6_target_set (struct bonding * bond , int slot ,
12381301 struct in6_addr * target ,
12391302 unsigned long last_rx )
@@ -1243,8 +1306,10 @@ static void _bond_options_ns_ip6_target_set(struct bonding *bond, int slot,
12431306 struct slave * slave ;
12441307
12451308 if (slot >= 0 && slot < BOND_MAX_NS_TARGETS ) {
1246- bond_for_each_slave (bond , slave , iter )
1309+ bond_for_each_slave (bond , slave , iter ) {
12471310 slave -> target_last_arp_rx [slot ] = last_rx ;
1311+ slave_set_ns_maddr (bond , slave , target , & targets [slot ]);
1312+ }
12481313 targets [slot ] = * target ;
12491314 }
12501315}
@@ -1296,15 +1361,30 @@ static int bond_option_ns_ip6_targets_set(struct bonding *bond,
12961361{
12971362 return - EPERM ;
12981363}
1364+
1365+ static void slave_set_ns_maddrs (struct bonding * bond , struct slave * slave , bool add ) {}
1366+
1367+ void bond_slave_ns_maddrs_add (struct bonding * bond , struct slave * slave ) {}
1368+
1369+ void bond_slave_ns_maddrs_del (struct bonding * bond , struct slave * slave ) {}
12991370#endif
13001371
13011372static int bond_option_arp_validate_set (struct bonding * bond ,
13021373 const struct bond_opt_value * newval )
13031374{
1375+ bool changed = !!bond -> params .arp_validate != !!newval -> value ;
1376+ struct list_head * iter ;
1377+ struct slave * slave ;
1378+
13041379 netdev_dbg (bond -> dev , "Setting arp_validate to %s (%llu)\n" ,
13051380 newval -> string , newval -> value );
13061381 bond -> params .arp_validate = newval -> value ;
13071382
1383+ if (changed ) {
1384+ bond_for_each_slave (bond , slave , iter )
1385+ slave_set_ns_maddrs (bond , slave , !!bond -> params .arp_validate );
1386+ }
1387+
13081388 return 0 ;
13091389}
13101390
0 commit comments