net/sched: act_csum: compute crc32c on SCTP packets
authorDavide Caratti <dcaratti@redhat.com>
Mon, 9 Jan 2017 10:24:21 +0000 (11:24 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 9 Jan 2017 19:36:57 +0000 (14:36 -0500)
modify act_csum to compute crc32c on IPv4/IPv6 packets having SCTP in
their payload, and extend UAPI definitions accordingly.

Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/tc_act/tc_csum.h
net/sched/act_csum.c

index 8ac8041..a11bb35 100644 (file)
@@ -21,7 +21,8 @@ enum {
        TCA_CSUM_UPDATE_FLAG_IGMP    = 4,
        TCA_CSUM_UPDATE_FLAG_TCP     = 8,
        TCA_CSUM_UPDATE_FLAG_UDP     = 16,
-       TCA_CSUM_UPDATE_FLAG_UDPLITE = 32
+       TCA_CSUM_UPDATE_FLAG_UDPLITE = 32,
+       TCA_CSUM_UPDATE_FLAG_SCTP    = 64,
 };
 
 struct tc_csum {
index a0edd80..e978ccd 100644 (file)
@@ -30,6 +30,7 @@
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/ip6_checksum.h>
+#include <net/sctp/checksum.h>
 
 #include <net/act_api.h>
 
@@ -322,6 +323,25 @@ ignore_obscure_skb:
        return 1;
 }
 
+static int tcf_csum_sctp(struct sk_buff *skb, unsigned int ihl,
+                        unsigned int ipl)
+{
+       struct sctphdr *sctph;
+
+       if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_SCTP)
+               return 1;
+
+       sctph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*sctph));
+       if (!sctph)
+               return 0;
+
+       sctph->checksum = sctp_compute_cksum(skb,
+                                            skb_network_offset(skb) + ihl);
+       skb->ip_summed = CHECKSUM_NONE;
+
+       return 1;
+}
+
 static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
 {
        const struct iphdr *iph;
@@ -365,6 +385,11 @@ static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
                                               ntohs(iph->tot_len), 1))
                                goto fail;
                break;
+       case IPPROTO_SCTP:
+               if ((update_flags & TCA_CSUM_UPDATE_FLAG_SCTP) &&
+                   !tcf_csum_sctp(skb, iph->ihl * 4, ntohs(iph->tot_len)))
+                       goto fail;
+               break;
        }
 
        if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) {
@@ -481,6 +506,11 @@ static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags)
                                                       pl + sizeof(*ip6h), 1))
                                        goto fail;
                        goto done;
+               case IPPROTO_SCTP:
+                       if ((update_flags & TCA_CSUM_UPDATE_FLAG_SCTP) &&
+                           !tcf_csum_sctp(skb, hl, pl + sizeof(*ip6h)))
+                               goto fail;
+                       goto done;
                default:
                        goto ignore_skb;
                }