diff options
author | David S. Miller <davem@davemloft.net> | 2019-06-27 21:06:39 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-27 21:06:39 -0700 |
commit | d96ff269a04be286989ead13bf8b4be55bdee8ee (patch) | |
tree | 46b6d010a9a4dfe96dc86339d1cbded8874c6b8f /net/ipv4/ip_output.c | |
parent | 3a49584477ff4c8838833be9f3b7cc13f0f7c0d3 (diff) | |
parent | 556e2f6020bf90f63c5dd65e9a2254be6db3185b (diff) | |
download | linux-d96ff269a04be286989ead13bf8b4be55bdee8ee.tar.bz2 |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
The new route handling in ip_mc_finish_output() from 'net' overlapped
with the new support for returning congestion notifications from BPF
programs.
In order to handle this I had to take the dev_loopback_xmit() calls
out of the switch statement.
The aquantia driver conflicts were simple overlapping changes.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index cdd6c3418b9e..cc7ef0d05bbd 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -327,18 +327,35 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk static int ip_mc_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { - int ret; + struct rtable *new_rt; + bool do_cn = false; + int ret, err; ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); switch (ret) { - case NET_XMIT_SUCCESS: - return dev_loopback_xmit(net, sk, skb); case NET_XMIT_CN: - return dev_loopback_xmit(net, sk, skb) ? : ret; + do_cn = true; + /* fall through */ + case NET_XMIT_SUCCESS: + break; default: kfree_skb(skb); return ret; } + + /* Reset rt_iif so that inet_iif() will return skb->skb_iif. Setting + * this to non-zero causes ipi_ifindex in in_pktinfo to be overwritten, + * see ipv4_pktinfo_prepare(). + */ + new_rt = rt_dst_clone(net->loopback_dev, skb_rtable(skb)); + if (new_rt) { + new_rt->rt_iif = 0; + skb_dst_drop(skb); + skb_dst_set(skb, &new_rt->dst); + } + + err = dev_loopback_xmit(net, sk, skb); + return (do_cn && err) ? ret : err; } int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) |