diff options
author | David S. Miller <davem@davemloft.net> | 2015-02-09 16:20:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-09 16:20:53 -0500 |
commit | 9dce285b70c157754d753203112cfef22770b1f9 (patch) | |
tree | 4859799a8311ecd637e2a582600af1057a78e08b /net/tipc/node.c | |
parent | c8ac18f2006b2926ce375c01646b2f487d1c33b2 (diff) | |
parent | 941787b82982b3f33ac398c8c00035ddd0f8c514 (diff) |
Merge branch 'tipc-next'
Richard Alpe says:
====================
tipc: new compat layer for the legacy NL API
This is a compatibility / transcoding layer for the old netlink API.
It relies on the new netlink API to collect data or perform actions
(dumpit / doit).
The main benefit of this compat layer is that it removes a lot of
complex code from the tipc core as only the new API needs to be able
harness data or perform actions. I.e. the compat layer isn't concerned
with locking or how the internal data-structures look. As long as the
new API stays relatively intact the compat layer should be fine.
The main challenge in this compat layer is the randomness of the legacy
API. Some commands send binary data and some send ASCII data, some are
very picky in optimizing there buffer sizes and some just don't care.
Most legacy commands put there data in a single TLV (data container) but some
segment the data into multiple TLV's. This list of randomness goes on and on..
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 131 |
1 files changed, 2 insertions, 129 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index 52308498f208..86152de8248d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "config.h" | 38 | #include "link.h" |
39 | #include "node.h" | 39 | #include "node.h" |
40 | #include "name_distr.h" | 40 | #include "name_distr.h" |
41 | #include "socket.h" | 41 | #include "socket.h" |
@@ -120,7 +120,6 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr) | |||
120 | list_add_tail_rcu(&n_ptr->list, &temp_node->list); | 120 | list_add_tail_rcu(&n_ptr->list, &temp_node->list); |
121 | n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; | 121 | n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; |
122 | n_ptr->signature = INVALID_NODE_SIG; | 122 | n_ptr->signature = INVALID_NODE_SIG; |
123 | tn->num_nodes++; | ||
124 | exit: | 123 | exit: |
125 | spin_unlock_bh(&tn->node_list_lock); | 124 | spin_unlock_bh(&tn->node_list_lock); |
126 | return n_ptr; | 125 | return n_ptr; |
@@ -131,8 +130,6 @@ static void tipc_node_delete(struct tipc_net *tn, struct tipc_node *n_ptr) | |||
131 | list_del_rcu(&n_ptr->list); | 130 | list_del_rcu(&n_ptr->list); |
132 | hlist_del_rcu(&n_ptr->hash); | 131 | hlist_del_rcu(&n_ptr->hash); |
133 | kfree_rcu(n_ptr, rcu); | 132 | kfree_rcu(n_ptr, rcu); |
134 | |||
135 | tn->num_nodes--; | ||
136 | } | 133 | } |
137 | 134 | ||
138 | void tipc_node_stop(struct net *net) | 135 | void tipc_node_stop(struct net *net) |
@@ -319,27 +316,18 @@ int tipc_node_is_up(struct tipc_node *n_ptr) | |||
319 | 316 | ||
320 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 317 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) |
321 | { | 318 | { |
322 | struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); | ||
323 | |||
324 | n_ptr->links[l_ptr->bearer_id] = l_ptr; | 319 | n_ptr->links[l_ptr->bearer_id] = l_ptr; |
325 | spin_lock_bh(&tn->node_list_lock); | ||
326 | tn->num_links++; | ||
327 | spin_unlock_bh(&tn->node_list_lock); | ||
328 | n_ptr->link_cnt++; | 320 | n_ptr->link_cnt++; |
329 | } | 321 | } |
330 | 322 | ||
331 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 323 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) |
332 | { | 324 | { |
333 | struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); | ||
334 | int i; | 325 | int i; |
335 | 326 | ||
336 | for (i = 0; i < MAX_BEARERS; i++) { | 327 | for (i = 0; i < MAX_BEARERS; i++) { |
337 | if (l_ptr != n_ptr->links[i]) | 328 | if (l_ptr != n_ptr->links[i]) |
338 | continue; | 329 | continue; |
339 | n_ptr->links[i] = NULL; | 330 | n_ptr->links[i] = NULL; |
340 | spin_lock_bh(&tn->node_list_lock); | ||
341 | tn->num_links--; | ||
342 | spin_unlock_bh(&tn->node_list_lock); | ||
343 | n_ptr->link_cnt--; | 331 | n_ptr->link_cnt--; |
344 | } | 332 | } |
345 | } | 333 | } |
@@ -416,121 +404,6 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
416 | } | 404 | } |
417 | } | 405 | } |
418 | 406 | ||
419 | struct sk_buff *tipc_node_get_nodes(struct net *net, const void *req_tlv_area, | ||
420 | int req_tlv_space) | ||
421 | { | ||
422 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
423 | u32 domain; | ||
424 | struct sk_buff *buf; | ||
425 | struct tipc_node *n_ptr; | ||
426 | struct tipc_node_info node_info; | ||
427 | u32 payload_size; | ||
428 | |||
429 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
430 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
431 | |||
432 | domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | ||
433 | if (!tipc_addr_domain_valid(domain)) | ||
434 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
435 | " (network address)"); | ||
436 | |||
437 | spin_lock_bh(&tn->node_list_lock); | ||
438 | if (!tn->num_nodes) { | ||
439 | spin_unlock_bh(&tn->node_list_lock); | ||
440 | return tipc_cfg_reply_none(); | ||
441 | } | ||
442 | |||
443 | /* For now, get space for all other nodes */ | ||
444 | payload_size = TLV_SPACE(sizeof(node_info)) * tn->num_nodes; | ||
445 | if (payload_size > 32768u) { | ||
446 | spin_unlock_bh(&tn->node_list_lock); | ||
447 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
448 | " (too many nodes)"); | ||
449 | } | ||
450 | spin_unlock_bh(&tn->node_list_lock); | ||
451 | |||
452 | buf = tipc_cfg_reply_alloc(payload_size); | ||
453 | if (!buf) | ||
454 | return NULL; | ||
455 | |||
456 | /* Add TLVs for all nodes in scope */ | ||
457 | rcu_read_lock(); | ||
458 | list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { | ||
459 | if (!tipc_in_scope(domain, n_ptr->addr)) | ||
460 | continue; | ||
461 | node_info.addr = htonl(n_ptr->addr); | ||
462 | node_info.up = htonl(tipc_node_is_up(n_ptr)); | ||
463 | tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, | ||
464 | &node_info, sizeof(node_info)); | ||
465 | } | ||
466 | rcu_read_unlock(); | ||
467 | return buf; | ||
468 | } | ||
469 | |||
470 | struct sk_buff *tipc_node_get_links(struct net *net, const void *req_tlv_area, | ||
471 | int req_tlv_space) | ||
472 | { | ||
473 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
474 | u32 domain; | ||
475 | struct sk_buff *buf; | ||
476 | struct tipc_node *n_ptr; | ||
477 | struct tipc_link_info link_info; | ||
478 | u32 payload_size; | ||
479 | |||
480 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
481 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
482 | |||
483 | domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | ||
484 | if (!tipc_addr_domain_valid(domain)) | ||
485 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
486 | " (network address)"); | ||
487 | |||
488 | if (!tn->own_addr) | ||
489 | return tipc_cfg_reply_none(); | ||
490 | |||
491 | spin_lock_bh(&tn->node_list_lock); | ||
492 | /* Get space for all unicast links + broadcast link */ | ||
493 | payload_size = TLV_SPACE((sizeof(link_info)) * (tn->num_links + 1)); | ||
494 | if (payload_size > 32768u) { | ||
495 | spin_unlock_bh(&tn->node_list_lock); | ||
496 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
497 | " (too many links)"); | ||
498 | } | ||
499 | spin_unlock_bh(&tn->node_list_lock); | ||
500 | |||
501 | buf = tipc_cfg_reply_alloc(payload_size); | ||
502 | if (!buf) | ||
503 | return NULL; | ||
504 | |||
505 | /* Add TLV for broadcast link */ | ||
506 | link_info.dest = htonl(tipc_cluster_mask(tn->own_addr)); | ||
507 | link_info.up = htonl(1); | ||
508 | strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); | ||
509 | tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); | ||
510 | |||
511 | /* Add TLVs for any other links in scope */ | ||
512 | rcu_read_lock(); | ||
513 | list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { | ||
514 | u32 i; | ||
515 | |||
516 | if (!tipc_in_scope(domain, n_ptr->addr)) | ||
517 | continue; | ||
518 | tipc_node_lock(n_ptr); | ||
519 | for (i = 0; i < MAX_BEARERS; i++) { | ||
520 | if (!n_ptr->links[i]) | ||
521 | continue; | ||
522 | link_info.dest = htonl(n_ptr->addr); | ||
523 | link_info.up = htonl(tipc_link_is_up(n_ptr->links[i])); | ||
524 | strcpy(link_info.str, n_ptr->links[i]->name); | ||
525 | tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, | ||
526 | &link_info, sizeof(link_info)); | ||
527 | } | ||
528 | tipc_node_unlock(n_ptr); | ||
529 | } | ||
530 | rcu_read_unlock(); | ||
531 | return buf; | ||
532 | } | ||
533 | |||
534 | /** | 407 | /** |
535 | * tipc_node_get_linkname - get the name of a link | 408 | * tipc_node_get_linkname - get the name of a link |
536 | * | 409 | * |
@@ -623,7 +496,7 @@ static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) | |||
623 | void *hdr; | 496 | void *hdr; |
624 | struct nlattr *attrs; | 497 | struct nlattr *attrs; |
625 | 498 | ||
626 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, | 499 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, |
627 | NLM_F_MULTI, TIPC_NL_NODE_GET); | 500 | NLM_F_MULTI, TIPC_NL_NODE_GET); |
628 | if (!hdr) | 501 | if (!hdr) |
629 | return -EMSGSIZE; | 502 | return -EMSGSIZE; |