sctp: add support for setting flowlabel when adding a transport
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>
This commit is contained in:
parent
0b0dce7a36
commit
4be4139f7d
2 changed files with 15 additions and 2 deletions
|
@ -650,8 +650,16 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
|
||||||
peer->sackdelay = asoc->sackdelay;
|
peer->sackdelay = asoc->sackdelay;
|
||||||
peer->sackfreq = asoc->sackfreq;
|
peer->sackfreq = asoc->sackfreq;
|
||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET6)
|
if (addr->sa.sa_family == AF_INET6) {
|
||||||
peer->flowlabel = asoc->flowlabel;
|
__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;
|
peer->dscp = asoc->dscp;
|
||||||
|
|
||||||
/* Enable/disable heartbeat, SACK delay, and path MTU discovery
|
/* Enable/disable heartbeat, SACK delay, and path MTU discovery
|
||||||
|
|
|
@ -1697,6 +1697,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
|
||||||
struct sctp_association *asoc;
|
struct sctp_association *asoc;
|
||||||
enum sctp_scope scope;
|
enum sctp_scope scope;
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
|
__be32 flowinfo = 0;
|
||||||
struct sctp_af *af;
|
struct sctp_af *af;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -1781,6 +1782,9 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
|
||||||
if (!cmsgs->addrs_msg)
|
if (!cmsgs->addrs_msg)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (daddr->sa.sa_family == AF_INET6)
|
||||||
|
flowinfo = daddr->v6.sin6_flowinfo;
|
||||||
|
|
||||||
/* sendv addr list parse */
|
/* sendv addr list parse */
|
||||||
for_each_cmsghdr(cmsg, cmsgs->addrs_msg) {
|
for_each_cmsghdr(cmsg, cmsgs->addrs_msg) {
|
||||||
struct sctp_transport *transport;
|
struct sctp_transport *transport;
|
||||||
|
@ -1813,6 +1817,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
|
||||||
}
|
}
|
||||||
|
|
||||||
dlen = sizeof(struct in6_addr);
|
dlen = sizeof(struct in6_addr);
|
||||||
|
daddr->v6.sin6_flowinfo = flowinfo;
|
||||||
daddr->v6.sin6_family = AF_INET6;
|
daddr->v6.sin6_family = AF_INET6;
|
||||||
daddr->v6.sin6_port = htons(asoc->peer.port);
|
daddr->v6.sin6_port = htons(asoc->peer.port);
|
||||||
memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen);
|
memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen);
|
||||||
|
|
Loading…
Reference in a new issue