|
@@ -586,7 +586,8 @@ int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
|
|
EXPORT_SYMBOL(ip_tunnel_encap);
|
|
EXPORT_SYMBOL(ip_tunnel_encap);
|
|
|
|
|
|
static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
|
|
static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
|
|
- struct rtable *rt, __be16 df)
|
|
|
|
|
|
+ struct rtable *rt, __be16 df,
|
|
|
|
+ const struct iphdr *inner_iph)
|
|
{
|
|
{
|
|
struct ip_tunnel *tunnel = netdev_priv(dev);
|
|
struct ip_tunnel *tunnel = netdev_priv(dev);
|
|
int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
|
|
int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
|
|
@@ -603,7 +604,8 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
|
|
|
|
|
|
if (skb->protocol == htons(ETH_P_IP)) {
|
|
if (skb->protocol == htons(ETH_P_IP)) {
|
|
if (!skb_is_gso(skb) &&
|
|
if (!skb_is_gso(skb) &&
|
|
- (df & htons(IP_DF)) && mtu < pkt_size) {
|
|
|
|
|
|
+ (inner_iph->frag_off & htons(IP_DF)) &&
|
|
|
|
+ mtu < pkt_size) {
|
|
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
|
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
|
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
|
|
return -E2BIG;
|
|
return -E2BIG;
|
|
@@ -737,7 +739,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
|
goto tx_error;
|
|
goto tx_error;
|
|
}
|
|
}
|
|
|
|
|
|
- if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
|
|
|
|
|
|
+ if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) {
|
|
ip_rt_put(rt);
|
|
ip_rt_put(rt);
|
|
goto tx_error;
|
|
goto tx_error;
|
|
}
|
|
}
|