From 8dea78da5cee153b8af9c07a2745f6c55057fe12 Mon Sep 17 00:00:00 2001 From: Jonathan Herman Date: Thu, 17 Jan 2013 16:15:55 -0500 Subject: Patched in Tegra support. --- net/tipc/node.c | 180 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 115 insertions(+), 65 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/node.c b/net/tipc/node.c index 48f39dd3eae..2d106ef4fa4 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1,7 +1,7 @@ /* * net/tipc/node.c: TIPC node management routines * - * Copyright (c) 2000-2006, 2012 Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005-2006, 2010-2011, Wind River Systems * All rights reserved. * @@ -39,8 +39,6 @@ #include "node.h" #include "name_distr.h" -#define NODE_HTABLE_SIZE 512 - static void node_lost_contact(struct tipc_node *n_ptr); static void node_established_contact(struct tipc_node *n_ptr); @@ -51,27 +49,18 @@ LIST_HEAD(tipc_node_list); static u32 tipc_num_nodes; static atomic_t tipc_num_links = ATOMIC_INIT(0); +u32 tipc_own_tag; -/* - * A trivial power-of-two bitmask technique is used for speed, since this - * operation is done for every incoming TIPC packet. The number of hash table - * entries has been chosen so that no hash chain exceeds 8 nodes and will - * usually be much smaller (typically only a single node). - */ -static unsigned int tipc_hashfn(u32 addr) -{ - return addr & (NODE_HTABLE_SIZE - 1); -} - -/* +/** * tipc_node_find - locate specified node object, if it exists */ + struct tipc_node *tipc_node_find(u32 addr) { struct tipc_node *node; struct hlist_node *pos; - if (unlikely(!in_own_cluster_exact(addr))) + if (unlikely(!in_own_cluster(addr))) return NULL; hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) { @@ -90,6 +79,7 @@ struct tipc_node *tipc_node_find(u32 addr) * time. (It would be preferable to switch to holding net_lock in write mode, * but this is a non-trivial change.) */ + struct tipc_node *tipc_node_create(u32 addr) { struct tipc_node *n_ptr, *temp_node; @@ -105,7 +95,7 @@ struct tipc_node *tipc_node_create(u32 addr) n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); if (!n_ptr) { spin_unlock_bh(&node_create_lock); - pr_warn("Node creation failed, no memory\n"); + warn("Node creation failed, no memory\n"); return NULL; } @@ -122,8 +112,6 @@ struct tipc_node *tipc_node_create(u32 addr) break; } list_add_tail(&n_ptr->list, &temp_node->list); - n_ptr->block_setup = WAIT_PEER_DOWN; - n_ptr->signature = INVALID_NODE_SIG; tipc_num_nodes++; @@ -140,19 +128,21 @@ void tipc_node_delete(struct tipc_node *n_ptr) tipc_num_nodes--; } + /** * tipc_node_link_up - handle addition of link * * Link becomes active (alone or shared) or standby, depending on its priority. */ -void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) + +void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr) { - struct tipc_link **active = &n_ptr->active_links[0]; + struct link **active = &n_ptr->active_links[0]; n_ptr->working_links++; - pr_info("Established link <%s> on network plane %c\n", - l_ptr->name, l_ptr->b_ptr->net_plane); + info("Established link <%s> on network plane %c\n", + l_ptr->name, l_ptr->b_ptr->net_plane); if (!active[0]) { active[0] = active[1] = l_ptr; @@ -160,7 +150,7 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) return; } if (l_ptr->priority < active[0]->priority) { - pr_info("New link <%s> becomes standby\n", l_ptr->name); + info("New link <%s> becomes standby\n", l_ptr->name); return; } tipc_link_send_duplicate(active[0], l_ptr); @@ -168,25 +158,26 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) active[0] = l_ptr; return; } - pr_info("Old link <%s> becomes standby\n", active[0]->name); + info("Old link <%s> becomes standby\n", active[0]->name); if (active[1] != active[0]) - pr_info("Old link <%s> becomes standby\n", active[1]->name); + info("Old link <%s> becomes standby\n", active[1]->name); active[0] = active[1] = l_ptr; } /** * node_select_active_links - select active link */ + static void node_select_active_links(struct tipc_node *n_ptr) { - struct tipc_link **active = &n_ptr->active_links[0]; + struct link **active = &n_ptr->active_links[0]; u32 i; u32 highest_prio = 0; active[0] = active[1] = NULL; for (i = 0; i < MAX_BEARERS; i++) { - struct tipc_link *l_ptr = n_ptr->links[i]; + struct link *l_ptr = n_ptr->links[i]; if (!l_ptr || !tipc_link_is_up(l_ptr) || (l_ptr->priority < highest_prio)) @@ -204,18 +195,19 @@ static void node_select_active_links(struct tipc_node *n_ptr) /** * tipc_node_link_down - handle loss of link */ -void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) + +void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr) { - struct tipc_link **active; + struct link **active; n_ptr->working_links--; if (!tipc_link_is_active(l_ptr)) { - pr_info("Lost standby link <%s> on network plane %c\n", - l_ptr->name, l_ptr->b_ptr->net_plane); + info("Lost standby link <%s> on network plane %c\n", + l_ptr->name, l_ptr->b_ptr->net_plane); return; } - pr_info("Lost link <%s> on network plane %c\n", + info("Lost link <%s> on network plane %c\n", l_ptr->name, l_ptr->b_ptr->net_plane); active = &n_ptr->active_links[0]; @@ -246,29 +238,81 @@ int tipc_node_is_up(struct tipc_node *n_ptr) return tipc_node_active_links(n_ptr); } -void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) +void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr) { n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; atomic_inc(&tipc_num_links); n_ptr->link_cnt++; } -void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) +void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) { n_ptr->links[l_ptr->b_ptr->identity] = NULL; atomic_dec(&tipc_num_links); n_ptr->link_cnt--; } +/* + * Routing table management - five cases to handle: + * + * 1: A link towards a zone/cluster external node comes up. + * => Send a multicast message updating routing tables of all + * system nodes within own cluster that the new destination + * can be reached via this node. + * (node.establishedContact()=>cluster.multicastNewRoute()) + * + * 2: A link towards a slave node comes up. + * => Send a multicast message updating routing tables of all + * system nodes within own cluster that the new destination + * can be reached via this node. + * (node.establishedContact()=>cluster.multicastNewRoute()) + * => Send a message to the slave node about existence + * of all system nodes within cluster: + * (node.establishedContact()=>cluster.sendLocalRoutes()) + * + * 3: A new cluster local system node becomes available. + * => Send message(s) to this particular node containing + * information about all cluster external and slave + * nodes which can be reached via this node. + * (node.establishedContact()==>network.sendExternalRoutes()) + * (node.establishedContact()==>network.sendSlaveRoutes()) + * => Send messages to all directly connected slave nodes + * containing information about the existence of the new node + * (node.establishedContact()=>cluster.multicastNewRoute()) + * + * 4: The link towards a zone/cluster external node or slave + * node goes down. + * => Send a multcast message updating routing tables of all + * nodes within cluster that the new destination can not any + * longer be reached via this node. + * (node.lostAllLinks()=>cluster.bcastLostRoute()) + * + * 5: A cluster local system node becomes unavailable. + * => Remove all references to this node from the local + * routing tables. Note: This is a completely node + * local operation. + * (node.lostAllLinks()=>network.removeAsRouter()) + * => Send messages to all directly connected slave nodes + * containing information about loss of the node + * (node.establishedContact()=>cluster.multicastLostRoute()) + * + */ + static void node_established_contact(struct tipc_node *n_ptr) { tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); - n_ptr->bclink.oos_state = 0; + + /* Syncronize broadcast acks */ n_ptr->bclink.acked = tipc_bclink_get_last_sent(); - tipc_bclink_add_node(n_ptr->addr); + + if (n_ptr->bclink.supported) { + tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr); + if (n_ptr->addr < tipc_own_addr) + tipc_own_tag++; + } } -static void node_name_purge_complete(unsigned long node_addr) +static void node_cleanup_finished(unsigned long node_addr) { struct tipc_node *n_ptr; @@ -276,7 +320,7 @@ static void node_name_purge_complete(unsigned long node_addr) n_ptr = tipc_node_find(node_addr); if (n_ptr) { tipc_node_lock(n_ptr); - n_ptr->block_setup &= ~WAIT_NAMES_GONE; + n_ptr->cleanup_required = 0; tipc_node_unlock(n_ptr); } read_unlock_bh(&tipc_net_lock); @@ -287,32 +331,32 @@ static void node_lost_contact(struct tipc_node *n_ptr) char addr_string[16]; u32 i; - pr_info("Lost contact with %s\n", - tipc_addr_string_fill(addr_string, n_ptr->addr)); - - /* Flush broadcast link info associated with lost node */ - if (n_ptr->bclink.recv_permitted) { - while (n_ptr->bclink.deferred_head) { - struct sk_buff *buf = n_ptr->bclink.deferred_head; - n_ptr->bclink.deferred_head = buf->next; - kfree_skb(buf); - } - n_ptr->bclink.deferred_size = 0; - - if (n_ptr->bclink.defragm) { - kfree_skb(n_ptr->bclink.defragm); - n_ptr->bclink.defragm = NULL; - } - - tipc_bclink_remove_node(n_ptr->addr); - tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ); + /* Clean up broadcast reception remains */ + n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; + while (n_ptr->bclink.deferred_head) { + struct sk_buff *buf = n_ptr->bclink.deferred_head; + n_ptr->bclink.deferred_head = buf->next; + buf_discard(buf); + } + if (n_ptr->bclink.defragm) { + buf_discard(n_ptr->bclink.defragm); + n_ptr->bclink.defragm = NULL; + } - n_ptr->bclink.recv_permitted = false; + if (n_ptr->bclink.supported) { + tipc_bclink_acknowledge(n_ptr, + mod(n_ptr->bclink.acked + 10000)); + tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr); + if (n_ptr->addr < tipc_own_addr) + tipc_own_tag--; } + info("Lost contact with %s\n", + tipc_addr_string_fill(addr_string, n_ptr->addr)); + /* Abort link changeover */ for (i = 0; i < MAX_BEARERS; i++) { - struct tipc_link *l_ptr = n_ptr->links[i]; + struct link *l_ptr = n_ptr->links[i]; if (!l_ptr) continue; l_ptr->reset_checkpoint = l_ptr->next_in_no; @@ -323,9 +367,10 @@ static void node_lost_contact(struct tipc_node *n_ptr) /* Notify subscribers */ tipc_nodesub_notify(n_ptr); - /* Prevent re-contact with node until cleanup is done */ - n_ptr->block_setup = WAIT_PEER_DOWN | WAIT_NAMES_GONE; - tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr); + /* Prevent re-contact with node until all cleanup is done */ + + n_ptr->cleanup_required = 1; + tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); } struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) @@ -351,6 +396,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) } /* For now, get space for all other nodes */ + payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; if (payload_size > 32768u) { read_unlock_bh(&tipc_net_lock); @@ -364,6 +410,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) } /* Add TLVs for all nodes in scope */ + list_for_each_entry(n_ptr, &tipc_node_list, list) { if (!tipc_in_scope(domain, n_ptr->addr)) continue; @@ -393,12 +440,13 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network address)"); - if (!tipc_own_addr) + if (tipc_mode != TIPC_NET_MODE) return tipc_cfg_reply_none(); read_lock_bh(&tipc_net_lock); - /* Get space for all unicast links + broadcast link */ + /* Get space for all unicast links + multicast link */ + payload_size = TLV_SPACE(sizeof(link_info)) * (atomic_read(&tipc_num_links) + 1); if (payload_size > 32768u) { @@ -413,12 +461,14 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) } /* Add TLV for broadcast link */ + link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr)); link_info.up = htonl(1); strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); /* Add TLVs for any other links in scope */ + list_for_each_entry(n_ptr, &tipc_node_list, list) { u32 i; -- cgit v1.2.2