exporting patch:
# HG changeset patch
# User Susant Sahani <ssahani@redhat.com>
# Date 1386670710 -19800
#      Tue Dec 10 15:48:30 2013 +0530
# Branch iperf-dev
# Node ID 85341017b862a2d4cb299af9c0ac67cc5e974e9d
# Parent  c37286118cc5dd5431a64112d90182ca7a374af8
IPV6 header field flowlabel support for Linux

An option (-L) to set the flowlabel header field in the IPv6 header
for an outgoing stream on the client side for TCP. Support added for Linux.

diff -r c37286118cc5 -r 85341017b862 src/flowlabel.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/flowlabel.h	Tue Dec 10 15:48:30 2013 +0530
@@ -0,0 +1,54 @@
+/*      
+ * Copyright (c) 2009-2011, The Regents of the University of California, 
+ * through Lawrence Berkeley National Laboratory (subject to receipt of any
+ * required approvals from the U.S. Dept. of Energy).  All rights reserved.
+ * This code is distributed under a BSD style license, see the LICENSE file
+ * for complete information.                                                                                 
+ */
+
+#ifndef        __FLOW_LABEL_H
+#define        __FLOW_LABEL_H
+
+
+#include <linux/types.h>
+
+/*                                                                                                                                                                             
+   It is just a stripped copy of the Linux kernel header "linux/in6.h" 
+   "Flow label" things are still not defined in "netinet/in*.h" headers,
+   but we cannot use "linux/in6.h" immediately because it currently
+   conflicts with "netinet/in.h" .
+*/
+
+struct in6_flowlabel_req
+{
+    struct in6_addr flr_dst;
+    __u32   flr_label;
+    __u8    flr_action;
+    __u8    flr_share;
+    __u16   flr_flags;
+    __u16   flr_expires;
+    __u16   flr_linger;
+    __u32   __flr_pad;
+    /* Options in format of IPV6_PKTOPTIONS */
+};
+
+#define IPV6_FL_A_GET           0
+#define IPV6_FL_A_PUT           1
+#define IPV6_FL_A_RENEW         2
+
+#define IPV6_FL_F_CREATE        1
+#define IPV6_FL_F_EXCL          2
+
+#define IPV6_FL_S_NONE          0
+#define IPV6_FL_S_EXCL          1
+#define IPV6_FL_S_PROCESS       2
+#define IPV6_FL_S_USER          3
+#define IPV6_FL_S_ANY           255
+
+#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff
+#define IPV6_FLOWINFO_PRIORITY  0x0ff00000
+
+#define IPV6_FLOWLABEL_MGR      32
+#define IPV6_FLOWINFO_SEND      33
+
+#endif
diff -r c37286118cc5 -r 85341017b862 src/iperf_api.c
--- a/src/iperf_api.c	Mon Dec 09 17:52:59 2013 -0800
+++ b/src/iperf_api.c	Tue Dec 10 15:48:30 2013 +0530
@@ -655,7 +655,7 @@
 		client_flag = 1;
                 break;
             case 'L':
-#ifdef notdef
+#if defined(linux)
                 test->settings->flowlabel = strtol(optarg, NULL, 0);
 		if (test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) {
                     i_errno = IESETFLOW;
@@ -663,8 +663,8 @@
 		}
 		client_flag = 1;
 #else /* notdef */
-		i_errno = IEUNIMP;
-		return -1;
+                i_errno = IEUNIMP;
+                return -1;
 #endif /* notdef */
                 break;
             case 'Z':
diff -r c37286118cc5 -r 85341017b862 src/iperf_tcp.c
--- a/src/iperf_tcp.c	Mon Dec 09 17:52:59 2013 -0800
+++ b/src/iperf_tcp.c	Tue Dec 10 15:48:30 2013 +0530
@@ -25,6 +25,9 @@
 #include "iperf_tcp.h"
 #include "net.h"
 
+#if defined(linux)
+#include "flowlabel.h"
+#endif
 
 /* iperf_tcp_recv
  *
@@ -291,6 +294,7 @@
             return -1;
         }
     }
+#if defined(linux)
     if (test->settings->flowlabel) {
         if (server_res->ai_addr->sa_family != AF_INET6) {
 	    close(s);
@@ -299,9 +303,35 @@
             return -1;
 	} else {
 	    struct sockaddr_in6* sa6P = (struct sockaddr_in6*) server_res->ai_addr;
-	    sa6P->sin6_flowinfo = htonl(test->settings->flowlabel);
+            char freq_buf[sizeof(struct in6_flowlabel_req)];
+            struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf;
+            int freq_len = sizeof(*freq);
+
+            memset(freq, 0, sizeof(*freq));
+            freq->flr_label = htonl(test->settings->flowlabel & IPV6_FLOWINFO_FLOWLABEL);
+            freq->flr_action = IPV6_FL_A_GET;
+            freq->flr_flags = IPV6_FL_F_CREATE;
+            freq->flr_share = IPV6_FL_F_CREATE | IPV6_FL_S_EXCL;
+            memcpy(&freq->flr_dst, &sa6P->sin6_addr, 16);
+
+            if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, freq, freq_len) < 0) {
+                close(s);
+                freeaddrinfo(server_res);
+                i_errno = IESETFLOW;
+                return -1;
+            }
+            sa6P->sin6_flowinfo = freq->flr_label;
+
+            opt = 1;
+            if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, &opt, sizeof(opt)) < 0) {
+                close(s);
+                freeaddrinfo(server_res);
+                i_errno = IESETFLOW;
+                return -1;
+            } 
 	}
     }
+#endif
 
     if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) {
 	close(s);
diff -r c37286118cc5 -r 85341017b862 src/locale.c
--- a/src/locale.c	Mon Dec 09 17:52:59 2013 -0800
+++ b/src/locale.c	Tue Dec 10 15:48:30 2013 +0530
@@ -99,7 +99,9 @@
                            "  -4, --version4            only use IPv4\n"
                            "  -6, --version6            only use IPv6\n"
                            "  -S, --tos N               set the IP 'type of service'\n"
-                           /* "  -L, --flowlabel N         set the IPv6 'flow label'\n" */
+#if defined(linux)
+                           "  -L, --flowlabel N         set the IPv6 'flow label'\n"
+#endif
                            "  -Z, --zerocopy            use a 'zero copy' method of sending data\n"
                            "  -O, --omit N              omit the first n seconds\n"
                            "  -T, --title str           prefix every output line with this string\n"
