aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ktime.h24
-rw-r--r--include/net/sctp/structs.h6
-rw-r--r--net/sctp/associola.c168
-rw-r--r--net/sctp/endpointola.c2
-rw-r--r--net/sctp/sm_make_chunk.c2
-rw-r--r--net/sctp/transport.c2
6 files changed, 136 insertions, 68 deletions
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 31c0cd1c941a..de9e46e6bcc9 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -304,6 +304,30 @@ static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
304 return 0; 304 return 0;
305} 305}
306 306
307/**
308 * ktime_after - Compare if a ktime_t value is bigger than another one.
309 * @cmp1: comparable1
310 * @cmp2: comparable2
311 *
312 * Return: true if cmp1 happened after cmp2.
313 */
314static inline bool ktime_after(const ktime_t cmp1, const ktime_t cmp2)
315{
316 return ktime_compare(cmp1, cmp2) > 0;
317}
318
319/**
320 * ktime_before - Compare if a ktime_t value is smaller than another one.
321 * @cmp1: comparable1
322 * @cmp2: comparable2
323 *
324 * Return: true if cmp1 happened before cmp2.
325 */
326static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
327{
328 return ktime_compare(cmp1, cmp2) < 0;
329}
330
307static inline s64 ktime_to_us(const ktime_t kt) 331static inline s64 ktime_to_us(const ktime_t kt)
308{ 332{
309 struct timeval tv = ktime_to_timeval(kt); 333 struct timeval tv = ktime_to_timeval(kt);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 0dfcc92600e8..f38588bf3462 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -838,10 +838,10 @@ struct sctp_transport {
838 unsigned long sackdelay; 838 unsigned long sackdelay;
839 __u32 sackfreq; 839 __u32 sackfreq;
840 840
841 /* When was the last time (in jiffies) that we heard from this 841 /* When was the last time that we heard from this transport? We use
842 * transport? We use this to pick new active and retran paths. 842 * this to pick new active and retran paths.
843 */ 843 */
844 unsigned long last_time_heard; 844 ktime_t last_time_heard;
845 845
846 /* Last time(in jiffies) when cwnd is reduced due to the congestion 846 /* Last time(in jiffies) when cwnd is reduced due to the congestion
847 * indication based on ECNE chunk. 847 * indication based on ECNE chunk.
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 39579c3e0d14..9e0509ce2f84 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -55,6 +55,7 @@
55#include <net/sctp/sm.h> 55#include <net/sctp/sm.h>
56 56
57/* Forward declarations for internal functions. */ 57/* Forward declarations for internal functions. */
58static void sctp_select_active_and_retran_path(struct sctp_association *asoc);
58static void sctp_assoc_bh_rcv(struct work_struct *work); 59static void sctp_assoc_bh_rcv(struct work_struct *work);
59static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc); 60static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
60static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc); 61static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc);
@@ -774,9 +775,6 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
774 sctp_transport_cmd_t command, 775 sctp_transport_cmd_t command,
775 sctp_sn_error_t error) 776 sctp_sn_error_t error)
776{ 777{
777 struct sctp_transport *t = NULL;
778 struct sctp_transport *first;
779 struct sctp_transport *second;
780 struct sctp_ulpevent *event; 778 struct sctp_ulpevent *event;
781 struct sockaddr_storage addr; 779 struct sockaddr_storage addr;
782 int spc_state = 0; 780 int spc_state = 0;
@@ -829,13 +827,14 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
829 return; 827 return;
830 } 828 }
831 829
832 /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the 830 /* Generate and send a SCTP_PEER_ADDR_CHANGE notification
833 * user. 831 * to the user.
834 */ 832 */
835 if (ulp_notify) { 833 if (ulp_notify) {
836 memset(&addr, 0, sizeof(struct sockaddr_storage)); 834 memset(&addr, 0, sizeof(struct sockaddr_storage));
837 memcpy(&addr, &transport->ipaddr, 835 memcpy(&addr, &transport->ipaddr,
838 transport->af_specific->sockaddr_len); 836 transport->af_specific->sockaddr_len);
837
839 event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, 838 event = sctp_ulpevent_make_peer_addr_change(asoc, &addr,
840 0, spc_state, error, GFP_ATOMIC); 839 0, spc_state, error, GFP_ATOMIC);
841 if (event) 840 if (event)
@@ -843,60 +842,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
843 } 842 }
844 843
845 /* Select new active and retran paths. */ 844 /* Select new active and retran paths. */
846 845 sctp_select_active_and_retran_path(asoc);
847 /* Look for the two most recently used active transports.
848 *
849 * This code produces the wrong ordering whenever jiffies
850 * rolls over, but we still get usable transports, so we don't
851 * worry about it.
852 */
853 first = NULL; second = NULL;
854
855 list_for_each_entry(t, &asoc->peer.transport_addr_list,
856 transports) {
857
858 if ((t->state == SCTP_INACTIVE) ||
859 (t->state == SCTP_UNCONFIRMED) ||
860 (t->state == SCTP_PF))
861 continue;
862 if (!first || t->last_time_heard > first->last_time_heard) {
863 second = first;
864 first = t;
865 } else if (!second ||
866 t->last_time_heard > second->last_time_heard)
867 second = t;
868 }
869
870 /* RFC 2960 6.4 Multi-Homed SCTP Endpoints
871 *
872 * By default, an endpoint should always transmit to the
873 * primary path, unless the SCTP user explicitly specifies the
874 * destination transport address (and possibly source
875 * transport address) to use.
876 *
877 * [If the primary is active but not most recent, bump the most
878 * recently used transport.]
879 */
880 if (((asoc->peer.primary_path->state == SCTP_ACTIVE) ||
881 (asoc->peer.primary_path->state == SCTP_UNKNOWN)) &&
882 first != asoc->peer.primary_path) {
883 second = first;
884 first = asoc->peer.primary_path;
885 }
886
887 if (!second)
888 second = first;
889 /* If we failed to find a usable transport, just camp on the
890 * primary, even if it is inactive.
891 */
892 if (!first) {
893 first = asoc->peer.primary_path;
894 second = asoc->peer.primary_path;
895 }
896
897 /* Set the active and retran transports. */
898 asoc->peer.active_path = first;
899 asoc->peer.retran_path = second;
900} 846}
901 847
902/* Hold a reference to an association. */ 848/* Hold a reference to an association. */
@@ -1090,7 +1036,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
1090 } 1036 }
1091 1037
1092 if (chunk->transport) 1038 if (chunk->transport)
1093 chunk->transport->last_time_heard = jiffies; 1039 chunk->transport->last_time_heard = ktime_get();
1094 1040
1095 /* Run through the state machine. */ 1041 /* Run through the state machine. */
1096 error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, 1042 error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype,
@@ -1278,13 +1224,41 @@ static u8 sctp_trans_score(const struct sctp_transport *trans)
1278 return sctp_trans_state_to_prio_map[trans->state]; 1224 return sctp_trans_state_to_prio_map[trans->state];
1279} 1225}
1280 1226
1227static struct sctp_transport *sctp_trans_elect_tie(struct sctp_transport *trans1,
1228 struct sctp_transport *trans2)
1229{
1230 if (trans1->error_count > trans2->error_count) {
1231 return trans2;
1232 } else if (trans1->error_count == trans2->error_count &&
1233 ktime_after(trans2->last_time_heard,
1234 trans1->last_time_heard)) {
1235 return trans2;
1236 } else {
1237 return trans1;
1238 }
1239}
1240
1281static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr, 1241static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr,
1282 struct sctp_transport *best) 1242 struct sctp_transport *best)
1283{ 1243{
1244 u8 score_curr, score_best;
1245
1284 if (best == NULL) 1246 if (best == NULL)
1285 return curr; 1247 return curr;
1286 1248
1287 return sctp_trans_score(curr) > sctp_trans_score(best) ? curr : best; 1249 score_curr = sctp_trans_score(curr);
1250 score_best = sctp_trans_score(best);
1251
1252 /* First, try a score-based selection if both transport states
1253 * differ. If we're in a tie, lets try to make a more clever
1254 * decision here based on error counts and last time heard.
1255 */
1256 if (score_curr > score_best)
1257 return curr;
1258 else if (score_curr == score_best)
1259 return sctp_trans_elect_tie(curr, best);
1260 else
1261 return best;
1288} 1262}
1289 1263
1290void sctp_assoc_update_retran_path(struct sctp_association *asoc) 1264void sctp_assoc_update_retran_path(struct sctp_association *asoc)
@@ -1325,6 +1299,76 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
1325 __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); 1299 __func__, asoc, &asoc->peer.retran_path->ipaddr.sa);
1326} 1300}
1327 1301
1302static void sctp_select_active_and_retran_path(struct sctp_association *asoc)
1303{
1304 struct sctp_transport *trans, *trans_pri = NULL, *trans_sec = NULL;
1305 struct sctp_transport *trans_pf = NULL;
1306
1307 /* Look for the two most recently used active transports. */
1308 list_for_each_entry(trans, &asoc->peer.transport_addr_list,
1309 transports) {
1310 /* Skip uninteresting transports. */
1311 if (trans->state == SCTP_INACTIVE ||
1312 trans->state == SCTP_UNCONFIRMED)
1313 continue;
1314 /* Keep track of the best PF transport from our
1315 * list in case we don't find an active one.
1316 */
1317 if (trans->state == SCTP_PF) {
1318 trans_pf = sctp_trans_elect_best(trans, trans_pf);
1319 continue;
1320 }
1321 /* For active transports, pick the most recent ones. */
1322 if (trans_pri == NULL ||
1323 ktime_after(trans->last_time_heard,
1324 trans_pri->last_time_heard)) {
1325 trans_sec = trans_pri;
1326 trans_pri = trans;
1327 } else if (trans_sec == NULL ||
1328 ktime_after(trans->last_time_heard,
1329 trans_sec->last_time_heard)) {
1330 trans_sec = trans;
1331 }
1332 }
1333
1334 /* RFC 2960 6.4 Multi-Homed SCTP Endpoints
1335 *
1336 * By default, an endpoint should always transmit to the primary
1337 * path, unless the SCTP user explicitly specifies the
1338 * destination transport address (and possibly source transport
1339 * address) to use. [If the primary is active but not most recent,
1340 * bump the most recently used transport.]
1341 */
1342 if ((asoc->peer.primary_path->state == SCTP_ACTIVE ||
1343 asoc->peer.primary_path->state == SCTP_UNKNOWN) &&
1344 asoc->peer.primary_path != trans_pri) {
1345 trans_sec = trans_pri;
1346 trans_pri = asoc->peer.primary_path;
1347 }
1348
1349 /* We did not find anything useful for a possible retransmission
1350 * path; either primary path that we found is the the same as
1351 * the current one, or we didn't generally find an active one.
1352 */
1353 if (trans_sec == NULL)
1354 trans_sec = trans_pri;
1355
1356 /* If we failed to find a usable transport, just camp on the
1357 * primary or retran, even if they are inactive, if possible
1358 * pick a PF iff it's the better choice.
1359 */
1360 if (trans_pri == NULL) {
1361 trans_pri = sctp_trans_elect_best(asoc->peer.primary_path,
1362 asoc->peer.retran_path);
1363 trans_pri = sctp_trans_elect_best(trans_pri, trans_pf);
1364 trans_sec = asoc->peer.primary_path;
1365 }
1366
1367 /* Set the active and retran transports. */
1368 asoc->peer.active_path = trans_pri;
1369 asoc->peer.retran_path = trans_sec;
1370}
1371
1328struct sctp_transport * 1372struct sctp_transport *
1329sctp_assoc_choose_alter_transport(struct sctp_association *asoc, 1373sctp_assoc_choose_alter_transport(struct sctp_association *asoc,
1330 struct sctp_transport *last_sent_to) 1374 struct sctp_transport *last_sent_to)
@@ -1547,7 +1591,7 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
1547/* Set an association id for a given association */ 1591/* Set an association id for a given association */
1548int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) 1592int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
1549{ 1593{
1550 bool preload = gfp & __GFP_WAIT; 1594 bool preload = !!(gfp & __GFP_WAIT);
1551 int ret; 1595 int ret;
1552 1596
1553 /* If the id is already assigned, keep it. */ 1597 /* If the id is already assigned, keep it. */
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 3d9f429858dc..9da76ba4d10f 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -481,7 +481,7 @@ normal:
481 } 481 }
482 482
483 if (chunk->transport) 483 if (chunk->transport)
484 chunk->transport->last_time_heard = jiffies; 484 chunk->transport->last_time_heard = ktime_get();
485 485
486 error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state, 486 error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state,
487 ep, asoc, chunk, GFP_ATOMIC); 487 ep, asoc, chunk, GFP_ATOMIC);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index fee5552ddf92..ae0e616a7ca5 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1782,7 +1782,7 @@ no_hmac:
1782 else 1782 else
1783 kt = ktime_get(); 1783 kt = ktime_get();
1784 1784
1785 if (!asoc && ktime_compare(bear_cookie->expiration, kt) < 0) { 1785 if (!asoc && ktime_before(bear_cookie->expiration, kt)) {
1786 /* 1786 /*
1787 * Section 3.3.10.3 Stale Cookie Error (3) 1787 * Section 3.3.10.3 Stale Cookie Error (3)
1788 * 1788 *
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 1d348d15b33d..7dd672fa651f 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -72,7 +72,7 @@ static struct sctp_transport *sctp_transport_init(struct net *net,
72 */ 72 */
73 peer->rto = msecs_to_jiffies(net->sctp.rto_initial); 73 peer->rto = msecs_to_jiffies(net->sctp.rto_initial);
74 74
75 peer->last_time_heard = jiffies; 75 peer->last_time_heard = ktime_get();
76 peer->last_time_ecne_reduced = jiffies; 76 peer->last_time_ecne_reduced = jiffies;
77 77
78 peer->param_flags = SPP_HB_DISABLE | 78 peer->param_flags = SPP_HB_DISABLE |