ipv4: fib: Notify about nexthop status changes
When a multipath route is hit the kernel doesn't consider nexthops that are DEAD or LINKDOWN when IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN is set. Devices that offload multipath routes need to be made aware of nexthop status changes. Otherwise, the device will keep forwarding packets to non-functional nexthops. Add the FIB_EVENT_NH_{ADD,DEL} events to the fib notification chain, which notify capable devices when they should add or delete a nexthop from their tables. Cc: Roopa Prabhu <roopa@cumulusnetworks.com> Cc: David Ahern <dsa@cumulusnetworks.com> Cc: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Reviewed-by: Andy Gospodarek <gospo@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
70ad35067c
commit
982acb9756
|
@ -214,11 +214,18 @@ struct fib_entry_notifier_info {
|
|||
u32 nlflags;
|
||||
};
|
||||
|
||||
struct fib_nh_notifier_info {
|
||||
struct fib_notifier_info info; /* must be first */
|
||||
struct fib_nh *fib_nh;
|
||||
};
|
||||
|
||||
enum fib_event_type {
|
||||
FIB_EVENT_ENTRY_ADD,
|
||||
FIB_EVENT_ENTRY_DEL,
|
||||
FIB_EVENT_RULE_ADD,
|
||||
FIB_EVENT_RULE_DEL,
|
||||
FIB_EVENT_NH_ADD,
|
||||
FIB_EVENT_NH_DEL,
|
||||
};
|
||||
|
||||
int register_fib_notifier(struct notifier_block *nb,
|
||||
|
|
|
@ -1355,6 +1355,36 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int call_fib_nh_notifiers(struct fib_nh *fib_nh,
|
||||
enum fib_event_type event_type)
|
||||
{
|
||||
struct in_device *in_dev = __in_dev_get_rtnl(fib_nh->nh_dev);
|
||||
struct fib_nh_notifier_info info = {
|
||||
.fib_nh = fib_nh,
|
||||
};
|
||||
|
||||
switch (event_type) {
|
||||
case FIB_EVENT_NH_ADD:
|
||||
if (fib_nh->nh_flags & RTNH_F_DEAD)
|
||||
break;
|
||||
if (IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
|
||||
fib_nh->nh_flags & RTNH_F_LINKDOWN)
|
||||
break;
|
||||
return call_fib_notifiers(dev_net(fib_nh->nh_dev), event_type,
|
||||
&info.info);
|
||||
case FIB_EVENT_NH_DEL:
|
||||
if ((IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
|
||||
fib_nh->nh_flags & RTNH_F_LINKDOWN) ||
|
||||
(fib_nh->nh_flags & RTNH_F_DEAD))
|
||||
return call_fib_notifiers(dev_net(fib_nh->nh_dev),
|
||||
event_type, &info.info);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/* Event force Flags Description
|
||||
* NETDEV_CHANGE 0 LINKDOWN Carrier OFF, not for scope host
|
||||
* NETDEV_DOWN 0 LINKDOWN|DEAD Link down, not for scope host
|
||||
|
@ -1396,6 +1426,8 @@ int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force)
|
|||
nexthop_nh->nh_flags |= RTNH_F_LINKDOWN;
|
||||
break;
|
||||
}
|
||||
call_fib_nh_notifiers(nexthop_nh,
|
||||
FIB_EVENT_NH_DEL);
|
||||
dead++;
|
||||
}
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
|
@ -1550,6 +1582,7 @@ int fib_sync_up(struct net_device *dev, unsigned int nh_flags)
|
|||
continue;
|
||||
alive++;
|
||||
nexthop_nh->nh_flags &= ~nh_flags;
|
||||
call_fib_nh_notifiers(nexthop_nh, FIB_EVENT_NH_ADD);
|
||||
} endfor_nexthops(fi)
|
||||
|
||||
if (alive > 0) {
|
||||
|
|
Loading…
Reference in New Issue