]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/core/pktgen.c
pktgen: add needed include file
[karo-tx-linux.git] / net / core / pktgen.c
index 9640972ec50e5658eac7493fb0da180a0de353c9..261357a663001ccf98a92ba5f6d0f6ad141c7ce3 100644 (file)
 #include <net/net_namespace.h>
 #include <net/checksum.h>
 #include <net/ipv6.h>
+#include <net/udp.h>
+#include <net/ip6_checksum.h>
 #include <net/addrconf.h>
 #ifdef CONFIG_XFRM
 #include <net/xfrm.h>
 #define F_QUEUE_MAP_RND (1<<13)        /* queue map Random */
 #define F_QUEUE_MAP_CPU (1<<14)        /* queue map mirrors smp_processor_id() */
 #define F_NODE          (1<<15)        /* Node memory alloc*/
+#define F_UDPCSUM       (1<<16)        /* Include UDP checksum */
 
 /* Thread control flag bits */
 #define T_STOP        (1<<0)   /* Stop run */
@@ -631,6 +634,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
        if (pkt_dev->flags & F_UDPDST_RND)
                seq_printf(seq, "UDPDST_RND  ");
 
+       if (pkt_dev->flags & F_UDPCSUM)
+               seq_printf(seq, "UDPCSUM  ");
+
        if (pkt_dev->flags & F_MPLS_RND)
                seq_printf(seq,  "MPLS_RND  ");
 
@@ -1228,6 +1234,12 @@ static ssize_t pktgen_if_write(struct file *file,
                else if (strcmp(f, "!NODE_ALLOC") == 0)
                        pkt_dev->flags &= ~F_NODE;
 
+               else if (strcmp(f, "UDPCSUM") == 0)
+                       pkt_dev->flags |= F_UDPCSUM;
+
+               else if (strcmp(f, "!UDPCSUM") == 0)
+                       pkt_dev->flags &= ~F_UDPCSUM;
+
                else {
                        sprintf(pg_result,
                                "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
@@ -2733,7 +2745,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        udph->source = htons(pkt_dev->cur_udp_src);
        udph->dest = htons(pkt_dev->cur_udp_dst);
        udph->len = htons(datalen + 8); /* DATA + udphdr */
-       udph->check = 0;        /* No checksum */
+       udph->check = 0;
 
        iph->ihl = 5;
        iph->version = 4;
@@ -2747,11 +2759,28 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        iph->frag_off = 0;
        iplen = 20 + 8 + datalen;
        iph->tot_len = htons(iplen);
-       iph->check = 0;
-       iph->check = ip_fast_csum((void *)iph, iph->ihl);
+       ip_send_check(iph);
        skb->protocol = protocol;
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
+
+       if (!(pkt_dev->flags & F_UDPCSUM)) {
+               skb->ip_summed = CHECKSUM_NONE;
+       } else if (odev->features & NETIF_F_V4_CSUM) {
+               skb->ip_summed = CHECKSUM_PARTIAL;
+               skb->csum = 0;
+               udp4_hwcsum(skb, udph->source, udph->dest);
+       } else {
+               __wsum csum = udp_csum(skb);
+
+               /* add protocol-dependent pseudo-header */
+               udph->check = csum_tcpudp_magic(udph->source, udph->dest,
+                                               datalen + 8, IPPROTO_UDP, csum);
+
+               if (udph->check == 0)
+                       udph->check = CSUM_MANGLED_0;
+       }
+
        pktgen_finalize_skb(pkt_dev, skb, datalen);
 
 #ifdef CONFIG_XFRM
@@ -2768,7 +2797,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        struct sk_buff *skb = NULL;
        __u8 *eth;
        struct udphdr *udph;
-       int datalen;
+       int datalen, udplen;
        struct ipv6hdr *iph;
        __be16 protocol = htons(ETH_P_IPV6);
        __be32 *mpls;
@@ -2844,10 +2873,11 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                net_info_ratelimited("increased datalen to %d\n", datalen);
        }
 
+       udplen = datalen + sizeof(struct udphdr);
        udph->source = htons(pkt_dev->cur_udp_src);
        udph->dest = htons(pkt_dev->cur_udp_dst);
-       udph->len = htons(datalen + sizeof(struct udphdr));
-       udph->check = 0;        /* No checksum */
+       udph->len = htons(udplen);
+       udph->check = 0;
 
        *(__be32 *) iph = htonl(0x60000000);    /* Version + flow */
 
@@ -2858,7 +2888,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 
        iph->hop_limit = 32;
 
-       iph->payload_len = htons(sizeof(struct udphdr) + datalen);
+       iph->payload_len = htons(udplen);
        iph->nexthdr = IPPROTO_UDP;
 
        iph->daddr = pkt_dev->cur_in6_daddr;
@@ -2868,6 +2898,23 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
 
+       if (!(pkt_dev->flags & F_UDPCSUM)) {
+               skb->ip_summed = CHECKSUM_NONE;
+       } else if (odev->features & NETIF_F_V6_CSUM) {
+               skb->ip_summed = CHECKSUM_PARTIAL;
+               skb->csum_start = skb_transport_header(skb) - skb->head;
+               skb->csum_offset = offsetof(struct udphdr, check);
+               udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0);
+       } else {
+               __wsum csum = udp_csum(skb);
+
+               /* add protocol-dependent pseudo-header */
+               udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum);
+
+               if (udph->check == 0)
+                       udph->check = CSUM_MANGLED_0;
+       }
+
        pktgen_finalize_skb(pkt_dev, skb, datalen);
 
        return skb;