diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 227 |
1 files changed, 117 insertions, 110 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index 572063a0190e..47d5f84c90c5 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -141,10 +141,63 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr) | |||
141 | return NULL; | 141 | return NULL; |
142 | } | 142 | } |
143 | 143 | ||
144 | void tipc_node_read_lock(struct tipc_node *n) | ||
145 | { | ||
146 | read_lock_bh(&n->lock); | ||
147 | } | ||
148 | |||
149 | void tipc_node_read_unlock(struct tipc_node *n) | ||
150 | { | ||
151 | read_unlock_bh(&n->lock); | ||
152 | } | ||
153 | |||
154 | static void tipc_node_write_lock(struct tipc_node *n) | ||
155 | { | ||
156 | write_lock_bh(&n->lock); | ||
157 | } | ||
158 | |||
159 | static void tipc_node_write_unlock(struct tipc_node *n) | ||
160 | { | ||
161 | struct net *net = n->net; | ||
162 | u32 addr = 0; | ||
163 | u32 flags = n->action_flags; | ||
164 | u32 link_id = 0; | ||
165 | struct list_head *publ_list; | ||
166 | |||
167 | if (likely(!flags)) { | ||
168 | write_unlock_bh(&n->lock); | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | addr = n->addr; | ||
173 | link_id = n->link_id; | ||
174 | publ_list = &n->publ_list; | ||
175 | |||
176 | n->action_flags &= ~(TIPC_NOTIFY_NODE_DOWN | TIPC_NOTIFY_NODE_UP | | ||
177 | TIPC_NOTIFY_LINK_DOWN | TIPC_NOTIFY_LINK_UP); | ||
178 | |||
179 | write_unlock_bh(&n->lock); | ||
180 | |||
181 | if (flags & TIPC_NOTIFY_NODE_DOWN) | ||
182 | tipc_publ_notify(net, publ_list, addr); | ||
183 | |||
184 | if (flags & TIPC_NOTIFY_NODE_UP) | ||
185 | tipc_named_node_up(net, addr); | ||
186 | |||
187 | if (flags & TIPC_NOTIFY_LINK_UP) | ||
188 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, | ||
189 | TIPC_NODE_SCOPE, link_id, addr); | ||
190 | |||
191 | if (flags & TIPC_NOTIFY_LINK_DOWN) | ||
192 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, | ||
193 | link_id, addr); | ||
194 | } | ||
195 | |||
144 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | 196 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) |
145 | { | 197 | { |
146 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 198 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
147 | struct tipc_node *n_ptr, *temp_node; | 199 | struct tipc_node *n_ptr, *temp_node; |
200 | int i; | ||
148 | 201 | ||
149 | spin_lock_bh(&tn->node_list_lock); | 202 | spin_lock_bh(&tn->node_list_lock); |
150 | n_ptr = tipc_node_find(net, addr); | 203 | n_ptr = tipc_node_find(net, addr); |
@@ -159,7 +212,7 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | |||
159 | n_ptr->net = net; | 212 | n_ptr->net = net; |
160 | n_ptr->capabilities = capabilities; | 213 | n_ptr->capabilities = capabilities; |
161 | kref_init(&n_ptr->kref); | 214 | kref_init(&n_ptr->kref); |
162 | spin_lock_init(&n_ptr->lock); | 215 | rwlock_init(&n_ptr->lock); |
163 | INIT_HLIST_NODE(&n_ptr->hash); | 216 | INIT_HLIST_NODE(&n_ptr->hash); |
164 | INIT_LIST_HEAD(&n_ptr->list); | 217 | INIT_LIST_HEAD(&n_ptr->list); |
165 | INIT_LIST_HEAD(&n_ptr->publ_list); | 218 | INIT_LIST_HEAD(&n_ptr->publ_list); |
@@ -168,6 +221,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | |||
168 | skb_queue_head_init(&n_ptr->bc_entry.inputq1); | 221 | skb_queue_head_init(&n_ptr->bc_entry.inputq1); |
169 | __skb_queue_head_init(&n_ptr->bc_entry.arrvq); | 222 | __skb_queue_head_init(&n_ptr->bc_entry.arrvq); |
170 | skb_queue_head_init(&n_ptr->bc_entry.inputq2); | 223 | skb_queue_head_init(&n_ptr->bc_entry.inputq2); |
224 | for (i = 0; i < MAX_BEARERS; i++) | ||
225 | spin_lock_init(&n_ptr->links[i].lock); | ||
171 | hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]); | 226 | hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]); |
172 | list_for_each_entry_rcu(temp_node, &tn->node_list, list) { | 227 | list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
173 | if (n_ptr->addr < temp_node->addr) | 228 | if (n_ptr->addr < temp_node->addr) |
@@ -246,9 +301,9 @@ void tipc_node_subscribe(struct net *net, struct list_head *subscr, u32 addr) | |||
246 | pr_warn("Node subscribe rejected, unknown node 0x%x\n", addr); | 301 | pr_warn("Node subscribe rejected, unknown node 0x%x\n", addr); |
247 | return; | 302 | return; |
248 | } | 303 | } |
249 | tipc_node_lock(n); | 304 | tipc_node_write_lock(n); |
250 | list_add_tail(subscr, &n->publ_list); | 305 | list_add_tail(subscr, &n->publ_list); |
251 | tipc_node_unlock(n); | 306 | tipc_node_write_unlock(n); |
252 | tipc_node_put(n); | 307 | tipc_node_put(n); |
253 | } | 308 | } |
254 | 309 | ||
@@ -264,9 +319,9 @@ void tipc_node_unsubscribe(struct net *net, struct list_head *subscr, u32 addr) | |||
264 | pr_warn("Node unsubscribe rejected, unknown node 0x%x\n", addr); | 319 | pr_warn("Node unsubscribe rejected, unknown node 0x%x\n", addr); |
265 | return; | 320 | return; |
266 | } | 321 | } |
267 | tipc_node_lock(n); | 322 | tipc_node_write_lock(n); |
268 | list_del_init(subscr); | 323 | list_del_init(subscr); |
269 | tipc_node_unlock(n); | 324 | tipc_node_write_unlock(n); |
270 | tipc_node_put(n); | 325 | tipc_node_put(n); |
271 | } | 326 | } |
272 | 327 | ||
@@ -293,9 +348,9 @@ int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) | |||
293 | conn->port = port; | 348 | conn->port = port; |
294 | conn->peer_port = peer_port; | 349 | conn->peer_port = peer_port; |
295 | 350 | ||
296 | tipc_node_lock(node); | 351 | tipc_node_write_lock(node); |
297 | list_add_tail(&conn->list, &node->conn_sks); | 352 | list_add_tail(&conn->list, &node->conn_sks); |
298 | tipc_node_unlock(node); | 353 | tipc_node_write_unlock(node); |
299 | exit: | 354 | exit: |
300 | tipc_node_put(node); | 355 | tipc_node_put(node); |
301 | return err; | 356 | return err; |
@@ -313,14 +368,14 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) | |||
313 | if (!node) | 368 | if (!node) |
314 | return; | 369 | return; |
315 | 370 | ||
316 | tipc_node_lock(node); | 371 | tipc_node_write_lock(node); |
317 | list_for_each_entry_safe(conn, safe, &node->conn_sks, list) { | 372 | list_for_each_entry_safe(conn, safe, &node->conn_sks, list) { |
318 | if (port != conn->port) | 373 | if (port != conn->port) |
319 | continue; | 374 | continue; |
320 | list_del(&conn->list); | 375 | list_del(&conn->list); |
321 | kfree(conn); | 376 | kfree(conn); |
322 | } | 377 | } |
323 | tipc_node_unlock(node); | 378 | tipc_node_write_unlock(node); |
324 | tipc_node_put(node); | 379 | tipc_node_put(node); |
325 | } | 380 | } |
326 | 381 | ||
@@ -337,7 +392,7 @@ static void tipc_node_timeout(unsigned long data) | |||
337 | __skb_queue_head_init(&xmitq); | 392 | __skb_queue_head_init(&xmitq); |
338 | 393 | ||
339 | for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) { | 394 | for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) { |
340 | tipc_node_lock(n); | 395 | tipc_node_read_lock(n); |
341 | le = &n->links[bearer_id]; | 396 | le = &n->links[bearer_id]; |
342 | spin_lock_bh(&le->lock); | 397 | spin_lock_bh(&le->lock); |
343 | if (le->link) { | 398 | if (le->link) { |
@@ -346,7 +401,7 @@ static void tipc_node_timeout(unsigned long data) | |||
346 | rc = tipc_link_timeout(le->link, &xmitq); | 401 | rc = tipc_link_timeout(le->link, &xmitq); |
347 | } | 402 | } |
348 | spin_unlock_bh(&le->lock); | 403 | spin_unlock_bh(&le->lock); |
349 | tipc_node_unlock(n); | 404 | tipc_node_read_unlock(n); |
350 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr); | 405 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr); |
351 | if (rc & TIPC_LINK_DOWN_EVT) | 406 | if (rc & TIPC_LINK_DOWN_EVT) |
352 | tipc_node_link_down(n, bearer_id, false); | 407 | tipc_node_link_down(n, bearer_id, false); |
@@ -425,9 +480,9 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, | |||
425 | static void tipc_node_link_up(struct tipc_node *n, int bearer_id, | 480 | static void tipc_node_link_up(struct tipc_node *n, int bearer_id, |
426 | struct sk_buff_head *xmitq) | 481 | struct sk_buff_head *xmitq) |
427 | { | 482 | { |
428 | tipc_node_lock(n); | 483 | tipc_node_write_lock(n); |
429 | __tipc_node_link_up(n, bearer_id, xmitq); | 484 | __tipc_node_link_up(n, bearer_id, xmitq); |
430 | tipc_node_unlock(n); | 485 | tipc_node_write_unlock(n); |
431 | } | 486 | } |
432 | 487 | ||
433 | /** | 488 | /** |
@@ -516,7 +571,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | |||
516 | 571 | ||
517 | __skb_queue_head_init(&xmitq); | 572 | __skb_queue_head_init(&xmitq); |
518 | 573 | ||
519 | tipc_node_lock(n); | 574 | tipc_node_write_lock(n); |
520 | if (!tipc_link_is_establishing(l)) { | 575 | if (!tipc_link_is_establishing(l)) { |
521 | __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr); | 576 | __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr); |
522 | if (delete) { | 577 | if (delete) { |
@@ -528,7 +583,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | |||
528 | /* Defuse pending tipc_node_link_up() */ | 583 | /* Defuse pending tipc_node_link_up() */ |
529 | tipc_link_fsm_evt(l, LINK_RESET_EVT); | 584 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
530 | } | 585 | } |
531 | tipc_node_unlock(n); | 586 | tipc_node_write_unlock(n); |
532 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); | 587 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); |
533 | tipc_sk_rcv(n->net, &le->inputq); | 588 | tipc_sk_rcv(n->net, &le->inputq); |
534 | } | 589 | } |
@@ -561,7 +616,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
561 | if (!n) | 616 | if (!n) |
562 | return; | 617 | return; |
563 | 618 | ||
564 | tipc_node_lock(n); | 619 | tipc_node_write_lock(n); |
565 | 620 | ||
566 | le = &n->links[b->identity]; | 621 | le = &n->links[b->identity]; |
567 | 622 | ||
@@ -656,7 +711,6 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
656 | if (n->state == NODE_FAILINGOVER) | 711 | if (n->state == NODE_FAILINGOVER) |
657 | tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); | 712 | tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); |
658 | le->link = l; | 713 | le->link = l; |
659 | spin_lock_init(&le->lock); | ||
660 | n->link_cnt++; | 714 | n->link_cnt++; |
661 | tipc_node_calculate_timer(n, l); | 715 | tipc_node_calculate_timer(n, l); |
662 | if (n->link_cnt == 1) | 716 | if (n->link_cnt == 1) |
@@ -665,7 +719,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
665 | } | 719 | } |
666 | memcpy(&le->maddr, maddr, sizeof(*maddr)); | 720 | memcpy(&le->maddr, maddr, sizeof(*maddr)); |
667 | exit: | 721 | exit: |
668 | tipc_node_unlock(n); | 722 | tipc_node_write_unlock(n); |
669 | if (reset && !tipc_link_is_reset(l)) | 723 | if (reset && !tipc_link_is_reset(l)) |
670 | tipc_node_link_down(n, b->identity, false); | 724 | tipc_node_link_down(n, b->identity, false); |
671 | tipc_node_put(n); | 725 | tipc_node_put(n); |
@@ -873,24 +927,6 @@ illegal_evt: | |||
873 | pr_err("Illegal node fsm evt %x in state %x\n", evt, state); | 927 | pr_err("Illegal node fsm evt %x in state %x\n", evt, state); |
874 | } | 928 | } |
875 | 929 | ||
876 | bool tipc_node_filter_pkt(struct tipc_node *n, struct tipc_msg *hdr) | ||
877 | { | ||
878 | int state = n->state; | ||
879 | |||
880 | if (likely(state == SELF_UP_PEER_UP)) | ||
881 | return true; | ||
882 | |||
883 | if (state == SELF_LEAVING_PEER_DOWN) | ||
884 | return false; | ||
885 | |||
886 | if (state == SELF_DOWN_PEER_LEAVING) { | ||
887 | if (msg_peer_node_is_up(hdr)) | ||
888 | return false; | ||
889 | } | ||
890 | |||
891 | return true; | ||
892 | } | ||
893 | |||
894 | static void node_lost_contact(struct tipc_node *n, | 930 | static void node_lost_contact(struct tipc_node *n, |
895 | struct sk_buff_head *inputq) | 931 | struct sk_buff_head *inputq) |
896 | { | 932 | { |
@@ -952,56 +988,18 @@ int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 addr, | |||
952 | if (bearer_id >= MAX_BEARERS) | 988 | if (bearer_id >= MAX_BEARERS) |
953 | goto exit; | 989 | goto exit; |
954 | 990 | ||
955 | tipc_node_lock(node); | 991 | tipc_node_read_lock(node); |
956 | link = node->links[bearer_id].link; | 992 | link = node->links[bearer_id].link; |
957 | if (link) { | 993 | if (link) { |
958 | strncpy(linkname, link->name, len); | 994 | strncpy(linkname, link->name, len); |
959 | err = 0; | 995 | err = 0; |
960 | } | 996 | } |
961 | exit: | 997 | exit: |
962 | tipc_node_unlock(node); | 998 | tipc_node_read_unlock(node); |
963 | tipc_node_put(node); | 999 | tipc_node_put(node); |
964 | return err; | 1000 | return err; |
965 | } | 1001 | } |
966 | 1002 | ||
967 | void tipc_node_unlock(struct tipc_node *node) | ||
968 | { | ||
969 | struct net *net = node->net; | ||
970 | u32 addr = 0; | ||
971 | u32 flags = node->action_flags; | ||
972 | u32 link_id = 0; | ||
973 | struct list_head *publ_list; | ||
974 | |||
975 | if (likely(!flags)) { | ||
976 | spin_unlock_bh(&node->lock); | ||
977 | return; | ||
978 | } | ||
979 | |||
980 | addr = node->addr; | ||
981 | link_id = node->link_id; | ||
982 | publ_list = &node->publ_list; | ||
983 | |||
984 | node->action_flags &= ~(TIPC_NOTIFY_NODE_DOWN | TIPC_NOTIFY_NODE_UP | | ||
985 | TIPC_NOTIFY_LINK_DOWN | TIPC_NOTIFY_LINK_UP); | ||
986 | |||
987 | spin_unlock_bh(&node->lock); | ||
988 | |||
989 | if (flags & TIPC_NOTIFY_NODE_DOWN) | ||
990 | tipc_publ_notify(net, publ_list, addr); | ||
991 | |||
992 | if (flags & TIPC_NOTIFY_NODE_UP) | ||
993 | tipc_named_node_up(net, addr); | ||
994 | |||
995 | if (flags & TIPC_NOTIFY_LINK_UP) | ||
996 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, | ||
997 | TIPC_NODE_SCOPE, link_id, addr); | ||
998 | |||
999 | if (flags & TIPC_NOTIFY_LINK_DOWN) | ||
1000 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, | ||
1001 | link_id, addr); | ||
1002 | |||
1003 | } | ||
1004 | |||
1005 | /* Caller should hold node lock for the passed node */ | 1003 | /* Caller should hold node lock for the passed node */ |
1006 | static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) | 1004 | static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) |
1007 | { | 1005 | { |
@@ -1048,40 +1046,38 @@ msg_full: | |||
1048 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, | 1046 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, |
1049 | u32 dnode, int selector) | 1047 | u32 dnode, int selector) |
1050 | { | 1048 | { |
1051 | struct tipc_link_entry *le; | 1049 | struct tipc_link_entry *le = NULL; |
1052 | struct tipc_node *n; | 1050 | struct tipc_node *n; |
1053 | struct sk_buff_head xmitq; | 1051 | struct sk_buff_head xmitq; |
1054 | struct tipc_media_addr *maddr = NULL; | ||
1055 | int bearer_id = -1; | 1052 | int bearer_id = -1; |
1056 | int rc = -EHOSTUNREACH; | 1053 | int rc = -EHOSTUNREACH; |
1057 | 1054 | ||
1058 | __skb_queue_head_init(&xmitq); | 1055 | __skb_queue_head_init(&xmitq); |
1059 | n = tipc_node_find(net, dnode); | 1056 | n = tipc_node_find(net, dnode); |
1060 | if (likely(n)) { | 1057 | if (likely(n)) { |
1061 | tipc_node_lock(n); | 1058 | tipc_node_read_lock(n); |
1062 | bearer_id = n->active_links[selector & 1]; | 1059 | bearer_id = n->active_links[selector & 1]; |
1063 | if (bearer_id >= 0) { | 1060 | if (bearer_id >= 0) { |
1064 | le = &n->links[bearer_id]; | 1061 | le = &n->links[bearer_id]; |
1065 | maddr = &le->maddr; | ||
1066 | spin_lock_bh(&le->lock); | 1062 | spin_lock_bh(&le->lock); |
1067 | if (likely(le->link)) | 1063 | rc = tipc_link_xmit(le->link, list, &xmitq); |
1068 | rc = tipc_link_xmit(le->link, list, &xmitq); | ||
1069 | spin_unlock_bh(&le->lock); | 1064 | spin_unlock_bh(&le->lock); |
1070 | } | 1065 | } |
1071 | tipc_node_unlock(n); | 1066 | tipc_node_read_unlock(n); |
1067 | if (likely(!skb_queue_empty(&xmitq))) { | ||
1068 | tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr); | ||
1069 | return 0; | ||
1070 | } | ||
1072 | if (unlikely(rc == -ENOBUFS)) | 1071 | if (unlikely(rc == -ENOBUFS)) |
1073 | tipc_node_link_down(n, bearer_id, false); | 1072 | tipc_node_link_down(n, bearer_id, false); |
1074 | tipc_node_put(n); | 1073 | tipc_node_put(n); |
1074 | return rc; | ||
1075 | } | 1075 | } |
1076 | if (likely(!skb_queue_empty(&xmitq))) { | 1076 | |
1077 | tipc_bearer_xmit(net, bearer_id, &xmitq, maddr); | 1077 | if (unlikely(!in_own_node(net, dnode))) |
1078 | return 0; | 1078 | return rc; |
1079 | } | 1079 | tipc_sk_rcv(net, list); |
1080 | if (likely(in_own_node(net, dnode))) { | 1080 | return 0; |
1081 | tipc_sk_rcv(net, list); | ||
1082 | return 0; | ||
1083 | } | ||
1084 | return rc; | ||
1085 | } | 1081 | } |
1086 | 1082 | ||
1087 | /* tipc_node_xmit_skb(): send single buffer to destination | 1083 | /* tipc_node_xmit_skb(): send single buffer to destination |
@@ -1171,9 +1167,9 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id | |||
1171 | 1167 | ||
1172 | /* Broadcast ACKs are sent on a unicast link */ | 1168 | /* Broadcast ACKs are sent on a unicast link */ |
1173 | if (rc & TIPC_LINK_SND_BC_ACK) { | 1169 | if (rc & TIPC_LINK_SND_BC_ACK) { |
1174 | tipc_node_lock(n); | 1170 | tipc_node_read_lock(n); |
1175 | tipc_link_build_ack_msg(le->link, &xmitq); | 1171 | tipc_link_build_ack_msg(le->link, &xmitq); |
1176 | tipc_node_unlock(n); | 1172 | tipc_node_read_unlock(n); |
1177 | } | 1173 | } |
1178 | 1174 | ||
1179 | if (!skb_queue_empty(&xmitq)) | 1175 | if (!skb_queue_empty(&xmitq)) |
@@ -1229,7 +1225,7 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
1229 | } | 1225 | } |
1230 | } | 1226 | } |
1231 | 1227 | ||
1232 | /* Update node accesibility if applicable */ | 1228 | /* Check and update node accesibility if applicable */ |
1233 | if (state == SELF_UP_PEER_COMING) { | 1229 | if (state == SELF_UP_PEER_COMING) { |
1234 | if (!tipc_link_is_up(l)) | 1230 | if (!tipc_link_is_up(l)) |
1235 | return true; | 1231 | return true; |
@@ -1245,6 +1241,9 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
1245 | return true; | 1241 | return true; |
1246 | } | 1242 | } |
1247 | 1243 | ||
1244 | if (state == SELF_LEAVING_PEER_DOWN) | ||
1245 | return false; | ||
1246 | |||
1248 | /* Ignore duplicate packets */ | 1247 | /* Ignore duplicate packets */ |
1249 | if ((usr != LINK_PROTOCOL) && less(oseqno, rcv_nxt)) | 1248 | if ((usr != LINK_PROTOCOL) && less(oseqno, rcv_nxt)) |
1250 | return true; | 1249 | return true; |
@@ -1361,21 +1360,29 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
1361 | else if (unlikely(n->bc_entry.link->acked != bc_ack)) | 1360 | else if (unlikely(n->bc_entry.link->acked != bc_ack)) |
1362 | tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack); | 1361 | tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack); |
1363 | 1362 | ||
1364 | tipc_node_lock(n); | 1363 | /* Receive packet directly if conditions permit */ |
1365 | 1364 | tipc_node_read_lock(n); | |
1366 | /* Is reception permitted at the moment ? */ | 1365 | if (likely((n->state == SELF_UP_PEER_UP) && (usr != TUNNEL_PROTOCOL))) { |
1367 | if (!tipc_node_filter_pkt(n, hdr)) | ||
1368 | goto unlock; | ||
1369 | |||
1370 | /* Check and if necessary update node state */ | ||
1371 | if (likely(tipc_node_check_state(n, skb, bearer_id, &xmitq))) { | ||
1372 | spin_lock_bh(&le->lock); | 1366 | spin_lock_bh(&le->lock); |
1373 | rc = tipc_link_rcv(le->link, skb, &xmitq); | 1367 | if (le->link) { |
1368 | rc = tipc_link_rcv(le->link, skb, &xmitq); | ||
1369 | skb = NULL; | ||
1370 | } | ||
1374 | spin_unlock_bh(&le->lock); | 1371 | spin_unlock_bh(&le->lock); |
1375 | skb = NULL; | ||
1376 | } | 1372 | } |
1377 | unlock: | 1373 | tipc_node_read_unlock(n); |
1378 | tipc_node_unlock(n); | 1374 | |
1375 | /* Check/update node state before receiving */ | ||
1376 | if (unlikely(skb)) { | ||
1377 | tipc_node_write_lock(n); | ||
1378 | if (tipc_node_check_state(n, skb, bearer_id, &xmitq)) { | ||
1379 | if (le->link) { | ||
1380 | rc = tipc_link_rcv(le->link, skb, &xmitq); | ||
1381 | skb = NULL; | ||
1382 | } | ||
1383 | } | ||
1384 | tipc_node_write_unlock(n); | ||
1385 | } | ||
1379 | 1386 | ||
1380 | if (unlikely(rc & TIPC_LINK_UP_EVT)) | 1387 | if (unlikely(rc & TIPC_LINK_UP_EVT)) |
1381 | tipc_node_link_up(n, bearer_id, &xmitq); | 1388 | tipc_node_link_up(n, bearer_id, &xmitq); |
@@ -1440,15 +1447,15 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1440 | continue; | 1447 | continue; |
1441 | } | 1448 | } |
1442 | 1449 | ||
1443 | tipc_node_lock(node); | 1450 | tipc_node_read_lock(node); |
1444 | err = __tipc_nl_add_node(&msg, node); | 1451 | err = __tipc_nl_add_node(&msg, node); |
1445 | if (err) { | 1452 | if (err) { |
1446 | last_addr = node->addr; | 1453 | last_addr = node->addr; |
1447 | tipc_node_unlock(node); | 1454 | tipc_node_read_unlock(node); |
1448 | goto out; | 1455 | goto out; |
1449 | } | 1456 | } |
1450 | 1457 | ||
1451 | tipc_node_unlock(node); | 1458 | tipc_node_read_unlock(node); |
1452 | } | 1459 | } |
1453 | done = 1; | 1460 | done = 1; |
1454 | out: | 1461 | out: |