diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-13 21:49:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-13 21:49:11 -0400 |
commit | 27b61ae2d73936554fcd07e77c3cc13bc88c41a9 (patch) | |
tree | 12f589c6a4671bf7f08045bb11059514f47bb924 /net/tipc | |
parent | 46af31800b6916c92fffa529dc3c357008da957d (diff) | |
parent | 633d2bdedc3b81f202bda8fdad17aeb08809b7df (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/Kconfig | 12 | ||||
-rw-r--r-- | net/tipc/addr.c | 15 | ||||
-rw-r--r-- | net/tipc/addr.h | 17 | ||||
-rw-r--r-- | net/tipc/bearer.c | 18 | ||||
-rw-r--r-- | net/tipc/bearer.h | 6 | ||||
-rw-r--r-- | net/tipc/config.c | 31 | ||||
-rw-r--r-- | net/tipc/core.c | 6 | ||||
-rw-r--r-- | net/tipc/core.h | 1 | ||||
-rw-r--r-- | net/tipc/discover.c | 103 | ||||
-rw-r--r-- | net/tipc/link.c | 50 | ||||
-rw-r--r-- | net/tipc/link.h | 3 | ||||
-rw-r--r-- | net/tipc/msg.c | 34 | ||||
-rw-r--r-- | net/tipc/msg.h | 42 | ||||
-rw-r--r-- | net/tipc/name_distr.c | 18 | ||||
-rw-r--r-- | net/tipc/net.c | 32 | ||||
-rw-r--r-- | net/tipc/net.h | 19 | ||||
-rw-r--r-- | net/tipc/node.c | 123 | ||||
-rw-r--r-- | net/tipc/node.h | 36 | ||||
-rw-r--r-- | net/tipc/node_subscr.c | 21 | ||||
-rw-r--r-- | net/tipc/node_subscr.h | 3 | ||||
-rw-r--r-- | net/tipc/socket.c | 70 |
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 | ||
32 | config 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 | |||
44 | config TIPC_PORTS | 32 | config 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 | ||
40 | static inline u32 tipc_zone_mask(u32 addr) | ||
41 | { | ||
42 | return addr & 0xff000000u; | ||
43 | } | ||
44 | |||
45 | static inline u32 tipc_cluster_mask(u32 addr) | ||
46 | { | ||
47 | return addr & 0xfffff000u; | ||
48 | } | ||
49 | |||
40 | static inline int in_own_cluster(u32 addr) | 50 | static 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 | ||
52 | static inline int addr_domain(int sc) | 62 | static 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 | ||
62 | int tipc_addr_domain_valid(u32); | 71 | int 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 | ||
477 | int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) | 476 | int 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; |
576 | failed: | 572 | failed: |
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); | |||
167 | int tipc_block_bearer(const char *name); | 163 | int tipc_block_bearer(const char *name); |
168 | void tipc_continue(struct tipc_bearer *tb_ptr); | 164 | void tipc_continue(struct tipc_bearer *tb_ptr); |
169 | 165 | ||
170 | int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority); | 166 | int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); |
171 | int tipc_disable_bearer(const char *name); | 167 | int 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 | ||
263 | static 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 | |||
282 | static struct sk_buff *cfg_set_netid(void) | 263 | static 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 | ||
66 | u32 tipc_own_addr; | 62 | u32 tipc_own_addr; |
67 | int tipc_max_nodes; | ||
68 | int tipc_max_ports; | 63 | int tipc_max_ports; |
69 | int tipc_max_subscriptions; | 64 | int tipc_max_subscriptions; |
70 | int tipc_max_publications; | 65 | int 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 | ||
149 | extern u32 tipc_own_addr; | 149 | extern u32 tipc_own_addr; |
150 | extern int tipc_max_nodes; | ||
151 | extern int tipc_max_ports; | 150 | extern int tipc_max_ports; |
152 | extern int tipc_max_subscriptions; | 151 | extern int tipc_max_subscriptions; |
153 | extern int tipc_max_publications; | 152 | extern 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 | ||
120 | void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | 120 | void 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 | ||
303 | struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, | 303 | struct 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 | ||
208 | struct tipc_port; | 208 | struct tipc_port; |
209 | 209 | ||
210 | struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, | 210 | struct 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); |
212 | void tipc_link_delete(struct link *l_ptr); | 213 | void tipc_link_delete(struct link *l_ptr); |
213 | void tipc_link_changeover(struct link *l_ptr); | 214 | void 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 | ||
424 | static 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 | |||
431 | static inline u32 msg_nametype(struct tipc_msg *m) | 424 | static 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 | ||
441 | static inline void msg_set_timestamp(struct tipc_msg *m, u32 n) | ||
442 | { | ||
443 | msg_set_word(m, 8, n); | ||
444 | } | ||
445 | |||
446 | static inline u32 msg_timestamp(struct tipc_msg *m) | ||
447 | { | ||
448 | return msg_word(m, 8); | ||
449 | } | ||
450 | |||
451 | static inline u32 msg_nameinst(struct tipc_msg *m) | 434 | static 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 | ||
732 | static inline void msg_set_redundant_link(struct tipc_msg *m) | 714 | static 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 | |||
737 | static 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 | |||
792 | static inline u32 msg_remote_node(struct tipc_msg *m) | ||
793 | { | ||
794 | return msg_word(m, msg_hdr_sz(m)/4); | ||
795 | } | ||
796 | |||
797 | static 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 | ||
227 | static void node_is_down(struct publication *publ) | 224 | static 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 | ||
110 | DEFINE_RWLOCK(tipc_net_lock); | 111 | DEFINE_RWLOCK(tipc_net_lock); |
111 | struct network tipc_net; | ||
112 | |||
113 | static 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 | |||
122 | static 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 | ||
132 | static void net_route_named_msg(struct sk_buff *buf) | 113 | static 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 | ||
236 | void tipc_net_stop(void) | 214 | void 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 | ||
40 | struct 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 | |||
49 | struct network { | ||
50 | struct tipc_node **nodes; | ||
51 | u32 highest_node; | ||
52 | u32 links; | ||
53 | }; | ||
54 | |||
55 | |||
56 | extern struct network tipc_net; | ||
57 | extern rwlock_t tipc_net_lock; | 40 | extern rwlock_t tipc_net_lock; |
58 | 41 | ||
59 | void tipc_net_route_msg(struct sk_buff *buf); | 42 | void 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 | ||
45 | static DEFINE_SPINLOCK(node_create_lock); | 45 | static DEFINE_SPINLOCK(node_create_lock); |
46 | 46 | ||
47 | static struct hlist_head node_htable[NODE_HTABLE_SIZE]; | ||
48 | LIST_HEAD(tipc_node_list); | ||
49 | static u32 tipc_num_nodes; | ||
50 | |||
51 | static atomic_t tipc_num_links = ATOMIC_INIT(0); | ||
47 | u32 tipc_own_tag; | 52 | u32 tipc_own_tag; |
48 | 53 | ||
49 | /** | 54 | /** |
55 | * tipc_node_find - locate specified node object, if it exists | ||
56 | */ | ||
57 | |||
58 | struct 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 | ||
59 | struct tipc_node *tipc_node_create(u32 addr) | 83 | struct 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 | ||
92 | void tipc_node_delete(struct tipc_node *n_ptr) | 122 | void 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 | ||
203 | int tipc_node_has_active_links(struct tipc_node *n_ptr) | 226 | int 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 | ||
208 | int tipc_node_has_redundant_links(struct tipc_node *n_ptr) | 231 | int 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 | ||
213 | int tipc_node_is_up(struct tipc_node *n_ptr) | 236 | int 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 | ||
218 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | 241 | void 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 | ||
247 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) | 248 | void 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 | ||
328 | static void node_lost_contact(struct tipc_node *n_ptr) | 329 | static 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 @@ | |||
69 | struct tipc_node { | 70 | struct 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 | ||
96 | extern 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 | */ | ||
104 | static inline unsigned int tipc_hashfn(u32 addr) | ||
105 | { | ||
106 | return addr & (NODE_HTABLE_SIZE - 1); | ||
107 | } | ||
108 | |||
93 | extern u32 tipc_own_tag; | 109 | extern u32 tipc_own_tag; |
94 | 110 | ||
111 | struct tipc_node *tipc_node_find(u32 addr); | ||
95 | struct tipc_node *tipc_node_create(u32 addr); | 112 | struct tipc_node *tipc_node_create(u32 addr); |
96 | void tipc_node_delete(struct tipc_node *n_ptr); | 113 | void tipc_node_delete(struct tipc_node *n_ptr); |
97 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr); | 114 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr); |
98 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr); | 115 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr); |
99 | void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr); | 116 | void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr); |
100 | void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr); | 117 | void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr); |
101 | int tipc_node_has_active_links(struct tipc_node *n_ptr); | 118 | int tipc_node_active_links(struct tipc_node *n_ptr); |
102 | int tipc_node_has_redundant_links(struct tipc_node *n_ptr); | 119 | int tipc_node_redundant_links(struct tipc_node *n_ptr); |
103 | int tipc_node_is_up(struct tipc_node *n_ptr); | 120 | int tipc_node_is_up(struct tipc_node *n_ptr); |
104 | struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); | 121 | struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); |
105 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); | 122 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); |
106 | 123 | ||
107 | static 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 | |||
114 | static inline void tipc_node_lock(struct tipc_node *n_ptr) | 124 | static 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 | |||
86 | void 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 { | |||
59 | void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, | 59 | void 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); |
61 | void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub); | 61 | void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub); |
62 | void 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 | |||
61 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); | 64 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); |
62 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); | 65 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); |
63 | static void wakeupdispatch(struct tipc_port *tport); | 66 | static 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); | ||
933 | restart: | 935 | restart: |
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); | |
1067 | restart: | 1062 | restart: |
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 | } |