aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-13 21:49:11 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-13 21:49:11 -0400
commit27b61ae2d73936554fcd07e77c3cc13bc88c41a9 (patch)
tree12f589c6a4671bf7f08045bb11059514f47bb924 /net/tipc
parent46af31800b6916c92fffa529dc3c357008da957d (diff)
parent633d2bdedc3b81f202bda8fdad17aeb08809b7df (diff)
Merge branch 'tipc-Mar13-2011' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/net-next-2.6
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/Kconfig12
-rw-r--r--net/tipc/addr.c15
-rw-r--r--net/tipc/addr.h17
-rw-r--r--net/tipc/bearer.c18
-rw-r--r--net/tipc/bearer.h6
-rw-r--r--net/tipc/config.c31
-rw-r--r--net/tipc/core.c6
-rw-r--r--net/tipc/core.h1
-rw-r--r--net/tipc/discover.c103
-rw-r--r--net/tipc/link.c50
-rw-r--r--net/tipc/link.h3
-rw-r--r--net/tipc/msg.c34
-rw-r--r--net/tipc/msg.h42
-rw-r--r--net/tipc/name_distr.c18
-rw-r--r--net/tipc/net.c32
-rw-r--r--net/tipc/net.h19
-rw-r--r--net/tipc/node.c123
-rw-r--r--net/tipc/node.h36
-rw-r--r--net/tipc/node_subscr.c21
-rw-r--r--net/tipc/node_subscr.h3
-rw-r--r--net/tipc/socket.c70
21 files changed, 273 insertions, 387 deletions
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
index 0436927369f3..2c5954b85933 100644
--- a/net/tipc/Kconfig
+++ b/net/tipc/Kconfig
@@ -29,18 +29,6 @@ config TIPC_ADVANCED
29 Saying Y here will open some advanced configuration for TIPC. 29 Saying Y here will open some advanced configuration for TIPC.
30 Most users do not need to bother; if unsure, just say N. 30 Most users do not need to bother; if unsure, just say N.
31 31
32config TIPC_NODES
33 int "Maximum number of nodes in a cluster"
34 depends on TIPC_ADVANCED
35 range 8 2047
36 default "255"
37 help
38 Specifies how many nodes can be supported in a TIPC cluster.
39 Can range from 8 to 2047 nodes; default is 255.
40
41 Setting this to a smaller value saves some memory;
42 setting it to higher allows for more nodes.
43
44config TIPC_PORTS 32config TIPC_PORTS
45 int "Maximum number of ports in a node" 33 int "Maximum number of ports in a node"
46 depends on TIPC_ADVANCED 34 depends on TIPC_ADVANCED
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index 88463d9a6f12..a6fdab33877e 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -2,7 +2,7 @@
2 * net/tipc/addr.c: TIPC address utility routines 2 * net/tipc/addr.c: TIPC address utility routines
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems 5 * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
41 * tipc_addr_domain_valid - validates a network domain address 41 * tipc_addr_domain_valid - validates a network domain address
42 * 42 *
43 * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>, 43 * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>,
44 * where Z, C, and N are non-zero and do not exceed the configured limits. 44 * where Z, C, and N are non-zero.
45 * 45 *
46 * Returns 1 if domain address is valid, otherwise 0 46 * Returns 1 if domain address is valid, otherwise 0
47 */ 47 */
@@ -51,10 +51,6 @@ int tipc_addr_domain_valid(u32 addr)
51 u32 n = tipc_node(addr); 51 u32 n = tipc_node(addr);
52 u32 c = tipc_cluster(addr); 52 u32 c = tipc_cluster(addr);
53 u32 z = tipc_zone(addr); 53 u32 z = tipc_zone(addr);
54 u32 max_nodes = tipc_max_nodes;
55
56 if (n > max_nodes)
57 return 0;
58 54
59 if (n && (!z || !c)) 55 if (n && (!z || !c))
60 return 0; 56 return 0;
@@ -66,8 +62,7 @@ int tipc_addr_domain_valid(u32 addr)
66/** 62/**
67 * tipc_addr_node_valid - validates a proposed network address for this node 63 * tipc_addr_node_valid - validates a proposed network address for this node
68 * 64 *
69 * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed 65 * Accepts <Z.C.N>, where Z, C, and N are non-zero.
70 * the configured limits.
71 * 66 *
72 * Returns 1 if address can be used, otherwise 0 67 * Returns 1 if address can be used, otherwise 0
73 */ 68 */
@@ -81,9 +76,9 @@ int tipc_in_scope(u32 domain, u32 addr)
81{ 76{
82 if (!domain || (domain == addr)) 77 if (!domain || (domain == addr))
83 return 1; 78 return 1;
84 if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ 79 if (domain == tipc_cluster_mask(addr)) /* domain <Z.C.0> */
85 return 1; 80 return 1;
86 if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ 81 if (domain == tipc_zone_mask(addr)) /* domain <Z.0.0> */
87 return 1; 82 return 1;
88 return 0; 83 return 0;
89} 84}
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
index 2490fadd0caf..8971aba99aea 100644
--- a/net/tipc/addr.h
+++ b/net/tipc/addr.h
@@ -37,6 +37,16 @@
37#ifndef _TIPC_ADDR_H 37#ifndef _TIPC_ADDR_H
38#define _TIPC_ADDR_H 38#define _TIPC_ADDR_H
39 39
40static inline u32 tipc_zone_mask(u32 addr)
41{
42 return addr & 0xff000000u;
43}
44
45static inline u32 tipc_cluster_mask(u32 addr)
46{
47 return addr & 0xfffff000u;
48}
49
40static inline int in_own_cluster(u32 addr) 50static inline int in_own_cluster(u32 addr)
41{ 51{
42 return !((addr ^ tipc_own_addr) >> 12); 52 return !((addr ^ tipc_own_addr) >> 12);
@@ -49,14 +59,13 @@ static inline int in_own_cluster(u32 addr)
49 * after a network hop. 59 * after a network hop.
50 */ 60 */
51 61
52static inline int addr_domain(int sc) 62static inline u32 addr_domain(u32 sc)
53{ 63{
54 if (likely(sc == TIPC_NODE_SCOPE)) 64 if (likely(sc == TIPC_NODE_SCOPE))
55 return tipc_own_addr; 65 return tipc_own_addr;
56 if (sc == TIPC_CLUSTER_SCOPE) 66 if (sc == TIPC_CLUSTER_SCOPE)
57 return tipc_addr(tipc_zone(tipc_own_addr), 67 return tipc_cluster_mask(tipc_own_addr);
58 tipc_cluster(tipc_own_addr), 0); 68 return tipc_zone_mask(tipc_own_addr);
59 return tipc_addr(tipc_zone(tipc_own_addr), 0, 0);
60} 69}
61 70
62int tipc_addr_domain_valid(u32); 71int tipc_addr_domain_valid(u32);
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index f2839b0f6b65..411719feb803 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -158,7 +158,6 @@ int tipc_register_media(u32 media_type,
158 m_ptr->disable_bearer = disable; 158 m_ptr->disable_bearer = disable;
159 m_ptr->addr2str = addr2str; 159 m_ptr->addr2str = addr2str;
160 memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr)); 160 memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
161 m_ptr->bcast = 1;
162 strcpy(m_ptr->name, name); 161 strcpy(m_ptr->name, name);
163 m_ptr->priority = bearer_priority; 162 m_ptr->priority = bearer_priority;
164 m_ptr->tolerance = link_tolerance; 163 m_ptr->tolerance = link_tolerance;
@@ -474,7 +473,7 @@ int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct link *l_ptr)
474 * tipc_enable_bearer - enable bearer with the given name 473 * tipc_enable_bearer - enable bearer with the given name
475 */ 474 */
476 475
477int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) 476int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
478{ 477{
479 struct tipc_bearer *b_ptr; 478 struct tipc_bearer *b_ptr;
480 struct media *m_ptr; 479 struct media *m_ptr;
@@ -494,9 +493,9 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
494 warn("Bearer <%s> rejected, illegal name\n", name); 493 warn("Bearer <%s> rejected, illegal name\n", name);
495 return -EINVAL; 494 return -EINVAL;
496 } 495 }
497 if (!tipc_addr_domain_valid(bcast_scope) || 496 if (!tipc_addr_domain_valid(disc_domain) ||
498 !tipc_in_scope(bcast_scope, tipc_own_addr)) { 497 !tipc_in_scope(disc_domain, tipc_own_addr)) {
499 warn("Bearer <%s> rejected, illegal broadcast scope\n", name); 498 warn("Bearer <%s> rejected, illegal discovery domain\n", name);
500 return -EINVAL; 499 return -EINVAL;
501 } 500 }
502 if ((priority < TIPC_MIN_LINK_PRI || 501 if ((priority < TIPC_MIN_LINK_PRI ||
@@ -560,18 +559,15 @@ restart:
560 b_ptr->media = m_ptr; 559 b_ptr->media = m_ptr;
561 b_ptr->net_plane = bearer_id + 'A'; 560 b_ptr->net_plane = bearer_id + 'A';
562 b_ptr->active = 1; 561 b_ptr->active = 1;
563 b_ptr->detect_scope = bcast_scope;
564 b_ptr->priority = priority; 562 b_ptr->priority = priority;
565 INIT_LIST_HEAD(&b_ptr->cong_links); 563 INIT_LIST_HEAD(&b_ptr->cong_links);
566 INIT_LIST_HEAD(&b_ptr->links); 564 INIT_LIST_HEAD(&b_ptr->links);
567 if (m_ptr->bcast) { 565 b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
568 b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, 566 disc_domain);
569 bcast_scope);
570 }
571 spin_lock_init(&b_ptr->lock); 567 spin_lock_init(&b_ptr->lock);
572 write_unlock_bh(&tipc_net_lock); 568 write_unlock_bh(&tipc_net_lock);
573 info("Enabled bearer <%s>, discovery domain %s, priority %u\n", 569 info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
574 name, tipc_addr_string_fill(addr_string, bcast_scope), priority); 570 name, tipc_addr_string_fill(addr_string, disc_domain), priority);
575 return 0; 571 return 0;
576failed: 572failed:
577 write_unlock_bh(&tipc_net_lock); 573 write_unlock_bh(&tipc_net_lock);
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 255dea64f7bd..31d6172b20fd 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -70,7 +70,6 @@ struct tipc_bearer;
70 * @disable_bearer: routine which disables a bearer 70 * @disable_bearer: routine which disables a bearer
71 * @addr2str: routine which converts bearer's address to string form 71 * @addr2str: routine which converts bearer's address to string form
72 * @bcast_addr: media address used in broadcasting 72 * @bcast_addr: media address used in broadcasting
73 * @bcast: non-zero if media supports broadcasting [currently mandatory]
74 * @priority: default link (and bearer) priority 73 * @priority: default link (and bearer) priority
75 * @tolerance: default time (in ms) before declaring link failure 74 * @tolerance: default time (in ms) before declaring link failure
76 * @window: default window (in packets) before declaring link congestion 75 * @window: default window (in packets) before declaring link congestion
@@ -87,7 +86,6 @@ struct media {
87 char *(*addr2str)(struct tipc_media_addr *a, 86 char *(*addr2str)(struct tipc_media_addr *a,
88 char *str_buf, int str_size); 87 char *str_buf, int str_size);
89 struct tipc_media_addr bcast_addr; 88 struct tipc_media_addr bcast_addr;
90 int bcast;
91 u32 priority; 89 u32 priority;
92 u32 tolerance; 90 u32 tolerance;
93 u32 window; 91 u32 window;
@@ -105,7 +103,6 @@ struct media {
105 * @name: bearer name (format = media:interface) 103 * @name: bearer name (format = media:interface)
106 * @media: ptr to media structure associated with bearer 104 * @media: ptr to media structure associated with bearer
107 * @priority: default link priority for bearer 105 * @priority: default link priority for bearer
108 * @detect_scope: network address mask used during automatic link creation
109 * @identity: array index of this bearer within TIPC bearer array 106 * @identity: array index of this bearer within TIPC bearer array
110 * @link_req: ptr to (optional) structure making periodic link setup requests 107 * @link_req: ptr to (optional) structure making periodic link setup requests
111 * @links: list of non-congested links associated with bearer 108 * @links: list of non-congested links associated with bearer
@@ -128,7 +125,6 @@ struct tipc_bearer {
128 spinlock_t lock; 125 spinlock_t lock;
129 struct media *media; 126 struct media *media;
130 u32 priority; 127 u32 priority;
131 u32 detect_scope;
132 u32 identity; 128 u32 identity;
133 struct link_req *link_req; 129 struct link_req *link_req;
134 struct list_head links; 130 struct list_head links;
@@ -167,7 +163,7 @@ void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
167int tipc_block_bearer(const char *name); 163int tipc_block_bearer(const char *name);
168void tipc_continue(struct tipc_bearer *tb_ptr); 164void tipc_continue(struct tipc_bearer *tb_ptr);
169 165
170int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority); 166int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
171int tipc_disable_bearer(const char *name); 167int tipc_disable_bearer(const char *name);
172 168
173/* 169/*
diff --git a/net/tipc/config.c b/net/tipc/config.c
index e16750dcf3c1..b25a396b7e1e 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -2,7 +2,7 @@
2 * net/tipc/config.c: TIPC configuration management code 2 * net/tipc/config.c: TIPC configuration management code
3 * 3 *
4 * Copyright (c) 2002-2006, Ericsson AB 4 * Copyright (c) 2002-2006, Ericsson AB
5 * Copyright (c) 2004-2007, Wind River Systems 5 * Copyright (c) 2004-2007, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -148,7 +148,7 @@ static struct sk_buff *cfg_enable_bearer(void)
148 148
149 args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); 149 args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
150 if (tipc_enable_bearer(args->name, 150 if (tipc_enable_bearer(args->name,
151 ntohl(args->detect_scope), 151 ntohl(args->disc_domain),
152 ntohl(args->priority))) 152 ntohl(args->priority)))
153 return tipc_cfg_reply_error_string("unable to enable bearer"); 153 return tipc_cfg_reply_error_string("unable to enable bearer");
154 154
@@ -260,25 +260,6 @@ static struct sk_buff *cfg_set_max_ports(void)
260 return tipc_cfg_reply_none(); 260 return tipc_cfg_reply_none();
261} 261}
262 262
263static struct sk_buff *cfg_set_max_nodes(void)
264{
265 u32 value;
266
267 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
268 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
269 value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
270 if (value == tipc_max_nodes)
271 return tipc_cfg_reply_none();
272 if (value != delimit(value, 8, 2047))
273 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
274 " (max nodes must be 8-2047)");
275 if (tipc_mode == TIPC_NET_MODE)
276 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
277 " (cannot change max nodes once TIPC has joined a network)");
278 tipc_max_nodes = value;
279 return tipc_cfg_reply_none();
280}
281
282static struct sk_buff *cfg_set_netid(void) 263static struct sk_buff *cfg_set_netid(void)
283{ 264{
284 u32 value; 265 u32 value;
@@ -397,9 +378,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
397 case TIPC_CMD_SET_MAX_SUBSCR: 378 case TIPC_CMD_SET_MAX_SUBSCR:
398 rep_tlv_buf = cfg_set_max_subscriptions(); 379 rep_tlv_buf = cfg_set_max_subscriptions();
399 break; 380 break;
400 case TIPC_CMD_SET_MAX_NODES:
401 rep_tlv_buf = cfg_set_max_nodes();
402 break;
403 case TIPC_CMD_SET_NETID: 381 case TIPC_CMD_SET_NETID:
404 rep_tlv_buf = cfg_set_netid(); 382 rep_tlv_buf = cfg_set_netid();
405 break; 383 break;
@@ -415,9 +393,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
415 case TIPC_CMD_GET_MAX_SUBSCR: 393 case TIPC_CMD_GET_MAX_SUBSCR:
416 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); 394 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions);
417 break; 395 break;
418 case TIPC_CMD_GET_MAX_NODES:
419 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes);
420 break;
421 case TIPC_CMD_GET_NETID: 396 case TIPC_CMD_GET_NETID:
422 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); 397 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
423 break; 398 break;
@@ -431,6 +406,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
431 case TIPC_CMD_GET_MAX_SLAVES: 406 case TIPC_CMD_GET_MAX_SLAVES:
432 case TIPC_CMD_SET_MAX_CLUSTERS: 407 case TIPC_CMD_SET_MAX_CLUSTERS:
433 case TIPC_CMD_GET_MAX_CLUSTERS: 408 case TIPC_CMD_GET_MAX_CLUSTERS:
409 case TIPC_CMD_SET_MAX_NODES:
410 case TIPC_CMD_GET_MAX_NODES:
434 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 411 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
435 " (obsolete command)"); 412 " (obsolete command)");
436 break; 413 break;
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 2da1fc75ad65..c9a73e7763f6 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -41,10 +41,6 @@
41#include "config.h" 41#include "config.h"
42 42
43 43
44#ifndef CONFIG_TIPC_NODES
45#define CONFIG_TIPC_NODES 255
46#endif
47
48#ifndef CONFIG_TIPC_PORTS 44#ifndef CONFIG_TIPC_PORTS
49#define CONFIG_TIPC_PORTS 8191 45#define CONFIG_TIPC_PORTS 8191
50#endif 46#endif
@@ -64,7 +60,6 @@ const char tipc_alphabet[] =
64/* configurable TIPC parameters */ 60/* configurable TIPC parameters */
65 61
66u32 tipc_own_addr; 62u32 tipc_own_addr;
67int tipc_max_nodes;
68int tipc_max_ports; 63int tipc_max_ports;
69int tipc_max_subscriptions; 64int tipc_max_subscriptions;
70int tipc_max_publications; 65int tipc_max_publications;
@@ -192,7 +187,6 @@ static int __init tipc_init(void)
192 tipc_max_publications = 10000; 187 tipc_max_publications = 10000;
193 tipc_max_subscriptions = 2000; 188 tipc_max_subscriptions = 2000;
194 tipc_max_ports = CONFIG_TIPC_PORTS; 189 tipc_max_ports = CONFIG_TIPC_PORTS;
195 tipc_max_nodes = CONFIG_TIPC_NODES;
196 tipc_net_id = 4711; 190 tipc_net_id = 4711;
197 191
198 res = tipc_core_start(); 192 res = tipc_core_start();
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 37544d9f73e1..436dda1159d2 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -147,7 +147,6 @@ void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *);
147 */ 147 */
148 148
149extern u32 tipc_own_addr; 149extern u32 tipc_own_addr;
150extern int tipc_max_nodes;
151extern int tipc_max_ports; 150extern int tipc_max_ports;
152extern int tipc_max_subscriptions; 151extern int tipc_max_subscriptions;
153extern int tipc_max_publications; 152extern int tipc_max_publications;
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 09ce2318b89e..491eff56b9da 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -75,12 +75,12 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
75 u32 dest_domain, 75 u32 dest_domain,
76 struct tipc_bearer *b_ptr) 76 struct tipc_bearer *b_ptr)
77{ 77{
78 struct sk_buff *buf = tipc_buf_acquire(DSC_H_SIZE); 78 struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE);
79 struct tipc_msg *msg; 79 struct tipc_msg *msg;
80 80
81 if (buf) { 81 if (buf) {
82 msg = buf_msg(buf); 82 msg = buf_msg(buf);
83 tipc_msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain); 83 tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain);
84 msg_set_non_seq(msg, 1); 84 msg_set_non_seq(msg, 1);
85 msg_set_dest_domain(msg, dest_domain); 85 msg_set_dest_domain(msg, dest_domain);
86 msg_set_bc_netid(msg, tipc_net_id); 86 msg_set_bc_netid(msg, tipc_net_id);
@@ -119,17 +119,21 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
119 119
120void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) 120void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
121{ 121{
122 struct tipc_node *n_ptr;
122 struct link *link; 123 struct link *link;
123 struct tipc_media_addr media_addr; 124 struct tipc_media_addr media_addr, *addr;
125 struct sk_buff *rbuf;
124 struct tipc_msg *msg = buf_msg(buf); 126 struct tipc_msg *msg = buf_msg(buf);
125 u32 dest = msg_dest_domain(msg); 127 u32 dest = msg_dest_domain(msg);
126 u32 orig = msg_prevnode(msg); 128 u32 orig = msg_prevnode(msg);
127 u32 net_id = msg_bc_netid(msg); 129 u32 net_id = msg_bc_netid(msg);
128 u32 type = msg_type(msg); 130 u32 type = msg_type(msg);
131 int link_fully_up;
129 132
130 msg_get_media_addr(msg, &media_addr); 133 msg_get_media_addr(msg, &media_addr);
131 buf_discard(buf); 134 buf_discard(buf);
132 135
136 /* Validate discovery message from requesting node */
133 if (net_id != tipc_net_id) 137 if (net_id != tipc_net_id)
134 return; 138 return;
135 if (!tipc_addr_domain_valid(dest)) 139 if (!tipc_addr_domain_valid(dest))
@@ -143,57 +147,70 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
143 } 147 }
144 if (!tipc_in_scope(dest, tipc_own_addr)) 148 if (!tipc_in_scope(dest, tipc_own_addr))
145 return; 149 return;
146 if (in_own_cluster(orig)) { 150 if (!in_own_cluster(orig))
147 /* Always accept link here */ 151 return;
148 struct sk_buff *rbuf;
149 struct tipc_media_addr *addr;
150 struct tipc_node *n_ptr = tipc_node_find(orig);
151 int link_fully_up;
152
153 if (n_ptr == NULL) {
154 n_ptr = tipc_node_create(orig);
155 if (!n_ptr)
156 return;
157 }
158 spin_lock_bh(&n_ptr->lock);
159
160 /* Don't talk to neighbor during cleanup after last session */
161 152
162 if (n_ptr->cleanup_required) { 153 /* Locate structure corresponding to requesting node */
163 spin_unlock_bh(&n_ptr->lock); 154 n_ptr = tipc_node_find(orig);
155 if (!n_ptr) {
156 n_ptr = tipc_node_create(orig);
157 if (!n_ptr)
164 return; 158 return;
165 } 159 }
160 tipc_node_lock(n_ptr);
161
162 /* Don't talk to neighbor during cleanup after last session */
163 if (n_ptr->cleanup_required) {
164 tipc_node_unlock(n_ptr);
165 return;
166 }
167
168 link = n_ptr->links[b_ptr->identity];
166 169
167 link = n_ptr->links[b_ptr->identity]; 170 /* Create a link endpoint for this bearer, if necessary */
171 if (!link) {
172 link = tipc_link_create(n_ptr, b_ptr, &media_addr);
168 if (!link) { 173 if (!link) {
169 link = tipc_link_create(b_ptr, orig, &media_addr); 174 tipc_node_unlock(n_ptr);
170 if (!link) { 175 return;
171 spin_unlock_bh(&n_ptr->lock);
172 return;
173 }
174 }
175 addr = &link->media_addr;
176 if (memcmp(addr, &media_addr, sizeof(*addr))) {
177 if (tipc_link_is_up(link) || (!link->started)) {
178 disc_dupl_alert(b_ptr, orig, &media_addr);
179 spin_unlock_bh(&n_ptr->lock);
180 return;
181 }
182 warn("Resetting link <%s>, peer interface address changed\n",
183 link->name);
184 memcpy(addr, &media_addr, sizeof(*addr));
185 tipc_link_reset(link);
186 } 176 }
187 link_fully_up = link_working_working(link); 177 }
188 spin_unlock_bh(&n_ptr->lock); 178
189 if ((type == DSC_RESP_MSG) || link_fully_up) 179 /*
180 * Ensure requesting node's media address is correct
181 *
182 * If media address doesn't match and the link is working, reject the
183 * request (must be from a duplicate node).
184 *
185 * If media address doesn't match and the link is not working, accept
186 * the new media address and reset the link to ensure it starts up
187 * cleanly.
188 */
189 addr = &link->media_addr;
190 if (memcmp(addr, &media_addr, sizeof(*addr))) {
191 if (tipc_link_is_up(link) || (!link->started)) {
192 disc_dupl_alert(b_ptr, orig, &media_addr);
193 tipc_node_unlock(n_ptr);
190 return; 194 return;
195 }
196 warn("Resetting link <%s>, peer interface address changed\n",
197 link->name);
198 memcpy(addr, &media_addr, sizeof(*addr));
199 tipc_link_reset(link);
200 }
201
202 /* Accept discovery message & send response, if necessary */
203 link_fully_up = link_working_working(link);
204
205 if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {
191 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); 206 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
192 if (rbuf != NULL) { 207 if (rbuf) {
193 b_ptr->media->send_msg(rbuf, b_ptr, &media_addr); 208 b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
194 buf_discard(rbuf); 209 buf_discard(rbuf);
195 } 210 }
196 } 211 }
212
213 tipc_node_unlock(n_ptr);
197} 214}
198 215
199/** 216/**
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 89fbb6d6e956..43639ff1cbec 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -293,19 +293,35 @@ static void link_set_timer(struct link *l_ptr, u32 time)
293 293
294/** 294/**
295 * tipc_link_create - create a new link 295 * tipc_link_create - create a new link
296 * @n_ptr: pointer to associated node
296 * @b_ptr: pointer to associated bearer 297 * @b_ptr: pointer to associated bearer
297 * @peer: network address of node at other end of link
298 * @media_addr: media address to use when sending messages over link 298 * @media_addr: media address to use when sending messages over link
299 * 299 *
300 * Returns pointer to link. 300 * Returns pointer to link.
301 */ 301 */
302 302
303struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, 303struct link *tipc_link_create(struct tipc_node *n_ptr,
304 struct tipc_bearer *b_ptr,
304 const struct tipc_media_addr *media_addr) 305 const struct tipc_media_addr *media_addr)
305{ 306{
306 struct link *l_ptr; 307 struct link *l_ptr;
307 struct tipc_msg *msg; 308 struct tipc_msg *msg;
308 char *if_name; 309 char *if_name;
310 char addr_string[16];
311 u32 peer = n_ptr->addr;
312
313 if (n_ptr->link_cnt >= 2) {
314 tipc_addr_string_fill(addr_string, n_ptr->addr);
315 err("Attempt to establish third link to %s\n", addr_string);
316 return NULL;
317 }
318
319 if (n_ptr->links[b_ptr->identity]) {
320 tipc_addr_string_fill(addr_string, n_ptr->addr);
321 err("Attempt to establish second link on <%s> to %s\n",
322 b_ptr->name, addr_string);
323 return NULL;
324 }
309 325
310 l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC); 326 l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC);
311 if (!l_ptr) { 327 if (!l_ptr) {
@@ -322,6 +338,7 @@ struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer,
322 tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); 338 tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
323 /* note: peer i/f is appended to link name by reset/activate */ 339 /* note: peer i/f is appended to link name by reset/activate */
324 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); 340 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
341 l_ptr->owner = n_ptr;
325 l_ptr->checkpoint = 1; 342 l_ptr->checkpoint = 1;
326 l_ptr->b_ptr = b_ptr; 343 l_ptr->b_ptr = b_ptr;
327 link_set_supervision_props(l_ptr, b_ptr->media->tolerance); 344 link_set_supervision_props(l_ptr, b_ptr->media->tolerance);
@@ -345,11 +362,7 @@ struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer,
345 362
346 link_reset_statistics(l_ptr); 363 link_reset_statistics(l_ptr);
347 364
348 l_ptr->owner = tipc_node_attach_link(l_ptr); 365 tipc_node_attach_link(n_ptr, l_ptr);
349 if (!l_ptr->owner) {
350 kfree(l_ptr);
351 return NULL;
352 }
353 366
354 k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); 367 k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
355 list_add_tail(&l_ptr->link_list, &b_ptr->links); 368 list_add_tail(&l_ptr->link_list, &b_ptr->links);
@@ -548,7 +561,7 @@ void tipc_link_reset(struct link *l_ptr)
548 tipc_node_link_down(l_ptr->owner, l_ptr); 561 tipc_node_link_down(l_ptr->owner, l_ptr);
549 tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); 562 tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
550 563
551 if (was_active_link && tipc_node_has_active_links(l_ptr->owner) && 564 if (was_active_link && tipc_node_active_links(l_ptr->owner) &&
552 l_ptr->owner->permit_changeover) { 565 l_ptr->owner->permit_changeover) {
553 l_ptr->reset_checkpoint = checkpoint; 566 l_ptr->reset_checkpoint = checkpoint;
554 l_ptr->exp_msg_count = START_CHANGEOVER; 567 l_ptr->exp_msg_count = START_CHANGEOVER;
@@ -1733,10 +1746,6 @@ deliver:
1733 tipc_node_unlock(n_ptr); 1746 tipc_node_unlock(n_ptr);
1734 tipc_link_recv_bundle(buf); 1747 tipc_link_recv_bundle(buf);
1735 continue; 1748 continue;
1736 case ROUTE_DISTRIBUTOR:
1737 tipc_node_unlock(n_ptr);
1738 buf_discard(buf);
1739 continue;
1740 case NAME_DISTRIBUTOR: 1749 case NAME_DISTRIBUTOR:
1741 tipc_node_unlock(n_ptr); 1750 tipc_node_unlock(n_ptr);
1742 tipc_named_recv(buf); 1751 tipc_named_recv(buf);
@@ -1763,6 +1772,10 @@ deliver:
1763 goto protocol_check; 1772 goto protocol_check;
1764 } 1773 }
1765 break; 1774 break;
1775 default:
1776 buf_discard(buf);
1777 buf = NULL;
1778 break;
1766 } 1779 }
1767 } 1780 }
1768 tipc_node_unlock(n_ptr); 1781 tipc_node_unlock(n_ptr);
@@ -1898,6 +1911,7 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
1898 struct sk_buff *buf = NULL; 1911 struct sk_buff *buf = NULL;
1899 struct tipc_msg *msg = l_ptr->pmsg; 1912 struct tipc_msg *msg = l_ptr->pmsg;
1900 u32 msg_size = sizeof(l_ptr->proto_msg); 1913 u32 msg_size = sizeof(l_ptr->proto_msg);
1914 int r_flag;
1901 1915
1902 if (link_blocked(l_ptr)) 1916 if (link_blocked(l_ptr))
1903 return; 1917 return;
@@ -1954,10 +1968,8 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
1954 msg_set_max_pkt(msg, l_ptr->max_pkt_target); 1968 msg_set_max_pkt(msg, l_ptr->max_pkt_target);
1955 } 1969 }
1956 1970
1957 if (tipc_node_has_redundant_links(l_ptr->owner)) 1971 r_flag = (l_ptr->owner->working_links > tipc_link_is_up(l_ptr));
1958 msg_set_redundant_link(msg); 1972 msg_set_redundant_link(msg, r_flag);
1959 else
1960 msg_clear_redundant_link(msg);
1961 msg_set_linkprio(msg, l_ptr->priority); 1973 msg_set_linkprio(msg, l_ptr->priority);
1962 1974
1963 /* Ensure sequence number will not fit : */ 1975 /* Ensure sequence number will not fit : */
@@ -1977,7 +1989,6 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
1977 skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); 1989 skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg));
1978 return; 1990 return;
1979 } 1991 }
1980 msg_set_timestamp(msg, jiffies_to_msecs(jiffies));
1981 1992
1982 /* Message can be sent */ 1993 /* Message can be sent */
1983 1994
@@ -2065,7 +2076,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf)
2065 l_ptr->peer_bearer_id = msg_bearer_id(msg); 2076 l_ptr->peer_bearer_id = msg_bearer_id(msg);
2066 2077
2067 /* Synchronize broadcast sequence numbers */ 2078 /* Synchronize broadcast sequence numbers */
2068 if (!tipc_node_has_redundant_links(l_ptr->owner)) 2079 if (!tipc_node_redundant_links(l_ptr->owner))
2069 l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); 2080 l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg));
2070 break; 2081 break;
2071 case STATE_MSG: 2082 case STATE_MSG:
@@ -2412,9 +2423,6 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
2412 else 2423 else
2413 destaddr = msg_destnode(inmsg); 2424 destaddr = msg_destnode(inmsg);
2414 2425
2415 if (msg_routed(inmsg))
2416 msg_set_prevnode(inmsg, tipc_own_addr);
2417
2418 /* Prepare reusable fragment header: */ 2426 /* Prepare reusable fragment header: */
2419 2427
2420 tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, 2428 tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
diff --git a/net/tipc/link.h b/net/tipc/link.h
index a7794e7ede29..e6a30dbe1aaa 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -207,7 +207,8 @@ struct link {
207 207
208struct tipc_port; 208struct tipc_port;
209 209
210struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, 210struct link *tipc_link_create(struct tipc_node *n_ptr,
211 struct tipc_bearer *b_ptr,
211 const struct tipc_media_addr *media_addr); 212 const struct tipc_media_addr *media_addr);
212void tipc_link_delete(struct link *l_ptr); 213void tipc_link_delete(struct link *l_ptr);
213void tipc_link_changeover(struct link *l_ptr); 214void tipc_link_changeover(struct link *l_ptr);
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 0787e12423b8..6d92d17e7fb5 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -192,8 +192,6 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
192 default: 192 default:
193 tipc_printf(buf, "UNKNOWN TYPE %u", msg_type(msg)); 193 tipc_printf(buf, "UNKNOWN TYPE %u", msg_type(msg));
194 } 194 }
195 if (msg_routed(msg) && !msg_non_seq(msg))
196 tipc_printf(buf, "ROUT:");
197 if (msg_reroute_cnt(msg)) 195 if (msg_reroute_cnt(msg))
198 tipc_printf(buf, "REROUTED(%u):", 196 tipc_printf(buf, "REROUTED(%u):",
199 msg_reroute_cnt(msg)); 197 msg_reroute_cnt(msg));
@@ -210,8 +208,6 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
210 default: 208 default:
211 tipc_printf(buf, "UNKNOWN:%x", msg_type(msg)); 209 tipc_printf(buf, "UNKNOWN:%x", msg_type(msg));
212 } 210 }
213 if (msg_routed(msg))
214 tipc_printf(buf, "ROUT:");
215 if (msg_reroute_cnt(msg)) 211 if (msg_reroute_cnt(msg))
216 tipc_printf(buf, "REROUTED(%u):", 212 tipc_printf(buf, "REROUTED(%u):",
217 msg_reroute_cnt(msg)); 213 msg_reroute_cnt(msg));
@@ -232,13 +228,10 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
232 default: 228 default:
233 tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); 229 tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
234 } 230 }
235 if (msg_routed(msg))
236 tipc_printf(buf, "ROUT:");
237 if (msg_reroute_cnt(msg)) 231 if (msg_reroute_cnt(msg))
238 tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg)); 232 tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg));
239 break; 233 break;
240 case LINK_PROTOCOL: 234 case LINK_PROTOCOL:
241 tipc_printf(buf, "PROT:TIM(%u):", msg_timestamp(msg));
242 switch (msg_type(msg)) { 235 switch (msg_type(msg)) {
243 case STATE_MSG: 236 case STATE_MSG:
244 tipc_printf(buf, "STATE:"); 237 tipc_printf(buf, "STATE:");
@@ -275,33 +268,6 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
275 tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); 268 tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
276 } 269 }
277 break; 270 break;
278 case ROUTE_DISTRIBUTOR:
279 tipc_printf(buf, "ROUTING_MNG:");
280 switch (msg_type(msg)) {
281 case EXT_ROUTING_TABLE:
282 tipc_printf(buf, "EXT_TBL:");
283 tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
284 break;
285 case LOCAL_ROUTING_TABLE:
286 tipc_printf(buf, "LOCAL_TBL:");
287 tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
288 break;
289 case SLAVE_ROUTING_TABLE:
290 tipc_printf(buf, "DP_TBL:");
291 tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
292 break;
293 case ROUTE_ADDITION:
294 tipc_printf(buf, "ADD:");
295 tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
296 break;
297 case ROUTE_REMOVAL:
298 tipc_printf(buf, "REMOVE:");
299 tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
300 break;
301 default:
302 tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
303 }
304 break;
305 case LINK_CONFIG: 271 case LINK_CONFIG:
306 tipc_printf(buf, "CFG:"); 272 tipc_printf(buf, "CFG:");
307 switch (msg_type(msg)) { 273 switch (msg_type(msg)) {
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 9d643a1b7d22..de02339fc175 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -421,13 +421,6 @@ static inline int msg_is_dest(struct tipc_msg *m, u32 d)
421 return msg_short(m) || (msg_destnode(m) == d); 421 return msg_short(m) || (msg_destnode(m) == d);
422} 422}
423 423
424static inline u32 msg_routed(struct tipc_msg *m)
425{
426 if (likely(msg_short(m)))
427 return 0;
428 return (msg_destnode(m) ^ msg_orignode(m)) >> 11;
429}
430
431static inline u32 msg_nametype(struct tipc_msg *m) 424static inline u32 msg_nametype(struct tipc_msg *m)
432{ 425{
433 return msg_word(m, 8); 426 return msg_word(m, 8);
@@ -438,16 +431,6 @@ static inline void msg_set_nametype(struct tipc_msg *m, u32 n)
438 msg_set_word(m, 8, n); 431 msg_set_word(m, 8, n);
439} 432}
440 433
441static inline void msg_set_timestamp(struct tipc_msg *m, u32 n)
442{
443 msg_set_word(m, 8, n);
444}
445
446static inline u32 msg_timestamp(struct tipc_msg *m)
447{
448 return msg_word(m, 8);
449}
450
451static inline u32 msg_nameinst(struct tipc_msg *m) 434static inline u32 msg_nameinst(struct tipc_msg *m)
452{ 435{
453 return msg_word(m, 9); 436 return msg_word(m, 9);
@@ -535,7 +518,6 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
535#define NAME_DISTRIBUTOR 11 518#define NAME_DISTRIBUTOR 11
536#define MSG_FRAGMENTER 12 519#define MSG_FRAGMENTER 12
537#define LINK_CONFIG 13 520#define LINK_CONFIG 13
538#define DSC_H_SIZE 40
539 521
540/* 522/*
541 * Connection management protocol messages 523 * Connection management protocol messages
@@ -729,14 +711,9 @@ static inline u32 msg_redundant_link(struct tipc_msg *m)
729 return msg_bits(m, 5, 12, 0x1); 711 return msg_bits(m, 5, 12, 0x1);
730} 712}
731 713
732static inline void msg_set_redundant_link(struct tipc_msg *m) 714static inline void msg_set_redundant_link(struct tipc_msg *m, u32 r)
733{ 715{
734 msg_set_bits(m, 5, 12, 0x1, 1); 716 msg_set_bits(m, 5, 12, 0x1, r);
735}
736
737static inline void msg_clear_redundant_link(struct tipc_msg *m)
738{
739 msg_set_bits(m, 5, 12, 0x1, 0);
740} 717}
741 718
742 719
@@ -785,21 +762,6 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
785} 762}
786 763
787/* 764/*
788 * Routing table message data
789 */
790
791
792static inline u32 msg_remote_node(struct tipc_msg *m)
793{
794 return msg_word(m, msg_hdr_sz(m)/4);
795}
796
797static inline void msg_set_remote_node(struct tipc_msg *m, u32 a)
798{
799 msg_set_word(m, msg_hdr_sz(m)/4, a);
800}
801
802/*
803 * Segmentation message types 765 * Segmentation message types
804 */ 766 */
805 767
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 483c226c9581..c9fa6dfcf287 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -2,7 +2,7 @@
2 * net/tipc/name_distr.c: TIPC name distribution code 2 * net/tipc/name_distr.c: TIPC name distribution code
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -109,11 +109,9 @@ static void named_cluster_distribute(struct sk_buff *buf)
109{ 109{
110 struct sk_buff *buf_copy; 110 struct sk_buff *buf_copy;
111 struct tipc_node *n_ptr; 111 struct tipc_node *n_ptr;
112 u32 n_num;
113 112
114 for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { 113 list_for_each_entry(n_ptr, &tipc_node_list, list) {
115 n_ptr = tipc_net.nodes[n_num]; 114 if (tipc_node_active_links(n_ptr)) {
116 if (n_ptr && tipc_node_has_active_links(n_ptr)) {
117 buf_copy = skb_copy(buf, GFP_ATOMIC); 115 buf_copy = skb_copy(buf, GFP_ATOMIC);
118 if (!buf_copy) 116 if (!buf_copy)
119 break; 117 break;
@@ -214,17 +212,16 @@ exit:
214} 212}
215 213
216/** 214/**
217 * node_is_down - remove publication associated with a failed node 215 * named_purge_publ - remove publication associated with a failed node
218 * 216 *
219 * Invoked for each publication issued by a newly failed node. 217 * Invoked for each publication issued by a newly failed node.
220 * Removes publication structure from name table & deletes it. 218 * Removes publication structure from name table & deletes it.
221 * In rare cases the link may have come back up again when this 219 * In rare cases the link may have come back up again when this
222 * function is called, and we have two items representing the same 220 * function is called, and we have two items representing the same
223 * publication. Nudge this item's key to distinguish it from the other. 221 * publication. Nudge this item's key to distinguish it from the other.
224 * (Note: Publication's node subscription is already unsubscribed.)
225 */ 222 */
226 223
227static void node_is_down(struct publication *publ) 224static void named_purge_publ(struct publication *publ)
228{ 225{
229 struct publication *p; 226 struct publication *p;
230 227
@@ -232,6 +229,8 @@ static void node_is_down(struct publication *publ)
232 publ->key += 1222345; 229 publ->key += 1222345;
233 p = tipc_nametbl_remove_publ(publ->type, publ->lower, 230 p = tipc_nametbl_remove_publ(publ->type, publ->lower,
234 publ->node, publ->ref, publ->key); 231 publ->node, publ->ref, publ->key);
232 if (p)
233 tipc_nodesub_unsubscribe(&p->subscr);
235 write_unlock_bh(&tipc_nametbl_lock); 234 write_unlock_bh(&tipc_nametbl_lock);
236 235
237 if (p != publ) { 236 if (p != publ) {
@@ -268,7 +267,8 @@ void tipc_named_recv(struct sk_buff *buf)
268 tipc_nodesub_subscribe(&publ->subscr, 267 tipc_nodesub_subscribe(&publ->subscr,
269 msg_orignode(msg), 268 msg_orignode(msg),
270 publ, 269 publ,
271 (net_ev_handler)node_is_down); 270 (net_ev_handler)
271 named_purge_publ);
272 } 272 }
273 } else if (msg_type(msg) == WITHDRAWAL) { 273 } else if (msg_type(msg) == WITHDRAWAL) {
274 publ = tipc_nametbl_remove_publ(ntohl(item->type), 274 publ = tipc_nametbl_remove_publ(ntohl(item->type),
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 9bacfd00b91e..8fbc7e6ae3df 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -2,7 +2,7 @@
2 * net/tipc/net.c: TIPC network routing code 2 * net/tipc/net.c: TIPC network routing code
3 * 3 *
4 * Copyright (c) 1995-2006, Ericsson AB 4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
39#include "name_distr.h" 39#include "name_distr.h"
40#include "subscr.h" 40#include "subscr.h"
41#include "port.h" 41#include "port.h"
42#include "node.h"
42#include "config.h" 43#include "config.h"
43 44
44/* 45/*
@@ -108,26 +109,6 @@
108*/ 109*/
109 110
110DEFINE_RWLOCK(tipc_net_lock); 111DEFINE_RWLOCK(tipc_net_lock);
111struct network tipc_net;
112
113static int net_start(void)
114{
115 tipc_net.nodes = kcalloc(tipc_max_nodes + 1,
116 sizeof(*tipc_net.nodes), GFP_ATOMIC);
117 tipc_net.highest_node = 0;
118
119 return tipc_net.nodes ? 0 : -ENOMEM;
120}
121
122static void net_stop(void)
123{
124 u32 n_num;
125
126 for (n_num = 1; n_num <= tipc_net.highest_node; n_num++)
127 tipc_node_delete(tipc_net.nodes[n_num]);
128 kfree(tipc_net.nodes);
129 tipc_net.nodes = NULL;
130}
131 112
132static void net_route_named_msg(struct sk_buff *buf) 113static void net_route_named_msg(struct sk_buff *buf)
133{ 114{
@@ -217,9 +198,6 @@ int tipc_net_start(u32 addr)
217 tipc_named_reinit(); 198 tipc_named_reinit();
218 tipc_port_reinit(); 199 tipc_port_reinit();
219 200
220 res = net_start();
221 if (res)
222 return res;
223 res = tipc_bclink_init(); 201 res = tipc_bclink_init();
224 if (res) 202 if (res)
225 return res; 203 return res;
@@ -235,14 +213,16 @@ int tipc_net_start(u32 addr)
235 213
236void tipc_net_stop(void) 214void tipc_net_stop(void)
237{ 215{
216 struct tipc_node *node, *t_node;
217
238 if (tipc_mode != TIPC_NET_MODE) 218 if (tipc_mode != TIPC_NET_MODE)
239 return; 219 return;
240 write_lock_bh(&tipc_net_lock); 220 write_lock_bh(&tipc_net_lock);
241 tipc_bearer_stop(); 221 tipc_bearer_stop();
242 tipc_mode = TIPC_NODE_MODE; 222 tipc_mode = TIPC_NODE_MODE;
243 tipc_bclink_stop(); 223 tipc_bclink_stop();
244 net_stop(); 224 list_for_each_entry_safe(node, t_node, &tipc_node_list, list);
225 tipc_node_delete(node);
245 write_unlock_bh(&tipc_net_lock); 226 write_unlock_bh(&tipc_net_lock);
246 info("Left network mode\n"); 227 info("Left network mode\n");
247} 228}
248
diff --git a/net/tipc/net.h b/net/tipc/net.h
index 4ae59ad04893..9eb4b9e220eb 100644
--- a/net/tipc/net.h
+++ b/net/tipc/net.h
@@ -2,7 +2,7 @@
2 * net/tipc/net.h: Include file for TIPC network routing code 2 * net/tipc/net.h: Include file for TIPC network routing code
3 * 3 *
4 * Copyright (c) 1995-2006, Ericsson AB 4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -37,23 +37,6 @@
37#ifndef _TIPC_NET_H 37#ifndef _TIPC_NET_H
38#define _TIPC_NET_H 38#define _TIPC_NET_H
39 39
40struct tipc_node;
41
42/**
43 * struct network - TIPC network structure
44 * @nodes: array of pointers to all nodes within cluster
45 * @highest_node: id of highest numbered node within cluster
46 * @links: number of (unicast) links to cluster
47 */
48
49struct network {
50 struct tipc_node **nodes;
51 u32 highest_node;
52 u32 links;
53};
54
55
56extern struct network tipc_net;
57extern rwlock_t tipc_net_lock; 40extern rwlock_t tipc_net_lock;
58 41
59void tipc_net_route_msg(struct sk_buff *buf); 42void tipc_net_route_msg(struct sk_buff *buf);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index e4dba1dfb6ea..2d106ef4fa4c 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -44,9 +44,33 @@ static void node_established_contact(struct tipc_node *n_ptr);
44 44
45static DEFINE_SPINLOCK(node_create_lock); 45static DEFINE_SPINLOCK(node_create_lock);
46 46
47static struct hlist_head node_htable[NODE_HTABLE_SIZE];
48LIST_HEAD(tipc_node_list);
49static u32 tipc_num_nodes;
50
51static atomic_t tipc_num_links = ATOMIC_INIT(0);
47u32 tipc_own_tag; 52u32 tipc_own_tag;
48 53
49/** 54/**
55 * tipc_node_find - locate specified node object, if it exists
56 */
57
58struct tipc_node *tipc_node_find(u32 addr)
59{
60 struct tipc_node *node;
61 struct hlist_node *pos;
62
63 if (unlikely(!in_own_cluster(addr)))
64 return NULL;
65
66 hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) {
67 if (node->addr == addr)
68 return node;
69 }
70 return NULL;
71}
72
73/**
50 * tipc_node_create - create neighboring node 74 * tipc_node_create - create neighboring node
51 * 75 *
52 * Currently, this routine is called by neighbor discovery code, which holds 76 * Currently, this routine is called by neighbor discovery code, which holds
@@ -58,8 +82,7 @@ u32 tipc_own_tag;
58 82
59struct tipc_node *tipc_node_create(u32 addr) 83struct tipc_node *tipc_node_create(u32 addr)
60{ 84{
61 struct tipc_node *n_ptr; 85 struct tipc_node *n_ptr, *temp_node;
62 u32 n_num;
63 86
64 spin_lock_bh(&node_create_lock); 87 spin_lock_bh(&node_create_lock);
65 88
@@ -78,12 +101,19 @@ struct tipc_node *tipc_node_create(u32 addr)
78 101
79 n_ptr->addr = addr; 102 n_ptr->addr = addr;
80 spin_lock_init(&n_ptr->lock); 103 spin_lock_init(&n_ptr->lock);
104 INIT_HLIST_NODE(&n_ptr->hash);
105 INIT_LIST_HEAD(&n_ptr->list);
81 INIT_LIST_HEAD(&n_ptr->nsub); 106 INIT_LIST_HEAD(&n_ptr->nsub);
82 107
83 n_num = tipc_node(addr); 108 hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]);
84 tipc_net.nodes[n_num] = n_ptr; 109
85 if (n_num > tipc_net.highest_node) 110 list_for_each_entry(temp_node, &tipc_node_list, list) {
86 tipc_net.highest_node = n_num; 111 if (n_ptr->addr < temp_node->addr)
112 break;
113 }
114 list_add_tail(&n_ptr->list, &temp_node->list);
115
116 tipc_num_nodes++;
87 117
88 spin_unlock_bh(&node_create_lock); 118 spin_unlock_bh(&node_create_lock);
89 return n_ptr; 119 return n_ptr;
@@ -91,18 +121,11 @@ struct tipc_node *tipc_node_create(u32 addr)
91 121
92void tipc_node_delete(struct tipc_node *n_ptr) 122void tipc_node_delete(struct tipc_node *n_ptr)
93{ 123{
94 u32 n_num; 124 list_del(&n_ptr->list);
95 125 hlist_del(&n_ptr->hash);
96 if (!n_ptr)
97 return;
98
99 n_num = tipc_node(n_ptr->addr);
100 tipc_net.nodes[n_num] = NULL;
101 kfree(n_ptr); 126 kfree(n_ptr);
102 127
103 while (!tipc_net.nodes[tipc_net.highest_node]) 128 tipc_num_nodes--;
104 if (--tipc_net.highest_node == 0)
105 break;
106} 129}
107 130
108 131
@@ -200,54 +223,32 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr)
200 node_lost_contact(n_ptr); 223 node_lost_contact(n_ptr);
201} 224}
202 225
203int tipc_node_has_active_links(struct tipc_node *n_ptr) 226int tipc_node_active_links(struct tipc_node *n_ptr)
204{ 227{
205 return n_ptr->active_links[0] != NULL; 228 return n_ptr->active_links[0] != NULL;
206} 229}
207 230
208int tipc_node_has_redundant_links(struct tipc_node *n_ptr) 231int tipc_node_redundant_links(struct tipc_node *n_ptr)
209{ 232{
210 return n_ptr->working_links > 1; 233 return n_ptr->working_links > 1;
211} 234}
212 235
213int tipc_node_is_up(struct tipc_node *n_ptr) 236int tipc_node_is_up(struct tipc_node *n_ptr)
214{ 237{
215 return tipc_node_has_active_links(n_ptr); 238 return tipc_node_active_links(n_ptr);
216} 239}
217 240
218struct tipc_node *tipc_node_attach_link(struct link *l_ptr) 241void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr)
219{ 242{
220 struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr); 243 n_ptr->links[l_ptr->b_ptr->identity] = l_ptr;
221 244 atomic_inc(&tipc_num_links);
222 if (!n_ptr) 245 n_ptr->link_cnt++;
223 n_ptr = tipc_node_create(l_ptr->addr);
224 if (n_ptr) {
225 u32 bearer_id = l_ptr->b_ptr->identity;
226 char addr_string[16];
227
228 if (n_ptr->link_cnt >= 2) {
229 err("Attempt to create third link to %s\n",
230 tipc_addr_string_fill(addr_string, n_ptr->addr));
231 return NULL;
232 }
233
234 if (!n_ptr->links[bearer_id]) {
235 n_ptr->links[bearer_id] = l_ptr;
236 tipc_net.links++;
237 n_ptr->link_cnt++;
238 return n_ptr;
239 }
240 err("Attempt to establish second link on <%s> to %s\n",
241 l_ptr->b_ptr->name,
242 tipc_addr_string_fill(addr_string, l_ptr->addr));
243 }
244 return NULL;
245} 246}
246 247
247void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) 248void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
248{ 249{
249 n_ptr->links[l_ptr->b_ptr->identity] = NULL; 250 n_ptr->links[l_ptr->b_ptr->identity] = NULL;
250 tipc_net.links--; 251 atomic_dec(&tipc_num_links);
251 n_ptr->link_cnt--; 252 n_ptr->link_cnt--;
252} 253}
253 254
@@ -327,7 +328,6 @@ static void node_cleanup_finished(unsigned long node_addr)
327 328
328static void node_lost_contact(struct tipc_node *n_ptr) 329static void node_lost_contact(struct tipc_node *n_ptr)
329{ 330{
330 struct tipc_node_subscr *ns, *tns;
331 char addr_string[16]; 331 char addr_string[16];
332 u32 i; 332 u32 i;
333 333
@@ -365,12 +365,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
365 } 365 }
366 366
367 /* Notify subscribers */ 367 /* Notify subscribers */
368 list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { 368 tipc_nodesub_notify(n_ptr);
369 ns->node = NULL;
370 list_del_init(&ns->nodesub_list);
371 tipc_k_signal((Handler)ns->handle_node_down,
372 (unsigned long)ns->usr_handle);
373 }
374 369
375 /* Prevent re-contact with node until all cleanup is done */ 370 /* Prevent re-contact with node until all cleanup is done */
376 371
@@ -385,7 +380,6 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
385 struct tipc_node *n_ptr; 380 struct tipc_node *n_ptr;
386 struct tipc_node_info node_info; 381 struct tipc_node_info node_info;
387 u32 payload_size; 382 u32 payload_size;
388 u32 n_num;
389 383
390 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) 384 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
391 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 385 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -396,15 +390,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
396 " (network address)"); 390 " (network address)");
397 391
398 read_lock_bh(&tipc_net_lock); 392 read_lock_bh(&tipc_net_lock);
399 if (!tipc_net.nodes) { 393 if (!tipc_num_nodes) {
400 read_unlock_bh(&tipc_net_lock); 394 read_unlock_bh(&tipc_net_lock);
401 return tipc_cfg_reply_none(); 395 return tipc_cfg_reply_none();
402 } 396 }
403 397
404 /* For now, get space for all other nodes */ 398 /* For now, get space for all other nodes */
405 399
406 payload_size = TLV_SPACE(sizeof(node_info)) * 400 payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
407 (tipc_net.highest_node - 1);
408 if (payload_size > 32768u) { 401 if (payload_size > 32768u) {
409 read_unlock_bh(&tipc_net_lock); 402 read_unlock_bh(&tipc_net_lock);
410 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 403 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
@@ -418,9 +411,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
418 411
419 /* Add TLVs for all nodes in scope */ 412 /* Add TLVs for all nodes in scope */
420 413
421 for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { 414 list_for_each_entry(n_ptr, &tipc_node_list, list) {
422 n_ptr = tipc_net.nodes[n_num]; 415 if (!tipc_in_scope(domain, n_ptr->addr))
423 if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
424 continue; 416 continue;
425 node_info.addr = htonl(n_ptr->addr); 417 node_info.addr = htonl(n_ptr->addr);
426 node_info.up = htonl(tipc_node_is_up(n_ptr)); 418 node_info.up = htonl(tipc_node_is_up(n_ptr));
@@ -439,7 +431,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
439 struct tipc_node *n_ptr; 431 struct tipc_node *n_ptr;
440 struct tipc_link_info link_info; 432 struct tipc_link_info link_info;
441 u32 payload_size; 433 u32 payload_size;
442 u32 n_num;
443 434
444 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) 435 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
445 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 436 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -456,7 +447,8 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
456 447
457 /* Get space for all unicast links + multicast link */ 448 /* Get space for all unicast links + multicast link */
458 449
459 payload_size = TLV_SPACE(sizeof(link_info)) * (tipc_net.links + 1); 450 payload_size = TLV_SPACE(sizeof(link_info)) *
451 (atomic_read(&tipc_num_links) + 1);
460 if (payload_size > 32768u) { 452 if (payload_size > 32768u) {
461 read_unlock_bh(&tipc_net_lock); 453 read_unlock_bh(&tipc_net_lock);
462 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 454 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
@@ -470,18 +462,17 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
470 462
471 /* Add TLV for broadcast link */ 463 /* Add TLV for broadcast link */
472 464
473 link_info.dest = htonl(tipc_own_addr & 0xfffff00); 465 link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));
474 link_info.up = htonl(1); 466 link_info.up = htonl(1);
475 strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); 467 strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);
476 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); 468 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
477 469
478 /* Add TLVs for any other links in scope */ 470 /* Add TLVs for any other links in scope */
479 471
480 for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { 472 list_for_each_entry(n_ptr, &tipc_node_list, list) {
481 u32 i; 473 u32 i;
482 474
483 n_ptr = tipc_net.nodes[n_num]; 475 if (!tipc_in_scope(domain, n_ptr->addr))
484 if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
485 continue; 476 continue;
486 tipc_node_lock(n_ptr); 477 tipc_node_lock(n_ptr);
487 for (i = 0; i < MAX_BEARERS; i++) { 478 for (i = 0; i < MAX_BEARERS; i++) {
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 206a8efa410e..5c61afc7a0b9 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -2,7 +2,7 @@
2 * net/tipc/node.h: Include file for TIPC node management routines 2 * net/tipc/node.h: Include file for TIPC node management routines
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,8 @@
46 * struct tipc_node - TIPC node structure 46 * struct tipc_node - TIPC node structure
47 * @addr: network address of node 47 * @addr: network address of node
48 * @lock: spinlock governing access to structure 48 * @lock: spinlock governing access to structure
49 * @next: pointer to next node in sorted list of cluster's nodes 49 * @hash: links to adjacent nodes in unsorted hash chain
50 * @list: links to adjacent nodes in sorted list of cluster's nodes
50 * @nsub: list of "node down" subscriptions monitoring node 51 * @nsub: list of "node down" subscriptions monitoring node
51 * @active_links: pointers to active links to node 52 * @active_links: pointers to active links to node
52 * @links: pointers to all links to node 53 * @links: pointers to all links to node
@@ -69,7 +70,8 @@
69struct tipc_node { 70struct tipc_node {
70 u32 addr; 71 u32 addr;
71 spinlock_t lock; 72 spinlock_t lock;
72 struct tipc_node *next; 73 struct hlist_node hash;
74 struct list_head list;
73 struct list_head nsub; 75 struct list_head nsub;
74 struct link *active_links[2]; 76 struct link *active_links[2];
75 struct link *links[MAX_BEARERS]; 77 struct link *links[MAX_BEARERS];
@@ -90,27 +92,35 @@ struct tipc_node {
90 } bclink; 92 } bclink;
91}; 93};
92 94
95#define NODE_HTABLE_SIZE 512
96extern struct list_head tipc_node_list;
97
98/*
99 * A trivial power-of-two bitmask technique is used for speed, since this
100 * operation is done for every incoming TIPC packet. The number of hash table
101 * entries has been chosen so that no hash chain exceeds 8 nodes and will
102 * usually be much smaller (typically only a single node).
103 */
104static inline unsigned int tipc_hashfn(u32 addr)
105{
106 return addr & (NODE_HTABLE_SIZE - 1);
107}
108
93extern u32 tipc_own_tag; 109extern u32 tipc_own_tag;
94 110
111struct tipc_node *tipc_node_find(u32 addr);
95struct tipc_node *tipc_node_create(u32 addr); 112struct tipc_node *tipc_node_create(u32 addr);
96void tipc_node_delete(struct tipc_node *n_ptr); 113void tipc_node_delete(struct tipc_node *n_ptr);
97struct tipc_node *tipc_node_attach_link(struct link *l_ptr); 114void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr);
98void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr); 115void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr);
99void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr); 116void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr);
100void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr); 117void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr);
101int tipc_node_has_active_links(struct tipc_node *n_ptr); 118int tipc_node_active_links(struct tipc_node *n_ptr);
102int tipc_node_has_redundant_links(struct tipc_node *n_ptr); 119int tipc_node_redundant_links(struct tipc_node *n_ptr);
103int tipc_node_is_up(struct tipc_node *n_ptr); 120int tipc_node_is_up(struct tipc_node *n_ptr);
104struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); 121struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
105struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); 122struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
106 123
107static inline struct tipc_node *tipc_node_find(u32 addr)
108{
109 if (likely(in_own_cluster(addr)))
110 return tipc_net.nodes[tipc_node(addr)];
111 return NULL;
112}
113
114static inline void tipc_node_lock(struct tipc_node *n_ptr) 124static inline void tipc_node_lock(struct tipc_node *n_ptr)
115{ 125{
116 spin_lock_bh(&n_ptr->lock); 126 spin_lock_bh(&n_ptr->lock);
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index 018a55332d91..c3c2815ae630 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -2,7 +2,7 @@
2 * net/tipc/node_subscr.c: TIPC "node down" subscription handling 2 * net/tipc/node_subscr.c: TIPC "node down" subscription handling
3 * 3 *
4 * Copyright (c) 1995-2006, Ericsson AB 4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -76,3 +76,22 @@ void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub)
76 list_del_init(&node_sub->nodesub_list); 76 list_del_init(&node_sub->nodesub_list);
77 tipc_node_unlock(node_sub->node); 77 tipc_node_unlock(node_sub->node);
78} 78}
79
80/**
81 * tipc_nodesub_notify - notify subscribers that a node is unreachable
82 *
83 * Note: node is locked by caller
84 */
85
86void tipc_nodesub_notify(struct tipc_node *node)
87{
88 struct tipc_node_subscr *ns;
89
90 list_for_each_entry(ns, &node->nsub, nodesub_list) {
91 if (ns->handle_node_down) {
92 tipc_k_signal((Handler)ns->handle_node_down,
93 (unsigned long)ns->usr_handle);
94 ns->handle_node_down = NULL;
95 }
96 }
97}
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h
index 006ed739f515..4bc2ca0867a1 100644
--- a/net/tipc/node_subscr.h
+++ b/net/tipc/node_subscr.h
@@ -2,7 +2,7 @@
2 * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling 2 * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling
3 * 3 *
4 * Copyright (c) 1995-2006, Ericsson AB 4 * Copyright (c) 1995-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -59,5 +59,6 @@ struct tipc_node_subscr {
59void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, 59void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
60 void *usr_handle, net_ev_handler handle_down); 60 void *usr_handle, net_ev_handler handle_down);
61void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub); 61void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub);
62void tipc_nodesub_notify(struct tipc_node *node);
62 63
63#endif 64#endif
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 125dcb0737b2..29d94d53198d 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -58,6 +58,9 @@ struct tipc_sock {
58#define tipc_sk(sk) ((struct tipc_sock *)(sk)) 58#define tipc_sk(sk) ((struct tipc_sock *)(sk))
59#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p)) 59#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
60 60
61#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \
62 (sock->state == SS_DISCONNECTING))
63
61static int backlog_rcv(struct sock *sk, struct sk_buff *skb); 64static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
62static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); 65static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
63static void wakeupdispatch(struct tipc_port *tport); 66static void wakeupdispatch(struct tipc_port *tport);
@@ -289,7 +292,7 @@ static int release(struct socket *sock)
289 if (buf == NULL) 292 if (buf == NULL)
290 break; 293 break;
291 atomic_dec(&tipc_queue_size); 294 atomic_dec(&tipc_queue_size);
292 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) 295 if (TIPC_SKB_CB(buf)->handle != 0)
293 buf_discard(buf); 296 buf_discard(buf);
294 else { 297 else {
295 if ((sock->state == SS_CONNECTING) || 298 if ((sock->state == SS_CONNECTING) ||
@@ -911,15 +914,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
911 struct tipc_port *tport = tipc_sk_port(sk); 914 struct tipc_port *tport = tipc_sk_port(sk);
912 struct sk_buff *buf; 915 struct sk_buff *buf;
913 struct tipc_msg *msg; 916 struct tipc_msg *msg;
917 long timeout;
914 unsigned int sz; 918 unsigned int sz;
915 u32 err; 919 u32 err;
916 int res; 920 int res;
917 921
918 /* Catch invalid receive requests */ 922 /* Catch invalid receive requests */
919 923
920 if (m->msg_iovlen != 1)
921 return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
922
923 if (unlikely(!buf_len)) 924 if (unlikely(!buf_len))
924 return -EINVAL; 925 return -EINVAL;
925 926
@@ -930,6 +931,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
930 goto exit; 931 goto exit;
931 } 932 }
932 933
934 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
933restart: 935restart:
934 936
935 /* Look for a message in receive queue; wait if necessary */ 937 /* Look for a message in receive queue; wait if necessary */
@@ -939,17 +941,15 @@ restart:
939 res = -ENOTCONN; 941 res = -ENOTCONN;
940 goto exit; 942 goto exit;
941 } 943 }
942 if (flags & MSG_DONTWAIT) { 944 if (timeout <= 0L) {
943 res = -EWOULDBLOCK; 945 res = timeout ? timeout : -EWOULDBLOCK;
944 goto exit; 946 goto exit;
945 } 947 }
946 release_sock(sk); 948 release_sock(sk);
947 res = wait_event_interruptible(*sk_sleep(sk), 949 timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
948 (!skb_queue_empty(&sk->sk_receive_queue) || 950 tipc_rx_ready(sock),
949 (sock->state == SS_DISCONNECTING))); 951 timeout);
950 lock_sock(sk); 952 lock_sock(sk);
951 if (res)
952 goto exit;
953 } 953 }
954 954
955 /* Look at first message in receive queue */ 955 /* Look at first message in receive queue */
@@ -991,11 +991,10 @@ restart:
991 sz = buf_len; 991 sz = buf_len;
992 m->msg_flags |= MSG_TRUNC; 992 m->msg_flags |= MSG_TRUNC;
993 } 993 }
994 if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), 994 res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
995 sz))) { 995 m->msg_iov, sz);
996 res = -EFAULT; 996 if (res)
997 goto exit; 997 goto exit;
998 }
999 res = sz; 998 res = sz;
1000 } else { 999 } else {
1001 if ((sock->state == SS_READY) || 1000 if ((sock->state == SS_READY) ||
@@ -1038,19 +1037,15 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1038 struct tipc_port *tport = tipc_sk_port(sk); 1037 struct tipc_port *tport = tipc_sk_port(sk);
1039 struct sk_buff *buf; 1038 struct sk_buff *buf;
1040 struct tipc_msg *msg; 1039 struct tipc_msg *msg;
1040 long timeout;
1041 unsigned int sz; 1041 unsigned int sz;
1042 int sz_to_copy, target, needed; 1042 int sz_to_copy, target, needed;
1043 int sz_copied = 0; 1043 int sz_copied = 0;
1044 char __user *crs = m->msg_iov->iov_base;
1045 unsigned char *buf_crs;
1046 u32 err; 1044 u32 err;
1047 int res = 0; 1045 int res = 0;
1048 1046
1049 /* Catch invalid receive attempts */ 1047 /* Catch invalid receive attempts */
1050 1048
1051 if (m->msg_iovlen != 1)
1052 return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
1053
1054 if (unlikely(!buf_len)) 1049 if (unlikely(!buf_len))
1055 return -EINVAL; 1050 return -EINVAL;
1056 1051
@@ -1063,7 +1058,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1063 } 1058 }
1064 1059
1065 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); 1060 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
1066 1061 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1067restart: 1062restart:
1068 1063
1069 /* Look for a message in receive queue; wait if necessary */ 1064 /* Look for a message in receive queue; wait if necessary */
@@ -1073,17 +1068,15 @@ restart:
1073 res = -ENOTCONN; 1068 res = -ENOTCONN;
1074 goto exit; 1069 goto exit;
1075 } 1070 }
1076 if (flags & MSG_DONTWAIT) { 1071 if (timeout <= 0L) {
1077 res = -EWOULDBLOCK; 1072 res = timeout ? timeout : -EWOULDBLOCK;
1078 goto exit; 1073 goto exit;
1079 } 1074 }
1080 release_sock(sk); 1075 release_sock(sk);
1081 res = wait_event_interruptible(*sk_sleep(sk), 1076 timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
1082 (!skb_queue_empty(&sk->sk_receive_queue) || 1077 tipc_rx_ready(sock),
1083 (sock->state == SS_DISCONNECTING))); 1078 timeout);
1084 lock_sock(sk); 1079 lock_sock(sk);
1085 if (res)
1086 goto exit;
1087 } 1080 }
1088 1081
1089 /* Look at first message in receive queue */ 1082 /* Look at first message in receive queue */
@@ -1112,24 +1105,25 @@ restart:
1112 /* Capture message data (if valid) & compute return value (always) */ 1105 /* Capture message data (if valid) & compute return value (always) */
1113 1106
1114 if (!err) { 1107 if (!err) {
1115 buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); 1108 u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
1116 sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
1117 1109
1110 sz -= offset;
1118 needed = (buf_len - sz_copied); 1111 needed = (buf_len - sz_copied);
1119 sz_to_copy = (sz <= needed) ? sz : needed; 1112 sz_to_copy = (sz <= needed) ? sz : needed;
1120 if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { 1113
1121 res = -EFAULT; 1114 res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
1115 m->msg_iov, sz_to_copy);
1116 if (res)
1122 goto exit; 1117 goto exit;
1123 } 1118
1124 sz_copied += sz_to_copy; 1119 sz_copied += sz_to_copy;
1125 1120
1126 if (sz_to_copy < sz) { 1121 if (sz_to_copy < sz) {
1127 if (!(flags & MSG_PEEK)) 1122 if (!(flags & MSG_PEEK))
1128 TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; 1123 TIPC_SKB_CB(buf)->handle =
1124 (void *)(unsigned long)(offset + sz_to_copy);
1129 goto exit; 1125 goto exit;
1130 } 1126 }
1131
1132 crs += sz_to_copy;
1133 } else { 1127 } else {
1134 if (sz_copied != 0) 1128 if (sz_copied != 0)
1135 goto exit; /* can't add error msg to valid data */ 1129 goto exit; /* can't add error msg to valid data */
@@ -1256,7 +1250,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
1256 1250
1257 /* Enqueue message (finally!) */ 1251 /* Enqueue message (finally!) */
1258 1252
1259 TIPC_SKB_CB(buf)->handle = msg_data(msg); 1253 TIPC_SKB_CB(buf)->handle = 0;
1260 atomic_inc(&tipc_queue_size); 1254 atomic_inc(&tipc_queue_size);
1261 __skb_queue_tail(&sk->sk_receive_queue, buf); 1255 __skb_queue_tail(&sk->sk_receive_queue, buf);
1262 1256
@@ -1608,7 +1602,7 @@ restart:
1608 buf = __skb_dequeue(&sk->sk_receive_queue); 1602 buf = __skb_dequeue(&sk->sk_receive_queue);
1609 if (buf) { 1603 if (buf) {
1610 atomic_dec(&tipc_queue_size); 1604 atomic_dec(&tipc_queue_size);
1611 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { 1605 if (TIPC_SKB_CB(buf)->handle != 0) {
1612 buf_discard(buf); 1606 buf_discard(buf);
1613 goto restart; 1607 goto restart;
1614 } 1608 }