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