net: mpls: Fix nexthop alive tracking on down events
Alive tracking of nexthops can account for a link twice if the carrier goes down followed by an admin down of the same link rendering multipath routes useless. This is similar tozero-colors79099aab38
for UNREGISTER events and DOWN events. Fix by tracking number of alive nexthops in mpls_ifdown similar to the logic in mpls_ifup. Checking the flags per nexthop once after all events have been processed is simpler than trying to maintian a running count through all event combinations. Also, WRITE_ONCE is used instead of ACCESS_ONCE to set rt_nhn_alive per a comment from checkpatch: WARNING: Prefer WRITE_ONCE(<FOO>, <BAR>) over ACCESS_ONCE(<FOO>) = <BAR> Fixes:c89359a42e
("mpls: support for dead routes") Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Acked-by: Robert Shearman <rshearma@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
parent
bc9ab9231e
commit
61733c91c4
|
@ -1269,6 +1269,8 @@ static void mpls_ifdown(struct net_device *dev, int event)
|
|||
{
|
||||
struct mpls_route __rcu **platform_label;
|
||||
struct net *net = dev_net(dev);
|
||||
unsigned int nh_flags = RTNH_F_DEAD | RTNH_F_LINKDOWN;
|
||||
unsigned int alive;
|
||||
unsigned index;
|
||||
|
||||
platform_label = rtnl_dereference(net->mpls.platform_label);
|
||||
|
@ -1278,9 +1280,11 @@ static void mpls_ifdown(struct net_device *dev, int event)
|
|||
if (!rt)
|
||||
continue;
|
||||
|
||||
alive = 0;
|
||||
change_nexthops(rt) {
|
||||
if (rtnl_dereference(nh->nh_dev) != dev)
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_DOWN:
|
||||
case NETDEV_UNREGISTER:
|
||||
|
@ -1288,13 +1292,16 @@ static void mpls_ifdown(struct net_device *dev, int event)
|
|||
/* fall through */
|
||||
case NETDEV_CHANGE:
|
||||
nh->nh_flags |= RTNH_F_LINKDOWN;
|
||||
if (event != NETDEV_UNREGISTER)
|
||||
ACCESS_ONCE(rt->rt_nhn_alive) = rt->rt_nhn_alive - 1;
|
||||
break;
|
||||
}
|
||||
if (event == NETDEV_UNREGISTER)
|
||||
RCU_INIT_POINTER(nh->nh_dev, NULL);
|
||||
next:
|
||||
if (!(nh->nh_flags & nh_flags))
|
||||
alive++;
|
||||
} endfor_nexthops(rt);
|
||||
|
||||
WRITE_ONCE(rt->rt_nhn_alive, alive);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue