aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/name_distr.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/name_distr.c')
-rw-r--r--net/tipc/name_distr.c140
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
74int sysctl_tipc_named_timeout __read_mostly = 2000;
75
76/**
77 * struct tipc_dist_queue - queue holding deferred name table updates
78 */
79static struct list_head tipc_dist_queue = LIST_HEAD_INIT(tipc_dist_queue);
80
81struct 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 */
287static 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 */
321static 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 */
340void 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 */
268void tipc_named_rcv(struct sk_buff *buf) 366void 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}