aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/discover.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/discover.c')
-rw-r--r--net/tipc/discover.c140
1 files changed, 76 insertions, 64 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index fa026bd91a68..491eff56b9da 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -2,7 +2,7 @@
2 * net/tipc/discover.c 2 * net/tipc/discover.c
3 * 3 *
4 * Copyright (c) 2003-2006, Ericsson AB 4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005-2006, Wind River Systems 5 * Copyright (c) 2005-2006, 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
@@ -57,7 +57,7 @@
57 * @timer_intv: current interval between requests (in ms) 57 * @timer_intv: current interval between requests (in ms)
58 */ 58 */
59struct link_req { 59struct link_req {
60 struct bearer *bearer; 60 struct tipc_bearer *bearer;
61 struct tipc_media_addr dest; 61 struct tipc_media_addr dest;
62 struct sk_buff *buf; 62 struct sk_buff *buf;
63 struct timer_list timer; 63 struct timer_list timer;
@@ -67,27 +67,24 @@ struct link_req {
67/** 67/**
68 * tipc_disc_init_msg - initialize a link setup message 68 * tipc_disc_init_msg - initialize a link setup message
69 * @type: message type (request or response) 69 * @type: message type (request or response)
70 * @req_links: number of links associated with message
71 * @dest_domain: network domain of node(s) which should respond to message 70 * @dest_domain: network domain of node(s) which should respond to message
72 * @b_ptr: ptr to bearer issuing message 71 * @b_ptr: ptr to bearer issuing message
73 */ 72 */
74 73
75static struct sk_buff *tipc_disc_init_msg(u32 type, 74static struct sk_buff *tipc_disc_init_msg(u32 type,
76 u32 req_links,
77 u32 dest_domain, 75 u32 dest_domain,
78 struct bearer *b_ptr) 76 struct tipc_bearer *b_ptr)
79{ 77{
80 struct sk_buff *buf = tipc_buf_acquire(DSC_H_SIZE); 78 struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE);
81 struct tipc_msg *msg; 79 struct tipc_msg *msg;
82 80
83 if (buf) { 81 if (buf) {
84 msg = buf_msg(buf); 82 msg = buf_msg(buf);
85 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);
86 msg_set_non_seq(msg, 1); 84 msg_set_non_seq(msg, 1);
87 msg_set_req_links(msg, req_links);
88 msg_set_dest_domain(msg, dest_domain); 85 msg_set_dest_domain(msg, dest_domain);
89 msg_set_bc_netid(msg, tipc_net_id); 86 msg_set_bc_netid(msg, tipc_net_id);
90 msg_set_media_addr(msg, &b_ptr->publ.addr); 87 msg_set_media_addr(msg, &b_ptr->addr);
91 } 88 }
92 return buf; 89 return buf;
93} 90}
@@ -99,7 +96,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
99 * @media_addr: media address advertised by duplicated node 96 * @media_addr: media address advertised by duplicated node
100 */ 97 */
101 98
102static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, 99static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
103 struct tipc_media_addr *media_addr) 100 struct tipc_media_addr *media_addr)
104{ 101{
105 char node_addr_str[16]; 102 char node_addr_str[16];
@@ -111,7 +108,7 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
111 tipc_media_addr_printf(&pb, media_addr); 108 tipc_media_addr_printf(&pb, media_addr);
112 tipc_printbuf_validate(&pb); 109 tipc_printbuf_validate(&pb);
113 warn("Duplicate %s using %s seen on <%s>\n", 110 warn("Duplicate %s using %s seen on <%s>\n",
114 node_addr_str, media_addr_str, b_ptr->publ.name); 111 node_addr_str, media_addr_str, b_ptr->name);
115} 112}
116 113
117/** 114/**
@@ -120,19 +117,23 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
120 * @b_ptr: bearer that message arrived on 117 * @b_ptr: bearer that message arrived on
121 */ 118 */
122 119
123void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr) 120void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
124{ 121{
122 struct tipc_node *n_ptr;
125 struct link *link; 123 struct link *link;
126 struct tipc_media_addr media_addr; 124 struct tipc_media_addr media_addr, *addr;
125 struct sk_buff *rbuf;
127 struct tipc_msg *msg = buf_msg(buf); 126 struct tipc_msg *msg = buf_msg(buf);
128 u32 dest = msg_dest_domain(msg); 127 u32 dest = msg_dest_domain(msg);
129 u32 orig = msg_prevnode(msg); 128 u32 orig = msg_prevnode(msg);
130 u32 net_id = msg_bc_netid(msg); 129 u32 net_id = msg_bc_netid(msg);
131 u32 type = msg_type(msg); 130 u32 type = msg_type(msg);
131 int link_fully_up;
132 132
133 msg_get_media_addr(msg, &media_addr); 133 msg_get_media_addr(msg, &media_addr);
134 buf_discard(buf); 134 buf_discard(buf);
135 135
136 /* Validate discovery message from requesting node */
136 if (net_id != tipc_net_id) 137 if (net_id != tipc_net_id)
137 return; 138 return;
138 if (!tipc_addr_domain_valid(dest)) 139 if (!tipc_addr_domain_valid(dest))
@@ -140,63 +141,76 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
140 if (!tipc_addr_node_valid(orig)) 141 if (!tipc_addr_node_valid(orig))
141 return; 142 return;
142 if (orig == tipc_own_addr) { 143 if (orig == tipc_own_addr) {
143 if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr))) 144 if (memcmp(&media_addr, &b_ptr->addr, sizeof(media_addr)))
144 disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr); 145 disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
145 return; 146 return;
146 } 147 }
147 if (!tipc_in_scope(dest, tipc_own_addr)) 148 if (!tipc_in_scope(dest, tipc_own_addr))
148 return; 149 return;
149 if (in_own_cluster(orig)) { 150 if (!in_own_cluster(orig))
150 /* Always accept link here */ 151 return;
151 struct sk_buff *rbuf;
152 struct tipc_media_addr *addr;
153 struct tipc_node *n_ptr = tipc_node_find(orig);
154 int link_fully_up;
155
156 if (n_ptr == NULL) {
157 n_ptr = tipc_node_create(orig);
158 if (!n_ptr)
159 return;
160 }
161 spin_lock_bh(&n_ptr->lock);
162
163 /* Don't talk to neighbor during cleanup after last session */
164 152
165 if (n_ptr->cleanup_required) { 153 /* Locate structure corresponding to requesting node */
166 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)
167 return; 158 return;
168 } 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];
169 169
170 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);
171 if (!link) { 173 if (!link) {
172 link = tipc_link_create(b_ptr, orig, &media_addr); 174 tipc_node_unlock(n_ptr);
173 if (!link) { 175 return;
174 spin_unlock_bh(&n_ptr->lock);
175 return;
176 }
177 }
178 addr = &link->media_addr;
179 if (memcmp(addr, &media_addr, sizeof(*addr))) {
180 if (tipc_link_is_up(link) || (!link->started)) {
181 disc_dupl_alert(b_ptr, orig, &media_addr);
182 spin_unlock_bh(&n_ptr->lock);
183 return;
184 }
185 warn("Resetting link <%s>, peer interface address changed\n",
186 link->name);
187 memcpy(addr, &media_addr, sizeof(*addr));
188 tipc_link_reset(link);
189 } 176 }
190 link_fully_up = link_working_working(link); 177 }
191 spin_unlock_bh(&n_ptr->lock); 178
192 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);
193 return; 194 return;
194 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); 195 }
195 if (rbuf != NULL) { 196 warn("Resetting link <%s>, peer interface address changed\n",
196 b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr); 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) {
206 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
207 if (rbuf) {
208 b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
197 buf_discard(rbuf); 209 buf_discard(rbuf);
198 } 210 }
199 } 211 }
212
213 tipc_node_unlock(n_ptr);
200} 214}
201 215
202/** 216/**
@@ -249,9 +263,9 @@ void tipc_disc_update_link_req(struct link_req *req)
249 263
250static void disc_timeout(struct link_req *req) 264static void disc_timeout(struct link_req *req)
251{ 265{
252 spin_lock_bh(&req->bearer->publ.lock); 266 spin_lock_bh(&req->bearer->lock);
253 267
254 req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest); 268 req->bearer->media->send_msg(req->buf, req->bearer, &req->dest);
255 269
256 if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || 270 if ((req->timer_intv == TIPC_LINK_REQ_SLOW) ||
257 (req->timer_intv == TIPC_LINK_REQ_FAST)) { 271 (req->timer_intv == TIPC_LINK_REQ_FAST)) {
@@ -266,7 +280,7 @@ static void disc_timeout(struct link_req *req)
266 } 280 }
267 k_start_timer(&req->timer, req->timer_intv); 281 k_start_timer(&req->timer, req->timer_intv);
268 282
269 spin_unlock_bh(&req->bearer->publ.lock); 283 spin_unlock_bh(&req->bearer->lock);
270} 284}
271 285
272/** 286/**
@@ -274,15 +288,13 @@ static void disc_timeout(struct link_req *req)
274 * @b_ptr: ptr to bearer issuing requests 288 * @b_ptr: ptr to bearer issuing requests
275 * @dest: destination address for request messages 289 * @dest: destination address for request messages
276 * @dest_domain: network domain of node(s) which should respond to message 290 * @dest_domain: network domain of node(s) which should respond to message
277 * @req_links: max number of desired links
278 * 291 *
279 * Returns pointer to link request structure, or NULL if unable to create. 292 * Returns pointer to link request structure, or NULL if unable to create.
280 */ 293 */
281 294
282struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, 295struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr,
283 const struct tipc_media_addr *dest, 296 const struct tipc_media_addr *dest,
284 u32 dest_domain, 297 u32 dest_domain)
285 u32 req_links)
286{ 298{
287 struct link_req *req; 299 struct link_req *req;
288 300
@@ -290,7 +302,7 @@ struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
290 if (!req) 302 if (!req)
291 return NULL; 303 return NULL;
292 304
293 req->buf = tipc_disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); 305 req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr);
294 if (!req->buf) { 306 if (!req->buf) {
295 kfree(req); 307 kfree(req);
296 return NULL; 308 return NULL;