diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/pktgen.c | 57 | ||||
-rw-r--r-- | net/ipv4/udp.c | 3 |
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 | */ |
707 | static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) | 707 | void 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 | } |
743 | EXPORT_SYMBOL_GPL(udp4_hwcsum); | ||
743 | 744 | ||
744 | static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) | 745 | static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) |
745 | { | 746 | { |