1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include "core.h"
38#include "link.h"
39#include "discover.h"
40
41#define TIPC_LINK_REQ_INIT 125
42#define TIPC_LINK_REQ_FAST 1000
43#define TIPC_LINK_REQ_SLOW 60000
44#define TIPC_LINK_REQ_INACTIVE 0xffffffff
45
46
47
48
49
50
51
52
53
54
55
56
57struct tipc_link_req {
58 struct tipc_bearer *bearer;
59 struct tipc_media_addr dest;
60 u32 domain;
61 int num_nodes;
62 struct sk_buff *buf;
63 struct timer_list timer;
64 unsigned int timer_intv;
65};
66
67
68
69
70
71
72
73static struct sk_buff *tipc_disc_init_msg(u32 type,
74 u32 dest_domain,
75 struct tipc_bearer *b_ptr)
76{
77 struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE);
78 struct tipc_msg *msg;
79
80 if (buf) {
81 msg = buf_msg(buf);
82 tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain);
83 msg_set_non_seq(msg, 1);
84 msg_set_node_sig(msg, tipc_random);
85 msg_set_dest_domain(msg, dest_domain);
86 msg_set_bc_netid(msg, tipc_net_id);
87 b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg));
88 }
89 return buf;
90}
91
92
93
94
95
96
97
98static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
99 struct tipc_media_addr *media_addr)
100{
101 char node_addr_str[16];
102 char media_addr_str[64];
103
104 tipc_addr_string_fill(node_addr_str, node_addr);
105 tipc_media_addr_printf(media_addr_str, sizeof(media_addr_str),
106 media_addr);
107 pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str,
108 media_addr_str, b_ptr->name);
109}
110
111
112
113
114
115
116void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
117{
118 struct tipc_node *n_ptr;
119 struct tipc_link *link;
120 struct tipc_media_addr media_addr;
121 struct sk_buff *rbuf;
122 struct tipc_msg *msg = buf_msg(buf);
123 u32 dest = msg_dest_domain(msg);
124 u32 orig = msg_prevnode(msg);
125 u32 net_id = msg_bc_netid(msg);
126 u32 type = msg_type(msg);
127 u32 signature = msg_node_sig(msg);
128 int addr_mismatch;
129 int link_fully_up;
130
131 media_addr.broadcast = 1;
132 b_ptr->media->msg2addr(b_ptr, &media_addr, msg_media_addr(msg));
133 kfree_skb(buf);
134
135
136 if (net_id != tipc_net_id)
137 return;
138 if (media_addr.broadcast)
139 return;
140 if (!tipc_addr_domain_valid(dest))
141 return;
142 if (!tipc_addr_node_valid(orig))
143 return;
144 if (orig == tipc_own_addr) {
145 if (memcmp(&media_addr, &b_ptr->addr, sizeof(media_addr)))
146 disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
147 return;
148 }
149 if (!tipc_in_scope(dest, tipc_own_addr))
150 return;
151 if (!tipc_in_scope(b_ptr->link_req->domain, orig))
152 return;
153
154
155 n_ptr = tipc_node_find(orig);
156 if (!n_ptr) {
157 n_ptr = tipc_node_create(orig);
158 if (!n_ptr)
159 return;
160 }
161 tipc_node_lock(n_ptr);
162
163
164 link = n_ptr->links[b_ptr->identity];
165 addr_mismatch = (link != NULL) &&
166 memcmp(&link->media_addr, &media_addr, sizeof(media_addr));
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 if (signature != n_ptr->signature) {
186 if (n_ptr->working_links == 0) {
187 struct tipc_link *curr_link;
188 int i;
189
190 for (i = 0; i < MAX_BEARERS; i++) {
191 curr_link = n_ptr->links[i];
192 if (curr_link) {
193 memset(&curr_link->media_addr, 0,
194 sizeof(media_addr));
195 tipc_link_reset(curr_link);
196 }
197 }
198 addr_mismatch = (link != NULL);
199 } else if (tipc_link_is_up(link) && !addr_mismatch) {
200
201 } else {
202 disc_dupl_alert(b_ptr, orig, &media_addr);
203 tipc_node_unlock(n_ptr);
204 return;
205 }
206 n_ptr->signature = signature;
207 }
208
209
210
211
212
213
214
215
216
217
218
219 if (addr_mismatch) {
220 if (tipc_link_is_up(link)) {
221 disc_dupl_alert(b_ptr, orig, &media_addr);
222 tipc_node_unlock(n_ptr);
223 return;
224 } else {
225 memcpy(&link->media_addr, &media_addr,
226 sizeof(media_addr));
227 tipc_link_reset(link);
228 }
229 }
230
231
232 if (!link) {
233 link = tipc_link_create(n_ptr, b_ptr, &media_addr);
234 if (!link) {
235 tipc_node_unlock(n_ptr);
236 return;
237 }
238 }
239
240
241 link_fully_up = link_working_working(link);
242
243 if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {
244 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
245 if (rbuf) {
246 tipc_bearer_send(b_ptr, rbuf, &media_addr);
247 kfree_skb(rbuf);
248 }
249 }
250
251 tipc_node_unlock(n_ptr);
252}
253
254
255
256
257
258
259
260
261static void disc_update(struct tipc_link_req *req)
262{
263 if (!req->num_nodes) {
264 if ((req->timer_intv == TIPC_LINK_REQ_INACTIVE) ||
265 (req->timer_intv > TIPC_LINK_REQ_FAST)) {
266 req->timer_intv = TIPC_LINK_REQ_INIT;
267 k_start_timer(&req->timer, req->timer_intv);
268 }
269 }
270}
271
272
273
274
275
276void tipc_disc_add_dest(struct tipc_link_req *req)
277{
278 req->num_nodes++;
279}
280
281
282
283
284
285void tipc_disc_remove_dest(struct tipc_link_req *req)
286{
287 req->num_nodes--;
288 disc_update(req);
289}
290
291
292
293
294
295static void disc_send_msg(struct tipc_link_req *req)
296{
297 if (!req->bearer->blocked)
298 tipc_bearer_send(req->bearer, req->buf, &req->dest);
299}
300
301
302
303
304
305
306
307static void disc_timeout(struct tipc_link_req *req)
308{
309 int max_delay;
310
311 spin_lock_bh(&req->bearer->lock);
312
313
314 if (tipc_node(req->domain) && req->num_nodes) {
315 req->timer_intv = TIPC_LINK_REQ_INACTIVE;
316 goto exit;
317 }
318
319
320
321
322
323
324
325
326 disc_send_msg(req);
327
328 req->timer_intv *= 2;
329 if (req->num_nodes)
330 max_delay = TIPC_LINK_REQ_SLOW;
331 else
332 max_delay = TIPC_LINK_REQ_FAST;
333 if (req->timer_intv > max_delay)
334 req->timer_intv = max_delay;
335
336 k_start_timer(&req->timer, req->timer_intv);
337exit:
338 spin_unlock_bh(&req->bearer->lock);
339}
340
341
342
343
344
345
346
347
348
349int tipc_disc_create(struct tipc_bearer *b_ptr,
350 struct tipc_media_addr *dest, u32 dest_domain)
351{
352 struct tipc_link_req *req;
353
354 req = kmalloc(sizeof(*req), GFP_ATOMIC);
355 if (!req)
356 return -ENOMEM;
357
358 req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr);
359 if (!req->buf) {
360 kfree(req);
361 return -ENOMSG;
362 }
363
364 memcpy(&req->dest, dest, sizeof(*dest));
365 req->bearer = b_ptr;
366 req->domain = dest_domain;
367 req->num_nodes = 0;
368 req->timer_intv = TIPC_LINK_REQ_INIT;
369 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
370 k_start_timer(&req->timer, req->timer_intv);
371 b_ptr->link_req = req;
372 disc_send_msg(req);
373 return 0;
374}
375
376
377
378
379
380void tipc_disc_delete(struct tipc_link_req *req)
381{
382 k_cancel_timer(&req->timer);
383 k_term_timer(&req->timer);
384 kfree_skb(req->buf);
385 kfree(req);
386}
387