aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/pktgen.c57
-rw-r--r--net/ipv4/udp.c3
2 files changed, 54 insertions, 6 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 9640972ec50e..48cebf2c3e7a 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -160,6 +160,7 @@
160#include <net/net_namespace.h> 160#include <net/net_namespace.h>
161#include <net/checksum.h> 161#include <net/checksum.h>
162#include <net/ipv6.h> 162#include <net/ipv6.h>
163#include <net/udp.h>
163#include <net/addrconf.h> 164#include <net/addrconf.h>
164#ifdef CONFIG_XFRM 165#ifdef CONFIG_XFRM
165#include <net/xfrm.h> 166#include <net/xfrm.h>
@@ -198,6 +199,7 @@
198#define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ 199#define F_QUEUE_MAP_RND (1<<13) /* queue map Random */
199#define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ 200#define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */
200#define F_NODE (1<<15) /* Node memory alloc*/ 201#define F_NODE (1<<15) /* Node memory alloc*/
202#define F_UDPCSUM (1<<16) /* Include UDP checksum */
201 203
202/* Thread control flag bits */ 204/* Thread control flag bits */
203#define T_STOP (1<<0) /* Stop run */ 205#define T_STOP (1<<0) /* Stop run */
@@ -631,6 +633,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
631 if (pkt_dev->flags & F_UDPDST_RND) 633 if (pkt_dev->flags & F_UDPDST_RND)
632 seq_printf(seq, "UDPDST_RND "); 634 seq_printf(seq, "UDPDST_RND ");
633 635
636 if (pkt_dev->flags & F_UDPCSUM)
637 seq_printf(seq, "UDPCSUM ");
638
634 if (pkt_dev->flags & F_MPLS_RND) 639 if (pkt_dev->flags & F_MPLS_RND)
635 seq_printf(seq, "MPLS_RND "); 640 seq_printf(seq, "MPLS_RND ");
636 641
@@ -1228,6 +1233,12 @@ static ssize_t pktgen_if_write(struct file *file,
1228 else if (strcmp(f, "!NODE_ALLOC") == 0) 1233 else if (strcmp(f, "!NODE_ALLOC") == 0)
1229 pkt_dev->flags &= ~F_NODE; 1234 pkt_dev->flags &= ~F_NODE;
1230 1235
1236 else if (strcmp(f, "UDPCSUM") == 0)
1237 pkt_dev->flags |= F_UDPCSUM;
1238
1239 else if (strcmp(f, "!UDPCSUM") == 0)
1240 pkt_dev->flags &= ~F_UDPCSUM;
1241
1231 else { 1242 else {
1232 sprintf(pg_result, 1243 sprintf(pg_result,
1233 "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", 1244 "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
@@ -2733,7 +2744,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
2733 udph->source = htons(pkt_dev->cur_udp_src); 2744 udph->source = htons(pkt_dev->cur_udp_src);
2734 udph->dest = htons(pkt_dev->cur_udp_dst); 2745 udph->dest = htons(pkt_dev->cur_udp_dst);
2735 udph->len = htons(datalen + 8); /* DATA + udphdr */ 2746 udph->len = htons(datalen + 8); /* DATA + udphdr */
2736 udph->check = 0; /* No checksum */ 2747 udph->check = 0;
2737 2748
2738 iph->ihl = 5; 2749 iph->ihl = 5;
2739 iph->version = 4; 2750 iph->version = 4;
@@ -2752,6 +2763,24 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
2752 skb->protocol = protocol; 2763 skb->protocol = protocol;
2753 skb->dev = odev; 2764 skb->dev = odev;
2754 skb->pkt_type = PACKET_HOST; 2765 skb->pkt_type = PACKET_HOST;
2766
2767 if (!(pkt_dev->flags & F_UDPCSUM)) {
2768 skb->ip_summed = CHECKSUM_NONE;
2769 } else if (odev->features & NETIF_F_V4_CSUM) {
2770 skb->ip_summed = CHECKSUM_PARTIAL;
2771 skb->csum = 0;
2772 udp4_hwcsum(skb, udph->source, udph->dest);
2773 } else {
2774 __wsum csum = udp_csum(skb);
2775
2776 /* add protocol-dependent pseudo-header */
2777 udph->check = csum_tcpudp_magic(udph->source, udph->dest,
2778 datalen + 8, IPPROTO_UDP, csum);
2779
2780 if (udph->check == 0)
2781 udph->check = CSUM_MANGLED_0;
2782 }
2783
2755 pktgen_finalize_skb(pkt_dev, skb, datalen); 2784 pktgen_finalize_skb(pkt_dev, skb, datalen);
2756 2785
2757#ifdef CONFIG_XFRM 2786#ifdef CONFIG_XFRM
@@ -2768,7 +2797,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2768 struct sk_buff *skb = NULL; 2797 struct sk_buff *skb = NULL;
2769 __u8 *eth; 2798 __u8 *eth;
2770 struct udphdr *udph; 2799 struct udphdr *udph;
2771 int datalen; 2800 int datalen, udplen;
2772 struct ipv6hdr *iph; 2801 struct ipv6hdr *iph;
2773 __be16 protocol = htons(ETH_P_IPV6); 2802 __be16 protocol = htons(ETH_P_IPV6);
2774 __be32 *mpls; 2803 __be32 *mpls;
@@ -2844,10 +2873,11 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2844 net_info_ratelimited("increased datalen to %d\n", datalen); 2873 net_info_ratelimited("increased datalen to %d\n", datalen);
2845 } 2874 }
2846 2875
2876 udplen = datalen + sizeof(struct udphdr);
2847 udph->source = htons(pkt_dev->cur_udp_src); 2877 udph->source = htons(pkt_dev->cur_udp_src);
2848 udph->dest = htons(pkt_dev->cur_udp_dst); 2878 udph->dest = htons(pkt_dev->cur_udp_dst);
2849 udph->len = htons(datalen + sizeof(struct udphdr)); 2879 udph->len = htons(udplen);
2850 udph->check = 0; /* No checksum */ 2880 udph->check = 0;
2851 2881
2852 *(__be32 *) iph = htonl(0x60000000); /* Version + flow */ 2882 *(__be32 *) iph = htonl(0x60000000); /* Version + flow */
2853 2883
@@ -2858,7 +2888,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2858 2888
2859 iph->hop_limit = 32; 2889 iph->hop_limit = 32;
2860 2890
2861 iph->payload_len = htons(sizeof(struct udphdr) + datalen); 2891 iph->payload_len = htons(udplen);
2862 iph->nexthdr = IPPROTO_UDP; 2892 iph->nexthdr = IPPROTO_UDP;
2863 2893
2864 iph->daddr = pkt_dev->cur_in6_daddr; 2894 iph->daddr = pkt_dev->cur_in6_daddr;
@@ -2868,6 +2898,23 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2868 skb->dev = odev; 2898 skb->dev = odev;
2869 skb->pkt_type = PACKET_HOST; 2899 skb->pkt_type = PACKET_HOST;
2870 2900
2901 if (!(pkt_dev->flags & F_UDPCSUM)) {
2902 skb->ip_summed = CHECKSUM_NONE;
2903 } else if (odev->features & NETIF_F_V6_CSUM) {
2904 skb->ip_summed = CHECKSUM_PARTIAL;
2905 skb->csum_start = skb_transport_header(skb) - skb->head;
2906 skb->csum_offset = offsetof(struct udphdr, check);
2907 udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0);
2908 } else {
2909 __wsum csum = udp_csum(skb);
2910
2911 /* add protocol-dependent pseudo-header */
2912 udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum);
2913
2914 if (udph->check == 0)
2915 udph->check = CSUM_MANGLED_0;
2916 }
2917
2871 pktgen_finalize_skb(pkt_dev, skb, datalen); 2918 pktgen_finalize_skb(pkt_dev, skb, datalen);
2872 2919
2873 return skb; 2920 return skb;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 766e6bab9113..9e88af0e8ab0 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -704,7 +704,7 @@ EXPORT_SYMBOL(udp_flush_pending_frames);
704 * @src: source IP address 704 * @src: source IP address
705 * @dst: destination IP address 705 * @dst: destination IP address
706 */ 706 */
707static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) 707void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst)
708{ 708{
709 struct udphdr *uh = udp_hdr(skb); 709 struct udphdr *uh = udp_hdr(skb);
710 struct sk_buff *frags = skb_shinfo(skb)->frag_list; 710 struct sk_buff *frags = skb_shinfo(skb)->frag_list;
@@ -740,6 +740,7 @@ static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst)
740 uh->check = CSUM_MANGLED_0; 740 uh->check = CSUM_MANGLED_0;
741 } 741 }
742} 742}
743EXPORT_SYMBOL_GPL(udp4_hwcsum);
743 744
744static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) 745static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4)
745{ 746{