diff --git a/include/net/mrp.h b/include/net/mrp.h index 4fbf02aa2ec1e7..0f7558b638ae6f 100644 --- a/include/net/mrp.h +++ b/include/net/mrp.h @@ -112,6 +112,7 @@ struct mrp_applicant { struct mrp_application *app; struct net_device *dev; struct timer_list join_timer; + struct timer_list periodic_timer; spinlock_t lock; struct sk_buff_head queue; diff --git a/net/802/mrp.c b/net/802/mrp.c index 1eb05d80b07bea..97566ecdabcb26 100644 --- a/net/802/mrp.c +++ b/net/802/mrp.c @@ -24,6 +24,11 @@ static unsigned int mrp_join_time __read_mostly = 200; module_param(mrp_join_time, uint, 0644); MODULE_PARM_DESC(mrp_join_time, "Join time in ms (default 200ms)"); + +static unsigned int mrp_periodic_time __read_mostly = 1000; +module_param(mrp_periodic_time, uint, 0644); +MODULE_PARM_DESC(mrp_periodic_time, "Periodic time in ms (default 1s)"); + MODULE_LICENSE("GPL"); static const u8 @@ -595,6 +600,43 @@ static void mrp_join_timer(unsigned long data) mrp_join_timer_arm(app); } +static void mrp_periodic_timer_arm(struct mrp_applicant *app) +{ + unsigned long delay; + + delay = (u64)msecs_to_jiffies(mrp_periodic_time); + mod_timer(&app->periodic_timer, jiffies + delay); +} + + +/* + Added periodic timer from [802.1Q-2011] to retry if MRP loses + messages. MRP used to lose JoinIn messages and never retry if it + sent messages before the interface becomes ready. + + The periodic timer from the 802.1Q spec never turns off. It fires + every second, causing MRP to bounce from state QA to AA and back. + You might think that would stop when the registrar responds with an + JoinIn, but there's no state in the MRP state table to ignore the + periodic timer after getting a reply. The result is MRP sends a + JoinIn message every second. This may not be desirable, but it's + what the spec requires. + + [802.1Q-2011] + http://standards.ieee.org/findstds/standard/802.1Q-2011.html +*/ +static void mrp_periodic_timer(unsigned long data) +{ + struct mrp_applicant *app = (struct mrp_applicant *)data; + + spin_lock(&app->lock); + mrp_mad_event(app, MRP_EVENT_PERIODIC); + mrp_pdu_queue(app); + spin_unlock(&app->lock); + + mrp_periodic_timer_arm(app); +} + static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset) { __be16 endmark; @@ -845,6 +887,8 @@ int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl) rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app); setup_timer(&app->join_timer, mrp_join_timer, (unsigned long)app); mrp_join_timer_arm(app); + setup_timer(&app->periodic_timer, mrp_periodic_timer, (unsigned long)app); + mrp_periodic_timer_arm(app); return 0; err3: @@ -870,6 +914,7 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl) * all pending messages before the applicant is gone. */ del_timer_sync(&app->join_timer); + del_timer_sync(&app->periodic_timer); spin_lock_bh(&app->lock); mrp_mad_event(app, MRP_EVENT_TX);