During ip route save we may get flags RTNH_F_DEAD and RTNH_F_LINKDOWN in final dump image. But we can't set these flags back during restore, because these flags calculated dynamically in the kernel. It's an inconsistency between NLM_F_DUMP and NLM_F_CREATE.
It's fully safe to workaround it just by ignoring such flags in the kernel during RTM_NEWROUTE request processing. Later, once my patches will be merged to mainstream we can drop this commit. Reproducer: $ ip link add type veth $ ip addr add 10.0.0.1/24 dev veth0 $ ip link set veth0 up $ ip route add default via 10.0.0.1 $ ip route save > route_dump $ ip route restore < route_dump Error: Invalid rtm_flags - can not contain DEAD or LINKDOWN. Reference: [RFC PATCH net-next] rtnetlink: add RTNH_F_REJECT_MASK [RFC PATCH iproute2] ip route: save: exclude rtnh_flags which can't be set https://lore.kernel.org/netdev/20211111160240.739294-1-alexander.mikhalit...@virtuozzo.com/T/#t https://jira.sw.ru/browse/PSBM-135303 https://jira.sw.ru/browse/PSBM-140280 Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalit...@virtuozzo.com> --- net/ipv4/fib_semantics.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index e20c16aad81a..c200a2643ef4 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -683,11 +683,24 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, return -EINVAL; } +#if 0 if (rtnh->rtnh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) { NL_SET_ERR_MSG(extack, "Invalid flags for nexthop - can not contain DEAD or LINKDOWN"); return -EINVAL; } +#else + /* We just want to workaround inconsistency between dump and restore. + * During dump the userspace requests: + * nlmsg_type=RTM_GETROUTE, nlmsg_flags=NLM_F_REQUEST|NLM_F_DUMP + * it may get RTNH_F_DEAD and RTNH_F_LINKDOWN bits set on rtnh_flags. + * But during the restore process: + * nlmsg_type=RTM_NEWROUTE, nlmsg_flags=NLM_F_REQUEST|..|NLM_F_CREATE + * the userspace can't set this flags back. It's obvious inconsistency, + * let's temporarily workaround it just by ignoring excess flags. + */ + rtnh->rtnh_flags &= ~(RTNH_F_DEAD | RTNH_F_LINKDOWN); +#endif fib_cfg.fc_flags = (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags; fib_cfg.fc_oif = rtnh->rtnh_ifindex; @@ -1361,11 +1374,15 @@ struct fib_info *fib_create_info(struct fib_config *cfg, goto err_inval; } +#if 0 if (cfg->fc_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) { NL_SET_ERR_MSG(extack, "Invalid rtm_flags - can not contain DEAD or LINKDOWN"); goto err_inval; } +#else + cfg->fc_flags &= ~(RTNH_F_DEAD | RTNH_F_LINKDOWN); +#endif if (cfg->fc_nh_id) { if (!cfg->fc_mx) { -- 2.36.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel