Struct sockaddr_in6 has the member sin6_flowinfo that includes the
ipv6 flowlabel, it should also support for setting flowlabel when
adding a transport whose ipaddr is from userspace.
Note that addrinfo in sctp_sendmsg is using struct in6_addr for
the secondary addrs, which doesn't contain sin6_flowinfo, and
it needs to copy sin6_flowinfo from the primary addr.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
        peer->sackdelay = asoc->sackdelay;
        peer->sackfreq = asoc->sackfreq;
 
-       if (addr->sa.sa_family == AF_INET6)
-               peer->flowlabel = asoc->flowlabel;
+       if (addr->sa.sa_family == AF_INET6) {
+               __be32 info = addr->v6.sin6_flowinfo;
+
+               if (info) {
+                       peer->flowlabel = ntohl(info & IPV6_FLOWLABEL_MASK);
+                       peer->flowlabel |= SCTP_FLOWLABEL_SET_MASK;
+               } else {
+                       peer->flowlabel = asoc->flowlabel;
+               }
+       }
        peer->dscp = asoc->dscp;
 
        /* Enable/disable heartbeat, SACK delay, and path MTU discovery
 
        struct sctp_association *asoc;
        enum sctp_scope scope;
        struct cmsghdr *cmsg;
+       __be32 flowinfo = 0;
        struct sctp_af *af;
        int err;
 
        if (!cmsgs->addrs_msg)
                return 0;
 
+       if (daddr->sa.sa_family == AF_INET6)
+               flowinfo = daddr->v6.sin6_flowinfo;
+
        /* sendv addr list parse */
        for_each_cmsghdr(cmsg, cmsgs->addrs_msg) {
                struct sctp_transport *transport;
                        }
 
                        dlen = sizeof(struct in6_addr);
+                       daddr->v6.sin6_flowinfo = flowinfo;
                        daddr->v6.sin6_family = AF_INET6;
                        daddr->v6.sin6_port = htons(asoc->peer.port);
                        memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen);