aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/bcast.c117
-rw-r--r--net/tipc/bcast.h1
-rw-r--r--net/tipc/bearer.c9
-rw-r--r--net/tipc/bearer.h6
-rw-r--r--net/tipc/config.h1
-rw-r--r--net/tipc/core.c2
-rw-r--r--net/tipc/core.h8
-rw-r--r--net/tipc/discover.c6
-rw-r--r--net/tipc/eth_media.c34
-rw-r--r--net/tipc/link.c117
-rw-r--r--net/tipc/link.h1
-rw-r--r--net/tipc/msg.c6
-rw-r--r--net/tipc/msg.h34
-rw-r--r--net/tipc/name_distr.c41
-rw-r--r--net/tipc/name_table.c289
-rw-r--r--net/tipc/name_table.h14
-rw-r--r--net/tipc/net.c11
-rw-r--r--net/tipc/node.c45
-rw-r--r--net/tipc/node.h10
-rw-r--r--net/tipc/port.c284
-rw-r--r--net/tipc/socket.c63
-rw-r--r--net/tipc/subscr.c3
-rw-r--r--net/tipc/subscr.h6
23 files changed, 522 insertions, 586 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index fa68d1e..28908f5 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -39,6 +39,7 @@
#include "link.h"
#include "port.h"
#include "bcast.h"
+#include "name_distr.h"
#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
@@ -298,14 +299,9 @@ static void bclink_send_nack(struct tipc_node *n_ptr)
msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
msg_set_bcast_tag(msg, tipc_own_tag);
- if (tipc_bearer_send(&bcbearer->bearer, buf, NULL)) {
- bcl->stats.sent_nacks++;
- buf_discard(buf);
- } else {
- tipc_bearer_schedule(bcl->b_ptr, bcl);
- bcl->proto_msg_queue = buf;
- bcl->stats.bearer_congs++;
- }
+ tipc_bearer_send(&bcbearer->bearer, buf, NULL);
+ bcl->stats.sent_nacks++;
+ buf_discard(buf);
/*
* Ensure we doesn't send another NACK msg to the node
@@ -426,20 +422,28 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
void tipc_bclink_recv_pkt(struct sk_buff *buf)
{
struct tipc_msg *msg = buf_msg(buf);
- struct tipc_node *node = tipc_node_find(msg_prevnode(msg));
+ struct tipc_node *node;
u32 next_in;
u32 seqno;
struct sk_buff *deferred;
- if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported ||
- (msg_mc_netid(msg) != tipc_net_id))) {
- buf_discard(buf);
- return;
- }
+ /* Screen out unwanted broadcast messages */
+
+ if (msg_mc_netid(msg) != tipc_net_id)
+ goto exit;
+
+ node = tipc_node_find(msg_prevnode(msg));
+ if (unlikely(!node))
+ goto exit;
+
+ tipc_node_lock(node);
+ if (unlikely(!node->bclink.supported))
+ goto unlock;
if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) {
+ if (msg_type(msg) != STATE_MSG)
+ goto unlock;
if (msg_destnode(msg) == tipc_own_addr) {
- tipc_node_lock(node);
tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
tipc_node_unlock(node);
spin_lock_bh(&bc_lock);
@@ -449,18 +453,18 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
msg_bcgap_to(msg));
spin_unlock_bh(&bc_lock);
} else {
+ tipc_node_unlock(node);
tipc_bclink_peek_nack(msg_destnode(msg),
msg_bcast_tag(msg),
msg_bcgap_after(msg),
msg_bcgap_to(msg));
}
- buf_discard(buf);
- return;
+ goto exit;
}
- tipc_node_lock(node);
+ /* Handle in-sequence broadcast message */
+
receive:
- deferred = node->bclink.deferred_head;
next_in = mod(node->bclink.last_in + 1);
seqno = msg_seqno(msg);
@@ -474,7 +478,10 @@ receive:
}
if (likely(msg_isdata(msg))) {
tipc_node_unlock(node);
- tipc_port_recv_mcast(buf, NULL);
+ if (likely(msg_mcast(msg)))
+ tipc_port_recv_mcast(buf, NULL);
+ else
+ buf_discard(buf);
} else if (msg_user(msg) == MSG_BUNDLER) {
bcl->stats.recv_bundles++;
bcl->stats.recv_bundled += msg_msgcnt(msg);
@@ -487,18 +494,22 @@ receive:
bcl->stats.recv_fragmented++;
tipc_node_unlock(node);
tipc_net_route_msg(buf);
+ } else if (msg_user(msg) == NAME_DISTRIBUTOR) {
+ tipc_node_unlock(node);
+ tipc_named_recv(buf);
} else {
tipc_node_unlock(node);
- tipc_net_route_msg(buf);
+ buf_discard(buf);
}
+ buf = NULL;
+ tipc_node_lock(node);
+ deferred = node->bclink.deferred_head;
if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) {
- tipc_node_lock(node);
buf = deferred;
msg = buf_msg(buf);
node->bclink.deferred_head = deferred->next;
goto receive;
}
- return;
} else if (less(next_in, seqno)) {
u32 gap_after = node->bclink.gap_after;
u32 gap_to = node->bclink.gap_to;
@@ -513,6 +524,7 @@ receive:
else if (less(gap_after, seqno) && less(seqno, gap_to))
node->bclink.gap_to = seqno;
}
+ buf = NULL;
if (bclink_ack_allowed(node->bclink.nack_sync)) {
if (gap_to != gap_after)
bclink_send_nack(node);
@@ -520,9 +532,11 @@ receive:
}
} else {
bcl->stats.duplicates++;
- buf_discard(buf);
}
+unlock:
tipc_node_unlock(node);
+exit:
+ buf_discard(buf);
}
u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
@@ -535,10 +549,11 @@ u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
/**
* tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer
*
- * Send through as many bearers as necessary to reach all nodes
- * that support TIPC multicasting.
+ * Send packet over as many bearers as necessary to reach all nodes
+ * that have joined the broadcast link.
*
- * Returns 0 if packet sent successfully, non-zero if not
+ * Returns 0 (packet sent successfully) under all circumstances,
+ * since the broadcast link's pseudo-bearer never blocks
*/
static int tipc_bcbearer_send(struct sk_buff *buf,
@@ -547,17 +562,26 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
{
int bp_index;
- /* Prepare buffer for broadcasting (if first time trying to send it) */
+ /*
+ * Prepare broadcast link message for reliable transmission,
+ * if first time trying to send it;
+ * preparation is skipped for broadcast link protocol messages
+ * since they are sent in an unreliable manner and don't need it
+ */
if (likely(!msg_non_seq(buf_msg(buf)))) {
struct tipc_msg *msg;
- assert(tipc_bcast_nmap.count != 0);
bcbuf_set_acks(buf, tipc_bcast_nmap.count);
msg = buf_msg(buf);
msg_set_non_seq(msg, 1);
msg_set_mc_netid(msg, tipc_net_id);
bcl->stats.sent_info++;
+
+ if (WARN_ON(!tipc_bcast_nmap.count)) {
+ dump_stack();
+ return 0;
+ }
}
/* Send buffer over bearers until all targets reached */
@@ -592,18 +616,12 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
}
if (bcbearer->remains_new.count == 0)
- return 0;
+ break; /* all targets reached */
bcbearer->remains = bcbearer->remains_new;
}
- /*
- * Unable to reach all targets (indicate success, since currently
- * there isn't code in place to properly block & unblock the
- * pseudo-bearer used by the broadcast link)
- */
-
- return TIPC_OK;
+ return 0;
}
/**
@@ -663,27 +681,6 @@ void tipc_bcbearer_sort(void)
spin_unlock_bh(&bc_lock);
}
-/**
- * tipc_bcbearer_push - resolve bearer congestion
- *
- * Forces bclink to push out any unsent packets, until all packets are gone
- * or congestion reoccurs.
- * No locks set when function called
- */
-
-void tipc_bcbearer_push(void)
-{
- struct tipc_bearer *b_ptr;
-
- spin_lock_bh(&bc_lock);
- b_ptr = &bcbearer->bearer;
- if (b_ptr->blocked) {
- b_ptr->blocked = 0;
- tipc_bearer_lock_push(b_ptr);
- }
- spin_unlock_bh(&bc_lock);
-}
-
int tipc_bclink_stats(char *buf, const u32 buf_size)
{
@@ -760,7 +757,7 @@ int tipc_bclink_init(void)
bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC);
bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC);
if (!bcbearer || !bclink) {
- warn("Multicast link creation failed, no memory\n");
+ warn("Broadcast link creation failed, no memory\n");
kfree(bcbearer);
bcbearer = NULL;
kfree(bclink);
@@ -771,7 +768,7 @@ int tipc_bclink_init(void)
INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
bcbearer->bearer.media = &bcbearer->media;
bcbearer->media.send_msg = tipc_bcbearer_send;
- sprintf(bcbearer->media.name, "tipc-multicast");
+ sprintf(bcbearer->media.name, "tipc-broadcast");
bcl = &bclink->link;
INIT_LIST_HEAD(&bcl->waiting_ports);
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 500c97f..06740da 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -101,6 +101,5 @@ int tipc_bclink_stats(char *stats_buf, const u32 buf_size);
int tipc_bclink_reset_stats(void);
int tipc_bclink_set_queue_limits(u32 limit);
void tipc_bcbearer_sort(void);
-void tipc_bcbearer_push(void);
#endif
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 85209ea..e2202de 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -385,13 +385,9 @@ static int bearer_push(struct tipc_bearer *b_ptr)
void tipc_bearer_lock_push(struct tipc_bearer *b_ptr)
{
- int res;
-
spin_lock_bh(&b_ptr->lock);
- res = bearer_push(b_ptr);
+ bearer_push(b_ptr);
spin_unlock_bh(&b_ptr->lock);
- if (res)
- tipc_bcbearer_push();
}
@@ -402,7 +398,6 @@ void tipc_bearer_lock_push(struct tipc_bearer *b_ptr)
void tipc_continue(struct tipc_bearer *b_ptr)
{
spin_lock_bh(&b_ptr->lock);
- b_ptr->continue_count++;
if (!list_empty(&b_ptr->cong_links))
tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
b_ptr->blocked = 0;
@@ -609,6 +604,7 @@ int tipc_block_bearer(const char *name)
info("Blocking bearer <%s>\n", name);
spin_lock_bh(&b_ptr->lock);
b_ptr->blocked = 1;
+ list_splice_init(&b_ptr->cong_links, &b_ptr->links);
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
struct tipc_node *n_ptr = l_ptr->owner;
@@ -636,6 +632,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
spin_lock_bh(&b_ptr->lock);
b_ptr->blocked = 1;
b_ptr->media->disable_bearer(b_ptr);
+ list_splice_init(&b_ptr->cong_links, &b_ptr->links);
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
tipc_link_delete(l_ptr);
}
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 31d6172..d696f9e 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -39,8 +39,8 @@
#include "bcast.h"
-#define MAX_BEARERS 8
-#define MAX_MEDIA 4
+#define MAX_BEARERS 2
+#define MAX_MEDIA 2
/*
* Identifiers of supported TIPC media types
@@ -107,7 +107,6 @@ struct media {
* @link_req: ptr to (optional) structure making periodic link setup requests
* @links: list of non-congested links associated with bearer
* @cong_links: list of congested links associated with bearer
- * @continue_count: # of times bearer has resumed after congestion or blocking
* @active: non-zero if bearer structure is represents a bearer
* @net_plane: network plane ('A' through 'H') currently associated with bearer
* @nodes: indicates which nodes in cluster can be reached through bearer
@@ -129,7 +128,6 @@ struct tipc_bearer {
struct link_req *link_req;
struct list_head links;
struct list_head cong_links;
- u32 continue_count;
int active;
char net_plane;
struct tipc_node_map nodes;
diff --git a/net/tipc/config.h b/net/tipc/config.h
index 443159a..80da6eb 100644
--- a/net/tipc/config.h
+++ b/net/tipc/config.h
@@ -65,7 +65,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd,
const void *req_tlv_area, int req_tlv_space,
int headroom);
-void tipc_cfg_link_event(u32 addr, char *name, int up);
int tipc_cfg_init(void);
void tipc_cfg_stop(void);
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 943b6af..c21331d 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -34,6 +34,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <linux/module.h>
+
#include "core.h"
#include "ref.h"
#include "name_table.h"
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 436dda1..2761af3 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -47,7 +47,7 @@
#include <linux/string.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/hardirq.h>
#include <linux/netdevice.h>
#include <linux/in.h>
@@ -62,12 +62,6 @@ struct tipc_msg; /* msg.h */
struct print_buf; /* log.h */
/*
- * TIPC sanity test macros
- */
-
-#define assert(i) BUG_ON(!(i))
-
-/*
* TIPC system monitoring code
*/
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 0987933..f2fb96e 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -159,12 +159,6 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
}
tipc_node_lock(n_ptr);
- /* Don't talk to neighbor during cleanup after last session */
- if (n_ptr->cleanup_required) {
- tipc_node_unlock(n_ptr);
- return;
- }
-
link = n_ptr->links[b_ptr->identity];
/* Create a link endpoint for this bearer, if necessary */
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index a8c2a6b2..a224a38 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -2,7 +2,7 @@
* net/tipc/eth_media.c: Ethernet bearer support for TIPC
*
* Copyright (c) 2001-2007, Ericsson AB
- * Copyright (c) 2005-2007, Wind River Systems
+ * Copyright (c) 2005-2008, 2011, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
#include "core.h"
#include "bearer.h"
-#define MAX_ETH_BEARERS 2
+#define MAX_ETH_BEARERS MAX_BEARERS
#define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI
#define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL
#define ETH_LINK_WINDOW TIPC_DEF_LINK_WIN
@@ -156,32 +156,28 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
/* Find device with specified name */
+ read_lock(&dev_base_lock);
for_each_netdev(&init_net, pdev) {
if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) {
dev = pdev;
+ dev_hold(dev);
break;
}
}
+ read_unlock(&dev_base_lock);
if (!dev)
return -ENODEV;
- /* Find Ethernet bearer for device (or create one) */
-
- while ((eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev))
- eb_ptr++;
- if (eb_ptr == stop)
- return -EDQUOT;
- if (!eb_ptr->dev) {
- eb_ptr->dev = dev;
- eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
- eb_ptr->tipc_packet_type.dev = dev;
- eb_ptr->tipc_packet_type.func = recv_msg;
- eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
- INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
- dev_hold(dev);
- INIT_WORK(&eb_ptr->setup, setup_bearer);
- schedule_work(&eb_ptr->setup);
- }
+ /* Create Ethernet bearer for device */
+
+ eb_ptr->dev = dev;
+ eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
+ eb_ptr->tipc_packet_type.dev = dev;
+ eb_ptr->tipc_packet_type.func = recv_msg;
+ eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
+ INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
+ INIT_WORK(&eb_ptr->setup, setup_bearer);
+ schedule_work(&eb_ptr->setup);
/* Associate TIPC bearer with Ethernet bearer */
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 5ed4b4f..ae98a72 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -332,15 +332,16 @@ struct link *tipc_link_create(struct tipc_node *n_ptr,
l_ptr->addr = peer;
if_name = strchr(b_ptr->name, ':') + 1;
- sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:",
+ sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown",
tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
tipc_node(tipc_own_addr),
if_name,
tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
- /* note: peer i/f is appended to link name by reset/activate */
+ /* note: peer i/f name is updated by reset/activate message */
memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
l_ptr->owner = n_ptr;
l_ptr->checkpoint = 1;
+ l_ptr->peer_session = INVALID_SESSION;
l_ptr->b_ptr = b_ptr;
link_set_supervision_props(l_ptr, b_ptr->media->tolerance);
l_ptr->state = RESET_UNKNOWN;
@@ -536,9 +537,6 @@ void tipc_link_stop(struct link *l_ptr)
l_ptr->proto_msg_queue = NULL;
}
-/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
-#define link_send_event(fcn, l_ptr, up) do { } while (0)
-
void tipc_link_reset(struct link *l_ptr)
{
struct sk_buff *buf;
@@ -596,10 +594,6 @@ void tipc_link_reset(struct link *l_ptr)
l_ptr->fsm_msg_cnt = 0;
l_ptr->stale_count = 0;
link_reset_statistics(l_ptr);
-
- link_send_event(tipc_cfg_link_event, l_ptr, 0);
- if (!in_own_cluster(l_ptr->addr))
- link_send_event(tipc_disc_link_event, l_ptr, 0);
}
@@ -608,9 +602,6 @@ static void link_activate(struct link *l_ptr)
l_ptr->next_in_no = l_ptr->stats.recv_info = 1;
tipc_node_link_up(l_ptr->owner, l_ptr);
tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
- link_send_event(tipc_cfg_link_event, l_ptr, 1);
- if (!in_own_cluster(l_ptr->addr))
- link_send_event(tipc_disc_link_event, l_ptr, 1);
}
/**
@@ -985,6 +976,51 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
}
/*
+ * tipc_link_send_names - send name table entries to new neighbor
+ *
+ * Send routine for bulk delivery of name table messages when contact
+ * with a new neighbor occurs. No link congestion checking is performed
+ * because name table messages *must* be delivered. The messages must be
+ * small enough not to require fragmentation.
+ * Called without any locks held.
+ */
+
+void tipc_link_send_names(struct list_head *message_list, u32 dest)
+{
+ struct tipc_node *n_ptr;
+ struct link *l_ptr;
+ struct sk_buff *buf;
+ struct sk_buff *temp_buf;
+
+ if (list_empty(message_list))
+ return;
+
+ read_lock_bh(&tipc_net_lock);
+ n_ptr = tipc_node_find(dest);
+ if (n_ptr) {
+ tipc_node_lock(n_ptr);
+ l_ptr = n_ptr->active_links[0];
+ if (l_ptr) {
+ /* convert circular list to linear list */
+ ((struct sk_buff *)message_list->prev)->next = NULL;
+ link_add_chain_to_outqueue(l_ptr,
+ (struct sk_buff *)message_list->next, 0);
+ tipc_link_push_queue(l_ptr);
+ INIT_LIST_HEAD(message_list);
+ }
+ tipc_node_unlock(n_ptr);
+ }
+ read_unlock_bh(&tipc_net_lock);
+
+ /* discard the messages if they couldn't be sent */
+
+ list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) {
+ list_del((struct list_head *)buf);
+ buf_discard(buf);
+ }
+}
+
+/*
* link_send_buf_fast: Entry for data messages where the
* destination link is known and the header is complete,
* inclusive total message length. Very time critical.
@@ -1031,9 +1067,6 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
u32 selector = msg_origport(buf_msg(buf)) & 1;
u32 dummy;
- if (destnode == tipc_own_addr)
- return tipc_port_recv_msg(buf);
-
read_lock_bh(&tipc_net_lock);
n_ptr = tipc_node_find(destnode);
if (likely(n_ptr)) {
@@ -1572,7 +1605,7 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
static int link_recv_buf_validate(struct sk_buff *buf)
{
static u32 min_data_hdr_size[8] = {
- SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE,
+ SHORT_H_SIZE, MCAST_H_SIZE, NAMED_H_SIZE, BASIC_H_SIZE,
MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
};
@@ -1658,19 +1691,12 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
continue;
}
+ /* Discard unicast link messages destined for another node */
+
if (unlikely(!msg_short(msg) &&
(msg_destnode(msg) != tipc_own_addr)))
goto cont;
- /* Discard non-routeable messages destined for another node */
-
- if (unlikely(!msg_isdata(msg) &&
- (msg_destnode(msg) != tipc_own_addr))) {
- if ((msg_user(msg) != CONN_MANAGER) &&
- (msg_user(msg) != MSG_FRAGMENTER))
- goto cont;
- }
-
/* Locate neighboring node that sent message */
n_ptr = tipc_node_find(msg_prevnode(msg));
@@ -1678,17 +1704,24 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
goto cont;
tipc_node_lock(n_ptr);
- /* Don't talk to neighbor during cleanup after last session */
+ /* Locate unicast link endpoint that should handle message */
- if (n_ptr->cleanup_required) {
+ l_ptr = n_ptr->links[b_ptr->identity];
+ if (unlikely(!l_ptr)) {
tipc_node_unlock(n_ptr);
goto cont;
}
- /* Locate unicast link endpoint that should handle message */
+ /* Verify that communication with node is currently allowed */
- l_ptr = n_ptr->links[b_ptr->identity];
- if (unlikely(!l_ptr)) {
+ if ((n_ptr->block_setup & WAIT_PEER_DOWN) &&
+ msg_user(msg) == LINK_PROTOCOL &&
+ (msg_type(msg) == RESET_MSG ||
+ msg_type(msg) == ACTIVATE_MSG) &&
+ !msg_redundant_link(msg))
+ n_ptr->block_setup &= ~WAIT_PEER_DOWN;
+
+ if (n_ptr->block_setup) {
tipc_node_unlock(n_ptr);
goto cont;
}
@@ -1923,6 +1956,12 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
if (link_blocked(l_ptr))
return;
+
+ /* Abort non-RESET send if communication with node is prohibited */
+
+ if ((l_ptr->owner->block_setup) && (msg_typ != RESET_MSG))
+ return;
+
msg_set_type(msg, msg_typ);
msg_set_net_plane(msg, l_ptr->b_ptr->net_plane);
msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in));
@@ -2051,9 +2090,19 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf)
case RESET_MSG:
if (!link_working_unknown(l_ptr) &&
(l_ptr->peer_session != INVALID_SESSION)) {
- if (msg_session(msg) == l_ptr->peer_session)
- break; /* duplicate: ignore */
+ if (less_eq(msg_session(msg), l_ptr->peer_session))
+ break; /* duplicate or old reset: ignore */
+ }
+
+ if (!msg_redundant_link(msg) && (link_working_working(l_ptr) ||
+ link_working_unknown(l_ptr))) {
+ /*
+ * peer has lost contact -- don't allow peer's links
+ * to reactivate before we recognize loss & clean up
+ */
+ l_ptr->owner->block_setup = WAIT_NODE_DOWN;
}
+
/* fall thru' */
case ACTIVATE_MSG:
/* Update link settings according other endpoint's values */
@@ -2553,7 +2602,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
u32 msg_sz = msg_size(imsg);
u32 fragm_sz = msg_data_sz(fragm);
u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz);
- u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE;
+ u32 max = TIPC_MAX_USER_MSG_SIZE + NAMED_H_SIZE;
if (msg_type(imsg) == TIPC_MCAST_MSG)
max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE;
if (msg_size(imsg) > max) {
@@ -2882,7 +2931,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
profile_total = 1;
tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n"
" 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
- "-16354:%u%% -32768:%u%% -66000:%u%%\n",
+ "-16384:%u%% -32768:%u%% -66000:%u%%\n",
l_ptr->stats.msg_length_counts,
l_ptr->stats.msg_lengths_total / profile_total,
percent(l_ptr->stats.msg_length_profile[0], profile_total),
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 74fbeca..e56cb53 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -223,6 +223,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_s
struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
void tipc_link_reset(struct link *l_ptr);
int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
+void tipc_link_send_names(struct list_head *message_list, u32 dest);
int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf);
u32 tipc_link_get_max_pkt(u32 dest, u32 selector);
int tipc_link_send_sections_fast(struct tipc_port *sender,
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 03e57bf..83d5096 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -61,10 +61,8 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
msg_set_size(m, hsize);
msg_set_prevnode(m, tipc_own_addr);
msg_set_type(m, type);
- if (!msg_short(m)) {
- msg_set_orignode(m, tipc_own_addr);
- msg_set_destnode(m, destnode);
- }
+ msg_set_orignode(m, tipc_own_addr);
+ msg_set_destnode(m, destnode);
}
/**
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 8452454..d93178f 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -68,10 +68,10 @@
* Message header sizes
*/
-#define SHORT_H_SIZE 24 /* Connected, in-cluster messages */
-#define DIR_MSG_H_SIZE 32 /* Directly addressed messages */
-#define LONG_H_SIZE 40 /* Named messages */
-#define MCAST_H_SIZE 44 /* Multicast messages */
+#define SHORT_H_SIZE 24 /* In-cluster basic payload message */
+#define BASIC_H_SIZE 32 /* Basic payload message */
+#define NAMED_H_SIZE 40 /* Named payload message */
+#define MCAST_H_SIZE 44 /* Multicast payload message */
#define INT_H_SIZE 40 /* Internal messages */
#define MIN_H_SIZE 24 /* Smallest legal TIPC header size */
#define MAX_H_SIZE 60 /* Largest possible TIPC header size */
@@ -311,26 +311,6 @@ static inline void msg_set_seqno(struct tipc_msg *m, u32 n)
}
/*
- * TIPC may utilize the "link ack #" and "link seq #" fields of a short
- * message header to hold the destination node for the message, since the
- * normal "dest node" field isn't present. This cache is only referenced
- * when required, so populating the cache of a longer message header is
- * harmless (as long as the header has the two link sequence fields present).
- *
- * Note: Host byte order is OK here, since the info never goes off-card.
- */
-
-static inline u32 msg_destnode_cache(struct tipc_msg *m)
-{
- return m->hdr[2];
-}
-
-static inline void msg_set_destnode_cache(struct tipc_msg *m, u32 dnode)
-{
- m->hdr[2] = dnode;
-}
-
-/*
* Words 3-10
*/
@@ -377,7 +357,7 @@ static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p)
static inline int msg_short(struct tipc_msg *m)
{
- return msg_hdr_sz(m) == 24;
+ return msg_hdr_sz(m) == SHORT_H_SIZE;
}
static inline u32 msg_orignode(struct tipc_msg *m)
@@ -635,7 +615,7 @@ static inline u32 msg_link_selector(struct tipc_msg *m)
static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
{
- msg_set_bits(m, 4, 0, 1, (n & 1));
+ msg_set_bits(m, 4, 0, 1, n);
}
/*
@@ -659,7 +639,7 @@ static inline u32 msg_probe(struct tipc_msg *m)
static inline void msg_set_probe(struct tipc_msg *m, u32 val)
{
- msg_set_bits(m, 5, 0, 1, (val & 1));
+ msg_set_bits(m, 5, 0, 1, val);
}
static inline char msg_net_plane(struct tipc_msg *m)
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 80025a1..b7ca1bd 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -94,13 +94,13 @@ static void publ_to_item(struct distr_item *i, struct publication *p)
static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
{
- struct sk_buff *buf = tipc_buf_acquire(LONG_H_SIZE + size);
+ struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size);
struct tipc_msg *msg;
if (buf != NULL) {
msg = buf_msg(buf);
- tipc_msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest);
- msg_set_size(msg, LONG_H_SIZE + size);
+ tipc_msg_init(msg, NAME_DISTRIBUTOR, type, INT_H_SIZE, dest);
+ msg_set_size(msg, INT_H_SIZE + size);
}
return buf;
}
@@ -173,18 +173,40 @@ void tipc_named_withdraw(struct publication *publ)
* tipc_named_node_up - tell specified node about all publications by this node
*/
-void tipc_named_node_up(unsigned long node)
+void tipc_named_node_up(unsigned long nodearg)
{
+ struct tipc_node *n_ptr;
+ struct link *l_ptr;
struct publication *publ;
struct distr_item *item = NULL;
struct sk_buff *buf = NULL;
+ struct list_head message_list;
+ u32 node = (u32)nodearg;
u32 left = 0;
u32 rest;
- u32 max_item_buf;
+ u32 max_item_buf = 0;
+
+ /* compute maximum amount of publication data to send per message */
+
+ read_lock_bh(&tipc_net_lock);
+ n_ptr = tipc_node_find(node);
+ if (n_ptr) {
+ tipc_node_lock(n_ptr);
+ l_ptr = n_ptr->active_links[0];
+ if (l_ptr)
+ max_item_buf = ((l_ptr->max_pkt - INT_H_SIZE) /
+ ITEM_SIZE) * ITEM_SIZE;
+ tipc_node_unlock(n_ptr);
+ }
+ read_unlock_bh(&tipc_net_lock);
+ if (!max_item_buf)
+ return;
+
+ /* create list of publication messages, then send them as a unit */
+
+ INIT_LIST_HEAD(&message_list);
read_lock_bh(&tipc_nametbl_lock);
- max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
- max_item_buf *= ITEM_SIZE;
rest = publ_cnt * ITEM_SIZE;
list_for_each_entry(publ, &publ_root, local_list) {
@@ -202,13 +224,14 @@ void tipc_named_node_up(unsigned long node)
item++;
left -= ITEM_SIZE;
if (!left) {
- msg_set_link_selector(buf_msg(buf), node);
- tipc_link_send(buf, node, node);
+ list_add_tail((struct list_head *)buf, &message_list);
buf = NULL;
}
}
exit:
read_unlock_bh(&tipc_nametbl_lock);
+
+ tipc_link_send_names(&message_list, (u32)node);
}
/**
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 205ed4a..46e6b6c 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -2,7 +2,7 @@
* net/tipc/name_table.c: TIPC name table code
*
* Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2004-2008, Wind River Systems
+ * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,9 +44,7 @@
static int tipc_nametbl_size = 1024; /* must be a power of 2 */
/**
- * struct sub_seq - container for all published instances of a name sequence
- * @lower: name sequence lower bound
- * @upper: name sequence upper bound
+ * struct name_info - name sequence publication info
* @node_list: circular list of publications made by own node
* @cluster_list: circular list of publications made by own cluster
* @zone_list: circular list of publications made by own zone
@@ -59,18 +57,29 @@ static int tipc_nametbl_size = 1024; /* must be a power of 2 */
* (The cluster and node lists may be empty.)
*/
-struct sub_seq {
- u32 lower;
- u32 upper;
- struct publication *node_list;
- struct publication *cluster_list;
- struct publication *zone_list;
+struct name_info {
+ struct list_head node_list;
+ struct list_head cluster_list;
+ struct list_head zone_list;
u32 node_list_size;
u32 cluster_list_size;
u32 zone_list_size;
};
/**
+ * struct sub_seq - container for all published instances of a name sequence
+ * @lower: name sequence lower bound
+ * @upper: name sequence upper bound
+ * @info: pointer to name sequence publication info
+ */
+
+struct sub_seq {
+ u32 lower;
+ u32 upper;
+ struct name_info *info;
+};
+
+/**
* struct name_seq - container for all published instances of a name type
* @type: 32 bit 'type' value for name sequence
* @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
@@ -246,6 +255,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
struct subscription *st;
struct publication *publ;
struct sub_seq *sseq;
+ struct name_info *info;
int created_subseq = 0;
sseq = nameseq_find_subseq(nseq, lower);
@@ -258,6 +268,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
type, lower, upper);
return NULL;
}
+
+ info = sseq->info;
} else {
u32 inspos;
struct sub_seq *freesseq;
@@ -292,6 +304,17 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
nseq->alloc *= 2;
}
+ info = kzalloc(sizeof(*info), GFP_ATOMIC);
+ if (!info) {
+ warn("Cannot publish {%u,%u,%u}, no memory\n",
+ type, lower, upper);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&info->node_list);
+ INIT_LIST_HEAD(&info->cluster_list);
+ INIT_LIST_HEAD(&info->zone_list);
+
/* Insert new sub-sequence */
sseq = &nseq->sseqs[inspos];
@@ -301,6 +324,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
nseq->first_free++;
sseq->lower = lower;
sseq->upper = upper;
+ sseq->info = info;
created_subseq = 1;
}
@@ -310,33 +334,17 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
if (!publ)
return NULL;
- sseq->zone_list_size++;
- if (!sseq->zone_list)
- sseq->zone_list = publ->zone_list_next = publ;
- else {
- publ->zone_list_next = sseq->zone_list->zone_list_next;
- sseq->zone_list->zone_list_next = publ;
- }
+ list_add(&publ->zone_list, &info->zone_list);
+ info->zone_list_size++;
if (in_own_cluster(node)) {
- sseq->cluster_list_size++;
- if (!sseq->cluster_list)
- sseq->cluster_list = publ->cluster_list_next = publ;
- else {
- publ->cluster_list_next =
- sseq->cluster_list->cluster_list_next;
- sseq->cluster_list->cluster_list_next = publ;
- }
+ list_add(&publ->cluster_list, &info->cluster_list);
+ info->cluster_list_size++;
}
if (node == tipc_own_addr) {
- sseq->node_list_size++;
- if (!sseq->node_list)
- sseq->node_list = publ->node_list_next = publ;
- else {
- publ->node_list_next = sseq->node_list->node_list_next;
- sseq->node_list->node_list_next = publ;
- }
+ list_add(&publ->node_list, &info->node_list);
+ info->node_list_size++;
}
/*
@@ -370,9 +378,8 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
u32 node, u32 ref, u32 key)
{
struct publication *publ;
- struct publication *curr;
- struct publication *prev;
struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
+ struct name_info *info;
struct sub_seq *free;
struct subscription *s, *st;
int removed_subseq = 0;
@@ -380,96 +387,41 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
if (!sseq)
return NULL;
- /* Remove publication from zone scope list */
+ info = sseq->info;
- prev = sseq->zone_list;
- publ = sseq->zone_list->zone_list_next;
- while ((publ->key != key) || (publ->ref != ref) ||
- (publ->node && (publ->node != node))) {
- prev = publ;
- publ = publ->zone_list_next;
- if (prev == sseq->zone_list) {
+ /* Locate publication, if it exists */
- /* Prevent endless loop if publication not found */
-
- return NULL;
- }
- }
- if (publ != sseq->zone_list)
- prev->zone_list_next = publ->zone_list_next;
- else if (publ->zone_list_next != publ) {
- prev->zone_list_next = publ->zone_list_next;
- sseq->zone_list = publ->zone_list_next;
- } else {
- sseq->zone_list = NULL;
+ list_for_each_entry(publ, &info->zone_list, zone_list) {
+ if ((publ->key == key) && (publ->ref == ref) &&
+ (!publ->node || (publ->node == node)))
+ goto found;
}
- sseq->zone_list_size--;
+ return NULL;
+
+found:
+ /* Remove publication from zone scope list */
+
+ list_del(&publ->zone_list);
+ info->zone_list_size--;
/* Remove publication from cluster scope list, if present */
if (in_own_cluster(node)) {
- prev = sseq->cluster_list;
- curr = sseq->cluster_list->cluster_list_next;
- while (curr != publ) {
- prev = curr;
- curr = curr->cluster_list_next;
- if (prev == sseq->cluster_list) {
-
- /* Prevent endless loop for malformed list */
-
- err("Unable to de-list cluster publication\n"
- "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
- publ->type, publ->lower, publ->node,
- publ->ref, publ->key);
- goto end_cluster;
- }
- }
- if (publ != sseq->cluster_list)
- prev->cluster_list_next = publ->cluster_list_next;
- else if (publ->cluster_list_next != publ) {
- prev->cluster_list_next = publ->cluster_list_next;
- sseq->cluster_list = publ->cluster_list_next;
- } else {
- sseq->cluster_list = NULL;
- }
- sseq->cluster_list_size--;
+ list_del(&publ->cluster_list);
+ info->cluster_list_size--;
}
-end_cluster:
/* Remove publication from node scope list, if present */
if (node == tipc_own_addr) {
- prev = sseq->node_list;
- curr = sseq->node_list->node_list_next;
- while (curr != publ) {
- prev = curr;
- curr = curr->node_list_next;
- if (prev == sseq->node_list) {
-
- /* Prevent endless loop for malformed list */
-
- err("Unable to de-list node publication\n"
- "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
- publ->type, publ->lower, publ->node,
- publ->ref, publ->key);
- goto end_node;
- }
- }
- if (publ != sseq->node_list)
- prev->node_list_next = publ->node_list_next;
- else if (publ->node_list_next != publ) {
- prev->node_list_next = publ->node_list_next;
- sseq->node_list = publ->node_list_next;
- } else {
- sseq->node_list = NULL;
- }
- sseq->node_list_size--;
+ list_del(&publ->node_list);
+ info->node_list_size--;
}
-end_node:
/* Contract subseq list if no more publications for that subseq */
- if (!sseq->zone_list) {
+ if (list_empty(&info->zone_list)) {
+ kfree(info);
free = &nseq->sseqs[nseq->first_free--];
memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq));
removed_subseq = 1;
@@ -506,12 +458,12 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s
return;
while (sseq != &nseq->sseqs[nseq->first_free]) {
- struct publication *zl = sseq->zone_list;
- if (zl && tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
- struct publication *crs = zl;
+ if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
+ struct publication *crs;
+ struct name_info *info = sseq->info;
int must_report = 1;
- do {
+ list_for_each_entry(crs, &info->zone_list, zone_list) {
tipc_subscr_report_overlap(s,
sseq->lower,
sseq->upper,
@@ -520,8 +472,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s
crs->node,
must_report);
must_report = 0;
- crs = crs->zone_list_next;
- } while (crs != zl);
+ }
}
sseq++;
}
@@ -591,9 +542,10 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
{
struct sub_seq *sseq;
- struct publication *publ = NULL;
+ struct name_info *info;
+ struct publication *publ;
struct name_seq *seq;
- u32 ref;
+ u32 ref = 0;
if (!tipc_in_scope(*destnode, tipc_own_addr))
return 0;
@@ -606,55 +558,57 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
if (unlikely(!sseq))
goto not_found;
spin_lock_bh(&seq->lock);
+ info = sseq->info;
/* Closest-First Algorithm: */
if (likely(!*destnode)) {
- publ = sseq->node_list;
- if (publ) {
- sseq->node_list = publ->node_list_next;
-found:
- ref = publ->ref;
- *destnode = publ->node;
- spin_unlock_bh(&seq->lock);
- read_unlock_bh(&tipc_nametbl_lock);
- return ref;
- }
- publ = sseq->cluster_list;
- if (publ) {
- sseq->cluster_list = publ->cluster_list_next;
- goto found;
- }
- publ = sseq->zone_list;
- if (publ) {
- sseq->zone_list = publ->zone_list_next;
- goto found;
+ if (!list_empty(&info->node_list)) {
+ publ = list_first_entry(&info->node_list,
+ struct publication,
+ node_list);
+ list_move_tail(&publ->node_list,
+ &info->node_list);
+ } else if (!list_empty(&info->cluster_list)) {
+ publ = list_first_entry(&info->cluster_list,
+ struct publication,
+ cluster_list);
+ list_move_tail(&publ->cluster_list,
+ &info->cluster_list);
+ } else {
+ publ = list_first_entry(&info->zone_list,
+ struct publication,
+ zone_list);
+ list_move_tail(&publ->zone_list,
+ &info->zone_list);
}
}
/* Round-Robin Algorithm: */
else if (*destnode == tipc_own_addr) {
- publ = sseq->node_list;
- if (publ) {
- sseq->node_list = publ->node_list_next;
- goto found;
- }
+ if (list_empty(&info->node_list))
+ goto no_match;
+ publ = list_first_entry(&info->node_list, struct publication,
+ node_list);
+ list_move_tail(&publ->node_list, &info->node_list);
} else if (in_own_cluster(*destnode)) {
- publ = sseq->cluster_list;
- if (publ) {
- sseq->cluster_list = publ->cluster_list_next;
- goto found;
- }
+ if (list_empty(&info->cluster_list))
+ goto no_match;
+ publ = list_first_entry(&info->cluster_list, struct publication,
+ cluster_list);
+ list_move_tail(&publ->cluster_list, &info->cluster_list);
} else {
- publ = sseq->zone_list;
- if (publ) {
- sseq->zone_list = publ->zone_list_next;
- goto found;
- }
+ publ = list_first_entry(&info->zone_list, struct publication,
+ zone_list);
+ list_move_tail(&publ->zone_list, &info->zone_list);
}
+
+ ref = publ->ref;
+ *destnode = publ->node;
+no_match:
spin_unlock_bh(&seq->lock);
not_found:
read_unlock_bh(&tipc_nametbl_lock);
- return 0;
+ return ref;
}
/**
@@ -676,6 +630,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
struct name_seq *seq;
struct sub_seq *sseq;
struct sub_seq *sseq_stop;
+ struct name_info *info;
int res = 0;
read_lock_bh(&tipc_nametbl_lock);
@@ -693,16 +648,13 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
if (sseq->lower > upper)
break;
- publ = sseq->node_list;
- if (publ) {
- do {
- if (publ->scope <= limit)
- tipc_port_list_add(dports, publ->ref);
- publ = publ->node_list_next;
- } while (publ != sseq->node_list);
+ info = sseq->info;
+ list_for_each_entry(publ, &info->node_list, node_list) {
+ if (publ->scope <= limit)
+ tipc_port_list_add(dports, publ->ref);
}
- if (sseq->cluster_list_size != sseq->node_list_size)
+ if (info->cluster_list_size != info->node_list_size)
res = 1;
}
@@ -840,16 +792,19 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
{
char portIdStr[27];
const char *scope_str[] = {"", " zone", " cluster", " node"};
- struct publication *publ = sseq->zone_list;
+ struct publication *publ;
+ struct name_info *info;
tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
- if (depth == 2 || !publ) {
+ if (depth == 2) {
tipc_printf(buf, "\n");
return;
}
- do {
+ info = sseq->info;
+
+ list_for_each_entry(publ, &info->zone_list, zone_list) {
sprintf(portIdStr, "<%u.%u.%u:%u>",
tipc_zone(publ->node), tipc_cluster(publ->node),
tipc_node(publ->node), publ->ref);
@@ -858,13 +813,9 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
tipc_printf(buf, "%-10u %s", publ->key,
scope_str[publ->scope]);
}
-
- publ = publ->zone_list_next;
- if (publ == sseq->zone_list)
- break;
-
- tipc_printf(buf, "\n%33s", " ");
- } while (1);
+ if (!list_is_last(&publ->zone_list, &info->zone_list))
+ tipc_printf(buf, "\n%33s", " ");
+ };
tipc_printf(buf, "\n");
}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index d228bd6..62d77e5 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -2,7 +2,7 @@
* net/tipc/name_table.h: Include file for TIPC name table code
*
* Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,9 +61,9 @@ struct port_list;
* @subscr: subscription to "node down" event (for off-node publications only)
* @local_list: adjacent entries in list of publications made by this node
* @pport_list: adjacent entries in list of publications made by this port
- * @node_list: next matching name seq publication with >= node scope
- * @cluster_list: next matching name seq publication with >= cluster scope
- * @zone_list: next matching name seq publication with >= zone scope
+ * @node_list: adjacent matching name seq publications with >= node scope
+ * @cluster_list: adjacent matching name seq publications with >= cluster scope
+ * @zone_list: adjacent matching name seq publications with >= zone scope
*
* Note that the node list, cluster list, and zone list are circular lists.
*/
@@ -79,9 +79,9 @@ struct publication {
struct tipc_node_subscr subscr;
struct list_head local_list;
struct list_head pport_list;
- struct publication *node_list_next;
- struct publication *cluster_list_next;
- struct publication *zone_list_next;
+ struct list_head node_list;
+ struct list_head cluster_list;
+ struct list_head zone_list;
};
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 68b3dd6..fafef6c 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -141,17 +141,6 @@ void tipc_net_route_msg(struct sk_buff *buf)
return;
msg = buf_msg(buf);
- msg_incr_reroute_cnt(msg);
- if (msg_reroute_cnt(msg) > 6) {
- if (msg_errcode(msg)) {
- buf_discard(buf);
- } else {
- tipc_reject_msg(buf, msg_destport(msg) ?
- TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME);
- }
- return;
- }
-
/* Handle message for this node */
dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg);
if (tipc_in_scope(dnode, tipc_own_addr)) {
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 2d106ef..27b4bb0 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -112,6 +112,7 @@ 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;
tipc_num_nodes++;
@@ -312,7 +313,7 @@ static void node_established_contact(struct tipc_node *n_ptr)
}
}
-static void node_cleanup_finished(unsigned long node_addr)
+static void node_name_purge_complete(unsigned long node_addr)
{
struct tipc_node *n_ptr;
@@ -320,7 +321,7 @@ static void node_cleanup_finished(unsigned long node_addr)
n_ptr = tipc_node_find(node_addr);
if (n_ptr) {
tipc_node_lock(n_ptr);
- n_ptr->cleanup_required = 0;
+ n_ptr->block_setup &= ~WAIT_NAMES_GONE;
tipc_node_unlock(n_ptr);
}
read_unlock_bh(&tipc_net_lock);
@@ -331,28 +332,32 @@ static void node_lost_contact(struct tipc_node *n_ptr)
char addr_string[16];
u32 i;
- /* 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;
- }
+ 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.supported) {
+ 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;
+ }
+
+ tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr);
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));
+ n_ptr->bclink.supported = 0;
+ }
/* Abort link changeover */
for (i = 0; i < MAX_BEARERS; i++) {
@@ -367,10 +372,10 @@ static void node_lost_contact(struct tipc_node *n_ptr)
/* Notify subscribers */
tipc_nodesub_notify(n_ptr);
- /* Prevent re-contact with node until all cleanup is done */
+ /* Prevent re-contact with node until cleanup is done */
- n_ptr->cleanup_required = 1;
- tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr);
+ n_ptr->block_setup = WAIT_PEER_DOWN | WAIT_NAMES_GONE;
+ tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr);
}
struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 5c61afc..4f15cb4 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -42,6 +42,12 @@
#include "net.h"
#include "bearer.h"
+/* Flags used to block (re)establishment of contact with a neighboring node */
+
+#define WAIT_PEER_DOWN 0x0001 /* wait to see that peer's links are down */
+#define WAIT_NAMES_GONE 0x0002 /* wait for peer's publications to be purged */
+#define WAIT_NODE_DOWN 0x0004 /* wait until peer node is declared down */
+
/**
* struct tipc_node - TIPC node structure
* @addr: network address of node
@@ -52,7 +58,7 @@
* @active_links: pointers to active links to node
* @links: pointers to all links to node
* @working_links: number of working links to node (both active and standby)
- * @cleanup_required: non-zero if cleaning up after a prior loss of contact
+ * @block_setup: bit mask of conditions preventing link establishment to node
* @link_cnt: number of links to node
* @permit_changeover: non-zero if node has redundant links to this system
* @bclink: broadcast-related info
@@ -77,7 +83,7 @@ struct tipc_node {
struct link *links[MAX_BEARERS];
int link_cnt;
int working_links;
- int cleanup_required;
+ int block_setup;
int permit_changeover;
struct {
int supported;
diff --git a/net/tipc/port.c b/net/tipc/port.c
index c68dc95..54d812a 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -222,7 +222,7 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,
p_ptr->max_pkt = MAX_PKT_DEFAULT;
p_ptr->ref = ref;
msg = &p_ptr->phdr;
- tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0);
+ tipc_msg_init(msg, importance, TIPC_NAMED_MSG, NAMED_H_SIZE, 0);
msg_set_origport(msg, ref);
INIT_LIST_HEAD(&p_ptr->wait_list);
INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
@@ -327,26 +327,23 @@ int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
}
/*
- * port_build_proto_msg(): build a port level protocol
- * or a connection abortion message. Called with
- * tipc_port lock on.
+ * port_build_proto_msg(): create connection protocol message for port
+ *
+ * On entry the port must be locked and connected.
*/
-static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
- u32 origport, u32 orignode,
- u32 usr, u32 type, u32 err,
- u32 ack)
+static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr,
+ u32 type, u32 ack)
{
struct sk_buff *buf;
struct tipc_msg *msg;
- buf = tipc_buf_acquire(LONG_H_SIZE);
+ buf = tipc_buf_acquire(INT_H_SIZE);
if (buf) {
msg = buf_msg(buf);
- tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode);
- msg_set_errcode(msg, err);
- msg_set_destport(msg, destport);
- msg_set_origport(msg, origport);
- msg_set_orignode(msg, orignode);
+ tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE,
+ port_peernode(p_ptr));
+ msg_set_destport(msg, port_peerport(p_ptr));
+ msg_set_origport(msg, p_ptr->ref);
msg_set_msgcnt(msg, ack);
}
return buf;
@@ -358,45 +355,48 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
struct sk_buff *rbuf;
struct tipc_msg *rmsg;
int hdr_sz;
- u32 imp = msg_importance(msg);
+ u32 imp;
u32 data_sz = msg_data_sz(msg);
-
- if (data_sz > MAX_REJECT_SIZE)
- data_sz = MAX_REJECT_SIZE;
- if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE))
- imp++;
+ u32 src_node;
+ u32 rmsg_sz;
/* discard rejected message if it shouldn't be returned to sender */
- if (msg_errcode(msg) || msg_dest_droppable(msg)) {
- buf_discard(buf);
- return data_sz;
- }
- /* construct rejected message */
- if (msg_mcast(msg))
- hdr_sz = MCAST_H_SIZE;
- else
- hdr_sz = LONG_H_SIZE;
- rbuf = tipc_buf_acquire(data_sz + hdr_sz);
- if (rbuf == NULL) {
- buf_discard(buf);
- return data_sz;
+ if (WARN(!msg_isdata(msg),
+ "attempt to reject message with user=%u", msg_user(msg))) {
+ dump_stack();
+ goto exit;
}
+ if (msg_errcode(msg) || msg_dest_droppable(msg))
+ goto exit;
+
+ /*
+ * construct returned message by copying rejected message header and
+ * data (or subset), then updating header fields that need adjusting
+ */
+
+ hdr_sz = msg_hdr_sz(msg);
+ rmsg_sz = hdr_sz + min_t(u32, data_sz, MAX_REJECT_SIZE);
+
+ rbuf = tipc_buf_acquire(rmsg_sz);
+ if (rbuf == NULL)
+ goto exit;
+
rmsg = buf_msg(rbuf);
- tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg));
- msg_set_errcode(rmsg, err);
- msg_set_destport(rmsg, msg_origport(msg));
- msg_set_origport(rmsg, msg_destport(msg));
- if (msg_short(msg)) {
- msg_set_orignode(rmsg, tipc_own_addr);
- /* leave name type & instance as zeroes */
- } else {
- msg_set_orignode(rmsg, msg_destnode(msg));
- msg_set_nametype(rmsg, msg_nametype(msg));
- msg_set_nameinst(rmsg, msg_nameinst(msg));
+ skb_copy_to_linear_data(rbuf, msg, rmsg_sz);
+
+ if (msg_connected(rmsg)) {
+ imp = msg_importance(rmsg);
+ if (imp < TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(rmsg, ++imp);
}
- msg_set_size(rmsg, data_sz + hdr_sz);
- skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz);
+ msg_set_non_seq(rmsg, 0);
+ msg_set_size(rmsg, rmsg_sz);
+ msg_set_errcode(rmsg, err);
+ msg_set_prevnode(rmsg, tipc_own_addr);
+ msg_swap_words(rmsg, 4, 5);
+ if (!msg_short(rmsg))
+ msg_swap_words(rmsg, 6, 7);
/* send self-abort message when rejecting on a connected port */
if (msg_connected(msg)) {
@@ -411,9 +411,15 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
tipc_net_route_msg(abuf);
}
- /* send rejected message */
+ /* send returned message & dispose of rejected message */
+
+ src_node = msg_prevnode(msg);
+ if (src_node == tipc_own_addr)
+ tipc_port_recv_msg(rbuf);
+ else
+ tipc_link_send(rbuf, src_node, msg_link_selector(rmsg));
+exit:
buf_discard(buf);
- tipc_net_route_msg(rbuf);
return data_sz;
}
@@ -449,14 +455,7 @@ static void port_timeout(unsigned long ref)
if (p_ptr->probing_state == PROBING) {
buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
} else {
- buf = port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- p_ptr->ref,
- tipc_own_addr,
- CONN_MANAGER,
- CONN_PROBE,
- TIPC_OK,
- 0);
+ buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0);
p_ptr->probing_state = PROBING;
k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
}
@@ -480,100 +479,94 @@ static void port_handle_node_down(unsigned long ref)
static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err)
{
- u32 imp = msg_importance(&p_ptr->phdr);
+ struct sk_buff *buf = port_build_peer_abort_msg(p_ptr, err);
- if (!p_ptr->connected)
- return NULL;
- if (imp < TIPC_CRITICAL_IMPORTANCE)
- imp++;
- return port_build_proto_msg(p_ptr->ref,
- tipc_own_addr,
- port_peerport(p_ptr),
- port_peernode(p_ptr),
- imp,
- TIPC_CONN_MSG,
- err,
- 0);
+ if (buf) {
+ struct tipc_msg *msg = buf_msg(buf);
+ msg_swap_words(msg, 4, 5);
+ msg_swap_words(msg, 6, 7);
+ }
+ return buf;
}
static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err)
{
- u32 imp = msg_importance(&p_ptr->phdr);
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ u32 imp;
if (!p_ptr->connected)
return NULL;
- if (imp < TIPC_CRITICAL_IMPORTANCE)
- imp++;
- return port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- p_ptr->ref,
- tipc_own_addr,
- imp,
- TIPC_CONN_MSG,
- err,
- 0);
+
+ buf = tipc_buf_acquire(BASIC_H_SIZE);
+ if (buf) {
+ msg = buf_msg(buf);
+ memcpy(msg, &p_ptr->phdr, BASIC_H_SIZE);
+ msg_set_hdr_sz(msg, BASIC_H_SIZE);
+ msg_set_size(msg, BASIC_H_SIZE);
+ imp = msg_importance(msg);
+ if (imp < TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(msg, ++imp);
+ msg_set_errcode(msg, err);
+ }
+ return buf;
}
void tipc_port_recv_proto_msg(struct sk_buff *buf)
{
struct tipc_msg *msg = buf_msg(buf);
- struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg));
- u32 err = TIPC_OK;
+ struct tipc_port *p_ptr;
struct sk_buff *r_buf = NULL;
- struct sk_buff *abort_buf = NULL;
-
- if (!p_ptr) {
- err = TIPC_ERR_NO_PORT;
- } else if (p_ptr->connected) {
- if ((port_peernode(p_ptr) != msg_orignode(msg)) ||
- (port_peerport(p_ptr) != msg_origport(msg))) {
- err = TIPC_ERR_NO_PORT;
- } else if (msg_type(msg) == CONN_ACK) {
- int wakeup = tipc_port_congested(p_ptr) &&
- p_ptr->congested &&
- p_ptr->wakeup;
- p_ptr->acked += msg_msgcnt(msg);
- if (tipc_port_congested(p_ptr))
- goto exit;
- p_ptr->congested = 0;
- if (!wakeup)
- goto exit;
- p_ptr->wakeup(p_ptr);
- goto exit;
+ u32 orignode = msg_orignode(msg);
+ u32 origport = msg_origport(msg);
+ u32 destport = msg_destport(msg);
+ int wakeable;
+
+ /* Validate connection */
+
+ p_ptr = tipc_port_lock(destport);
+ if (!p_ptr || !p_ptr->connected ||
+ (port_peernode(p_ptr) != orignode) ||
+ (port_peerport(p_ptr) != origport)) {
+ r_buf = tipc_buf_acquire(BASIC_H_SIZE);
+ if (r_buf) {
+ msg = buf_msg(r_buf);
+ tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG,
+ BASIC_H_SIZE, orignode);
+ msg_set_errcode(msg, TIPC_ERR_NO_PORT);
+ msg_set_origport(msg, destport);
+ msg_set_destport(msg, origport);
}
- } else if (p_ptr->published) {
- err = TIPC_ERR_NO_PORT;
- }
- if (err) {
- r_buf = port_build_proto_msg(msg_origport(msg),
- msg_orignode(msg),
- msg_destport(msg),
- tipc_own_addr,
- TIPC_HIGH_IMPORTANCE,
- TIPC_CONN_MSG,
- err,
- 0);
+ if (p_ptr)
+ tipc_port_unlock(p_ptr);
goto exit;
}
- /* All is fine */
- if (msg_type(msg) == CONN_PROBE) {
- r_buf = port_build_proto_msg(msg_origport(msg),
- msg_orignode(msg),
- msg_destport(msg),
- tipc_own_addr,
- CONN_MANAGER,
- CONN_PROBE_REPLY,
- TIPC_OK,
- 0);
+ /* Process protocol message sent by peer */
+
+ switch (msg_type(msg)) {
+ case CONN_ACK:
+ wakeable = tipc_port_congested(p_ptr) && p_ptr->congested &&
+ p_ptr->wakeup;
+ p_ptr->acked += msg_msgcnt(msg);
+ if (!tipc_port_congested(p_ptr)) {
+ p_ptr->congested = 0;
+ if (wakeable)
+ p_ptr->wakeup(p_ptr);
+ }
+ break;
+ case CONN_PROBE:
+ r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0);
+ break;
+ default:
+ /* CONN_PROBE_REPLY or unrecognized - no action required */
+ break;
}
p_ptr->probing_state = CONFIRMED;
+ tipc_port_unlock(p_ptr);
exit:
- if (p_ptr)
- tipc_port_unlock(p_ptr);
tipc_net_route_msg(r_buf);
- tipc_net_route_msg(abort_buf);
buf_discard(buf);
}
@@ -889,14 +882,7 @@ void tipc_acknowledge(u32 ref, u32 ack)
return;
if (p_ptr->connected) {
p_ptr->conn_unacked -= ack;
- buf = port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- ref,
- tipc_own_addr,
- CONN_MANAGER,
- CONN_ACK,
- TIPC_OK,
- ack);
+ buf = port_build_proto_msg(p_ptr, CONN_ACK, ack);
}
tipc_port_unlock(p_ptr);
tipc_net_route_msg(buf);
@@ -1140,19 +1126,7 @@ int tipc_shutdown(u32 ref)
if (!p_ptr)
return -EINVAL;
- if (p_ptr->connected) {
- u32 imp = msg_importance(&p_ptr->phdr);
- if (imp < TIPC_CRITICAL_IMPORTANCE)
- imp++;
- buf = port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- ref,
- tipc_own_addr,
- imp,
- TIPC_CONN_MSG,
- TIPC_CONN_SHUTDOWN,
- 0);
- }
+ buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN);
tipc_port_unlock(p_ptr);
tipc_net_route_msg(buf);
return tipc_disconnect(ref);
@@ -1238,7 +1212,7 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
msg_set_type(msg, TIPC_NAMED_MSG);
msg_set_orignode(msg, tipc_own_addr);
msg_set_origport(msg, ref);
- msg_set_hdr_sz(msg, LONG_H_SIZE);
+ msg_set_hdr_sz(msg, NAMED_H_SIZE);
msg_set_nametype(msg, name->type);
msg_set_nameinst(msg, name->instance);
msg_set_lookup_scope(msg, tipc_addr_scope(domain));
@@ -1291,7 +1265,7 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest,
msg_set_origport(msg, ref);
msg_set_destnode(msg, dest->node);
msg_set_destport(msg, dest->ref);
- msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
+ msg_set_hdr_sz(msg, BASIC_H_SIZE);
if (dest->node == tipc_own_addr)
res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect,
@@ -1331,13 +1305,13 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
msg_set_origport(msg, ref);
msg_set_destnode(msg, dest->node);
msg_set_destport(msg, dest->ref);
- msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
- msg_set_size(msg, DIR_MSG_H_SIZE + dsz);
- if (skb_cow(buf, DIR_MSG_H_SIZE))
+ msg_set_hdr_sz(msg, BASIC_H_SIZE);
+ msg_set_size(msg, BASIC_H_SIZE + dsz);
+ if (skb_cow(buf, BASIC_H_SIZE))
return -ENOMEM;
- skb_push(buf, DIR_MSG_H_SIZE);
- skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE);
+ skb_push(buf, BASIC_H_SIZE);
+ skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE);
if (dest->node == tipc_own_addr)
res = tipc_port_recv_msg(buf);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3610786..580ecf2 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -34,11 +34,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <linux/export.h>
#include <net/sock.h>
-#include <linux/tipc.h>
-#include <linux/tipc_config.h>
-
#include "core.h"
#include "port.h"
@@ -52,7 +50,7 @@ struct tipc_sock {
struct sock sk;
struct tipc_port *p;
struct tipc_portid peer_name;
- long conn_timeout;
+ unsigned int conn_timeout;
};
#define tipc_sk(sk) ((struct tipc_sock *)(sk))
@@ -234,7 +232,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
sock_init_data(sock, sk);
sk->sk_backlog_rcv = backlog_rcv;
tipc_sk(sk)->p = tp_ptr;
- tipc_sk(sk)->conn_timeout = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
+ tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT;
spin_unlock_bh(tp_ptr->lock);
@@ -528,6 +526,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
struct tipc_port *tport = tipc_sk_port(sk);
struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
int needs_conn;
+ long timeout_val;
int res = -EINVAL;
if (unlikely(!dest))
@@ -567,6 +566,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
reject_rx_queue(sk);
}
+ timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
+
do {
if (dest->addrtype == TIPC_ADDR_NAME) {
res = dest_name_check(dest, m);
@@ -603,16 +604,14 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
sock->state = SS_CONNECTING;
break;
}
- if (m->msg_flags & MSG_DONTWAIT) {
- res = -EWOULDBLOCK;
+ if (timeout_val <= 0L) {
+ res = timeout_val ? timeout_val : -EWOULDBLOCK;
break;
}
release_sock(sk);
- res = wait_event_interruptible(*sk_sleep(sk),
- !tport->congested);
+ timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk),
+ !tport->congested, timeout_val);
lock_sock(sk);
- if (res)
- break;
} while (1);
exit:
@@ -639,6 +638,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
struct sock *sk = sock->sk;
struct tipc_port *tport = tipc_sk_port(sk);
struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+ long timeout_val;
int res;
/* Handle implied connection establishment */
@@ -653,6 +653,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
if (iocb)
lock_sock(sk);
+ timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
+
do {
if (unlikely(sock->state != SS_CONNECTED)) {
if (sock->state == SS_DISCONNECTING)
@@ -666,16 +668,14 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
total_len);
if (likely(res != -ELINKCONG))
break;
- if (m->msg_flags & MSG_DONTWAIT) {
- res = -EWOULDBLOCK;
+ if (timeout_val <= 0L) {
+ res = timeout_val ? timeout_val : -EWOULDBLOCK;
break;
}
release_sock(sk);
- res = wait_event_interruptible(*sk_sleep(sk),
- (!tport->congested || !tport->connected));
+ timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk),
+ (!tport->congested || !tport->connected), timeout_val);
lock_sock(sk);
- if (res)
- break;
} while (1);
if (iocb)
@@ -949,9 +949,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
goto exit;
}
- /* will be updated in set_orig_addr() if needed */
- m->msg_namelen = 0;
-
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart:
@@ -1078,9 +1075,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
goto exit;
}
- /* will be updated in set_orig_addr() if needed */
- m->msg_namelen = 0;
-
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart:
@@ -1379,7 +1373,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
struct msghdr m = {NULL,};
struct sk_buff *buf;
struct tipc_msg *msg;
- long timeout;
+ unsigned int timeout;
int res;
lock_sock(sk);
@@ -1444,7 +1438,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
res = wait_event_interruptible_timeout(*sk_sleep(sk),
(!skb_queue_empty(&sk->sk_receive_queue) ||
(sock->state != SS_CONNECTING)),
- timeout ? timeout : MAX_SCHEDULE_TIMEOUT);
+ timeout ? (long)msecs_to_jiffies(timeout)
+ : MAX_SCHEDULE_TIMEOUT);
lock_sock(sk);
if (res > 0) {
@@ -1490,9 +1485,7 @@ static int listen(struct socket *sock, int len)
lock_sock(sk);
- if (sock->state == SS_READY)
- res = -EOPNOTSUPP;
- else if (sock->state != SS_UNCONNECTED)
+ if (sock->state != SS_UNCONNECTED)
res = -EINVAL;
else {
sock->state = SS_LISTENING;
@@ -1520,10 +1513,6 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
lock_sock(sk);
- if (sock->state == SS_READY) {
- res = -EOPNOTSUPP;
- goto exit;
- }
if (sock->state != SS_LISTENING) {
res = -EINVAL;
goto exit;
@@ -1552,6 +1541,8 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
u32 new_ref = new_tport->ref;
struct tipc_msg *msg = buf_msg(buf);
+ security_sk_clone(sock->sk, new_sock->sk);
+
lock_sock(new_sk);
/*
@@ -1706,7 +1697,7 @@ static int setsockopt(struct socket *sock,
res = tipc_set_portunreturnable(tport->ref, value);
break;
case TIPC_CONN_TIMEOUT:
- tipc_sk(sk)->conn_timeout = msecs_to_jiffies(value);
+ tipc_sk(sk)->conn_timeout = value;
/* no need to set "res", since already 0 at this point */
break;
default:
@@ -1762,7 +1753,7 @@ static int getsockopt(struct socket *sock,
res = tipc_portunreturnable(tport->ref, &value);
break;
case TIPC_CONN_TIMEOUT:
- value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout);
+ value = tipc_sk(sk)->conn_timeout;
/* no need to set "res", since already 0 at this point */
break;
case TIPC_NODE_RECVQ_DEPTH:
@@ -1800,11 +1791,11 @@ static const struct proto_ops msg_ops = {
.bind = bind,
.connect = connect,
.socketpair = sock_no_socketpair,
- .accept = accept,
+ .accept = sock_no_accept,
.getname = get_name,
.poll = poll,
.ioctl = sock_no_ioctl,
- .listen = listen,
+ .listen = sock_no_listen,
.shutdown = shutdown,
.setsockopt = setsockopt,
.getsockopt = getsockopt,
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 6cf7268..1983717 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -151,7 +151,7 @@ void tipc_subscr_report_overlap(struct subscription *sub,
if (!must && !(sub->filter & TIPC_SUB_PORTS))
return;
- sub->event_cb(sub, found_lower, found_upper, event, port_ref, node);
+ subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
}
/**
@@ -365,7 +365,6 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s,
subscr_terminate(subscriber);
return NULL;
}
- sub->event_cb = subscr_send_event;
INIT_LIST_HEAD(&sub->nameseq_list);
list_add(&sub->subscription_list, &subscriber->subscription_list);
sub->server_ref = subscriber->port_ref;
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index 45d89bf..4b06ef6 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -39,16 +39,11 @@
struct subscription;
-typedef void (*tipc_subscr_event) (struct subscription *sub,
- u32 found_lower, u32 found_upper,
- u32 event, u32 port_ref, u32 node);
-
/**
* struct subscription - TIPC network topology subscription object
* @seq: name sequence associated with subscription
* @timeout: duration of subscription (in ms)
* @filter: event filtering to be done for subscription
- * @event_cb: routine invoked when a subscription event is detected
* @timer: timer governing subscription duration (optional)
* @nameseq_list: adjacent subscriptions in name sequence's subscription list
* @subscription_list: adjacent subscriptions in subscriber's subscription list
@@ -61,7 +56,6 @@ struct subscription {
struct tipc_name_seq seq;
u32 timeout;
u32 filter;
- tipc_subscr_event event_cb;
struct timer_list timer;
struct list_head nameseq_list;
struct list_head subscription_list;