diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 84 |
1 files changed, 81 insertions, 3 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index 558df25a7fc6..6a0680ba98a9 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -407,6 +407,44 @@ bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *b, | |||
407 | return true; | 407 | return true; |
408 | } | 408 | } |
409 | 409 | ||
410 | void tipc_node_delete_links(struct net *net, int bearer_id) | ||
411 | { | ||
412 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
413 | struct tipc_link *l; | ||
414 | struct tipc_node *n; | ||
415 | |||
416 | rcu_read_lock(); | ||
417 | list_for_each_entry_rcu(n, &tn->node_list, list) { | ||
418 | tipc_node_lock(n); | ||
419 | l = n->links[bearer_id].link; | ||
420 | if (l) { | ||
421 | tipc_link_reset(l); | ||
422 | n->links[bearer_id].link = NULL; | ||
423 | n->link_cnt--; | ||
424 | } | ||
425 | tipc_node_unlock(n); | ||
426 | kfree(l); | ||
427 | } | ||
428 | rcu_read_unlock(); | ||
429 | } | ||
430 | |||
431 | static void tipc_node_reset_links(struct tipc_node *n) | ||
432 | { | ||
433 | char addr_string[16]; | ||
434 | u32 i; | ||
435 | |||
436 | tipc_node_lock(n); | ||
437 | |||
438 | pr_warn("Resetting all links to %s\n", | ||
439 | tipc_addr_string_fill(addr_string, n->addr)); | ||
440 | |||
441 | for (i = 0; i < MAX_BEARERS; i++) { | ||
442 | if (n->links[i].link) | ||
443 | tipc_link_reset(n->links[i].link); | ||
444 | } | ||
445 | tipc_node_unlock(n); | ||
446 | } | ||
447 | |||
410 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 448 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) |
411 | { | 449 | { |
412 | n_ptr->links[l_ptr->bearer_id].link = l_ptr; | 450 | n_ptr->links[l_ptr->bearer_id].link = l_ptr; |
@@ -721,7 +759,7 @@ void tipc_node_unlock(struct tipc_node *node) | |||
721 | tipc_bclink_input(net); | 759 | tipc_bclink_input(net); |
722 | 760 | ||
723 | if (flags & TIPC_BCAST_RESET) | 761 | if (flags & TIPC_BCAST_RESET) |
724 | tipc_link_reset_all(node); | 762 | tipc_node_reset_links(node); |
725 | } | 763 | } |
726 | 764 | ||
727 | /* Caller should hold node lock for the passed node */ | 765 | /* Caller should hold node lock for the passed node */ |
@@ -836,6 +874,40 @@ int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode, | |||
836 | return 0; | 874 | return 0; |
837 | } | 875 | } |
838 | 876 | ||
877 | /* tipc_node_tnl_init(): handle a received TUNNEL_PROTOCOL packet, | ||
878 | * in order to control parallel link failover or synchronization | ||
879 | */ | ||
880 | static void tipc_node_tnl_init(struct tipc_node *n, int bearer_id, | ||
881 | struct sk_buff *skb) | ||
882 | { | ||
883 | struct tipc_link *tnl, *pl; | ||
884 | struct tipc_msg *hdr = buf_msg(skb); | ||
885 | u16 oseqno = msg_seqno(hdr); | ||
886 | int pb_id = msg_bearer_id(hdr); | ||
887 | |||
888 | if (pb_id >= MAX_BEARERS) | ||
889 | return; | ||
890 | |||
891 | tnl = n->links[bearer_id].link; | ||
892 | if (!tnl) | ||
893 | return; | ||
894 | |||
895 | /* Ignore if duplicate */ | ||
896 | if (less(oseqno, tnl->rcv_nxt)) | ||
897 | return; | ||
898 | |||
899 | pl = n->links[pb_id].link; | ||
900 | if (!pl) | ||
901 | return; | ||
902 | |||
903 | if (msg_type(hdr) == FAILOVER_MSG) { | ||
904 | if (tipc_link_is_up(pl)) { | ||
905 | tipc_link_reset(pl); | ||
906 | pl->exec_mode = TIPC_LINK_BLOCKED; | ||
907 | } | ||
908 | } | ||
909 | } | ||
910 | |||
839 | /** | 911 | /** |
840 | * tipc_rcv - process TIPC packets/messages arriving from off-node | 912 | * tipc_rcv - process TIPC packets/messages arriving from off-node |
841 | * @net: the applicable net namespace | 913 | * @net: the applicable net namespace |
@@ -854,6 +926,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
854 | struct tipc_media_addr *maddr; | 926 | struct tipc_media_addr *maddr; |
855 | int bearer_id = b->identity; | 927 | int bearer_id = b->identity; |
856 | int rc = 0; | 928 | int rc = 0; |
929 | int usr; | ||
857 | 930 | ||
858 | __skb_queue_head_init(&xmitq); | 931 | __skb_queue_head_init(&xmitq); |
859 | 932 | ||
@@ -863,8 +936,9 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
863 | 936 | ||
864 | /* Handle arrival of a non-unicast link packet */ | 937 | /* Handle arrival of a non-unicast link packet */ |
865 | hdr = buf_msg(skb); | 938 | hdr = buf_msg(skb); |
939 | usr = msg_user(hdr); | ||
866 | if (unlikely(msg_non_seq(hdr))) { | 940 | if (unlikely(msg_non_seq(hdr))) { |
867 | if (msg_user(hdr) == LINK_CONFIG) | 941 | if (usr == LINK_CONFIG) |
868 | tipc_disc_rcv(net, skb, b); | 942 | tipc_disc_rcv(net, skb, b); |
869 | else | 943 | else |
870 | tipc_bclink_rcv(net, skb); | 944 | tipc_bclink_rcv(net, skb); |
@@ -877,6 +951,10 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
877 | goto discard; | 951 | goto discard; |
878 | tipc_node_lock(n); | 952 | tipc_node_lock(n); |
879 | 953 | ||
954 | /* Prepare links for tunneled reception if applicable */ | ||
955 | if (unlikely(usr == TUNNEL_PROTOCOL)) | ||
956 | tipc_node_tnl_init(n, bearer_id, skb); | ||
957 | |||
880 | /* Locate link endpoint that should handle packet */ | 958 | /* Locate link endpoint that should handle packet */ |
881 | l = n->links[bearer_id].link; | 959 | l = n->links[bearer_id].link; |
882 | if (unlikely(!l)) | 960 | if (unlikely(!l)) |
@@ -887,7 +965,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
887 | if (!tipc_node_filter_skb(n, l, hdr)) | 965 | if (!tipc_node_filter_skb(n, l, hdr)) |
888 | goto unlock; | 966 | goto unlock; |
889 | 967 | ||
890 | if (unlikely(msg_user(hdr) == LINK_PROTOCOL)) | 968 | if (unlikely(usr == LINK_PROTOCOL)) |
891 | tipc_bclink_sync_state(n, hdr); | 969 | tipc_bclink_sync_state(n, hdr); |
892 | 970 | ||
893 | /* Release acked broadcast messages */ | 971 | /* Release acked broadcast messages */ |