Revert "net: Add l3mdev index to flow struct and avoid oif reset for port devices"

This reverts commit 740de19877 which is
commit 40867d74c374b235e14d839f3a77f26684feefe5 upstream.

It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.

Bug: 161946584
Change-Id: I338a2fc5a37732a8e54dfdadf37b360cd1881991
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman 2024-11-09 16:48:24 +00:00
parent 5cb5d15755
commit 4098b69102
12 changed files with 63 additions and 37 deletions

View File

@ -470,13 +470,14 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
memset(&fl6, 0, sizeof(fl6));
/* needed to match OIF rule */
fl6.flowi6_l3mdev = dev->ifindex;
fl6.flowi6_oif = dev->ifindex;
fl6.flowi6_iif = LOOPBACK_IFINDEX;
fl6.daddr = iph->daddr;
fl6.saddr = iph->saddr;
fl6.flowlabel = ip6_flowinfo(iph);
fl6.flowi6_mark = skb->mark;
fl6.flowi6_proto = iph->nexthdr;
fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
dst = ip6_dst_lookup_flow(net, NULL, &fl6, NULL);
if (IS_ERR(dst) || dst == dst_null)
@ -549,10 +550,10 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
memset(&fl4, 0, sizeof(fl4));
/* needed to match OIF rule */
fl4.flowi4_l3mdev = vrf_dev->ifindex;
fl4.flowi4_oif = vrf_dev->ifindex;
fl4.flowi4_iif = LOOPBACK_IFINDEX;
fl4.flowi4_tos = RT_TOS(ip4h->tos);
fl4.flowi4_flags = FLOWI_FLAG_ANYSRC;
fl4.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF;
fl4.flowi4_proto = ip4h->protocol;
fl4.daddr = ip4h->daddr;
fl4.saddr = ip4h->saddr;

View File

@ -29,7 +29,6 @@ struct flowi_tunnel {
struct flowi_common {
int flowic_oif;
int flowic_iif;
int flowic_l3mdev;
__u32 flowic_mark;
__u8 flowic_tos;
__u8 flowic_scope;
@ -37,6 +36,7 @@ struct flowi_common {
__u8 flowic_flags;
#define FLOWI_FLAG_ANYSRC 0x01
#define FLOWI_FLAG_KNOWN_NH 0x02
#define FLOWI_FLAG_SKIP_NH_OIF 0x04
__u32 flowic_secid;
kuid_t flowic_uid;
struct flowi_tunnel flowic_tun_key;
@ -71,7 +71,6 @@ struct flowi4 {
struct flowi_common __fl_common;
#define flowi4_oif __fl_common.flowic_oif
#define flowi4_iif __fl_common.flowic_iif
#define flowi4_l3mdev __fl_common.flowic_l3mdev
#define flowi4_mark __fl_common.flowic_mark
#define flowi4_tos __fl_common.flowic_tos
#define flowi4_scope __fl_common.flowic_scope
@ -105,7 +104,6 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
{
fl4->flowi4_oif = oif;
fl4->flowi4_iif = LOOPBACK_IFINDEX;
fl4->flowi4_l3mdev = 0;
fl4->flowi4_mark = mark;
fl4->flowi4_tos = tos;
fl4->flowi4_scope = scope;
@ -136,7 +134,6 @@ struct flowi6 {
struct flowi_common __fl_common;
#define flowi6_oif __fl_common.flowic_oif
#define flowi6_iif __fl_common.flowic_iif
#define flowi6_l3mdev __fl_common.flowic_l3mdev
#define flowi6_mark __fl_common.flowic_mark
#define flowi6_scope __fl_common.flowic_scope
#define flowi6_proto __fl_common.flowic_proto
@ -183,7 +180,6 @@ struct flowi {
} u;
#define flowi_oif u.__fl_common.flowic_oif
#define flowi_iif u.__fl_common.flowic_iif
#define flowi_l3mdev u.__fl_common.flowic_l3mdev
#define flowi_mark u.__fl_common.flowic_mark
#define flowi_tos u.__fl_common.flowic_tos
#define flowi_scope u.__fl_common.flowic_scope

View File

@ -290,7 +290,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev);
struct flowi4 fl4 = {
.flowi4_iif = LOOPBACK_IFINDEX,
.flowi4_l3mdev = l3mdev_master_ifindex_rcu(dev),
.flowi4_oif = l3mdev_master_ifindex_rcu(dev),
.daddr = ip_hdr(skb)->saddr,
.flowi4_tos = ip_hdr(skb)->tos & IPTOS_RT_MASK,
.flowi4_scope = scope,
@ -352,8 +352,9 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
bool dev_match;
fl4.flowi4_oif = 0;
fl4.flowi4_l3mdev = l3mdev_master_ifindex_rcu(dev);
fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX;
fl4.flowi4_iif = l3mdev_master_ifindex_rcu(dev);
if (!fl4.flowi4_iif)
fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX;
fl4.daddr = src;
fl4.saddr = dst;
fl4.flowi4_tos = tos;

View File

@ -2267,7 +2267,7 @@ void fib_select_multipath(struct fib_result *res, int hash)
void fib_select_path(struct net *net, struct fib_result *res,
struct flowi4 *fl4, const struct sk_buff *skb)
{
if (fl4->flowi4_oif)
if (fl4->flowi4_oif && !(fl4->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF))
goto check_saddr;
#ifdef CONFIG_IP_ROUTE_MULTIPATH

View File

@ -1384,8 +1384,11 @@ bool fib_lookup_good_nhc(const struct fib_nh_common *nhc, int fib_flags,
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
return false;
if (flp->flowi4_oif && flp->flowi4_oif != nhc->nhc_oif)
return false;
if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) {
if (flp->flowi4_oif &&
flp->flowi4_oif != nhc->nhc_oif)
return false;
}
return true;
}

View File

@ -2191,7 +2191,6 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
/*
* Now we are ready to route packet.
*/
fl4.flowi4_l3mdev = 0;
fl4.flowi4_oif = 0;
fl4.flowi4_iif = dev->ifindex;
fl4.flowi4_mark = skb->mark;
@ -2664,7 +2663,8 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
res->fi = NULL;
res->table = NULL;
if (fl4->flowi4_oif &&
(ipv4_is_multicast(fl4->daddr) || !fl4->flowi4_l3mdev)) {
(ipv4_is_multicast(fl4->daddr) ||
!netif_index_is_l3_master(net, fl4->flowi4_oif))) {
/* Apparently, routing tables are wrong. Assume,
that the destination is on link.

View File

@ -28,11 +28,13 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
memset(fl4, 0, sizeof(*fl4));
fl4->daddr = daddr->a4;
fl4->flowi4_tos = tos;
fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
fl4->flowi4_oif = l3mdev_master_ifindex_by_index(net, oif);
fl4->flowi4_mark = mark;
if (saddr)
fl4->saddr = saddr->a4;
fl4->flowi4_flags = FLOWI_FLAG_SKIP_NH_OIF;
rt = __ip_route_output_key(net, fl4);
if (!IS_ERR(rt))
return &rt->dst;

View File

@ -1067,7 +1067,8 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
#ifdef CONFIG_IPV6_SUBTREES
ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) ||
#endif
(fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) {
(!(fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) &&
(fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex))) {
dst_release(dst);
dst = NULL;
}

View File

@ -1207,6 +1207,9 @@ INDIRECT_CALLABLE_SCOPE struct rt6_info *ip6_pol_route_lookup(struct net *net,
struct fib6_node *fn;
struct rt6_info *rt;
if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
flags &= ~RT6_LOOKUP_F_IFACE;
rcu_read_lock();
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
restart:
@ -2180,6 +2183,9 @@ int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif,
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
saved_fn = fn;
if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
oif = 0;
redo_rt6_select:
rt6_select(net, fn, oif, res, strict);
if (res->f6i == net->ipv6.fib6_null_entry) {
@ -2926,6 +2932,12 @@ INDIRECT_CALLABLE_SCOPE struct rt6_info *__ip6_route_redirect(struct net *net,
struct fib6_info *rt;
struct fib6_node *fn;
/* l3mdev_update_flow overrides oif if the device is enslaved; in
* this case we must match on the real ingress device, so reset it
*/
if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
fl6->flowi6_oif = skb->dev->ifindex;
/* Get the "current" route for this destination and
* check if the redirect has come from appropriate router.
*

View File

@ -33,7 +33,8 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
int err;
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
fl6.flowi6_oif = l3mdev_master_ifindex_by_index(net, oif);
fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
fl6.flowi6_mark = mark;
memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
if (saddr)

View File

@ -249,19 +249,25 @@ int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
struct net_device *dev;
int rc = 0;
/* update flow ensures flowi_l3mdev is set when relevant */
if (!fl->flowi_l3mdev)
return 0;
rcu_read_lock();
dev = dev_get_by_index_rcu(net, fl->flowi_l3mdev);
dev = dev_get_by_index_rcu(net, fl->flowi_oif);
if (dev && netif_is_l3_master(dev) &&
dev->l3mdev_ops->l3mdev_fib_table) {
arg->table = dev->l3mdev_ops->l3mdev_fib_table(dev);
rc = 1;
goto out;
}
dev = dev_get_by_index_rcu(net, fl->flowi_iif);
if (dev && netif_is_l3_master(dev) &&
dev->l3mdev_ops->l3mdev_fib_table) {
arg->table = dev->l3mdev_ops->l3mdev_fib_table(dev);
rc = 1;
goto out;
}
out:
rcu_read_unlock();
return rc;
@ -270,28 +276,31 @@ int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
void l3mdev_update_flow(struct net *net, struct flowi *fl)
{
struct net_device *dev;
int ifindex;
rcu_read_lock();
if (fl->flowi_oif) {
dev = dev_get_by_index_rcu(net, fl->flowi_oif);
if (dev) {
if (!fl->flowi_l3mdev)
fl->flowi_l3mdev = l3mdev_master_ifindex_rcu(dev);
/* oif set to L3mdev directs lookup to its table;
* reset to avoid oif match in fib_lookup
*/
if (netif_is_l3_master(dev))
fl->flowi_oif = 0;
goto out;
ifindex = l3mdev_master_ifindex_rcu(dev);
if (ifindex) {
fl->flowi_oif = ifindex;
fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF;
goto out;
}
}
}
if (fl->flowi_iif > LOOPBACK_IFINDEX && !fl->flowi_l3mdev) {
if (fl->flowi_iif) {
dev = dev_get_by_index_rcu(net, fl->flowi_iif);
if (dev)
fl->flowi_l3mdev = l3mdev_master_ifindex_rcu(dev);
if (dev) {
ifindex = l3mdev_master_ifindex_rcu(dev);
if (ifindex) {
fl->flowi_iif = ifindex;
fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF;
}
}
}
out:

View File

@ -741,7 +741,7 @@ ipv4_ping_vrf()
log_start
show_hint "Fails since address on vrf device is out of device scope"
run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
log_test_addr ${a} $? 2 "ping local, device bind"
log_test_addr ${a} $? 1 "ping local, device bind"
done
#