diff options
author | David S. Miller <davem@davemloft.net> | 2019-06-28 00:06:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-28 00:06:39 -0400 |
commit | d96ff269a04be286989ead13bf8b4be55bdee8ee (patch) | |
tree | 46b6d010a9a4dfe96dc86339d1cbded8874c6b8f /net/ipv4 | |
parent | 3a49584477ff4c8838833be9f3b7cc13f0f7c0d3 (diff) | |
parent | 556e2f6020bf90f63c5dd65e9a2254be6db3185b (diff) |
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')
-rw-r--r-- | net/ipv4/ip_output.c | 25 | ||||
-rw-r--r-- | net/ipv4/raw.c | 2 | ||||
-rw-r--r-- | net/ipv4/route.c | 33 |
3 files changed, 55 insertions, 5 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 | |||
327 | static int ip_mc_finish_output(struct net *net, struct sock *sk, | 327 | static int ip_mc_finish_output(struct net *net, struct sock *sk, |
328 | struct sk_buff *skb) | 328 | struct sk_buff *skb) |
329 | { | 329 | { |
330 | int ret; | 330 | struct rtable *new_rt; |
331 | bool do_cn = false; | ||
332 | int ret, err; | ||
331 | 333 | ||
332 | ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); | 334 | ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); |
333 | switch (ret) { | 335 | switch (ret) { |
334 | case NET_XMIT_SUCCESS: | ||
335 | return dev_loopback_xmit(net, sk, skb); | ||
336 | case NET_XMIT_CN: | 336 | case NET_XMIT_CN: |
337 | return dev_loopback_xmit(net, sk, skb) ? : ret; | 337 | do_cn = true; |
338 | /* fall through */ | ||
339 | case NET_XMIT_SUCCESS: | ||
340 | break; | ||
338 | default: | 341 | default: |
339 | kfree_skb(skb); | 342 | kfree_skb(skb); |
340 | return ret; | 343 | return ret; |
341 | } | 344 | } |
345 | |||
346 | /* Reset rt_iif so that inet_iif() will return skb->skb_iif. Setting | ||
347 | * this to non-zero causes ipi_ifindex in in_pktinfo to be overwritten, | ||
348 | * see ipv4_pktinfo_prepare(). | ||
349 | */ | ||
350 | new_rt = rt_dst_clone(net->loopback_dev, skb_rtable(skb)); | ||
351 | if (new_rt) { | ||
352 | new_rt->rt_iif = 0; | ||
353 | skb_dst_drop(skb); | ||
354 | skb_dst_set(skb, &new_rt->dst); | ||
355 | } | ||
356 | |||
357 | err = dev_loopback_xmit(net, sk, skb); | ||
358 | return (do_cn && err) ? ret : err; | ||
342 | } | 359 | } |
343 | 360 | ||
344 | int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) | 361 | int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 0b8e06ca75d6..40a6abbc9cf6 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -197,7 +197,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) | |||
197 | } | 197 | } |
198 | sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, | 198 | sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, |
199 | iph->saddr, iph->daddr, | 199 | iph->saddr, iph->daddr, |
200 | skb->dev->ifindex, sdif); | 200 | dif, sdif); |
201 | } | 201 | } |
202 | out: | 202 | out: |
203 | read_unlock(&raw_v4_hashinfo.lock); | 203 | read_unlock(&raw_v4_hashinfo.lock); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 59670fafcd26..a3e466b6a60c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1648,6 +1648,39 @@ struct rtable *rt_dst_alloc(struct net_device *dev, | |||
1648 | } | 1648 | } |
1649 | EXPORT_SYMBOL(rt_dst_alloc); | 1649 | EXPORT_SYMBOL(rt_dst_alloc); |
1650 | 1650 | ||
1651 | struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt) | ||
1652 | { | ||
1653 | struct rtable *new_rt; | ||
1654 | |||
1655 | new_rt = dst_alloc(&ipv4_dst_ops, dev, 1, DST_OBSOLETE_FORCE_CHK, | ||
1656 | rt->dst.flags); | ||
1657 | |||
1658 | if (new_rt) { | ||
1659 | new_rt->rt_genid = rt_genid_ipv4(dev_net(dev)); | ||
1660 | new_rt->rt_flags = rt->rt_flags; | ||
1661 | new_rt->rt_type = rt->rt_type; | ||
1662 | new_rt->rt_is_input = rt->rt_is_input; | ||
1663 | new_rt->rt_iif = rt->rt_iif; | ||
1664 | new_rt->rt_pmtu = rt->rt_pmtu; | ||
1665 | new_rt->rt_mtu_locked = rt->rt_mtu_locked; | ||
1666 | new_rt->rt_gw_family = rt->rt_gw_family; | ||
1667 | if (rt->rt_gw_family == AF_INET) | ||
1668 | new_rt->rt_gw4 = rt->rt_gw4; | ||
1669 | else if (rt->rt_gw_family == AF_INET6) | ||
1670 | new_rt->rt_gw6 = rt->rt_gw6; | ||
1671 | INIT_LIST_HEAD(&new_rt->rt_uncached); | ||
1672 | |||
1673 | new_rt->dst.flags |= DST_HOST; | ||
1674 | new_rt->dst.input = rt->dst.input; | ||
1675 | new_rt->dst.output = rt->dst.output; | ||
1676 | new_rt->dst.error = rt->dst.error; | ||
1677 | new_rt->dst.lastuse = jiffies; | ||
1678 | new_rt->dst.lwtstate = lwtstate_get(rt->dst.lwtstate); | ||
1679 | } | ||
1680 | return new_rt; | ||
1681 | } | ||
1682 | EXPORT_SYMBOL(rt_dst_clone); | ||
1683 | |||
1651 | /* called in rcu_read_lock() section */ | 1684 | /* called in rcu_read_lock() section */ |
1652 | int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr, | 1685 | int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr, |
1653 | u8 tos, struct net_device *dev, | 1686 | u8 tos, struct net_device *dev, |