aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/addr.c7
-rw-r--r--net/tipc/addr.h8
-rw-r--r--net/tipc/bcast.c41
-rw-r--r--net/tipc/bcast.h1
-rw-r--r--net/tipc/bearer.c20
-rw-r--r--net/tipc/bearer.h2
-rw-r--r--net/tipc/core.c4
-rw-r--r--net/tipc/core.h37
-rw-r--r--net/tipc/link.c311
-rw-r--r--net/tipc/link.h59
-rw-r--r--net/tipc/msg.c51
-rw-r--r--net/tipc/msg.h37
-rw-r--r--net/tipc/name_table.c34
-rw-r--r--net/tipc/net.c1
-rw-r--r--net/tipc/netlink_compat.c137
-rw-r--r--net/tipc/node.c3
-rw-r--r--net/tipc/node.h2
-rw-r--r--net/tipc/server.c6
-rw-r--r--net/tipc/socket.c10
-rw-r--r--net/tipc/subscr.c242
-rw-r--r--net/tipc/subscr.h18
21 files changed, 539 insertions, 492 deletions
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index ba7daa864d44..48fd3b5a73fb 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -38,13 +38,6 @@
38#include "addr.h" 38#include "addr.h"
39#include "core.h" 39#include "core.h"
40 40
41u32 tipc_own_addr(struct net *net)
42{
43 struct tipc_net *tn = net_generic(net, tipc_net_id);
44
45 return tn->own_addr;
46}
47
48/** 41/**
49 * in_own_cluster - test for cluster inclusion; <0.0.0> always matches 42 * in_own_cluster - test for cluster inclusion; <0.0.0> always matches
50 */ 43 */
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
index 7ba6d5c8ae40..93f7c983be33 100644
--- a/net/tipc/addr.h
+++ b/net/tipc/addr.h
@@ -41,10 +41,18 @@
41#include <linux/tipc.h> 41#include <linux/tipc.h>
42#include <net/net_namespace.h> 42#include <net/net_namespace.h>
43#include <net/netns/generic.h> 43#include <net/netns/generic.h>
44#include "core.h"
44 45
45#define TIPC_ZONE_MASK 0xff000000u 46#define TIPC_ZONE_MASK 0xff000000u
46#define TIPC_CLUSTER_MASK 0xfffff000u 47#define TIPC_CLUSTER_MASK 0xfffff000u
47 48
49static inline u32 tipc_own_addr(struct net *net)
50{
51 struct tipc_net *tn = net_generic(net, tipc_net_id);
52
53 return tn->own_addr;
54}
55
48static inline u32 tipc_zone_mask(u32 addr) 56static inline u32 tipc_zone_mask(u32 addr)
49{ 57{
50 return addr & TIPC_ZONE_MASK; 58 return addr & TIPC_ZONE_MASK;
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index c5cbdcb1f0b5..4906ca3c0f3a 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -115,19 +115,15 @@ static void bclink_set_last_sent(struct net *net)
115{ 115{
116 struct tipc_net *tn = net_generic(net, tipc_net_id); 116 struct tipc_net *tn = net_generic(net, tipc_net_id);
117 struct tipc_link *bcl = tn->bcl; 117 struct tipc_link *bcl = tn->bcl;
118 struct sk_buff *skb = skb_peek(&bcl->backlogq);
119 118
120 if (skb) 119 bcl->silent_intv_cnt = mod(bcl->snd_nxt - 1);
121 bcl->fsm_msg_cnt = mod(buf_seqno(skb) - 1);
122 else
123 bcl->fsm_msg_cnt = mod(bcl->next_out_no - 1);
124} 120}
125 121
126u32 tipc_bclink_get_last_sent(struct net *net) 122u32 tipc_bclink_get_last_sent(struct net *net)
127{ 123{
128 struct tipc_net *tn = net_generic(net, tipc_net_id); 124 struct tipc_net *tn = net_generic(net, tipc_net_id);
129 125
130 return tn->bcl->fsm_msg_cnt; 126 return tn->bcl->silent_intv_cnt;
131} 127}
132 128
133static void bclink_update_last_sent(struct tipc_node *node, u32 seqno) 129static void bclink_update_last_sent(struct tipc_node *node, u32 seqno)
@@ -212,16 +208,16 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked)
212 * or both sent and unsent messages (otherwise) 208 * or both sent and unsent messages (otherwise)
213 */ 209 */
214 if (tn->bclink->bcast_nodes.count) 210 if (tn->bclink->bcast_nodes.count)
215 acked = tn->bcl->fsm_msg_cnt; 211 acked = tn->bcl->silent_intv_cnt;
216 else 212 else
217 acked = tn->bcl->next_out_no; 213 acked = tn->bcl->snd_nxt;
218 } else { 214 } else {
219 /* 215 /*
220 * Bail out if specified sequence number does not correspond 216 * Bail out if specified sequence number does not correspond
221 * to a message that has been sent and not yet acknowledged 217 * to a message that has been sent and not yet acknowledged
222 */ 218 */
223 if (less(acked, buf_seqno(skb)) || 219 if (less(acked, buf_seqno(skb)) ||
224 less(tn->bcl->fsm_msg_cnt, acked) || 220 less(tn->bcl->silent_intv_cnt, acked) ||
225 less_eq(acked, n_ptr->bclink.acked)) 221 less_eq(acked, n_ptr->bclink.acked))
226 goto exit; 222 goto exit;
227 } 223 }
@@ -803,9 +799,9 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
803 goto attr_msg_full; 799 goto attr_msg_full;
804 if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name)) 800 if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name))
805 goto attr_msg_full; 801 goto attr_msg_full;
806 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->next_in_no)) 802 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt))
807 goto attr_msg_full; 803 goto attr_msg_full;
808 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->next_out_no)) 804 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt))
809 goto attr_msg_full; 805 goto attr_msg_full;
810 806
811 prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP); 807 prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
@@ -866,6 +862,27 @@ int tipc_bclink_set_queue_limits(struct net *net, u32 limit)
866 return 0; 862 return 0;
867} 863}
868 864
865int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[])
866{
867 int err;
868 u32 win;
869 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
870
871 if (!attrs[TIPC_NLA_LINK_PROP])
872 return -EINVAL;
873
874 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], props);
875 if (err)
876 return err;
877
878 if (!props[TIPC_NLA_PROP_WIN])
879 return -EOPNOTSUPP;
880
881 win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
882
883 return tipc_bclink_set_queue_limits(net, win);
884}
885
869int tipc_bclink_init(struct net *net) 886int tipc_bclink_init(struct net *net)
870{ 887{
871 struct tipc_net *tn = net_generic(net, tipc_net_id); 888 struct tipc_net *tn = net_generic(net, tipc_net_id);
@@ -893,7 +910,7 @@ int tipc_bclink_init(struct net *net)
893 __skb_queue_head_init(&bcl->backlogq); 910 __skb_queue_head_init(&bcl->backlogq);
894 __skb_queue_head_init(&bcl->deferdq); 911 __skb_queue_head_init(&bcl->deferdq);
895 skb_queue_head_init(&bcl->wakeupq); 912 skb_queue_head_init(&bcl->wakeupq);
896 bcl->next_out_no = 1; 913 bcl->snd_nxt = 1;
897 spin_lock_init(&bclink->node.lock); 914 spin_lock_init(&bclink->node.lock);
898 __skb_queue_head_init(&bclink->arrvq); 915 __skb_queue_head_init(&bclink->arrvq);
899 skb_queue_head_init(&bclink->inputq); 916 skb_queue_head_init(&bclink->inputq);
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 4bdc12277d33..3c290a48f720 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -131,6 +131,7 @@ uint tipc_bclink_get_mtu(void);
131int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list); 131int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list);
132void tipc_bclink_wakeup_users(struct net *net); 132void tipc_bclink_wakeup_users(struct net *net);
133int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg); 133int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg);
134int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]);
134void tipc_bclink_input(struct net *net); 135void tipc_bclink_input(struct net *net);
135 136
136#endif 137#endif
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 70e3dacbf84a..00bc0e620532 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -71,8 +71,7 @@ static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = {
71 [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } 71 [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED }
72}; 72};
73 73
74static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, 74static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr);
75 bool shutting_down);
76 75
77/** 76/**
78 * tipc_media_find - locates specified media object by name 77 * tipc_media_find - locates specified media object by name
@@ -324,7 +323,7 @@ restart:
324 323
325 res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr); 324 res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr);
326 if (res) { 325 if (res) {
327 bearer_disable(net, b_ptr, false); 326 bearer_disable(net, b_ptr);
328 pr_warn("Bearer <%s> rejected, discovery object creation failed\n", 327 pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
329 name); 328 name);
330 return -EINVAL; 329 return -EINVAL;
@@ -344,7 +343,7 @@ restart:
344static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) 343static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr)
345{ 344{
346 pr_info("Resetting bearer <%s>\n", b_ptr->name); 345 pr_info("Resetting bearer <%s>\n", b_ptr->name);
347 tipc_link_reset_list(net, b_ptr->identity); 346 tipc_link_delete_list(net, b_ptr->identity);
348 tipc_disc_reset(net, b_ptr); 347 tipc_disc_reset(net, b_ptr);
349 return 0; 348 return 0;
350} 349}
@@ -354,8 +353,7 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr)
354 * 353 *
355 * Note: This routine assumes caller holds RTNL lock. 354 * Note: This routine assumes caller holds RTNL lock.
356 */ 355 */
357static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, 356static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr)
358 bool shutting_down)
359{ 357{
360 struct tipc_net *tn = net_generic(net, tipc_net_id); 358 struct tipc_net *tn = net_generic(net, tipc_net_id);
361 u32 i; 359 u32 i;
@@ -363,7 +361,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr,
363 pr_info("Disabling bearer <%s>\n", b_ptr->name); 361 pr_info("Disabling bearer <%s>\n", b_ptr->name);
364 b_ptr->media->disable_media(b_ptr); 362 b_ptr->media->disable_media(b_ptr);
365 363
366 tipc_link_delete_list(net, b_ptr->identity, shutting_down); 364 tipc_link_delete_list(net, b_ptr->identity);
367 if (b_ptr->link_req) 365 if (b_ptr->link_req)
368 tipc_disc_delete(b_ptr->link_req); 366 tipc_disc_delete(b_ptr->link_req);
369 367
@@ -541,7 +539,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
541 break; 539 break;
542 case NETDEV_UNREGISTER: 540 case NETDEV_UNREGISTER:
543 case NETDEV_CHANGENAME: 541 case NETDEV_CHANGENAME:
544 bearer_disable(dev_net(dev), b_ptr, false); 542 bearer_disable(dev_net(dev), b_ptr);
545 break; 543 break;
546 } 544 }
547 return NOTIFY_OK; 545 return NOTIFY_OK;
@@ -583,7 +581,7 @@ void tipc_bearer_stop(struct net *net)
583 for (i = 0; i < MAX_BEARERS; i++) { 581 for (i = 0; i < MAX_BEARERS; i++) {
584 b_ptr = rtnl_dereference(tn->bearer_list[i]); 582 b_ptr = rtnl_dereference(tn->bearer_list[i]);
585 if (b_ptr) { 583 if (b_ptr) {
586 bearer_disable(net, b_ptr, true); 584 bearer_disable(net, b_ptr);
587 tn->bearer_list[i] = NULL; 585 tn->bearer_list[i] = NULL;
588 } 586 }
589 } 587 }
@@ -747,7 +745,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
747 return -EINVAL; 745 return -EINVAL;
748 } 746 }
749 747
750 bearer_disable(net, bearer, false); 748 bearer_disable(net, bearer);
751 rtnl_unlock(); 749 rtnl_unlock();
752 750
753 return 0; 751 return 0;
@@ -812,7 +810,7 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
812 char *name; 810 char *name;
813 struct tipc_bearer *b; 811 struct tipc_bearer *b;
814 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; 812 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
815 struct net *net = genl_info_net(info); 813 struct net *net = sock_net(skb->sk);
816 814
817 if (!info->attrs[TIPC_NLA_BEARER]) 815 if (!info->attrs[TIPC_NLA_BEARER])
818 return -EINVAL; 816 return -EINVAL;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 5cad243ee8fc..dc714d977768 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -38,9 +38,9 @@
38#define _TIPC_BEARER_H 38#define _TIPC_BEARER_H
39 39
40#include "netlink.h" 40#include "netlink.h"
41#include "core.h"
41#include <net/genetlink.h> 42#include <net/genetlink.h>
42 43
43#define MAX_BEARERS 2
44#define MAX_MEDIA 3 44#define MAX_MEDIA 3
45#define MAX_NODES 4096 45#define MAX_NODES 4096
46#define WSIZE 32 46#define WSIZE 32
diff --git a/net/tipc/core.c b/net/tipc/core.c
index be1c9fa60b09..005ba5eb0ea4 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -68,7 +68,7 @@ static int __net_init tipc_init_net(struct net *net)
68 if (err) 68 if (err)
69 goto out_nametbl; 69 goto out_nametbl;
70 70
71 err = tipc_subscr_start(net); 71 err = tipc_topsrv_start(net);
72 if (err) 72 if (err)
73 goto out_subscr; 73 goto out_subscr;
74 return 0; 74 return 0;
@@ -83,7 +83,7 @@ out_sk_rht:
83 83
84static void __net_exit tipc_exit_net(struct net *net) 84static void __net_exit tipc_exit_net(struct net *net)
85{ 85{
86 tipc_subscr_stop(net); 86 tipc_topsrv_stop(net);
87 tipc_net_stop(net); 87 tipc_net_stop(net);
88 tipc_nametbl_stop(net); 88 tipc_nametbl_stop(net);
89 tipc_sk_rht_destroy(net); 89 tipc_sk_rht_destroy(net);
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 3dc68c7a966d..0fcf133d5cb7 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -60,16 +60,19 @@
60#include <net/netns/generic.h> 60#include <net/netns/generic.h>
61#include <linux/rhashtable.h> 61#include <linux/rhashtable.h>
62 62
63#include "node.h" 63struct tipc_node;
64#include "bearer.h" 64struct tipc_bearer;
65#include "bcast.h" 65struct tipc_bcbearer;
66#include "netlink.h" 66struct tipc_bclink;
67#include "link.h" 67struct tipc_link;
68#include "node.h" 68struct tipc_name_table;
69#include "msg.h" 69struct tipc_server;
70 70
71#define TIPC_MOD_VER "2.0.0" 71#define TIPC_MOD_VER "2.0.0"
72 72
73#define NODE_HTABLE_SIZE 512
74#define MAX_BEARERS 3
75
73extern int tipc_net_id __read_mostly; 76extern int tipc_net_id __read_mostly;
74extern int sysctl_tipc_rmem[3] __read_mostly; 77extern int sysctl_tipc_rmem[3] __read_mostly;
75extern int sysctl_tipc_named_timeout __read_mostly; 78extern int sysctl_tipc_named_timeout __read_mostly;
@@ -106,6 +109,26 @@ struct tipc_net {
106 atomic_t subscription_count; 109 atomic_t subscription_count;
107}; 110};
108 111
112static inline u16 mod(u16 x)
113{
114 return x & 0xffffu;
115}
116
117static inline int less_eq(u16 left, u16 right)
118{
119 return mod(right - left) < 32768u;
120}
121
122static inline int more(u16 left, u16 right)
123{
124 return !less_eq(left, right);
125}
126
127static inline int less(u16 left, u16 right)
128{
129 return less_eq(left, right) && (mod(right) != mod(left));
130}
131
109#ifdef CONFIG_SYSCTL 132#ifdef CONFIG_SYSCTL
110int tipc_register_sysctl(void); 133int tipc_register_sysctl(void);
111void tipc_unregister_sysctl(void); 134void tipc_unregister_sysctl(void);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 43a515dc97b0..ca8b8e0f49b5 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -86,7 +86,7 @@ static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
86 */ 86 */
87#define STARTING_EVT 856384768 /* link processing trigger */ 87#define STARTING_EVT 856384768 /* link processing trigger */
88#define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */ 88#define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */
89#define TIMEOUT_EVT 560817u /* link timer expired */ 89#define SILENCE_EVT 560817u /* timer dicovered silence from peer */
90 90
91/* 91/*
92 * State value stored in 'failover_pkts' 92 * State value stored in 'failover_pkts'
@@ -106,6 +106,7 @@ static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf);
106static void tipc_link_input(struct tipc_link *l, struct sk_buff *skb); 106static void tipc_link_input(struct tipc_link *l, struct sk_buff *skb);
107static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb); 107static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb);
108static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb); 108static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb);
109static void link_set_timer(struct tipc_link *link, unsigned long time);
109/* 110/*
110 * Simple link routines 111 * Simple link routines
111 */ 112 */
@@ -197,11 +198,12 @@ static void link_timeout(unsigned long data)
197 } 198 }
198 199
199 /* do all other link processing performed on a periodic basis */ 200 /* do all other link processing performed on a periodic basis */
200 link_state_event(l_ptr, TIMEOUT_EVT); 201 if (l_ptr->silent_intv_cnt || tipc_bclink_acks_missing(l_ptr->owner))
201 202 link_state_event(l_ptr, SILENCE_EVT);
203 l_ptr->silent_intv_cnt++;
202 if (skb_queue_len(&l_ptr->backlogq)) 204 if (skb_queue_len(&l_ptr->backlogq))
203 tipc_link_push_packets(l_ptr); 205 tipc_link_push_packets(l_ptr);
204 206 link_set_timer(l_ptr, l_ptr->keepalive_intv);
205 tipc_node_unlock(l_ptr->owner); 207 tipc_node_unlock(l_ptr->owner);
206 tipc_link_put(l_ptr); 208 tipc_link_put(l_ptr);
207} 209}
@@ -233,8 +235,8 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
233 235
234 if (n_ptr->link_cnt >= MAX_BEARERS) { 236 if (n_ptr->link_cnt >= MAX_BEARERS) {
235 tipc_addr_string_fill(addr_string, n_ptr->addr); 237 tipc_addr_string_fill(addr_string, n_ptr->addr);
236 pr_err("Attempt to establish %uth link to %s. Max %u allowed.\n", 238 pr_err("Cannot establish %uth link to %s. Max %u allowed.\n",
237 n_ptr->link_cnt, addr_string, MAX_BEARERS); 239 n_ptr->link_cnt, addr_string, MAX_BEARERS);
238 return NULL; 240 return NULL;
239 } 241 }
240 242
@@ -261,7 +263,6 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
261 /* note: peer i/f name is updated by reset/activate message */ 263 /* note: peer i/f name is updated by reset/activate message */
262 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); 264 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
263 l_ptr->owner = n_ptr; 265 l_ptr->owner = n_ptr;
264 l_ptr->checkpoint = 1;
265 l_ptr->peer_session = INVALID_SESSION; 266 l_ptr->peer_session = INVALID_SESSION;
266 l_ptr->bearer_id = b_ptr->identity; 267 l_ptr->bearer_id = b_ptr->identity;
267 link_set_supervision_props(l_ptr, b_ptr->tolerance); 268 link_set_supervision_props(l_ptr, b_ptr->tolerance);
@@ -280,7 +281,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
280 l_ptr->mtu = l_ptr->advertised_mtu; 281 l_ptr->mtu = l_ptr->advertised_mtu;
281 l_ptr->priority = b_ptr->priority; 282 l_ptr->priority = b_ptr->priority;
282 tipc_link_set_queue_limits(l_ptr, b_ptr->window); 283 tipc_link_set_queue_limits(l_ptr, b_ptr->window);
283 l_ptr->next_out_no = 1; 284 l_ptr->snd_nxt = 1;
284 __skb_queue_head_init(&l_ptr->transmq); 285 __skb_queue_head_init(&l_ptr->transmq);
285 __skb_queue_head_init(&l_ptr->backlogq); 286 __skb_queue_head_init(&l_ptr->backlogq);
286 __skb_queue_head_init(&l_ptr->deferdq); 287 __skb_queue_head_init(&l_ptr->deferdq);
@@ -311,8 +312,7 @@ void tipc_link_delete(struct tipc_link *l)
311 tipc_link_put(l); 312 tipc_link_put(l);
312} 313}
313 314
314void tipc_link_delete_list(struct net *net, unsigned int bearer_id, 315void tipc_link_delete_list(struct net *net, unsigned int bearer_id)
315 bool shutting_down)
316{ 316{
317 struct tipc_net *tn = net_generic(net, tipc_net_id); 317 struct tipc_net *tn = net_generic(net, tipc_net_id);
318 struct tipc_link *link; 318 struct tipc_link *link;
@@ -451,9 +451,9 @@ void tipc_link_reset(struct tipc_link *l_ptr)
451 451
452 if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) { 452 if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) {
453 l_ptr->flags |= LINK_FAILINGOVER; 453 l_ptr->flags |= LINK_FAILINGOVER;
454 l_ptr->failover_checkpt = l_ptr->next_in_no; 454 l_ptr->failover_checkpt = l_ptr->rcv_nxt;
455 pl->failover_pkts = FIRST_FAILOVER; 455 pl->failover_pkts = FIRST_FAILOVER;
456 pl->failover_checkpt = l_ptr->next_in_no; 456 pl->failover_checkpt = l_ptr->rcv_nxt;
457 pl->failover_skb = l_ptr->reasm_buf; 457 pl->failover_skb = l_ptr->reasm_buf;
458 } else { 458 } else {
459 kfree_skb(l_ptr->reasm_buf); 459 kfree_skb(l_ptr->reasm_buf);
@@ -469,36 +469,19 @@ void tipc_link_reset(struct tipc_link *l_ptr)
469 tipc_link_purge_backlog(l_ptr); 469 tipc_link_purge_backlog(l_ptr);
470 l_ptr->reasm_buf = NULL; 470 l_ptr->reasm_buf = NULL;
471 l_ptr->rcv_unacked = 0; 471 l_ptr->rcv_unacked = 0;
472 l_ptr->checkpoint = 1; 472 l_ptr->snd_nxt = 1;
473 l_ptr->next_out_no = 1; 473 l_ptr->silent_intv_cnt = 0;
474 l_ptr->fsm_msg_cnt = 0;
475 l_ptr->stale_count = 0; 474 l_ptr->stale_count = 0;
476 link_reset_statistics(l_ptr); 475 link_reset_statistics(l_ptr);
477} 476}
478 477
479void tipc_link_reset_list(struct net *net, unsigned int bearer_id)
480{
481 struct tipc_net *tn = net_generic(net, tipc_net_id);
482 struct tipc_link *l_ptr;
483 struct tipc_node *n_ptr;
484
485 rcu_read_lock();
486 list_for_each_entry_rcu(n_ptr, &tn->node_list, list) {
487 tipc_node_lock(n_ptr);
488 l_ptr = n_ptr->links[bearer_id];
489 if (l_ptr)
490 tipc_link_reset(l_ptr);
491 tipc_node_unlock(n_ptr);
492 }
493 rcu_read_unlock();
494}
495
496static void link_activate(struct tipc_link *link) 478static void link_activate(struct tipc_link *link)
497{ 479{
498 struct tipc_node *node = link->owner; 480 struct tipc_node *node = link->owner;
499 481
500 link->next_in_no = 1; 482 link->rcv_nxt = 1;
501 link->stats.recv_info = 1; 483 link->stats.recv_info = 1;
484 link->silent_intv_cnt = 0;
502 tipc_node_link_up(node, link); 485 tipc_node_link_up(node, link);
503 tipc_bearer_add_dest(node->net, link->bearer_id, link->addr); 486 tipc_bearer_add_dest(node->net, link->bearer_id, link->addr);
504} 487}
@@ -511,7 +494,7 @@ static void link_activate(struct tipc_link *link)
511static void link_state_event(struct tipc_link *l_ptr, unsigned int event) 494static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
512{ 495{
513 struct tipc_link *other; 496 struct tipc_link *other;
514 unsigned long cont_intv = l_ptr->cont_intv; 497 unsigned long timer_intv = l_ptr->keepalive_intv;
515 498
516 if (l_ptr->flags & LINK_STOPPED) 499 if (l_ptr->flags & LINK_STOPPED)
517 return; 500 return;
@@ -519,45 +502,33 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
519 if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT)) 502 if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT))
520 return; /* Not yet. */ 503 return; /* Not yet. */
521 504
522 if (l_ptr->flags & LINK_FAILINGOVER) { 505 if (l_ptr->flags & LINK_FAILINGOVER)
523 if (event == TIMEOUT_EVT)
524 link_set_timer(l_ptr, cont_intv);
525 return; 506 return;
526 }
527 507
528 switch (l_ptr->state) { 508 switch (l_ptr->state) {
529 case WORKING_WORKING: 509 case WORKING_WORKING:
530 switch (event) { 510 switch (event) {
531 case TRAFFIC_MSG_EVT: 511 case TRAFFIC_MSG_EVT:
532 case ACTIVATE_MSG: 512 case ACTIVATE_MSG:
513 l_ptr->silent_intv_cnt = 0;
533 break; 514 break;
534 case TIMEOUT_EVT: 515 case SILENCE_EVT:
535 if (l_ptr->next_in_no != l_ptr->checkpoint) { 516 if (!l_ptr->silent_intv_cnt) {
536 l_ptr->checkpoint = l_ptr->next_in_no; 517 if (tipc_bclink_acks_missing(l_ptr->owner))
537 if (tipc_bclink_acks_missing(l_ptr->owner)) {
538 tipc_link_proto_xmit(l_ptr, STATE_MSG, 518 tipc_link_proto_xmit(l_ptr, STATE_MSG,
539 0, 0, 0, 0); 519 0, 0, 0, 0);
540 l_ptr->fsm_msg_cnt++;
541 }
542 link_set_timer(l_ptr, cont_intv);
543 break; 520 break;
544 } 521 }
545 l_ptr->state = WORKING_UNKNOWN; 522 l_ptr->state = WORKING_UNKNOWN;
546 l_ptr->fsm_msg_cnt = 0;
547 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); 523 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0);
548 l_ptr->fsm_msg_cnt++;
549 link_set_timer(l_ptr, cont_intv / 4);
550 break; 524 break;
551 case RESET_MSG: 525 case RESET_MSG:
552 pr_debug("%s<%s>, requested by peer\n", 526 pr_debug("%s<%s>, requested by peer\n",
553 link_rst_msg, l_ptr->name); 527 link_rst_msg, l_ptr->name);
554 tipc_link_reset(l_ptr); 528 tipc_link_reset(l_ptr);
555 l_ptr->state = RESET_RESET; 529 l_ptr->state = RESET_RESET;
556 l_ptr->fsm_msg_cnt = 0;
557 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, 530 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
558 0, 0, 0, 0); 531 0, 0, 0, 0);
559 l_ptr->fsm_msg_cnt++;
560 link_set_timer(l_ptr, cont_intv);
561 break; 532 break;
562 default: 533 default:
563 pr_debug("%s%u in WW state\n", link_unk_evt, event); 534 pr_debug("%s%u in WW state\n", link_unk_evt, event);
@@ -568,46 +539,33 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
568 case TRAFFIC_MSG_EVT: 539 case TRAFFIC_MSG_EVT:
569 case ACTIVATE_MSG: 540 case ACTIVATE_MSG:
570 l_ptr->state = WORKING_WORKING; 541 l_ptr->state = WORKING_WORKING;
571 l_ptr->fsm_msg_cnt = 0; 542 l_ptr->silent_intv_cnt = 0;
572 link_set_timer(l_ptr, cont_intv);
573 break; 543 break;
574 case RESET_MSG: 544 case RESET_MSG:
575 pr_debug("%s<%s>, requested by peer while probing\n", 545 pr_debug("%s<%s>, requested by peer while probing\n",
576 link_rst_msg, l_ptr->name); 546 link_rst_msg, l_ptr->name);
577 tipc_link_reset(l_ptr); 547 tipc_link_reset(l_ptr);
578 l_ptr->state = RESET_RESET; 548 l_ptr->state = RESET_RESET;
579 l_ptr->fsm_msg_cnt = 0;
580 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, 549 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
581 0, 0, 0, 0); 550 0, 0, 0, 0);
582 l_ptr->fsm_msg_cnt++;
583 link_set_timer(l_ptr, cont_intv);
584 break; 551 break;
585 case TIMEOUT_EVT: 552 case SILENCE_EVT:
586 if (l_ptr->next_in_no != l_ptr->checkpoint) { 553 if (!l_ptr->silent_intv_cnt) {
587 l_ptr->state = WORKING_WORKING; 554 l_ptr->state = WORKING_WORKING;
588 l_ptr->fsm_msg_cnt = 0; 555 if (tipc_bclink_acks_missing(l_ptr->owner))
589 l_ptr->checkpoint = l_ptr->next_in_no;
590 if (tipc_bclink_acks_missing(l_ptr->owner)) {
591 tipc_link_proto_xmit(l_ptr, STATE_MSG, 556 tipc_link_proto_xmit(l_ptr, STATE_MSG,
592 0, 0, 0, 0); 557 0, 0, 0, 0);
593 l_ptr->fsm_msg_cnt++; 558 } else if (l_ptr->silent_intv_cnt <
594 } 559 l_ptr->abort_limit) {
595 link_set_timer(l_ptr, cont_intv);
596 } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) {
597 tipc_link_proto_xmit(l_ptr, STATE_MSG, 560 tipc_link_proto_xmit(l_ptr, STATE_MSG,
598 1, 0, 0, 0); 561 1, 0, 0, 0);
599 l_ptr->fsm_msg_cnt++;
600 link_set_timer(l_ptr, cont_intv / 4);
601 } else { /* Link has failed */ 562 } else { /* Link has failed */
602 pr_debug("%s<%s>, peer not responding\n", 563 pr_debug("%s<%s>, peer not responding\n",
603 link_rst_msg, l_ptr->name); 564 link_rst_msg, l_ptr->name);
604 tipc_link_reset(l_ptr); 565 tipc_link_reset(l_ptr);
605 l_ptr->state = RESET_UNKNOWN; 566 l_ptr->state = RESET_UNKNOWN;
606 l_ptr->fsm_msg_cnt = 0;
607 tipc_link_proto_xmit(l_ptr, RESET_MSG, 567 tipc_link_proto_xmit(l_ptr, RESET_MSG,
608 0, 0, 0, 0); 568 0, 0, 0, 0);
609 l_ptr->fsm_msg_cnt++;
610 link_set_timer(l_ptr, cont_intv);
611 } 569 }
612 break; 570 break;
613 default: 571 default:
@@ -623,31 +581,22 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
623 if (other && link_working_unknown(other)) 581 if (other && link_working_unknown(other))
624 break; 582 break;
625 l_ptr->state = WORKING_WORKING; 583 l_ptr->state = WORKING_WORKING;
626 l_ptr->fsm_msg_cnt = 0;
627 link_activate(l_ptr); 584 link_activate(l_ptr);
628 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); 585 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0);
629 l_ptr->fsm_msg_cnt++;
630 if (l_ptr->owner->working_links == 1) 586 if (l_ptr->owner->working_links == 1)
631 tipc_link_sync_xmit(l_ptr); 587 tipc_link_sync_xmit(l_ptr);
632 link_set_timer(l_ptr, cont_intv);
633 break; 588 break;
634 case RESET_MSG: 589 case RESET_MSG:
635 l_ptr->state = RESET_RESET; 590 l_ptr->state = RESET_RESET;
636 l_ptr->fsm_msg_cnt = 0;
637 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, 591 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
638 1, 0, 0, 0); 592 1, 0, 0, 0);
639 l_ptr->fsm_msg_cnt++;
640 link_set_timer(l_ptr, cont_intv);
641 break; 593 break;
642 case STARTING_EVT: 594 case STARTING_EVT:
643 l_ptr->flags |= LINK_STARTED; 595 l_ptr->flags |= LINK_STARTED;
644 l_ptr->fsm_msg_cnt++; 596 link_set_timer(l_ptr, timer_intv);
645 link_set_timer(l_ptr, cont_intv);
646 break; 597 break;
647 case TIMEOUT_EVT: 598 case SILENCE_EVT:
648 tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0); 599 tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0);
649 l_ptr->fsm_msg_cnt++;
650 link_set_timer(l_ptr, cont_intv);
651 break; 600 break;
652 default: 601 default:
653 pr_err("%s%u in RU state\n", link_unk_evt, event); 602 pr_err("%s%u in RU state\n", link_unk_evt, event);
@@ -661,21 +610,16 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
661 if (other && link_working_unknown(other)) 610 if (other && link_working_unknown(other))
662 break; 611 break;
663 l_ptr->state = WORKING_WORKING; 612 l_ptr->state = WORKING_WORKING;
664 l_ptr->fsm_msg_cnt = 0;
665 link_activate(l_ptr); 613 link_activate(l_ptr);
666 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0); 614 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0);
667 l_ptr->fsm_msg_cnt++;
668 if (l_ptr->owner->working_links == 1) 615 if (l_ptr->owner->working_links == 1)
669 tipc_link_sync_xmit(l_ptr); 616 tipc_link_sync_xmit(l_ptr);
670 link_set_timer(l_ptr, cont_intv);
671 break; 617 break;
672 case RESET_MSG: 618 case RESET_MSG:
673 break; 619 break;
674 case TIMEOUT_EVT: 620 case SILENCE_EVT:
675 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, 621 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
676 0, 0, 0, 0); 622 0, 0, 0, 0);
677 l_ptr->fsm_msg_cnt++;
678 link_set_timer(l_ptr, cont_intv);
679 break; 623 break;
680 default: 624 default:
681 pr_err("%s%u in RR state\n", link_unk_evt, event); 625 pr_err("%s%u in RR state\n", link_unk_evt, event);
@@ -701,53 +645,58 @@ int __tipc_link_xmit(struct net *net, struct tipc_link *link,
701{ 645{
702 struct tipc_msg *msg = buf_msg(skb_peek(list)); 646 struct tipc_msg *msg = buf_msg(skb_peek(list));
703 unsigned int maxwin = link->window; 647 unsigned int maxwin = link->window;
704 unsigned int imp = msg_importance(msg); 648 unsigned int i, imp = msg_importance(msg);
705 uint mtu = link->mtu; 649 uint mtu = link->mtu;
706 uint ack = mod(link->next_in_no - 1); 650 u16 ack = mod(link->rcv_nxt - 1);
707 uint seqno = link->next_out_no; 651 u16 seqno = link->snd_nxt;
708 uint bc_last_in = link->owner->bclink.last_in; 652 u16 bc_last_in = link->owner->bclink.last_in;
709 struct tipc_media_addr *addr = &link->media_addr; 653 struct tipc_media_addr *addr = &link->media_addr;
710 struct sk_buff_head *transmq = &link->transmq; 654 struct sk_buff_head *transmq = &link->transmq;
711 struct sk_buff_head *backlogq = &link->backlogq; 655 struct sk_buff_head *backlogq = &link->backlogq;
712 struct sk_buff *skb, *tmp; 656 struct sk_buff *skb, *bskb;
713
714 /* Match backlog limit against msg importance: */
715 if (unlikely(link->backlog[imp].len >= link->backlog[imp].limit))
716 return link_schedule_user(link, list);
717 657
658 /* Match msg importance against this and all higher backlog limits: */
659 for (i = imp; i <= TIPC_SYSTEM_IMPORTANCE; i++) {
660 if (unlikely(link->backlog[i].len >= link->backlog[i].limit))
661 return link_schedule_user(link, list);
662 }
718 if (unlikely(msg_size(msg) > mtu)) { 663 if (unlikely(msg_size(msg) > mtu)) {
719 __skb_queue_purge(list); 664 __skb_queue_purge(list);
720 return -EMSGSIZE; 665 return -EMSGSIZE;
721 } 666 }
722 /* Prepare each packet for sending, and add to relevant queue: */ 667 /* Prepare each packet for sending, and add to relevant queue: */
723 skb_queue_walk_safe(list, skb, tmp) { 668 while (skb_queue_len(list)) {
724 __skb_unlink(skb, list); 669 skb = skb_peek(list);
725 msg = buf_msg(skb); 670 msg = buf_msg(skb);
726 msg_set_seqno(msg, seqno); 671 msg_set_seqno(msg, seqno);
727 msg_set_ack(msg, ack); 672 msg_set_ack(msg, ack);
728 msg_set_bcast_ack(msg, bc_last_in); 673 msg_set_bcast_ack(msg, bc_last_in);
729 674
730 if (likely(skb_queue_len(transmq) < maxwin)) { 675 if (likely(skb_queue_len(transmq) < maxwin)) {
676 __skb_dequeue(list);
731 __skb_queue_tail(transmq, skb); 677 __skb_queue_tail(transmq, skb);
732 tipc_bearer_send(net, link->bearer_id, skb, addr); 678 tipc_bearer_send(net, link->bearer_id, skb, addr);
733 link->rcv_unacked = 0; 679 link->rcv_unacked = 0;
734 seqno++; 680 seqno++;
735 continue; 681 continue;
736 } 682 }
737 if (tipc_msg_bundle(skb_peek_tail(backlogq), skb, mtu)) { 683 if (tipc_msg_bundle(skb_peek_tail(backlogq), msg, mtu)) {
684 kfree_skb(__skb_dequeue(list));
738 link->stats.sent_bundled++; 685 link->stats.sent_bundled++;
739 continue; 686 continue;
740 } 687 }
741 if (tipc_msg_make_bundle(&skb, mtu, link->addr)) { 688 if (tipc_msg_make_bundle(&bskb, msg, mtu, link->addr)) {
689 kfree_skb(__skb_dequeue(list));
690 __skb_queue_tail(backlogq, bskb);
691 link->backlog[msg_importance(buf_msg(bskb))].len++;
742 link->stats.sent_bundled++; 692 link->stats.sent_bundled++;
743 link->stats.sent_bundles++; 693 link->stats.sent_bundles++;
744 imp = msg_importance(buf_msg(skb)); 694 continue;
745 } 695 }
746 __skb_queue_tail(backlogq, skb); 696 link->backlog[imp].len += skb_queue_len(list);
747 link->backlog[imp].len++; 697 skb_queue_splice_tail_init(list, backlogq);
748 seqno++;
749 } 698 }
750 link->next_out_no = seqno; 699 link->snd_nxt = seqno;
751 return 0; 700 return 0;
752} 701}
753 702
@@ -877,7 +826,8 @@ void tipc_link_push_packets(struct tipc_link *link)
877{ 826{
878 struct sk_buff *skb; 827 struct sk_buff *skb;
879 struct tipc_msg *msg; 828 struct tipc_msg *msg;
880 unsigned int ack = mod(link->next_in_no - 1); 829 u16 seqno = link->snd_nxt;
830 u16 ack = mod(link->rcv_nxt - 1);
881 831
882 while (skb_queue_len(&link->transmq) < link->window) { 832 while (skb_queue_len(&link->transmq) < link->window) {
883 skb = __skb_dequeue(&link->backlogq); 833 skb = __skb_dequeue(&link->backlogq);
@@ -886,12 +836,15 @@ void tipc_link_push_packets(struct tipc_link *link)
886 msg = buf_msg(skb); 836 msg = buf_msg(skb);
887 link->backlog[msg_importance(msg)].len--; 837 link->backlog[msg_importance(msg)].len--;
888 msg_set_ack(msg, ack); 838 msg_set_ack(msg, ack);
839 msg_set_seqno(msg, seqno);
840 seqno = mod(seqno + 1);
889 msg_set_bcast_ack(msg, link->owner->bclink.last_in); 841 msg_set_bcast_ack(msg, link->owner->bclink.last_in);
890 link->rcv_unacked = 0; 842 link->rcv_unacked = 0;
891 __skb_queue_tail(&link->transmq, skb); 843 __skb_queue_tail(&link->transmq, skb);
892 tipc_bearer_send(link->owner->net, link->bearer_id, 844 tipc_bearer_send(link->owner->net, link->bearer_id,
893 skb, &link->media_addr); 845 skb, &link->media_addr);
894 } 846 }
847 link->snd_nxt = seqno;
895} 848}
896 849
897void tipc_link_reset_all(struct tipc_node *node) 850void tipc_link_reset_all(struct tipc_node *node)
@@ -964,13 +917,13 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *skb,
964 msg = buf_msg(skb); 917 msg = buf_msg(skb);
965 918
966 /* Detect repeated retransmit failures */ 919 /* Detect repeated retransmit failures */
967 if (l_ptr->last_retransmitted == msg_seqno(msg)) { 920 if (l_ptr->last_retransm == msg_seqno(msg)) {
968 if (++l_ptr->stale_count > 100) { 921 if (++l_ptr->stale_count > 100) {
969 link_retransmit_failure(l_ptr, skb); 922 link_retransmit_failure(l_ptr, skb);
970 return; 923 return;
971 } 924 }
972 } else { 925 } else {
973 l_ptr->last_retransmitted = msg_seqno(msg); 926 l_ptr->last_retransm = msg_seqno(msg);
974 l_ptr->stale_count = 1; 927 l_ptr->stale_count = 1;
975 } 928 }
976 929
@@ -978,7 +931,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *skb,
978 if (!retransmits) 931 if (!retransmits)
979 break; 932 break;
980 msg = buf_msg(skb); 933 msg = buf_msg(skb);
981 msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); 934 msg_set_ack(msg, mod(l_ptr->rcv_nxt - 1));
982 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 935 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
983 tipc_bearer_send(l_ptr->owner->net, l_ptr->bearer_id, skb, 936 tipc_bearer_send(l_ptr->owner->net, l_ptr->bearer_id, skb,
984 &l_ptr->media_addr); 937 &l_ptr->media_addr);
@@ -1001,11 +954,11 @@ static bool link_synch(struct tipc_link *l)
1001 goto synched; 954 goto synched;
1002 955
1003 /* Was last pre-synch packet added to input queue ? */ 956 /* Was last pre-synch packet added to input queue ? */
1004 if (less_eq(pl->next_in_no, l->synch_point)) 957 if (less_eq(pl->rcv_nxt, l->synch_point))
1005 return false; 958 return false;
1006 959
1007 /* Is it still in the input queue ? */ 960 /* Is it still in the input queue ? */
1008 post_synch = mod(pl->next_in_no - l->synch_point) - 1; 961 post_synch = mod(pl->rcv_nxt - l->synch_point) - 1;
1009 if (skb_queue_len(&pl->inputq) > post_synch) 962 if (skb_queue_len(&pl->inputq) > post_synch)
1010 return false; 963 return false;
1011synched: 964synched:
@@ -1016,13 +969,13 @@ synched:
1016static void link_retrieve_defq(struct tipc_link *link, 969static void link_retrieve_defq(struct tipc_link *link,
1017 struct sk_buff_head *list) 970 struct sk_buff_head *list)
1018{ 971{
1019 u32 seq_no; 972 u16 seq_no;
1020 973
1021 if (skb_queue_empty(&link->deferdq)) 974 if (skb_queue_empty(&link->deferdq))
1022 return; 975 return;
1023 976
1024 seq_no = buf_seqno(skb_peek(&link->deferdq)); 977 seq_no = buf_seqno(skb_peek(&link->deferdq));
1025 if (seq_no == mod(link->next_in_no)) 978 if (seq_no == link->rcv_nxt)
1026 skb_queue_splice_tail_init(&link->deferdq, list); 979 skb_queue_splice_tail_init(&link->deferdq, list);
1027} 980}
1028 981
@@ -1043,8 +996,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1043 struct tipc_link *l_ptr; 996 struct tipc_link *l_ptr;
1044 struct sk_buff *skb1, *tmp; 997 struct sk_buff *skb1, *tmp;
1045 struct tipc_msg *msg; 998 struct tipc_msg *msg;
1046 u32 seq_no; 999 u16 seq_no;
1047 u32 ackd; 1000 u16 ackd;
1048 u32 released; 1001 u32 released;
1049 1002
1050 skb2list(skb, &head); 1003 skb2list(skb, &head);
@@ -1137,18 +1090,20 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1137 } 1090 }
1138 1091
1139 /* Link is now in state WORKING_WORKING */ 1092 /* Link is now in state WORKING_WORKING */
1140 if (unlikely(seq_no != mod(l_ptr->next_in_no))) { 1093 if (unlikely(seq_no != l_ptr->rcv_nxt)) {
1141 link_handle_out_of_seq_msg(l_ptr, skb); 1094 link_handle_out_of_seq_msg(l_ptr, skb);
1142 link_retrieve_defq(l_ptr, &head); 1095 link_retrieve_defq(l_ptr, &head);
1143 skb = NULL; 1096 skb = NULL;
1144 goto unlock; 1097 goto unlock;
1145 } 1098 }
1099 l_ptr->silent_intv_cnt = 0;
1100
1146 /* Synchronize with parallel link if applicable */ 1101 /* Synchronize with parallel link if applicable */
1147 if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) { 1102 if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) {
1148 if (!link_synch(l_ptr)) 1103 if (!link_synch(l_ptr))
1149 goto unlock; 1104 goto unlock;
1150 } 1105 }
1151 l_ptr->next_in_no++; 1106 l_ptr->rcv_nxt++;
1152 if (unlikely(!skb_queue_empty(&l_ptr->deferdq))) 1107 if (unlikely(!skb_queue_empty(&l_ptr->deferdq)))
1153 link_retrieve_defq(l_ptr, &head); 1108 link_retrieve_defq(l_ptr, &head);
1154 if (unlikely(++l_ptr->rcv_unacked >= TIPC_MIN_LINK_WIN)) { 1109 if (unlikely(++l_ptr->rcv_unacked >= TIPC_MIN_LINK_WIN)) {
@@ -1268,7 +1223,7 @@ static void tipc_link_input(struct tipc_link *link, struct sk_buff *skb)
1268u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb) 1223u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb)
1269{ 1224{
1270 struct sk_buff *skb1; 1225 struct sk_buff *skb1;
1271 u32 seq_no = buf_seqno(skb); 1226 u16 seq_no = buf_seqno(skb);
1272 1227
1273 /* Empty queue ? */ 1228 /* Empty queue ? */
1274 if (skb_queue_empty(list)) { 1229 if (skb_queue_empty(list)) {
@@ -1284,7 +1239,7 @@ u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb)
1284 1239
1285 /* Locate insertion point in queue, then insert; discard if duplicate */ 1240 /* Locate insertion point in queue, then insert; discard if duplicate */
1286 skb_queue_walk(list, skb1) { 1241 skb_queue_walk(list, skb1) {
1287 u32 curr_seqno = buf_seqno(skb1); 1242 u16 curr_seqno = buf_seqno(skb1);
1288 1243
1289 if (seq_no == curr_seqno) { 1244 if (seq_no == curr_seqno) {
1290 kfree_skb(skb); 1245 kfree_skb(skb);
@@ -1312,14 +1267,14 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
1312 return; 1267 return;
1313 } 1268 }
1314 1269
1315 /* Record OOS packet arrival (force mismatch on next timeout) */ 1270 /* Record OOS packet arrival */
1316 l_ptr->checkpoint--; 1271 l_ptr->silent_intv_cnt = 0;
1317 1272
1318 /* 1273 /*
1319 * Discard packet if a duplicate; otherwise add it to deferred queue 1274 * Discard packet if a duplicate; otherwise add it to deferred queue
1320 * and notify peer of gap as per protocol specification 1275 * and notify peer of gap as per protocol specification
1321 */ 1276 */
1322 if (less(seq_no, mod(l_ptr->next_in_no))) { 1277 if (less(seq_no, l_ptr->rcv_nxt)) {
1323 l_ptr->stats.duplicates++; 1278 l_ptr->stats.duplicates++;
1324 kfree_skb(buf); 1279 kfree_skb(buf);
1325 return; 1280 return;
@@ -1344,6 +1299,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
1344 struct tipc_msg *msg = l_ptr->pmsg; 1299 struct tipc_msg *msg = l_ptr->pmsg;
1345 u32 msg_size = sizeof(l_ptr->proto_msg); 1300 u32 msg_size = sizeof(l_ptr->proto_msg);
1346 int r_flag; 1301 int r_flag;
1302 u16 last_rcv;
1347 1303
1348 /* Don't send protocol message during link failover */ 1304 /* Don't send protocol message during link failover */
1349 if (l_ptr->flags & LINK_FAILINGOVER) 1305 if (l_ptr->flags & LINK_FAILINGOVER)
@@ -1360,16 +1316,14 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
1360 msg_set_last_bcast(msg, tipc_bclink_get_last_sent(l_ptr->owner->net)); 1316 msg_set_last_bcast(msg, tipc_bclink_get_last_sent(l_ptr->owner->net));
1361 1317
1362 if (msg_typ == STATE_MSG) { 1318 if (msg_typ == STATE_MSG) {
1363 u32 next_sent = mod(l_ptr->next_out_no); 1319 u16 next_sent = l_ptr->snd_nxt;
1364 1320
1365 if (!tipc_link_is_up(l_ptr)) 1321 if (!tipc_link_is_up(l_ptr))
1366 return; 1322 return;
1367 if (skb_queue_len(&l_ptr->backlogq))
1368 next_sent = buf_seqno(skb_peek(&l_ptr->backlogq));
1369 msg_set_next_sent(msg, next_sent); 1323 msg_set_next_sent(msg, next_sent);
1370 if (!skb_queue_empty(&l_ptr->deferdq)) { 1324 if (!skb_queue_empty(&l_ptr->deferdq)) {
1371 u32 rec = buf_seqno(skb_peek(&l_ptr->deferdq)); 1325 last_rcv = buf_seqno(skb_peek(&l_ptr->deferdq));
1372 gap = mod(rec - mod(l_ptr->next_in_no)); 1326 gap = mod(last_rcv - l_ptr->rcv_nxt);
1373 } 1327 }
1374 msg_set_seq_gap(msg, gap); 1328 msg_set_seq_gap(msg, gap);
1375 if (gap) 1329 if (gap)
@@ -1377,7 +1331,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
1377 msg_set_link_tolerance(msg, tolerance); 1331 msg_set_link_tolerance(msg, tolerance);
1378 msg_set_linkprio(msg, priority); 1332 msg_set_linkprio(msg, priority);
1379 msg_set_max_pkt(msg, l_ptr->mtu); 1333 msg_set_max_pkt(msg, l_ptr->mtu);
1380 msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); 1334 msg_set_ack(msg, mod(l_ptr->rcv_nxt - 1));
1381 msg_set_probe(msg, probe_msg != 0); 1335 msg_set_probe(msg, probe_msg != 0);
1382 if (probe_msg) 1336 if (probe_msg)
1383 l_ptr->stats.sent_probes++; 1337 l_ptr->stats.sent_probes++;
@@ -1397,7 +1351,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
1397 msg_set_linkprio(msg, l_ptr->priority); 1351 msg_set_linkprio(msg, l_ptr->priority);
1398 msg_set_size(msg, msg_size); 1352 msg_set_size(msg, msg_size);
1399 1353
1400 msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2))); 1354 msg_set_seqno(msg, mod(l_ptr->snd_nxt + (0xffff / 2)));
1401 1355
1402 buf = tipc_buf_acquire(msg_size); 1356 buf = tipc_buf_acquire(msg_size);
1403 if (!buf) 1357 if (!buf)
@@ -1496,17 +1450,15 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
1496 } 1450 }
1497 1451
1498 /* Record reception; force mismatch at next timeout: */ 1452 /* Record reception; force mismatch at next timeout: */
1499 l_ptr->checkpoint--; 1453 l_ptr->silent_intv_cnt = 0;
1500 1454
1501 link_state_event(l_ptr, TRAFFIC_MSG_EVT); 1455 link_state_event(l_ptr, TRAFFIC_MSG_EVT);
1502 l_ptr->stats.recv_states++; 1456 l_ptr->stats.recv_states++;
1503 if (link_reset_unknown(l_ptr)) 1457 if (link_reset_unknown(l_ptr))
1504 break; 1458 break;
1505 1459
1506 if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) { 1460 if (less_eq(l_ptr->rcv_nxt, msg_next_sent(msg)))
1507 rec_gap = mod(msg_next_sent(msg) - 1461 rec_gap = mod(msg_next_sent(msg) - l_ptr->rcv_nxt);
1508 mod(l_ptr->next_in_no));
1509 }
1510 1462
1511 if (msg_probe(msg)) 1463 if (msg_probe(msg))
1512 l_ptr->stats.recv_probes++; 1464 l_ptr->stats.recv_probes++;
@@ -1580,6 +1532,11 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr)
1580 1532
1581 tipc_msg_init(link_own_addr(l_ptr), &tunnel_hdr, TUNNEL_PROTOCOL, 1533 tipc_msg_init(link_own_addr(l_ptr), &tunnel_hdr, TUNNEL_PROTOCOL,
1582 FAILOVER_MSG, INT_H_SIZE, l_ptr->addr); 1534 FAILOVER_MSG, INT_H_SIZE, l_ptr->addr);
1535
1536 skb_queue_walk(&l_ptr->backlogq, skb) {
1537 msg_set_seqno(buf_msg(skb), l_ptr->snd_nxt);
1538 l_ptr->snd_nxt = mod(l_ptr->snd_nxt + 1);
1539 }
1583 skb_queue_splice_tail_init(&l_ptr->backlogq, &l_ptr->transmq); 1540 skb_queue_splice_tail_init(&l_ptr->backlogq, &l_ptr->transmq);
1584 tipc_link_purge_backlog(l_ptr); 1541 tipc_link_purge_backlog(l_ptr);
1585 msgcount = skb_queue_len(&l_ptr->transmq); 1542 msgcount = skb_queue_len(&l_ptr->transmq);
@@ -1640,6 +1597,7 @@ void tipc_link_dup_queue_xmit(struct tipc_link *link,
1640 struct tipc_msg tnl_hdr; 1597 struct tipc_msg tnl_hdr;
1641 struct sk_buff_head *queue = &link->transmq; 1598 struct sk_buff_head *queue = &link->transmq;
1642 int mcnt; 1599 int mcnt;
1600 u16 seqno;
1643 1601
1644 tipc_msg_init(link_own_addr(link), &tnl_hdr, TUNNEL_PROTOCOL, 1602 tipc_msg_init(link_own_addr(link), &tnl_hdr, TUNNEL_PROTOCOL,
1645 SYNCH_MSG, INT_H_SIZE, link->addr); 1603 SYNCH_MSG, INT_H_SIZE, link->addr);
@@ -1653,7 +1611,7 @@ tunnel_queue:
1653 struct tipc_msg *msg = buf_msg(skb); 1611 struct tipc_msg *msg = buf_msg(skb);
1654 u32 len = msg_size(msg); 1612 u32 len = msg_size(msg);
1655 1613
1656 msg_set_ack(msg, mod(link->next_in_no - 1)); 1614 msg_set_ack(msg, mod(link->rcv_nxt - 1));
1657 msg_set_bcast_ack(msg, link->owner->bclink.last_in); 1615 msg_set_bcast_ack(msg, link->owner->bclink.last_in);
1658 msg_set_size(&tnl_hdr, len + INT_H_SIZE); 1616 msg_set_size(&tnl_hdr, len + INT_H_SIZE);
1659 outskb = tipc_buf_acquire(len + INT_H_SIZE); 1617 outskb = tipc_buf_acquire(len + INT_H_SIZE);
@@ -1671,6 +1629,11 @@ tunnel_queue:
1671 } 1629 }
1672 if (queue == &link->backlogq) 1630 if (queue == &link->backlogq)
1673 return; 1631 return;
1632 seqno = link->snd_nxt;
1633 skb_queue_walk(&link->backlogq, skb) {
1634 msg_set_seqno(buf_msg(skb), seqno);
1635 seqno = mod(seqno + 1);
1636 }
1674 queue = &link->backlogq; 1637 queue = &link->backlogq;
1675 goto tunnel_queue; 1638 goto tunnel_queue;
1676} 1639}
@@ -1742,8 +1705,8 @@ static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tol)
1742 return; 1705 return;
1743 1706
1744 l_ptr->tolerance = tol; 1707 l_ptr->tolerance = tol;
1745 l_ptr->cont_intv = msecs_to_jiffies(intv); 1708 l_ptr->keepalive_intv = msecs_to_jiffies(intv);
1746 l_ptr->abort_limit = tol / (jiffies_to_msecs(l_ptr->cont_intv) / 4); 1709 l_ptr->abort_limit = tol / (jiffies_to_msecs(l_ptr->keepalive_intv));
1747} 1710}
1748 1711
1749void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) 1712void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
@@ -1803,8 +1766,8 @@ static struct tipc_node *tipc_link_find_owner(struct net *net,
1803static void link_reset_statistics(struct tipc_link *l_ptr) 1766static void link_reset_statistics(struct tipc_link *l_ptr)
1804{ 1767{
1805 memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); 1768 memset(&l_ptr->stats, 0, sizeof(l_ptr->stats));
1806 l_ptr->stats.sent_info = l_ptr->next_out_no; 1769 l_ptr->stats.sent_info = l_ptr->snd_nxt;
1807 l_ptr->stats.recv_info = l_ptr->next_in_no; 1770 l_ptr->stats.recv_info = l_ptr->rcv_nxt;
1808} 1771}
1809 1772
1810static void link_print(struct tipc_link *l_ptr, const char *str) 1773static void link_print(struct tipc_link *l_ptr, const char *str)
@@ -1893,6 +1856,9 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info)
1893 1856
1894 name = nla_data(attrs[TIPC_NLA_LINK_NAME]); 1857 name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
1895 1858
1859 if (strcmp(name, tipc_bclink_name) == 0)
1860 return tipc_nl_bc_link_set(net, attrs);
1861
1896 node = tipc_link_find_owner(net, name, &bearer_id); 1862 node = tipc_link_find_owner(net, name, &bearer_id);
1897 if (!node) 1863 if (!node)
1898 return -EINVAL; 1864 return -EINVAL;
@@ -2034,9 +2000,9 @@ static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
2034 goto attr_msg_full; 2000 goto attr_msg_full;
2035 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->mtu)) 2001 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->mtu))
2036 goto attr_msg_full; 2002 goto attr_msg_full;
2037 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->next_in_no)) 2003 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->rcv_nxt))
2038 goto attr_msg_full; 2004 goto attr_msg_full;
2039 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->next_out_no)) 2005 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->snd_nxt))
2040 goto attr_msg_full; 2006 goto attr_msg_full;
2041 2007
2042 if (tipc_link_is_up(link)) 2008 if (tipc_link_is_up(link))
@@ -2175,50 +2141,53 @@ out:
2175int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) 2141int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info)
2176{ 2142{
2177 struct net *net = genl_info_net(info); 2143 struct net *net = genl_info_net(info);
2178 struct sk_buff *ans_skb;
2179 struct tipc_nl_msg msg; 2144 struct tipc_nl_msg msg;
2180 struct tipc_link *link;
2181 struct tipc_node *node;
2182 char *name; 2145 char *name;
2183 int bearer_id;
2184 int err; 2146 int err;
2185 2147
2148 msg.portid = info->snd_portid;
2149 msg.seq = info->snd_seq;
2150
2186 if (!info->attrs[TIPC_NLA_LINK_NAME]) 2151 if (!info->attrs[TIPC_NLA_LINK_NAME])
2187 return -EINVAL; 2152 return -EINVAL;
2188
2189 name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); 2153 name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]);
2190 node = tipc_link_find_owner(net, name, &bearer_id);
2191 if (!node)
2192 return -EINVAL;
2193 2154
2194 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 2155 msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2195 if (!ans_skb) 2156 if (!msg.skb)
2196 return -ENOMEM; 2157 return -ENOMEM;
2197 2158
2198 msg.skb = ans_skb; 2159 if (strcmp(name, tipc_bclink_name) == 0) {
2199 msg.portid = info->snd_portid; 2160 err = tipc_nl_add_bc_link(net, &msg);
2200 msg.seq = info->snd_seq; 2161 if (err) {
2201 2162 nlmsg_free(msg.skb);
2202 tipc_node_lock(node); 2163 return err;
2203 link = node->links[bearer_id]; 2164 }
2204 if (!link) { 2165 } else {
2205 err = -EINVAL; 2166 int bearer_id;
2206 goto err_out; 2167 struct tipc_node *node;
2207 } 2168 struct tipc_link *link;
2208
2209 err = __tipc_nl_add_link(net, &msg, link, 0);
2210 if (err)
2211 goto err_out;
2212 2169
2213 tipc_node_unlock(node); 2170 node = tipc_link_find_owner(net, name, &bearer_id);
2171 if (!node)
2172 return -EINVAL;
2214 2173
2215 return genlmsg_reply(ans_skb, info); 2174 tipc_node_lock(node);
2175 link = node->links[bearer_id];
2176 if (!link) {
2177 tipc_node_unlock(node);
2178 nlmsg_free(msg.skb);
2179 return -EINVAL;
2180 }
2216 2181
2217err_out: 2182 err = __tipc_nl_add_link(net, &msg, link, 0);
2218 tipc_node_unlock(node); 2183 tipc_node_unlock(node);
2219 nlmsg_free(ans_skb); 2184 if (err) {
2185 nlmsg_free(msg.skb);
2186 return err;
2187 }
2188 }
2220 2189
2221 return err; 2190 return genlmsg_reply(msg.skb, info);
2222} 2191}
2223 2192
2224int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) 2193int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info)
diff --git a/net/tipc/link.h b/net/tipc/link.h
index b5b4e3554d4e..0c02c973e985 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -107,30 +107,29 @@ struct tipc_stats {
107 * @owner: pointer to peer node 107 * @owner: pointer to peer node
108 * @refcnt: reference counter for permanent references (owner node & timer) 108 * @refcnt: reference counter for permanent references (owner node & timer)
109 * @flags: execution state flags for link endpoint instance 109 * @flags: execution state flags for link endpoint instance
110 * @checkpoint: reference point for triggering link continuity checking
111 * @peer_session: link session # being used by peer end of link 110 * @peer_session: link session # being used by peer end of link
112 * @peer_bearer_id: bearer id used by link's peer endpoint 111 * @peer_bearer_id: bearer id used by link's peer endpoint
113 * @bearer_id: local bearer id used by link 112 * @bearer_id: local bearer id used by link
114 * @tolerance: minimum link continuity loss needed to reset link [in ms] 113 * @tolerance: minimum link continuity loss needed to reset link [in ms]
115 * @cont_intv: link continuity testing interval 114 * @keepalive_intv: link keepalive timer interval
116 * @abort_limit: # of unacknowledged continuity probes needed to reset link 115 * @abort_limit: # of unacknowledged continuity probes needed to reset link
117 * @state: current state of link FSM 116 * @state: current state of link FSM
118 * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state 117 * @silent_intv_cnt: # of timer intervals without any reception from peer
119 * @proto_msg: template for control messages generated by link 118 * @proto_msg: template for control messages generated by link
120 * @pmsg: convenience pointer to "proto_msg" field 119 * @pmsg: convenience pointer to "proto_msg" field
121 * @priority: current link priority 120 * @priority: current link priority
122 * @net_plane: current link network plane ('A' through 'H') 121 * @net_plane: current link network plane ('A' through 'H')
123 * @backlog_limit: backlog queue congestion thresholds (indexed by importance) 122 * @backlog_limit: backlog queue congestion thresholds (indexed by importance)
124 * @exp_msg_count: # of tunnelled messages expected during link changeover 123 * @exp_msg_count: # of tunnelled messages expected during link changeover
125 * @reset_checkpoint: seq # of last acknowledged message at time of link reset 124 * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset
126 * @mtu: current maximum packet size for this link 125 * @mtu: current maximum packet size for this link
127 * @advertised_mtu: advertised own mtu when link is being established 126 * @advertised_mtu: advertised own mtu when link is being established
128 * @transmitq: queue for sent, non-acked messages 127 * @transmitq: queue for sent, non-acked messages
129 * @backlogq: queue for messages waiting to be sent 128 * @backlogq: queue for messages waiting to be sent
130 * @next_out_no: next sequence number to use for outbound messages 129 * @snt_nxt: next sequence number to use for outbound messages
131 * @last_retransmitted: sequence number of most recently retransmitted message 130 * @last_retransmitted: sequence number of most recently retransmitted message
132 * @stale_count: # of identical retransmit requests made by peer 131 * @stale_count: # of identical retransmit requests made by peer
133 * @next_in_no: next sequence number to expect for inbound messages 132 * @rcv_nxt: next sequence number to expect for inbound messages
134 * @deferred_queue: deferred queue saved OOS b'cast message received from node 133 * @deferred_queue: deferred queue saved OOS b'cast message received from node
135 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer 134 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
136 * @inputq: buffer queue for messages to be delivered upwards 135 * @inputq: buffer queue for messages to be delivered upwards
@@ -151,15 +150,14 @@ struct tipc_link {
151 150
152 /* Management and link supervision data */ 151 /* Management and link supervision data */
153 unsigned int flags; 152 unsigned int flags;
154 u32 checkpoint;
155 u32 peer_session; 153 u32 peer_session;
156 u32 peer_bearer_id; 154 u32 peer_bearer_id;
157 u32 bearer_id; 155 u32 bearer_id;
158 u32 tolerance; 156 u32 tolerance;
159 unsigned long cont_intv; 157 unsigned long keepalive_intv;
160 u32 abort_limit; 158 u32 abort_limit;
161 int state; 159 int state;
162 u32 fsm_msg_cnt; 160 u32 silent_intv_cnt;
163 struct { 161 struct {
164 unchar hdr[INT_H_SIZE]; 162 unchar hdr[INT_H_SIZE];
165 unchar body[TIPC_MAX_IF_NAME]; 163 unchar body[TIPC_MAX_IF_NAME];
@@ -185,13 +183,13 @@ struct tipc_link {
185 u16 len; 183 u16 len;
186 u16 limit; 184 u16 limit;
187 } backlog[5]; 185 } backlog[5];
188 u32 next_out_no; 186 u16 snd_nxt;
187 u16 last_retransm;
189 u32 window; 188 u32 window;
190 u32 last_retransmitted;
191 u32 stale_count; 189 u32 stale_count;
192 190
193 /* Reception */ 191 /* Reception */
194 u32 next_in_no; 192 u16 rcv_nxt;
195 u32 rcv_unacked; 193 u32 rcv_unacked;
196 struct sk_buff_head deferdq; 194 struct sk_buff_head deferdq;
197 struct sk_buff_head inputq; 195 struct sk_buff_head inputq;
@@ -213,8 +211,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
213 struct tipc_bearer *b_ptr, 211 struct tipc_bearer *b_ptr,
214 const struct tipc_media_addr *media_addr); 212 const struct tipc_media_addr *media_addr);
215void tipc_link_delete(struct tipc_link *link); 213void tipc_link_delete(struct tipc_link *link);
216void tipc_link_delete_list(struct net *net, unsigned int bearer_id, 214void tipc_link_delete_list(struct net *net, unsigned int bearer_id);
217 bool shutting_down);
218void tipc_link_failover_send_queue(struct tipc_link *l_ptr); 215void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
219void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct tipc_link *dest); 216void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct tipc_link *dest);
220void tipc_link_reset_fragments(struct tipc_link *l_ptr); 217void tipc_link_reset_fragments(struct tipc_link *l_ptr);
@@ -223,7 +220,6 @@ int tipc_link_is_active(struct tipc_link *l_ptr);
223void tipc_link_purge_queues(struct tipc_link *l_ptr); 220void tipc_link_purge_queues(struct tipc_link *l_ptr);
224void tipc_link_reset_all(struct tipc_node *node); 221void tipc_link_reset_all(struct tipc_node *node);
225void tipc_link_reset(struct tipc_link *l_ptr); 222void tipc_link_reset(struct tipc_link *l_ptr);
226void tipc_link_reset_list(struct net *net, unsigned int bearer_id);
227int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, 223int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest,
228 u32 selector); 224 u32 selector);
229int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dest, 225int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dest,
@@ -247,39 +243,6 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info);
247int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); 243int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
248void link_prepare_wakeup(struct tipc_link *l); 244void link_prepare_wakeup(struct tipc_link *l);
249 245
250/*
251 * Link sequence number manipulation routines (uses modulo 2**16 arithmetic)
252 */
253static inline u32 buf_seqno(struct sk_buff *buf)
254{
255 return msg_seqno(buf_msg(buf));
256}
257
258static inline u32 mod(u32 x)
259{
260 return x & 0xffffu;
261}
262
263static inline int less_eq(u32 left, u32 right)
264{
265 return mod(right - left) < 32768u;
266}
267
268static inline int more(u32 left, u32 right)
269{
270 return !less_eq(left, right);
271}
272
273static inline int less(u32 left, u32 right)
274{
275 return less_eq(left, right) && (mod(right) != mod(left));
276}
277
278static inline u32 lesser(u32 left, u32 right)
279{
280 return less_eq(left, right) ? left : right;
281}
282
283static inline u32 link_own_addr(struct tipc_link *l) 246static inline u32 link_own_addr(struct tipc_link *l)
284{ 247{
285 return msg_prevnode(l->pmsg); 248 return msg_prevnode(l->pmsg);
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index c3e96e815418..08b4cc7d496d 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -331,16 +331,15 @@ error:
331 331
332/** 332/**
333 * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one 333 * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one
334 * @bskb: the buffer to append to ("bundle") 334 * @skb: the buffer to append to ("bundle")
335 * @skb: buffer to be appended 335 * @msg: message to be appended
336 * @mtu: max allowable size for the bundle buffer 336 * @mtu: max allowable size for the bundle buffer
337 * Consumes buffer if successful 337 * Consumes buffer if successful
338 * Returns true if bundling could be performed, otherwise false 338 * Returns true if bundling could be performed, otherwise false
339 */ 339 */
340bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu) 340bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu)
341{ 341{
342 struct tipc_msg *bmsg; 342 struct tipc_msg *bmsg;
343 struct tipc_msg *msg = buf_msg(skb);
344 unsigned int bsz; 343 unsigned int bsz;
345 unsigned int msz = msg_size(msg); 344 unsigned int msz = msg_size(msg);
346 u32 start, pad; 345 u32 start, pad;
@@ -348,9 +347,9 @@ bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu)
348 347
349 if (likely(msg_user(msg) == MSG_FRAGMENTER)) 348 if (likely(msg_user(msg) == MSG_FRAGMENTER))
350 return false; 349 return false;
351 if (!bskb) 350 if (!skb)
352 return false; 351 return false;
353 bmsg = buf_msg(bskb); 352 bmsg = buf_msg(skb);
354 bsz = msg_size(bmsg); 353 bsz = msg_size(bmsg);
355 start = align(bsz); 354 start = align(bsz);
356 pad = start - bsz; 355 pad = start - bsz;
@@ -359,18 +358,20 @@ bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu)
359 return false; 358 return false;
360 if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) 359 if (unlikely(msg_user(msg) == BCAST_PROTOCOL))
361 return false; 360 return false;
362 if (likely(msg_user(bmsg) != MSG_BUNDLER)) 361 if (unlikely(msg_user(bmsg) != MSG_BUNDLER))
363 return false; 362 return false;
364 if (unlikely(skb_tailroom(bskb) < (pad + msz))) 363 if (unlikely(skb_tailroom(skb) < (pad + msz)))
365 return false; 364 return false;
366 if (unlikely(max < (start + msz))) 365 if (unlikely(max < (start + msz)))
367 return false; 366 return false;
367 if ((msg_importance(msg) < TIPC_SYSTEM_IMPORTANCE) &&
368 (msg_importance(bmsg) == TIPC_SYSTEM_IMPORTANCE))
369 return false;
368 370
369 skb_put(bskb, pad + msz); 371 skb_put(skb, pad + msz);
370 skb_copy_to_linear_data_offset(bskb, start, skb->data, msz); 372 skb_copy_to_linear_data_offset(skb, start, msg, msz);
371 msg_set_size(bmsg, start + msz); 373 msg_set_size(bmsg, start + msz);
372 msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1); 374 msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1);
373 kfree_skb(skb);
374 return true; 375 return true;
375} 376}
376 377
@@ -416,18 +417,18 @@ none:
416 417
417/** 418/**
418 * tipc_msg_make_bundle(): Create bundle buf and append message to its tail 419 * tipc_msg_make_bundle(): Create bundle buf and append message to its tail
419 * @list: the buffer chain 420 * @list: the buffer chain, where head is the buffer to replace/append
420 * @skb: buffer to be appended and replaced 421 * @skb: buffer to be created, appended to and returned in case of success
422 * @msg: message to be appended
421 * @mtu: max allowable size for the bundle buffer, inclusive header 423 * @mtu: max allowable size for the bundle buffer, inclusive header
422 * @dnode: destination node for message. (Not always present in header) 424 * @dnode: destination node for message. (Not always present in header)
423 * Replaces buffer if successful
424 * Returns true if success, otherwise false 425 * Returns true if success, otherwise false
425 */ 426 */
426bool tipc_msg_make_bundle(struct sk_buff **skb, u32 mtu, u32 dnode) 427bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
428 u32 mtu, u32 dnode)
427{ 429{
428 struct sk_buff *bskb; 430 struct sk_buff *_skb;
429 struct tipc_msg *bmsg; 431 struct tipc_msg *bmsg;
430 struct tipc_msg *msg = buf_msg(*skb);
431 u32 msz = msg_size(msg); 432 u32 msz = msg_size(msg);
432 u32 max = mtu - INT_H_SIZE; 433 u32 max = mtu - INT_H_SIZE;
433 434
@@ -440,19 +441,23 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, u32 mtu, u32 dnode)
440 if (msz > (max / 2)) 441 if (msz > (max / 2))
441 return false; 442 return false;
442 443
443 bskb = tipc_buf_acquire(max); 444 _skb = tipc_buf_acquire(max);
444 if (!bskb) 445 if (!_skb)
445 return false; 446 return false;
446 447
447 skb_trim(bskb, INT_H_SIZE); 448 skb_trim(_skb, INT_H_SIZE);
448 bmsg = buf_msg(bskb); 449 bmsg = buf_msg(_skb);
449 tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0, 450 tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0,
450 INT_H_SIZE, dnode); 451 INT_H_SIZE, dnode);
452 if (msg_isdata(msg))
453 msg_set_importance(bmsg, TIPC_CRITICAL_IMPORTANCE);
454 else
455 msg_set_importance(bmsg, TIPC_SYSTEM_IMPORTANCE);
451 msg_set_seqno(bmsg, msg_seqno(msg)); 456 msg_set_seqno(bmsg, msg_seqno(msg));
452 msg_set_ack(bmsg, msg_ack(msg)); 457 msg_set_ack(bmsg, msg_ack(msg));
453 msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); 458 msg_set_bcast_ack(bmsg, msg_bcast_ack(msg));
454 tipc_msg_bundle(bskb, *skb, mtu); 459 tipc_msg_bundle(_skb, msg, mtu);
455 *skb = bskb; 460 *skb = _skb;
456 return true; 461 return true;
457} 462}
458 463
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index e1d3595e2ee9..19c45fb66238 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -313,12 +313,12 @@ static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
313 msg_set_bits(m, 1, 19, 0x3, n); 313 msg_set_bits(m, 1, 19, 0x3, n);
314} 314}
315 315
316static inline u32 msg_bcast_ack(struct tipc_msg *m) 316static inline u16 msg_bcast_ack(struct tipc_msg *m)
317{ 317{
318 return msg_bits(m, 1, 0, 0xffff); 318 return msg_bits(m, 1, 0, 0xffff);
319} 319}
320 320
321static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) 321static inline void msg_set_bcast_ack(struct tipc_msg *m, u16 n)
322{ 322{
323 msg_set_bits(m, 1, 0, 0xffff, n); 323 msg_set_bits(m, 1, 0, 0xffff, n);
324} 324}
@@ -327,22 +327,22 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n)
327/* 327/*
328 * Word 2 328 * Word 2
329 */ 329 */
330static inline u32 msg_ack(struct tipc_msg *m) 330static inline u16 msg_ack(struct tipc_msg *m)
331{ 331{
332 return msg_bits(m, 2, 16, 0xffff); 332 return msg_bits(m, 2, 16, 0xffff);
333} 333}
334 334
335static inline void msg_set_ack(struct tipc_msg *m, u32 n) 335static inline void msg_set_ack(struct tipc_msg *m, u16 n)
336{ 336{
337 msg_set_bits(m, 2, 16, 0xffff, n); 337 msg_set_bits(m, 2, 16, 0xffff, n);
338} 338}
339 339
340static inline u32 msg_seqno(struct tipc_msg *m) 340static inline u16 msg_seqno(struct tipc_msg *m)
341{ 341{
342 return msg_bits(m, 2, 0, 0xffff); 342 return msg_bits(m, 2, 0, 0xffff);
343} 343}
344 344
345static inline void msg_set_seqno(struct tipc_msg *m, u32 n) 345static inline void msg_set_seqno(struct tipc_msg *m, u16 n)
346{ 346{
347 msg_set_bits(m, 2, 0, 0xffff, n); 347 msg_set_bits(m, 2, 0, 0xffff, n);
348} 348}
@@ -352,18 +352,22 @@ static inline void msg_set_seqno(struct tipc_msg *m, u32 n)
352 */ 352 */
353static inline u32 msg_importance(struct tipc_msg *m) 353static inline u32 msg_importance(struct tipc_msg *m)
354{ 354{
355 if (unlikely(msg_user(m) == MSG_FRAGMENTER)) 355 int usr = msg_user(m);
356
357 if (likely((usr <= TIPC_CRITICAL_IMPORTANCE) && !msg_errcode(m)))
358 return usr;
359 if ((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER))
356 return msg_bits(m, 5, 13, 0x7); 360 return msg_bits(m, 5, 13, 0x7);
357 if (likely(msg_isdata(m) && !msg_errcode(m)))
358 return msg_user(m);
359 return TIPC_SYSTEM_IMPORTANCE; 361 return TIPC_SYSTEM_IMPORTANCE;
360} 362}
361 363
362static inline void msg_set_importance(struct tipc_msg *m, u32 i) 364static inline void msg_set_importance(struct tipc_msg *m, u32 i)
363{ 365{
364 if (unlikely(msg_user(m) == MSG_FRAGMENTER)) 366 int usr = msg_user(m);
367
368 if (likely((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER)))
365 msg_set_bits(m, 5, 13, 0x7, i); 369 msg_set_bits(m, 5, 13, 0x7, i);
366 else if (likely(i < TIPC_SYSTEM_IMPORTANCE)) 370 else if (i < TIPC_SYSTEM_IMPORTANCE)
367 msg_set_user(m, i); 371 msg_set_user(m, i);
368 else 372 else
369 pr_warn("Trying to set illegal importance in message\n"); 373 pr_warn("Trying to set illegal importance in message\n");
@@ -772,9 +776,9 @@ struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz,
772 uint data_sz, u32 dnode, u32 onode, 776 uint data_sz, u32 dnode, u32 onode,
773 u32 dport, u32 oport, int errcode); 777 u32 dport, u32 oport, int errcode);
774int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); 778int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf);
775bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu); 779bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu);
776 780bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
777bool tipc_msg_make_bundle(struct sk_buff **skb, u32 mtu, u32 dnode); 781 u32 mtu, u32 dnode);
778bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos); 782bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos);
779int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, 783int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
780 int offset, int dsz, int mtu, struct sk_buff_head *list); 784 int offset, int dsz, int mtu, struct sk_buff_head *list);
@@ -782,6 +786,11 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode,
782 int *err); 786 int *err);
783struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); 787struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list);
784 788
789static inline u16 buf_seqno(struct sk_buff *skb)
790{
791 return msg_seqno(buf_msg(skb));
792}
793
785/* tipc_skb_peek(): peek and reserve first buffer in list 794/* tipc_skb_peek(): peek and reserve first buffer in list
786 * @list: list to be peeked in 795 * @list: list to be peeked in
787 * Returns pointer to first buffer in list, if any 796 * Returns pointer to first buffer in list, if any
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index ab0ac62a1287..0f47f08bf38f 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -330,13 +330,9 @@ static struct publication *tipc_nameseq_insert_publ(struct net *net,
330 330
331 /* Any subscriptions waiting for notification? */ 331 /* Any subscriptions waiting for notification? */
332 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { 332 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
333 tipc_subscr_report_overlap(s, 333 tipc_subscrp_report_overlap(s, publ->lower, publ->upper,
334 publ->lower, 334 TIPC_PUBLISHED, publ->ref,
335 publ->upper, 335 publ->node, created_subseq);
336 TIPC_PUBLISHED,
337 publ->ref,
338 publ->node,
339 created_subseq);
340 } 336 }
341 return publ; 337 return publ;
342} 338}
@@ -404,13 +400,9 @@ found:
404 400
405 /* Notify any waiting subscriptions */ 401 /* Notify any waiting subscriptions */
406 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { 402 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
407 tipc_subscr_report_overlap(s, 403 tipc_subscrp_report_overlap(s, publ->lower, publ->upper,
408 publ->lower, 404 TIPC_WITHDRAWN, publ->ref,
409 publ->upper, 405 publ->node, removed_subseq);
410 TIPC_WITHDRAWN,
411 publ->ref,
412 publ->node,
413 removed_subseq);
414 } 406 }
415 407
416 return publ; 408 return publ;
@@ -432,19 +424,17 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq,
432 return; 424 return;
433 425
434 while (sseq != &nseq->sseqs[nseq->first_free]) { 426 while (sseq != &nseq->sseqs[nseq->first_free]) {
435 if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) { 427 if (tipc_subscrp_check_overlap(s, sseq->lower, sseq->upper)) {
436 struct publication *crs; 428 struct publication *crs;
437 struct name_info *info = sseq->info; 429 struct name_info *info = sseq->info;
438 int must_report = 1; 430 int must_report = 1;
439 431
440 list_for_each_entry(crs, &info->zone_list, zone_list) { 432 list_for_each_entry(crs, &info->zone_list, zone_list) {
441 tipc_subscr_report_overlap(s, 433 tipc_subscrp_report_overlap(s, sseq->lower,
442 sseq->lower, 434 sseq->upper,
443 sseq->upper, 435 TIPC_PUBLISHED,
444 TIPC_PUBLISHED, 436 crs->ref, crs->node,
445 crs->ref, 437 must_report);
446 crs->node,
447 must_report);
448 must_report = 0; 438 must_report = 0;
449 } 439 }
450 } 440 }
diff --git a/net/tipc/net.c b/net/tipc/net.c
index a54f3cbe2246..d6d1399ae229 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -40,6 +40,7 @@
40#include "subscr.h" 40#include "subscr.h"
41#include "socket.h" 41#include "socket.h"
42#include "node.h" 42#include "node.h"
43#include "bcast.h"
43 44
44static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { 45static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {
45 [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC }, 46 [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC },
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index ce9121e8e990..53e0fee80086 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -55,6 +55,7 @@ struct tipc_nl_compat_msg {
55 int rep_type; 55 int rep_type;
56 int rep_size; 56 int rep_size;
57 int req_type; 57 int req_type;
58 struct net *net;
58 struct sk_buff *rep; 59 struct sk_buff *rep;
59 struct tlv_desc *req; 60 struct tlv_desc *req;
60 struct sock *dst_sk; 61 struct sock *dst_sk;
@@ -68,7 +69,8 @@ struct tipc_nl_compat_cmd_dump {
68 69
69struct tipc_nl_compat_cmd_doit { 70struct tipc_nl_compat_cmd_doit {
70 int (*doit)(struct sk_buff *skb, struct genl_info *info); 71 int (*doit)(struct sk_buff *skb, struct genl_info *info);
71 int (*transcode)(struct sk_buff *skb, struct tipc_nl_compat_msg *msg); 72 int (*transcode)(struct tipc_nl_compat_cmd_doit *cmd,
73 struct sk_buff *skb, struct tipc_nl_compat_msg *msg);
72}; 74};
73 75
74static int tipc_skb_tailroom(struct sk_buff *skb) 76static int tipc_skb_tailroom(struct sk_buff *skb)
@@ -281,7 +283,7 @@ static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd,
281 if (!trans_buf) 283 if (!trans_buf)
282 return -ENOMEM; 284 return -ENOMEM;
283 285
284 err = (*cmd->transcode)(trans_buf, msg); 286 err = (*cmd->transcode)(cmd, trans_buf, msg);
285 if (err) 287 if (err)
286 goto trans_out; 288 goto trans_out;
287 289
@@ -353,7 +355,8 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg,
353 nla_len(bearer[TIPC_NLA_BEARER_NAME])); 355 nla_len(bearer[TIPC_NLA_BEARER_NAME]));
354} 356}
355 357
356static int tipc_nl_compat_bearer_enable(struct sk_buff *skb, 358static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
359 struct sk_buff *skb,
357 struct tipc_nl_compat_msg *msg) 360 struct tipc_nl_compat_msg *msg)
358{ 361{
359 struct nlattr *prop; 362 struct nlattr *prop;
@@ -385,7 +388,8 @@ static int tipc_nl_compat_bearer_enable(struct sk_buff *skb,
385 return 0; 388 return 0;
386} 389}
387 390
388static int tipc_nl_compat_bearer_disable(struct sk_buff *skb, 391static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
392 struct sk_buff *skb,
389 struct tipc_nl_compat_msg *msg) 393 struct tipc_nl_compat_msg *msg)
390{ 394{
391 char *name; 395 char *name;
@@ -576,11 +580,81 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg,
576 &link_info, sizeof(link_info)); 580 &link_info, sizeof(link_info));
577} 581}
578 582
579static int tipc_nl_compat_link_set(struct sk_buff *skb, 583static int __tipc_add_link_prop(struct sk_buff *skb,
580 struct tipc_nl_compat_msg *msg) 584 struct tipc_nl_compat_msg *msg,
585 struct tipc_link_config *lc)
586{
587 switch (msg->cmd) {
588 case TIPC_CMD_SET_LINK_PRI:
589 return nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value));
590 case TIPC_CMD_SET_LINK_TOL:
591 return nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value));
592 case TIPC_CMD_SET_LINK_WINDOW:
593 return nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value));
594 }
595
596 return -EINVAL;
597}
598
599static int tipc_nl_compat_media_set(struct sk_buff *skb,
600 struct tipc_nl_compat_msg *msg)
581{ 601{
582 struct nlattr *link;
583 struct nlattr *prop; 602 struct nlattr *prop;
603 struct nlattr *media;
604 struct tipc_link_config *lc;
605
606 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
607
608 media = nla_nest_start(skb, TIPC_NLA_MEDIA);
609 if (!media)
610 return -EMSGSIZE;
611
612 if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
613 return -EMSGSIZE;
614
615 prop = nla_nest_start(skb, TIPC_NLA_MEDIA_PROP);
616 if (!prop)
617 return -EMSGSIZE;
618
619 __tipc_add_link_prop(skb, msg, lc);
620 nla_nest_end(skb, prop);
621 nla_nest_end(skb, media);
622
623 return 0;
624}
625
626static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
627 struct tipc_nl_compat_msg *msg)
628{
629 struct nlattr *prop;
630 struct nlattr *bearer;
631 struct tipc_link_config *lc;
632
633 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
634
635 bearer = nla_nest_start(skb, TIPC_NLA_BEARER);
636 if (!bearer)
637 return -EMSGSIZE;
638
639 if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
640 return -EMSGSIZE;
641
642 prop = nla_nest_start(skb, TIPC_NLA_BEARER_PROP);
643 if (!prop)
644 return -EMSGSIZE;
645
646 __tipc_add_link_prop(skb, msg, lc);
647 nla_nest_end(skb, prop);
648 nla_nest_end(skb, bearer);
649
650 return 0;
651}
652
653static int __tipc_nl_compat_link_set(struct sk_buff *skb,
654 struct tipc_nl_compat_msg *msg)
655{
656 struct nlattr *prop;
657 struct nlattr *link;
584 struct tipc_link_config *lc; 658 struct tipc_link_config *lc;
585 659
586 lc = (struct tipc_link_config *)TLV_DATA(msg->req); 660 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
@@ -596,24 +670,40 @@ static int tipc_nl_compat_link_set(struct sk_buff *skb,
596 if (!prop) 670 if (!prop)
597 return -EMSGSIZE; 671 return -EMSGSIZE;
598 672
599 if (msg->cmd == TIPC_CMD_SET_LINK_PRI) { 673 __tipc_add_link_prop(skb, msg, lc);
600 if (nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value)))
601 return -EMSGSIZE;
602 } else if (msg->cmd == TIPC_CMD_SET_LINK_TOL) {
603 if (nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value)))
604 return -EMSGSIZE;
605 } else if (msg->cmd == TIPC_CMD_SET_LINK_WINDOW) {
606 if (nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value)))
607 return -EMSGSIZE;
608 }
609
610 nla_nest_end(skb, prop); 674 nla_nest_end(skb, prop);
611 nla_nest_end(skb, link); 675 nla_nest_end(skb, link);
612 676
613 return 0; 677 return 0;
614} 678}
615 679
616static int tipc_nl_compat_link_reset_stats(struct sk_buff *skb, 680static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
681 struct sk_buff *skb,
682 struct tipc_nl_compat_msg *msg)
683{
684 struct tipc_link_config *lc;
685 struct tipc_bearer *bearer;
686 struct tipc_media *media;
687
688 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
689
690 media = tipc_media_find(lc->name);
691 if (media) {
692 cmd->doit = &tipc_nl_media_set;
693 return tipc_nl_compat_media_set(skb, msg);
694 }
695
696 bearer = tipc_bearer_find(msg->net, lc->name);
697 if (bearer) {
698 cmd->doit = &tipc_nl_bearer_set;
699 return tipc_nl_compat_bearer_set(skb, msg);
700 }
701
702 return __tipc_nl_compat_link_set(skb, msg);
703}
704
705static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
706 struct sk_buff *skb,
617 struct tipc_nl_compat_msg *msg) 707 struct tipc_nl_compat_msg *msg)
618{ 708{
619 char *name; 709 char *name;
@@ -851,7 +941,8 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg,
851 sizeof(node_info)); 941 sizeof(node_info));
852} 942}
853 943
854static int tipc_nl_compat_net_set(struct sk_buff *skb, 944static int tipc_nl_compat_net_set(struct tipc_nl_compat_cmd_doit *cmd,
945 struct sk_buff *skb,
855 struct tipc_nl_compat_msg *msg) 946 struct tipc_nl_compat_msg *msg)
856{ 947{
857 u32 val; 948 u32 val;
@@ -1007,7 +1098,6 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
1007 struct nlmsghdr *req_nlh; 1098 struct nlmsghdr *req_nlh;
1008 struct nlmsghdr *rep_nlh; 1099 struct nlmsghdr *rep_nlh;
1009 struct tipc_genlmsghdr *req_userhdr = info->userhdr; 1100 struct tipc_genlmsghdr *req_userhdr = info->userhdr;
1010 struct net *net = genl_info_net(info);
1011 1101
1012 memset(&msg, 0, sizeof(msg)); 1102 memset(&msg, 0, sizeof(msg));
1013 1103
@@ -1015,6 +1105,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
1015 msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; 1105 msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN;
1016 msg.cmd = req_userhdr->cmd; 1106 msg.cmd = req_userhdr->cmd;
1017 msg.dst_sk = info->dst_sk; 1107 msg.dst_sk = info->dst_sk;
1108 msg.net = genl_info_net(info);
1018 1109
1019 if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { 1110 if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) {
1020 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); 1111 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN);
@@ -1030,7 +1121,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
1030 } 1121 }
1031 1122
1032 err = tipc_nl_compat_handle(&msg); 1123 err = tipc_nl_compat_handle(&msg);
1033 if (err == -EOPNOTSUPP) 1124 if ((err == -EOPNOTSUPP) || (err == -EPERM))
1034 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); 1125 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
1035 else if (err == -EINVAL) 1126 else if (err == -EINVAL)
1036 msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR); 1127 msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR);
@@ -1043,7 +1134,7 @@ send:
1043 rep_nlh = nlmsg_hdr(msg.rep); 1134 rep_nlh = nlmsg_hdr(msg.rep);
1044 memcpy(rep_nlh, info->nlhdr, len); 1135 memcpy(rep_nlh, info->nlhdr, len);
1045 rep_nlh->nlmsg_len = msg.rep->len; 1136 rep_nlh->nlmsg_len = msg.rep->len;
1046 genlmsg_unicast(net, msg.rep, NETLINK_CB(skb).portid); 1137 genlmsg_unicast(msg.net, msg.rep, NETLINK_CB(skb).portid);
1047 1138
1048 return err; 1139 return err;
1049} 1140}
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 22c059ad2999..0b1d61a5f853 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/node.c: TIPC node management routines 2 * net/tipc/node.c: TIPC node management routines
3 * 3 *
4 * Copyright (c) 2000-2006, 2012-2014, Ericsson AB 4 * Copyright (c) 2000-2006, 2012-2015, Ericsson AB
5 * Copyright (c) 2005-2006, 2010-2014, Wind River Systems 5 * Copyright (c) 2005-2006, 2010-2014, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -39,6 +39,7 @@
39#include "node.h" 39#include "node.h"
40#include "name_distr.h" 40#include "name_distr.h"
41#include "socket.h" 41#include "socket.h"
42#include "bcast.h"
42 43
43static void node_lost_contact(struct tipc_node *n_ptr); 44static void node_lost_contact(struct tipc_node *n_ptr);
44static void node_established_contact(struct tipc_node *n_ptr); 45static void node_established_contact(struct tipc_node *n_ptr);
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 02d5c20dc551..5a834cf142c8 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -45,8 +45,6 @@
45/* Out-of-range value for node signature */ 45/* Out-of-range value for node signature */
46#define INVALID_NODE_SIG 0x10000 46#define INVALID_NODE_SIG 0x10000
47 47
48#define NODE_HTABLE_SIZE 512
49
50/* Flags used to take different actions according to flag type 48/* Flags used to take different actions according to flag type
51 * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down 49 * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down
52 * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down 50 * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down
diff --git a/net/tipc/server.c b/net/tipc/server.c
index 77ff03ed1e18..922e04a43396 100644
--- a/net/tipc/server.c
+++ b/net/tipc/server.c
@@ -309,6 +309,10 @@ static int tipc_accept_from_sock(struct tipc_conn *con)
309 309
310 /* Notify that new connection is incoming */ 310 /* Notify that new connection is incoming */
311 newcon->usr_data = s->tipc_conn_new(newcon->conid); 311 newcon->usr_data = s->tipc_conn_new(newcon->conid);
312 if (!newcon->usr_data) {
313 sock_release(newsock);
314 return -ENOMEM;
315 }
312 316
313 /* Wake up receive process in case of 'SYN+' message */ 317 /* Wake up receive process in case of 'SYN+' message */
314 newsock->sk->sk_data_ready(newsock->sk); 318 newsock->sk->sk_data_ready(newsock->sk);
@@ -321,7 +325,7 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con)
321 struct socket *sock = NULL; 325 struct socket *sock = NULL;
322 int ret; 326 int ret;
323 327
324 ret = __sock_create(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock, 1); 328 ret = sock_create_kern(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock);
325 if (ret < 0) 329 if (ret < 0)
326 return NULL; 330 return NULL;
327 ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, 331 ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE,
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index f485600c4507..46b6ed534ef2 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -41,6 +41,7 @@
41#include "link.h" 41#include "link.h"
42#include "name_distr.h" 42#include "name_distr.h"
43#include "socket.h" 43#include "socket.h"
44#include "bcast.h"
44 45
45#define SS_LISTENING -1 /* socket is listening */ 46#define SS_LISTENING -1 /* socket is listening */
46#define SS_READY -2 /* socket is connectionless */ 47#define SS_READY -2 /* socket is connectionless */
@@ -342,7 +343,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
342 } 343 }
343 344
344 /* Allocate socket's protocol area */ 345 /* Allocate socket's protocol area */
345 sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto); 346 sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, kern);
346 if (sk == NULL) 347 if (sk == NULL)
347 return -ENOMEM; 348 return -ENOMEM;
348 349
@@ -409,7 +410,7 @@ static int tipc_release(struct socket *sock)
409 struct net *net; 410 struct net *net;
410 struct tipc_sock *tsk; 411 struct tipc_sock *tsk;
411 struct sk_buff *skb; 412 struct sk_buff *skb;
412 u32 dnode, probing_state; 413 u32 dnode;
413 414
414 /* 415 /*
415 * Exit if socket isn't fully initialized (occurs when a failed accept() 416 * Exit if socket isn't fully initialized (occurs when a failed accept()
@@ -447,10 +448,7 @@ static int tipc_release(struct socket *sock)
447 } 448 }
448 449
449 tipc_sk_withdraw(tsk, 0, NULL); 450 tipc_sk_withdraw(tsk, 0, NULL);
450 probing_state = tsk->probing_state; 451 sk_stop_timer(sk, &sk->sk_timer);
451 if (del_timer_sync(&sk->sk_timer) &&
452 probing_state != TIPC_CONN_PROBING)
453 sock_put(sk);
454 tipc_sk_remove(tsk); 452 tipc_sk_remove(tsk);
455 if (tsk->connected) { 453 if (tsk->connected) {
456 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, 454 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 1c147c869c2e..350cca33ee0a 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -40,16 +40,21 @@
40 40
41/** 41/**
42 * struct tipc_subscriber - TIPC network topology subscriber 42 * struct tipc_subscriber - TIPC network topology subscriber
43 * @kref: reference counter to tipc_subscription object
43 * @conid: connection identifier to server connecting to subscriber 44 * @conid: connection identifier to server connecting to subscriber
44 * @lock: control access to subscriber 45 * @lock: control access to subscriber
45 * @subscription_list: list of subscription objects for this subscriber 46 * @subscrp_list: list of subscription objects for this subscriber
46 */ 47 */
47struct tipc_subscriber { 48struct tipc_subscriber {
49 struct kref kref;
48 int conid; 50 int conid;
49 spinlock_t lock; 51 spinlock_t lock;
50 struct list_head subscription_list; 52 struct list_head subscrp_list;
51}; 53};
52 54
55static void tipc_subscrp_delete(struct tipc_subscription *sub);
56static void tipc_subscrb_put(struct tipc_subscriber *subscriber);
57
53/** 58/**
54 * htohl - convert value to endianness used by destination 59 * htohl - convert value to endianness used by destination
55 * @in: value to convert 60 * @in: value to convert
@@ -62,9 +67,9 @@ static u32 htohl(u32 in, int swap)
62 return swap ? swab32(in) : in; 67 return swap ? swab32(in) : in;
63} 68}
64 69
65static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, 70static void tipc_subscrp_send_event(struct tipc_subscription *sub,
66 u32 found_upper, u32 event, u32 port_ref, 71 u32 found_lower, u32 found_upper,
67 u32 node) 72 u32 event, u32 port_ref, u32 node)
68{ 73{
69 struct tipc_net *tn = net_generic(sub->net, tipc_net_id); 74 struct tipc_net *tn = net_generic(sub->net, tipc_net_id);
70 struct tipc_subscriber *subscriber = sub->subscriber; 75 struct tipc_subscriber *subscriber = sub->subscriber;
@@ -82,12 +87,13 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower,
82} 87}
83 88
84/** 89/**
85 * tipc_subscr_overlap - test for subscription overlap with the given values 90 * tipc_subscrp_check_overlap - test for subscription overlap with the
91 * given values
86 * 92 *
87 * Returns 1 if there is overlap, otherwise 0. 93 * Returns 1 if there is overlap, otherwise 0.
88 */ 94 */
89int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, 95int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower,
90 u32 found_upper) 96 u32 found_upper)
91{ 97{
92 if (found_lower < sub->seq.lower) 98 if (found_lower < sub->seq.lower)
93 found_lower = sub->seq.lower; 99 found_lower = sub->seq.lower;
@@ -98,138 +104,121 @@ int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower,
98 return 1; 104 return 1;
99} 105}
100 106
101/** 107void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
102 * tipc_subscr_report_overlap - issue event if there is subscription overlap 108 u32 found_upper, u32 event, u32 port_ref,
103 * 109 u32 node, int must)
104 * Protected by nameseq.lock in name_table.c
105 */
106void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower,
107 u32 found_upper, u32 event, u32 port_ref,
108 u32 node, int must)
109{ 110{
110 if (!tipc_subscr_overlap(sub, found_lower, found_upper)) 111 if (!tipc_subscrp_check_overlap(sub, found_lower, found_upper))
111 return; 112 return;
112 if (!must && !(sub->filter & TIPC_SUB_PORTS)) 113 if (!must && !(sub->filter & TIPC_SUB_PORTS))
113 return; 114 return;
114 115
115 subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); 116 tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref,
117 node);
116} 118}
117 119
118static void subscr_timeout(unsigned long data) 120static void tipc_subscrp_timeout(unsigned long data)
119{ 121{
120 struct tipc_subscription *sub = (struct tipc_subscription *)data; 122 struct tipc_subscription *sub = (struct tipc_subscription *)data;
121 struct tipc_subscriber *subscriber = sub->subscriber; 123 struct tipc_subscriber *subscriber = sub->subscriber;
122 struct tipc_net *tn = net_generic(sub->net, tipc_net_id);
123 124
124 /* The spin lock per subscriber is used to protect its members */ 125 /* Notify subscriber of timeout */
125 spin_lock_bh(&subscriber->lock); 126 tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper,
127 TIPC_SUBSCR_TIMEOUT, 0, 0);
126 128
127 /* Validate timeout (in case subscription is being cancelled) */ 129 spin_lock_bh(&subscriber->lock);
128 if (sub->timeout == TIPC_WAIT_FOREVER) { 130 tipc_subscrp_delete(sub);
129 spin_unlock_bh(&subscriber->lock); 131 spin_unlock_bh(&subscriber->lock);
130 return;
131 }
132 132
133 /* Unlink subscription from name table */ 133 tipc_subscrb_put(subscriber);
134 tipc_nametbl_unsubscribe(sub); 134}
135 135
136 /* Unlink subscription from subscriber */ 136static void tipc_subscrb_kref_release(struct kref *kref)
137 list_del(&sub->subscription_list); 137{
138 struct tipc_subscriber *subcriber = container_of(kref,
139 struct tipc_subscriber, kref);
138 140
139 spin_unlock_bh(&subscriber->lock); 141 kfree(subcriber);
142}
140 143
141 /* Notify subscriber of timeout */ 144static void tipc_subscrb_put(struct tipc_subscriber *subscriber)
142 subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, 145{
143 TIPC_SUBSCR_TIMEOUT, 0, 0); 146 kref_put(&subscriber->kref, tipc_subscrb_kref_release);
147}
144 148
145 /* Now destroy subscription */ 149static void tipc_subscrb_get(struct tipc_subscriber *subscriber)
146 kfree(sub); 150{
147 atomic_dec(&tn->subscription_count); 151 kref_get(&subscriber->kref);
148} 152}
149 153
150/** 154static struct tipc_subscriber *tipc_subscrb_create(int conid)
151 * subscr_del - delete a subscription within a subscription list
152 *
153 * Called with subscriber lock held.
154 */
155static void subscr_del(struct tipc_subscription *sub)
156{ 155{
157 struct tipc_net *tn = net_generic(sub->net, tipc_net_id); 156 struct tipc_subscriber *subscriber;
158 157
159 tipc_nametbl_unsubscribe(sub); 158 subscriber = kzalloc(sizeof(*subscriber), GFP_ATOMIC);
160 list_del(&sub->subscription_list); 159 if (!subscriber) {
161 kfree(sub); 160 pr_warn("Subscriber rejected, no memory\n");
162 atomic_dec(&tn->subscription_count); 161 return NULL;
162 }
163 kref_init(&subscriber->kref);
164 INIT_LIST_HEAD(&subscriber->subscrp_list);
165 subscriber->conid = conid;
166 spin_lock_init(&subscriber->lock);
167
168 return subscriber;
163} 169}
164 170
165static void subscr_release(struct tipc_subscriber *subscriber) 171static void tipc_subscrb_delete(struct tipc_subscriber *subscriber)
166{ 172{
167 struct tipc_subscription *sub; 173 struct tipc_subscription *sub, *temp;
168 struct tipc_subscription *sub_temp;
169 174
170 spin_lock_bh(&subscriber->lock); 175 spin_lock_bh(&subscriber->lock);
171
172 /* Destroy any existing subscriptions for subscriber */ 176 /* Destroy any existing subscriptions for subscriber */
173 list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, 177 list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list,
174 subscription_list) { 178 subscrp_list) {
175 if (sub->timeout != TIPC_WAIT_FOREVER) { 179 if (del_timer(&sub->timer)) {
176 spin_unlock_bh(&subscriber->lock); 180 tipc_subscrp_delete(sub);
177 del_timer_sync(&sub->timer); 181 tipc_subscrb_put(subscriber);
178 spin_lock_bh(&subscriber->lock);
179 } 182 }
180 subscr_del(sub);
181 } 183 }
182 spin_unlock_bh(&subscriber->lock); 184 spin_unlock_bh(&subscriber->lock);
183 185
184 /* Now destroy subscriber */ 186 tipc_subscrb_put(subscriber);
185 kfree(subscriber);
186} 187}
187 188
188/** 189static void tipc_subscrp_delete(struct tipc_subscription *sub)
189 * subscr_cancel - handle subscription cancellation request
190 *
191 * Called with subscriber lock held. Routine must temporarily release lock
192 * to enable the subscription timeout routine to finish without deadlocking;
193 * the lock is then reclaimed to allow caller to release it upon return.
194 *
195 * Note that fields of 's' use subscriber's endianness!
196 */
197static void subscr_cancel(struct tipc_subscr *s,
198 struct tipc_subscriber *subscriber)
199{ 190{
200 struct tipc_subscription *sub; 191 struct tipc_net *tn = net_generic(sub->net, tipc_net_id);
201 struct tipc_subscription *sub_temp; 192
202 int found = 0; 193 tipc_nametbl_unsubscribe(sub);
194 list_del(&sub->subscrp_list);
195 kfree(sub);
196 atomic_dec(&tn->subscription_count);
197}
203 198
199static void tipc_subscrp_cancel(struct tipc_subscr *s,
200 struct tipc_subscriber *subscriber)
201{
202 struct tipc_subscription *sub, *temp;
203
204 spin_lock_bh(&subscriber->lock);
204 /* Find first matching subscription, exit if not found */ 205 /* Find first matching subscription, exit if not found */
205 list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, 206 list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list,
206 subscription_list) { 207 subscrp_list) {
207 if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { 208 if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
208 found = 1; 209 if (del_timer(&sub->timer)) {
210 tipc_subscrp_delete(sub);
211 tipc_subscrb_put(subscriber);
212 }
209 break; 213 break;
210 } 214 }
211 } 215 }
212 if (!found) 216 spin_unlock_bh(&subscriber->lock);
213 return;
214
215 /* Cancel subscription timer (if used), then delete subscription */
216 if (sub->timeout != TIPC_WAIT_FOREVER) {
217 sub->timeout = TIPC_WAIT_FOREVER;
218 spin_unlock_bh(&subscriber->lock);
219 del_timer_sync(&sub->timer);
220 spin_lock_bh(&subscriber->lock);
221 }
222 subscr_del(sub);
223} 217}
224 218
225/** 219static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s,
226 * subscr_subscribe - create subscription for subscriber 220 struct tipc_subscriber *subscriber,
227 * 221 struct tipc_subscription **sub_p)
228 * Called with subscriber lock held.
229 */
230static int subscr_subscribe(struct net *net, struct tipc_subscr *s,
231 struct tipc_subscriber *subscriber,
232 struct tipc_subscription **sub_p)
233{ 222{
234 struct tipc_net *tn = net_generic(net, tipc_net_id); 223 struct tipc_net *tn = net_generic(net, tipc_net_id);
235 struct tipc_subscription *sub; 224 struct tipc_subscription *sub;
@@ -241,7 +230,7 @@ static int subscr_subscribe(struct net *net, struct tipc_subscr *s,
241 /* Detect & process a subscription cancellation request */ 230 /* Detect & process a subscription cancellation request */
242 if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { 231 if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {
243 s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); 232 s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
244 subscr_cancel(s, subscriber); 233 tipc_subscrp_cancel(s, subscriber);
245 return 0; 234 return 0;
246 } 235 }
247 236
@@ -273,62 +262,51 @@ static int subscr_subscribe(struct net *net, struct tipc_subscr *s,
273 kfree(sub); 262 kfree(sub);
274 return -EINVAL; 263 return -EINVAL;
275 } 264 }
276 list_add(&sub->subscription_list, &subscriber->subscription_list); 265 spin_lock_bh(&subscriber->lock);
266 list_add(&sub->subscrp_list, &subscriber->subscrp_list);
267 spin_unlock_bh(&subscriber->lock);
277 sub->subscriber = subscriber; 268 sub->subscriber = subscriber;
278 sub->swap = swap; 269 sub->swap = swap;
279 memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); 270 memcpy(&sub->evt.s, s, sizeof(*s));
280 atomic_inc(&tn->subscription_count); 271 atomic_inc(&tn->subscription_count);
281 if (sub->timeout != TIPC_WAIT_FOREVER) { 272 setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub);
282 setup_timer(&sub->timer, subscr_timeout, (unsigned long)sub); 273 if (sub->timeout != TIPC_WAIT_FOREVER)
283 mod_timer(&sub->timer, jiffies + sub->timeout); 274 sub->timeout += jiffies;
284 } 275 if (!mod_timer(&sub->timer, sub->timeout))
276 tipc_subscrb_get(subscriber);
285 *sub_p = sub; 277 *sub_p = sub;
286 return 0; 278 return 0;
287} 279}
288 280
289/* Handle one termination request for the subscriber */ 281/* Handle one termination request for the subscriber */
290static void subscr_conn_shutdown_event(int conid, void *usr_data) 282static void tipc_subscrb_shutdown_cb(int conid, void *usr_data)
291{ 283{
292 subscr_release((struct tipc_subscriber *)usr_data); 284 tipc_subscrb_delete((struct tipc_subscriber *)usr_data);
293} 285}
294 286
295/* Handle one request to create a new subscription for the subscriber */ 287/* Handle one request to create a new subscription for the subscriber */
296static void subscr_conn_msg_event(struct net *net, int conid, 288static void tipc_subscrb_rcv_cb(struct net *net, int conid,
297 struct sockaddr_tipc *addr, void *usr_data, 289 struct sockaddr_tipc *addr, void *usr_data,
298 void *buf, size_t len) 290 void *buf, size_t len)
299{ 291{
300 struct tipc_subscriber *subscriber = usr_data; 292 struct tipc_subscriber *subscriber = usr_data;
301 struct tipc_subscription *sub = NULL; 293 struct tipc_subscription *sub = NULL;
302 struct tipc_net *tn = net_generic(net, tipc_net_id); 294 struct tipc_net *tn = net_generic(net, tipc_net_id);
303 295
304 spin_lock_bh(&subscriber->lock); 296 tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscriber, &sub);
305 subscr_subscribe(net, (struct tipc_subscr *)buf, subscriber, &sub);
306 if (sub) 297 if (sub)
307 tipc_nametbl_subscribe(sub); 298 tipc_nametbl_subscribe(sub);
308 else 299 else
309 tipc_conn_terminate(tn->topsrv, subscriber->conid); 300 tipc_conn_terminate(tn->topsrv, subscriber->conid);
310 spin_unlock_bh(&subscriber->lock);
311} 301}
312 302
313/* Handle one request to establish a new subscriber */ 303/* Handle one request to establish a new subscriber */
314static void *subscr_named_msg_event(int conid) 304static void *tipc_subscrb_connect_cb(int conid)
315{ 305{
316 struct tipc_subscriber *subscriber; 306 return (void *)tipc_subscrb_create(conid);
317
318 /* Create subscriber object */
319 subscriber = kzalloc(sizeof(struct tipc_subscriber), GFP_ATOMIC);
320 if (subscriber == NULL) {
321 pr_warn("Subscriber rejected, no memory\n");
322 return NULL;
323 }
324 INIT_LIST_HEAD(&subscriber->subscription_list);
325 subscriber->conid = conid;
326 spin_lock_init(&subscriber->lock);
327
328 return (void *)subscriber;
329} 307}
330 308
331int tipc_subscr_start(struct net *net) 309int tipc_topsrv_start(struct net *net)
332{ 310{
333 struct tipc_net *tn = net_generic(net, tipc_net_id); 311 struct tipc_net *tn = net_generic(net, tipc_net_id);
334 const char name[] = "topology_server"; 312 const char name[] = "topology_server";
@@ -355,9 +333,9 @@ int tipc_subscr_start(struct net *net)
355 topsrv->imp = TIPC_CRITICAL_IMPORTANCE; 333 topsrv->imp = TIPC_CRITICAL_IMPORTANCE;
356 topsrv->type = SOCK_SEQPACKET; 334 topsrv->type = SOCK_SEQPACKET;
357 topsrv->max_rcvbuf_size = sizeof(struct tipc_subscr); 335 topsrv->max_rcvbuf_size = sizeof(struct tipc_subscr);
358 topsrv->tipc_conn_recvmsg = subscr_conn_msg_event; 336 topsrv->tipc_conn_recvmsg = tipc_subscrb_rcv_cb;
359 topsrv->tipc_conn_new = subscr_named_msg_event; 337 topsrv->tipc_conn_new = tipc_subscrb_connect_cb;
360 topsrv->tipc_conn_shutdown = subscr_conn_shutdown_event; 338 topsrv->tipc_conn_shutdown = tipc_subscrb_shutdown_cb;
361 339
362 strncpy(topsrv->name, name, strlen(name) + 1); 340 strncpy(topsrv->name, name, strlen(name) + 1);
363 tn->topsrv = topsrv; 341 tn->topsrv = topsrv;
@@ -366,7 +344,7 @@ int tipc_subscr_start(struct net *net)
366 return tipc_server_start(topsrv); 344 return tipc_server_start(topsrv);
367} 345}
368 346
369void tipc_subscr_stop(struct net *net) 347void tipc_topsrv_stop(struct net *net)
370{ 348{
371 struct tipc_net *tn = net_generic(net, tipc_net_id); 349 struct tipc_net *tn = net_generic(net, tipc_net_id);
372 struct tipc_server *topsrv = tn->topsrv; 350 struct tipc_server *topsrv = tn->topsrv;
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index 33488bd9fe3c..92ee18cc5fe6 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -54,7 +54,7 @@ struct tipc_subscriber;
54 * @filter: event filtering to be done for subscription 54 * @filter: event filtering to be done for subscription
55 * @timer: timer governing subscription duration (optional) 55 * @timer: timer governing subscription duration (optional)
56 * @nameseq_list: adjacent subscriptions in name sequence's subscription list 56 * @nameseq_list: adjacent subscriptions in name sequence's subscription list
57 * @subscription_list: adjacent subscriptions in subscriber's subscription list 57 * @subscrp_list: adjacent subscriptions in subscriber's subscription list
58 * @server_ref: object reference of server port associated with subscription 58 * @server_ref: object reference of server port associated with subscription
59 * @swap: indicates if subscriber uses opposite endianness in its messages 59 * @swap: indicates if subscriber uses opposite endianness in its messages
60 * @evt: template for events generated by subscription 60 * @evt: template for events generated by subscription
@@ -67,17 +67,17 @@ struct tipc_subscription {
67 u32 filter; 67 u32 filter;
68 struct timer_list timer; 68 struct timer_list timer;
69 struct list_head nameseq_list; 69 struct list_head nameseq_list;
70 struct list_head subscription_list; 70 struct list_head subscrp_list;
71 int swap; 71 int swap;
72 struct tipc_event evt; 72 struct tipc_event evt;
73}; 73};
74 74
75int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, 75int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower,
76 u32 found_upper); 76 u32 found_upper);
77void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, 77void tipc_subscrp_report_overlap(struct tipc_subscription *sub,
78 u32 found_upper, u32 event, u32 port_ref, 78 u32 found_lower, u32 found_upper, u32 event,
79 u32 node, int must); 79 u32 port_ref, u32 node, int must);
80int tipc_subscr_start(struct net *net); 80int tipc_topsrv_start(struct net *net);
81void tipc_subscr_stop(struct net *net); 81void tipc_topsrv_stop(struct net *net);
82 82
83#endif 83#endif