diff options
Diffstat (limited to 'net/tipc/link.c')
| -rw-r--r-- | net/tipc/link.c | 216 |
1 files changed, 73 insertions, 143 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index c5190ab75290..ad2c57f5868d 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include "core.h" | 37 | #include "core.h" |
| 38 | #include "link.h" | 38 | #include "link.h" |
| 39 | #include "port.h" | 39 | #include "port.h" |
| 40 | #include "socket.h" | ||
| 40 | #include "name_distr.h" | 41 | #include "name_distr.h" |
| 41 | #include "discover.h" | 42 | #include "discover.h" |
| 42 | #include "config.h" | 43 | #include "config.h" |
| @@ -101,9 +102,18 @@ static unsigned int align(unsigned int i) | |||
| 101 | 102 | ||
| 102 | static void link_init_max_pkt(struct tipc_link *l_ptr) | 103 | static void link_init_max_pkt(struct tipc_link *l_ptr) |
| 103 | { | 104 | { |
| 105 | struct tipc_bearer *b_ptr; | ||
| 104 | u32 max_pkt; | 106 | u32 max_pkt; |
| 105 | 107 | ||
| 106 | max_pkt = (l_ptr->b_ptr->mtu & ~3); | 108 | rcu_read_lock(); |
| 109 | b_ptr = rcu_dereference_rtnl(bearer_list[l_ptr->bearer_id]); | ||
| 110 | if (!b_ptr) { | ||
| 111 | rcu_read_unlock(); | ||
| 112 | return; | ||
| 113 | } | ||
| 114 | max_pkt = (b_ptr->mtu & ~3); | ||
| 115 | rcu_read_unlock(); | ||
| 116 | |||
| 107 | if (max_pkt > MAX_MSG_SIZE) | 117 | if (max_pkt > MAX_MSG_SIZE) |
| 108 | max_pkt = MAX_MSG_SIZE; | 118 | max_pkt = MAX_MSG_SIZE; |
| 109 | 119 | ||
| @@ -248,7 +258,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
| 248 | l_ptr->owner = n_ptr; | 258 | l_ptr->owner = n_ptr; |
| 249 | l_ptr->checkpoint = 1; | 259 | l_ptr->checkpoint = 1; |
| 250 | l_ptr->peer_session = INVALID_SESSION; | 260 | l_ptr->peer_session = INVALID_SESSION; |
| 251 | l_ptr->b_ptr = b_ptr; | 261 | l_ptr->bearer_id = b_ptr->identity; |
| 252 | link_set_supervision_props(l_ptr, b_ptr->tolerance); | 262 | link_set_supervision_props(l_ptr, b_ptr->tolerance); |
| 253 | l_ptr->state = RESET_UNKNOWN; | 263 | l_ptr->state = RESET_UNKNOWN; |
| 254 | 264 | ||
| @@ -263,6 +273,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
| 263 | l_ptr->priority = b_ptr->priority; | 273 | l_ptr->priority = b_ptr->priority; |
| 264 | tipc_link_set_queue_limits(l_ptr, b_ptr->window); | 274 | tipc_link_set_queue_limits(l_ptr, b_ptr->window); |
| 265 | 275 | ||
| 276 | l_ptr->net_plane = b_ptr->net_plane; | ||
| 266 | link_init_max_pkt(l_ptr); | 277 | link_init_max_pkt(l_ptr); |
| 267 | 278 | ||
| 268 | l_ptr->next_out_no = 1; | 279 | l_ptr->next_out_no = 1; |
| @@ -287,14 +298,14 @@ void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) | |||
| 287 | 298 | ||
| 288 | rcu_read_lock(); | 299 | rcu_read_lock(); |
| 289 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | 300 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { |
| 290 | spin_lock_bh(&n_ptr->lock); | 301 | tipc_node_lock(n_ptr); |
| 291 | l_ptr = n_ptr->links[bearer_id]; | 302 | l_ptr = n_ptr->links[bearer_id]; |
| 292 | if (l_ptr) { | 303 | if (l_ptr) { |
| 293 | tipc_link_reset(l_ptr); | 304 | tipc_link_reset(l_ptr); |
| 294 | if (shutting_down || !tipc_node_is_up(n_ptr)) { | 305 | if (shutting_down || !tipc_node_is_up(n_ptr)) { |
| 295 | tipc_node_detach_link(l_ptr->owner, l_ptr); | 306 | tipc_node_detach_link(l_ptr->owner, l_ptr); |
| 296 | tipc_link_reset_fragments(l_ptr); | 307 | tipc_link_reset_fragments(l_ptr); |
| 297 | spin_unlock_bh(&n_ptr->lock); | 308 | tipc_node_unlock(n_ptr); |
| 298 | 309 | ||
| 299 | /* Nobody else can access this link now: */ | 310 | /* Nobody else can access this link now: */ |
| 300 | del_timer_sync(&l_ptr->timer); | 311 | del_timer_sync(&l_ptr->timer); |
| @@ -302,12 +313,12 @@ void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) | |||
| 302 | } else { | 313 | } else { |
| 303 | /* Detach/delete when failover is finished: */ | 314 | /* Detach/delete when failover is finished: */ |
| 304 | l_ptr->flags |= LINK_STOPPED; | 315 | l_ptr->flags |= LINK_STOPPED; |
| 305 | spin_unlock_bh(&n_ptr->lock); | 316 | tipc_node_unlock(n_ptr); |
| 306 | del_timer_sync(&l_ptr->timer); | 317 | del_timer_sync(&l_ptr->timer); |
| 307 | } | 318 | } |
| 308 | continue; | 319 | continue; |
| 309 | } | 320 | } |
| 310 | spin_unlock_bh(&n_ptr->lock); | 321 | tipc_node_unlock(n_ptr); |
| 311 | } | 322 | } |
| 312 | rcu_read_unlock(); | 323 | rcu_read_unlock(); |
| 313 | } | 324 | } |
| @@ -388,9 +399,8 @@ static void link_release_outqueue(struct tipc_link *l_ptr) | |||
| 388 | */ | 399 | */ |
| 389 | void tipc_link_reset_fragments(struct tipc_link *l_ptr) | 400 | void tipc_link_reset_fragments(struct tipc_link *l_ptr) |
| 390 | { | 401 | { |
| 391 | kfree_skb(l_ptr->reasm_head); | 402 | kfree_skb(l_ptr->reasm_buf); |
| 392 | l_ptr->reasm_head = NULL; | 403 | l_ptr->reasm_buf = NULL; |
| 393 | l_ptr->reasm_tail = NULL; | ||
| 394 | } | 404 | } |
| 395 | 405 | ||
| 396 | /** | 406 | /** |
| @@ -426,7 +436,7 @@ void tipc_link_reset(struct tipc_link *l_ptr) | |||
| 426 | return; | 436 | return; |
| 427 | 437 | ||
| 428 | tipc_node_link_down(l_ptr->owner, l_ptr); | 438 | tipc_node_link_down(l_ptr->owner, l_ptr); |
| 429 | tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); | 439 | tipc_bearer_remove_dest(l_ptr->bearer_id, l_ptr->addr); |
| 430 | 440 | ||
| 431 | if (was_active_link && tipc_node_active_links(l_ptr->owner)) { | 441 | if (was_active_link && tipc_node_active_links(l_ptr->owner)) { |
| 432 | l_ptr->reset_checkpoint = checkpoint; | 442 | l_ptr->reset_checkpoint = checkpoint; |
| @@ -464,11 +474,11 @@ void tipc_link_reset_list(unsigned int bearer_id) | |||
| 464 | 474 | ||
| 465 | rcu_read_lock(); | 475 | rcu_read_lock(); |
| 466 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | 476 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { |
| 467 | spin_lock_bh(&n_ptr->lock); | 477 | tipc_node_lock(n_ptr); |
| 468 | l_ptr = n_ptr->links[bearer_id]; | 478 | l_ptr = n_ptr->links[bearer_id]; |
| 469 | if (l_ptr) | 479 | if (l_ptr) |
| 470 | tipc_link_reset(l_ptr); | 480 | tipc_link_reset(l_ptr); |
| 471 | spin_unlock_bh(&n_ptr->lock); | 481 | tipc_node_unlock(n_ptr); |
| 472 | } | 482 | } |
| 473 | rcu_read_unlock(); | 483 | rcu_read_unlock(); |
| 474 | } | 484 | } |
| @@ -477,7 +487,7 @@ static void link_activate(struct tipc_link *l_ptr) | |||
| 477 | { | 487 | { |
| 478 | l_ptr->next_in_no = l_ptr->stats.recv_info = 1; | 488 | l_ptr->next_in_no = l_ptr->stats.recv_info = 1; |
| 479 | tipc_node_link_up(l_ptr->owner, l_ptr); | 489 | tipc_node_link_up(l_ptr->owner, l_ptr); |
| 480 | tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); | 490 | tipc_bearer_add_dest(l_ptr->bearer_id, l_ptr->addr); |
| 481 | } | 491 | } |
| 482 | 492 | ||
| 483 | /** | 493 | /** |
| @@ -777,7 +787,7 @@ int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 777 | if (likely(!link_congested(l_ptr))) { | 787 | if (likely(!link_congested(l_ptr))) { |
| 778 | link_add_to_outqueue(l_ptr, buf, msg); | 788 | link_add_to_outqueue(l_ptr, buf, msg); |
| 779 | 789 | ||
| 780 | tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); | 790 | tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr); |
| 781 | l_ptr->unacked_window = 0; | 791 | l_ptr->unacked_window = 0; |
| 782 | return dsz; | 792 | return dsz; |
| 783 | } | 793 | } |
| @@ -825,7 +835,6 @@ int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector) | |||
| 825 | struct tipc_node *n_ptr; | 835 | struct tipc_node *n_ptr; |
| 826 | int res = -ELINKCONG; | 836 | int res = -ELINKCONG; |
| 827 | 837 | ||
| 828 | read_lock_bh(&tipc_net_lock); | ||
| 829 | n_ptr = tipc_node_find(dest); | 838 | n_ptr = tipc_node_find(dest); |
| 830 | if (n_ptr) { | 839 | if (n_ptr) { |
| 831 | tipc_node_lock(n_ptr); | 840 | tipc_node_lock(n_ptr); |
| @@ -838,7 +847,6 @@ int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector) | |||
| 838 | } else { | 847 | } else { |
| 839 | kfree_skb(buf); | 848 | kfree_skb(buf); |
| 840 | } | 849 | } |
| 841 | read_unlock_bh(&tipc_net_lock); | ||
| 842 | return res; | 850 | return res; |
| 843 | } | 851 | } |
| 844 | 852 | ||
| @@ -902,7 +910,6 @@ void tipc_link_names_xmit(struct list_head *message_list, u32 dest) | |||
| 902 | if (list_empty(message_list)) | 910 | if (list_empty(message_list)) |
| 903 | return; | 911 | return; |
| 904 | 912 | ||
| 905 | read_lock_bh(&tipc_net_lock); | ||
| 906 | n_ptr = tipc_node_find(dest); | 913 | n_ptr = tipc_node_find(dest); |
| 907 | if (n_ptr) { | 914 | if (n_ptr) { |
| 908 | tipc_node_lock(n_ptr); | 915 | tipc_node_lock(n_ptr); |
| @@ -917,7 +924,6 @@ void tipc_link_names_xmit(struct list_head *message_list, u32 dest) | |||
| 917 | } | 924 | } |
| 918 | tipc_node_unlock(n_ptr); | 925 | tipc_node_unlock(n_ptr); |
| 919 | } | 926 | } |
| 920 | read_unlock_bh(&tipc_net_lock); | ||
| 921 | 927 | ||
| 922 | /* discard the messages if they couldn't be sent */ | 928 | /* discard the messages if they couldn't be sent */ |
| 923 | list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { | 929 | list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { |
| @@ -941,7 +947,7 @@ static int tipc_link_xmit_fast(struct tipc_link *l_ptr, struct sk_buff *buf, | |||
| 941 | if (likely(!link_congested(l_ptr))) { | 947 | if (likely(!link_congested(l_ptr))) { |
| 942 | if (likely(msg_size(msg) <= l_ptr->max_pkt)) { | 948 | if (likely(msg_size(msg) <= l_ptr->max_pkt)) { |
| 943 | link_add_to_outqueue(l_ptr, buf, msg); | 949 | link_add_to_outqueue(l_ptr, buf, msg); |
| 944 | tipc_bearer_send(l_ptr->b_ptr, buf, | 950 | tipc_bearer_send(l_ptr->bearer_id, buf, |
| 945 | &l_ptr->media_addr); | 951 | &l_ptr->media_addr); |
| 946 | l_ptr->unacked_window = 0; | 952 | l_ptr->unacked_window = 0; |
| 947 | return res; | 953 | return res; |
| @@ -979,7 +985,6 @@ again: | |||
| 979 | if (unlikely(res < 0)) | 985 | if (unlikely(res < 0)) |
| 980 | return res; | 986 | return res; |
| 981 | 987 | ||
| 982 | read_lock_bh(&tipc_net_lock); | ||
| 983 | node = tipc_node_find(destaddr); | 988 | node = tipc_node_find(destaddr); |
| 984 | if (likely(node)) { | 989 | if (likely(node)) { |
| 985 | tipc_node_lock(node); | 990 | tipc_node_lock(node); |
| @@ -990,7 +995,6 @@ again: | |||
| 990 | &sender->max_pkt); | 995 | &sender->max_pkt); |
| 991 | exit: | 996 | exit: |
| 992 | tipc_node_unlock(node); | 997 | tipc_node_unlock(node); |
| 993 | read_unlock_bh(&tipc_net_lock); | ||
| 994 | return res; | 998 | return res; |
| 995 | } | 999 | } |
| 996 | 1000 | ||
| @@ -1007,7 +1011,6 @@ exit: | |||
| 1007 | */ | 1011 | */ |
| 1008 | sender->max_pkt = l_ptr->max_pkt; | 1012 | sender->max_pkt = l_ptr->max_pkt; |
| 1009 | tipc_node_unlock(node); | 1013 | tipc_node_unlock(node); |
| 1010 | read_unlock_bh(&tipc_net_lock); | ||
| 1011 | 1014 | ||
| 1012 | 1015 | ||
| 1013 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) | 1016 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) |
| @@ -1018,7 +1021,6 @@ exit: | |||
| 1018 | } | 1021 | } |
| 1019 | tipc_node_unlock(node); | 1022 | tipc_node_unlock(node); |
| 1020 | } | 1023 | } |
| 1021 | read_unlock_bh(&tipc_net_lock); | ||
| 1022 | 1024 | ||
| 1023 | /* Couldn't find a link to the destination node */ | 1025 | /* Couldn't find a link to the destination node */ |
| 1024 | kfree_skb(buf); | 1026 | kfree_skb(buf); |
| @@ -1204,7 +1206,7 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr) | |||
| 1204 | if (r_q_size && buf) { | 1206 | if (r_q_size && buf) { |
| 1205 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | 1207 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); |
| 1206 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); | 1208 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); |
| 1207 | tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); | 1209 | tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr); |
| 1208 | l_ptr->retransm_queue_head = mod(++r_q_head); | 1210 | l_ptr->retransm_queue_head = mod(++r_q_head); |
| 1209 | l_ptr->retransm_queue_size = --r_q_size; | 1211 | l_ptr->retransm_queue_size = --r_q_size; |
| 1210 | l_ptr->stats.retransmitted++; | 1212 | l_ptr->stats.retransmitted++; |
| @@ -1216,7 +1218,7 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr) | |||
| 1216 | if (buf) { | 1218 | if (buf) { |
| 1217 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | 1219 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); |
| 1218 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); | 1220 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); |
| 1219 | tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); | 1221 | tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr); |
| 1220 | l_ptr->unacked_window = 0; | 1222 | l_ptr->unacked_window = 0; |
| 1221 | kfree_skb(buf); | 1223 | kfree_skb(buf); |
| 1222 | l_ptr->proto_msg_queue = NULL; | 1224 | l_ptr->proto_msg_queue = NULL; |
| @@ -1233,7 +1235,8 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr) | |||
| 1233 | if (mod(next - first) < l_ptr->queue_limit[0]) { | 1235 | if (mod(next - first) < l_ptr->queue_limit[0]) { |
| 1234 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 1236 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); |
| 1235 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 1237 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); |
| 1236 | tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); | 1238 | tipc_bearer_send(l_ptr->bearer_id, buf, |
| 1239 | &l_ptr->media_addr); | ||
| 1237 | if (msg_user(msg) == MSG_BUNDLER) | 1240 | if (msg_user(msg) == MSG_BUNDLER) |
| 1238 | msg_set_type(msg, CLOSED_MSG); | 1241 | msg_set_type(msg, CLOSED_MSG); |
| 1239 | l_ptr->next_out = buf->next; | 1242 | l_ptr->next_out = buf->next; |
| @@ -1256,33 +1259,24 @@ void tipc_link_push_queue(struct tipc_link *l_ptr) | |||
| 1256 | } while (!res); | 1259 | } while (!res); |
| 1257 | } | 1260 | } |
| 1258 | 1261 | ||
| 1259 | static void link_reset_all(unsigned long addr) | 1262 | void tipc_link_reset_all(struct tipc_node *node) |
| 1260 | { | 1263 | { |
| 1261 | struct tipc_node *n_ptr; | ||
| 1262 | char addr_string[16]; | 1264 | char addr_string[16]; |
| 1263 | u32 i; | 1265 | u32 i; |
| 1264 | 1266 | ||
| 1265 | read_lock_bh(&tipc_net_lock); | 1267 | tipc_node_lock(node); |
| 1266 | n_ptr = tipc_node_find((u32)addr); | ||
| 1267 | if (!n_ptr) { | ||
| 1268 | read_unlock_bh(&tipc_net_lock); | ||
| 1269 | return; /* node no longer exists */ | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | tipc_node_lock(n_ptr); | ||
| 1273 | 1268 | ||
| 1274 | pr_warn("Resetting all links to %s\n", | 1269 | pr_warn("Resetting all links to %s\n", |
| 1275 | tipc_addr_string_fill(addr_string, n_ptr->addr)); | 1270 | tipc_addr_string_fill(addr_string, node->addr)); |
| 1276 | 1271 | ||
| 1277 | for (i = 0; i < MAX_BEARERS; i++) { | 1272 | for (i = 0; i < MAX_BEARERS; i++) { |
| 1278 | if (n_ptr->links[i]) { | 1273 | if (node->links[i]) { |
| 1279 | link_print(n_ptr->links[i], "Resetting link\n"); | 1274 | link_print(node->links[i], "Resetting link\n"); |
| 1280 | tipc_link_reset(n_ptr->links[i]); | 1275 | tipc_link_reset(node->links[i]); |
| 1281 | } | 1276 | } |
| 1282 | } | 1277 | } |
| 1283 | 1278 | ||
| 1284 | tipc_node_unlock(n_ptr); | 1279 | tipc_node_unlock(node); |
| 1285 | read_unlock_bh(&tipc_net_lock); | ||
| 1286 | } | 1280 | } |
| 1287 | 1281 | ||
| 1288 | static void link_retransmit_failure(struct tipc_link *l_ptr, | 1282 | static void link_retransmit_failure(struct tipc_link *l_ptr, |
| @@ -1319,10 +1313,9 @@ static void link_retransmit_failure(struct tipc_link *l_ptr, | |||
| 1319 | n_ptr->bclink.oos_state, | 1313 | n_ptr->bclink.oos_state, |
| 1320 | n_ptr->bclink.last_sent); | 1314 | n_ptr->bclink.last_sent); |
| 1321 | 1315 | ||
| 1322 | tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); | ||
| 1323 | |||
| 1324 | tipc_node_unlock(n_ptr); | 1316 | tipc_node_unlock(n_ptr); |
| 1325 | 1317 | ||
| 1318 | tipc_bclink_set_flags(TIPC_BCLINK_RESET); | ||
| 1326 | l_ptr->stale_count = 0; | 1319 | l_ptr->stale_count = 0; |
| 1327 | } | 1320 | } |
| 1328 | } | 1321 | } |
| @@ -1352,7 +1345,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf, | |||
| 1352 | msg = buf_msg(buf); | 1345 | msg = buf_msg(buf); |
| 1353 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 1346 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); |
| 1354 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 1347 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); |
| 1355 | tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); | 1348 | tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr); |
| 1356 | buf = buf->next; | 1349 | buf = buf->next; |
| 1357 | retransmits--; | 1350 | retransmits--; |
| 1358 | l_ptr->stats.retransmitted++; | 1351 | l_ptr->stats.retransmitted++; |
| @@ -1440,14 +1433,13 @@ static int link_recv_buf_validate(struct sk_buff *buf) | |||
| 1440 | /** | 1433 | /** |
| 1441 | * tipc_rcv - process TIPC packets/messages arriving from off-node | 1434 | * tipc_rcv - process TIPC packets/messages arriving from off-node |
| 1442 | * @head: pointer to message buffer chain | 1435 | * @head: pointer to message buffer chain |
| 1443 | * @tb_ptr: pointer to bearer message arrived on | 1436 | * @b_ptr: pointer to bearer message arrived on |
| 1444 | * | 1437 | * |
| 1445 | * Invoked with no locks held. Bearer pointer must point to a valid bearer | 1438 | * Invoked with no locks held. Bearer pointer must point to a valid bearer |
| 1446 | * structure (i.e. cannot be NULL), but bearer can be inactive. | 1439 | * structure (i.e. cannot be NULL), but bearer can be inactive. |
| 1447 | */ | 1440 | */ |
| 1448 | void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | 1441 | void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) |
| 1449 | { | 1442 | { |
| 1450 | read_lock_bh(&tipc_net_lock); | ||
| 1451 | while (head) { | 1443 | while (head) { |
| 1452 | struct tipc_node *n_ptr; | 1444 | struct tipc_node *n_ptr; |
| 1453 | struct tipc_link *l_ptr; | 1445 | struct tipc_link *l_ptr; |
| @@ -1497,14 +1489,14 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1497 | goto unlock_discard; | 1489 | goto unlock_discard; |
| 1498 | 1490 | ||
| 1499 | /* Verify that communication with node is currently allowed */ | 1491 | /* Verify that communication with node is currently allowed */ |
| 1500 | if ((n_ptr->block_setup & WAIT_PEER_DOWN) && | 1492 | if ((n_ptr->action_flags & TIPC_WAIT_PEER_LINKS_DOWN) && |
| 1501 | msg_user(msg) == LINK_PROTOCOL && | 1493 | msg_user(msg) == LINK_PROTOCOL && |
| 1502 | (msg_type(msg) == RESET_MSG || | 1494 | (msg_type(msg) == RESET_MSG || |
| 1503 | msg_type(msg) == ACTIVATE_MSG) && | 1495 | msg_type(msg) == ACTIVATE_MSG) && |
| 1504 | !msg_redundant_link(msg)) | 1496 | !msg_redundant_link(msg)) |
| 1505 | n_ptr->block_setup &= ~WAIT_PEER_DOWN; | 1497 | n_ptr->action_flags &= ~TIPC_WAIT_PEER_LINKS_DOWN; |
| 1506 | 1498 | ||
| 1507 | if (n_ptr->block_setup) | 1499 | if (tipc_node_blocked(n_ptr)) |
| 1508 | goto unlock_discard; | 1500 | goto unlock_discard; |
| 1509 | 1501 | ||
| 1510 | /* Validate message sequence number info */ | 1502 | /* Validate message sequence number info */ |
| @@ -1581,17 +1573,12 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1581 | } | 1573 | } |
| 1582 | msg = buf_msg(buf); | 1574 | msg = buf_msg(buf); |
| 1583 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | 1575 | } else if (msg_user(msg) == MSG_FRAGMENTER) { |
| 1584 | int rc; | ||
| 1585 | |||
| 1586 | l_ptr->stats.recv_fragments++; | 1576 | l_ptr->stats.recv_fragments++; |
| 1587 | rc = tipc_link_frag_rcv(&l_ptr->reasm_head, | 1577 | if (tipc_buf_append(&l_ptr->reasm_buf, &buf)) { |
| 1588 | &l_ptr->reasm_tail, | ||
| 1589 | &buf); | ||
| 1590 | if (rc == LINK_REASM_COMPLETE) { | ||
| 1591 | l_ptr->stats.recv_fragmented++; | 1578 | l_ptr->stats.recv_fragmented++; |
| 1592 | msg = buf_msg(buf); | 1579 | msg = buf_msg(buf); |
| 1593 | } else { | 1580 | } else { |
| 1594 | if (rc == LINK_REASM_ERROR) | 1581 | if (!l_ptr->reasm_buf) |
| 1595 | tipc_link_reset(l_ptr); | 1582 | tipc_link_reset(l_ptr); |
| 1596 | tipc_node_unlock(n_ptr); | 1583 | tipc_node_unlock(n_ptr); |
| 1597 | continue; | 1584 | continue; |
| @@ -1604,7 +1591,7 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1604 | case TIPC_HIGH_IMPORTANCE: | 1591 | case TIPC_HIGH_IMPORTANCE: |
| 1605 | case TIPC_CRITICAL_IMPORTANCE: | 1592 | case TIPC_CRITICAL_IMPORTANCE: |
| 1606 | tipc_node_unlock(n_ptr); | 1593 | tipc_node_unlock(n_ptr); |
| 1607 | tipc_port_rcv(buf); | 1594 | tipc_sk_rcv(buf); |
| 1608 | continue; | 1595 | continue; |
| 1609 | case MSG_BUNDLER: | 1596 | case MSG_BUNDLER: |
| 1610 | l_ptr->stats.recv_bundles++; | 1597 | l_ptr->stats.recv_bundles++; |
| @@ -1635,7 +1622,6 @@ unlock_discard: | |||
| 1635 | discard: | 1622 | discard: |
| 1636 | kfree_skb(buf); | 1623 | kfree_skb(buf); |
| 1637 | } | 1624 | } |
| 1638 | read_unlock_bh(&tipc_net_lock); | ||
| 1639 | } | 1625 | } |
| 1640 | 1626 | ||
| 1641 | /** | 1627 | /** |
| @@ -1747,12 +1733,12 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, | |||
| 1747 | return; | 1733 | return; |
| 1748 | 1734 | ||
| 1749 | /* Abort non-RESET send if communication with node is prohibited */ | 1735 | /* Abort non-RESET send if communication with node is prohibited */ |
| 1750 | if ((l_ptr->owner->block_setup) && (msg_typ != RESET_MSG)) | 1736 | if ((tipc_node_blocked(l_ptr->owner)) && (msg_typ != RESET_MSG)) |
| 1751 | return; | 1737 | return; |
| 1752 | 1738 | ||
| 1753 | /* Create protocol message with "out-of-sequence" sequence number */ | 1739 | /* Create protocol message with "out-of-sequence" sequence number */ |
| 1754 | msg_set_type(msg, msg_typ); | 1740 | msg_set_type(msg, msg_typ); |
| 1755 | msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); | 1741 | msg_set_net_plane(msg, l_ptr->net_plane); |
| 1756 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 1742 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); |
| 1757 | msg_set_last_bcast(msg, tipc_bclink_get_last_sent()); | 1743 | msg_set_last_bcast(msg, tipc_bclink_get_last_sent()); |
| 1758 | 1744 | ||
| @@ -1818,7 +1804,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, | |||
| 1818 | skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); | 1804 | skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); |
| 1819 | buf->priority = TC_PRIO_CONTROL; | 1805 | buf->priority = TC_PRIO_CONTROL; |
| 1820 | 1806 | ||
| 1821 | tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); | 1807 | tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr); |
| 1822 | l_ptr->unacked_window = 0; | 1808 | l_ptr->unacked_window = 0; |
| 1823 | kfree_skb(buf); | 1809 | kfree_skb(buf); |
| 1824 | } | 1810 | } |
| @@ -1840,12 +1826,9 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 1840 | if (l_ptr->exp_msg_count) | 1826 | if (l_ptr->exp_msg_count) |
| 1841 | goto exit; | 1827 | goto exit; |
| 1842 | 1828 | ||
| 1843 | /* record unnumbered packet arrival (force mismatch on next timeout) */ | 1829 | if (l_ptr->net_plane != msg_net_plane(msg)) |
| 1844 | l_ptr->checkpoint--; | ||
| 1845 | |||
| 1846 | if (l_ptr->b_ptr->net_plane != msg_net_plane(msg)) | ||
| 1847 | if (tipc_own_addr > msg_prevnode(msg)) | 1830 | if (tipc_own_addr > msg_prevnode(msg)) |
| 1848 | l_ptr->b_ptr->net_plane = msg_net_plane(msg); | 1831 | l_ptr->net_plane = msg_net_plane(msg); |
| 1849 | 1832 | ||
| 1850 | switch (msg_type(msg)) { | 1833 | switch (msg_type(msg)) { |
| 1851 | 1834 | ||
| @@ -1862,7 +1845,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 1862 | * peer has lost contact -- don't allow peer's links | 1845 | * peer has lost contact -- don't allow peer's links |
| 1863 | * to reactivate before we recognize loss & clean up | 1846 | * to reactivate before we recognize loss & clean up |
| 1864 | */ | 1847 | */ |
| 1865 | l_ptr->owner->block_setup = WAIT_NODE_DOWN; | 1848 | l_ptr->owner->action_flags |= TIPC_WAIT_OWN_LINKS_DOWN; |
| 1866 | } | 1849 | } |
| 1867 | 1850 | ||
| 1868 | link_state_event(l_ptr, RESET_MSG); | 1851 | link_state_event(l_ptr, RESET_MSG); |
| @@ -1918,6 +1901,10 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 1918 | tipc_link_reset(l_ptr); /* Enforce change to take effect */ | 1901 | tipc_link_reset(l_ptr); /* Enforce change to take effect */ |
| 1919 | break; | 1902 | break; |
| 1920 | } | 1903 | } |
| 1904 | |||
| 1905 | /* Record reception; force mismatch at next timeout: */ | ||
| 1906 | l_ptr->checkpoint--; | ||
| 1907 | |||
| 1921 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); | 1908 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); |
| 1922 | l_ptr->stats.recv_states++; | 1909 | l_ptr->stats.recv_states++; |
| 1923 | if (link_reset_unknown(l_ptr)) | 1910 | if (link_reset_unknown(l_ptr)) |
| @@ -2177,9 +2164,7 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr, | |||
| 2177 | } | 2164 | } |
| 2178 | if (msg_user(msg) == MSG_FRAGMENTER) { | 2165 | if (msg_user(msg) == MSG_FRAGMENTER) { |
| 2179 | l_ptr->stats.recv_fragments++; | 2166 | l_ptr->stats.recv_fragments++; |
| 2180 | tipc_link_frag_rcv(&l_ptr->reasm_head, | 2167 | tipc_buf_append(&l_ptr->reasm_buf, &buf); |
| 2181 | &l_ptr->reasm_tail, | ||
| 2182 | &buf); | ||
| 2183 | } | 2168 | } |
| 2184 | } | 2169 | } |
| 2185 | exit: | 2170 | exit: |
| @@ -2317,53 +2302,6 @@ static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 2317 | return dsz; | 2302 | return dsz; |
| 2318 | } | 2303 | } |
| 2319 | 2304 | ||
| 2320 | /* tipc_link_frag_rcv(): Called with node lock on. Returns | ||
| 2321 | * the reassembled buffer if message is complete. | ||
| 2322 | */ | ||
| 2323 | int tipc_link_frag_rcv(struct sk_buff **head, struct sk_buff **tail, | ||
| 2324 | struct sk_buff **fbuf) | ||
| 2325 | { | ||
| 2326 | struct sk_buff *frag = *fbuf; | ||
| 2327 | struct tipc_msg *msg = buf_msg(frag); | ||
| 2328 | u32 fragid = msg_type(msg); | ||
| 2329 | bool headstolen; | ||
| 2330 | int delta; | ||
| 2331 | |||
| 2332 | skb_pull(frag, msg_hdr_sz(msg)); | ||
| 2333 | if (fragid == FIRST_FRAGMENT) { | ||
| 2334 | if (*head || skb_unclone(frag, GFP_ATOMIC)) | ||
| 2335 | goto out_free; | ||
| 2336 | *head = frag; | ||
| 2337 | skb_frag_list_init(*head); | ||
| 2338 | *fbuf = NULL; | ||
| 2339 | return 0; | ||
| 2340 | } else if (*head && | ||
| 2341 | skb_try_coalesce(*head, frag, &headstolen, &delta)) { | ||
| 2342 | kfree_skb_partial(frag, headstolen); | ||
| 2343 | } else { | ||
| 2344 | if (!*head) | ||
| 2345 | goto out_free; | ||
| 2346 | if (!skb_has_frag_list(*head)) | ||
| 2347 | skb_shinfo(*head)->frag_list = frag; | ||
| 2348 | else | ||
| 2349 | (*tail)->next = frag; | ||
| 2350 | *tail = frag; | ||
| 2351 | (*head)->truesize += frag->truesize; | ||
| 2352 | } | ||
| 2353 | if (fragid == LAST_FRAGMENT) { | ||
| 2354 | *fbuf = *head; | ||
| 2355 | *tail = *head = NULL; | ||
| 2356 | return LINK_REASM_COMPLETE; | ||
| 2357 | } | ||
| 2358 | *fbuf = NULL; | ||
| 2359 | return 0; | ||
| 2360 | out_free: | ||
| 2361 | pr_warn_ratelimited("Link unable to reassemble fragmented message\n"); | ||
| 2362 | kfree_skb(*fbuf); | ||
| 2363 | *fbuf = NULL; | ||
| 2364 | return LINK_REASM_ERROR; | ||
| 2365 | } | ||
| 2366 | |||
| 2367 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) | 2305 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) |
| 2368 | { | 2306 | { |
| 2369 | if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL)) | 2307 | if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL)) |
| @@ -2397,8 +2335,6 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window) | |||
| 2397 | /* tipc_link_find_owner - locate owner node of link by link's name | 2335 | /* tipc_link_find_owner - locate owner node of link by link's name |
| 2398 | * @name: pointer to link name string | 2336 | * @name: pointer to link name string |
| 2399 | * @bearer_id: pointer to index in 'node->links' array where the link was found. | 2337 | * @bearer_id: pointer to index in 'node->links' array where the link was found. |
| 2400 | * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted; | ||
| 2401 | * this also prevents link deletion. | ||
| 2402 | * | 2338 | * |
| 2403 | * Returns pointer to node owning the link, or 0 if no matching link is found. | 2339 | * Returns pointer to node owning the link, or 0 if no matching link is found. |
| 2404 | */ | 2340 | */ |
| @@ -2460,7 +2396,7 @@ static int link_value_is_valid(u16 cmd, u32 new_value) | |||
| 2460 | * @new_value: new value of link, bearer, or media setting | 2396 | * @new_value: new value of link, bearer, or media setting |
| 2461 | * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*) | 2397 | * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*) |
| 2462 | * | 2398 | * |
| 2463 | * Caller must hold 'tipc_net_lock' to ensure link/bearer/media is not deleted. | 2399 | * Caller must hold RTNL lock to ensure link/bearer/media is not deleted. |
| 2464 | * | 2400 | * |
| 2465 | * Returns 0 if value updated and negative value on error. | 2401 | * Returns 0 if value updated and negative value on error. |
| 2466 | */ | 2402 | */ |
| @@ -2566,9 +2502,7 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space | |||
| 2566 | " (cannot change setting on broadcast link)"); | 2502 | " (cannot change setting on broadcast link)"); |
| 2567 | } | 2503 | } |
| 2568 | 2504 | ||
| 2569 | read_lock_bh(&tipc_net_lock); | ||
| 2570 | res = link_cmd_set_value(args->name, new_value, cmd); | 2505 | res = link_cmd_set_value(args->name, new_value, cmd); |
| 2571 | read_unlock_bh(&tipc_net_lock); | ||
| 2572 | if (res) | 2506 | if (res) |
| 2573 | return tipc_cfg_reply_error_string("cannot change link setting"); | 2507 | return tipc_cfg_reply_error_string("cannot change link setting"); |
| 2574 | 2508 | ||
| @@ -2602,22 +2536,18 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_ | |||
| 2602 | return tipc_cfg_reply_error_string("link not found"); | 2536 | return tipc_cfg_reply_error_string("link not found"); |
| 2603 | return tipc_cfg_reply_none(); | 2537 | return tipc_cfg_reply_none(); |
| 2604 | } | 2538 | } |
| 2605 | read_lock_bh(&tipc_net_lock); | ||
| 2606 | node = tipc_link_find_owner(link_name, &bearer_id); | 2539 | node = tipc_link_find_owner(link_name, &bearer_id); |
| 2607 | if (!node) { | 2540 | if (!node) |
| 2608 | read_unlock_bh(&tipc_net_lock); | ||
| 2609 | return tipc_cfg_reply_error_string("link not found"); | 2541 | return tipc_cfg_reply_error_string("link not found"); |
| 2610 | } | 2542 | |
| 2611 | tipc_node_lock(node); | 2543 | tipc_node_lock(node); |
| 2612 | l_ptr = node->links[bearer_id]; | 2544 | l_ptr = node->links[bearer_id]; |
| 2613 | if (!l_ptr) { | 2545 | if (!l_ptr) { |
| 2614 | tipc_node_unlock(node); | 2546 | tipc_node_unlock(node); |
| 2615 | read_unlock_bh(&tipc_net_lock); | ||
| 2616 | return tipc_cfg_reply_error_string("link not found"); | 2547 | return tipc_cfg_reply_error_string("link not found"); |
| 2617 | } | 2548 | } |
| 2618 | link_reset_statistics(l_ptr); | 2549 | link_reset_statistics(l_ptr); |
| 2619 | tipc_node_unlock(node); | 2550 | tipc_node_unlock(node); |
| 2620 | read_unlock_bh(&tipc_net_lock); | ||
| 2621 | return tipc_cfg_reply_none(); | 2551 | return tipc_cfg_reply_none(); |
| 2622 | } | 2552 | } |
| 2623 | 2553 | ||
| @@ -2650,18 +2580,15 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) | |||
| 2650 | if (!strcmp(name, tipc_bclink_name)) | 2580 | if (!strcmp(name, tipc_bclink_name)) |
| 2651 | return tipc_bclink_stats(buf, buf_size); | 2581 | return tipc_bclink_stats(buf, buf_size); |
| 2652 | 2582 | ||
| 2653 | read_lock_bh(&tipc_net_lock); | ||
| 2654 | node = tipc_link_find_owner(name, &bearer_id); | 2583 | node = tipc_link_find_owner(name, &bearer_id); |
| 2655 | if (!node) { | 2584 | if (!node) |
| 2656 | read_unlock_bh(&tipc_net_lock); | ||
| 2657 | return 0; | 2585 | return 0; |
| 2658 | } | 2586 | |
| 2659 | tipc_node_lock(node); | 2587 | tipc_node_lock(node); |
| 2660 | 2588 | ||
| 2661 | l = node->links[bearer_id]; | 2589 | l = node->links[bearer_id]; |
| 2662 | if (!l) { | 2590 | if (!l) { |
| 2663 | tipc_node_unlock(node); | 2591 | tipc_node_unlock(node); |
| 2664 | read_unlock_bh(&tipc_net_lock); | ||
| 2665 | return 0; | 2592 | return 0; |
| 2666 | } | 2593 | } |
| 2667 | 2594 | ||
| @@ -2727,7 +2654,6 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) | |||
| 2727 | (s->accu_queue_sz / s->queue_sz_counts) : 0); | 2654 | (s->accu_queue_sz / s->queue_sz_counts) : 0); |
| 2728 | 2655 | ||
| 2729 | tipc_node_unlock(node); | 2656 | tipc_node_unlock(node); |
| 2730 | read_unlock_bh(&tipc_net_lock); | ||
| 2731 | return ret; | 2657 | return ret; |
| 2732 | } | 2658 | } |
| 2733 | 2659 | ||
| @@ -2778,7 +2704,6 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector) | |||
| 2778 | if (dest == tipc_own_addr) | 2704 | if (dest == tipc_own_addr) |
| 2779 | return MAX_MSG_SIZE; | 2705 | return MAX_MSG_SIZE; |
| 2780 | 2706 | ||
| 2781 | read_lock_bh(&tipc_net_lock); | ||
| 2782 | n_ptr = tipc_node_find(dest); | 2707 | n_ptr = tipc_node_find(dest); |
| 2783 | if (n_ptr) { | 2708 | if (n_ptr) { |
| 2784 | tipc_node_lock(n_ptr); | 2709 | tipc_node_lock(n_ptr); |
| @@ -2787,13 +2712,18 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector) | |||
| 2787 | res = l_ptr->max_pkt; | 2712 | res = l_ptr->max_pkt; |
| 2788 | tipc_node_unlock(n_ptr); | 2713 | tipc_node_unlock(n_ptr); |
| 2789 | } | 2714 | } |
| 2790 | read_unlock_bh(&tipc_net_lock); | ||
| 2791 | return res; | 2715 | return res; |
| 2792 | } | 2716 | } |
| 2793 | 2717 | ||
| 2794 | static void link_print(struct tipc_link *l_ptr, const char *str) | 2718 | static void link_print(struct tipc_link *l_ptr, const char *str) |
| 2795 | { | 2719 | { |
| 2796 | pr_info("%s Link %x<%s>:", str, l_ptr->addr, l_ptr->b_ptr->name); | 2720 | struct tipc_bearer *b_ptr; |
| 2721 | |||
| 2722 | rcu_read_lock(); | ||
| 2723 | b_ptr = rcu_dereference_rtnl(bearer_list[l_ptr->bearer_id]); | ||
| 2724 | if (b_ptr) | ||
| 2725 | pr_info("%s Link %x<%s>:", str, l_ptr->addr, b_ptr->name); | ||
| 2726 | rcu_read_unlock(); | ||
| 2797 | 2727 | ||
| 2798 | if (link_working_unknown(l_ptr)) | 2728 | if (link_working_unknown(l_ptr)) |
| 2799 | pr_cont(":WU\n"); | 2729 | pr_cont(":WU\n"); |
