diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
| -rw-r--r-- | net/ipv4/ip_output.c | 21 | 
1 files changed, 18 insertions, 3 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index dde37fb340bf..05d105832bdb 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -73,6 +73,7 @@  #include <net/icmp.h>  #include <net/checksum.h>  #include <net/inetpeer.h> +#include <net/lwtunnel.h>  #include <linux/igmp.h>  #include <linux/netfilter_ipv4.h>  #include <linux/netfilter_bridge.h> @@ -98,6 +99,14 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)  	iph->tot_len = htons(skb->len);  	ip_send_check(iph); + +	/* if egress device is enslaved to an L3 master device pass the +	 * skb to its handler for processing +	 */ +	skb = l3mdev_ip_out(sk, skb); +	if (unlikely(!skb)) +		return 0; +  	return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,  		       net, sk, skb, NULL, skb_dst(skb)->dev,  		       dst_output); @@ -197,6 +206,13 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s  		skb = skb2;  	} +	if (lwtunnel_xmit_redirect(dst->lwtstate)) { +		int res = lwtunnel_xmit(skb); + +		if (res < 0 || res == LWTUNNEL_XMIT_DONE) +			return res; +	} +  	rcu_read_lock_bh();  	nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr);  	neigh = __ipv4_neigh_lookup_noref(dev, nexthop); @@ -482,7 +498,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)  	to->tc_index = from->tc_index;  #endif  	nf_copy(to, from); -#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) +#if IS_ENABLED(CONFIG_IP_VS)  	to->ipvs_property = from->ipvs_property;  #endif  	skb_copy_secmark(to, from); @@ -1566,8 +1582,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,  	}  	oif = arg->bound_dev_if; -	if (!oif && netif_index_is_l3_master(net, skb->skb_iif)) -		oif = skb->skb_iif; +	oif = oif ? : skb->skb_iif;  	flowi4_init_output(&fl4, oif,  			   IP4_REPLY_MARK(net, skb->mark),  |