ip_tunnel: allow to inherit from VLAN encapsulated IP
The current code allows to inherit the TOS, TTL, DF from the payload when skb->protocol is ETH_P_IP or ETH_P_IPV6. However when the payload is VLAN encapsulated (e.g because the tunnel is of type GRETAP), then this inheriting does not work, because the visible skb->protocol is of type ETH_P_8021Q or ETH_P_8021AD. Instead of skb->protocol, use skb_protocol(). Signed-off-by: Matthias May <matthias.may@westermo.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b6afeb87ad
commit
7ae29fd1be
1 changed files with 9 additions and 8 deletions
|
@ -641,6 +641,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||||
const struct iphdr *inner_iph;
|
const struct iphdr *inner_iph;
|
||||||
unsigned int max_headroom; /* The extra header space needed */
|
unsigned int max_headroom; /* The extra header space needed */
|
||||||
struct rtable *rt = NULL; /* Route to the other host */
|
struct rtable *rt = NULL; /* Route to the other host */
|
||||||
|
__be16 payload_protocol;
|
||||||
bool use_cache = false;
|
bool use_cache = false;
|
||||||
struct flowi4 fl4;
|
struct flowi4 fl4;
|
||||||
bool md = false;
|
bool md = false;
|
||||||
|
@ -651,6 +652,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||||
|
|
||||||
inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
|
inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
|
||||||
connected = (tunnel->parms.iph.daddr != 0);
|
connected = (tunnel->parms.iph.daddr != 0);
|
||||||
|
payload_protocol = skb_protocol(skb, true);
|
||||||
|
|
||||||
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
||||||
|
|
||||||
|
@ -670,13 +672,12 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||||
dst = tun_info->key.u.ipv4.dst;
|
dst = tun_info->key.u.ipv4.dst;
|
||||||
md = true;
|
md = true;
|
||||||
connected = true;
|
connected = true;
|
||||||
}
|
} else if (payload_protocol == htons(ETH_P_IP)) {
|
||||||
else if (skb->protocol == htons(ETH_P_IP)) {
|
|
||||||
rt = skb_rtable(skb);
|
rt = skb_rtable(skb);
|
||||||
dst = rt_nexthop(rt, inner_iph->daddr);
|
dst = rt_nexthop(rt, inner_iph->daddr);
|
||||||
}
|
}
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
else if (skb->protocol == htons(ETH_P_IPV6)) {
|
else if (payload_protocol == htons(ETH_P_IPV6)) {
|
||||||
const struct in6_addr *addr6;
|
const struct in6_addr *addr6;
|
||||||
struct neighbour *neigh;
|
struct neighbour *neigh;
|
||||||
bool do_tx_error_icmp;
|
bool do_tx_error_icmp;
|
||||||
|
@ -716,10 +717,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||||
tos = tnl_params->tos;
|
tos = tnl_params->tos;
|
||||||
if (tos & 0x1) {
|
if (tos & 0x1) {
|
||||||
tos &= ~0x1;
|
tos &= ~0x1;
|
||||||
if (skb->protocol == htons(ETH_P_IP)) {
|
if (payload_protocol == htons(ETH_P_IP)) {
|
||||||
tos = inner_iph->tos;
|
tos = inner_iph->tos;
|
||||||
connected = false;
|
connected = false;
|
||||||
} else if (skb->protocol == htons(ETH_P_IPV6)) {
|
} else if (payload_protocol == htons(ETH_P_IPV6)) {
|
||||||
tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
|
tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
|
||||||
connected = false;
|
connected = false;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +766,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
df = tnl_params->frag_off;
|
df = tnl_params->frag_off;
|
||||||
if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
|
if (payload_protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
|
||||||
df |= (inner_iph->frag_off & htons(IP_DF));
|
df |= (inner_iph->frag_off & htons(IP_DF));
|
||||||
|
|
||||||
if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) {
|
if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) {
|
||||||
|
@ -786,10 +787,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||||
tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
|
tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
|
||||||
ttl = tnl_params->ttl;
|
ttl = tnl_params->ttl;
|
||||||
if (ttl == 0) {
|
if (ttl == 0) {
|
||||||
if (skb->protocol == htons(ETH_P_IP))
|
if (payload_protocol == htons(ETH_P_IP))
|
||||||
ttl = inner_iph->ttl;
|
ttl = inner_iph->ttl;
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
else if (skb->protocol == htons(ETH_P_IPV6))
|
else if (payload_protocol == htons(ETH_P_IPV6))
|
||||||
ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
|
ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
|
|
Loading…
Add table
Reference in a new issue