diff options
Diffstat (limited to 'net/tipc/name_distr.c')
-rw-r--r-- | net/tipc/name_distr.c | 140 |
1 files changed, 103 insertions, 37 deletions
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index dcc15bcd5692..376d2bb51d8d 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
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, 2014, Ericsson AB |
5 | * Copyright (c) 2005, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2005, 2010-2011, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -71,6 +71,21 @@ static struct publ_list *publ_lists[] = { | |||
71 | }; | 71 | }; |
72 | 72 | ||
73 | 73 | ||
74 | int sysctl_tipc_named_timeout __read_mostly = 2000; | ||
75 | |||
76 | /** | ||
77 | * struct tipc_dist_queue - queue holding deferred name table updates | ||
78 | */ | ||
79 | static struct list_head tipc_dist_queue = LIST_HEAD_INIT(tipc_dist_queue); | ||
80 | |||
81 | struct distr_queue_item { | ||
82 | struct distr_item i; | ||
83 | u32 dtype; | ||
84 | u32 node; | ||
85 | unsigned long expires; | ||
86 | struct list_head next; | ||
87 | }; | ||
88 | |||
74 | /** | 89 | /** |
75 | * publ_to_item - add publication info to a publication message | 90 | * publ_to_item - add publication info to a publication message |
76 | */ | 91 | */ |
@@ -263,54 +278,105 @@ static void named_purge_publ(struct publication *publ) | |||
263 | } | 278 | } |
264 | 279 | ||
265 | /** | 280 | /** |
281 | * tipc_update_nametbl - try to process a nametable update and notify | ||
282 | * subscribers | ||
283 | * | ||
284 | * tipc_nametbl_lock must be held. | ||
285 | * Returns the publication item if successful, otherwise NULL. | ||
286 | */ | ||
287 | static bool tipc_update_nametbl(struct distr_item *i, u32 node, u32 dtype) | ||
288 | { | ||
289 | struct publication *publ = NULL; | ||
290 | |||
291 | if (dtype == PUBLICATION) { | ||
292 | publ = tipc_nametbl_insert_publ(ntohl(i->type), ntohl(i->lower), | ||
293 | ntohl(i->upper), | ||
294 | TIPC_CLUSTER_SCOPE, node, | ||
295 | ntohl(i->ref), ntohl(i->key)); | ||
296 | if (publ) { | ||
297 | tipc_nodesub_subscribe(&publ->subscr, node, publ, | ||
298 | (net_ev_handler) | ||
299 | named_purge_publ); | ||
300 | return true; | ||
301 | } | ||
302 | } else if (dtype == WITHDRAWAL) { | ||
303 | publ = tipc_nametbl_remove_publ(ntohl(i->type), ntohl(i->lower), | ||
304 | node, ntohl(i->ref), | ||
305 | ntohl(i->key)); | ||
306 | if (publ) { | ||
307 | tipc_nodesub_unsubscribe(&publ->subscr); | ||
308 | kfree(publ); | ||
309 | return true; | ||
310 | } | ||
311 | } else { | ||
312 | pr_warn("Unrecognized name table message received\n"); | ||
313 | } | ||
314 | return false; | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * tipc_named_add_backlog - add a failed name table update to the backlog | ||
319 | * | ||
320 | */ | ||
321 | static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node) | ||
322 | { | ||
323 | struct distr_queue_item *e; | ||
324 | unsigned long now = get_jiffies_64(); | ||
325 | |||
326 | e = kzalloc(sizeof(*e), GFP_ATOMIC); | ||
327 | if (!e) | ||
328 | return; | ||
329 | e->dtype = type; | ||
330 | e->node = node; | ||
331 | e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout); | ||
332 | memcpy(e, i, sizeof(*i)); | ||
333 | list_add_tail(&e->next, &tipc_dist_queue); | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * tipc_named_process_backlog - try to process any pending name table updates | ||
338 | * from the network. | ||
339 | */ | ||
340 | void tipc_named_process_backlog(void) | ||
341 | { | ||
342 | struct distr_queue_item *e, *tmp; | ||
343 | char addr[16]; | ||
344 | unsigned long now = get_jiffies_64(); | ||
345 | |||
346 | list_for_each_entry_safe(e, tmp, &tipc_dist_queue, next) { | ||
347 | if (time_after(e->expires, now)) { | ||
348 | if (!tipc_update_nametbl(&e->i, e->node, e->dtype)) | ||
349 | continue; | ||
350 | } else { | ||
351 | tipc_addr_string_fill(addr, e->node); | ||
352 | pr_warn_ratelimited("Dropping name table update (%d) of {%u, %u, %u} from %s key=%u\n", | ||
353 | e->dtype, ntohl(e->i.type), | ||
354 | ntohl(e->i.lower), | ||
355 | ntohl(e->i.upper), | ||
356 | addr, ntohl(e->i.key)); | ||
357 | } | ||
358 | list_del(&e->next); | ||
359 | kfree(e); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /** | ||
266 | * tipc_named_rcv - process name table update message sent by another node | 364 | * tipc_named_rcv - process name table update message sent by another node |
267 | */ | 365 | */ |
268 | void tipc_named_rcv(struct sk_buff *buf) | 366 | void tipc_named_rcv(struct sk_buff *buf) |
269 | { | 367 | { |
270 | struct publication *publ; | ||
271 | struct tipc_msg *msg = buf_msg(buf); | 368 | struct tipc_msg *msg = buf_msg(buf); |
272 | struct distr_item *item = (struct distr_item *)msg_data(msg); | 369 | struct distr_item *item = (struct distr_item *)msg_data(msg); |
273 | u32 count = msg_data_sz(msg) / ITEM_SIZE; | 370 | u32 count = msg_data_sz(msg) / ITEM_SIZE; |
371 | u32 node = msg_orignode(msg); | ||
274 | 372 | ||
275 | write_lock_bh(&tipc_nametbl_lock); | 373 | write_lock_bh(&tipc_nametbl_lock); |
276 | while (count--) { | 374 | while (count--) { |
277 | if (msg_type(msg) == PUBLICATION) { | 375 | if (!tipc_update_nametbl(item, node, msg_type(msg))) |
278 | publ = tipc_nametbl_insert_publ(ntohl(item->type), | 376 | tipc_named_add_backlog(item, msg_type(msg), node); |
279 | ntohl(item->lower), | ||
280 | ntohl(item->upper), | ||
281 | TIPC_CLUSTER_SCOPE, | ||
282 | msg_orignode(msg), | ||
283 | ntohl(item->ref), | ||
284 | ntohl(item->key)); | ||
285 | if (publ) { | ||
286 | tipc_nodesub_subscribe(&publ->subscr, | ||
287 | msg_orignode(msg), | ||
288 | publ, | ||
289 | (net_ev_handler) | ||
290 | named_purge_publ); | ||
291 | } | ||
292 | } else if (msg_type(msg) == WITHDRAWAL) { | ||
293 | publ = tipc_nametbl_remove_publ(ntohl(item->type), | ||
294 | ntohl(item->lower), | ||
295 | msg_orignode(msg), | ||
296 | ntohl(item->ref), | ||
297 | ntohl(item->key)); | ||
298 | |||
299 | if (publ) { | ||
300 | tipc_nodesub_unsubscribe(&publ->subscr); | ||
301 | kfree(publ); | ||
302 | } else { | ||
303 | pr_err("Unable to remove publication by node 0x%x\n" | ||
304 | " (type=%u, lower=%u, ref=%u, key=%u)\n", | ||
305 | msg_orignode(msg), ntohl(item->type), | ||
306 | ntohl(item->lower), ntohl(item->ref), | ||
307 | ntohl(item->key)); | ||
308 | } | ||
309 | } else { | ||
310 | pr_warn("Unrecognized name table message received\n"); | ||
311 | } | ||
312 | item++; | 377 | item++; |
313 | } | 378 | } |
379 | tipc_named_process_backlog(); | ||
314 | write_unlock_bh(&tipc_nametbl_lock); | 380 | write_unlock_bh(&tipc_nametbl_lock); |
315 | kfree_skb(buf); | 381 | kfree_skb(buf); |
316 | } | 382 | } |