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.c326
1 files changed, 170 insertions, 156 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index fc1fcf5e6b53..0987933155b9 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
@@ -35,97 +35,56 @@
35 */ 35 */
36 36
37#include "core.h" 37#include "core.h"
38#include "dbg.h"
39#include "link.h" 38#include "link.h"
40#include "zone.h"
41#include "discover.h" 39#include "discover.h"
42#include "port.h"
43#include "name_table.h"
44 40
45#define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ 41#define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */
46#define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ 42#define TIPC_LINK_REQ_FAST 1000 /* max delay if bearer has no links */
47#define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ 43#define TIPC_LINK_REQ_SLOW 60000 /* max delay if bearer has links */
48 44#define TIPC_LINK_REQ_INACTIVE 0xffffffff /* indicates no timer in use */
49#if 0
50#define GET_NODE_INFO 300
51#define GET_NODE_INFO_RESULT 301
52#define FORWARD_LINK_PROBE 302
53#define LINK_REQUEST_REJECTED 303
54#define LINK_REQUEST_ACCEPTED 304
55#define DROP_LINK_REQUEST 305
56#define CHECK_LINK_COUNT 306
57#endif
58
59/*
60 * TODO: Most of the inter-cluster setup stuff should be
61 * rewritten, and be made conformant with specification.
62 */
63 45
64 46
65/** 47/**
66 * struct link_req - information about an ongoing link setup request 48 * struct link_req - information about an ongoing link setup request
67 * @bearer: bearer issuing requests 49 * @bearer: bearer issuing requests
68 * @dest: destination address for request messages 50 * @dest: destination address for request messages
51 * @domain: network domain to which links can be established
52 * @num_nodes: number of nodes currently discovered (i.e. with an active link)
69 * @buf: request message to be (repeatedly) sent 53 * @buf: request message to be (repeatedly) sent
70 * @timer: timer governing period between requests 54 * @timer: timer governing period between requests
71 * @timer_intv: current interval between requests (in ms) 55 * @timer_intv: current interval between requests (in ms)
72 */ 56 */
73struct link_req { 57struct link_req {
74 struct bearer *bearer; 58 struct tipc_bearer *bearer;
75 struct tipc_media_addr dest; 59 struct tipc_media_addr dest;
60 u32 domain;
61 int num_nodes;
76 struct sk_buff *buf; 62 struct sk_buff *buf;
77 struct timer_list timer; 63 struct timer_list timer;
78 unsigned int timer_intv; 64 unsigned int timer_intv;
79}; 65};
80 66
81
82#if 0
83int disc_create_link(const struct tipc_link_create *argv)
84{
85 /*
86 * Code for inter cluster link setup here
87 */
88 return TIPC_OK;
89}
90#endif
91
92/*
93 * disc_lost_link(): A link has lost contact
94 */
95
96void tipc_disc_link_event(u32 addr, char *name, int up)
97{
98 if (in_own_cluster(addr))
99 return;
100 /*
101 * Code for inter cluster link setup here
102 */
103}
104
105/** 67/**
106 * tipc_disc_init_msg - initialize a link setup message 68 * tipc_disc_init_msg - initialize a link setup message
107 * @type: message type (request or response) 69 * @type: message type (request or response)
108 * @req_links: number of links associated with message
109 * @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
110 * @b_ptr: ptr to bearer issuing message 71 * @b_ptr: ptr to bearer issuing message
111 */ 72 */
112 73
113static struct sk_buff *tipc_disc_init_msg(u32 type, 74static struct sk_buff *tipc_disc_init_msg(u32 type,
114 u32 req_links,
115 u32 dest_domain, 75 u32 dest_domain,
116 struct bearer *b_ptr) 76 struct tipc_bearer *b_ptr)
117{ 77{
118 struct sk_buff *buf = buf_acquire(DSC_H_SIZE); 78 struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE);
119 struct tipc_msg *msg; 79 struct tipc_msg *msg;
120 80
121 if (buf) { 81 if (buf) {
122 msg = buf_msg(buf); 82 msg = buf_msg(buf);
123 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);
124 msg_set_non_seq(msg, 1); 84 msg_set_non_seq(msg, 1);
125 msg_set_req_links(msg, req_links);
126 msg_set_dest_domain(msg, dest_domain); 85 msg_set_dest_domain(msg, dest_domain);
127 msg_set_bc_netid(msg, tipc_net_id); 86 msg_set_bc_netid(msg, tipc_net_id);
128 msg_set_media_addr(msg, &b_ptr->publ.addr); 87 msg_set_media_addr(msg, &b_ptr->addr);
129 } 88 }
130 return buf; 89 return buf;
131} 90}
@@ -137,7 +96,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
137 * @media_addr: media address advertised by duplicated node 96 * @media_addr: media address advertised by duplicated node
138 */ 97 */
139 98
140static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, 99static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
141 struct tipc_media_addr *media_addr) 100 struct tipc_media_addr *media_addr)
142{ 101{
143 char node_addr_str[16]; 102 char node_addr_str[16];
@@ -149,7 +108,7 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
149 tipc_media_addr_printf(&pb, media_addr); 108 tipc_media_addr_printf(&pb, media_addr);
150 tipc_printbuf_validate(&pb); 109 tipc_printbuf_validate(&pb);
151 warn("Duplicate %s using %s seen on <%s>\n", 110 warn("Duplicate %s using %s seen on <%s>\n",
152 node_addr_str, media_addr_str, b_ptr->publ.name); 111 node_addr_str, media_addr_str, b_ptr->name);
153} 112}
154 113
155/** 114/**
@@ -158,20 +117,23 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
158 * @b_ptr: bearer that message arrived on 117 * @b_ptr: bearer that message arrived on
159 */ 118 */
160 119
161void 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)
162{ 121{
122 struct tipc_node *n_ptr;
163 struct link *link; 123 struct link *link;
164 struct tipc_media_addr media_addr; 124 struct tipc_media_addr media_addr, *addr;
125 struct sk_buff *rbuf;
165 struct tipc_msg *msg = buf_msg(buf); 126 struct tipc_msg *msg = buf_msg(buf);
166 u32 dest = msg_dest_domain(msg); 127 u32 dest = msg_dest_domain(msg);
167 u32 orig = msg_prevnode(msg); 128 u32 orig = msg_prevnode(msg);
168 u32 net_id = msg_bc_netid(msg); 129 u32 net_id = msg_bc_netid(msg);
169 u32 type = msg_type(msg); 130 u32 type = msg_type(msg);
131 int link_fully_up;
170 132
171 msg_get_media_addr(msg,&media_addr); 133 msg_get_media_addr(msg, &media_addr);
172 msg_dbg(msg, "RECV:");
173 buf_discard(buf); 134 buf_discard(buf);
174 135
136 /* Validate discovery message from requesting node */
175 if (net_id != tipc_net_id) 137 if (net_id != tipc_net_id)
176 return; 138 return;
177 if (!tipc_addr_domain_valid(dest)) 139 if (!tipc_addr_domain_valid(dest))
@@ -179,103 +141,127 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
179 if (!tipc_addr_node_valid(orig)) 141 if (!tipc_addr_node_valid(orig))
180 return; 142 return;
181 if (orig == tipc_own_addr) { 143 if (orig == tipc_own_addr) {
182 if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr))) 144 if (memcmp(&media_addr, &b_ptr->addr, sizeof(media_addr)))
183 disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr); 145 disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
184 return; 146 return;
185 } 147 }
186 if (!tipc_in_scope(dest, tipc_own_addr)) 148 if (!tipc_in_scope(dest, tipc_own_addr))
187 return; 149 return;
188 if (is_slave(tipc_own_addr) && is_slave(orig)) 150 if (!tipc_in_scope(b_ptr->link_req->domain, orig))
189 return; 151 return;
190 if (is_slave(orig) && !in_own_cluster(orig)) 152
153 /* Locate structure corresponding to requesting node */
154 n_ptr = tipc_node_find(orig);
155 if (!n_ptr) {
156 n_ptr = tipc_node_create(orig);
157 if (!n_ptr)
158 return;
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);
191 return; 165 return;
192 if (in_own_cluster(orig)) { 166 }
193 /* Always accept link here */ 167
194 struct sk_buff *rbuf; 168 link = n_ptr->links[b_ptr->identity];
195 struct tipc_media_addr *addr; 169
196 struct tipc_node *n_ptr = tipc_node_find(orig); 170 /* Create a link endpoint for this bearer, if necessary */
197 int link_fully_up; 171 if (!link) {
198 172 link = tipc_link_create(n_ptr, b_ptr, &media_addr);
199 dbg(" in own cluster\n");
200 if (n_ptr == NULL) {
201 n_ptr = tipc_node_create(orig);
202 if (!n_ptr)
203 return;
204 }
205 spin_lock_bh(&n_ptr->lock);
206 link = n_ptr->links[b_ptr->identity];
207 if (!link) { 173 if (!link) {
208 dbg("creating link\n"); 174 tipc_node_unlock(n_ptr);
209 link = tipc_link_create(b_ptr, orig, &media_addr); 175 return;
210 if (!link) {
211 spin_unlock_bh(&n_ptr->lock);
212 return;
213 }
214 }
215 addr = &link->media_addr;
216 if (memcmp(addr, &media_addr, sizeof(*addr))) {
217 if (tipc_link_is_up(link) || (!link->started)) {
218 disc_dupl_alert(b_ptr, orig, &media_addr);
219 spin_unlock_bh(&n_ptr->lock);
220 return;
221 }
222 warn("Resetting link <%s>, peer interface address changed\n",
223 link->name);
224 memcpy(addr, &media_addr, sizeof(*addr));
225 tipc_link_reset(link);
226 } 176 }
227 link_fully_up = link_working_working(link); 177 }
228 spin_unlock_bh(&n_ptr->lock); 178
229 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);
230 return; 194 return;
231 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); 195 }
232 if (rbuf != NULL) { 196 warn("Resetting link <%s>, peer interface address changed\n",
233 msg_dbg(buf_msg(rbuf),"SEND:"); 197 link->name);
234 b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr); 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);
235 buf_discard(rbuf); 209 buf_discard(rbuf);
236 } 210 }
237 } 211 }
212
213 tipc_node_unlock(n_ptr);
238} 214}
239 215
240/** 216/**
241 * tipc_disc_stop_link_req - stop sending periodic link setup requests 217 * disc_update - update frequency of periodic link setup requests
242 * @req: ptr to link request structure 218 * @req: ptr to link request structure
219 *
220 * Reinitiates discovery process if discovery object has no associated nodes
221 * and is either not currently searching or is searching at a slow rate
243 */ 222 */
244 223
245void tipc_disc_stop_link_req(struct link_req *req) 224static void disc_update(struct link_req *req)
246{ 225{
247 if (!req) 226 if (!req->num_nodes) {
248 return; 227 if ((req->timer_intv == TIPC_LINK_REQ_INACTIVE) ||
228 (req->timer_intv > TIPC_LINK_REQ_FAST)) {
229 req->timer_intv = TIPC_LINK_REQ_INIT;
230 k_start_timer(&req->timer, req->timer_intv);
231 }
232 }
233}
249 234
250 k_cancel_timer(&req->timer); 235/**
251 k_term_timer(&req->timer); 236 * tipc_disc_add_dest - increment set of discovered nodes
252 buf_discard(req->buf); 237 * @req: ptr to link request structure
253 kfree(req); 238 */
239
240void tipc_disc_add_dest(struct link_req *req)
241{
242 req->num_nodes++;
254} 243}
255 244
256/** 245/**
257 * tipc_disc_update_link_req - update frequency of periodic link setup requests 246 * tipc_disc_remove_dest - decrement set of discovered nodes
258 * @req: ptr to link request structure 247 * @req: ptr to link request structure
259 */ 248 */
260 249
261void tipc_disc_update_link_req(struct link_req *req) 250void tipc_disc_remove_dest(struct link_req *req)
262{ 251{
263 if (!req) 252 req->num_nodes--;
264 return; 253 disc_update(req);
254}
265 255
266 if (req->timer_intv == TIPC_LINK_REQ_SLOW) { 256/**
267 if (!req->bearer->nodes.count) { 257 * disc_send_msg - send link setup request message
268 req->timer_intv = TIPC_LINK_REQ_FAST; 258 * @req: ptr to link request structure
269 k_start_timer(&req->timer, req->timer_intv); 259 */
270 } 260
271 } else if (req->timer_intv == TIPC_LINK_REQ_FAST) { 261static void disc_send_msg(struct link_req *req)
272 if (req->bearer->nodes.count) { 262{
273 req->timer_intv = TIPC_LINK_REQ_SLOW; 263 if (!req->bearer->blocked)
274 k_start_timer(&req->timer, req->timer_intv); 264 tipc_bearer_send(req->bearer, req->buf, &req->dest);
275 }
276 } else {
277 /* leave timer "as is" if haven't yet reached a "normal" rate */
278 }
279} 265}
280 266
281/** 267/**
@@ -287,58 +273,86 @@ void tipc_disc_update_link_req(struct link_req *req)
287 273
288static void disc_timeout(struct link_req *req) 274static void disc_timeout(struct link_req *req)
289{ 275{
290 spin_lock_bh(&req->bearer->publ.lock); 276 int max_delay;
291 277
292 req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest); 278 spin_lock_bh(&req->bearer->lock);
293 279
294 if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || 280 /* Stop searching if only desired node has been found */
295 (req->timer_intv == TIPC_LINK_REQ_FAST)) { 281
296 /* leave timer interval "as is" if already at a "normal" rate */ 282 if (tipc_node(req->domain) && req->num_nodes) {
297 } else { 283 req->timer_intv = TIPC_LINK_REQ_INACTIVE;
298 req->timer_intv *= 2; 284 goto exit;
299 if (req->timer_intv > TIPC_LINK_REQ_FAST)
300 req->timer_intv = TIPC_LINK_REQ_FAST;
301 if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
302 (req->bearer->nodes.count))
303 req->timer_intv = TIPC_LINK_REQ_SLOW;
304 } 285 }
305 k_start_timer(&req->timer, req->timer_intv);
306 286
307 spin_unlock_bh(&req->bearer->publ.lock); 287 /*
288 * Send discovery message, then update discovery timer
289 *
290 * Keep doubling time between requests until limit is reached;
291 * hold at fast polling rate if don't have any associated nodes,
292 * otherwise hold at slow polling rate
293 */
294
295 disc_send_msg(req);
296
297 req->timer_intv *= 2;
298 if (req->num_nodes)
299 max_delay = TIPC_LINK_REQ_SLOW;
300 else
301 max_delay = TIPC_LINK_REQ_FAST;
302 if (req->timer_intv > max_delay)
303 req->timer_intv = max_delay;
304
305 k_start_timer(&req->timer, req->timer_intv);
306exit:
307 spin_unlock_bh(&req->bearer->lock);
308} 308}
309 309
310/** 310/**
311 * tipc_disc_init_link_req - start sending periodic link setup requests 311 * tipc_disc_create - create object to send periodic link setup requests
312 * @b_ptr: ptr to bearer issuing requests 312 * @b_ptr: ptr to bearer issuing requests
313 * @dest: destination address for request messages 313 * @dest: destination address for request messages
314 * @dest_domain: network domain of node(s) which should respond to message 314 * @dest_domain: network domain to which links can be established
315 * @req_links: max number of desired links
316 * 315 *
317 * Returns pointer to link request structure, or NULL if unable to create. 316 * Returns 0 if successful, otherwise -errno.
318 */ 317 */
319 318
320struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, 319int tipc_disc_create(struct tipc_bearer *b_ptr,
321 const struct tipc_media_addr *dest, 320 struct tipc_media_addr *dest, u32 dest_domain)
322 u32 dest_domain,
323 u32 req_links)
324{ 321{
325 struct link_req *req; 322 struct link_req *req;
326 323
327 req = kmalloc(sizeof(*req), GFP_ATOMIC); 324 req = kmalloc(sizeof(*req), GFP_ATOMIC);
328 if (!req) 325 if (!req)
329 return NULL; 326 return -ENOMEM;
330 327
331 req->buf = tipc_disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); 328 req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr);
332 if (!req->buf) { 329 if (!req->buf) {
333 kfree(req); 330 kfree(req);
334 return NULL; 331 return -ENOMSG;
335 } 332 }
336 333
337 memcpy(&req->dest, dest, sizeof(*dest)); 334 memcpy(&req->dest, dest, sizeof(*dest));
338 req->bearer = b_ptr; 335 req->bearer = b_ptr;
336 req->domain = dest_domain;
337 req->num_nodes = 0;
339 req->timer_intv = TIPC_LINK_REQ_INIT; 338 req->timer_intv = TIPC_LINK_REQ_INIT;
340 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); 339 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
341 k_start_timer(&req->timer, req->timer_intv); 340 k_start_timer(&req->timer, req->timer_intv);
342 return req; 341 b_ptr->link_req = req;
342 disc_send_msg(req);
343 return 0;
344}
345
346/**
347 * tipc_disc_delete - destroy object sending periodic link setup requests
348 * @req: ptr to link request structure
349 */
350
351void tipc_disc_delete(struct link_req *req)
352{
353 k_cancel_timer(&req->timer);
354 k_term_timer(&req->timer);
355 buf_discard(req->buf);
356 kfree(req);
343} 357}
344 358