struct net_bridge *br = port->br;
spin_lock(&br->multicast_lock);
- if (port->multicast_router != MDB_RTR_TYPE_TEMP_QUERY ||
+ if (port->multicast_router == MDB_RTR_TYPE_DISABLED ||
+ port->multicast_router == MDB_RTR_TYPE_PERM ||
timer_pending(&port->multicast_router_timer) ||
hlist_unhashed(&port->rlist))
goto out;
hlist_del_init_rcu(&port->rlist);
br_rtr_notify(br->dev, port, RTM_DELMDB);
+ /* Don't allow timer refresh if the router expired */
+ if (port->multicast_router == MDB_RTR_TYPE_TEMP)
+ port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
out:
spin_unlock(&br->multicast_lock);
if (!hlist_unhashed(&port->rlist)) {
hlist_del_init_rcu(&port->rlist);
br_rtr_notify(br->dev, port, RTM_DELMDB);
+ /* Don't allow timer refresh if disabling */
+ if (port->multicast_router == MDB_RTR_TYPE_TEMP)
+ port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
}
del_timer(&port->multicast_router_timer);
del_timer(&port->ip4_own_query.timer);
return;
}
- if (port->multicast_router != MDB_RTR_TYPE_TEMP_QUERY)
+ if (port->multicast_router == MDB_RTR_TYPE_DISABLED ||
+ port->multicast_router == MDB_RTR_TYPE_PERM)
return;
br_multicast_add_router(br, port);
int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
{
struct net_bridge *br = p->br;
+ unsigned long now = jiffies;
int err = -EINVAL;
spin_lock(&br->multicast_lock);
if (p->multicast_router == val) {
+ /* Refresh the temp router port timer */
+ if (p->multicast_router == MDB_RTR_TYPE_TEMP)
+ mod_timer(&p->multicast_router_timer,
+ now + br->multicast_querier_interval);
err = 0;
goto unlock;
}
del_timer(&p->multicast_router_timer);
br_multicast_add_router(br, p);
break;
+ case MDB_RTR_TYPE_TEMP:
+ p->multicast_router = MDB_RTR_TYPE_TEMP;
+ br_multicast_mark_router(br, p);
+ break;
default:
goto unlock;
}