Skip to content

Commit

Permalink
sctp: add support for dscp and flowlabel per transport
Browse files Browse the repository at this point in the history
Like some other per transport params, flowlabel and dscp are added
in transport, asoc and sctp_sock. By default, transport sets its
value from asoc's, and asoc does it from sctp_sock. flowlabel
only works for ipv6 transport.

Other than that they need to be passed down in sctp_xmit, flow4/6
also needs to set them before looking up route in get_dst.

Note that it uses '& 0x100000' to check if flowlabel is set and
'& 0x1' (tos 1st bit is unused) to check if dscp is set by users,
so that they could be set to 0 by sockopt in next patch.

Signed-off-by: Xin Long <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
lxin authored and davem330 committed Jul 4, 2018
1 parent 69b9e1e commit 8a9c58d
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 6 deletions.
7 changes: 7 additions & 0 deletions include/linux/sctp.h
Original file line number Diff line number Diff line change
Expand Up @@ -801,4 +801,11 @@ struct sctp_strreset_resptsn {
__be32 receivers_next_tsn;
};

enum {
SCTP_DSCP_SET_MASK = 0x1,
SCTP_DSCP_VAL_MASK = 0xfc,
SCTP_FLOWLABEL_SET_MASK = 0x100000,
SCTP_FLOWLABEL_VAL_MASK = 0xfffff
};

#endif /* __LINUX_SCTP_H__ */
9 changes: 9 additions & 0 deletions include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ struct sctp_sock {
/* This is the max_retrans value for new associations. */
__u16 pathmaxrxt;

__u32 flowlabel;
__u8 dscp;

/* The initial Path MTU to use for new associations. */
__u32 pathmtu;

Expand Down Expand Up @@ -895,6 +898,9 @@ struct sctp_transport {
*/
__u16 pathmaxrxt;

__u32 flowlabel;
__u8 dscp;

/* This is the partially failed retrans value for the transport
* and will be initialized from the assocs value. This can be changed
* using the SCTP_PEER_ADDR_THLDS socket option
Expand Down Expand Up @@ -1772,6 +1778,9 @@ struct sctp_association {
*/
__u16 pathmaxrxt;

__u32 flowlabel;
__u8 dscp;

/* Flag that path mtu update is pending */
__u8 pmtu_pending;

Expand Down
7 changes: 7 additions & 0 deletions net/sctp/associola.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ static struct sctp_association *sctp_association_init(
/* Initialize path max retrans value. */
asoc->pathmaxrxt = sp->pathmaxrxt;

asoc->flowlabel = sp->flowlabel;
asoc->dscp = sp->dscp;

/* Initialize default path MTU. */
asoc->pathmtu = sp->pathmtu;

Expand Down Expand Up @@ -647,6 +650,10 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer->sackdelay = asoc->sackdelay;
peer->sackfreq = asoc->sackfreq;

if (addr->sa.sa_family == AF_INET6)
peer->flowlabel = asoc->flowlabel;
peer->dscp = asoc->dscp;

/* Enable/disable heartbeat, SACK delay, and path MTU discovery
* based on association setting.
*/
Expand Down
11 changes: 9 additions & 2 deletions net/sctp/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,17 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
struct sock *sk = skb->sk;
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi6 *fl6 = &transport->fl.u.ip6;
__u8 tclass = np->tclass;
int res;

pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb,
skb->len, &fl6->saddr, &fl6->daddr);

IP6_ECN_flow_xmit(sk, fl6->flowlabel);
if (transport->dscp & SCTP_DSCP_SET_MASK)
tclass = transport->dscp & SCTP_DSCP_VAL_MASK;

if (INET_ECN_is_capable(tclass))
IP6_ECN_flow_xmit(sk, fl6->flowlabel);

if (!(transport->param_flags & SPP_PMTUD_ENABLE))
skb->ignore_df = 1;
Expand All @@ -223,7 +228,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)

rcu_read_lock();
res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt),
np->tclass);
tclass);
rcu_read_unlock();
return res;
}
Expand Down Expand Up @@ -254,6 +259,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
fl6->flowi6_oif = daddr->v6.sin6_scope_id;
else if (asoc)
fl6->flowi6_oif = asoc->base.sk->sk_bound_dev_if;
if (t->flowlabel & SCTP_FLOWLABEL_SET_MASK)
fl6->flowlabel = htonl(t->flowlabel & SCTP_FLOWLABEL_VAL_MASK);

pr_debug("%s: dst=%pI6 ", __func__, &fl6->daddr);

Expand Down
16 changes: 12 additions & 4 deletions net/sctp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,13 +426,16 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
struct dst_entry *dst = NULL;
union sctp_addr *daddr = &t->ipaddr;
union sctp_addr dst_saddr;
__u8 tos = inet_sk(sk)->tos;

if (t->dscp & SCTP_DSCP_SET_MASK)
tos = t->dscp & SCTP_DSCP_VAL_MASK;
memset(fl4, 0x0, sizeof(struct flowi4));
fl4->daddr = daddr->v4.sin_addr.s_addr;
fl4->fl4_dport = daddr->v4.sin_port;
fl4->flowi4_proto = IPPROTO_SCTP;
if (asoc) {
fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk);
fl4->flowi4_tos = RT_CONN_FLAGS_TOS(asoc->base.sk, tos);
fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if;
fl4->fl4_sport = htons(asoc->base.bind_addr.port);
}
Expand Down Expand Up @@ -495,7 +498,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
fl4->fl4_sport = laddr->a.v4.sin_port;
flowi4_update_output(fl4,
asoc->base.sk->sk_bound_dev_if,
RT_CONN_FLAGS(asoc->base.sk),
RT_CONN_FLAGS_TOS(asoc->base.sk, tos),
daddr->v4.sin_addr.s_addr,
laddr->a.v4.sin_addr.s_addr);

Expand Down Expand Up @@ -971,16 +974,21 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
struct sctp_transport *transport)
{
struct inet_sock *inet = inet_sk(skb->sk);
__u8 dscp = inet->tos;

pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb,
skb->len, &transport->fl.u.ip4.saddr, &transport->fl.u.ip4.daddr);
skb->len, &transport->fl.u.ip4.saddr,
&transport->fl.u.ip4.daddr);

if (transport->dscp & SCTP_DSCP_SET_MASK)
dscp = transport->dscp & SCTP_DSCP_VAL_MASK;

inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
IP_PMTUDISC_DO : IP_PMTUDISC_DONT;

SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);

return ip_queue_xmit(&inet->sk, skb, &transport->fl);
return __ip_queue_xmit(&inet->sk, skb, &transport->fl, dscp);
}

static struct sctp_af sctp_af_inet;
Expand Down

0 comments on commit 8a9c58d

Please sign in to comment.