aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/associola.c
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2014-06-11 12:19:29 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-11 15:23:17 -0400
commitb82e8f31acc7d799638692e65ff017f3e1b6a43d (patch)
tree5dfe890048406a67d58ecead0e966a3954c85732 /net/sctp/associola.c
parent67cb9366ff5f99868100198efba5ca88aaa6ad25 (diff)
net: sctp: refactor active path selection
This patch just refactors and moves the code for the active path selection into its own helper function outside of sctp_assoc_control_transport() which is already big enough. No functional changes here. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r--net/sctp/associola.c120
1 files changed, 61 insertions, 59 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 39579c3e0d14..9f1cc6f1535d 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. */
@@ -1325,6 +1271,62 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
1325 __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); 1271 __func__, asoc, &asoc->peer.retran_path->ipaddr.sa);
1326} 1272}
1327 1273
1274static void sctp_select_active_and_retran_path(struct sctp_association *asoc)
1275{
1276 struct sctp_transport *trans, *trans_pri = NULL, *trans_sec = NULL;
1277
1278 /* Look for the two most recently used active transports. */
1279 list_for_each_entry(trans, &asoc->peer.transport_addr_list,
1280 transports) {
1281 if (trans->state == SCTP_INACTIVE ||
1282 trans->state == SCTP_UNCONFIRMED ||
1283 trans->state == SCTP_PF)
1284 continue;
1285 if (trans_pri == NULL ||
1286 trans->last_time_heard > trans_pri->last_time_heard) {
1287 trans_sec = trans_pri;
1288 trans_pri = trans;
1289 } else if (trans_sec == NULL ||
1290 trans->last_time_heard > trans_sec->last_time_heard) {
1291 trans_sec = trans;
1292 }
1293 }
1294
1295 /* RFC 2960 6.4 Multi-Homed SCTP Endpoints
1296 *
1297 * By default, an endpoint should always transmit to the primary
1298 * path, unless the SCTP user explicitly specifies the
1299 * destination transport address (and possibly source transport
1300 * address) to use. [If the primary is active but not most recent,
1301 * bump the most recently used transport.]
1302 */
1303 if ((asoc->peer.primary_path->state == SCTP_ACTIVE ||
1304 asoc->peer.primary_path->state == SCTP_UNKNOWN) &&
1305 asoc->peer.primary_path != trans_pri) {
1306 trans_sec = trans_pri;
1307 trans_pri = asoc->peer.primary_path;
1308 }
1309
1310 /* We did not find anything useful for a possible retransmission
1311 * path; either primary path that we found is the the same as
1312 * the current one, or we didn't generally find an active one.
1313 */
1314 if (trans_sec == NULL)
1315 trans_sec = trans_pri;
1316
1317 /* If we failed to find a usable transport, just camp on the
1318 * primary, even if they are inactive.
1319 */
1320 if (trans_pri == NULL) {
1321 trans_pri = asoc->peer.primary_path;
1322 trans_sec = asoc->peer.primary_path;
1323 }
1324
1325 /* Set the active and retran transports. */
1326 asoc->peer.active_path = trans_pri;
1327 asoc->peer.retran_path = trans_sec;
1328}
1329
1328struct sctp_transport * 1330struct sctp_transport *
1329sctp_assoc_choose_alter_transport(struct sctp_association *asoc, 1331sctp_assoc_choose_alter_transport(struct sctp_association *asoc,
1330 struct sctp_transport *last_sent_to) 1332 struct sctp_transport *last_sent_to)