summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2018-07-02 06:21:12 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-03 22:36:54 -0400
commit8a9c58d28d0f66569737a3295116710ed24573cd (patch)
tree4d530788207cca98e68faee6d5a4145d5d8befc4
parent69b9e1e07d98b57b972df3c44647ca8795284d39 (diff)
sctp: add support for dscp and flowlabel per transport
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 <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/sctp.h7
-rw-r--r--include/net/sctp/structs.h9
-rw-r--r--net/sctp/associola.c7
-rw-r--r--net/sctp/ipv6.c11
-rw-r--r--net/sctp/protocol.c16
5 files changed, 44 insertions, 6 deletions
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index b36c76635f18..83d94341e003 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -801,4 +801,11 @@ struct sctp_strreset_resptsn {
801 __be32 receivers_next_tsn; 801 __be32 receivers_next_tsn;
802}; 802};
803 803
804enum {
805 SCTP_DSCP_SET_MASK = 0x1,
806 SCTP_DSCP_VAL_MASK = 0xfc,
807 SCTP_FLOWLABEL_SET_MASK = 0x100000,
808 SCTP_FLOWLABEL_VAL_MASK = 0xfffff
809};
810
804#endif /* __LINUX_SCTP_H__ */ 811#endif /* __LINUX_SCTP_H__ */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 701a51736fa5..ab869e0d8326 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -193,6 +193,9 @@ struct sctp_sock {
193 /* This is the max_retrans value for new associations. */ 193 /* This is the max_retrans value for new associations. */
194 __u16 pathmaxrxt; 194 __u16 pathmaxrxt;
195 195
196 __u32 flowlabel;
197 __u8 dscp;
198
196 /* The initial Path MTU to use for new associations. */ 199 /* The initial Path MTU to use for new associations. */
197 __u32 pathmtu; 200 __u32 pathmtu;
198 201
@@ -895,6 +898,9 @@ struct sctp_transport {
895 */ 898 */
896 __u16 pathmaxrxt; 899 __u16 pathmaxrxt;
897 900
901 __u32 flowlabel;
902 __u8 dscp;
903
898 /* This is the partially failed retrans value for the transport 904 /* This is the partially failed retrans value for the transport
899 * and will be initialized from the assocs value. This can be changed 905 * and will be initialized from the assocs value. This can be changed
900 * using the SCTP_PEER_ADDR_THLDS socket option 906 * using the SCTP_PEER_ADDR_THLDS socket option
@@ -1772,6 +1778,9 @@ struct sctp_association {
1772 */ 1778 */
1773 __u16 pathmaxrxt; 1779 __u16 pathmaxrxt;
1774 1780
1781 __u32 flowlabel;
1782 __u8 dscp;
1783
1775 /* Flag that path mtu update is pending */ 1784 /* Flag that path mtu update is pending */
1776 __u8 pmtu_pending; 1785 __u8 pmtu_pending;
1777 1786
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 5d5a16204d50..16ecfbc95614 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -115,6 +115,9 @@ static struct sctp_association *sctp_association_init(
115 /* Initialize path max retrans value. */ 115 /* Initialize path max retrans value. */
116 asoc->pathmaxrxt = sp->pathmaxrxt; 116 asoc->pathmaxrxt = sp->pathmaxrxt;
117 117
118 asoc->flowlabel = sp->flowlabel;
119 asoc->dscp = sp->dscp;
120
118 /* Initialize default path MTU. */ 121 /* Initialize default path MTU. */
119 asoc->pathmtu = sp->pathmtu; 122 asoc->pathmtu = sp->pathmtu;
120 123
@@ -647,6 +650,10 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
647 peer->sackdelay = asoc->sackdelay; 650 peer->sackdelay = asoc->sackdelay;
648 peer->sackfreq = asoc->sackfreq; 651 peer->sackfreq = asoc->sackfreq;
649 652
653 if (addr->sa.sa_family == AF_INET6)
654 peer->flowlabel = asoc->flowlabel;
655 peer->dscp = asoc->dscp;
656
650 /* Enable/disable heartbeat, SACK delay, and path MTU discovery 657 /* Enable/disable heartbeat, SACK delay, and path MTU discovery
651 * based on association setting. 658 * based on association setting.
652 */ 659 */
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 0cd2e764f47f..38102bf7f13e 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -209,12 +209,17 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
209 struct sock *sk = skb->sk; 209 struct sock *sk = skb->sk;
210 struct ipv6_pinfo *np = inet6_sk(sk); 210 struct ipv6_pinfo *np = inet6_sk(sk);
211 struct flowi6 *fl6 = &transport->fl.u.ip6; 211 struct flowi6 *fl6 = &transport->fl.u.ip6;
212 __u8 tclass = np->tclass;
212 int res; 213 int res;
213 214
214 pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, 215 pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb,
215 skb->len, &fl6->saddr, &fl6->daddr); 216 skb->len, &fl6->saddr, &fl6->daddr);
216 217
217 IP6_ECN_flow_xmit(sk, fl6->flowlabel); 218 if (transport->dscp & SCTP_DSCP_SET_MASK)
219 tclass = transport->dscp & SCTP_DSCP_VAL_MASK;
220
221 if (INET_ECN_is_capable(tclass))
222 IP6_ECN_flow_xmit(sk, fl6->flowlabel);
218 223
219 if (!(transport->param_flags & SPP_PMTUD_ENABLE)) 224 if (!(transport->param_flags & SPP_PMTUD_ENABLE))
220 skb->ignore_df = 1; 225 skb->ignore_df = 1;
@@ -223,7 +228,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
223 228
224 rcu_read_lock(); 229 rcu_read_lock();
225 res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt), 230 res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt),
226 np->tclass); 231 tclass);
227 rcu_read_unlock(); 232 rcu_read_unlock();
228 return res; 233 return res;
229} 234}
@@ -254,6 +259,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
254 fl6->flowi6_oif = daddr->v6.sin6_scope_id; 259 fl6->flowi6_oif = daddr->v6.sin6_scope_id;
255 else if (asoc) 260 else if (asoc)
256 fl6->flowi6_oif = asoc->base.sk->sk_bound_dev_if; 261 fl6->flowi6_oif = asoc->base.sk->sk_bound_dev_if;
262 if (t->flowlabel & SCTP_FLOWLABEL_SET_MASK)
263 fl6->flowlabel = htonl(t->flowlabel & SCTP_FLOWLABEL_VAL_MASK);
257 264
258 pr_debug("%s: dst=%pI6 ", __func__, &fl6->daddr); 265 pr_debug("%s: dst=%pI6 ", __func__, &fl6->daddr);
259 266
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 67f73d3a1356..e948db29ab53 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -426,13 +426,16 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
426 struct dst_entry *dst = NULL; 426 struct dst_entry *dst = NULL;
427 union sctp_addr *daddr = &t->ipaddr; 427 union sctp_addr *daddr = &t->ipaddr;
428 union sctp_addr dst_saddr; 428 union sctp_addr dst_saddr;
429 __u8 tos = inet_sk(sk)->tos;
429 430
431 if (t->dscp & SCTP_DSCP_SET_MASK)
432 tos = t->dscp & SCTP_DSCP_VAL_MASK;
430 memset(fl4, 0x0, sizeof(struct flowi4)); 433 memset(fl4, 0x0, sizeof(struct flowi4));
431 fl4->daddr = daddr->v4.sin_addr.s_addr; 434 fl4->daddr = daddr->v4.sin_addr.s_addr;
432 fl4->fl4_dport = daddr->v4.sin_port; 435 fl4->fl4_dport = daddr->v4.sin_port;
433 fl4->flowi4_proto = IPPROTO_SCTP; 436 fl4->flowi4_proto = IPPROTO_SCTP;
434 if (asoc) { 437 if (asoc) {
435 fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); 438 fl4->flowi4_tos = RT_CONN_FLAGS_TOS(asoc->base.sk, tos);
436 fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if; 439 fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if;
437 fl4->fl4_sport = htons(asoc->base.bind_addr.port); 440 fl4->fl4_sport = htons(asoc->base.bind_addr.port);
438 } 441 }
@@ -495,7 +498,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
495 fl4->fl4_sport = laddr->a.v4.sin_port; 498 fl4->fl4_sport = laddr->a.v4.sin_port;
496 flowi4_update_output(fl4, 499 flowi4_update_output(fl4,
497 asoc->base.sk->sk_bound_dev_if, 500 asoc->base.sk->sk_bound_dev_if,
498 RT_CONN_FLAGS(asoc->base.sk), 501 RT_CONN_FLAGS_TOS(asoc->base.sk, tos),
499 daddr->v4.sin_addr.s_addr, 502 daddr->v4.sin_addr.s_addr,
500 laddr->a.v4.sin_addr.s_addr); 503 laddr->a.v4.sin_addr.s_addr);
501 504
@@ -971,16 +974,21 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
971 struct sctp_transport *transport) 974 struct sctp_transport *transport)
972{ 975{
973 struct inet_sock *inet = inet_sk(skb->sk); 976 struct inet_sock *inet = inet_sk(skb->sk);
977 __u8 dscp = inet->tos;
974 978
975 pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb, 979 pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb,
976 skb->len, &transport->fl.u.ip4.saddr, &transport->fl.u.ip4.daddr); 980 skb->len, &transport->fl.u.ip4.saddr,
981 &transport->fl.u.ip4.daddr);
982
983 if (transport->dscp & SCTP_DSCP_SET_MASK)
984 dscp = transport->dscp & SCTP_DSCP_VAL_MASK;
977 985
978 inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? 986 inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
979 IP_PMTUDISC_DO : IP_PMTUDISC_DONT; 987 IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
980 988
981 SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); 989 SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
982 990
983 return ip_queue_xmit(&inet->sk, skb, &transport->fl); 991 return __ip_queue_xmit(&inet->sk, skb, &transport->fl, dscp);
984} 992}
985 993
986static struct sctp_af sctp_af_inet; 994static struct sctp_af sctp_af_inet;