summaryrefslogtreecommitdiffstats
path: root/drivers/net/team
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2013-07-20 06:13:54 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-23 19:52:47 -0400
commit492b200efdd20b8fcfdac873f3cd8d4902386581 (patch)
tree71a8b0b141e7a44afcf18304911d036d5be77c6e /drivers/net/team
parent4aa5dee4d9997879adff858514844efab5a15a01 (diff)
team: add support for sending multicast rejoins
Similar to what is implemented in bonding. User is able to ask team driver to send IGMP rejoins in case port is enabled or disabled. Using previously introduced netdev notifier. Signed-off-by: Jiri Pirko <jiri@resnulli.us> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/team')
-rw-r--r--drivers/net/team/team.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 2587dc86d533..75159e4184fd 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -662,6 +662,46 @@ static void team_notify_peers_fini(struct team *team)
662} 662}
663 663
664 664
665/*******************************
666 * Send multicast group rejoins
667 *******************************/
668
669static void team_mcast_rejoin_work(struct work_struct *work)
670{
671 struct team *team;
672
673 team = container_of(work, struct team, mcast_rejoin.dw.work);
674
675 if (!rtnl_trylock()) {
676 schedule_delayed_work(&team->mcast_rejoin.dw, 0);
677 return;
678 }
679 call_netdevice_notifiers(NETDEV_RESEND_IGMP, team->dev);
680 rtnl_unlock();
681 if (!atomic_dec_and_test(&team->mcast_rejoin.count_pending))
682 schedule_delayed_work(&team->mcast_rejoin.dw,
683 msecs_to_jiffies(team->mcast_rejoin.interval));
684}
685
686static void team_mcast_rejoin(struct team *team)
687{
688 if (!team->mcast_rejoin.count || !netif_running(team->dev))
689 return;
690 atomic_set(&team->mcast_rejoin.count_pending, team->mcast_rejoin.count);
691 schedule_delayed_work(&team->mcast_rejoin.dw, 0);
692}
693
694static void team_mcast_rejoin_init(struct team *team)
695{
696 INIT_DELAYED_WORK(&team->mcast_rejoin.dw, team_mcast_rejoin_work);
697}
698
699static void team_mcast_rejoin_fini(struct team *team)
700{
701 cancel_delayed_work_sync(&team->mcast_rejoin.dw);
702}
703
704
665/************************ 705/************************
666 * Rx path frame handler 706 * Rx path frame handler
667 ************************/ 707 ************************/
@@ -887,6 +927,7 @@ static void team_port_enable(struct team *team,
887 if (team->ops.port_enabled) 927 if (team->ops.port_enabled)
888 team->ops.port_enabled(team, port); 928 team->ops.port_enabled(team, port);
889 team_notify_peers(team); 929 team_notify_peers(team);
930 team_mcast_rejoin(team);
890} 931}
891 932
892static void __reconstruct_port_hlist(struct team *team, int rm_index) 933static void __reconstruct_port_hlist(struct team *team, int rm_index)
@@ -917,6 +958,7 @@ static void team_port_disable(struct team *team,
917 team_queue_override_port_del(team, port); 958 team_queue_override_port_del(team, port);
918 team_adjust_ops(team); 959 team_adjust_ops(team);
919 team_notify_peers(team); 960 team_notify_peers(team);
961 team_mcast_rejoin(team);
920} 962}
921 963
922#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ 964#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
@@ -1275,6 +1317,34 @@ static int team_notify_peers_interval_set(struct team *team,
1275 return 0; 1317 return 0;
1276} 1318}
1277 1319
1320static int team_mcast_rejoin_count_get(struct team *team,
1321 struct team_gsetter_ctx *ctx)
1322{
1323 ctx->data.u32_val = team->mcast_rejoin.count;
1324 return 0;
1325}
1326
1327static int team_mcast_rejoin_count_set(struct team *team,
1328 struct team_gsetter_ctx *ctx)
1329{
1330 team->mcast_rejoin.count = ctx->data.u32_val;
1331 return 0;
1332}
1333
1334static int team_mcast_rejoin_interval_get(struct team *team,
1335 struct team_gsetter_ctx *ctx)
1336{
1337 ctx->data.u32_val = team->mcast_rejoin.interval;
1338 return 0;
1339}
1340
1341static int team_mcast_rejoin_interval_set(struct team *team,
1342 struct team_gsetter_ctx *ctx)
1343{
1344 team->mcast_rejoin.interval = ctx->data.u32_val;
1345 return 0;
1346}
1347
1278static int team_port_en_option_get(struct team *team, 1348static int team_port_en_option_get(struct team *team,
1279 struct team_gsetter_ctx *ctx) 1349 struct team_gsetter_ctx *ctx)
1280{ 1350{
@@ -1399,6 +1469,18 @@ static const struct team_option team_options[] = {
1399 .setter = team_notify_peers_interval_set, 1469 .setter = team_notify_peers_interval_set,
1400 }, 1470 },
1401 { 1471 {
1472 .name = "mcast_rejoin_count",
1473 .type = TEAM_OPTION_TYPE_U32,
1474 .getter = team_mcast_rejoin_count_get,
1475 .setter = team_mcast_rejoin_count_set,
1476 },
1477 {
1478 .name = "mcast_rejoin_interval",
1479 .type = TEAM_OPTION_TYPE_U32,
1480 .getter = team_mcast_rejoin_interval_get,
1481 .setter = team_mcast_rejoin_interval_set,
1482 },
1483 {
1402 .name = "enabled", 1484 .name = "enabled",
1403 .type = TEAM_OPTION_TYPE_BOOL, 1485 .type = TEAM_OPTION_TYPE_BOOL,
1404 .per_port = true, 1486 .per_port = true,
@@ -1480,6 +1562,7 @@ static int team_init(struct net_device *dev)
1480 INIT_LIST_HEAD(&team->option_inst_list); 1562 INIT_LIST_HEAD(&team->option_inst_list);
1481 1563
1482 team_notify_peers_init(team); 1564 team_notify_peers_init(team);
1565 team_mcast_rejoin_init(team);
1483 1566
1484 err = team_options_register(team, team_options, ARRAY_SIZE(team_options)); 1567 err = team_options_register(team, team_options, ARRAY_SIZE(team_options));
1485 if (err) 1568 if (err)
@@ -1491,6 +1574,7 @@ static int team_init(struct net_device *dev)
1491 return 0; 1574 return 0;
1492 1575
1493err_options_register: 1576err_options_register:
1577 team_mcast_rejoin_fini(team);
1494 team_notify_peers_fini(team); 1578 team_notify_peers_fini(team);
1495 team_queue_override_fini(team); 1579 team_queue_override_fini(team);
1496err_team_queue_override_init: 1580err_team_queue_override_init:
@@ -1511,6 +1595,7 @@ static void team_uninit(struct net_device *dev)
1511 1595
1512 __team_change_mode(team, NULL); /* cleanup */ 1596 __team_change_mode(team, NULL); /* cleanup */
1513 __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); 1597 __team_options_unregister(team, team_options, ARRAY_SIZE(team_options));
1598 team_mcast_rejoin_fini(team);
1514 team_notify_peers_fini(team); 1599 team_notify_peers_fini(team);
1515 team_queue_override_fini(team); 1600 team_queue_override_fini(team);
1516 mutex_unlock(&team->lock); 1601 mutex_unlock(&team->lock);