#include <net/icmp.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#include <net/ipv6.h>
+#endif
#include <net/protocol.h>
#include <net/route.h>
#include <net/xfrm.h>
icmph->checksum = csum_fold(nskb->csum);
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static bool
ipv6_should_icmp(struct sk_buff *skb)
{
+ payload_length,
ipv6h->nexthdr, nskb->csum);
}
+#endif /* IPv6 */
static bool
send_frag_needed(struct vport *vport, const struct mutable_config *mutable,
struct sk_buff *skb, unsigned int mtu, __be32 flow_key)
{
unsigned int eth_hdr_len = ETH_HLEN;
- unsigned int total_length, header_length, payload_length;
+ unsigned int total_length = 0, header_length = 0, payload_length;
struct ethhdr *eh, *old_eh = eth_hdr(skb);
struct sk_buff *nskb;
if (!ipv4_should_icmp(skb))
return true;
- } else {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
if (mtu < IPV6_MIN_MTU)
return false;
if (!ipv6_should_icmp(skb))
return true;
}
+#endif
+ else
+ return false;
/* Allocate */
if (old_eh->h_proto == htons(ETH_P_8021Q))
header_length = sizeof(struct iphdr) + sizeof(struct icmphdr);
total_length = min_t(unsigned int, header_length +
payload_length, 576);
- } else {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else {
header_length = sizeof(struct ipv6hdr) +
sizeof(struct icmp6hdr);
total_length = min_t(unsigned int, header_length +
payload_length, IPV6_MIN_MTU);
}
+#endif
+
total_length = min(total_length, mutable->mtu);
payload_length = total_length - header_length;
/* Protocol */
if (skb->protocol == htons(ETH_P_IP))
ipv4_build_icmp(skb, nskb, mtu, payload_length);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else
ipv6_build_icmp(skb, nskb, mtu, payload_length);
+#endif
/* Assume that flow based keys are symmetric with respect to input
* and output and use the key that we were going to put on the
if (skb->protocol == htons(ETH_P_IP))
inner = ((struct iphdr *)skb_network_header(skb))->tos;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
inner = ipv6_get_dsfield((struct ipv6hdr *)skb_network_header(skb));
+#endif
else
inner = 0;
return;
IP_ECN_set_ce((struct iphdr *)(nw_header + skb->data));
- } else if (protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (protocol == htons(ETH_P_IPV6)) {
if (unlikely(!pskb_may_pull(skb, nw_header
+ sizeof(struct ipv6hdr))))
return;
IP6_ECN_set_ce((struct ipv6hdr *)(nw_header
+ skb->data));
}
+#endif
}
}
if (skb->protocol == htons(ETH_P_IP))
tot_hdr_len += sizeof(struct iphdr);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
tot_hdr_len += sizeof(struct ipv6hdr);
+#endif
else
goto out;
goto out;
}
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
if (mtu < IPV6_MIN_MTU) {
unsigned int packet_length = sizeof(struct ipv6hdr) +
ntohs(ipv6_hdr(skb)->payload_len);
goto out;
}
}
+#endif
__pskb_pull(skb, tunnel_hdr_len);
send_frag_needed(vport, mutable, skb, mtu, key);
goto error_free;
}
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
unsigned int packet_length = skb->len - ETH_HLEN
- (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
goto error_free;
}
}
+#endif
skb_reset_transport_header(skb);
new_iph = (struct iphdr *)skb_push(skb, mutable->tunnel_hlen);
const struct mutable_config *mutable = rcu_dereference(gre_vport->mutable);
struct iphdr *old_iph;
- struct ipv6hdr *old_ipv6h;
int orig_len;
struct iphdr iph;
struct rtable *rt;
if (unlikely(!pskb_may_pull(skb, skb_network_header(skb)
+ sizeof(struct iphdr) - skb->data)))
skb->protocol = 0;
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
if (unlikely(!pskb_may_pull(skb, skb_network_header(skb)
+ sizeof(struct ipv6hdr) - skb->data)))
skb->protocol = 0;
}
-
+#endif
old_iph = ip_hdr(skb);
- old_ipv6h = ipv6_hdr(skb);
iph.tos = mutable->port_config.tos;
if (mutable->port_config.flags & GRE_F_TOS_INHERIT) {
if (skb->protocol == htons(ETH_P_IP))
iph.tos = old_iph->tos;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
iph.tos = ipv6_get_dsfield(ipv6_hdr(skb));
+#endif
}
iph.tos = ecn_encapsulate(iph.tos, skb);
if (mutable->port_config.flags & GRE_F_TTL_INHERIT) {
if (skb->protocol == htons(ETH_P_IP))
iph.ttl = old_iph->ttl;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
- iph.ttl = old_ipv6h->hop_limit;
+ iph.ttl = ipv6_hdr(skb)->hop_limit;
+#endif
}
if (!iph.ttl)
iph.ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
if (skb->protocol == htons(ETH_P_IP)) {
iph.frag_off |= old_iph->frag_off & htons(IP_DF);
mtu = max(mtu, IP_MIN_MTU);
-
- } else if (skb->protocol == htons(ETH_P_IPV6))
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6))
mtu = max(mtu, IPV6_MIN_MTU);
+#endif
iph.version = 4;
iph.ihl = sizeof(struct iphdr) >> 2;