summaryrefslogtreecommitdiff
path: root/include/net/inet_ecn.h
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2012-10-09 22:35:22 (GMT)
committerJ. Bruce Fields <bfields@redhat.com>2012-10-09 22:35:22 (GMT)
commitf474af7051212b4efc8267583fad9c4ebf33ccff (patch)
tree1aa46ebc8065a341f247c2a2d9af2f624ad1d4f8 /include/net/inet_ecn.h
parent0d22f68f02c10d5d10ec5712917e5828b001a822 (diff)
parente3dd9a52cb5552c46c2a4ca7ccdfb4dab5c72457 (diff)
downloadlinux-f474af7051212b4efc8267583fad9c4ebf33ccff.tar.xz
nfs: disintegrate UAPI for nfs
This is to complete part of the Userspace API (UAPI) disintegration for which the preparatory patches were pulled recently. After these patches, userspace headers will be segregated into: include/uapi/linux/.../foo.h for the userspace interface stuff, and: include/linux/.../foo.h for the strictly kernel internal stuff. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'include/net/inet_ecn.h')
-rw-r--r--include/net/inet_ecn.h76
1 files changed, 76 insertions, 0 deletions
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
index 2fa1469..aab7375 100644
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -15,6 +15,8 @@ enum {
INET_ECN_MASK = 3,
};
+extern int sysctl_tunnel_ecn_log;
+
static inline int INET_ECN_is_ce(__u8 dsfield)
{
return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
@@ -145,4 +147,78 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb)
return 0;
}
+/*
+ * RFC 6080 4.2
+ * To decapsulate the inner header at the tunnel egress, a compliant
+ * tunnel egress MUST set the outgoing ECN field to the codepoint at the
+ * intersection of the appropriate arriving inner header (row) and outer
+ * header (column) in Figure 4
+ *
+ * +---------+------------------------------------------------+
+ * |Arriving | Arriving Outer Header |
+ * | Inner +---------+------------+------------+------------+
+ * | Header | Not-ECT | ECT(0) | ECT(1) | CE |
+ * +---------+---------+------------+------------+------------+
+ * | Not-ECT | Not-ECT |Not-ECT(!!!)|Not-ECT(!!!)| <drop>(!!!)|
+ * | ECT(0) | ECT(0) | ECT(0) | ECT(1) | CE |
+ * | ECT(1) | ECT(1) | ECT(1) (!) | ECT(1) | CE |
+ * | CE | CE | CE | CE(!!!)| CE |
+ * +---------+---------+------------+------------+------------+
+ *
+ * Figure 4: New IP in IP Decapsulation Behaviour
+ *
+ * returns 0 on success
+ * 1 if something is broken and should be logged (!!! above)
+ * 2 if packet should be dropped
+ */
+static inline int INET_ECN_decapsulate(struct sk_buff *skb,
+ __u8 outer, __u8 inner)
+{
+ if (INET_ECN_is_not_ect(inner)) {
+ switch (outer & INET_ECN_MASK) {
+ case INET_ECN_NOT_ECT:
+ return 0;
+ case INET_ECN_ECT_0:
+ case INET_ECN_ECT_1:
+ return 1;
+ case INET_ECN_CE:
+ return 2;
+ }
+ }
+
+ if (INET_ECN_is_ce(outer))
+ INET_ECN_set_ce(skb);
+
+ return 0;
+}
+
+static inline int IP_ECN_decapsulate(const struct iphdr *oiph,
+ struct sk_buff *skb)
+{
+ __u8 inner;
+
+ if (skb->protocol == htons(ETH_P_IP))
+ inner = ip_hdr(skb)->tos;
+ else if (skb->protocol == htons(ETH_P_IPV6))
+ inner = ipv6_get_dsfield(ipv6_hdr(skb));
+ else
+ return 0;
+
+ return INET_ECN_decapsulate(skb, oiph->tos, inner);
+}
+
+static inline int IP6_ECN_decapsulate(const struct ipv6hdr *oipv6h,
+ struct sk_buff *skb)
+{
+ __u8 inner;
+
+ if (skb->protocol == htons(ETH_P_IP))
+ inner = ip_hdr(skb)->tos;
+ else if (skb->protocol == htons(ETH_P_IPV6))
+ inner = ipv6_get_dsfield(ipv6_hdr(skb));
+ else
+ return 0;
+
+ return INET_ECN_decapsulate(skb, ipv6_get_dsfield(oipv6h), inner);
+}
#endif