diff options
Diffstat (limited to 'net/tipc')
42 files changed, 1585 insertions, 3666 deletions
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig index b74f78d0c03..2c5954b8593 100644 --- a/net/tipc/Kconfig +++ b/net/tipc/Kconfig @@ -29,40 +29,6 @@ config TIPC_ADVANCED Saying Y here will open some advanced configuration for TIPC. Most users do not need to bother; if unsure, just say N. -config TIPC_ZONES - int "Maximum number of zones in a network" - depends on TIPC_ADVANCED - range 1 255 - default "3" - help - Specifies how many zones can be supported in a TIPC network. - Can range from 1 to 255 zones; default is 3. - - Setting this to a smaller value saves some memory; - setting it to a higher value allows for more zones. - -config TIPC_CLUSTERS - int "Maximum number of clusters in a zone" - depends on TIPC_ADVANCED - range 1 1 - default "1" - help - Specifies how many clusters can be supported in a TIPC zone. - - *** Currently TIPC only supports a single cluster per zone. *** - -config TIPC_NODES - int "Maximum number of nodes in a cluster" - depends on TIPC_ADVANCED - range 8 2047 - default "255" - help - Specifies how many nodes can be supported in a TIPC cluster. - Can range from 8 to 2047 nodes; default is 255. - - Setting this to a smaller value saves some memory; - setting it to higher allows for more nodes. - config TIPC_PORTS int "Maximum number of ports in a node" depends on TIPC_ADVANCED @@ -72,7 +38,7 @@ config TIPC_PORTS Specifies how many ports can be supported by a node. Can range from 127 to 65535 ports; default is 8191. - Setting this to a smaller value saves some memory, + Setting this to a smaller value saves some memory, setting it to higher allows for more ports. config TIPC_LOG @@ -89,12 +55,15 @@ config TIPC_LOG managed remotely via TIPC. config TIPC_DEBUG - bool "Enable debug messages" + bool "Enable debugging support" default n help - This enables debugging of TIPC. + Saying Y here enables TIPC debugging capabilities used by developers. + Most users do not need to bother; if unsure, just say N. - Only say Y here if you are having trouble with TIPC. It will - enable the display of detailed information about what is going on. + Enabling debugging support causes TIPC to display data about its + internal state when certain abnormal conditions occur. It also + makes it easy for developers to capture additional information of + interest using the dbg() or msg_dbg() macros. endif # TIPC diff --git a/net/tipc/Makefile b/net/tipc/Makefile index dceb7027946..521d24d04ab 100644 --- a/net/tipc/Makefile +++ b/net/tipc/Makefile @@ -4,10 +4,10 @@ obj-$(CONFIG_TIPC) := tipc.o -tipc-y += addr.o bcast.o bearer.o config.o cluster.o \ +tipc-y += addr.o bcast.o bearer.o config.o \ core.o handler.o link.o discover.o msg.o \ name_distr.o subscr.o name_table.o net.o \ netlink.o node.o node_subscr.o port.o ref.o \ - socket.o user_reg.o zone.o dbg.o eth_media.o + socket.o log.o eth_media.o # End of file diff --git a/net/tipc/addr.c b/net/tipc/addr.c index 8a2e89bffde..a6fdab33877 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -2,7 +2,7 @@ * net/tipc/addr.c: TIPC address utility routines * * 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 @@ -35,17 +35,13 @@ */ #include "core.h" -#include "dbg.h" #include "addr.h" -#include "zone.h" -#include "cluster.h" -#include "net.h" /** * tipc_addr_domain_valid - validates a network domain address * * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>, - * where Z, C, and N are non-zero and do not exceed the configured limits. + * where Z, C, and N are non-zero. * * Returns 1 if domain address is valid, otherwise 0 */ @@ -55,16 +51,6 @@ int tipc_addr_domain_valid(u32 addr) u32 n = tipc_node(addr); u32 c = tipc_cluster(addr); u32 z = tipc_zone(addr); - u32 max_nodes = tipc_max_nodes; - - if (is_slave(addr)) - max_nodes = LOWEST_SLAVE + tipc_max_slaves; - if (n > max_nodes) - return 0; - if (c > tipc_max_clusters) - return 0; - if (z > tipc_max_zones) - return 0; if (n && (!z || !c)) return 0; @@ -76,8 +62,7 @@ int tipc_addr_domain_valid(u32 addr) /** * tipc_addr_node_valid - validates a proposed network address for this node * - * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed - * the configured limits. + * Accepts <Z.C.N>, where Z, C, and N are non-zero. * * Returns 1 if address can be used, otherwise 0 */ @@ -91,9 +76,9 @@ int tipc_in_scope(u32 domain, u32 addr) { if (!domain || (domain == addr)) return 1; - if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ + if (domain == tipc_cluster_mask(addr)) /* domain <Z.C.0> */ return 1; - if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ + if (domain == tipc_zone_mask(addr)) /* domain <Z.0.0> */ return 1; return 0; } diff --git a/net/tipc/addr.h b/net/tipc/addr.h index c1cc5724d8c..e4f35afe320 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -37,19 +37,17 @@ #ifndef _TIPC_ADDR_H #define _TIPC_ADDR_H -static inline u32 own_node(void) -{ - return tipc_node(tipc_own_addr); -} +#define TIPC_ZONE_MASK 0xff000000u +#define TIPC_CLUSTER_MASK 0xfffff000u -static inline u32 own_cluster(void) +static inline u32 tipc_zone_mask(u32 addr) { - return tipc_cluster(tipc_own_addr); + return addr & TIPC_ZONE_MASK; } -static inline u32 own_zone(void) +static inline u32 tipc_cluster_mask(u32 addr) { - return tipc_zone(tipc_own_addr); + return addr & TIPC_CLUSTER_MASK; } static inline int in_own_cluster(u32 addr) @@ -57,16 +55,6 @@ static inline int in_own_cluster(u32 addr) return !((addr ^ tipc_own_addr) >> 12); } -static inline int is_slave(u32 addr) -{ - return addr & 0x800; -} - -static inline int may_route(u32 addr) -{ - return(addr ^ tipc_own_addr) >> 11; -} - /** * addr_domain - convert 2-bit scope value to equivalent message lookup domain * @@ -74,14 +62,13 @@ static inline int may_route(u32 addr) * after a network hop. */ -static inline int addr_domain(int sc) +static inline u32 addr_domain(u32 sc) { if (likely(sc == TIPC_NODE_SCOPE)) return tipc_own_addr; if (sc == TIPC_CLUSTER_SCOPE) - return tipc_addr(tipc_zone(tipc_own_addr), - tipc_cluster(tipc_own_addr), 0); - return tipc_addr(tipc_zone(tipc_own_addr), 0, 0); + return tipc_cluster_mask(tipc_own_addr); + return tipc_zone_mask(tipc_own_addr); } int tipc_addr_domain_valid(u32); diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 22a60fc9839..fa68d1e9ff4 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -3,7 +3,7 @@ * * Copyright (c) 2004-2006, Ericsson AB * Copyright (c) 2004, Intel Corporation. - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,32 +36,14 @@ */ #include "core.h" -#include "msg.h" -#include "dbg.h" #include "link.h" -#include "net.h" -#include "node.h" #include "port.h" -#include "addr.h" -#include "node_subscr.h" -#include "name_distr.h" -#include "bearer.h" -#include "name_table.h" #include "bcast.h" #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ -#define BCLINK_LOG_BUF_SIZE 0 - -/* - * Loss rate for incoming broadcast frames; used to test retransmission code. - * Set to N to cause every N'th frame to be discarded; 0 => don't discard any. - */ - -#define TIPC_BCAST_LOSS_RATE 0 - /** * struct bcbearer_pair - a pair of bearers used by broadcast link * @primary: pointer to primary bearer @@ -72,8 +54,8 @@ */ struct bcbearer_pair { - struct bearer *primary; - struct bearer *secondary; + struct tipc_bearer *primary; + struct tipc_bearer *secondary; }; /** @@ -92,7 +74,7 @@ struct bcbearer_pair { */ struct bcbearer { - struct bearer bearer; + struct tipc_bearer bearer; struct media media; struct bcbearer_pair bpairs[MAX_BEARERS]; struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1]; @@ -104,6 +86,7 @@ struct bcbearer { * struct bclink - link used for broadcast messages * @link: (non-standard) broadcast link structure * @node: (non-standard) node structure representing b'cast link's peer node + * @retransmit_to: node that most recently requested a retransmit * * Handles sequence numbering, fragmentation, bundling, etc. */ @@ -111,14 +94,18 @@ struct bcbearer { struct bclink { struct link link; struct tipc_node node; + struct tipc_node *retransmit_to; }; -static struct bcbearer *bcbearer = NULL; -static struct bclink *bclink = NULL; -static struct link *bcl = NULL; +static struct bcbearer *bcbearer; +static struct bclink *bclink; +static struct link *bcl; static DEFINE_SPINLOCK(bc_lock); +/* broadcast-capable node map */ +struct tipc_node_map tipc_bcast_nmap; + const char tipc_bclink_name[] = "broadcast-link"; static void tipc_nmap_diff(struct tipc_node_map *nm_a, @@ -192,6 +179,17 @@ static int bclink_ack_allowed(u32 n) /** + * tipc_bclink_retransmit_to - get most recent node to request retransmission + * + * Called with bc_lock locked + */ + +struct tipc_node *tipc_bclink_retransmit_to(void) +{ + return bclink->retransmit_to; +} + +/** * bclink_retransmit_pkt - retransmit broadcast packets * @after: sequence number of last packet to *not* retransmit * @to: sequence number of last packet to retransmit @@ -204,9 +202,8 @@ static void bclink_retransmit_pkt(u32 after, u32 to) struct sk_buff *buf; buf = bcl->first_out; - while (buf && less_eq(buf_seqno(buf), after)) { + while (buf && less_eq(buf_seqno(buf), after)) buf = buf->next; - } tipc_link_retransmit(bcl, buf, mod(to - after)); } @@ -232,9 +229,8 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) /* Skip over packets that node has previously acknowledged */ crs = bcl->first_out; - while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) { + while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) crs = crs->next; - } /* Update packets that node is now acknowledging */ @@ -295,6 +291,7 @@ static void bclink_send_nack(struct tipc_node *n_ptr) msg = buf_msg(buf); tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, n_ptr->addr); + msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tipc_net_id); msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); msg_set_bcgap_after(msg, n_ptr->bclink.gap_after); @@ -410,13 +407,9 @@ int tipc_bclink_send_msg(struct sk_buff *buf) spin_lock_bh(&bc_lock); res = tipc_link_send_buf(bcl, buf); - if (unlikely(res == -ELINKCONG)) - buf_discard(buf); - else + if (likely(res > 0)) bclink_set_last_sent(); - if (bcl->out_queue_size > bcl->stats.max_queue_sz) - bcl->stats.max_queue_sz = bcl->out_queue_size; bcl->stats.queue_sz_counts++; bcl->stats.accu_queue_sz += bcl->out_queue_size; @@ -432,17 +425,12 @@ int tipc_bclink_send_msg(struct sk_buff *buf) void tipc_bclink_recv_pkt(struct sk_buff *buf) { -#if (TIPC_BCAST_LOSS_RATE) - static int rx_count = 0; -#endif struct tipc_msg *msg = buf_msg(buf); - struct tipc_node* node = tipc_node_find(msg_prevnode(msg)); + struct tipc_node *node = tipc_node_find(msg_prevnode(msg)); u32 next_in; u32 seqno; struct sk_buff *deferred; - msg_dbg(msg, "<BC<<<"); - if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported || (msg_mc_netid(msg) != tipc_net_id))) { buf_discard(buf); @@ -450,17 +438,15 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) } if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { - msg_dbg(msg, "<BCNACK<<<"); 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); bcl->stats.recv_nacks++; - bcl->owner->next = node; /* remember requestor */ + bclink->retransmit_to = node; bclink_retransmit_pkt(msg_bcgap_after(msg), msg_bcgap_to(msg)); - bcl->owner->next = NULL; spin_unlock_bh(&bc_lock); } else { tipc_bclink_peek_nack(msg_destnode(msg), @@ -472,14 +458,6 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) return; } -#if (TIPC_BCAST_LOSS_RATE) - if (++rx_count == TIPC_BCAST_LOSS_RATE) { - rx_count = 0; - buf_discard(buf); - return; - } -#endif - tipc_node_lock(node); receive: deferred = node->bclink.deferred_head; @@ -574,8 +552,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf, if (likely(!msg_non_seq(buf_msg(buf)))) { struct tipc_msg *msg; - assert(tipc_cltr_bcast_nodes.count != 0); - bcbuf_set_acks(buf, tipc_cltr_bcast_nodes.count); + 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); @@ -584,11 +562,11 @@ static int tipc_bcbearer_send(struct sk_buff *buf, /* Send buffer over bearers until all targets reached */ - bcbearer->remains = tipc_cltr_bcast_nodes; + bcbearer->remains = tipc_bcast_nmap; for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { - struct bearer *p = bcbearer->bpairs[bp_index].primary; - struct bearer *s = bcbearer->bpairs[bp_index].secondary; + struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary; + struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; if (!p) break; /* no more bearers to try */ @@ -597,11 +575,11 @@ static int tipc_bcbearer_send(struct sk_buff *buf, if (bcbearer->remains_new.count == bcbearer->remains.count) continue; /* bearer pair doesn't add anything */ - if (p->publ.blocked || - p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { + if (p->blocked || + p->media->send_msg(buf, p, &p->media->bcast_addr)) { /* unable to send on primary bearer */ - if (!s || s->publ.blocked || - s->media->send_msg(buf, &s->publ, + if (!s || s->blocked || + s->media->send_msg(buf, s, &s->media->bcast_addr)) { /* unable to send on either bearer */ continue; @@ -646,7 +624,7 @@ void tipc_bcbearer_sort(void) memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); for (b_index = 0; b_index < MAX_BEARERS; b_index++) { - struct bearer *b = &tipc_bearers[b_index]; + struct tipc_bearer *b = &tipc_bearers[b_index]; if (!b->active || !b->nodes.count) continue; @@ -695,12 +673,12 @@ void tipc_bcbearer_sort(void) void tipc_bcbearer_push(void) { - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; spin_lock_bh(&bc_lock); b_ptr = &bcbearer->bearer; - if (b_ptr->publ.blocked) { - b_ptr->publ.blocked = 0; + if (b_ptr->blocked) { + b_ptr->blocked = 0; tipc_bearer_lock_push(b_ptr); } spin_unlock_bh(&bc_lock); @@ -782,7 +760,6 @@ int tipc_bclink_init(void) bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC); bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC); if (!bcbearer || !bclink) { - nomem: warn("Multicast link creation failed, no memory\n"); kfree(bcbearer); bcbearer = NULL; @@ -807,14 +784,6 @@ int tipc_bclink_init(void) bcl->state = WORKING_WORKING; strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); - if (BCLINK_LOG_BUF_SIZE) { - char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC); - - if (!pb) - goto nomem; - tipc_printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE); - } - return 0; } @@ -823,8 +792,6 @@ void tipc_bclink_stop(void) spin_lock_bh(&bc_lock); if (bcbearer) { tipc_link_stop(bcl); - if (BCLINK_LOG_BUF_SIZE) - kfree(bcl->print_buf.buf); bcl = NULL; kfree(bclink); bclink = NULL; diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 011c03f0a4a..500c97f1c85 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -2,7 +2,7 @@ * net/tipc/bcast.h: Include file for TIPC broadcast code * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ struct tipc_node_map { u32 map[MAX_NODES / WSIZE]; }; +extern struct tipc_node_map tipc_bcast_nmap; #define PLSIZE 32 @@ -89,6 +90,7 @@ void tipc_port_list_free(struct port_list *pl_ptr); int tipc_bclink_init(void); void tipc_bclink_stop(void); +struct tipc_node *tipc_bclink_retransmit_to(void); void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked); int tipc_bclink_send_msg(struct sk_buff *buf); void tipc_bclink_recv_pkt(struct sk_buff *buf); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 9927d1d56c4..85209eadfae 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -2,7 +2,7 @@ * net/tipc/bearer.c: TIPC bearer code * * Copyright (c) 1996-2006, Ericsson AB - * Copyright (c) 2004-2006, Wind River Systems + * Copyright (c) 2004-2006, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,19 +36,17 @@ #include "core.h" #include "config.h" -#include "dbg.h" #include "bearer.h" -#include "link.h" -#include "port.h" #include "discover.h" -#include "bcast.h" #define MAX_ADDR_STR 32 static struct media media_list[MAX_MEDIA]; -static u32 media_count = 0; +static u32 media_count; -struct bearer tipc_bearers[MAX_BEARERS]; +struct tipc_bearer tipc_bearers[MAX_BEARERS]; + +static void bearer_disable(struct tipc_bearer *b_ptr); /** * media_name_valid - validate media name @@ -162,12 +160,10 @@ int tipc_register_media(u32 media_type, m_ptr->disable_bearer = disable; m_ptr->addr2str = addr2str; memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr)); - m_ptr->bcast = 1; strcpy(m_ptr->name, name); m_ptr->priority = bearer_priority; m_ptr->tolerance = link_tolerance; m_ptr->window = send_window_limit; - dbg("Media <%s> registered\n", name); res = 0; exit: write_unlock_bh(&tipc_net_lock); @@ -199,9 +195,8 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) unchar *addr = (unchar *)&a->dev_addr; tipc_printf(pb, "UNKNOWN(%u)", media_type); - for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { + for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) tipc_printf(pb, "-%02x", addr[i]); - } } } @@ -256,7 +251,8 @@ static int bearer_name_validate(const char *name, /* ensure all component parts of bearer name are present */ media_name = name_copy; - if ((if_name = strchr(media_name, ':')) == NULL) + if_name = strchr(media_name, ':'); + if (if_name == NULL) return 0; *(if_name++) = 0; media_len = if_name - media_name; @@ -283,13 +279,13 @@ static int bearer_name_validate(const char *name, * bearer_find - locates bearer object with matching bearer name */ -static struct bearer *bearer_find(const char *name) +static struct tipc_bearer *bearer_find(const char *name) { - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; u32 i; for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { - if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) + if (b_ptr->active && (!strcmp(b_ptr->name, name))) return b_ptr; } return NULL; @@ -299,16 +295,16 @@ static struct bearer *bearer_find(const char *name) * tipc_bearer_find_interface - locates bearer object with matching interface name */ -struct bearer *tipc_bearer_find_interface(const char *if_name) +struct tipc_bearer *tipc_bearer_find_interface(const char *if_name) { - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; char *b_if_name; u32 i; for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { if (!b_ptr->active) continue; - b_if_name = strchr(b_ptr->publ.name, ':') + 1; + b_if_name = strchr(b_ptr->name, ':') + 1; if (!strcmp(b_if_name, if_name)) return b_ptr; } @@ -323,7 +319,7 @@ struct sk_buff *tipc_bearer_get_names(void) { struct sk_buff *buf; struct media *m_ptr; - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; int i, j; buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); @@ -336,8 +332,8 @@ struct sk_buff *tipc_bearer_get_names(void) b_ptr = &tipc_bearers[j]; if (b_ptr->active && (b_ptr->media == m_ptr)) { tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, - b_ptr->publ.name, - strlen(b_ptr->publ.name) + 1); + b_ptr->name, + strlen(b_ptr->name) + 1); } } } @@ -345,18 +341,18 @@ struct sk_buff *tipc_bearer_get_names(void) return buf; } -void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest) +void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) { tipc_nmap_add(&b_ptr->nodes, dest); - tipc_disc_update_link_req(b_ptr->link_req); tipc_bcbearer_sort(); + tipc_disc_add_dest(b_ptr->link_req); } -void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest) +void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) { tipc_nmap_remove(&b_ptr->nodes, dest); - tipc_disc_update_link_req(b_ptr->link_req); tipc_bcbearer_sort(); + tipc_disc_remove_dest(b_ptr->link_req); } /* @@ -367,12 +363,12 @@ void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest) * bearer.lock must be taken before calling * Returns binary true(1) ore false(0) */ -static int bearer_push(struct bearer *b_ptr) +static int bearer_push(struct tipc_bearer *b_ptr) { u32 res = 0; struct link *ln, *tln; - if (b_ptr->publ.blocked) + if (b_ptr->blocked) return 0; while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { @@ -387,13 +383,13 @@ static int bearer_push(struct bearer *b_ptr) return list_empty(&b_ptr->cong_links); } -void tipc_bearer_lock_push(struct bearer *b_ptr) +void tipc_bearer_lock_push(struct tipc_bearer *b_ptr) { int res; - spin_lock_bh(&b_ptr->publ.lock); + spin_lock_bh(&b_ptr->lock); res = bearer_push(b_ptr); - spin_unlock_bh(&b_ptr->publ.lock); + spin_unlock_bh(&b_ptr->lock); if (res) tipc_bcbearer_push(); } @@ -403,16 +399,14 @@ void tipc_bearer_lock_push(struct bearer *b_ptr) * Interrupt enabling new requests after bearer congestion or blocking: * See bearer_send(). */ -void tipc_continue(struct tipc_bearer *tb_ptr) +void tipc_continue(struct tipc_bearer *b_ptr) { - struct bearer *b_ptr = (struct bearer *)tb_ptr; - - spin_lock_bh(&b_ptr->publ.lock); + 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->publ.blocked = 0; - spin_unlock_bh(&b_ptr->publ.lock); + b_ptr->blocked = 0; + spin_unlock_bh(&b_ptr->lock); } /* @@ -423,7 +417,7 @@ void tipc_continue(struct tipc_bearer *tb_ptr) * bearer.lock is busy */ -static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr) +static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr, struct link *l_ptr) { list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); } @@ -436,11 +430,11 @@ static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_p * bearer.lock is free */ -void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr) +void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct link *l_ptr) { - spin_lock_bh(&b_ptr->publ.lock); + spin_lock_bh(&b_ptr->lock); tipc_bearer_schedule_unlocked(b_ptr, l_ptr); - spin_unlock_bh(&b_ptr->publ.lock); + spin_unlock_bh(&b_ptr->lock); } @@ -449,18 +443,18 @@ void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr) * and if there is, try to resolve it before returning. * 'tipc_net_lock' is read_locked when this function is called */ -int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) +int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, struct link *l_ptr) { int res = 1; if (list_empty(&b_ptr->cong_links)) return 1; - spin_lock_bh(&b_ptr->publ.lock); + spin_lock_bh(&b_ptr->lock); if (!bearer_push(b_ptr)) { tipc_bearer_schedule_unlocked(b_ptr, l_ptr); res = 0; } - spin_unlock_bh(&b_ptr->publ.lock); + spin_unlock_bh(&b_ptr->lock); return res; } @@ -468,9 +462,9 @@ int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) * tipc_bearer_congested - determines if bearer is currently congested */ -int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr) +int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct link *l_ptr) { - if (unlikely(b_ptr->publ.blocked)) + if (unlikely(b_ptr->blocked)) return 1; if (likely(list_empty(&b_ptr->cong_links))) return 0; @@ -481,9 +475,9 @@ int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr) * tipc_enable_bearer - enable bearer with the given name */ -int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) +int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) { - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; struct media *m_ptr; struct bearer_name b_name; char addr_string[16]; @@ -501,9 +495,16 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) warn("Bearer <%s> rejected, illegal name\n", name); return -EINVAL; } - if (!tipc_addr_domain_valid(bcast_scope) || - !tipc_in_scope(bcast_scope, tipc_own_addr)) { - warn("Bearer <%s> rejected, illegal broadcast scope\n", name); + if (tipc_addr_domain_valid(disc_domain) && + (disc_domain != tipc_own_addr)) { + if (tipc_in_scope(disc_domain, tipc_own_addr)) { + disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK; + res = 0; /* accept any node in own cluster */ + } else if (in_own_cluster(disc_domain)) + res = 0; /* accept specified node in own cluster */ + } + if (res) { + warn("Bearer <%s> rejected, illegal discovery domain\n", name); return -EINVAL; } if ((priority < TIPC_MIN_LINK_PRI || @@ -519,7 +520,7 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) if (!m_ptr) { warn("Bearer <%s> rejected, media <%s> not registered\n", name, b_name.media_name); - goto failed; + goto exit; } if (priority == TIPC_MEDIA_LINK_PRI) @@ -533,16 +534,16 @@ restart: bearer_id = i; continue; } - if (!strcmp(name, tipc_bearers[i].publ.name)) { + if (!strcmp(name, tipc_bearers[i].name)) { warn("Bearer <%s> rejected, already enabled\n", name); - goto failed; + goto exit; } if ((tipc_bearers[i].priority == priority) && (++with_this_prio > 2)) { if (priority-- == 0) { warn("Bearer <%s> rejected, duplicate priority\n", name); - goto failed; + goto exit; } warn("Bearer <%s> priority adjustment required %u->%u\n", name, priority + 1, priority); @@ -552,35 +553,36 @@ restart: if (bearer_id >= MAX_BEARERS) { warn("Bearer <%s> rejected, bearer limit reached (%u)\n", name, MAX_BEARERS); - goto failed; + goto exit; } b_ptr = &tipc_bearers[bearer_id]; - strcpy(b_ptr->publ.name, name); - res = m_ptr->enable_bearer(&b_ptr->publ); + strcpy(b_ptr->name, name); + res = m_ptr->enable_bearer(b_ptr); if (res) { warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); - goto failed; + goto exit; } b_ptr->identity = bearer_id; b_ptr->media = m_ptr; b_ptr->net_plane = bearer_id + 'A'; b_ptr->active = 1; - b_ptr->detect_scope = bcast_scope; b_ptr->priority = priority; INIT_LIST_HEAD(&b_ptr->cong_links); INIT_LIST_HEAD(&b_ptr->links); - if (m_ptr->bcast) { - b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, - bcast_scope, 2); + spin_lock_init(&b_ptr->lock); + + res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain); + if (res) { + bearer_disable(b_ptr); + warn("Bearer <%s> rejected, discovery object creation failed\n", + name); + goto exit; } - spin_lock_init(&b_ptr->publ.lock); - write_unlock_bh(&tipc_net_lock); info("Enabled bearer <%s>, discovery domain %s, priority %u\n", - name, tipc_addr_string_fill(addr_string, bcast_scope), priority); - return 0; -failed: + name, tipc_addr_string_fill(addr_string, disc_domain), priority); +exit: write_unlock_bh(&tipc_net_lock); return res; } @@ -592,7 +594,7 @@ failed: int tipc_block_bearer(const char *name) { - struct bearer *b_ptr = NULL; + struct tipc_bearer *b_ptr = NULL; struct link *l_ptr; struct link *temp_l_ptr; @@ -605,8 +607,8 @@ int tipc_block_bearer(const char *name) } info("Blocking bearer <%s>\n", name); - spin_lock_bh(&b_ptr->publ.lock); - b_ptr->publ.blocked = 1; + spin_lock_bh(&b_ptr->lock); + b_ptr->blocked = 1; list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { struct tipc_node *n_ptr = l_ptr->owner; @@ -614,7 +616,7 @@ int tipc_block_bearer(const char *name) tipc_link_reset(l_ptr); spin_unlock_bh(&n_ptr->lock); } - spin_unlock_bh(&b_ptr->publ.lock); + spin_unlock_bh(&b_ptr->lock); read_unlock_bh(&tipc_net_lock); return 0; } @@ -625,28 +627,27 @@ int tipc_block_bearer(const char *name) * Note: This routine assumes caller holds tipc_net_lock. */ -static int bearer_disable(struct bearer *b_ptr) +static void bearer_disable(struct tipc_bearer *b_ptr) { struct link *l_ptr; struct link *temp_l_ptr; - info("Disabling bearer <%s>\n", b_ptr->publ.name); - tipc_disc_stop_link_req(b_ptr->link_req); - spin_lock_bh(&b_ptr->publ.lock); - b_ptr->link_req = NULL; - b_ptr->publ.blocked = 1; - b_ptr->media->disable_bearer(&b_ptr->publ); + info("Disabling bearer <%s>\n", b_ptr->name); + spin_lock_bh(&b_ptr->lock); + b_ptr->blocked = 1; + b_ptr->media->disable_bearer(b_ptr); list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { tipc_link_delete(l_ptr); } - spin_unlock_bh(&b_ptr->publ.lock); - memset(b_ptr, 0, sizeof(struct bearer)); - return 0; + if (b_ptr->link_req) + tipc_disc_delete(b_ptr->link_req); + spin_unlock_bh(&b_ptr->lock); + memset(b_ptr, 0, sizeof(struct tipc_bearer)); } int tipc_disable_bearer(const char *name) { - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; int res; write_lock_bh(&tipc_net_lock); @@ -654,8 +655,10 @@ int tipc_disable_bearer(const char *name) if (b_ptr == NULL) { warn("Attempt to disable unknown bearer <%s>\n", name); res = -EINVAL; - } else - res = bearer_disable(b_ptr); + } else { + bearer_disable(b_ptr); + res = 0; + } write_unlock_bh(&tipc_net_lock); return res; } diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index a850b389663..31d6172b20f 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -2,7 +2,7 @@ * net/tipc/bearer.h: Include file for TIPC bearer code * * Copyright (c) 1996-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,12 +37,31 @@ #ifndef _TIPC_BEARER_H #define _TIPC_BEARER_H -#include "core.h" #include "bcast.h" #define MAX_BEARERS 8 #define MAX_MEDIA 4 +/* + * Identifiers of supported TIPC media types + */ +#define TIPC_MEDIA_TYPE_ETH 1 + +/* + * Destination address structure used by TIPC bearers when sending messages + * + * IMPORTANT: The fields of this structure MUST be stored using the specified + * byte order indicated below, as the structure is exchanged between nodes + * as part of a link setup process. + */ +struct tipc_media_addr { + __be32 type; /* bearer type (network byte order) */ + union { + __u8 eth_addr[6]; /* 48 bit Ethernet addr (byte array) */ + } dev_addr; +}; + +struct tipc_bearer; /** * struct media - TIPC media information available to internal users @@ -51,11 +70,10 @@ * @disable_bearer: routine which disables a bearer * @addr2str: routine which converts bearer's address to string form * @bcast_addr: media address used in broadcasting - * @bcast: non-zero if media supports broadcasting [currently mandatory] * @priority: default link (and bearer) priority * @tolerance: default time (in ms) before declaring link failure * @window: default window (in packets) before declaring link congestion - * @type_id: TIPC media identifier [defined in tipc_bearer.h] + * @type_id: TIPC media identifier * @name: media name */ @@ -68,7 +86,6 @@ struct media { char *(*addr2str)(struct tipc_media_addr *a, char *str_buf, int str_size); struct tipc_media_addr bcast_addr; - int bcast; u32 priority; u32 tolerance; u32 window; @@ -77,11 +94,15 @@ struct media { }; /** - * struct bearer - TIPC bearer information available to internal users - * @publ: bearer information available to privileged users + * struct tipc_bearer - TIPC bearer structure + * @usr_handle: pointer to additional media-specific information about bearer + * @mtu: max packet size bearer can support + * @blocked: non-zero if bearer is blocked + * @lock: spinlock for controlling access to bearer + * @addr: media-specific address associated with bearer + * @name: bearer name (format = media:interface) * @media: ptr to media structure associated with bearer * @priority: default link priority for bearer - * @detect_scope: network address mask used during automatic link creation * @identity: array index of this bearer within TIPC bearer array * @link_req: ptr to (optional) structure making periodic link setup requests * @links: list of non-congested links associated with bearer @@ -90,13 +111,20 @@ struct media { * @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 + * + * Note: media-specific code is responsible for initialization of the fields + * indicated below when a bearer is enabled; TIPC's generic bearer code takes + * care of initializing all other fields. */ - -struct bearer { - struct tipc_bearer publ; +struct tipc_bearer { + void *usr_handle; /* initalized by media */ + u32 mtu; /* initalized by media */ + int blocked; /* initalized by media */ + struct tipc_media_addr addr; /* initalized by media */ + char name[TIPC_MAX_BEARER_NAME]; + spinlock_t lock; struct media *media; u32 priority; - u32 detect_scope; u32 identity; struct link_req *link_req; struct list_head links; @@ -114,21 +142,48 @@ struct bearer_name { struct link; -extern struct bearer tipc_bearers[]; +extern struct tipc_bearer tipc_bearers[]; + +/* + * TIPC routines available to supported media types + */ +int tipc_register_media(u32 media_type, + char *media_name, int (*enable)(struct tipc_bearer *), + void (*disable)(struct tipc_bearer *), + int (*send_msg)(struct sk_buff *, + struct tipc_bearer *, struct tipc_media_addr *), + char *(*addr2str)(struct tipc_media_addr *a, + char *str_buf, int str_size), + struct tipc_media_addr *bcast_addr, const u32 bearer_priority, + const u32 link_tolerance, /* [ms] */ + const u32 send_window_limit); + +void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); + +int tipc_block_bearer(const char *name); +void tipc_continue(struct tipc_bearer *tb_ptr); + +int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); +int tipc_disable_bearer(const char *name); + +/* + * Routines made available to TIPC by supported media types + */ +int tipc_eth_media_start(void); +void tipc_eth_media_stop(void); void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); struct sk_buff *tipc_media_get_names(void); struct sk_buff *tipc_bearer_get_names(void); -void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest); -void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest); -void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); -struct bearer *tipc_bearer_find_interface(const char *if_name); -int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); -int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr); -int tipc_bearer_init(void); +void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest); +void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest); +void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct link *l_ptr); +struct tipc_bearer *tipc_bearer_find_interface(const char *if_name); +int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, struct link *l_ptr); +int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct link *l_ptr); void tipc_bearer_stop(void); -void tipc_bearer_lock_push(struct bearer *b_ptr); +void tipc_bearer_lock_push(struct tipc_bearer *b_ptr); /** @@ -149,10 +204,11 @@ void tipc_bearer_lock_push(struct bearer *b_ptr); * and let TIPC's link code deal with the undelivered message. */ -static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf, +static inline int tipc_bearer_send(struct tipc_bearer *b_ptr, + struct sk_buff *buf, struct tipc_media_addr *dest) { - return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest); + return !b_ptr->media->send_msg(buf, b_ptr, dest); } #endif /* _TIPC_BEARER_H */ diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c deleted file mode 100644 index 7fea14b98b9..00000000000 --- a/net/tipc/cluster.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * net/tipc/cluster.c: TIPC cluster management routines - * - * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "core.h" -#include "cluster.h" -#include "addr.h" -#include "node_subscr.h" -#include "link.h" -#include "node.h" -#include "net.h" -#include "msg.h" -#include "bearer.h" - -static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, - u32 lower, u32 upper); -static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest); - -struct tipc_node **tipc_local_nodes = NULL; -struct tipc_node_map tipc_cltr_bcast_nodes = {0,{0,}}; -u32 tipc_highest_allowed_slave = 0; - -struct cluster *tipc_cltr_create(u32 addr) -{ - struct _zone *z_ptr; - struct cluster *c_ptr; - int max_nodes; - - c_ptr = kzalloc(sizeof(*c_ptr), GFP_ATOMIC); - if (c_ptr == NULL) { - warn("Cluster creation failure, no memory\n"); - return NULL; - } - - c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); - if (in_own_cluster(addr)) - max_nodes = LOWEST_SLAVE + tipc_max_slaves; - else - max_nodes = tipc_max_nodes + 1; - - c_ptr->nodes = kcalloc(max_nodes + 1, sizeof(void*), GFP_ATOMIC); - if (c_ptr->nodes == NULL) { - warn("Cluster creation failure, no memory for node area\n"); - kfree(c_ptr); - return NULL; - } - - if (in_own_cluster(addr)) - tipc_local_nodes = c_ptr->nodes; - c_ptr->highest_slave = LOWEST_SLAVE - 1; - c_ptr->highest_node = 0; - - z_ptr = tipc_zone_find(tipc_zone(addr)); - if (!z_ptr) { - z_ptr = tipc_zone_create(addr); - } - if (!z_ptr) { - kfree(c_ptr->nodes); - kfree(c_ptr); - return NULL; - } - - tipc_zone_attach_cluster(z_ptr, c_ptr); - c_ptr->owner = z_ptr; - return c_ptr; -} - -void tipc_cltr_delete(struct cluster *c_ptr) -{ - u32 n_num; - - if (!c_ptr) - return; - for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) { - tipc_node_delete(c_ptr->nodes[n_num]); - } - for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) { - tipc_node_delete(c_ptr->nodes[n_num]); - } - kfree(c_ptr->nodes); - kfree(c_ptr); -} - - -void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr) -{ - u32 n_num = tipc_node(n_ptr->addr); - u32 max_n_num = tipc_max_nodes; - - if (in_own_cluster(n_ptr->addr)) - max_n_num = tipc_highest_allowed_slave; - assert(n_num > 0); - assert(n_num <= max_n_num); - assert(c_ptr->nodes[n_num] == NULL); - c_ptr->nodes[n_num] = n_ptr; - if (n_num > c_ptr->highest_node) - c_ptr->highest_node = n_num; -} - -/** - * tipc_cltr_select_router - select router to a cluster - * - * Uses deterministic and fair algorithm. - */ - -u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref) -{ - u32 n_num; - u32 ulim = c_ptr->highest_node; - u32 mask; - u32 tstart; - - assert(!in_own_cluster(c_ptr->addr)); - if (!ulim) - return 0; - - /* Start entry must be random */ - mask = tipc_max_nodes; - while (mask > ulim) - mask >>= 1; - tstart = ref & mask; - n_num = tstart; - - /* Lookup upwards with wrap-around */ - do { - if (tipc_node_is_up(c_ptr->nodes[n_num])) - break; - } while (++n_num <= ulim); - if (n_num > ulim) { - n_num = 1; - do { - if (tipc_node_is_up(c_ptr->nodes[n_num])) - break; - } while (++n_num < tstart); - if (n_num == tstart) - return 0; - } - assert(n_num <= ulim); - return tipc_node_select_router(c_ptr->nodes[n_num], ref); -} - -/** - * tipc_cltr_select_node - select destination node within a remote cluster - * - * Uses deterministic and fair algorithm. - */ - -struct tipc_node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector) -{ - u32 n_num; - u32 mask = tipc_max_nodes; - u32 start_entry; - - assert(!in_own_cluster(c_ptr->addr)); - if (!c_ptr->highest_node) - return NULL; - - /* Start entry must be random */ - while (mask > c_ptr->highest_node) { - mask >>= 1; - } - start_entry = (selector & mask) ? selector & mask : 1u; - assert(start_entry <= c_ptr->highest_node); - - /* Lookup upwards with wrap-around */ - for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) { - if (tipc_node_has_active_links(c_ptr->nodes[n_num])) - return c_ptr->nodes[n_num]; - } - for (n_num = 1; n_num < start_entry; n_num++) { - if (tipc_node_has_active_links(c_ptr->nodes[n_num])) - return c_ptr->nodes[n_num]; - } - return NULL; -} - -/* - * Routing table management: See description in node.c - */ - -static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest) -{ - u32 size = INT_H_SIZE + data_size; - struct sk_buff *buf = tipc_buf_acquire(size); - struct tipc_msg *msg; - - if (buf) { - msg = buf_msg(buf); - memset((char *)msg, 0, size); - tipc_msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest); - } - return buf; -} - -void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, - u32 lower, u32 upper) -{ - struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr); - struct tipc_msg *msg; - - if (buf) { - msg = buf_msg(buf); - msg_set_remote_node(msg, dest); - msg_set_type(msg, ROUTE_ADDITION); - tipc_cltr_multicast(c_ptr, buf, lower, upper); - } else { - warn("Memory squeeze: broadcast of new route failed\n"); - } -} - -void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, - u32 lower, u32 upper) -{ - struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr); - struct tipc_msg *msg; - - if (buf) { - msg = buf_msg(buf); - msg_set_remote_node(msg, dest); - msg_set_type(msg, ROUTE_REMOVAL); - tipc_cltr_multicast(c_ptr, buf, lower, upper); - } else { - warn("Memory squeeze: broadcast of lost route failed\n"); - } -} - -void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest) -{ - struct sk_buff *buf; - struct tipc_msg *msg; - u32 highest = c_ptr->highest_slave; - u32 n_num; - int send = 0; - - assert(!is_slave(dest)); - assert(in_own_cluster(dest)); - assert(in_own_cluster(c_ptr->addr)); - if (highest <= LOWEST_SLAVE) - return; - buf = tipc_cltr_prepare_routing_msg(highest - LOWEST_SLAVE + 1, - c_ptr->addr); - if (buf) { - msg = buf_msg(buf); - msg_set_remote_node(msg, c_ptr->addr); - msg_set_type(msg, SLAVE_ROUTING_TABLE); - for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) { - if (c_ptr->nodes[n_num] && - tipc_node_has_active_links(c_ptr->nodes[n_num])) { - send = 1; - msg_set_dataoctet(msg, n_num); - } - } - if (send) - tipc_link_send(buf, dest, dest); - else - buf_discard(buf); - } else { - warn("Memory squeeze: broadcast of lost route failed\n"); - } -} - -void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest) -{ - struct sk_buff *buf; - struct tipc_msg *msg; - u32 highest = c_ptr->highest_node; - u32 n_num; - int send = 0; - - if (in_own_cluster(c_ptr->addr)) - return; - assert(!is_slave(dest)); - assert(in_own_cluster(dest)); - highest = c_ptr->highest_node; - buf = tipc_cltr_prepare_routing_msg(highest + 1, c_ptr->addr); - if (buf) { - msg = buf_msg(buf); - msg_set_remote_node(msg, c_ptr->addr); - msg_set_type(msg, EXT_ROUTING_TABLE); - for (n_num = 1; n_num <= highest; n_num++) { - if (c_ptr->nodes[n_num] && - tipc_node_has_active_links(c_ptr->nodes[n_num])) { - send = 1; - msg_set_dataoctet(msg, n_num); - } - } - if (send) - tipc_link_send(buf, dest, dest); - else - buf_discard(buf); - } else { - warn("Memory squeeze: broadcast of external route failed\n"); - } -} - -void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest) -{ - struct sk_buff *buf; - struct tipc_msg *msg; - u32 highest = c_ptr->highest_node; - u32 n_num; - int send = 0; - - assert(is_slave(dest)); - assert(in_own_cluster(c_ptr->addr)); - buf = tipc_cltr_prepare_routing_msg(highest, c_ptr->addr); - if (buf) { - msg = buf_msg(buf); - msg_set_remote_node(msg, c_ptr->addr); - msg_set_type(msg, LOCAL_ROUTING_TABLE); - for (n_num = 1; n_num <= highest; n_num++) { - if (c_ptr->nodes[n_num] && - tipc_node_has_active_links(c_ptr->nodes[n_num])) { - send = 1; - msg_set_dataoctet(msg, n_num); - } - } - if (send) - tipc_link_send(buf, dest, dest); - else - buf_discard(buf); - } else { - warn("Memory squeeze: broadcast of local route failed\n"); - } -} - -void tipc_cltr_recv_routing_table(struct sk_buff *buf) -{ - struct tipc_msg *msg = buf_msg(buf); - struct cluster *c_ptr; - struct tipc_node *n_ptr; - unchar *node_table; - u32 table_size; - u32 router; - u32 rem_node = msg_remote_node(msg); - u32 z_num; - u32 c_num; - u32 n_num; - - c_ptr = tipc_cltr_find(rem_node); - if (!c_ptr) { - c_ptr = tipc_cltr_create(rem_node); - if (!c_ptr) { - buf_discard(buf); - return; - } - } - - node_table = buf->data + msg_hdr_sz(msg); - table_size = msg_size(msg) - msg_hdr_sz(msg); - router = msg_prevnode(msg); - z_num = tipc_zone(rem_node); - c_num = tipc_cluster(rem_node); - - switch (msg_type(msg)) { - case LOCAL_ROUTING_TABLE: - assert(is_slave(tipc_own_addr)); - case EXT_ROUTING_TABLE: - for (n_num = 1; n_num < table_size; n_num++) { - if (node_table[n_num]) { - u32 addr = tipc_addr(z_num, c_num, n_num); - n_ptr = c_ptr->nodes[n_num]; - if (!n_ptr) { - n_ptr = tipc_node_create(addr); - } - if (n_ptr) - tipc_node_add_router(n_ptr, router); - } - } - break; - case SLAVE_ROUTING_TABLE: - assert(!is_slave(tipc_own_addr)); - assert(in_own_cluster(c_ptr->addr)); - for (n_num = 1; n_num < table_size; n_num++) { - if (node_table[n_num]) { - u32 slave_num = n_num + LOWEST_SLAVE; - u32 addr = tipc_addr(z_num, c_num, slave_num); - n_ptr = c_ptr->nodes[slave_num]; - if (!n_ptr) { - n_ptr = tipc_node_create(addr); - } - if (n_ptr) - tipc_node_add_router(n_ptr, router); - } - } - break; - case ROUTE_ADDITION: - if (!is_slave(tipc_own_addr)) { - assert(!in_own_cluster(c_ptr->addr) || - is_slave(rem_node)); - } else { - assert(in_own_cluster(c_ptr->addr) && - !is_slave(rem_node)); - } - n_ptr = c_ptr->nodes[tipc_node(rem_node)]; - if (!n_ptr) - n_ptr = tipc_node_create(rem_node); - if (n_ptr) - tipc_node_add_router(n_ptr, router); - break; - case ROUTE_REMOVAL: - if (!is_slave(tipc_own_addr)) { - assert(!in_own_cluster(c_ptr->addr) || - is_slave(rem_node)); - } else { - assert(in_own_cluster(c_ptr->addr) && - !is_slave(rem_node)); - } - n_ptr = c_ptr->nodes[tipc_node(rem_node)]; - if (n_ptr) - tipc_node_remove_router(n_ptr, router); - break; - default: - assert(!"Illegal routing manager message received\n"); - } - buf_discard(buf); -} - -void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router) -{ - u32 start_entry; - u32 tstop; - u32 n_num; - - if (is_slave(router)) - return; /* Slave nodes can not be routers */ - - if (in_own_cluster(c_ptr->addr)) { - start_entry = LOWEST_SLAVE; - tstop = c_ptr->highest_slave; - } else { - start_entry = 1; - tstop = c_ptr->highest_node; - } - - for (n_num = start_entry; n_num <= tstop; n_num++) { - if (c_ptr->nodes[n_num]) { - tipc_node_remove_router(c_ptr->nodes[n_num], router); - } - } -} - -/** - * tipc_cltr_multicast - multicast message to local nodes - */ - -static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, - u32 lower, u32 upper) -{ - struct sk_buff *buf_copy; - struct tipc_node *n_ptr; - u32 n_num; - u32 tstop; - - assert(lower <= upper); - assert(((lower >= 1) && (lower <= tipc_max_nodes)) || - ((lower >= LOWEST_SLAVE) && (lower <= tipc_highest_allowed_slave))); - assert(((upper >= 1) && (upper <= tipc_max_nodes)) || - ((upper >= LOWEST_SLAVE) && (upper <= tipc_highest_allowed_slave))); - assert(in_own_cluster(c_ptr->addr)); - - tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node; - if (tstop > upper) - tstop = upper; - for (n_num = lower; n_num <= tstop; n_num++) { - n_ptr = c_ptr->nodes[n_num]; - if (n_ptr && tipc_node_has_active_links(n_ptr)) { - buf_copy = skb_copy(buf, GFP_ATOMIC); - if (buf_copy == NULL) - break; - msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); - tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr); - } - } - buf_discard(buf); -} - -/** - * tipc_cltr_broadcast - broadcast message to all nodes within cluster - */ - -void tipc_cltr_broadcast(struct sk_buff *buf) -{ - struct sk_buff *buf_copy; - struct cluster *c_ptr; - struct tipc_node *n_ptr; - u32 n_num; - u32 tstart; - u32 tstop; - u32 node_type; - - if (tipc_mode == TIPC_NET_MODE) { - c_ptr = tipc_cltr_find(tipc_own_addr); - assert(in_own_cluster(c_ptr->addr)); /* For now */ - - /* Send to standard nodes, then repeat loop sending to slaves */ - tstart = 1; - tstop = c_ptr->highest_node; - for (node_type = 1; node_type <= 2; node_type++) { - for (n_num = tstart; n_num <= tstop; n_num++) { - n_ptr = c_ptr->nodes[n_num]; - if (n_ptr && tipc_node_has_active_links(n_ptr)) { - buf_copy = skb_copy(buf, GFP_ATOMIC); - if (buf_copy == NULL) - goto exit; - msg_set_destnode(buf_msg(buf_copy), - n_ptr->addr); - tipc_link_send(buf_copy, n_ptr->addr, - n_ptr->addr); - } - } - tstart = LOWEST_SLAVE; - tstop = c_ptr->highest_slave; - } - } -exit: - buf_discard(buf); -} - -int tipc_cltr_init(void) -{ - tipc_highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves; - return tipc_cltr_create(tipc_own_addr) ? 0 : -ENOMEM; -} - diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h deleted file mode 100644 index 32636d98c9c..00000000000 --- a/net/tipc/cluster.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * net/tipc/cluster.h: Include file for TIPC cluster management routines - * - * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _TIPC_CLUSTER_H -#define _TIPC_CLUSTER_H - -#include "addr.h" -#include "zone.h" - -#define LOWEST_SLAVE 2048u - -/** - * struct cluster - TIPC cluster structure - * @addr: network address of cluster - * @owner: pointer to zone that cluster belongs to - * @nodes: array of pointers to all nodes within cluster - * @highest_node: id of highest numbered node within cluster - * @highest_slave: (used for secondary node support) - */ - -struct cluster { - u32 addr; - struct _zone *owner; - struct tipc_node **nodes; - u32 highest_node; - u32 highest_slave; -}; - - -extern struct tipc_node **tipc_local_nodes; -extern u32 tipc_highest_allowed_slave; -extern struct tipc_node_map tipc_cltr_bcast_nodes; - -void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router); -void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest); -struct tipc_node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector); -u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref); -void tipc_cltr_recv_routing_table(struct sk_buff *buf); -struct cluster *tipc_cltr_create(u32 addr); -void tipc_cltr_delete(struct cluster *c_ptr); -void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr); -void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest); -void tipc_cltr_broadcast(struct sk_buff *buf); -int tipc_cltr_init(void); - -void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); -void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest); -void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); - -static inline struct cluster *tipc_cltr_find(u32 addr) -{ - struct _zone *z_ptr = tipc_zone_find(addr); - - if (z_ptr) - return z_ptr->clusters[1]; - return NULL; -} - -#endif diff --git a/net/tipc/config.c b/net/tipc/config.c index 50a6133a366..b25a396b7e1 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -2,7 +2,7 @@ * net/tipc/config.c: TIPC configuration management code * * Copyright (c) 2002-2006, Ericsson AB - * Copyright (c) 2004-2007, Wind River Systems + * Copyright (c) 2004-2007, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,30 +35,11 @@ */ #include "core.h" -#include "dbg.h" -#include "bearer.h" #include "port.h" -#include "link.h" -#include "zone.h" -#include "addr.h" #include "name_table.h" -#include "node.h" #include "config.h" -#include "discover.h" -struct subscr_data { - char usr_handle[8]; - u32 domain; - u32 port_ref; - struct list_head subd_list; -}; - -struct manager { - u32 user_ref; - u32 port_ref; -}; - -static struct manager mng = { 0}; +static u32 config_port_ref; static DEFINE_SPINLOCK(config_lock); @@ -83,10 +64,8 @@ int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf); int new_tlv_space = TLV_SPACE(tlv_data_size); - if (skb_tailroom(buf) < new_tlv_space) { - dbg("tipc_cfg_append_tlv unable to append TLV\n"); + if (skb_tailroom(buf) < new_tlv_space) return 0; - } skb_put(buf, new_tlv_space); tlv->tlv_type = htons(tlv_type); tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); @@ -169,7 +148,7 @@ static struct sk_buff *cfg_enable_bearer(void) args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); if (tipc_enable_bearer(args->name, - ntohl(args->detect_scope), + ntohl(args->disc_domain), ntohl(args->priority))) return tipc_cfg_reply_error_string("unable to enable bearer"); @@ -281,70 +260,6 @@ static struct sk_buff *cfg_set_max_ports(void) return tipc_cfg_reply_none(); } -static struct sk_buff *cfg_set_max_zones(void) -{ - u32 value; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (value == tipc_max_zones) - return tipc_cfg_reply_none(); - if (value != delimit(value, 1, 255)) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max zones must be 1-255)"); - if (tipc_mode == TIPC_NET_MODE) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change max zones once TIPC has joined a network)"); - tipc_max_zones = value; - return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_max_clusters(void) -{ - u32 value; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (value != delimit(value, 1, 1)) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max clusters fixed at 1)"); - return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_max_nodes(void) -{ - u32 value; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (value == tipc_max_nodes) - return tipc_cfg_reply_none(); - if (value != delimit(value, 8, 2047)) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max nodes must be 8-2047)"); - if (tipc_mode == TIPC_NET_MODE) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change max nodes once TIPC has joined a network)"); - tipc_max_nodes = value; - return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_max_slaves(void) -{ - u32 value; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (value != 0) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (max secondary nodes fixed at 0)"); - return tipc_cfg_reply_none(); -} - static struct sk_buff *cfg_set_netid(void) { u32 value; @@ -388,8 +303,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area } else if (!tipc_remote_management) { rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); goto exit; - } - else if (cmd >= 0x4000) { + } else if (cmd >= 0x4000) { u32 domain = 0; if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || @@ -464,18 +378,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area case TIPC_CMD_SET_MAX_SUBSCR: rep_tlv_buf = cfg_set_max_subscriptions(); break; - case TIPC_CMD_SET_MAX_ZONES: - rep_tlv_buf = cfg_set_max_zones(); - break; - case TIPC_CMD_SET_MAX_CLUSTERS: - rep_tlv_buf = cfg_set_max_clusters(); - break; - case TIPC_CMD_SET_MAX_NODES: - rep_tlv_buf = cfg_set_max_nodes(); - break; - case TIPC_CMD_SET_MAX_SLAVES: - rep_tlv_buf = cfg_set_max_slaves(); - break; case TIPC_CMD_SET_NETID: rep_tlv_buf = cfg_set_netid(); break; @@ -491,18 +393,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area case TIPC_CMD_GET_MAX_SUBSCR: rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); break; - case TIPC_CMD_GET_MAX_ZONES: - rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_zones); - break; - case TIPC_CMD_GET_MAX_CLUSTERS: - rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_clusters); - break; - case TIPC_CMD_GET_MAX_NODES: - rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes); - break; - case TIPC_CMD_GET_MAX_SLAVES: - rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_slaves); - break; case TIPC_CMD_GET_NETID: rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); break; @@ -510,6 +400,17 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); break; + case TIPC_CMD_SET_MAX_ZONES: + case TIPC_CMD_GET_MAX_ZONES: + case TIPC_CMD_SET_MAX_SLAVES: + case TIPC_CMD_GET_MAX_SLAVES: + case TIPC_CMD_SET_MAX_CLUSTERS: + case TIPC_CMD_GET_MAX_CLUSTERS: + case TIPC_CMD_SET_MAX_NODES: + case TIPC_CMD_GET_MAX_NODES: + rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (obsolete command)"); + break; default: rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (unknown command)"); @@ -572,20 +473,16 @@ int tipc_cfg_init(void) struct tipc_name_seq seq; int res; - res = tipc_attach(&mng.user_ref, NULL, NULL); - if (res) - goto failed; - - res = tipc_createport(mng.user_ref, NULL, TIPC_CRITICAL_IMPORTANCE, + res = tipc_createport(NULL, TIPC_CRITICAL_IMPORTANCE, NULL, NULL, NULL, NULL, cfg_named_msg_event, NULL, - NULL, &mng.port_ref); + NULL, &config_port_ref); if (res) goto failed; seq.type = TIPC_CFG_SRV; seq.lower = seq.upper = tipc_own_addr; - res = tipc_nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); + res = tipc_nametbl_publish_rsv(config_port_ref, TIPC_ZONE_SCOPE, &seq); if (res) goto failed; @@ -593,15 +490,13 @@ int tipc_cfg_init(void) failed: err("Unable to create configuration service\n"); - tipc_detach(mng.user_ref); - mng.user_ref = 0; return res; } void tipc_cfg_stop(void) { - if (mng.user_ref) { - tipc_detach(mng.user_ref); - mng.user_ref = 0; + if (config_port_ref) { + tipc_deleteport(config_port_ref); + config_port_ref = 0; } } diff --git a/net/tipc/config.h b/net/tipc/config.h index 481e12ece71..443159a166f 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h @@ -39,7 +39,6 @@ /* ---------------------------------------------------------------------- */ -#include "core.h" #include "link.h" struct sk_buff *tipc_cfg_reply_alloc(int payload_size); diff --git a/net/tipc/core.c b/net/tipc/core.c index e2a09eb8efd..943b6af8426 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -2,7 +2,7 @@ * net/tipc/core.c: TIPC module code * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005-2006, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,37 +34,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/random.h> - #include "core.h" -#include "dbg.h" #include "ref.h" -#include "net.h" -#include "user_reg.h" #include "name_table.h" #include "subscr.h" #include "config.h" -#ifndef CONFIG_TIPC_ZONES -#define CONFIG_TIPC_ZONES 3 -#endif - -#ifndef CONFIG_TIPC_CLUSTERS -#define CONFIG_TIPC_CLUSTERS 1 -#endif - -#ifndef CONFIG_TIPC_NODES -#define CONFIG_TIPC_NODES 255 -#endif - -#ifndef CONFIG_TIPC_SLAVE_NODES -#define CONFIG_TIPC_SLAVE_NODES 0 -#endif - #ifndef CONFIG_TIPC_PORTS #define CONFIG_TIPC_PORTS 8191 #endif @@ -77,7 +53,6 @@ int tipc_mode = TIPC_NOT_RUNNING; int tipc_random; -atomic_t tipc_user_count = ATOMIC_INIT(0); const char tipc_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."; @@ -85,10 +60,6 @@ const char tipc_alphabet[] = /* configurable TIPC parameters */ u32 tipc_own_addr; -int tipc_max_zones; -int tipc_max_clusters; -int tipc_max_nodes; -int tipc_max_slaves; int tipc_max_ports; int tipc_max_subscriptions; int tipc_max_publications; @@ -138,10 +109,11 @@ int tipc_core_start_net(unsigned long addr) { int res; - if ((res = tipc_net_start(addr)) || - (res = tipc_eth_media_start())) { + res = tipc_net_start(addr); + if (!res) + res = tipc_eth_media_start(); + if (res) tipc_core_stop_net(); - } return res; } @@ -160,7 +132,6 @@ static void tipc_core_stop(void) tipc_handler_stop(); tipc_cfg_stop(); tipc_subscr_stop(); - tipc_reg_stop(); tipc_nametbl_stop(); tipc_ref_table_stop(); tipc_socket_stop(); @@ -181,16 +152,22 @@ static int tipc_core_start(void) get_random_bytes(&tipc_random, sizeof(tipc_random)); tipc_mode = TIPC_NODE_MODE; - if ((res = tipc_handler_start()) || - (res = tipc_ref_table_init(tipc_max_ports, tipc_random)) || - (res = tipc_reg_start()) || - (res = tipc_nametbl_init()) || - (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || - (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) || - (res = tipc_netlink_start()) || - (res = tipc_socket_init())) { + res = tipc_handler_start(); + if (!res) + res = tipc_ref_table_init(tipc_max_ports, tipc_random); + if (!res) + res = tipc_nametbl_init(); + if (!res) + res = tipc_k_signal((Handler)tipc_subscr_start, 0); + if (!res) + res = tipc_k_signal((Handler)tipc_cfg_init, 0); + if (!res) + res = tipc_netlink_start(); + if (!res) + res = tipc_socket_init(); + if (res) tipc_core_stop(); - } + return res; } @@ -202,21 +179,17 @@ static int __init tipc_init(void) if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) warn("Unable to create log buffer\n"); - info("Activated (version " TIPC_MOD_VER - " compiled " __DATE__ " " __TIME__ ")\n"); + info("Activated (version " TIPC_MOD_VER ")\n"); tipc_own_addr = 0; tipc_remote_management = 1; tipc_max_publications = 10000; tipc_max_subscriptions = 2000; tipc_max_ports = CONFIG_TIPC_PORTS; - tipc_max_zones = CONFIG_TIPC_ZONES; - tipc_max_clusters = CONFIG_TIPC_CLUSTERS; - tipc_max_nodes = CONFIG_TIPC_NODES; - tipc_max_slaves = CONFIG_TIPC_SLAVE_NODES; tipc_net_id = 4711; - if ((res = tipc_core_start())) + res = tipc_core_start(); + if (res) err("Unable to start in single node mode\n"); else info("Started in single node mode\n"); @@ -236,43 +209,3 @@ module_exit(tipc_exit); MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(TIPC_MOD_VER); - -/* Native TIPC API for kernel-space applications (see tipc.h) */ - -EXPORT_SYMBOL(tipc_attach); -EXPORT_SYMBOL(tipc_detach); -EXPORT_SYMBOL(tipc_createport); -EXPORT_SYMBOL(tipc_deleteport); -EXPORT_SYMBOL(tipc_ownidentity); -EXPORT_SYMBOL(tipc_portimportance); -EXPORT_SYMBOL(tipc_set_portimportance); -EXPORT_SYMBOL(tipc_portunreliable); -EXPORT_SYMBOL(tipc_set_portunreliable); -EXPORT_SYMBOL(tipc_portunreturnable); -EXPORT_SYMBOL(tipc_set_portunreturnable); -EXPORT_SYMBOL(tipc_publish); -EXPORT_SYMBOL(tipc_withdraw); -EXPORT_SYMBOL(tipc_connect2port); -EXPORT_SYMBOL(tipc_disconnect); -EXPORT_SYMBOL(tipc_shutdown); -EXPORT_SYMBOL(tipc_send); -EXPORT_SYMBOL(tipc_send2name); -EXPORT_SYMBOL(tipc_send2port); -EXPORT_SYMBOL(tipc_multicast); - -/* TIPC API for external bearers (see tipc_bearer.h) */ - -EXPORT_SYMBOL(tipc_block_bearer); -EXPORT_SYMBOL(tipc_continue); -EXPORT_SYMBOL(tipc_disable_bearer); -EXPORT_SYMBOL(tipc_enable_bearer); -EXPORT_SYMBOL(tipc_recv_msg); -EXPORT_SYMBOL(tipc_register_media); - -/* TIPC API for external APIs (see tipc_port.h) */ - -EXPORT_SYMBOL(tipc_createport_raw); -EXPORT_SYMBOL(tipc_reject_msg); -EXPORT_SYMBOL(tipc_send_buf_fast); -EXPORT_SYMBOL(tipc_acknowledge); - diff --git a/net/tipc/core.h b/net/tipc/core.h index e19389e5722..436dda1159d 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -2,7 +2,7 @@ * net/tipc/core.h: Include file for TIPC global declarations * * Copyright (c) 2005-2006, Ericsson AB - * Copyright (c) 2005-2007, Wind River Systems + * Copyright (c) 2005-2007, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,10 +39,6 @@ #include <linux/tipc.h> #include <linux/tipc_config.h> -#include <net/tipc/tipc_msg.h> -#include <net/tipc/tipc_port.h> -#include <net/tipc/tipc_bearer.h> -#include <net/tipc/tipc.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -62,6 +58,9 @@ #define TIPC_MOD_VER "2.0.0" +struct tipc_msg; /* msg.h */ +struct print_buf; /* log.h */ + /* * TIPC sanity test macros */ @@ -84,6 +83,7 @@ * user-defined buffers can be configured to do the same thing. */ extern struct print_buf *const TIPC_NULL; +extern struct print_buf *const TIPC_CONS; extern struct print_buf *const TIPC_LOG; void tipc_printf(struct print_buf *, const char *fmt, ...); @@ -96,73 +96,35 @@ void tipc_printf(struct print_buf *, const char *fmt, ...); #define TIPC_OUTPUT TIPC_LOG #endif -/* - * TIPC can be configured to send system messages to TIPC_OUTPUT - * or to the system console only. - */ - -#ifdef CONFIG_TIPC_DEBUG - #define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ - KERN_ERR "TIPC: " fmt, ## arg) + KERN_ERR "TIPC: " fmt, ## arg) #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ - KERN_WARNING "TIPC: " fmt, ## arg) + KERN_WARNING "TIPC: " fmt, ## arg) #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ - KERN_NOTICE "TIPC: " fmt, ## arg) - -#else - -#define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg) -#define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg) -#define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg) + KERN_NOTICE "TIPC: " fmt, ## arg) -#endif +#ifdef CONFIG_TIPC_DEBUG /* * DBG_OUTPUT is the destination print buffer for debug messages. - * It defaults to the the null print buffer, but can be redefined - * (typically in the individual .c files being debugged) to allow - * selected debug messages to be generated where needed. */ #ifndef DBG_OUTPUT -#define DBG_OUTPUT TIPC_NULL +#define DBG_OUTPUT TIPC_LOG #endif -/* - * TIPC can be configured to send debug messages to the specified print buffer - * (typically DBG_OUTPUT) or to suppress them entirely. - */ +#define dbg(fmt, arg...) tipc_printf(DBG_OUTPUT, KERN_DEBUG fmt, ## arg); -#ifdef CONFIG_TIPC_DEBUG - -#define dbg(fmt, arg...) \ - do { \ - if (DBG_OUTPUT != TIPC_NULL) \ - tipc_printf(DBG_OUTPUT, fmt, ## arg); \ - } while (0) -#define msg_dbg(msg, txt) \ - do { \ - if (DBG_OUTPUT != TIPC_NULL) \ - tipc_msg_dbg(DBG_OUTPUT, msg, txt); \ - } while (0) -#define dump(fmt, arg...) \ - do { \ - if (DBG_OUTPUT != TIPC_NULL) \ - tipc_dump_dbg(DBG_OUTPUT, fmt, ##arg); \ - } while (0) +#define msg_dbg(msg, txt) tipc_msg_dbg(DBG_OUTPUT, msg, txt); void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *); -void tipc_dump_dbg(struct print_buf *, const char *fmt, ...); #else #define dbg(fmt, arg...) do {} while (0) #define msg_dbg(msg, txt) do {} while (0) -#define dump(fmt, arg...) do {} while (0) -#define tipc_msg_dbg(...) do {} while (0) -#define tipc_dump_dbg(...) do {} while (0) +#define tipc_msg_dbg(buf, msg, txt) do {} while (0) #endif @@ -174,14 +136,17 @@ void tipc_dump_dbg(struct print_buf *, const char *fmt, ...); #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ /* + * TIPC operating mode routines + */ +#define TIPC_NOT_RUNNING 0 +#define TIPC_NODE_MODE 1 +#define TIPC_NET_MODE 2 + +/* * Global configuration variables */ extern u32 tipc_own_addr; -extern int tipc_max_zones; -extern int tipc_max_clusters; -extern int tipc_max_nodes; -extern int tipc_max_slaves; extern int tipc_max_ports; extern int tipc_max_subscriptions; extern int tipc_max_publications; @@ -195,7 +160,6 @@ extern int tipc_remote_management; extern int tipc_mode; extern int tipc_random; extern const char tipc_alphabet[]; -extern atomic_t tipc_user_count; /* @@ -240,7 +204,6 @@ u32 tipc_k_signal(Handler routine, unsigned long argument); static inline void k_init_timer(struct timer_list *timer, Handler routine, unsigned long argument) { - dbg("initializing timer %p\n", timer); setup_timer(timer, routine, argument); } @@ -260,7 +223,6 @@ static inline void k_init_timer(struct timer_list *timer, Handler routine, static inline void k_start_timer(struct timer_list *timer, unsigned long msec) { - dbg("starting timer %p for %u\n", timer, msec); mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1); } @@ -277,7 +239,6 @@ static inline void k_start_timer(struct timer_list *timer, unsigned long msec) static inline void k_cancel_timer(struct timer_list *timer) { - dbg("cancelling timer %p\n", timer); del_timer_sync(timer); } @@ -295,7 +256,6 @@ static inline void k_cancel_timer(struct timer_list *timer) static inline void k_term_timer(struct timer_list *timer) { - dbg("terminating timer %p\n", timer); } diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 4a7cd3719b7..0987933155b 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -2,7 +2,7 @@ * net/tipc/discover.c * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005-2006, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,34 +35,30 @@ */ #include "core.h" -#include "dbg.h" #include "link.h" -#include "zone.h" #include "discover.h" -#include "port.h" -#include "name_table.h" #define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ -#define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ -#define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ - -/* - * TODO: Most of the inter-cluster setup stuff should be - * rewritten, and be made conformant with specification. - */ +#define TIPC_LINK_REQ_FAST 1000 /* max delay if bearer has no links */ +#define TIPC_LINK_REQ_SLOW 60000 /* max delay if bearer has links */ +#define TIPC_LINK_REQ_INACTIVE 0xffffffff /* indicates no timer in use */ /** * struct link_req - information about an ongoing link setup request * @bearer: bearer issuing requests * @dest: destination address for request messages + * @domain: network domain to which links can be established + * @num_nodes: number of nodes currently discovered (i.e. with an active link) * @buf: request message to be (repeatedly) sent * @timer: timer governing period between requests * @timer_intv: current interval between requests (in ms) */ struct link_req { - struct bearer *bearer; + struct tipc_bearer *bearer; struct tipc_media_addr dest; + u32 domain; + int num_nodes; struct sk_buff *buf; struct timer_list timer; unsigned int timer_intv; @@ -71,27 +67,24 @@ struct link_req { /** * tipc_disc_init_msg - initialize a link setup message * @type: message type (request or response) - * @req_links: number of links associated with message * @dest_domain: network domain of node(s) which should respond to message * @b_ptr: ptr to bearer issuing message */ static struct sk_buff *tipc_disc_init_msg(u32 type, - u32 req_links, u32 dest_domain, - struct bearer *b_ptr) + struct tipc_bearer *b_ptr) { - struct sk_buff *buf = tipc_buf_acquire(DSC_H_SIZE); + struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE); struct tipc_msg *msg; if (buf) { msg = buf_msg(buf); - tipc_msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain); + tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); msg_set_non_seq(msg, 1); - msg_set_req_links(msg, req_links); msg_set_dest_domain(msg, dest_domain); msg_set_bc_netid(msg, tipc_net_id); - msg_set_media_addr(msg, &b_ptr->publ.addr); + msg_set_media_addr(msg, &b_ptr->addr); } return buf; } @@ -103,7 +96,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, * @media_addr: media address advertised by duplicated node */ -static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, +static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr, struct tipc_media_addr *media_addr) { char node_addr_str[16]; @@ -115,7 +108,7 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, tipc_media_addr_printf(&pb, media_addr); tipc_printbuf_validate(&pb); warn("Duplicate %s using %s seen on <%s>\n", - node_addr_str, media_addr_str, b_ptr->publ.name); + node_addr_str, media_addr_str, b_ptr->name); } /** @@ -124,20 +117,23 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, * @b_ptr: bearer that message arrived on */ -void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr) +void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) { + struct tipc_node *n_ptr; struct link *link; - struct tipc_media_addr media_addr; + struct tipc_media_addr media_addr, *addr; + struct sk_buff *rbuf; struct tipc_msg *msg = buf_msg(buf); u32 dest = msg_dest_domain(msg); u32 orig = msg_prevnode(msg); u32 net_id = msg_bc_netid(msg); u32 type = msg_type(msg); + int link_fully_up; - msg_get_media_addr(msg,&media_addr); - msg_dbg(msg, "RECV:"); + msg_get_media_addr(msg, &media_addr); buf_discard(buf); + /* Validate discovery message from requesting node */ if (net_id != tipc_net_id) return; if (!tipc_addr_domain_valid(dest)) @@ -145,111 +141,127 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr) if (!tipc_addr_node_valid(orig)) return; if (orig == tipc_own_addr) { - if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr))) + if (memcmp(&media_addr, &b_ptr->addr, sizeof(media_addr))) disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr); return; } if (!tipc_in_scope(dest, tipc_own_addr)) return; - if (is_slave(tipc_own_addr) && is_slave(orig)) + if (!tipc_in_scope(b_ptr->link_req->domain, orig)) return; - if (is_slave(orig) && !in_own_cluster(orig)) + + /* Locate structure corresponding to requesting node */ + n_ptr = tipc_node_find(orig); + if (!n_ptr) { + n_ptr = tipc_node_create(orig); + if (!n_ptr) + return; + } + 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; - if (in_own_cluster(orig)) { - /* Always accept link here */ - struct sk_buff *rbuf; - struct tipc_media_addr *addr; - struct tipc_node *n_ptr = tipc_node_find(orig); - int link_fully_up; - - dbg(" in own cluster\n"); - if (n_ptr == NULL) { - n_ptr = tipc_node_create(orig); - if (!n_ptr) - return; - } - spin_lock_bh(&n_ptr->lock); + } - /* Don't talk to neighbor during cleanup after last session */ + link = n_ptr->links[b_ptr->identity]; - if (n_ptr->cleanup_required) { - spin_unlock_bh(&n_ptr->lock); + /* Create a link endpoint for this bearer, if necessary */ + if (!link) { + link = tipc_link_create(n_ptr, b_ptr, &media_addr); + if (!link) { + tipc_node_unlock(n_ptr); return; } + } - link = n_ptr->links[b_ptr->identity]; - if (!link) { - dbg("creating link\n"); - link = tipc_link_create(b_ptr, orig, &media_addr); - if (!link) { - spin_unlock_bh(&n_ptr->lock); - return; - } - } - addr = &link->media_addr; - if (memcmp(addr, &media_addr, sizeof(*addr))) { - if (tipc_link_is_up(link) || (!link->started)) { - disc_dupl_alert(b_ptr, orig, &media_addr); - spin_unlock_bh(&n_ptr->lock); - return; - } - warn("Resetting link <%s>, peer interface address changed\n", - link->name); - memcpy(addr, &media_addr, sizeof(*addr)); - tipc_link_reset(link); - } - link_fully_up = link_working_working(link); - spin_unlock_bh(&n_ptr->lock); - if ((type == DSC_RESP_MSG) || link_fully_up) + /* + * Ensure requesting node's media address is correct + * + * If media address doesn't match and the link is working, reject the + * request (must be from a duplicate node). + * + * If media address doesn't match and the link is not working, accept + * the new media address and reset the link to ensure it starts up + * cleanly. + */ + addr = &link->media_addr; + if (memcmp(addr, &media_addr, sizeof(*addr))) { + if (tipc_link_is_up(link) || (!link->started)) { + disc_dupl_alert(b_ptr, orig, &media_addr); + tipc_node_unlock(n_ptr); return; - rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); - if (rbuf != NULL) { - msg_dbg(buf_msg(rbuf),"SEND:"); - b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr); + } + warn("Resetting link <%s>, peer interface address changed\n", + link->name); + memcpy(addr, &media_addr, sizeof(*addr)); + tipc_link_reset(link); + } + + /* Accept discovery message & send response, if necessary */ + link_fully_up = link_working_working(link); + + if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) { + rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); + if (rbuf) { + b_ptr->media->send_msg(rbuf, b_ptr, &media_addr); buf_discard(rbuf); } } + + tipc_node_unlock(n_ptr); } /** - * tipc_disc_stop_link_req - stop sending periodic link setup requests + * disc_update - update frequency of periodic link setup requests * @req: ptr to link request structure + * + * Reinitiates discovery process if discovery object has no associated nodes + * and is either not currently searching or is searching at a slow rate */ -void tipc_disc_stop_link_req(struct link_req *req) +static void disc_update(struct link_req *req) { - if (!req) - return; + if (!req->num_nodes) { + if ((req->timer_intv == TIPC_LINK_REQ_INACTIVE) || + (req->timer_intv > TIPC_LINK_REQ_FAST)) { + req->timer_intv = TIPC_LINK_REQ_INIT; + k_start_timer(&req->timer, req->timer_intv); + } + } +} - k_cancel_timer(&req->timer); - k_term_timer(&req->timer); - buf_discard(req->buf); - kfree(req); +/** + * tipc_disc_add_dest - increment set of discovered nodes + * @req: ptr to link request structure + */ + +void tipc_disc_add_dest(struct link_req *req) +{ + req->num_nodes++; } /** - * tipc_disc_update_link_req - update frequency of periodic link setup requests + * tipc_disc_remove_dest - decrement set of discovered nodes * @req: ptr to link request structure */ -void tipc_disc_update_link_req(struct link_req *req) +void tipc_disc_remove_dest(struct link_req *req) { - if (!req) - return; + req->num_nodes--; + disc_update(req); +} - if (req->timer_intv == TIPC_LINK_REQ_SLOW) { - if (!req->bearer->nodes.count) { - req->timer_intv = TIPC_LINK_REQ_FAST; - k_start_timer(&req->timer, req->timer_intv); - } - } else if (req->timer_intv == TIPC_LINK_REQ_FAST) { - if (req->bearer->nodes.count) { - req->timer_intv = TIPC_LINK_REQ_SLOW; - k_start_timer(&req->timer, req->timer_intv); - } - } else { - /* leave timer "as is" if haven't yet reached a "normal" rate */ - } +/** + * disc_send_msg - send link setup request message + * @req: ptr to link request structure + */ + +static void disc_send_msg(struct link_req *req) +{ + if (!req->bearer->blocked) + tipc_bearer_send(req->bearer, req->buf, &req->dest); } /** @@ -261,58 +273,86 @@ void tipc_disc_update_link_req(struct link_req *req) static void disc_timeout(struct link_req *req) { - spin_lock_bh(&req->bearer->publ.lock); - - req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest); - - if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || - (req->timer_intv == TIPC_LINK_REQ_FAST)) { - /* leave timer interval "as is" if already at a "normal" rate */ - } else { - req->timer_intv *= 2; - if (req->timer_intv > TIPC_LINK_REQ_FAST) - req->timer_intv = TIPC_LINK_REQ_FAST; - if ((req->timer_intv == TIPC_LINK_REQ_FAST) && - (req->bearer->nodes.count)) - req->timer_intv = TIPC_LINK_REQ_SLOW; + int max_delay; + + spin_lock_bh(&req->bearer->lock); + + /* Stop searching if only desired node has been found */ + + if (tipc_node(req->domain) && req->num_nodes) { + req->timer_intv = TIPC_LINK_REQ_INACTIVE; + goto exit; } - k_start_timer(&req->timer, req->timer_intv); - spin_unlock_bh(&req->bearer->publ.lock); + /* + * Send discovery message, then update discovery timer + * + * Keep doubling time between requests until limit is reached; + * hold at fast polling rate if don't have any associated nodes, + * otherwise hold at slow polling rate + */ + + disc_send_msg(req); + + req->timer_intv *= 2; + if (req->num_nodes) + max_delay = TIPC_LINK_REQ_SLOW; + else + max_delay = TIPC_LINK_REQ_FAST; + if (req->timer_intv > max_delay) + req->timer_intv = max_delay; + + k_start_timer(&req->timer, req->timer_intv); +exit: + spin_unlock_bh(&req->bearer->lock); } /** - * tipc_disc_init_link_req - start sending periodic link setup requests + * tipc_disc_create - create object to send periodic link setup requests * @b_ptr: ptr to bearer issuing requests * @dest: destination address for request messages - * @dest_domain: network domain of node(s) which should respond to message - * @req_links: max number of desired links + * @dest_domain: network domain to which links can be established * - * Returns pointer to link request structure, or NULL if unable to create. + * Returns 0 if successful, otherwise -errno. */ -struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain, - u32 req_links) +int tipc_disc_create(struct tipc_bearer *b_ptr, + struct tipc_media_addr *dest, u32 dest_domain) { struct link_req *req; req = kmalloc(sizeof(*req), GFP_ATOMIC); if (!req) - return NULL; + return -ENOMEM; - req->buf = tipc_disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); + req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); if (!req->buf) { kfree(req); - return NULL; + return -ENOMSG; } memcpy(&req->dest, dest, sizeof(*dest)); req->bearer = b_ptr; + req->domain = dest_domain; + req->num_nodes = 0; req->timer_intv = TIPC_LINK_REQ_INIT; k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); k_start_timer(&req->timer, req->timer_intv); - return req; + b_ptr->link_req = req; + disc_send_msg(req); + return 0; +} + +/** + * tipc_disc_delete - destroy object sending periodic link setup requests + * @req: ptr to link request structure + */ + +void tipc_disc_delete(struct link_req *req) +{ + k_cancel_timer(&req->timer); + k_term_timer(&req->timer); + buf_discard(req->buf); + kfree(req); } diff --git a/net/tipc/discover.h b/net/tipc/discover.h index f8e75063612..a3af595b86c 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -2,7 +2,7 @@ * net/tipc/discover.h * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,17 +37,13 @@ #ifndef _TIPC_DISCOVER_H #define _TIPC_DISCOVER_H -#include "core.h" - struct link_req; -struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain, - u32 req_links); -void tipc_disc_update_link_req(struct link_req *req); -void tipc_disc_stop_link_req(struct link_req *req); - -void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr); +int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, + u32 dest_domain); +void tipc_disc_delete(struct link_req *req); +void tipc_disc_add_dest(struct link_req *req); +void tipc_disc_remove_dest(struct link_req *req); +void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); #endif diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 6e988ba485f..b69092eb95d 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -34,12 +34,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <net/tipc/tipc.h> -#include <net/tipc/tipc_bearer.h> -#include <net/tipc/tipc_msg.h> -#include <linux/netdevice.h> -#include <linux/slab.h> -#include <net/net_namespace.h> +#include "core.h" +#include "bearer.h" #define MAX_ETH_BEARERS 2 #define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI @@ -60,7 +56,7 @@ struct eth_bearer { }; static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; -static int eth_started = 0; +static int eth_started; static struct notifier_block notifier; /** @@ -148,7 +144,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) /* Find device with specified name */ - for_each_netdev(&init_net, pdev){ + for_each_netdev(&init_net, pdev) { if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) { dev = pdev; break; @@ -159,7 +155,8 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) /* Find Ethernet bearer for device (or create one) */ - for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++); + while ((eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev)) + eb_ptr++; if (eb_ptr == stop) return -EDQUOT; if (!eb_ptr->dev) { diff --git a/net/tipc/handler.c b/net/tipc/handler.c index 0c70010a7df..274c98e164b 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -45,7 +45,7 @@ struct queue_item { static struct kmem_cache *tipc_queue_item_cache; static struct list_head signal_queue_head; static DEFINE_SPINLOCK(qitem_lock); -static int handler_enabled = 0; +static int handler_enabled; static void process_signal_queue(unsigned long dummy); diff --git a/net/tipc/link.c b/net/tipc/link.c index b31992ccd5d..5ed4b4f7452 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2,7 +2,7 @@ * net/tipc/link.c: TIPC link code * * Copyright (c) 1996-2007, Ericsson AB - * Copyright (c) 2004-2007, Wind River Systems + * Copyright (c) 2004-2007, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,19 +35,11 @@ */ #include "core.h" -#include "dbg.h" #include "link.h" -#include "net.h" -#include "node.h" #include "port.h" -#include "addr.h" -#include "node_subscr.h" #include "name_distr.h" -#include "bearer.h" -#include "name_table.h" #include "discover.h" #include "config.h" -#include "bcast.h" /* @@ -57,12 +49,6 @@ #define INVALID_SESSION 0x10000 /* - * Limit for deferred reception queue: - */ - -#define DEF_QUEUE_LIMIT 256u - -/* * Link state events: */ @@ -104,81 +90,17 @@ static void link_handle_out_of_seq_msg(struct link *l_ptr, static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf); static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf); static void link_set_supervision_props(struct link *l_ptr, u32 tolerance); -static int link_send_sections_long(struct port *sender, +static int link_send_sections_long(struct tipc_port *sender, struct iovec const *msg_sect, - u32 num_sect, u32 destnode); + u32 num_sect, unsigned int total_len, + u32 destnode); static void link_check_defragm_bufs(struct link *l_ptr); static void link_state_event(struct link *l_ptr, u32 event); static void link_reset_statistics(struct link *l_ptr); -static void link_print(struct link *l_ptr, struct print_buf *buf, - const char *str); +static void link_print(struct link *l_ptr, const char *str); static void link_start(struct link *l_ptr); static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); - -/* - * Debugging code used by link routines only - * - * When debugging link problems on a system that has multiple links, - * the standard TIPC debugging routines may not be useful since they - * allow the output from multiple links to be intermixed. For this reason - * routines of the form "dbg_link_XXX()" have been created that will capture - * debug info into a link's personal print buffer, which can then be dumped - * into the TIPC system log (TIPC_LOG) upon request. - * - * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size - * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0, - * the dbg_link_XXX() routines simply send their output to the standard - * debug print buffer (DBG_OUTPUT), if it has been defined; this can be useful - * when there is only a single link in the system being debugged. - * - * Notes: - * - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE - * - "l_ptr" must be valid when using dbg_link_XXX() macros - */ - -#define LINK_LOG_BUF_SIZE 0 - -#define dbg_link(fmt, arg...) \ - do { \ - if (LINK_LOG_BUF_SIZE) \ - tipc_printf(&l_ptr->print_buf, fmt, ## arg); \ - } while (0) -#define dbg_link_msg(msg, txt) \ - do { \ - if (LINK_LOG_BUF_SIZE) \ - tipc_msg_dbg(&l_ptr->print_buf, msg, txt); \ - } while (0) -#define dbg_link_state(txt) \ - do { \ - if (LINK_LOG_BUF_SIZE) \ - link_print(l_ptr, &l_ptr->print_buf, txt); \ - } while (0) -#define dbg_link_dump() do { \ - if (LINK_LOG_BUF_SIZE) { \ - tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \ - tipc_printbuf_move(LOG, &l_ptr->print_buf); \ - } \ -} while (0) - -static void dbg_print_link(struct link *l_ptr, const char *str) -{ - if (DBG_OUTPUT != TIPC_NULL) - link_print(l_ptr, DBG_OUTPUT, str); -} - -static void dbg_print_buf_chain(struct sk_buff *root_buf) -{ - if (DBG_OUTPUT != TIPC_NULL) { - struct sk_buff *buf = root_buf; - - while (buf) { - msg_dbg(buf_msg(buf), "In chain: "); - buf = buf->next; - } - } -} - /* * Simple link routines */ @@ -192,7 +114,7 @@ static void link_init_max_pkt(struct link *l_ptr) { u32 max_pkt; - max_pkt = (l_ptr->b_ptr->publ.mtu & ~3); + max_pkt = (l_ptr->b_ptr->mtu & ~3); if (max_pkt > MAX_MSG_SIZE) max_pkt = MAX_MSG_SIZE; @@ -266,14 +188,17 @@ static int link_name_validate(const char *name, struct link_name *name_parts) /* ensure all component parts of link name are present */ addr_local = name_copy; - if ((if_local = strchr(addr_local, ':')) == NULL) + if_local = strchr(addr_local, ':'); + if (if_local == NULL) return 0; *(if_local++) = 0; - if ((addr_peer = strchr(if_local, '-')) == NULL) + addr_peer = strchr(if_local, '-'); + if (addr_peer == NULL) return 0; *(addr_peer++) = 0; if_local_len = addr_peer - if_local; - if ((if_peer = strchr(addr_peer, ':')) == NULL) + if_peer = strchr(addr_peer, ':'); + if (if_peer == NULL) return 0; *(if_peer++) = 0; if_peer_len = strlen(if_peer) + 1; @@ -322,9 +247,6 @@ static void link_timeout(struct link *l_ptr) l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size; l_ptr->stats.queue_sz_counts++; - if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz) - l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; - if (l_ptr->first_out) { struct tipc_msg *msg = buf_msg(l_ptr->first_out); u32 length = msg_size(msg); @@ -372,39 +294,44 @@ static void link_set_timer(struct link *l_ptr, u32 time) /** * tipc_link_create - create a new link + * @n_ptr: pointer to associated node * @b_ptr: pointer to associated bearer - * @peer: network address of node at other end of link * @media_addr: media address to use when sending messages over link * * Returns pointer to link. */ -struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, +struct link *tipc_link_create(struct tipc_node *n_ptr, + struct tipc_bearer *b_ptr, const struct tipc_media_addr *media_addr) { struct link *l_ptr; struct tipc_msg *msg; char *if_name; + char addr_string[16]; + u32 peer = n_ptr->addr; - l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC); - if (!l_ptr) { - warn("Link creation failed, no memory\n"); + if (n_ptr->link_cnt >= 2) { + tipc_addr_string_fill(addr_string, n_ptr->addr); + err("Attempt to establish third link to %s\n", addr_string); return NULL; } - if (LINK_LOG_BUF_SIZE) { - char *pb = kmalloc(LINK_LOG_BUF_SIZE, GFP_ATOMIC); + if (n_ptr->links[b_ptr->identity]) { + tipc_addr_string_fill(addr_string, n_ptr->addr); + err("Attempt to establish second link on <%s> to %s\n", + b_ptr->name, addr_string); + return NULL; + } - if (!pb) { - kfree(l_ptr); - warn("Link creation failed, no memory for print buffer\n"); - return NULL; - } - tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); + l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC); + if (!l_ptr) { + warn("Link creation failed, no memory\n"); + return NULL; } l_ptr->addr = peer; - if_name = strchr(b_ptr->publ.name, ':') + 1; + if_name = strchr(b_ptr->name, ':') + 1; sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:", tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), tipc_node(tipc_own_addr), @@ -412,6 +339,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); /* note: peer i/f is appended to link name by reset/activate */ memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); + l_ptr->owner = n_ptr; l_ptr->checkpoint = 1; l_ptr->b_ptr = b_ptr; link_set_supervision_props(l_ptr, b_ptr->media->tolerance); @@ -435,21 +363,12 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, link_reset_statistics(l_ptr); - l_ptr->owner = tipc_node_attach_link(l_ptr); - if (!l_ptr->owner) { - if (LINK_LOG_BUF_SIZE) - kfree(l_ptr->print_buf.buf); - kfree(l_ptr); - return NULL; - } + tipc_node_attach_link(n_ptr, l_ptr); k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); list_add_tail(&l_ptr->link_list, &b_ptr->links); tipc_k_signal((Handler)link_start, (unsigned long)l_ptr); - dbg("tipc_link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n", - l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit); - return l_ptr; } @@ -469,8 +388,6 @@ void tipc_link_delete(struct link *l_ptr) return; } - dbg("tipc_link_delete()\n"); - k_cancel_timer(&l_ptr->timer); tipc_node_lock(l_ptr->owner); @@ -478,8 +395,6 @@ void tipc_link_delete(struct link *l_ptr) tipc_node_detach_link(l_ptr->owner, l_ptr); tipc_link_stop(l_ptr); list_del_init(&l_ptr->link_list); - if (LINK_LOG_BUF_SIZE) - kfree(l_ptr->print_buf.buf); tipc_node_unlock(l_ptr->owner); k_term_timer(&l_ptr->timer); kfree(l_ptr); @@ -487,8 +402,9 @@ void tipc_link_delete(struct link *l_ptr) static void link_start(struct link *l_ptr) { - dbg("link_start %x\n", l_ptr); + tipc_node_lock(l_ptr->owner); link_state_event(l_ptr, STARTING_EVT); + tipc_node_unlock(l_ptr->owner); } /** @@ -503,7 +419,7 @@ static void link_start(struct link *l_ptr) static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) { - struct port *p_ptr; + struct tipc_port *p_ptr; spin_lock_bh(&tipc_port_list_lock); p_ptr = tipc_port_lock(origport); @@ -512,7 +428,7 @@ static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) goto exit; if (!list_empty(&p_ptr->wait_list)) goto exit; - p_ptr->publ.congested = 1; + p_ptr->congested = 1; p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt); list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); l_ptr->stats.link_congs++; @@ -525,8 +441,8 @@ exit: void tipc_link_wakeup_ports(struct link *l_ptr, int all) { - struct port *p_ptr; - struct port *temp_p_ptr; + struct tipc_port *p_ptr; + struct tipc_port *temp_p_ptr; int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size; if (all) @@ -542,11 +458,11 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all) if (win <= 0) break; list_del_init(&p_ptr->wait_list); - spin_lock_bh(p_ptr->publ.lock); - p_ptr->publ.congested = 0; - p_ptr->wakeup(&p_ptr->publ); + spin_lock_bh(p_ptr->lock); + p_ptr->congested = 0; + p_ptr->wakeup(p_ptr); win -= p_ptr->waiting_pkts; - spin_unlock_bh(p_ptr->publ.lock); + spin_unlock_bh(p_ptr->lock); } exit: @@ -639,7 +555,6 @@ void tipc_link_reset(struct link *l_ptr) link_init_max_pkt(l_ptr); l_ptr->state = RESET_UNKNOWN; - dbg_link_state("Resetting Link\n"); if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET)) return; @@ -647,7 +562,7 @@ void tipc_link_reset(struct link *l_ptr) tipc_node_link_down(l_ptr->owner, l_ptr); tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); - if (was_active_link && tipc_node_has_active_links(l_ptr->owner) && + if (was_active_link && tipc_node_active_links(l_ptr->owner) && l_ptr->owner->permit_changeover) { l_ptr->reset_checkpoint = checkpoint; l_ptr->exp_msg_count = START_CHANGEOVER; @@ -713,25 +628,18 @@ static void link_state_event(struct link *l_ptr, unsigned event) return; /* Not yet. */ if (link_blocked(l_ptr)) { - if (event == TIMEOUT_EVT) { + if (event == TIMEOUT_EVT) link_set_timer(l_ptr, cont_intv); - } return; /* Changeover going on */ } - dbg_link("STATE_EV: <%s> ", l_ptr->name); switch (l_ptr->state) { case WORKING_WORKING: - dbg_link("WW/"); switch (event) { case TRAFFIC_MSG_EVT: - dbg_link("TRF-"); - /* fall through */ case ACTIVATE_MSG: - dbg_link("ACT\n"); break; case TIMEOUT_EVT: - dbg_link("TIM "); if (l_ptr->next_in_no != l_ptr->checkpoint) { l_ptr->checkpoint = l_ptr->next_in_no; if (tipc_bclink_acks_missing(l_ptr->owner)) { @@ -746,7 +654,6 @@ static void link_state_event(struct link *l_ptr, unsigned event) link_set_timer(l_ptr, cont_intv); break; } - dbg_link(" -> WU\n"); l_ptr->state = WORKING_UNKNOWN; l_ptr->fsm_msg_cnt = 0; tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); @@ -754,7 +661,6 @@ static void link_state_event(struct link *l_ptr, unsigned event) link_set_timer(l_ptr, cont_intv / 4); break; case RESET_MSG: - dbg_link("RES -> RR\n"); info("Resetting link <%s>, requested by peer\n", l_ptr->name); tipc_link_reset(l_ptr); @@ -769,18 +675,14 @@ static void link_state_event(struct link *l_ptr, unsigned event) } break; case WORKING_UNKNOWN: - dbg_link("WU/"); switch (event) { case TRAFFIC_MSG_EVT: - dbg_link("TRF-"); case ACTIVATE_MSG: - dbg_link("ACT -> WW\n"); l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; link_set_timer(l_ptr, cont_intv); break; case RESET_MSG: - dbg_link("RES -> RR\n"); info("Resetting link <%s>, requested by peer " "while probing\n", l_ptr->name); tipc_link_reset(l_ptr); @@ -791,9 +693,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) link_set_timer(l_ptr, cont_intv); break; case TIMEOUT_EVT: - dbg_link("TIM "); if (l_ptr->next_in_no != l_ptr->checkpoint) { - dbg_link("-> WW\n"); l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; l_ptr->checkpoint = l_ptr->next_in_no; @@ -804,16 +704,11 @@ static void link_state_event(struct link *l_ptr, unsigned event) } link_set_timer(l_ptr, cont_intv); } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { - dbg_link("Probing %u/%u,timer = %u ms)\n", - l_ptr->fsm_msg_cnt, l_ptr->abort_limit, - cont_intv / 4); tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv / 4); } else { /* Link has failed */ - dbg_link("-> RU (%u probes unanswered)\n", - l_ptr->fsm_msg_cnt); warn("Resetting link <%s>, peer not responding\n", l_ptr->name); tipc_link_reset(l_ptr); @@ -830,18 +725,13 @@ static void link_state_event(struct link *l_ptr, unsigned event) } break; case RESET_UNKNOWN: - dbg_link("RU/"); switch (event) { case TRAFFIC_MSG_EVT: - dbg_link("TRF-\n"); break; case ACTIVATE_MSG: other = l_ptr->owner->active_links[0]; - if (other && link_working_unknown(other)) { - dbg_link("ACT\n"); + if (other && link_working_unknown(other)) break; - } - dbg_link("ACT -> WW\n"); l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; link_activate(l_ptr); @@ -850,8 +740,6 @@ static void link_state_event(struct link *l_ptr, unsigned event) link_set_timer(l_ptr, cont_intv); break; case RESET_MSG: - dbg_link("RES\n"); - dbg_link(" -> RR\n"); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); @@ -859,11 +747,9 @@ static void link_state_event(struct link *l_ptr, unsigned event) link_set_timer(l_ptr, cont_intv); break; case STARTING_EVT: - dbg_link("START-"); l_ptr->started = 1; /* fall through */ case TIMEOUT_EVT: - dbg_link("TIM\n"); tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); @@ -873,18 +759,12 @@ static void link_state_event(struct link *l_ptr, unsigned event) } break; case RESET_RESET: - dbg_link("RR/ "); switch (event) { case TRAFFIC_MSG_EVT: - dbg_link("TRF-"); - /* fall through */ case ACTIVATE_MSG: other = l_ptr->owner->active_links[0]; - if (other && link_working_unknown(other)) { - dbg_link("ACT\n"); + if (other && link_working_unknown(other)) break; - } - dbg_link("ACT -> WW\n"); l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; link_activate(l_ptr); @@ -893,14 +773,11 @@ static void link_state_event(struct link *l_ptr, unsigned event) link_set_timer(l_ptr, cont_intv); break; case RESET_MSG: - dbg_link("RES\n"); break; case TIMEOUT_EVT: - dbg_link("TIM\n"); tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); - dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt); break; default: err("Unknown link event %u in RR state\n", event); @@ -940,9 +817,6 @@ static int link_bundle_buf(struct link *l_ptr, skb_copy_to_linear_data_offset(bundler, to_pos, buf->data, size); msg_set_size(bundler_msg, to_pos + size); msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); - dbg("Packed msg # %u(%u octets) into pos %u in buf(#%u)\n", - msg_msgcnt(bundler_msg), size, to_pos, msg_seqno(bundler_msg)); - msg_dbg(msg, "PACKD:"); buf_discard(buf); l_ptr->stats.sent_bundled++; return 1; @@ -963,7 +837,29 @@ static void link_add_to_outqueue(struct link *l_ptr, l_ptr->last_out = buf; } else l_ptr->first_out = l_ptr->last_out = buf; + l_ptr->out_queue_size++; + if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz) + l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; +} + +static void link_add_chain_to_outqueue(struct link *l_ptr, + struct sk_buff *buf_chain, + u32 long_msgno) +{ + struct sk_buff *buf; + struct tipc_msg *msg; + + if (!l_ptr->next_out) + l_ptr->next_out = buf_chain; + while (buf_chain) { + buf = buf_chain; + buf_chain = buf_chain->next; + + msg = buf_msg(buf); + msg_set_long_msgno(msg, long_msgno); + link_add_to_outqueue(l_ptr, buf, msg); + } } /* @@ -988,10 +884,10 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) if (unlikely(queue_size >= queue_limit)) { if (imp <= TIPC_CRITICAL_IMPORTANCE) { - return link_schedule_port(l_ptr, msg_origport(msg), - size); + link_schedule_port(l_ptr, msg_origport(msg), size); + buf_discard(buf); + return -ELINKCONG; } - msg_dbg(msg, "TIPC: Congestion, throwing away\n"); buf_discard(buf); if (imp > CONN_MANAGER) { warn("Resetting link <%s>, send queue full", l_ptr->name); @@ -1007,9 +903,6 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) /* Packet can be queued or sent: */ - if (queue_size > l_ptr->stats.max_queue_sz) - l_ptr->stats.max_queue_sz = queue_size; - if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && !link_congested(l_ptr))) { link_add_to_outqueue(l_ptr, buf, msg); @@ -1075,22 +968,16 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) int res = -ELINKCONG; read_lock_bh(&tipc_net_lock); - n_ptr = tipc_node_select(dest, selector); + n_ptr = tipc_node_find(dest); if (n_ptr) { tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector & 1]; - if (l_ptr) { - dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest); + if (l_ptr) res = tipc_link_send_buf(l_ptr, buf); - } else { - dbg("Attempt to send msg to unreachable node:\n"); - msg_dbg(buf_msg(buf),">>>"); + else buf_discard(buf); - } tipc_node_unlock(n_ptr); } else { - dbg("Attempt to send msg to unknown node:\n"); - msg_dbg(buf_msg(buf),">>>"); buf_discard(buf); } read_unlock_bh(&tipc_net_lock); @@ -1117,17 +1004,14 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) { l_ptr->unacked_window = 0; - msg_dbg(msg,"SENT_FAST:"); return res; } - dbg("failed sent fast...\n"); tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); l_ptr->stats.bearer_congs++; l_ptr->next_out = buf; return res; } - } - else + } else *used_max_pkt = l_ptr->max_pkt; } return tipc_link_send_buf(l_ptr, buf); /* All other cases */ @@ -1151,12 +1035,10 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) return tipc_port_recv_msg(buf); read_lock_bh(&tipc_net_lock); - n_ptr = tipc_node_select(destnode, selector); + n_ptr = tipc_node_find(destnode); if (likely(n_ptr)) { tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector]; - dbg("send_fast: buf %x selected %x, destnode = %x\n", - buf, l_ptr, destnode); if (likely(l_ptr)) { res = link_send_buf_fast(l_ptr, buf, &dummy); tipc_node_unlock(n_ptr); @@ -1178,12 +1060,13 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) * except for total message length. * Returns user data length or errno. */ -int tipc_link_send_sections_fast(struct port *sender, +int tipc_link_send_sections_fast(struct tipc_port *sender, struct iovec const *msg_sect, const u32 num_sect, + unsigned int total_len, u32 destaddr) { - struct tipc_msg *hdr = &sender->publ.phdr; + struct tipc_msg *hdr = &sender->phdr; struct link *l_ptr; struct sk_buff *buf; struct tipc_node *node; @@ -1196,20 +1079,18 @@ again: * (Must not hold any locks while building message.) */ - res = tipc_msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt, - !sender->user_port, &buf); + res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, + sender->max_pkt, !sender->user_port, &buf); read_lock_bh(&tipc_net_lock); - node = tipc_node_select(destaddr, selector); + node = tipc_node_find(destaddr); if (likely(node)) { tipc_node_lock(node); l_ptr = node->active_links[selector]; if (likely(l_ptr)) { if (likely(buf)) { res = link_send_buf_fast(l_ptr, buf, - &sender->publ.max_pkt); - if (unlikely(res < 0)) - buf_discard(buf); + &sender->max_pkt); exit: tipc_node_unlock(node); read_unlock_bh(&tipc_net_lock); @@ -1226,7 +1107,7 @@ exit: if (link_congested(l_ptr) || !list_empty(&l_ptr->b_ptr->cong_links)) { res = link_schedule_port(l_ptr, - sender->publ.ref, res); + sender->ref, res); goto exit; } @@ -1235,16 +1116,17 @@ exit: * then re-try fast path or fragment the message */ - sender->publ.max_pkt = l_ptr->max_pkt; + sender->max_pkt = l_ptr->max_pkt; tipc_node_unlock(node); read_unlock_bh(&tipc_net_lock); - if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt) + if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) goto again; return link_send_sections_long(sender, msg_sect, - num_sect, destaddr); + num_sect, total_len, + destaddr); } tipc_node_unlock(node); } @@ -1256,7 +1138,7 @@ exit: return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); if (res >= 0) return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, - TIPC_ERR_NO_NODE); + total_len, TIPC_ERR_NO_NODE); return res; } @@ -1274,26 +1156,27 @@ exit: * * Returns user data length or errno. */ -static int link_send_sections_long(struct port *sender, +static int link_send_sections_long(struct tipc_port *sender, struct iovec const *msg_sect, u32 num_sect, + unsigned int total_len, u32 destaddr) { struct link *l_ptr; struct tipc_node *node; - struct tipc_msg *hdr = &sender->publ.phdr; - u32 dsz = msg_data_sz(hdr); - u32 max_pkt,fragm_sz,rest; + struct tipc_msg *hdr = &sender->phdr; + u32 dsz = total_len; + u32 max_pkt, fragm_sz, rest; struct tipc_msg fragm_hdr; - struct sk_buff *buf,*buf_chain,*prev; - u32 fragm_crs,fragm_rest,hsz,sect_rest; + struct sk_buff *buf, *buf_chain, *prev; + u32 fragm_crs, fragm_rest, hsz, sect_rest; const unchar *sect_crs; int curr_sect; u32 fragm_no; again: fragm_no = 1; - max_pkt = sender->publ.max_pkt - INT_H_SIZE; + max_pkt = sender->max_pkt - INT_H_SIZE; /* leave room for tunnel header in case of link changeover */ fragm_sz = max_pkt - INT_H_SIZE; /* leave room for fragmentation header in each fragment */ @@ -1306,10 +1189,8 @@ again: /* Prepare reusable fragment header: */ - msg_dbg(hdr, ">FRAGMENTING>"); tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, msg_destnode(hdr)); - msg_set_link_selector(&fragm_hdr, sender->publ.ref); msg_set_size(&fragm_hdr, max_pkt); msg_set_fragm_no(&fragm_hdr, 1); @@ -1322,7 +1203,6 @@ again: skb_copy_to_linear_data(buf, &fragm_hdr, INT_H_SIZE); hsz = msg_hdr_sz(hdr); skb_copy_to_linear_data_offset(buf, INT_H_SIZE, hdr, hsz); - msg_dbg(buf_msg(buf), ">BUILD>"); /* Chop up message: */ @@ -1365,7 +1245,7 @@ error: /* Initiate new fragment: */ if (rest <= fragm_sz) { fragm_sz = rest; - msg_set_type(&fragm_hdr,LAST_FRAGMENT); + msg_set_type(&fragm_hdr, LAST_FRAGMENT); } else { msg_set_type(&fragm_hdr, FRAGMENT); } @@ -1381,25 +1261,23 @@ error: skb_copy_to_linear_data(buf, &fragm_hdr, INT_H_SIZE); fragm_crs = INT_H_SIZE; fragm_rest = fragm_sz; - msg_dbg(buf_msg(buf)," >BUILD>"); } - } - while (rest > 0); + } while (rest > 0); /* * Now we have a buffer chain. Select a link and check * that packet size is still OK */ - node = tipc_node_select(destaddr, sender->publ.ref & 1); + node = tipc_node_find(destaddr); if (likely(node)) { tipc_node_lock(node); - l_ptr = node->active_links[sender->publ.ref & 1]; + l_ptr = node->active_links[sender->ref & 1]; if (!l_ptr) { tipc_node_unlock(node); goto reject; } if (l_ptr->max_pkt < max_pkt) { - sender->publ.max_pkt = l_ptr->max_pkt; + sender->max_pkt = l_ptr->max_pkt; tipc_node_unlock(node); for (; buf_chain; buf_chain = buf) { buf = buf_chain->next; @@ -1414,29 +1292,15 @@ reject: buf_discard(buf_chain); } return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, - TIPC_ERR_NO_NODE); + total_len, TIPC_ERR_NO_NODE); } - /* Append whole chain to send queue: */ + /* Append chain of fragments to send queue & send them */ - buf = buf_chain; - l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1); - if (!l_ptr->next_out) - l_ptr->next_out = buf_chain; + l_ptr->long_msg_seq_no++; + link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); + l_ptr->stats.sent_fragments += fragm_no; l_ptr->stats.sent_fragmented++; - while (buf) { - struct sk_buff *next = buf->next; - struct tipc_msg *msg = buf_msg(buf); - - l_ptr->stats.sent_fragments++; - msg_set_long_msgno(msg, l_ptr->long_msg_seq_no); - link_add_to_outqueue(l_ptr, buf, msg); - msg_dbg(msg, ">ADD>"); - buf = next; - } - - /* Send it, if possible: */ - tipc_link_push_queue(l_ptr); tipc_node_unlock(node); return dsz; @@ -1473,14 +1337,12 @@ u32 tipc_link_push_packet(struct link *l_ptr) msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { - msg_dbg(buf_msg(buf), ">DEF-RETR>"); l_ptr->retransm_queue_head = mod(++r_q_head); l_ptr->retransm_queue_size = --r_q_size; l_ptr->stats.retransmitted++; return 0; } else { l_ptr->stats.bearer_congs++; - msg_dbg(buf_msg(buf), "|>DEF-RETR>"); return PUSH_FAILED; } } @@ -1490,15 +1352,13 @@ u32 tipc_link_push_packet(struct link *l_ptr) buf = l_ptr->proto_msg_queue; if (buf) { msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); - msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in); + msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { - msg_dbg(buf_msg(buf), ">DEF-PROT>"); l_ptr->unacked_window = 0; buf_discard(buf); l_ptr->proto_msg_queue = NULL; return 0; } else { - msg_dbg(buf_msg(buf), "|>DEF-PROT>"); l_ptr->stats.bearer_congs++; return PUSH_FAILED; } @@ -1518,11 +1378,9 @@ u32 tipc_link_push_packet(struct link *l_ptr) if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { if (msg_user(msg) == MSG_BUNDLER) msg_set_type(msg, CLOSED_MSG); - msg_dbg(msg, ">PUSH-DATA>"); l_ptr->next_out = buf->next; return 0; } else { - msg_dbg(msg, "|PUSH-DATA|"); l_ptr->stats.bearer_congs++; return PUSH_FAILED; } @@ -1570,8 +1428,7 @@ static void link_reset_all(unsigned long addr) for (i = 0; i < MAX_BEARERS; i++) { if (n_ptr->links[i]) { - link_print(n_ptr->links[i], TIPC_OUTPUT, - "Resetting link\n"); + link_print(n_ptr->links[i], "Resetting link\n"); tipc_link_reset(n_ptr->links[i]); } } @@ -1585,13 +1442,12 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) struct tipc_msg *msg = buf_msg(buf); warn("Retransmission failure on link <%s>\n", l_ptr->name); - tipc_msg_dbg(TIPC_OUTPUT, msg, ">RETR-FAIL>"); if (l_ptr->addr) { /* Handle failure on standard link */ - link_print(l_ptr, TIPC_OUTPUT, "Resetting link\n"); + link_print(l_ptr, "Resetting link\n"); tipc_link_reset(l_ptr); } else { @@ -1601,21 +1457,21 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) struct tipc_node *n_ptr; char addr_string[16]; - tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); - tipc_printf(TIPC_OUTPUT, "Outstanding acks: %lu\n", - (unsigned long) TIPC_SKB_CB(buf)->handle); + info("Msg seq number: %u, ", msg_seqno(msg)); + info("Outstanding acks: %lu\n", + (unsigned long) TIPC_SKB_CB(buf)->handle); - n_ptr = l_ptr->owner->next; + n_ptr = tipc_bclink_retransmit_to(); tipc_node_lock(n_ptr); tipc_addr_string_fill(addr_string, n_ptr->addr); - tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string); - tipc_printf(TIPC_OUTPUT, "Supported: %d, ", n_ptr->bclink.supported); - tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked); - tipc_printf(TIPC_OUTPUT, "Last in: %u, ", n_ptr->bclink.last_in); - tipc_printf(TIPC_OUTPUT, "Gap after: %u, ", n_ptr->bclink.gap_after); - tipc_printf(TIPC_OUTPUT, "Gap to: %u\n", n_ptr->bclink.gap_to); - tipc_printf(TIPC_OUTPUT, "Nack sync: %u\n\n", n_ptr->bclink.nack_sync); + info("Multicast link info for %s\n", addr_string); + info("Supported: %d, ", n_ptr->bclink.supported); + info("Acked: %u\n", n_ptr->bclink.acked); + info("Last in: %u, ", n_ptr->bclink.last_in); + info("Gap after: %u, ", n_ptr->bclink.gap_after); + info("Gap to: %u\n", n_ptr->bclink.gap_to); + info("Nack sync: %u\n\n", n_ptr->bclink.nack_sync); tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); @@ -1635,12 +1491,8 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, msg = buf_msg(buf); - dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); - if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { if (l_ptr->retransm_queue_size == 0) { - msg_dbg(msg, ">NO_RETR->BCONG>"); - dbg_print_link(l_ptr, " "); l_ptr->retransm_queue_head = msg_seqno(msg); l_ptr->retransm_queue_size = retransmits; } else { @@ -1667,7 +1519,6 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { - msg_dbg(buf_msg(buf), ">RETR>"); buf = buf->next; retransmits--; l_ptr->stats.retransmitted++; @@ -1764,11 +1615,10 @@ static int link_recv_buf_validate(struct sk_buff *buf) * structure (i.e. cannot be NULL), but bearer can be inactive. */ -void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) +void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) { read_lock_bh(&tipc_net_lock); while (head) { - struct bearer *b_ptr = (struct bearer *)tb_ptr; struct tipc_node *n_ptr; struct link *l_ptr; struct sk_buff *crs; @@ -1793,9 +1643,8 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) /* Ensure message data is a single contiguous unit */ - if (unlikely(buf_linearize(buf))) { + if (unlikely(buf_linearize(buf))) goto cont; - } /* Handle arrival of a non-unicast link message */ @@ -1905,10 +1754,6 @@ deliver: tipc_node_unlock(n_ptr); tipc_link_recv_bundle(buf); continue; - case ROUTE_DISTRIBUTOR: - tipc_node_unlock(n_ptr); - tipc_cltr_recv_routing_table(buf); - continue; case NAME_DISTRIBUTOR: tipc_node_unlock(n_ptr); tipc_named_recv(buf); @@ -1935,6 +1780,10 @@ deliver: goto protocol_check; } break; + default: + buf_discard(buf); + buf = NULL; + break; } } tipc_node_unlock(n_ptr); @@ -1953,12 +1802,10 @@ deliver: tipc_node_unlock(n_ptr); continue; } - msg_dbg(msg,"NSEQ<REC<"); link_state_event(l_ptr, TRAFFIC_MSG_EVT); if (link_working_working(l_ptr)) { /* Re-insert in front of queue */ - msg_dbg(msg,"RECV-REINS:"); buf->next = head; head = buf; tipc_node_unlock(n_ptr); @@ -2012,13 +1859,11 @@ u32 tipc_link_defer_pkt(struct sk_buff **head, *head = buf; return 1; } - if (seq_no == msg_seqno(msg)) { + if (seq_no == msg_seqno(msg)) break; - } prev = crs; crs = crs->next; - } - while (crs); + } while (crs); /* Message is a duplicate of an existing message */ @@ -2040,9 +1885,6 @@ static void link_handle_out_of_seq_msg(struct link *l_ptr, return; } - dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n", - seq_no, mod(l_ptr->next_in_no), l_ptr->next_in_no); - /* Record OOS packet arrival (force mismatch on next timeout) */ l_ptr->checkpoint--; @@ -2077,6 +1919,7 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, struct sk_buff *buf = NULL; struct tipc_msg *msg = l_ptr->pmsg; u32 msg_size = sizeof(l_ptr->proto_msg); + int r_flag; if (link_blocked(l_ptr)) return; @@ -2127,16 +1970,14 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1)); msg_set_seq_gap(msg, 0); msg_set_next_sent(msg, 1); + msg_set_probe(msg, 0); msg_set_link_tolerance(msg, l_ptr->tolerance); msg_set_linkprio(msg, l_ptr->priority); msg_set_max_pkt(msg, l_ptr->max_pkt_target); } - if (tipc_node_has_redundant_links(l_ptr->owner)) { - msg_set_redundant_link(msg); - } else { - msg_clear_redundant_link(msg); - } + r_flag = (l_ptr->owner->working_links > tipc_link_is_up(l_ptr)); + msg_set_redundant_link(msg, r_flag); msg_set_linkprio(msg, l_ptr->priority); /* Ensure sequence number will not fit : */ @@ -2156,12 +1997,9 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); return; } - msg_set_timestamp(msg, jiffies_to_msecs(jiffies)); /* Message can be sent */ - msg_dbg(msg, ">>"); - buf = tipc_buf_acquire(msg_size); if (!buf) return; @@ -2195,8 +2033,6 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) u32 msg_tol; struct tipc_msg *msg = buf_msg(buf); - dbg("AT(%u):", jiffies_to_msecs(jiffies)); - msg_dbg(msg, "<<"); if (link_blocked(l_ptr)) goto exit; @@ -2215,11 +2051,8 @@ 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) { - dbg("Duplicate RESET: %u<->%u\n", - msg_session(msg), l_ptr->peer_session); + if (msg_session(msg) == l_ptr->peer_session) break; /* duplicate: ignore */ - } } /* fall thru' */ case ACTIVATE_MSG: @@ -2227,8 +2060,8 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) strcpy((strrchr(l_ptr->name, ':') + 1), (char *)msg_data(msg)); - if ((msg_tol = msg_link_tolerance(msg)) && - (msg_tol > l_ptr->tolerance)) + msg_tol = msg_link_tolerance(msg); + if (msg_tol > l_ptr->tolerance) link_set_supervision_props(l_ptr, msg_tol); if (msg_linkprio(msg) > l_ptr->priority) @@ -2251,13 +2084,13 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) l_ptr->peer_bearer_id = msg_bearer_id(msg); /* Synchronize broadcast sequence numbers */ - if (!tipc_node_has_redundant_links(l_ptr->owner)) { + if (!tipc_node_redundant_links(l_ptr->owner)) l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); - } break; case STATE_MSG: - if ((msg_tol = msg_link_tolerance(msg))) + msg_tol = msg_link_tolerance(msg); + if (msg_tol) link_set_supervision_props(l_ptr, msg_tol); if (msg_linkprio(msg) && @@ -2280,8 +2113,6 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) max_pkt_ack = msg_max_pkt(msg); if (max_pkt_ack > l_ptr->max_pkt) { - dbg("Link <%s> updated MTU %u -> %u\n", - l_ptr->name, l_ptr->max_pkt, max_pkt_ack); l_ptr->max_pkt = max_pkt_ack; l_ptr->max_pkt_probes = 0; } @@ -2289,9 +2120,8 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) max_pkt_ack = 0; if (msg_probe(msg)) { l_ptr->stats.recv_probes++; - if (msg_size(msg) > sizeof(l_ptr->proto_msg)) { + if (msg_size(msg) > sizeof(l_ptr->proto_msg)) max_pkt_ack = msg_size(msg); - } } /* Protocol message before retransmits, reduce loss risk */ @@ -2303,14 +2133,11 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) 0, rec_gap, 0, 0, max_pkt_ack); } if (msg_seq_gap(msg)) { - msg_dbg(msg, "With Gap:"); l_ptr->stats.recv_nacks++; tipc_link_retransmit(l_ptr, l_ptr->first_out, msg_seq_gap(msg)); } break; - default: - msg_dbg(buf_msg(buf), "<DISCARDING UNKNOWN<"); } exit: buf_discard(buf); @@ -2345,8 +2172,6 @@ static void tipc_link_tunnel(struct link *l_ptr, } skb_copy_to_linear_data(buf, tunnel_hdr, INT_H_SIZE); skb_copy_to_linear_data_offset(buf, INT_H_SIZE, msg, length); - dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); - msg_dbg(buf_msg(buf), ">SEND>"); tipc_link_send_buf(tunnel, buf); } @@ -2378,7 +2203,6 @@ void tipc_link_changeover(struct link *l_ptr) ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr); msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); msg_set_msgcnt(&tunnel_hdr, msgcount); - dbg("Link changeover requires %u tunnel messages\n", msgcount); if (!l_ptr->first_out) { struct sk_buff *buf; @@ -2387,9 +2211,6 @@ void tipc_link_changeover(struct link *l_ptr) if (buf) { skb_copy_to_linear_data(buf, &tunnel_hdr, INT_H_SIZE); msg_set_size(&tunnel_hdr, INT_H_SIZE); - dbg("%c->%c:", l_ptr->b_ptr->net_plane, - tunnel->b_ptr->net_plane); - msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); tipc_link_send_buf(tunnel, buf); } else { warn("Link changeover error, " @@ -2406,11 +2227,11 @@ void tipc_link_changeover(struct link *l_ptr) if ((msg_user(msg) == MSG_BUNDLER) && split_bundles) { struct tipc_msg *m = msg_get_wrapped(msg); - unchar* pos = (unchar*)m; + unchar *pos = (unchar *)m; msgcount = msg_msgcnt(msg); while (msgcount--) { - msg_set_seqno(m,msg_seqno(msg)); + msg_set_seqno(m, msg_seqno(msg)); tipc_link_tunnel(l_ptr, &tunnel_hdr, m, msg_link_selector(m)); pos += align(msg_size(m)); @@ -2453,9 +2274,6 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) skb_copy_to_linear_data(outbuf, &tunnel_hdr, INT_H_SIZE); skb_copy_to_linear_data_offset(outbuf, INT_H_SIZE, iter->data, length); - dbg("%c->%c:", l_ptr->b_ptr->net_plane, - tunnel->b_ptr->net_plane); - msg_dbg(buf_msg(outbuf), ">SEND>"); tipc_link_send_buf(tunnel, outbuf); if (!tipc_link_is_up(l_ptr)) return; @@ -2502,31 +2320,24 @@ static int link_recv_changeover_msg(struct link **l_ptr, u32 msg_count = msg_msgcnt(tunnel_msg); dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; - if (!dest_link) { - msg_dbg(tunnel_msg, "NOLINK/<REC<"); + if (!dest_link) goto exit; - } if (dest_link == *l_ptr) { err("Unexpected changeover message on link <%s>\n", (*l_ptr)->name); goto exit; } - dbg("%c<-%c:", dest_link->b_ptr->net_plane, - (*l_ptr)->b_ptr->net_plane); *l_ptr = dest_link; msg = msg_get_wrapped(tunnel_msg); if (msg_typ == DUPLICATE_MSG) { - if (less(msg_seqno(msg), mod(dest_link->next_in_no))) { - msg_dbg(tunnel_msg, "DROP/<REC<"); + if (less(msg_seqno(msg), mod(dest_link->next_in_no))) goto exit; - } - *buf = buf_extract(tunnel_buf,INT_H_SIZE); + *buf = buf_extract(tunnel_buf, INT_H_SIZE); if (*buf == NULL) { warn("Link changeover error, duplicate msg dropped\n"); goto exit; } - msg_dbg(tunnel_msg, "TNL<REC<"); buf_discard(tunnel_buf); return 1; } @@ -2534,18 +2345,14 @@ static int link_recv_changeover_msg(struct link **l_ptr, /* First original message ?: */ if (tipc_link_is_up(dest_link)) { - msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); info("Resetting link <%s>, changeover initiated by peer\n", dest_link->name); tipc_link_reset(dest_link); dest_link->exp_msg_count = msg_count; - dbg("Expecting %u tunnelled messages\n", msg_count); if (!msg_count) goto exit; } else if (dest_link->exp_msg_count == START_CHANGEOVER) { - msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); dest_link->exp_msg_count = msg_count; - dbg("Expecting %u tunnelled messages\n", msg_count); if (!msg_count) goto exit; } @@ -2555,18 +2362,14 @@ static int link_recv_changeover_msg(struct link **l_ptr, if (dest_link->exp_msg_count == 0) { warn("Link switchover error, " "got too many tunnelled messages\n"); - msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); - dbg_print_link(dest_link, "LINK:"); goto exit; } dest_link->exp_msg_count--; if (less(msg_seqno(msg), dest_link->reset_checkpoint)) { - msg_dbg(tunnel_msg, "DROP/DUPL/<REC<"); goto exit; } else { *buf = buf_extract(tunnel_buf, INT_H_SIZE); if (*buf != NULL) { - msg_dbg(tunnel_msg, "TNL<REC<"); buf_discard(tunnel_buf); return 1; } else { @@ -2588,7 +2391,6 @@ void tipc_link_recv_bundle(struct sk_buff *buf) u32 pos = INT_H_SIZE; struct sk_buff *obuf; - msg_dbg(buf_msg(buf), "<BNDL<: "); while (msgcount--) { obuf = buf_extract(buf, pos); if (obuf == NULL) { @@ -2596,7 +2398,6 @@ void tipc_link_recv_bundle(struct sk_buff *buf) break; } pos += align(msg_size(buf_msg(obuf))); - msg_dbg(buf_msg(obuf), " /"); tipc_net_route_msg(obuf); } buf_discard(buf); @@ -2614,6 +2415,8 @@ void tipc_link_recv_bundle(struct sk_buff *buf) */ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) { + struct sk_buff *buf_chain = NULL; + struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain; struct tipc_msg *inmsg = buf_msg(buf); struct tipc_msg fragm_hdr; u32 insize = msg_size(inmsg); @@ -2622,7 +2425,7 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) u32 rest = insize; u32 pack_sz = l_ptr->max_pkt; u32 fragm_sz = pack_sz - INT_H_SIZE; - u32 fragm_no = 1; + u32 fragm_no = 0; u32 destaddr; if (msg_short(inmsg)) @@ -2630,17 +2433,10 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) else destaddr = msg_destnode(inmsg); - if (msg_routed(inmsg)) - msg_set_prevnode(inmsg, tipc_own_addr); - /* Prepare reusable fragment header: */ tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, destaddr); - msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); - msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); - msg_set_fragm_no(&fragm_hdr, fragm_no); - l_ptr->stats.sent_fragmented++; /* Chop up message: */ @@ -2653,27 +2449,37 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) } fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); if (fragm == NULL) { - warn("Link unable to fragment message\n"); - dsz = -ENOMEM; - goto exit; + buf_discard(buf); + while (buf_chain) { + buf = buf_chain; + buf_chain = buf_chain->next; + buf_discard(buf); + } + return -ENOMEM; } msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); + fragm_no++; + msg_set_fragm_no(&fragm_hdr, fragm_no); skb_copy_to_linear_data(fragm, &fragm_hdr, INT_H_SIZE); skb_copy_to_linear_data_offset(fragm, INT_H_SIZE, crs, fragm_sz); - /* Send queued messages first, if any: */ + buf_chain_tail->next = fragm; + buf_chain_tail = fragm; - l_ptr->stats.sent_fragments++; - tipc_link_send_buf(l_ptr, fragm); - if (!tipc_link_is_up(l_ptr)) - return dsz; - msg_set_fragm_no(&fragm_hdr, ++fragm_no); rest -= fragm_sz; crs += fragm_sz; msg_set_type(&fragm_hdr, FRAGMENT); } -exit: buf_discard(buf); + + /* Append chain of fragments to send queue & send them */ + + l_ptr->long_msg_seq_no++; + link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); + l_ptr->stats.sent_fragments += fragm_no; + l_ptr->stats.sent_fragmented++; + tipc_link_push_queue(l_ptr); + return dsz; } @@ -2681,7 +2487,7 @@ exit: * A pending message being re-assembled must store certain values * to handle subsequent fragments correctly. The following functions * help storing these values in unused, available fields in the - * pending message. This makes dynamic memory allocation unecessary. + * pending message. This makes dynamic memory allocation unnecessary. */ static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) @@ -2733,7 +2539,6 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, u32 long_msg_seq_no = msg_long_msgno(fragm); *fb = NULL; - msg_dbg(fragm,"FRG<REC<"); /* Is there an incomplete message waiting for this fragment? */ @@ -2752,7 +2557,6 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, if (msg_type(imsg) == TIPC_MCAST_MSG) max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; if (msg_size(imsg) > max) { - msg_dbg(fragm,"<REC<Oversized: "); buf_discard(fbuf); return 0; } @@ -2765,8 +2569,8 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, /* Prepare buffer for subsequent fragments. */ set_long_msg_seqno(pbuf, long_msg_seq_no); - set_fragm_size(pbuf,fragm_sz); - set_expected_frags(pbuf,exp_fragm_cnt - 1); + set_fragm_size(pbuf, fragm_sz); + set_expected_frags(pbuf, exp_fragm_cnt - 1); } else { warn("Link unable to reassemble fragmented message\n"); } @@ -2793,13 +2597,9 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, *m = buf_msg(pbuf); return 1; } - set_expected_frags(pbuf,exp_frags); + set_expected_frags(pbuf, exp_frags); return 0; } - dbg(" Discarding orphan fragment %x\n",fbuf); - msg_dbg(fragm,"ORPHAN:"); - dbg("Pending long buffers:\n"); - dbg_print_buf_chain(*pending); buf_discard(fbuf); return 0; } @@ -2827,11 +2627,6 @@ static void link_check_defragm_bufs(struct link *l_ptr) incr_timer_cnt(buf); prev = buf; } else { - dbg(" Discarding incomplete long buffer\n"); - msg_dbg(buf_msg(buf), "LONG:"); - dbg_print_link(l_ptr, "curr:"); - dbg("Pending long buffers:\n"); - dbg_print_buf_chain(l_ptr->defragm_buf); if (prev) prev->next = buf->next; else @@ -2846,6 +2641,9 @@ static void link_check_defragm_bufs(struct link *l_ptr) static void link_set_supervision_props(struct link *l_ptr, u32 tolerance) { + if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL)) + return; + l_ptr->tolerance = tolerance; l_ptr->continuity_interval = ((tolerance / 4) > 500) ? 500 : tolerance / 4; @@ -2866,7 +2664,6 @@ void tipc_link_set_queue_limits(struct link *l_ptr, u32 window) l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE + 4] = 900; l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE + 4] = 1200; l_ptr->queue_limit[CONN_MANAGER] = 1200; - l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200; l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500; l_ptr->queue_limit[NAME_DISTRIBUTOR] = 3000; /* FRAGMENT and LAST_FRAGMENT packets */ @@ -2887,7 +2684,7 @@ void tipc_link_set_queue_limits(struct link *l_ptr, u32 window) static struct link *link_find_link(const char *name, struct tipc_node **node) { struct link_name link_name_parts; - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; struct link *l_ptr; if (!link_name_validate(name, &link_name_parts)) @@ -3168,7 +2965,7 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector) return MAX_MSG_SIZE; read_lock_bh(&tipc_net_lock); - n_ptr = tipc_node_select(dest, selector); + n_ptr = tipc_node_find(dest); if (n_ptr) { tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector & 1]; @@ -3180,27 +2977,22 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector) return res; } -static void link_dump_send_queue(struct link *l_ptr) +static void link_print(struct link *l_ptr, const char *str) { - if (l_ptr->next_out) { - info("\nContents of unsent queue:\n"); - dbg_print_buf_chain(l_ptr->next_out); - } - info("\nContents of send queue:\n"); - if (l_ptr->first_out) { - dbg_print_buf_chain(l_ptr->first_out); - } - info("Empty send queue\n"); -} + char print_area[256]; + struct print_buf pb; + struct print_buf *buf = &pb; + + tipc_printbuf_init(buf, print_area, sizeof(print_area)); -static void link_print(struct link *l_ptr, struct print_buf *buf, - const char *str) -{ tipc_printf(buf, str); - if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr)) - return; tipc_printf(buf, "Link %x<%s>:", - l_ptr->addr, l_ptr->b_ptr->publ.name); + l_ptr->addr, l_ptr->b_ptr->name); + +#ifdef CONFIG_TIPC_DEBUG + if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr)) + goto print_state; + tipc_printf(buf, ": NXO(%u):", mod(l_ptr->next_out_no)); tipc_printf(buf, "NXI(%u):", mod(l_ptr->next_in_no)); tipc_printf(buf, "SQUE"); @@ -3215,10 +3007,9 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, != (l_ptr->out_queue_size - 1)) || (l_ptr->last_out->next != NULL)) { tipc_printf(buf, "\nSend queue inconsistency\n"); - tipc_printf(buf, "first_out= %x ", l_ptr->first_out); - tipc_printf(buf, "next_out= %x ", l_ptr->next_out); - tipc_printf(buf, "last_out= %x ", l_ptr->last_out); - link_dump_send_queue(l_ptr); + tipc_printf(buf, "first_out= %p ", l_ptr->first_out); + tipc_printf(buf, "next_out= %p ", l_ptr->next_out); + tipc_printf(buf, "last_out= %p ", l_ptr->last_out); } } else tipc_printf(buf, "[]"); @@ -3232,14 +3023,20 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, l_ptr->deferred_inqueue_sz); } } +print_state: +#endif + if (link_working_unknown(l_ptr)) tipc_printf(buf, ":WU"); - if (link_reset_reset(l_ptr)) + else if (link_reset_reset(l_ptr)) tipc_printf(buf, ":RR"); - if (link_reset_unknown(l_ptr)) + else if (link_reset_unknown(l_ptr)) tipc_printf(buf, ":RU"); - if (link_working_working(l_ptr)) + else if (link_working_working(l_ptr)) tipc_printf(buf, ":WW"); tipc_printf(buf, "\n"); + + tipc_printbuf_validate(buf); + info("%s", print_area); } diff --git a/net/tipc/link.h b/net/tipc/link.h index f98bc613de6..74fbecab1ea 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -2,7 +2,7 @@ * net/tipc/link.h: Include file for TIPC link code * * Copyright (c) 1995-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 @@ -37,9 +37,8 @@ #ifndef _TIPC_LINK_H #define _TIPC_LINK_H -#include "dbg.h" +#include "log.h" #include "msg.h" -#include "bearer.h" #include "node.h" #define PUSH_FAILED 1 @@ -108,7 +107,6 @@ * @long_msg_seq_no: next identifier to use for outbound fragmented messages * @defragm_buf: list of partially reassembled inbound message fragments * @stats: collects statistics regarding link activity - * @print_buf: print buffer used to log link activity */ struct link { @@ -124,7 +122,7 @@ struct link { u32 checkpoint; u32 peer_session; u32 peer_bearer_id; - struct bearer *b_ptr; + struct tipc_bearer *b_ptr; u32 tolerance; u32 continuity_interval; u32 abort_limit; @@ -198,26 +196,19 @@ struct link { u32 bearer_congs; u32 deferred_recv; u32 duplicates; - - /* for statistical profiling of send queue size */ - - u32 max_queue_sz; - u32 accu_queue_sz; - u32 queue_sz_counts; - - /* for statistical profiling of message lengths */ - - u32 msg_length_counts; - u32 msg_lengths_total; - u32 msg_length_profile[7]; + u32 max_queue_sz; /* send queue size high water mark */ + u32 accu_queue_sz; /* used for send queue size profiling */ + u32 queue_sz_counts; /* used for send queue size profiling */ + u32 msg_length_counts; /* used for message length profiling */ + u32 msg_lengths_total; /* used for message length profiling */ + u32 msg_length_profile[7]; /* used for msg. length profiling */ } stats; - - struct print_buf print_buf; }; -struct port; +struct tipc_port; -struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, +struct link *tipc_link_create(struct tipc_node *n_ptr, + struct tipc_bearer *b_ptr, const struct tipc_media_addr *media_addr); void tipc_link_delete(struct link *l_ptr); void tipc_link_changeover(struct link *l_ptr); @@ -233,10 +224,11 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_ void tipc_link_reset(struct link *l_ptr); int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector); 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 port* sender, +u32 tipc_link_get_max_pkt(u32 dest, u32 selector); +int tipc_link_send_sections_fast(struct tipc_port *sender, struct iovec const *msg_sect, const u32 num_sect, + unsigned int total_len, u32 destnode); void tipc_link_recv_bundle(struct sk_buff *buf); int tipc_link_recv_fragment(struct sk_buff **pending, diff --git a/net/tipc/dbg.c b/net/tipc/log.c index 46f51d208e5..952c39f643e 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/log.c @@ -1,5 +1,5 @@ /* - * net/tipc/dbg.c: TIPC print buffer routines for debugging + * net/tipc/log.c: TIPC print buffer routines for debugging * * Copyright (c) 1996-2006, Ericsson AB * Copyright (c) 2005-2007, Wind River Systems @@ -36,7 +36,7 @@ #include "core.h" #include "config.h" -#include "dbg.h" +#include "log.h" /* * TIPC pre-defines the following print buffers: @@ -52,7 +52,7 @@ static struct print_buf null_buf = { NULL, 0, NULL, 0 }; struct print_buf *const TIPC_NULL = &null_buf; static struct print_buf cons_buf = { NULL, 0, NULL, 1 }; -static struct print_buf *const TIPC_CONS = &cons_buf; +struct print_buf *const TIPC_CONS = &cons_buf; static struct print_buf log_buf = { NULL, 0, NULL, 1 }; struct print_buf *const TIPC_LOG = &log_buf; @@ -64,9 +64,9 @@ struct print_buf *const TIPC_LOG = &log_buf; * 'print_string' when writing to a print buffer. This also protects against * concurrent writes to the print buffer being written to. * - * 2) tipc_dump() and tipc_log_XXX() leverage the aforementioned - * use of 'print_lock' to protect against all types of concurrent operations - * on their associated print buffer (not just write operations). + * 2) tipc_log_XXX() leverages the aforementioned use of 'print_lock' to + * protect against all types of concurrent operations on their associated + * print buffer (not just write operations). * * Note: All routines of the form tipc_printbuf_XXX() are lock-free, and rely * on the caller to prevent simultaneous use of the print buffer(s) being @@ -76,18 +76,16 @@ struct print_buf *const TIPC_LOG = &log_buf; static char print_string[TIPC_PB_MAX_STR]; static DEFINE_SPINLOCK(print_lock); -static void tipc_printbuf_reset(struct print_buf *pb); -static int tipc_printbuf_empty(struct print_buf *pb); static void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); -#define FORMAT(PTR,LEN,FMT) \ +#define FORMAT(PTR, LEN, FMT) \ {\ - va_list args;\ - va_start(args, FMT);\ - LEN = vsprintf(PTR, FMT, args);\ - va_end(args);\ - *(PTR + LEN) = '\0';\ + va_list args;\ + va_start(args, FMT);\ + LEN = vsprintf(PTR, FMT, args);\ + va_end(args);\ + *(PTR + LEN) = '\0';\ } /** @@ -268,81 +266,6 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) spin_unlock_bh(&print_lock); } -#ifdef CONFIG_TIPC_DEBUG - -/** - * print_to_console - write string of bytes to console in multiple chunks - */ - -static void print_to_console(char *crs, int len) -{ - int rest = len; - - while (rest > 0) { - int sz = rest < TIPC_PB_MAX_STR ? rest : TIPC_PB_MAX_STR; - char c = crs[sz]; - - crs[sz] = 0; - printk((const char *)crs); - crs[sz] = c; - rest -= sz; - crs += sz; - } -} - -/** - * printbuf_dump - write print buffer contents to console - */ - -static void printbuf_dump(struct print_buf *pb) -{ - int len; - - if (!pb->buf) { - printk("*** PRINT BUFFER NOT ALLOCATED ***"); - return; - } - - /* Dump print buffer from char after cursor to end (if used) */ - - len = pb->buf + pb->size - pb->crs - 2; - if ((pb->buf[pb->size - 1] == 0) && (len > 0)) - print_to_console(pb->crs + 1, len); - - /* Dump print buffer from start to cursor (always) */ - - len = pb->crs - pb->buf; - print_to_console(pb->buf, len); -} - -/** - * tipc_dump_dbg - dump (non-console) print buffer to console - * @pb: pointer to print buffer - */ - -void tipc_dump_dbg(struct print_buf *pb, const char *fmt, ...) -{ - int len; - - if (pb == TIPC_CONS) - return; - - spin_lock_bh(&print_lock); - - FORMAT(print_string, len, fmt); - printk(print_string); - - printk("\n---- Start of %s log dump ----\n\n", - (pb == TIPC_LOG) ? "global" : "local"); - printbuf_dump(pb); - tipc_printbuf_reset(pb); - printk("\n---- End of dump ----\n"); - - spin_unlock_bh(&print_lock); -} - -#endif - /** * tipc_log_resize - change the size of the TIPC log buffer * @log_size: print buffer size to use @@ -353,10 +276,8 @@ int tipc_log_resize(int log_size) int res = 0; spin_lock_bh(&print_lock); - if (TIPC_LOG->buf) { - kfree(TIPC_LOG->buf); - TIPC_LOG->buf = NULL; - } + kfree(TIPC_LOG->buf); + TIPC_LOG->buf = NULL; if (log_size) { if (log_size < TIPC_PB_MIN_SIZE) log_size = TIPC_PB_MIN_SIZE; @@ -407,8 +328,7 @@ struct sk_buff *tipc_log_dump(void) } else if (tipc_printbuf_empty(TIPC_LOG)) { spin_unlock_bh(&print_lock); reply = tipc_cfg_reply_ultra_string("log is empty\n"); - } - else { + } else { struct tlv_desc *rep_tlv; struct print_buf pb; int str_len; @@ -429,4 +349,3 @@ struct sk_buff *tipc_log_dump(void) } return reply; } - diff --git a/net/tipc/dbg.h b/net/tipc/log.h index 3ba6ba8b434..2248d96238e 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/log.h @@ -1,5 +1,5 @@ /* - * net/tipc/dbg.h: Include file for TIPC print buffer routines + * net/tipc/log.h: Include file for TIPC print buffer routines * * Copyright (c) 1997-2006, Ericsson AB * Copyright (c) 2005-2007, Wind River Systems @@ -34,8 +34,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _TIPC_DBG_H -#define _TIPC_DBG_H +#ifndef _TIPC_LOG_H +#define _TIPC_LOG_H /** * struct print_buf - TIPC print buffer structure diff --git a/net/tipc/msg.c b/net/tipc/msg.c index ecb532fb035..03e57bf92c7 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -2,7 +2,7 @@ * net/tipc/msg.c: TIPC message header routines * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,10 +35,7 @@ */ #include "core.h" -#include "addr.h" -#include "dbg.h" #include "msg.h" -#include "bearer.h" u32 tipc_msg_tot_importance(struct tipc_msg *m) { @@ -71,20 +68,6 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, } /** - * tipc_msg_calc_data_size - determine total data size for message - */ - -int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) -{ - int dsz = 0; - int i; - - for (i = 0; i < num_sect; i++) - dsz += msg_sect[i].iov_len; - return dsz; -} - -/** * tipc_msg_build - create message using specified header and data * * Note: Caller must not hold any locks in case copy_from_user() is interrupted! @@ -92,18 +75,13 @@ int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) * Returns message data size or errno */ -int tipc_msg_build(struct tipc_msg *hdr, - struct iovec const *msg_sect, u32 num_sect, - int max_size, int usrmem, struct sk_buff** buf) +int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, + u32 num_sect, unsigned int total_len, + int max_size, int usrmem, struct sk_buff **buf) { int dsz, sz, hsz, pos, res, cnt; - dsz = tipc_msg_calc_data_size(msg_sect, num_sect); - if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { - *buf = NULL; - return -EINVAL; - } - + dsz = total_len; pos = hsz = msg_hdr_sz(hdr); sz = hsz + dsz; msg_set_size(hdr, sz); @@ -140,6 +118,7 @@ int tipc_msg_build(struct tipc_msg *hdr, void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) { u32 usr = msg_user(msg); + tipc_printf(buf, KERN_DEBUG); tipc_printf(buf, str); switch (usr) { @@ -163,10 +142,10 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, "LAST:"); break; default: - tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); + tipc_printf(buf, "UNKNOWN:%x", msg_type(msg)); } - tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg), + tipc_printf(buf, "NO(%u/%u):", msg_long_msgno(msg), msg_fragm_no(msg)); break; case TIPC_LOW_IMPORTANCE: @@ -192,10 +171,8 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, "DIR:"); break; default: - tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg)); + tipc_printf(buf, "UNKNOWN TYPE %u", msg_type(msg)); } - if (msg_routed(msg) && !msg_non_seq(msg)) - tipc_printf(buf, "ROUT:"); if (msg_reroute_cnt(msg)) tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg)); @@ -210,10 +187,8 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, "WDRW:"); break; default: - tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); + tipc_printf(buf, "UNKNOWN:%x", msg_type(msg)); } - if (msg_routed(msg)) - tipc_printf(buf, "ROUT:"); if (msg_reroute_cnt(msg)) tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg)); @@ -229,39 +204,36 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) break; case CONN_ACK: tipc_printf(buf, "CONN_ACK:"); - tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg)); + tipc_printf(buf, "ACK(%u):", msg_msgcnt(msg)); break; default: - tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); + tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); } - if (msg_routed(msg)) - tipc_printf(buf, "ROUT:"); if (msg_reroute_cnt(msg)) - tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg)); + tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg)); break; case LINK_PROTOCOL: - tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg)); switch (msg_type(msg)) { case STATE_MSG: tipc_printf(buf, "STATE:"); - tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :""); - tipc_printf(buf, "NXS(%u):",msg_next_sent(msg)); - tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg)); - tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg)); + tipc_printf(buf, "%s:", msg_probe(msg) ? "PRB" : ""); + tipc_printf(buf, "NXS(%u):", msg_next_sent(msg)); + tipc_printf(buf, "GAP(%u):", msg_seq_gap(msg)); + tipc_printf(buf, "LSTBC(%u):", msg_last_bcast(msg)); break; case RESET_MSG: tipc_printf(buf, "RESET:"); if (msg_size(msg) != msg_hdr_sz(msg)) - tipc_printf(buf, "BEAR:%s:",msg_data(msg)); + tipc_printf(buf, "BEAR:%s:", msg_data(msg)); break; case ACTIVATE_MSG: tipc_printf(buf, "ACTIVATE:"); break; default: - tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); + tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); } - tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg)); - tipc_printf(buf, "SESS(%u):",msg_session(msg)); + tipc_printf(buf, "PLANE(%c):", msg_net_plane(msg)); + tipc_printf(buf, "SESS(%u):", msg_session(msg)); break; case CHANGEOVER_PROTOCOL: tipc_printf(buf, "TUNL:"); @@ -271,37 +243,10 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) break; case ORIGINAL_MSG: tipc_printf(buf, "ORIG:"); - tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg)); + tipc_printf(buf, "EXP(%u)", msg_msgcnt(msg)); break; default: - tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); - } - break; - case ROUTE_DISTRIBUTOR: - tipc_printf(buf, "ROUTING_MNG:"); - switch (msg_type(msg)) { - case EXT_ROUTING_TABLE: - tipc_printf(buf, "EXT_TBL:"); - tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); - break; - case LOCAL_ROUTING_TABLE: - tipc_printf(buf, "LOCAL_TBL:"); - tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); - break; - case SLAVE_ROUTING_TABLE: - tipc_printf(buf, "DP_TBL:"); - tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); - break; - case ROUTE_ADDITION: - tipc_printf(buf, "ADD:"); - tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); - break; - case ROUTE_REMOVAL: - tipc_printf(buf, "REMOVE:"); - tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); - break; - default: - tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); + tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); } break; case LINK_CONFIG: @@ -314,7 +259,7 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, "DSC_RESP:"); break; default: - tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg)); + tipc_printf(buf, "UNKNOWN TYPE:%x:", msg_type(msg)); break; } break; @@ -350,7 +295,8 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, "UNKNOWN ERROR(%x):", msg_errcode(msg)); } - default:{} + default: + break; } tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg)); @@ -359,9 +305,8 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) if (msg_non_seq(msg)) tipc_printf(buf, "NOSEQ:"); - else { + else tipc_printf(buf, "ACK(%u):", msg_ack(msg)); - } tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg)); tipc_printf(buf, "PRND(%x)", msg_prevnode(msg)); @@ -383,21 +328,15 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, ":OPRT(%u):", msg_origport(msg)); tipc_printf(buf, ":DPRT(%u):", msg_destport(msg)); } - if (msg_routed(msg) && !msg_non_seq(msg)) - tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg)); } if (msg_user(msg) == NAME_DISTRIBUTOR) { tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg)); tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg)); - if (msg_routed(msg)) { - tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg)); - } } if (msg_user(msg) == LINK_CONFIG) { - u32* raw = (u32*)msg; - struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5]; - tipc_printf(buf, ":REQL(%u):", msg_req_links(msg)); + u32 *raw = (u32 *)msg; + struct tipc_media_addr *orig = (struct tipc_media_addr *)&raw[5]; tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg)); tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg)); tipc_media_addr_printf(buf, orig); @@ -407,12 +346,10 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg)); } tipc_printf(buf, "\n"); - if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { + if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); - } - if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { + if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); - } } #endif diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 031aad18efc..8452454731f 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -2,7 +2,7 @@ * net/tipc/msg.h: Include file for TIPC message header routines * * Copyright (c) 2000-2007, Ericsson AB - * Copyright (c) 2005-2008, Wind River Systems + * Copyright (c) 2005-2008, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,10 +37,37 @@ #ifndef _TIPC_MSG_H #define _TIPC_MSG_H -#include "core.h" +#include "bearer.h" + +/* + * Constants and routines used to read and write TIPC payload message headers + * + * Note: Some items are also used with TIPC internal message headers + */ #define TIPC_VERSION 2 +/* + * Payload message users are defined in TIPC's public API: + * - TIPC_LOW_IMPORTANCE + * - TIPC_MEDIUM_IMPORTANCE + * - TIPC_HIGH_IMPORTANCE + * - TIPC_CRITICAL_IMPORTANCE + */ + +/* + * Payload message types + */ + +#define TIPC_CONN_MSG 0 +#define TIPC_MCAST_MSG 1 +#define TIPC_NAMED_MSG 2 +#define TIPC_DIRECT_MSG 3 + +/* + * 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 */ @@ -52,20 +79,26 @@ #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE) -/* - TIPC user data message header format, version 2 +struct tipc_msg { + __be32 hdr[15]; +}; - - Fundamental definitions available to privileged TIPC users - are located in tipc_msg.h. - - Remaining definitions available to TIPC internal users appear below. -*/ +static inline u32 msg_word(struct tipc_msg *m, u32 pos) +{ + return ntohl(m->hdr[pos]); +} static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val) { m->hdr[w] = htonl(val); } +static inline u32 msg_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask) +{ + return (msg_word(m, w) >> pos) & mask; +} + static inline void msg_set_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask, u32 val) { @@ -112,16 +145,36 @@ static inline void msg_set_user(struct tipc_msg *m, u32 n) msg_set_bits(m, 0, 25, 0xf, n); } +static inline u32 msg_importance(struct tipc_msg *m) +{ + return msg_bits(m, 0, 25, 0xf); +} + static inline void msg_set_importance(struct tipc_msg *m, u32 i) { msg_set_user(m, i); } -static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n) +static inline u32 msg_hdr_sz(struct tipc_msg *m) +{ + return msg_bits(m, 0, 21, 0xf) << 2; +} + +static inline void msg_set_hdr_sz(struct tipc_msg *m, u32 n) { msg_set_bits(m, 0, 21, 0xf, n>>2); } +static inline u32 msg_size(struct tipc_msg *m) +{ + return msg_bits(m, 0, 0, 0x1ffff); +} + +static inline u32 msg_data_sz(struct tipc_msg *m) +{ + return msg_size(m) - msg_hdr_sz(m); +} + static inline int msg_non_seq(struct tipc_msg *m) { return msg_bits(m, 0, 20, 1); @@ -162,11 +215,36 @@ static inline void msg_set_size(struct tipc_msg *m, u32 sz) * Word 1 */ +static inline u32 msg_type(struct tipc_msg *m) +{ + return msg_bits(m, 1, 29, 0x7); +} + static inline void msg_set_type(struct tipc_msg *m, u32 n) { msg_set_bits(m, 1, 29, 0x7, n); } +static inline u32 msg_named(struct tipc_msg *m) +{ + return msg_type(m) == TIPC_NAMED_MSG; +} + +static inline u32 msg_mcast(struct tipc_msg *m) +{ + return msg_type(m) == TIPC_MCAST_MSG; +} + +static inline u32 msg_connected(struct tipc_msg *m) +{ + return msg_type(m) == TIPC_CONN_MSG; +} + +static inline u32 msg_errcode(struct tipc_msg *m) +{ + return msg_bits(m, 1, 25, 0xf); +} + static inline void msg_set_errcode(struct tipc_msg *m, u32 err) { msg_set_bits(m, 1, 25, 0xf, err); @@ -257,71 +335,96 @@ static inline void msg_set_destnode_cache(struct tipc_msg *m, u32 dnode) */ +static inline u32 msg_prevnode(struct tipc_msg *m) +{ + return msg_word(m, 3); +} + static inline void msg_set_prevnode(struct tipc_msg *m, u32 a) { msg_set_word(m, 3, a); } +static inline u32 msg_origport(struct tipc_msg *m) +{ + return msg_word(m, 4); +} + static inline void msg_set_origport(struct tipc_msg *m, u32 p) { msg_set_word(m, 4, p); } +static inline u32 msg_destport(struct tipc_msg *m) +{ + return msg_word(m, 5); +} + static inline void msg_set_destport(struct tipc_msg *m, u32 p) { msg_set_word(m, 5, p); } +static inline u32 msg_mc_netid(struct tipc_msg *m) +{ + return msg_word(m, 5); +} + static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) { msg_set_word(m, 5, p); } -static inline void msg_set_orignode(struct tipc_msg *m, u32 a) +static inline int msg_short(struct tipc_msg *m) { - msg_set_word(m, 6, a); + return msg_hdr_sz(m) == 24; } -static inline void msg_set_destnode(struct tipc_msg *m, u32 a) +static inline u32 msg_orignode(struct tipc_msg *m) { - msg_set_word(m, 7, a); + if (likely(msg_short(m))) + return msg_prevnode(m); + return msg_word(m, 6); } -static inline int msg_is_dest(struct tipc_msg *m, u32 d) +static inline void msg_set_orignode(struct tipc_msg *m, u32 a) { - return msg_short(m) || (msg_destnode(m) == d); + msg_set_word(m, 6, a); } -static inline u32 msg_routed(struct tipc_msg *m) +static inline u32 msg_destnode(struct tipc_msg *m) { - if (likely(msg_short(m))) - return 0; - return(msg_destnode(m) ^ msg_orignode(m)) >> 11; + return msg_word(m, 7); } -static inline void msg_set_nametype(struct tipc_msg *m, u32 n) +static inline void msg_set_destnode(struct tipc_msg *m, u32 a) { - msg_set_word(m, 8, n); + msg_set_word(m, 7, a); } -static inline u32 msg_transp_seqno(struct tipc_msg *m) +static inline int msg_is_dest(struct tipc_msg *m, u32 d) +{ + return msg_short(m) || (msg_destnode(m) == d); +} + +static inline u32 msg_nametype(struct tipc_msg *m) { return msg_word(m, 8); } -static inline void msg_set_timestamp(struct tipc_msg *m, u32 n) +static inline void msg_set_nametype(struct tipc_msg *m, u32 n) { msg_set_word(m, 8, n); } -static inline u32 msg_timestamp(struct tipc_msg *m) +static inline u32 msg_nameinst(struct tipc_msg *m) { - return msg_word(m, 8); + return msg_word(m, 9); } -static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n) +static inline u32 msg_namelower(struct tipc_msg *m) { - msg_set_word(m, 8, n); + return msg_nameinst(m); } static inline void msg_set_namelower(struct tipc_msg *m, u32 n) @@ -334,11 +437,21 @@ static inline void msg_set_nameinst(struct tipc_msg *m, u32 n) msg_set_namelower(m, n); } +static inline u32 msg_nameupper(struct tipc_msg *m) +{ + return msg_word(m, 10); +} + static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) { msg_set_word(m, 10, n); } +static inline unchar *msg_data(struct tipc_msg *m) +{ + return ((unchar *)m) + msg_hdr_sz(m); +} + static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) { return (struct tipc_msg *)msg_data(m); @@ -346,55 +459,25 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) /* - TIPC internal message header format, version 2 - - 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w0:|vers |msg usr|hdr sz |n|resrv| packet size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w1:|m typ| sequence gap | broadcast ack no | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w3:| previous node | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w5:| session no |rsv=0|r|berid|link prio|netpl|p| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w6:| originating node | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w7:| destination node | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w8:| transport sequence number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w9:| msg count / bcast tag | link tolerance | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - \ \ - / User Specific Data / - \ \ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - NB: CONN_MANAGER use data message format. LINK_CONFIG has own format. -*/ + * Constants and routines used to read and write TIPC internal message headers + */ /* - * Internal users + * Internal message users */ #define BCAST_PROTOCOL 5 #define MSG_BUNDLER 6 #define LINK_PROTOCOL 7 #define CONN_MANAGER 8 -#define ROUTE_DISTRIBUTOR 9 +#define ROUTE_DISTRIBUTOR 9 /* obsoleted */ #define CHANGEOVER_PROTOCOL 10 #define NAME_DISTRIBUTOR 11 #define MSG_FRAGMENTER 12 #define LINK_CONFIG 13 -#define DSC_H_SIZE 40 /* - * Connection management protocol messages + * Connection management protocol message types */ #define CONN_PROBE 0 @@ -402,12 +485,41 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) #define CONN_ACK 2 /* - * Name distributor messages + * Name distributor message types */ #define PUBLICATION 0 #define WITHDRAWAL 1 +/* + * Segmentation message types + */ + +#define FIRST_FRAGMENT 0 +#define FRAGMENT 1 +#define LAST_FRAGMENT 2 + +/* + * Link management protocol message types + */ + +#define STATE_MSG 0 +#define RESET_MSG 1 +#define ACTIVATE_MSG 2 + +/* + * Changeover tunnel message types + */ +#define DUPLICATE_MSG 0 +#define ORIGINAL_MSG 1 + +/* + * Config protocol message types + */ + +#define DSC_REQ_MSG 0 +#define DSC_RESP_MSG 1 + /* * Word 1 @@ -423,16 +535,6 @@ static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) msg_set_bits(m, 1, 16, 0x1fff, n); } -static inline u32 msg_req_links(struct tipc_msg *m) -{ - return msg_bits(m, 1, 16, 0xfff); -} - -static inline void msg_set_req_links(struct tipc_msg *m, u32 n) -{ - msg_set_bits(m, 1, 16, 0xfff, n); -} - /* * Word 2 @@ -595,14 +697,9 @@ static inline u32 msg_redundant_link(struct tipc_msg *m) return msg_bits(m, 5, 12, 0x1); } -static inline void msg_set_redundant_link(struct tipc_msg *m) +static inline void msg_set_redundant_link(struct tipc_msg *m, u32 r) { - msg_set_bits(m, 5, 12, 0x1, 1); -} - -static inline void msg_clear_redundant_link(struct tipc_msg *m) -{ - msg_set_bits(m, 5, 12, 0x1, 0); + msg_set_bits(m, 5, 12, 0x1, r); } @@ -650,71 +747,12 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) msg_set_bits(m, 9, 0, 0xffff, n); } -/* - * Routing table message data - */ - - -static inline u32 msg_remote_node(struct tipc_msg *m) -{ - return msg_word(m, msg_hdr_sz(m)/4); -} - -static inline void msg_set_remote_node(struct tipc_msg *m, u32 a) -{ - msg_set_word(m, msg_hdr_sz(m)/4, a); -} - -static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos) -{ - msg_data(m)[pos + 4] = 1; -} - -/* - * Segmentation message types - */ - -#define FIRST_FRAGMENT 0 -#define FRAGMENT 1 -#define LAST_FRAGMENT 2 - -/* - * Link management protocol message types - */ - -#define STATE_MSG 0 -#define RESET_MSG 1 -#define ACTIVATE_MSG 2 - -/* - * Changeover tunnel message types - */ -#define DUPLICATE_MSG 0 -#define ORIGINAL_MSG 1 - -/* - * Routing table message types - */ -#define EXT_ROUTING_TABLE 0 -#define LOCAL_ROUTING_TABLE 1 -#define SLAVE_ROUTING_TABLE 2 -#define ROUTE_ADDITION 3 -#define ROUTE_REMOVAL 4 - -/* - * Config protocol message types - */ - -#define DSC_REQ_MSG 0 -#define DSC_RESP_MSG 1 - u32 tipc_msg_tot_importance(struct tipc_msg *m); void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode); -int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect); -int tipc_msg_build(struct tipc_msg *hdr, - struct iovec const *msg_sect, u32 num_sect, - int max_size, int usrmem, struct sk_buff** buf); +int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, + u32 num_sect, unsigned int total_len, + int max_size, int usrmem, struct sk_buff **buf); static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) { @@ -723,7 +761,7 @@ static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr static inline void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) { - memcpy(a, &((int*)m)[5], sizeof(*a)); + memcpy(a, &((int *)m)[5], sizeof(*a)); } #endif diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 7b907171f87..80025a1b3bf 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -2,7 +2,7 @@ * net/tipc/name_distr.c: TIPC name distribution code * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,10 +35,7 @@ */ #include "core.h" -#include "cluster.h" -#include "dbg.h" #include "link.h" -#include "msg.h" #include "name_distr.h" #define ITEM_SIZE sizeof(struct distr_item) @@ -76,7 +73,7 @@ struct distr_item { */ static LIST_HEAD(publ_root); -static u32 publ_cnt = 0; +static u32 publ_cnt; /** * publ_to_item - add publication info to a publication message @@ -89,7 +86,6 @@ static void publ_to_item(struct distr_item *i, struct publication *p) i->upper = htonl(p->upper); i->ref = htonl(p->ref); i->key = htonl(p->key); - dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper); } /** @@ -109,6 +105,24 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) return buf; } +static void named_cluster_distribute(struct sk_buff *buf) +{ + struct sk_buff *buf_copy; + struct tipc_node *n_ptr; + + list_for_each_entry(n_ptr, &tipc_node_list, list) { + if (tipc_node_active_links(n_ptr)) { + buf_copy = skb_copy(buf, GFP_ATOMIC); + if (!buf_copy) + break; + msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); + tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr); + } + } + + buf_discard(buf); +} + /** * tipc_named_publish - tell other nodes about a new publication by this node */ @@ -129,8 +143,7 @@ void tipc_named_publish(struct publication *publ) item = (struct distr_item *)msg_data(buf_msg(buf)); publ_to_item(item, publ); - dbg("tipc_named_withdraw: broadcasting publish msg\n"); - tipc_cltr_broadcast(buf); + named_cluster_distribute(buf); } /** @@ -147,14 +160,13 @@ void tipc_named_withdraw(struct publication *publ) buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); if (!buf) { - warn("Withdrawl distribution failure\n"); + warn("Withdrawal distribution failure\n"); return; } item = (struct distr_item *)msg_data(buf_msg(buf)); publ_to_item(item, publ); - dbg("tipc_named_withdraw: broadcasting withdraw msg\n"); - tipc_cltr_broadcast(buf); + named_cluster_distribute(buf); } /** @@ -191,9 +203,6 @@ void tipc_named_node_up(unsigned long node) left -= ITEM_SIZE; if (!left) { msg_set_link_selector(buf_msg(buf), node); - dbg("tipc_named_node_up: sending publish msg to " - "<%u.%u.%u>\n", tipc_zone(node), - tipc_cluster(node), tipc_node(node)); tipc_link_send(buf, node, node); buf = NULL; } @@ -203,26 +212,25 @@ exit: } /** - * node_is_down - remove publication associated with a failed node + * named_purge_publ - remove publication associated with a failed node * * Invoked for each publication issued by a newly failed node. * Removes publication structure from name table & deletes it. * In rare cases the link may have come back up again when this * function is called, and we have two items representing the same * publication. Nudge this item's key to distinguish it from the other. - * (Note: Publication's node subscription is already unsubscribed.) */ -static void node_is_down(struct publication *publ) +static void named_purge_publ(struct publication *publ) { struct publication *p; write_lock_bh(&tipc_nametbl_lock); - dbg("node_is_down: withdrawing %u, %u, %u\n", - publ->type, publ->lower, publ->upper); publ->key += 1222345; p = tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, publ->ref, publ->key); + if (p) + tipc_nodesub_unsubscribe(&p->subscr); write_unlock_bh(&tipc_nametbl_lock); if (p != publ) { @@ -231,9 +239,7 @@ static void node_is_down(struct publication *publ) publ->type, publ->lower, publ->node, publ->ref, publ->key); } - if (p) { - kfree(p); - } + kfree(p); } /** @@ -250,9 +256,6 @@ void tipc_named_recv(struct sk_buff *buf) write_lock_bh(&tipc_nametbl_lock); while (count--) { if (msg_type(msg) == PUBLICATION) { - dbg("tipc_named_recv: got publication for %u, %u, %u\n", - ntohl(item->type), ntohl(item->lower), - ntohl(item->upper)); publ = tipc_nametbl_insert_publ(ntohl(item->type), ntohl(item->lower), ntohl(item->upper), @@ -264,12 +267,10 @@ void tipc_named_recv(struct sk_buff *buf) tipc_nodesub_subscribe(&publ->subscr, msg_orignode(msg), publ, - (net_ev_handler)node_is_down); + (net_ev_handler) + named_purge_publ); } } else if (msg_type(msg) == WITHDRAWAL) { - dbg("tipc_named_recv: got withdrawl for %u, %u, %u\n", - ntohl(item->type), ntohl(item->lower), - ntohl(item->upper)); publ = tipc_nametbl_remove_publ(ntohl(item->type), ntohl(item->lower), msg_orignode(msg), diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 3a8de4334da..205ed4a4e18 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -36,15 +36,10 @@ #include "core.h" #include "config.h" -#include "dbg.h" #include "name_table.h" #include "name_distr.h" -#include "addr.h" -#include "node_subscr.h" #include "subscr.h" #include "port.h" -#include "cluster.h" -#include "bcast.h" static int tipc_nametbl_size = 1024; /* must be a power of 2 */ @@ -109,7 +104,7 @@ struct name_table { u32 local_publ_count; }; -static struct name_table table = { NULL } ; +static struct name_table table; static atomic_t rsv_publ_ok = ATOMIC_INIT(0); DEFINE_RWLOCK(tipc_nametbl_lock); @@ -177,8 +172,6 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea spin_lock_init(&nseq->lock); nseq->type = type; nseq->sseqs = sseq; - dbg("tipc_nameseq_create(): nseq = %p, type %u, ssseqs %p, ff: %u\n", - nseq, type, nseq->sseqs, nseq->first_free); nseq->alloc = 1; INIT_HLIST_NODE(&nseq->ns_list); INIT_LIST_HEAD(&nseq->subscriptions); @@ -256,8 +249,6 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, int created_subseq = 0; sseq = nameseq_find_subseq(nseq, lower); - dbg("nameseq_ins: for seq %p, {%u,%u}, found sseq %p\n", - nseq, type, lower, sseq); if (sseq) { /* Lower end overlaps existing entry => need an exact match */ @@ -294,38 +285,30 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, type, lower, upper); return NULL; } - dbg("Allocated %u more sseqs\n", nseq->alloc); memcpy(sseqs, nseq->sseqs, nseq->alloc * sizeof(struct sub_seq)); kfree(nseq->sseqs); nseq->sseqs = sseqs; nseq->alloc *= 2; } - dbg("Have %u sseqs for type %u\n", nseq->alloc, type); /* Insert new sub-sequence */ - dbg("ins in pos %u, ff = %u\n", inspos, nseq->first_free); sseq = &nseq->sseqs[inspos]; freesseq = &nseq->sseqs[nseq->first_free]; - memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq)); - memset(sseq, 0, sizeof (*sseq)); + memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof(*sseq)); + memset(sseq, 0, sizeof(*sseq)); nseq->first_free++; sseq->lower = lower; sseq->upper = upper; created_subseq = 1; } - dbg("inserting {%u,%u,%u} from <0x%x:%u> into sseq %p(%u,%u) of seq %p\n", - type, lower, upper, node, port, sseq, - sseq->lower, sseq->upper, nseq); /* Insert a publication: */ publ = publ_create(type, lower, upper, scope, node, port, key); if (!publ) return NULL; - dbg("inserting publ %p, node=0x%x publ->node=0x%x, subscr->node=%p\n", - publ, node, publ->node, publ->subscr.node); sseq->zone_list_size++; if (!sseq->zone_list) @@ -360,7 +343,6 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, * Any subscriptions waiting for notification? */ list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { - dbg("calling report_overlap()\n"); tipc_subscr_report_overlap(s, publ->lower, publ->upper, @@ -398,9 +380,6 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i if (!sseq) return NULL; - dbg("tipc_nameseq_remove_publ: seq: %p, sseq %p, {%u,%u}, key %u\n", - nseq, sseq, nseq->type, inst, key); - /* Remove publication from zone scope list */ prev = sseq->zone_list; @@ -492,7 +471,7 @@ end_node: if (!sseq->zone_list) { free = &nseq->sseqs[nseq->first_free--]; - memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); + memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq)); removed_subseq = 1; } @@ -528,7 +507,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s while (sseq != &nseq->sseqs[nseq->first_free]) { struct publication *zl = sseq->zone_list; - if (zl && tipc_subscr_overlap(s,sseq->lower,sseq->upper)) { + if (zl && tipc_subscr_overlap(s, sseq->lower, sseq->upper)) { struct publication *crs = zl; int must_report = 1; @@ -554,15 +533,10 @@ static struct name_seq *nametbl_find_seq(u32 type) struct hlist_node *seq_node; struct name_seq *ns; - dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n", - type, htonl(type), type, table.types, hash(type)); - seq_head = &table.types[hash(type)]; hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { - if (ns->type == type) { - dbg("found %p\n", ns); + if (ns->type == type) return ns; - } } return NULL; @@ -573,18 +547,14 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, { struct name_seq *seq = nametbl_find_seq(type); - dbg("tipc_nametbl_insert_publ: {%u,%u,%u} found %p\n", type, lower, upper, seq); if (lower > upper) { warn("Failed to publish illegal {%u,%u,%u}\n", type, lower, upper); return NULL; } - dbg("Publishing {%u,%u,%u} from 0x%x\n", type, lower, upper, node); - if (!seq) { + if (!seq) seq = tipc_nameseq_create(type, &table.types[hash(type)]); - dbg("tipc_nametbl_insert_publ: created %p\n", seq); - } if (!seq) return NULL; @@ -601,7 +571,6 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, if (!seq) return NULL; - dbg("Withdrawing {%u,%u} from 0x%x\n", type, lower, node); publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); if (!seq->first_free && list_empty(&seq->subscriptions)) { @@ -782,9 +751,8 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, table.local_publ_count++; publ = tipc_nametbl_insert_publ(type, lower, upper, scope, tipc_own_addr, port_ref, key); - if (publ && (scope != TIPC_NODE_SCOPE)) { + if (publ && (scope != TIPC_NODE_SCOPE)) tipc_named_publish(publ); - } write_unlock_bh(&tipc_nametbl_lock); return publ; } @@ -797,7 +765,6 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) { struct publication *publ; - dbg("tipc_nametbl_withdraw: {%u,%u}, key=%u\n", type, lower, key); write_lock_bh(&tipc_nametbl_lock); publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); if (likely(publ)) { @@ -827,13 +794,10 @@ void tipc_nametbl_subscribe(struct subscription *s) write_lock_bh(&tipc_nametbl_lock); seq = nametbl_find_seq(type); - if (!seq) { + if (!seq) seq = tipc_nameseq_create(type, &table.types[hash(type)]); - } - if (seq){ + if (seq) { spin_lock_bh(&seq->lock); - dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}\n", - seq, type, s->seq.lower, s->seq.upper); tipc_nameseq_subscribe(seq, s); spin_unlock_bh(&seq->lock); } else { @@ -853,7 +817,7 @@ void tipc_nametbl_unsubscribe(struct subscription *s) write_lock_bh(&tipc_nametbl_lock); seq = nametbl_find_seq(s->seq.type); - if (seq != NULL){ + if (seq != NULL) { spin_lock_bh(&seq->lock); list_del_init(&s->nameseq_list); spin_unlock_bh(&seq->lock); @@ -886,7 +850,7 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, } do { - sprintf (portIdStr, "<%u.%u.%u:%u>", + sprintf(portIdStr, "<%u.%u.%u:%u>", tipc_zone(publ->node), tipc_cluster(publ->node), tipc_node(publ->node), publ->ref); tipc_printf(buf, "%-26s ", portIdStr); diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 139882d4ed0..d228bd68265 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -46,7 +46,7 @@ struct port_list; * TIPC name types reserved for internal TIPC use (both current and planned) */ -#define TIPC_ZM_SRV 3 /* zone master service name type */ +#define TIPC_ZM_SRV 3 /* zone master service name type */ /** diff --git a/net/tipc/net.c b/net/tipc/net.c index 1a621cfd660..68b3dd63729 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -2,7 +2,7 @@ * net/tipc/net.c: TIPC network routing code * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,18 +35,11 @@ */ #include "core.h" -#include "bearer.h" #include "net.h" -#include "zone.h" -#include "addr.h" -#include "name_table.h" #include "name_distr.h" #include "subscr.h" -#include "link.h" -#include "msg.h" #include "port.h" -#include "bcast.h" -#include "discover.h" +#include "node.h" #include "config.h" /* @@ -116,47 +109,6 @@ */ DEFINE_RWLOCK(tipc_net_lock); -static struct _zone *tipc_zones[256] = { NULL, }; -struct network tipc_net = { tipc_zones }; - -struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref) -{ - return tipc_zone_select_remote_node(tipc_net.zones[tipc_zone(addr)], addr, ref); -} - -u32 tipc_net_select_router(u32 addr, u32 ref) -{ - return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref); -} - -void tipc_net_remove_as_router(u32 router) -{ - u32 z_num; - - for (z_num = 1; z_num <= tipc_max_zones; z_num++) { - if (!tipc_net.zones[z_num]) - continue; - tipc_zone_remove_as_router(tipc_net.zones[z_num], router); - } -} - -void tipc_net_send_external_routes(u32 dest) -{ - u32 z_num; - - for (z_num = 1; z_num <= tipc_max_zones; z_num++) { - if (tipc_net.zones[z_num]) - tipc_zone_send_external_routes(tipc_net.zones[z_num], dest); - } -} - -static void net_stop(void) -{ - u32 z_num; - - for (z_num = 1; z_num <= tipc_max_zones; z_num++) - tipc_zone_delete(tipc_net.zones[z_num]); -} static void net_route_named_msg(struct sk_buff *buf) { @@ -165,22 +117,18 @@ static void net_route_named_msg(struct sk_buff *buf) u32 dport; if (!msg_named(msg)) { - msg_dbg(msg, "tipc_net->drop_nam:"); buf_discard(buf); return; } dnode = addr_domain(msg_lookup_scope(msg)); dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); - dbg("tipc_net->lookup<%u,%u>-><%u,%x>\n", - msg_nametype(msg), msg_nameinst(msg), dport, dnode); if (dport) { msg_set_destnode(msg, dnode); msg_set_destport(msg, dport); tipc_net_route_msg(buf); return; } - msg_dbg(msg, "tipc_net->rej:NO NAME: "); tipc_reject_msg(buf, TIPC_ERR_NO_NAME); } @@ -196,18 +144,14 @@ void tipc_net_route_msg(struct sk_buff *buf) msg_incr_reroute_cnt(msg); if (msg_reroute_cnt(msg) > 6) { if (msg_errcode(msg)) { - msg_dbg(msg, "NET>DISC>:"); buf_discard(buf); } else { - msg_dbg(msg, "NET>REJ>:"); tipc_reject_msg(buf, msg_destport(msg) ? TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME); } return; } - msg_dbg(msg, "tipc_net->rout: "); - /* Handle message for this node */ dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); if (tipc_in_scope(dnode, tipc_own_addr)) { @@ -221,9 +165,6 @@ void tipc_net_route_msg(struct sk_buff *buf) return; } switch (msg_user(msg)) { - case ROUTE_DISTRIBUTOR: - tipc_cltr_recv_routing_table(buf); - break; case NAME_DISTRIBUTOR: tipc_named_recv(buf); break; @@ -231,14 +172,12 @@ void tipc_net_route_msg(struct sk_buff *buf) tipc_port_recv_proto_msg(buf); break; default: - msg_dbg(msg,"DROP/NET/<REC<"); buf_discard(buf); } return; } /* Handle message for another node */ - msg_dbg(msg, "NET>SEND>: "); skb_trim(buf, msg_size(msg)); tipc_link_send(buf, dnode, msg_link_selector(msg)); } @@ -259,10 +198,9 @@ int tipc_net_start(u32 addr) tipc_named_reinit(); tipc_port_reinit(); - if ((res = tipc_cltr_init()) || - (res = tipc_bclink_init())) { + res = tipc_bclink_init(); + if (res) return res; - } tipc_k_signal((Handler)tipc_subscr_start, 0); tipc_k_signal((Handler)tipc_cfg_init, 0); @@ -275,14 +213,16 @@ int tipc_net_start(u32 addr) void tipc_net_stop(void) { + struct tipc_node *node, *t_node; + if (tipc_mode != TIPC_NET_MODE) return; write_lock_bh(&tipc_net_lock); tipc_bearer_stop(); tipc_mode = TIPC_NODE_MODE; tipc_bclink_stop(); - net_stop(); + list_for_each_entry_safe(node, t_node, &tipc_node_list, list) + tipc_node_delete(node); write_unlock_bh(&tipc_net_lock); info("Left network mode\n"); } - diff --git a/net/tipc/net.h b/net/tipc/net.h index de2b9ad8f64..9eb4b9e220e 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -2,7 +2,7 @@ * net/tipc/net.h: Include file for TIPC network routing code * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,26 +37,9 @@ #ifndef _TIPC_NET_H #define _TIPC_NET_H -struct _zone; - -/** - * struct network - TIPC network structure - * @zones: array of pointers to all zones within network - */ - -struct network { - struct _zone **zones; -}; - - -extern struct network tipc_net; extern rwlock_t tipc_net_lock; -void tipc_net_remove_as_router(u32 router); -void tipc_net_send_external_routes(u32 dest); void tipc_net_route_msg(struct sk_buff *buf); -struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref); -u32 tipc_net_select_router(u32 addr, u32 ref); int tipc_net_start(u32 addr); void tipc_net_stop(void); diff --git a/net/tipc/node.c b/net/tipc/node.c index b4d87eb2dc5..2d106ef4fa4 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -2,7 +2,7 @@ * net/tipc/node.c: TIPC node management routines * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005-2006, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,25 +37,38 @@ #include "core.h" #include "config.h" #include "node.h" -#include "cluster.h" -#include "net.h" -#include "addr.h" -#include "node_subscr.h" -#include "link.h" -#include "port.h" -#include "bearer.h" #include "name_distr.h" -void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str); static void node_lost_contact(struct tipc_node *n_ptr); static void node_established_contact(struct tipc_node *n_ptr); -/* sorted list of nodes within cluster */ -static struct tipc_node *tipc_nodes = NULL; - static DEFINE_SPINLOCK(node_create_lock); -u32 tipc_own_tag = 0; +static struct hlist_head node_htable[NODE_HTABLE_SIZE]; +LIST_HEAD(tipc_node_list); +static u32 tipc_num_nodes; + +static atomic_t tipc_num_links = ATOMIC_INIT(0); +u32 tipc_own_tag; + +/** + * 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(addr))) + return NULL; + + hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) { + if (node->addr == addr) + return node; + } + return NULL; +} /** * tipc_node_create - create neighboring node @@ -69,65 +82,50 @@ u32 tipc_own_tag = 0; struct tipc_node *tipc_node_create(u32 addr) { - struct cluster *c_ptr; - struct tipc_node *n_ptr; - struct tipc_node **curr_node; + struct tipc_node *n_ptr, *temp_node; spin_lock_bh(&node_create_lock); - for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { - if (addr < n_ptr->addr) - break; - if (addr == n_ptr->addr) { - spin_unlock_bh(&node_create_lock); - return n_ptr; - } + n_ptr = tipc_node_find(addr); + if (n_ptr) { + spin_unlock_bh(&node_create_lock); + return n_ptr; } - n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); + n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); if (!n_ptr) { spin_unlock_bh(&node_create_lock); warn("Node creation failed, no memory\n"); return NULL; } - c_ptr = tipc_cltr_find(addr); - if (!c_ptr) { - c_ptr = tipc_cltr_create(addr); - } - if (!c_ptr) { - spin_unlock_bh(&node_create_lock); - kfree(n_ptr); - return NULL; - } - n_ptr->addr = addr; - spin_lock_init(&n_ptr->lock); + spin_lock_init(&n_ptr->lock); + INIT_HLIST_NODE(&n_ptr->hash); + INIT_LIST_HEAD(&n_ptr->list); INIT_LIST_HEAD(&n_ptr->nsub); - n_ptr->owner = c_ptr; - tipc_cltr_attach_node(c_ptr, n_ptr); - n_ptr->last_router = -1; - - /* Insert node into ordered list */ - for (curr_node = &tipc_nodes; *curr_node; - curr_node = &(*curr_node)->next) { - if (addr < (*curr_node)->addr) { - n_ptr->next = *curr_node; + + hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); + + list_for_each_entry(temp_node, &tipc_node_list, list) { + if (n_ptr->addr < temp_node->addr) break; - } } - (*curr_node) = n_ptr; + list_add_tail(&n_ptr->list, &temp_node->list); + + tipc_num_nodes++; + spin_unlock_bh(&node_create_lock); return n_ptr; } void tipc_node_delete(struct tipc_node *n_ptr) { - if (!n_ptr) - return; - - dbg("node %x deleted\n", n_ptr->addr); + list_del(&n_ptr->list); + hlist_del(&n_ptr->hash); kfree(n_ptr); + + tipc_num_nodes--; } @@ -147,7 +145,6 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr) l_ptr->name, l_ptr->b_ptr->net_plane); if (!active[0]) { - dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); active[0] = active[1] = l_ptr; node_established_contact(n_ptr); return; @@ -226,59 +223,32 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr) node_lost_contact(n_ptr); } -int tipc_node_has_active_links(struct tipc_node *n_ptr) +int tipc_node_active_links(struct tipc_node *n_ptr) { return n_ptr->active_links[0] != NULL; } -int tipc_node_has_redundant_links(struct tipc_node *n_ptr) +int tipc_node_redundant_links(struct tipc_node *n_ptr) { return n_ptr->working_links > 1; } -static int tipc_node_has_active_routes(struct tipc_node *n_ptr) -{ - return n_ptr && (n_ptr->last_router >= 0); -} - int tipc_node_is_up(struct tipc_node *n_ptr) { - return tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr); + return tipc_node_active_links(n_ptr); } -struct tipc_node *tipc_node_attach_link(struct link *l_ptr) +void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr) { - struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr); - - if (!n_ptr) - n_ptr = tipc_node_create(l_ptr->addr); - if (n_ptr) { - u32 bearer_id = l_ptr->b_ptr->identity; - char addr_string[16]; - - if (n_ptr->link_cnt >= 2) { - err("Attempt to create third link to %s\n", - tipc_addr_string_fill(addr_string, n_ptr->addr)); - return NULL; - } - - if (!n_ptr->links[bearer_id]) { - n_ptr->links[bearer_id] = l_ptr; - tipc_net.zones[tipc_zone(l_ptr->addr)]->links++; - n_ptr->link_cnt++; - return n_ptr; - } - err("Attempt to establish second link on <%s> to %s\n", - l_ptr->b_ptr->publ.name, - tipc_addr_string_fill(addr_string, l_ptr->addr)); - } - return NULL; + 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 link *l_ptr) { n_ptr->links[l_ptr->b_ptr->identity] = NULL; - tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; + atomic_dec(&tipc_num_links); n_ptr->link_cnt--; } @@ -330,48 +300,16 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) static void node_established_contact(struct tipc_node *n_ptr) { - struct cluster *c_ptr; - - dbg("node_established_contact:-> %x\n", n_ptr->addr); - if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { - tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); - } + tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); /* Syncronize broadcast acks */ n_ptr->bclink.acked = tipc_bclink_get_last_sent(); - if (is_slave(tipc_own_addr)) - return; - if (!in_own_cluster(n_ptr->addr)) { - /* Usage case 1 (see above) */ - c_ptr = tipc_cltr_find(tipc_own_addr); - if (!c_ptr) - c_ptr = tipc_cltr_create(tipc_own_addr); - if (c_ptr) - tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, - tipc_max_nodes); - return; - } - - c_ptr = n_ptr->owner; - if (is_slave(n_ptr->addr)) { - /* Usage case 2 (see above) */ - tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); - tipc_cltr_send_local_routes(c_ptr, n_ptr->addr); - return; - } - if (n_ptr->bclink.supported) { - tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); + tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr); if (n_ptr->addr < tipc_own_addr) tipc_own_tag++; } - - /* Case 3 (see above) */ - tipc_net_send_external_routes(n_ptr->addr); - tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr); - tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, - tipc_highest_allowed_slave); } static void node_cleanup_finished(unsigned long node_addr) @@ -390,15 +328,13 @@ static void node_cleanup_finished(unsigned long node_addr) static void node_lost_contact(struct tipc_node *n_ptr) { - struct cluster *c_ptr; - struct tipc_node_subscr *ns, *tns; 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; + struct sk_buff *buf = n_ptr->bclink.deferred_head; n_ptr->bclink.deferred_head = buf->next; buf_discard(buf); } @@ -406,41 +342,14 @@ static void node_lost_contact(struct tipc_node *n_ptr) buf_discard(n_ptr->bclink.defragm); n_ptr->bclink.defragm = NULL; } - if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { - tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); - } - /* Update routing tables */ - if (is_slave(tipc_own_addr)) { - tipc_net_remove_as_router(n_ptr->addr); - } else { - if (!in_own_cluster(n_ptr->addr)) { - /* Case 4 (see above) */ - c_ptr = tipc_cltr_find(tipc_own_addr); - tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, - tipc_max_nodes); - } else { - /* Case 5 (see above) */ - c_ptr = tipc_cltr_find(n_ptr->addr); - if (is_slave(n_ptr->addr)) { - tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, - tipc_max_nodes); - } else { - if (n_ptr->bclink.supported) { - tipc_nmap_remove(&tipc_cltr_bcast_nodes, - n_ptr->addr); - if (n_ptr->addr < tipc_own_addr) - tipc_own_tag--; - } - tipc_net_remove_as_router(n_ptr->addr); - tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, - LOWEST_SLAVE, - tipc_highest_allowed_slave); - } - } + 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--; } - if (tipc_node_has_active_routes(n_ptr)) - return; info("Lost contact with %s\n", tipc_addr_string_fill(addr_string, n_ptr->addr)); @@ -456,12 +365,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) } /* Notify subscribers */ - list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { - ns->node = NULL; - list_del_init(&ns->nodesub_list); - tipc_k_signal((Handler)ns->handle_node_down, - (unsigned long)ns->usr_handle); - } + tipc_nodesub_notify(n_ptr); /* Prevent re-contact with node until all cleanup is done */ @@ -469,125 +373,6 @@ static void node_lost_contact(struct tipc_node *n_ptr) tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); } -/** - * tipc_node_select_next_hop - find the next-hop node for a message - * - * Called by when cluster local lookup has failed. - */ - -struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector) -{ - struct tipc_node *n_ptr; - u32 router_addr; - - if (!tipc_addr_domain_valid(addr)) - return NULL; - - /* Look for direct link to destination processsor */ - n_ptr = tipc_node_find(addr); - if (n_ptr && tipc_node_has_active_links(n_ptr)) - return n_ptr; - - /* Cluster local system nodes *must* have direct links */ - if (!is_slave(addr) && in_own_cluster(addr)) - return NULL; - - /* Look for cluster local router with direct link to node */ - router_addr = tipc_node_select_router(n_ptr, selector); - if (router_addr) - return tipc_node_select(router_addr, selector); - - /* Slave nodes can only be accessed within own cluster via a - known router with direct link -- if no router was found,give up */ - if (is_slave(addr)) - return NULL; - - /* Inter zone/cluster -- find any direct link to remote cluster */ - addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); - n_ptr = tipc_net_select_remote_node(addr, selector); - if (n_ptr && tipc_node_has_active_links(n_ptr)) - return n_ptr; - - /* Last resort -- look for any router to anywhere in remote zone */ - router_addr = tipc_net_select_router(addr, selector); - if (router_addr) - return tipc_node_select(router_addr, selector); - - return NULL; -} - -/** - * tipc_node_select_router - select router to reach specified node - * - * Uses a deterministic and fair algorithm for selecting router node. - */ - -u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref) -{ - u32 ulim; - u32 mask; - u32 start; - u32 r; - - if (!n_ptr) - return 0; - - if (n_ptr->last_router < 0) - return 0; - ulim = ((n_ptr->last_router + 1) * 32) - 1; - - /* Start entry must be random */ - mask = tipc_max_nodes; - while (mask > ulim) - mask >>= 1; - start = ref & mask; - r = start; - - /* Lookup upwards with wrap-around */ - do { - if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) - break; - } while (++r <= ulim); - if (r > ulim) { - r = 1; - do { - if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) - break; - } while (++r < start); - assert(r != start); - } - assert(r && (r <= ulim)); - return tipc_addr(own_zone(), own_cluster(), r); -} - -void tipc_node_add_router(struct tipc_node *n_ptr, u32 router) -{ - u32 r_num = tipc_node(router); - - n_ptr->routers[r_num / 32] = - ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]); - n_ptr->last_router = tipc_max_nodes / 32; - while ((--n_ptr->last_router >= 0) && - !n_ptr->routers[n_ptr->last_router]); -} - -void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router) -{ - u32 r_num = tipc_node(router); - - if (n_ptr->last_router < 0) - return; /* No routes */ - - n_ptr->routers[r_num / 32] = - ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32])); - n_ptr->last_router = tipc_max_nodes / 32; - while ((--n_ptr->last_router >= 0) && - !n_ptr->routers[n_ptr->last_router]); - - if (!tipc_node_is_up(n_ptr)) - node_lost_contact(n_ptr); -} - struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) { u32 domain; @@ -605,15 +390,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) " (network address)"); read_lock_bh(&tipc_net_lock); - if (!tipc_nodes) { + if (!tipc_num_nodes) { read_unlock_bh(&tipc_net_lock); return tipc_cfg_reply_none(); } - /* For now, get space for all other nodes - (will need to modify this when slave nodes are supported */ + /* For now, get space for all other nodes */ - payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); + payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; if (payload_size > 32768u) { read_unlock_bh(&tipc_net_lock); return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED @@ -627,7 +411,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) /* Add TLVs for all nodes in scope */ - for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { + list_for_each_entry(n_ptr, &tipc_node_list, list) { if (!tipc_in_scope(domain, n_ptr->addr)) continue; node_info.addr = htonl(n_ptr->addr); @@ -664,7 +448,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) /* Get space for all unicast links + multicast link */ payload_size = TLV_SPACE(sizeof(link_info)) * - (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); + (atomic_read(&tipc_num_links) + 1); if (payload_size > 32768u) { read_unlock_bh(&tipc_net_lock); return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED @@ -678,14 +462,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_own_addr & 0xfffff00); + 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 */ - for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { + list_for_each_entry(n_ptr, &tipc_node_list, list) { u32 i; if (!tipc_in_scope(domain, n_ptr->addr)) diff --git a/net/tipc/node.h b/net/tipc/node.h index fff331b2d26..5c61afc7a0b 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -2,7 +2,7 @@ * net/tipc/node.h: Include file for TIPC node management routines * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,15 +39,15 @@ #include "node_subscr.h" #include "addr.h" -#include "cluster.h" +#include "net.h" #include "bearer.h" /** * struct tipc_node - TIPC node structure * @addr: network address of node * @lock: spinlock governing access to structure - * @owner: pointer to cluster that node belongs to - * @next: pointer to next node in sorted list of cluster's nodes + * @hash: links to adjacent nodes in unsorted hash chain + * @list: links to adjacent nodes in sorted list of cluster's nodes * @nsub: list of "node down" subscriptions monitoring node * @active_links: pointers to active links to node * @links: pointers to all links to node @@ -55,8 +55,6 @@ * @cleanup_required: non-zero if cleaning up after a prior loss of contact * @link_cnt: number of links to node * @permit_changeover: non-zero if node has redundant links to this system - * @routers: bitmap (used for multicluster communication) - * @last_router: (used for multicluster communication) * @bclink: broadcast-related info * @supported: non-zero if node supports TIPC b'cast capability * @acked: sequence # of last outbound b'cast message acknowledged by node @@ -72,8 +70,8 @@ struct tipc_node { u32 addr; spinlock_t lock; - struct cluster *owner; - struct tipc_node *next; + struct hlist_node hash; + struct list_head list; struct list_head nsub; struct link *active_links[2]; struct link *links[MAX_BEARERS]; @@ -81,8 +79,6 @@ struct tipc_node { int working_links; int cleanup_required; int permit_changeover; - u32 routers[512/32]; - int last_router; struct { int supported; u32 acked; @@ -96,44 +92,35 @@ struct tipc_node { } bclink; }; +#define NODE_HTABLE_SIZE 512 +extern struct list_head tipc_node_list; + +/* + * 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 inline unsigned int tipc_hashfn(u32 addr) +{ + return addr & (NODE_HTABLE_SIZE - 1); +} + extern u32 tipc_own_tag; +struct tipc_node *tipc_node_find(u32 addr); struct tipc_node *tipc_node_create(u32 addr); void tipc_node_delete(struct tipc_node *n_ptr); -struct tipc_node *tipc_node_attach_link(struct link *l_ptr); +void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr); void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr); void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr); void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr); -int tipc_node_has_active_links(struct tipc_node *n_ptr); -int tipc_node_has_redundant_links(struct tipc_node *n_ptr); -u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref); -struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector); +int tipc_node_active_links(struct tipc_node *n_ptr); +int tipc_node_redundant_links(struct tipc_node *n_ptr); int tipc_node_is_up(struct tipc_node *n_ptr); -void tipc_node_add_router(struct tipc_node *n_ptr, u32 router); -void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router); struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); -static inline struct tipc_node *tipc_node_find(u32 addr) -{ - if (likely(in_own_cluster(addr))) - return tipc_local_nodes[tipc_node(addr)]; - else if (tipc_addr_domain_valid(addr)) { - struct cluster *c_ptr = tipc_cltr_find(addr); - - if (c_ptr) - return c_ptr->nodes[tipc_node(addr)]; - } - return NULL; -} - -static inline struct tipc_node *tipc_node_select(u32 addr, u32 selector) -{ - if (likely(in_own_cluster(addr))) - return tipc_local_nodes[tipc_node(addr)]; - return tipc_node_select_next_hop(addr, selector); -} - static inline void tipc_node_lock(struct tipc_node *n_ptr) { spin_lock_bh(&n_ptr->lock); diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index 19194d476a9..c3c2815ae63 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c @@ -2,7 +2,7 @@ * net/tipc/node_subscr.c: TIPC "node down" subscription handling * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,10 +35,8 @@ */ #include "core.h" -#include "dbg.h" #include "node_subscr.h" #include "node.h" -#include "addr.h" /** * tipc_nodesub_subscribe - create "node down" subscription for specified node @@ -78,3 +76,22 @@ void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub) list_del_init(&node_sub->nodesub_list); tipc_node_unlock(node_sub->node); } + +/** + * tipc_nodesub_notify - notify subscribers that a node is unreachable + * + * Note: node is locked by caller + */ + +void tipc_nodesub_notify(struct tipc_node *node) +{ + struct tipc_node_subscr *ns; + + list_for_each_entry(ns, &node->nsub, nodesub_list) { + if (ns->handle_node_down) { + tipc_k_signal((Handler)ns->handle_node_down, + (unsigned long)ns->usr_handle); + ns->handle_node_down = NULL; + } + } +} diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h index 006ed739f51..4bc2ca0867a 100644 --- a/net/tipc/node_subscr.h +++ b/net/tipc/node_subscr.h @@ -2,7 +2,7 @@ * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,5 +59,6 @@ struct tipc_node_subscr { void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, void *usr_handle, net_ev_handler handle_down); void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub); +void tipc_nodesub_notify(struct tipc_node *node); #endif diff --git a/net/tipc/port.c b/net/tipc/port.c index 82092eaa153..c68dc956a42 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -2,7 +2,7 @@ * net/tipc/port.c: TIPC port code * * Copyright (c) 1992-2007, 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 @@ -36,15 +36,8 @@ #include "core.h" #include "config.h" -#include "dbg.h" #include "port.h" -#include "addr.h" -#include "link.h" -#include "node.h" #include "name_table.h" -#include "user_reg.h" -#include "msg.h" -#include "bcast.h" /* Connection management: */ #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ @@ -53,55 +46,42 @@ #define MAX_REJECT_SIZE 1024 -static struct sk_buff *msg_queue_head = NULL; -static struct sk_buff *msg_queue_tail = NULL; +static struct sk_buff *msg_queue_head; +static struct sk_buff *msg_queue_tail; DEFINE_SPINLOCK(tipc_port_list_lock); static DEFINE_SPINLOCK(queue_lock); static LIST_HEAD(ports); static void port_handle_node_down(unsigned long ref); -static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err); -static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err); +static struct sk_buff *port_build_self_abort_msg(struct tipc_port *, u32 err); +static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *, u32 err); static void port_timeout(unsigned long ref); -static u32 port_peernode(struct port *p_ptr) +static u32 port_peernode(struct tipc_port *p_ptr) { - return msg_destnode(&p_ptr->publ.phdr); + return msg_destnode(&p_ptr->phdr); } -static u32 port_peerport(struct port *p_ptr) +static u32 port_peerport(struct tipc_port *p_ptr) { - return msg_destport(&p_ptr->publ.phdr); -} - -static u32 port_out_seqno(struct port *p_ptr) -{ - return msg_transp_seqno(&p_ptr->publ.phdr); -} - -static void port_incr_out_seqno(struct port *p_ptr) -{ - struct tipc_msg *m = &p_ptr->publ.phdr; - - if (likely(!msg_routed(m))) - return; - msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1)); + return msg_destport(&p_ptr->phdr); } /** * tipc_multicast - send a multicast message to local and remote destinations */ -int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, - u32 num_sect, struct iovec const *msg_sect) +int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, + u32 num_sect, struct iovec const *msg_sect, + unsigned int total_len) { struct tipc_msg *hdr; struct sk_buff *buf; struct sk_buff *ibuf = NULL; struct port_list dports = {0, NULL, }; - struct port *oport = tipc_port_deref(ref); + struct tipc_port *oport = tipc_port_deref(ref); int ext_targets; int res; @@ -110,13 +90,16 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, /* Create multicast message */ - hdr = &oport->publ.phdr; + hdr = &oport->phdr; msg_set_type(hdr, TIPC_MCAST_MSG); + msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE); + msg_set_destport(hdr, 0); + msg_set_destnode(hdr, 0); msg_set_nametype(hdr, seq->type); msg_set_namelower(hdr, seq->lower); msg_set_nameupper(hdr, seq->upper); msg_set_hdr_sz(hdr, MCAST_H_SIZE); - res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, + res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, !oport->user_port, &buf); if (unlikely(!buf)) return res; @@ -138,9 +121,8 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, } } res = tipc_bclink_send_msg(buf); - if ((res < 0) && (dports.count != 0)) { + if ((res < 0) && (dports.count != 0)) buf_discard(ibuf); - } } else { ibuf = buf; } @@ -162,7 +144,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) { - struct tipc_msg* msg; + struct tipc_msg *msg; struct port_list dports = {0, NULL, }; struct port_list *item = dp; int cnt = 0; @@ -183,6 +165,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) /* Deliver a copy of message to each destination port */ if (dp->count != 0) { + msg_set_destnode(msg, tipc_own_addr); if (dp->count == 1) { msg_set_destport(msg, dp->ports[0]); tipc_port_recv_msg(buf); @@ -195,13 +178,11 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) if (b == NULL) { warn("Unable to deliver multicast message(s)\n"); - msg_dbg(msg, "LOST:"); goto exit; } - if ((index == 0) && (cnt != 0)) { + if ((index == 0) && (cnt != 0)) item = item->next; - } - msg_set_destport(buf_msg(b),item->ports[index]); + msg_set_destport(buf_msg(b), item->ports[index]); tipc_port_recv_msg(b); } } @@ -221,7 +202,7 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, void (*wakeup)(struct tipc_port *), const u32 importance) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct tipc_msg *msg; u32 ref; @@ -230,21 +211,19 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, warn("Port creation failed, no memory\n"); return NULL; } - ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock); + ref = tipc_ref_acquire(p_ptr, &p_ptr->lock); if (!ref) { warn("Port creation failed, reference table exhausted\n"); kfree(p_ptr); return NULL; } - p_ptr->publ.usr_handle = usr_handle; - p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; - p_ptr->publ.ref = ref; - msg = &p_ptr->publ.phdr; + p_ptr->usr_handle = 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); msg_set_origport(msg, ref); - p_ptr->last_in_seqno = 41; - p_ptr->sent = 1; INIT_LIST_HEAD(&p_ptr->wait_list); INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); p_ptr->dispatcher = dispatcher; @@ -256,12 +235,12 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, INIT_LIST_HEAD(&p_ptr->port_list); list_add_tail(&p_ptr->port_list, &ports); spin_unlock_bh(&tipc_port_list_lock); - return &(p_ptr->publ); + return p_ptr; } int tipc_deleteport(u32 ref) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct sk_buff *buf = NULL; tipc_withdraw(ref, 0, NULL); @@ -273,14 +252,11 @@ int tipc_deleteport(u32 ref) tipc_port_unlock(p_ptr); k_cancel_timer(&p_ptr->timer); - if (p_ptr->publ.connected) { + if (p_ptr->connected) { buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); tipc_nodesub_unsubscribe(&p_ptr->subscription); } - if (p_ptr->user_port) { - tipc_reg_remove_port(p_ptr->user_port); - kfree(p_ptr->user_port); - } + kfree(p_ptr->user_port); spin_lock_bh(&tipc_port_list_lock); list_del(&p_ptr->port_list); @@ -288,19 +264,18 @@ int tipc_deleteport(u32 ref) spin_unlock_bh(&tipc_port_list_lock); k_term_timer(&p_ptr->timer); kfree(p_ptr); - dbg("Deleted port %u\n", ref); tipc_net_route_msg(buf); return 0; } -static int port_unreliable(struct port *p_ptr) +static int port_unreliable(struct tipc_port *p_ptr) { - return msg_src_droppable(&p_ptr->publ.phdr); + return msg_src_droppable(&p_ptr->phdr); } int tipc_portunreliable(u32 ref, unsigned int *isunreliable) { - struct port *p_ptr; + struct tipc_port *p_ptr; p_ptr = tipc_port_lock(ref); if (!p_ptr) @@ -312,24 +287,24 @@ int tipc_portunreliable(u32 ref, unsigned int *isunreliable) int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) { - struct port *p_ptr; + struct tipc_port *p_ptr; p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; - msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0)); + msg_set_src_droppable(&p_ptr->phdr, (isunreliable != 0)); tipc_port_unlock(p_ptr); return 0; } -static int port_unreturnable(struct port *p_ptr) +static int port_unreturnable(struct tipc_port *p_ptr) { - return msg_dest_droppable(&p_ptr->publ.phdr); + return msg_dest_droppable(&p_ptr->phdr); } int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) { - struct port *p_ptr; + struct tipc_port *p_ptr; p_ptr = tipc_port_lock(ref); if (!p_ptr) @@ -341,12 +316,12 @@ int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) { - struct port *p_ptr; + struct tipc_port *p_ptr; p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; - msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0)); + msg_set_dest_droppable(&p_ptr->phdr, (isunrejectable != 0)); tipc_port_unlock(p_ptr); return 0; } @@ -359,7 +334,7 @@ int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, u32 origport, u32 orignode, u32 usr, u32 type, u32 err, - u32 seqno, u32 ack) + u32 ack) { struct sk_buff *buf; struct tipc_msg *msg; @@ -372,9 +347,7 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, msg_set_destport(msg, destport); msg_set_origport(msg, origport); msg_set_orignode(msg, orignode); - msg_set_transp_seqno(msg, seqno); msg_set_msgcnt(msg, ack); - msg_dbg(msg, "PORT>SEND>:"); } return buf; } @@ -392,7 +365,6 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) data_sz = MAX_REJECT_SIZE; if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE)) imp++; - msg_dbg(msg, "port->rej: "); /* discard rejected message if it shouldn't be returned to sender */ if (msg_errcode(msg) || msg_dest_droppable(msg)) { @@ -429,10 +401,10 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) /* send self-abort message when rejecting on a connected port */ if (msg_connected(msg)) { struct sk_buff *abuf = NULL; - struct port *p_ptr = tipc_port_lock(msg_destport(msg)); + struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); if (p_ptr) { - if (p_ptr->publ.connected) + if (p_ptr->connected) abuf = port_build_self_abort_msg(p_ptr, err); tipc_port_unlock(p_ptr); } @@ -445,14 +417,14 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) return data_sz; } -int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, +int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, struct iovec const *msg_sect, u32 num_sect, - int err) + unsigned int total_len, int err) { struct sk_buff *buf; int res; - res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, + res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, !p_ptr->user_port, &buf); if (!buf) return res; @@ -462,13 +434,13 @@ int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, static void port_timeout(unsigned long ref) { - struct port *p_ptr = tipc_port_lock(ref); + struct tipc_port *p_ptr = tipc_port_lock(ref); struct sk_buff *buf = NULL; if (!p_ptr) return; - if (!p_ptr->publ.connected) { + if (!p_ptr->connected) { tipc_port_unlock(p_ptr); return; } @@ -479,14 +451,12 @@ static void port_timeout(unsigned long ref) } else { buf = port_build_proto_msg(port_peerport(p_ptr), port_peernode(p_ptr), - p_ptr->publ.ref, + p_ptr->ref, tipc_own_addr, CONN_MANAGER, CONN_PROBE, TIPC_OK, - port_out_seqno(p_ptr), 0); - port_incr_out_seqno(p_ptr); p_ptr->probing_state = PROBING; k_start_timer(&p_ptr->timer, p_ptr->probing_interval); } @@ -497,8 +467,8 @@ static void port_timeout(unsigned long ref) static void port_handle_node_down(unsigned long ref) { - struct port *p_ptr = tipc_port_lock(ref); - struct sk_buff* buf = NULL; + struct tipc_port *p_ptr = tipc_port_lock(ref); + struct sk_buff *buf = NULL; if (!p_ptr) return; @@ -508,75 +478,71 @@ static void port_handle_node_down(unsigned long ref) } -static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err) +static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err) { - u32 imp = msg_importance(&p_ptr->publ.phdr); + u32 imp = msg_importance(&p_ptr->phdr); - if (!p_ptr->publ.connected) + if (!p_ptr->connected) return NULL; if (imp < TIPC_CRITICAL_IMPORTANCE) imp++; - return port_build_proto_msg(p_ptr->publ.ref, + return port_build_proto_msg(p_ptr->ref, tipc_own_addr, port_peerport(p_ptr), port_peernode(p_ptr), imp, TIPC_CONN_MSG, err, - p_ptr->last_in_seqno + 1, 0); } -static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err) +static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err) { - u32 imp = msg_importance(&p_ptr->publ.phdr); + u32 imp = msg_importance(&p_ptr->phdr); - if (!p_ptr->publ.connected) + 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->publ.ref, + p_ptr->ref, tipc_own_addr, imp, TIPC_CONN_MSG, err, - port_out_seqno(p_ptr), 0); } void tipc_port_recv_proto_msg(struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); - struct port *p_ptr = tipc_port_lock(msg_destport(msg)); + struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); u32 err = TIPC_OK; struct sk_buff *r_buf = NULL; struct sk_buff *abort_buf = NULL; - msg_dbg(msg, "PORT<RECV<:"); - if (!p_ptr) { err = TIPC_ERR_NO_PORT; - } else if (p_ptr->publ.connected) { + } 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->publ.congested && + p_ptr->congested && p_ptr->wakeup; p_ptr->acked += msg_msgcnt(msg); if (tipc_port_congested(p_ptr)) goto exit; - p_ptr->publ.congested = 0; + p_ptr->congested = 0; if (!wakeup) goto exit; - p_ptr->wakeup(&p_ptr->publ); + p_ptr->wakeup(p_ptr); goto exit; } - } else if (p_ptr->publ.published) { + } else if (p_ptr->published) { err = TIPC_ERR_NO_PORT; } if (err) { @@ -587,7 +553,6 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG, err, - 0, 0); goto exit; } @@ -601,11 +566,9 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) CONN_MANAGER, CONN_PROBE_REPLY, TIPC_OK, - port_out_seqno(p_ptr), 0); } p_ptr->probing_state = CONFIRMED; - port_incr_out_seqno(p_ptr); exit: if (p_ptr) tipc_port_unlock(p_ptr); @@ -614,30 +577,29 @@ exit: buf_discard(buf); } -static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id) +static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id) { struct publication *publ; if (full_id) tipc_printf(buf, "<%u.%u.%u:%u>:", tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), - tipc_node(tipc_own_addr), p_ptr->publ.ref); + tipc_node(tipc_own_addr), p_ptr->ref); else - tipc_printf(buf, "%-10u:", p_ptr->publ.ref); + tipc_printf(buf, "%-10u:", p_ptr->ref); - if (p_ptr->publ.connected) { + if (p_ptr->connected) { u32 dport = port_peerport(p_ptr); u32 destnode = port_peernode(p_ptr); tipc_printf(buf, " connected to <%u.%u.%u:%u>", tipc_zone(destnode), tipc_cluster(destnode), tipc_node(destnode), dport); - if (p_ptr->publ.conn_type != 0) + if (p_ptr->conn_type != 0) tipc_printf(buf, " via {%u,%u}", - p_ptr->publ.conn_type, - p_ptr->publ.conn_instance); - } - else if (p_ptr->publ.published) { + p_ptr->conn_type, + p_ptr->conn_instance); + } else if (p_ptr->published) { tipc_printf(buf, " bound to"); list_for_each_entry(publ, &p_ptr->publications, pport_list) { if (publ->lower == publ->upper) @@ -658,7 +620,7 @@ struct sk_buff *tipc_port_get_ports(void) struct sk_buff *buf; struct tlv_desc *rep_tlv; struct print_buf pb; - struct port *p_ptr; + struct tipc_port *p_ptr; int str_len; buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); @@ -669,9 +631,9 @@ struct sk_buff *tipc_port_get_ports(void) tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); spin_lock_bh(&tipc_port_list_lock); list_for_each_entry(p_ptr, &ports, port_list) { - spin_lock_bh(p_ptr->publ.lock); + spin_lock_bh(p_ptr->lock); port_print(p_ptr, &pb, 0); - spin_unlock_bh(p_ptr->publ.lock); + spin_unlock_bh(p_ptr->lock); } spin_unlock_bh(&tipc_port_list_lock); str_len = tipc_printbuf_validate(&pb); @@ -684,12 +646,12 @@ struct sk_buff *tipc_port_get_ports(void) void tipc_port_reinit(void) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct tipc_msg *msg; spin_lock_bh(&tipc_port_list_lock); list_for_each_entry(p_ptr, &ports, port_list) { - msg = &p_ptr->publ.phdr; + msg = &p_ptr->phdr; if (msg_orignode(msg) == tipc_own_addr) break; msg_set_prevnode(msg, tipc_own_addr); @@ -714,7 +676,7 @@ static void port_dispatcher_sigh(void *dummy) spin_unlock_bh(&queue_lock); while (buf) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct user_port *up_ptr; struct tipc_portid orig; struct tipc_name_seq dseq; @@ -739,8 +701,8 @@ static void port_dispatcher_sigh(void *dummy) orig.node = msg_orignode(msg); up_ptr = p_ptr->user_port; usr_handle = up_ptr->usr_handle; - connected = p_ptr->publ.connected; - published = p_ptr->publ.published; + connected = p_ptr->connected; + published = p_ptr->published; if (unlikely(msg_errcode(msg))) goto err; @@ -751,6 +713,7 @@ static void port_dispatcher_sigh(void *dummy) tipc_conn_msg_event cb = up_ptr->conn_msg_cb; u32 peer_port = port_peerport(p_ptr); u32 peer_node = port_peernode(p_ptr); + u32 dsz; tipc_port_unlock(p_ptr); if (unlikely(!cb)) @@ -761,13 +724,14 @@ static void port_dispatcher_sigh(void *dummy) } else if ((msg_origport(msg) != peer_port) || (msg_orignode(msg) != peer_node)) goto reject; - if (unlikely(++p_ptr->publ.conn_unacked >= - TIPC_FLOW_CONTROL_WIN)) + dsz = msg_data_sz(msg); + if (unlikely(dsz && + (++p_ptr->conn_unacked >= + TIPC_FLOW_CONTROL_WIN))) tipc_acknowledge(dref, - p_ptr->publ.conn_unacked); + p_ptr->conn_unacked); skb_pull(buf, msg_hdr_sz(msg)); - cb(usr_handle, dref, &buf, msg_data(msg), - msg_data_sz(msg)); + cb(usr_handle, dref, &buf, msg_data(msg), dsz); break; } case TIPC_DIRECT_MSG:{ @@ -891,7 +855,7 @@ static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) static void port_wakeup_sh(unsigned long ref) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct user_port *up_ptr; tipc_continue_event cb = NULL; void *uh = NULL; @@ -917,14 +881,14 @@ static void port_wakeup(struct tipc_port *p_ptr) void tipc_acknowledge(u32 ref, u32 ack) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct sk_buff *buf = NULL; p_ptr = tipc_port_lock(ref); if (!p_ptr) return; - if (p_ptr->publ.connected) { - p_ptr->publ.conn_unacked -= ack; + if (p_ptr->connected) { + p_ptr->conn_unacked -= ack; buf = port_build_proto_msg(port_peerport(p_ptr), port_peernode(p_ptr), ref, @@ -932,7 +896,6 @@ void tipc_acknowledge(u32 ref, u32 ack) CONN_MANAGER, CONN_ACK, TIPC_OK, - port_out_seqno(p_ptr), ack); } tipc_port_unlock(p_ptr); @@ -940,12 +903,10 @@ void tipc_acknowledge(u32 ref, u32 ack) } /* - * tipc_createport(): user level call. Will add port to - * registry if non-zero user_ref. + * tipc_createport(): user level call. */ -int tipc_createport(u32 user_ref, - void *usr_handle, +int tipc_createport(void *usr_handle, unsigned int importance, tipc_msg_err_event error_cb, tipc_named_msg_err_event named_error_cb, @@ -957,14 +918,14 @@ int tipc_createport(u32 user_ref, u32 *portref) { struct user_port *up_ptr; - struct port *p_ptr; + struct tipc_port *p_ptr; up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); if (!up_ptr) { warn("Port creation failed, no memory\n"); return -ENOMEM; } - p_ptr = (struct port *)tipc_createport_raw(NULL, port_dispatcher, + p_ptr = (struct tipc_port *)tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance); if (!p_ptr) { kfree(up_ptr); @@ -972,9 +933,8 @@ int tipc_createport(u32 user_ref, } p_ptr->user_port = up_ptr; - up_ptr->user_ref = user_ref; up_ptr->usr_handle = usr_handle; - up_ptr->ref = p_ptr->publ.ref; + up_ptr->ref = p_ptr->ref; up_ptr->err_cb = error_cb; up_ptr->named_err_cb = named_error_cb; up_ptr->conn_err_cb = conn_error_cb; @@ -982,35 +942,26 @@ int tipc_createport(u32 user_ref, up_ptr->named_msg_cb = named_msg_cb; up_ptr->conn_msg_cb = conn_msg_cb; up_ptr->continue_event_cb = continue_event_cb; - INIT_LIST_HEAD(&up_ptr->uport_list); - tipc_reg_add_port(up_ptr); - *portref = p_ptr->publ.ref; + *portref = p_ptr->ref; tipc_port_unlock(p_ptr); return 0; } -int tipc_ownidentity(u32 ref, struct tipc_portid *id) -{ - id->ref = ref; - id->node = tipc_own_addr; - return 0; -} - int tipc_portimportance(u32 ref, unsigned int *importance) { - struct port *p_ptr; + struct tipc_port *p_ptr; p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; - *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr); + *importance = (unsigned int)msg_importance(&p_ptr->phdr); tipc_port_unlock(p_ptr); return 0; } int tipc_set_portimportance(u32 ref, unsigned int imp) { - struct port *p_ptr; + struct tipc_port *p_ptr; if (imp > TIPC_CRITICAL_IMPORTANCE) return -EINVAL; @@ -1018,7 +969,7 @@ int tipc_set_portimportance(u32 ref, unsigned int imp) p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; - msg_set_importance(&p_ptr->publ.phdr, (u32)imp); + msg_set_importance(&p_ptr->phdr, (u32)imp); tipc_port_unlock(p_ptr); return 0; } @@ -1026,7 +977,7 @@ int tipc_set_portimportance(u32 ref, unsigned int imp) int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct publication *publ; u32 key; int res = -EINVAL; @@ -1035,10 +986,7 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) if (!p_ptr) return -EINVAL; - dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " - "lower = %u, upper = %u\n", - ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); - if (p_ptr->publ.connected) + if (p_ptr->connected) goto exit; if (seq->lower > seq->upper) goto exit; @@ -1050,11 +998,11 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) goto exit; } publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, - scope, p_ptr->publ.ref, key); + scope, p_ptr->ref, key); if (publ) { list_add(&publ->pport_list, &p_ptr->publications); p_ptr->pub_count++; - p_ptr->publ.published = 1; + p_ptr->published = 1; res = 0; } exit: @@ -1064,7 +1012,7 @@ exit: int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct publication *publ; struct publication *tpubl; int res = -EINVAL; @@ -1097,49 +1045,46 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) } } if (list_empty(&p_ptr->publications)) - p_ptr->publ.published = 0; + p_ptr->published = 0; tipc_port_unlock(p_ptr); return res; } int tipc_connect2port(u32 ref, struct tipc_portid const *peer) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct tipc_msg *msg; int res = -EINVAL; p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; - if (p_ptr->publ.published || p_ptr->publ.connected) + if (p_ptr->published || p_ptr->connected) goto exit; if (!peer->ref) goto exit; - msg = &p_ptr->publ.phdr; + msg = &p_ptr->phdr; msg_set_destnode(msg, peer->node); msg_set_destport(msg, peer->ref); msg_set_orignode(msg, tipc_own_addr); - msg_set_origport(msg, p_ptr->publ.ref); - msg_set_transp_seqno(msg, 42); + msg_set_origport(msg, p_ptr->ref); msg_set_type(msg, TIPC_CONN_MSG); - if (!may_route(peer->node)) - msg_set_hdr_sz(msg, SHORT_H_SIZE); - else - msg_set_hdr_sz(msg, LONG_H_SIZE); + msg_set_lookup_scope(msg, 0); + msg_set_hdr_sz(msg, SHORT_H_SIZE); p_ptr->probing_interval = PROBING_INTERVAL; p_ptr->probing_state = CONFIRMED; - p_ptr->publ.connected = 1; + p_ptr->connected = 1; k_start_timer(&p_ptr->timer, p_ptr->probing_interval); - tipc_nodesub_subscribe(&p_ptr->subscription,peer->node, + tipc_nodesub_subscribe(&p_ptr->subscription, peer->node, (void *)(unsigned long)ref, (net_ev_handler)port_handle_node_down); res = 0; exit: tipc_port_unlock(p_ptr); - p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref); + p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref); return res; } @@ -1157,7 +1102,7 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr) tp_ptr->connected = 0; /* let timer expire on it's own to avoid deadlock! */ tipc_nodesub_unsubscribe( - &((struct port *)tp_ptr)->subscription); + &((struct tipc_port *)tp_ptr)->subscription); res = 0; } else { res = -ENOTCONN; @@ -1172,7 +1117,7 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr) int tipc_disconnect(u32 ref) { - struct port *p_ptr; + struct tipc_port *p_ptr; int res; p_ptr = tipc_port_lock(ref); @@ -1188,15 +1133,15 @@ int tipc_disconnect(u32 ref) */ int tipc_shutdown(u32 ref) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct sk_buff *buf = NULL; p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; - if (p_ptr->publ.connected) { - u32 imp = msg_importance(&p_ptr->publ.phdr); + 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), @@ -1206,7 +1151,6 @@ int tipc_shutdown(u32 ref) imp, TIPC_CONN_MSG, TIPC_CONN_SHUTDOWN, - port_out_seqno(p_ptr), 0); } tipc_port_unlock(p_ptr); @@ -1219,13 +1163,14 @@ int tipc_shutdown(u32 ref) * message for this node. */ -static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, - struct iovec const *msg_sect) +static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect, + struct iovec const *msg_sect, + unsigned int total_len) { struct sk_buff *buf; int res; - res = tipc_msg_build(&sender->publ.phdr, msg_sect, num_sect, + res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, !sender->user_port, &buf); if (likely(buf)) tipc_port_recv_msg(buf); @@ -1236,229 +1181,175 @@ static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, * tipc_send - send message sections on connection */ -int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) +int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len) { - struct port *p_ptr; + struct tipc_port *p_ptr; u32 destnode; int res; p_ptr = tipc_port_deref(ref); - if (!p_ptr || !p_ptr->publ.connected) + if (!p_ptr || !p_ptr->connected) return -EINVAL; - p_ptr->publ.congested = 1; + p_ptr->congested = 1; if (!tipc_port_congested(p_ptr)) { destnode = port_peernode(p_ptr); if (likely(destnode != tipc_own_addr)) res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, - destnode); + total_len, destnode); else - res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); + res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, + total_len); if (likely(res != -ELINKCONG)) { - port_incr_out_seqno(p_ptr); - p_ptr->publ.congested = 0; - p_ptr->sent++; + p_ptr->congested = 0; + if (res > 0) + p_ptr->sent++; return res; } } if (port_unreliable(p_ptr)) { - p_ptr->publ.congested = 0; - /* Just calculate msg length and return */ - return tipc_msg_calc_data_size(msg_sect, num_sect); + p_ptr->congested = 0; + return total_len; } return -ELINKCONG; } /** - * tipc_forward2name - forward message sections to port name + * tipc_send2name - send message sections to port name */ -static int tipc_forward2name(u32 ref, - struct tipc_name const *name, - u32 domain, - u32 num_sect, - struct iovec const *msg_sect, - struct tipc_portid const *orig, - unsigned int importance) +int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct tipc_msg *msg; u32 destnode = domain; u32 destport; int res; p_ptr = tipc_port_deref(ref); - if (!p_ptr || p_ptr->publ.connected) + if (!p_ptr || p_ptr->connected) return -EINVAL; - msg = &p_ptr->publ.phdr; + msg = &p_ptr->phdr; msg_set_type(msg, TIPC_NAMED_MSG); - msg_set_orignode(msg, orig->node); - msg_set_origport(msg, orig->ref); + msg_set_orignode(msg, tipc_own_addr); + msg_set_origport(msg, ref); msg_set_hdr_sz(msg, LONG_H_SIZE); msg_set_nametype(msg, name->type); msg_set_nameinst(msg, name->instance); msg_set_lookup_scope(msg, tipc_addr_scope(domain)); - if (importance <= TIPC_CRITICAL_IMPORTANCE) - msg_set_importance(msg,importance); destport = tipc_nametbl_translate(name->type, name->instance, &destnode); msg_set_destnode(msg, destnode); msg_set_destport(msg, destport); if (likely(destport)) { - p_ptr->sent++; if (likely(destnode == tipc_own_addr)) - return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); - res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, - destnode); - if (likely(res != -ELINKCONG)) + res = tipc_port_recv_sections(p_ptr, num_sect, + msg_sect, total_len); + else + res = tipc_link_send_sections_fast(p_ptr, msg_sect, + num_sect, total_len, + destnode); + if (likely(res != -ELINKCONG)) { + if (res > 0) + p_ptr->sent++; return res; + } if (port_unreliable(p_ptr)) { - /* Just calculate msg length and return */ - return tipc_msg_calc_data_size(msg_sect, num_sect); + return total_len; } return -ELINKCONG; } return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, - TIPC_ERR_NO_NAME); + total_len, TIPC_ERR_NO_NAME); } /** - * tipc_send2name - send message sections to port name - */ - -int tipc_send2name(u32 ref, - struct tipc_name const *name, - unsigned int domain, - unsigned int num_sect, - struct iovec const *msg_sect) -{ - struct tipc_portid orig; - - orig.ref = ref; - orig.node = tipc_own_addr; - return tipc_forward2name(ref, name, domain, num_sect, msg_sect, &orig, - TIPC_PORT_IMPORTANCE); -} - -/** - * tipc_forward2port - forward message sections to port identity + * tipc_send2port - send message sections to port identity */ -static int tipc_forward2port(u32 ref, - struct tipc_portid const *dest, - unsigned int num_sect, - struct iovec const *msg_sect, - struct tipc_portid const *orig, - unsigned int importance) +int tipc_send2port(u32 ref, struct tipc_portid const *dest, + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct tipc_msg *msg; int res; p_ptr = tipc_port_deref(ref); - if (!p_ptr || p_ptr->publ.connected) + if (!p_ptr || p_ptr->connected) return -EINVAL; - msg = &p_ptr->publ.phdr; + msg = &p_ptr->phdr; msg_set_type(msg, TIPC_DIRECT_MSG); - msg_set_orignode(msg, orig->node); - msg_set_origport(msg, orig->ref); + msg_set_lookup_scope(msg, 0); + msg_set_orignode(msg, tipc_own_addr); + 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); - if (importance <= TIPC_CRITICAL_IMPORTANCE) - msg_set_importance(msg, importance); - p_ptr->sent++; + if (dest->node == tipc_own_addr) - return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); - res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); - if (likely(res != -ELINKCONG)) + res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, + total_len); + else + res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, + total_len, dest->node); + if (likely(res != -ELINKCONG)) { + if (res > 0) + p_ptr->sent++; return res; + } if (port_unreliable(p_ptr)) { - /* Just calculate msg length and return */ - return tipc_msg_calc_data_size(msg_sect, num_sect); + return total_len; } return -ELINKCONG; } /** - * tipc_send2port - send message sections to port identity + * tipc_send_buf2port - send message buffer to port identity */ -int tipc_send2port(u32 ref, - struct tipc_portid const *dest, - unsigned int num_sect, - struct iovec const *msg_sect) -{ - struct tipc_portid orig; - - orig.ref = ref; - orig.node = tipc_own_addr; - return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig, - TIPC_PORT_IMPORTANCE); -} - -/** - * tipc_forward_buf2port - forward message buffer to port identity - */ -static int tipc_forward_buf2port(u32 ref, - struct tipc_portid const *dest, - struct sk_buff *buf, - unsigned int dsz, - struct tipc_portid const *orig, - unsigned int importance) +int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, + struct sk_buff *buf, unsigned int dsz) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct tipc_msg *msg; int res; - p_ptr = (struct port *)tipc_ref_deref(ref); - if (!p_ptr || p_ptr->publ.connected) + p_ptr = (struct tipc_port *)tipc_ref_deref(ref); + if (!p_ptr || p_ptr->connected) return -EINVAL; - msg = &p_ptr->publ.phdr; + msg = &p_ptr->phdr; msg_set_type(msg, TIPC_DIRECT_MSG); - msg_set_orignode(msg, orig->node); - msg_set_origport(msg, orig->ref); + msg_set_orignode(msg, tipc_own_addr); + 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); - if (importance <= TIPC_CRITICAL_IMPORTANCE) - msg_set_importance(msg, importance); msg_set_size(msg, DIR_MSG_H_SIZE + dsz); if (skb_cow(buf, DIR_MSG_H_SIZE)) return -ENOMEM; skb_push(buf, DIR_MSG_H_SIZE); skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE); - msg_dbg(msg, "buf2port: "); - p_ptr->sent++; + if (dest->node == tipc_own_addr) - return tipc_port_recv_msg(buf); - res = tipc_send_buf_fast(buf, dest->node); - if (likely(res != -ELINKCONG)) + res = tipc_port_recv_msg(buf); + else + res = tipc_send_buf_fast(buf, dest->node); + if (likely(res != -ELINKCONG)) { + if (res > 0) + p_ptr->sent++; return res; + } if (port_unreliable(p_ptr)) return dsz; return -ELINKCONG; } -/** - * tipc_send_buf2port - send message buffer to port identity - */ - -int tipc_send_buf2port(u32 ref, - struct tipc_portid const *dest, - struct sk_buff *buf, - unsigned int dsz) -{ - struct tipc_portid orig; - - orig.ref = ref; - orig.node = tipc_own_addr; - return tipc_forward_buf2port(ref, dest, buf, dsz, &orig, - TIPC_PORT_IMPORTANCE); -} - diff --git a/net/tipc/port.h b/net/tipc/port.h index 73bbf442b34..b9aa34195ae 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -2,7 +2,7 @@ * net/tipc/port.h: Include file for TIPC port code * * Copyright (c) 1994-2007, Ericsson AB - * Copyright (c) 2004-2007, Wind River Systems + * Copyright (c) 2004-2007, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,24 +37,52 @@ #ifndef _TIPC_PORT_H #define _TIPC_PORT_H -#include "core.h" #include "ref.h" #include "net.h" #include "msg.h" -#include "dbg.h" #include "node_subscr.h" +#define TIPC_FLOW_CONTROL_WIN 512 + +typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref, + struct sk_buff **buf, unsigned char const *data, + unsigned int size, int reason, + struct tipc_portid const *attmpt_destid); + +typedef void (*tipc_named_msg_err_event) (void *usr_handle, u32 portref, + struct sk_buff **buf, unsigned char const *data, + unsigned int size, int reason, + struct tipc_name_seq const *attmpt_dest); + +typedef void (*tipc_conn_shutdown_event) (void *usr_handle, u32 portref, + struct sk_buff **buf, unsigned char const *data, + unsigned int size, int reason); + +typedef void (*tipc_msg_event) (void *usr_handle, u32 portref, + struct sk_buff **buf, unsigned char const *data, + unsigned int size, unsigned int importance, + struct tipc_portid const *origin); + +typedef void (*tipc_named_msg_event) (void *usr_handle, u32 portref, + struct sk_buff **buf, unsigned char const *data, + unsigned int size, unsigned int importance, + struct tipc_portid const *orig, + struct tipc_name_seq const *dest); + +typedef void (*tipc_conn_msg_event) (void *usr_handle, u32 portref, + struct sk_buff **buf, unsigned char const *data, + unsigned int size); + +typedef void (*tipc_continue_event) (void *usr_handle, u32 portref); + /** * struct user_port - TIPC user port (used with native API) - * @user_ref: id of user who created user port * @usr_handle: user-specified field * @ref: object reference to associated TIPC port * <various callback routines> - * @uport_list: adjacent user ports in list of ports held by user */ struct user_port { - u32 user_ref; void *usr_handle; u32 ref; tipc_msg_err_event err_cb; @@ -64,31 +92,48 @@ struct user_port { tipc_named_msg_event named_msg_cb; tipc_conn_msg_event conn_msg_cb; tipc_continue_event continue_event_cb; - struct list_head uport_list; }; /** - * struct port - TIPC port structure - * @publ: TIPC port info available to privileged users + * struct tipc_port - TIPC port structure + * @usr_handle: pointer to additional user-defined information about port + * @lock: pointer to spinlock for controlling access to port + * @connected: non-zero if port is currently connected to a peer port + * @conn_type: TIPC type used when connection was established + * @conn_instance: TIPC instance used when connection was established + * @conn_unacked: number of unacknowledged messages received from peer port + * @published: non-zero if port has one or more associated names + * @congested: non-zero if cannot send because of link or port congestion + * @max_pkt: maximum packet size "hint" used when building messages sent by port + * @ref: unique reference to port in TIPC object registry + * @phdr: preformatted message header used when sending messages * @port_list: adjacent ports in TIPC's global list of ports * @dispatcher: ptr to routine which handles received messages * @wakeup: ptr to routine to call when port is no longer congested * @user_port: ptr to user port associated with port (if any) * @wait_list: adjacent ports in list of ports waiting on link congestion * @waiting_pkts: - * @sent: - * @acked: + * @sent: # of non-empty messages sent by port + * @acked: # of non-empty message acknowledgements from connected port's peer * @publications: list of publications for port * @pub_count: total # of publications port has made during its lifetime * @probing_state: * @probing_interval: - * @last_in_seqno: * @timer_ref: * @subscription: "node down" subscription used to terminate failed connections */ - -struct port { - struct tipc_port publ; +struct tipc_port { + void *usr_handle; + spinlock_t *lock; + int connected; + u32 conn_type; + u32 conn_instance; + u32 conn_unacked; + int published; + u32 congested; + u32 max_pkt; + u32 ref; + struct tipc_msg phdr; struct list_head port_list; u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); void (*wakeup)(struct tipc_port *); @@ -101,7 +146,6 @@ struct port { u32 pub_count; u32 probing_state; u32 probing_interval; - u32 last_in_seqno; struct timer_list timer; struct tipc_node_subscr subscription; }; @@ -109,11 +153,80 @@ struct port { extern spinlock_t tipc_port_list_lock; struct port_list; -int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, +/* + * TIPC port manipulation routines + */ +struct tipc_port *tipc_createport_raw(void *usr_handle, + u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), + void (*wakeup)(struct tipc_port *), const u32 importance); + +int tipc_reject_msg(struct sk_buff *buf, u32 err); + +int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode); + +void tipc_acknowledge(u32 port_ref, u32 ack); + +int tipc_createport(void *usr_handle, + unsigned int importance, tipc_msg_err_event error_cb, + tipc_named_msg_err_event named_error_cb, + tipc_conn_shutdown_event conn_error_cb, tipc_msg_event msg_cb, + tipc_named_msg_event named_msg_cb, + tipc_conn_msg_event conn_msg_cb, + tipc_continue_event continue_event_cb, u32 *portref); + +int tipc_deleteport(u32 portref); + +int tipc_portimportance(u32 portref, unsigned int *importance); +int tipc_set_portimportance(u32 portref, unsigned int importance); + +int tipc_portunreliable(u32 portref, unsigned int *isunreliable); +int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); + +int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); +int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); + +int tipc_publish(u32 portref, unsigned int scope, + struct tipc_name_seq const *name_seq); +int tipc_withdraw(u32 portref, unsigned int scope, + struct tipc_name_seq const *name_seq); + +int tipc_connect2port(u32 portref, struct tipc_portid const *port); + +int tipc_disconnect(u32 portref); + +int tipc_shutdown(u32 ref); + + +/* + * The following routines require that the port be locked on entry + */ +int tipc_disconnect_port(struct tipc_port *tp_ptr); + +/* + * TIPC messaging routines + */ +int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len); + +int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len); + +int tipc_send2port(u32 portref, struct tipc_portid const *dest, + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len); + +int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest, + struct sk_buff *buf, unsigned int dsz); + +int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, + unsigned int section_count, struct iovec const *msg, + unsigned int total_len); + +int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, struct iovec const *msg_sect, u32 num_sect, - int err); + unsigned int total_len, int err); struct sk_buff *tipc_port_get_ports(void); -struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space); void tipc_port_recv_proto_msg(struct sk_buff *buf); void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp); void tipc_port_reinit(void); @@ -122,9 +235,9 @@ void tipc_port_reinit(void); * tipc_port_lock - lock port instance referred to and return its pointer */ -static inline struct port *tipc_port_lock(u32 ref) +static inline struct tipc_port *tipc_port_lock(u32 ref) { - return (struct port *)tipc_ref_lock(ref); + return (struct tipc_port *)tipc_ref_lock(ref); } /** @@ -133,27 +246,27 @@ static inline struct port *tipc_port_lock(u32 ref) * Can use pointer instead of tipc_ref_unlock() since port is already locked. */ -static inline void tipc_port_unlock(struct port *p_ptr) +static inline void tipc_port_unlock(struct tipc_port *p_ptr) { - spin_unlock_bh(p_ptr->publ.lock); + spin_unlock_bh(p_ptr->lock); } -static inline struct port* tipc_port_deref(u32 ref) +static inline struct tipc_port *tipc_port_deref(u32 ref) { - return (struct port *)tipc_ref_deref(ref); + return (struct tipc_port *)tipc_ref_deref(ref); } -static inline u32 tipc_peer_port(struct port *p_ptr) +static inline u32 tipc_peer_port(struct tipc_port *p_ptr) { - return msg_destport(&p_ptr->publ.phdr); + return msg_destport(&p_ptr->phdr); } -static inline u32 tipc_peer_node(struct port *p_ptr) +static inline u32 tipc_peer_node(struct tipc_port *p_ptr) { - return msg_destnode(&p_ptr->publ.phdr); + return msg_destnode(&p_ptr->phdr); } -static inline int tipc_port_congested(struct port *p_ptr) +static inline int tipc_port_congested(struct tipc_port *p_ptr) { return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); } @@ -164,7 +277,7 @@ static inline int tipc_port_congested(struct port *p_ptr) static inline int tipc_port_recv_msg(struct sk_buff *buf) { - struct port *p_ptr; + struct tipc_port *p_ptr; struct tipc_msg *msg = buf_msg(buf); u32 destport = msg_destport(msg); u32 dsz = msg_data_sz(msg); @@ -179,7 +292,7 @@ static inline int tipc_port_recv_msg(struct sk_buff *buf) /* validate destination & pass to port, otherwise reject message */ p_ptr = tipc_port_lock(destport); if (likely(p_ptr)) { - if (likely(p_ptr->publ.connected)) { + if (likely(p_ptr->connected)) { if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) || (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) || (unlikely(!msg_connected(msg)))) { @@ -188,7 +301,7 @@ static inline int tipc_port_recv_msg(struct sk_buff *buf) goto reject; } } - err = p_ptr->dispatcher(&p_ptr->publ, buf); + err = p_ptr->dispatcher(p_ptr, buf); tipc_port_unlock(p_ptr); if (likely(!err)) return dsz; @@ -196,7 +309,6 @@ static inline int tipc_port_recv_msg(struct sk_buff *buf) err = TIPC_ERR_NO_PORT; } reject: - dbg("port->rejecting, err = %x..\n",err); return tipc_reject_msg(buf, err); } diff --git a/net/tipc/ref.c b/net/tipc/ref.c index ab8ad32d8c2..83116892528 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -89,7 +89,7 @@ struct ref_table { * have a reference value of 0 (although this is unlikely). */ -static struct ref_table tipc_ref_table = { NULL }; +static struct ref_table tipc_ref_table; static DEFINE_RWLOCK(ref_table_lock); @@ -178,14 +178,12 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) next_plus_upper = entry->ref; tipc_ref_table.first_free = next_plus_upper & index_mask; ref = (next_plus_upper & ~index_mask) + index; - } - else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { + } else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { index = tipc_ref_table.init_point++; entry = &(tipc_ref_table.entries[index]); spin_lock_init(&entry->lock); ref = tipc_ref_table.start_mask + index; - } - else { + } else { ref = 0; } write_unlock_bh(&ref_table_lock); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 33217fc3d69..33883739664 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -2,7 +2,7 @@ * net/tipc/socket.c: TIPC socket API * * Copyright (c) 2001-2007, 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 @@ -34,25 +34,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/module.h> -#include <linux/types.h> -#include <linux/net.h> -#include <linux/socket.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/poll.h> -#include <linux/fcntl.h> -#include <linux/gfp.h> -#include <asm/string.h> -#include <asm/atomic.h> #include <net/sock.h> #include <linux/tipc.h> #include <linux/tipc_config.h> -#include <net/tipc/tipc_msg.h> -#include <net/tipc/tipc_port.h> #include "core.h" +#include "port.h" #define SS_LISTENING -1 /* socket is listening */ #define SS_READY -2 /* socket is connectionless */ @@ -70,6 +58,9 @@ struct tipc_sock { #define tipc_sk(sk) ((struct tipc_sock *)(sk)) #define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p)) +#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \ + (sock->state == SS_DISCONNECTING)) + static int backlog_rcv(struct sock *sk, struct sk_buff *skb); static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); static void wakeupdispatch(struct tipc_port *tport); @@ -80,7 +71,7 @@ static const struct proto_ops msg_ops; static struct proto tipc_proto; -static int sockets_enabled = 0; +static int sockets_enabled; static atomic_t tipc_queue_size = ATOMIC_INIT(0); @@ -253,7 +244,6 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, tipc_set_portunreliable(tp_ptr->ref, 1); } - atomic_inc(&tipc_user_count); return 0; } @@ -302,7 +292,7 @@ static int release(struct socket *sock) if (buf == NULL) break; atomic_dec(&tipc_queue_size); - if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) + if (TIPC_SKB_CB(buf)->handle != 0) buf_discard(buf); else { if ((sock->state == SS_CONNECTING) || @@ -333,7 +323,6 @@ static int release(struct socket *sock) sock_put(sk); sock->sk = NULL; - atomic_dec(&tipc_user_count); return res; } @@ -387,7 +376,7 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) * * NOTE: This routine doesn't need to take the socket lock since it only * accesses socket information that is unchanging (or which changes in - * a completely predictable manner). + * a completely predictable manner). */ static int get_name(struct socket *sock, struct sockaddr *uaddr, @@ -396,6 +385,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; struct tipc_sock *tsock = tipc_sk(sock->sk); + memset(addr, 0, sizeof(*addr)); if (peer) { if ((sock->state != SS_CONNECTED) && ((peer != 2) || (sock->state != SS_DISCONNECTING))) @@ -403,7 +393,8 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, addr->addr.id.ref = tsock->peer_name.ref; addr->addr.id.node = tsock->peer_name.node; } else { - tipc_ownidentity(tsock->p->ref, &addr->addr.id); + addr->addr.id.ref = tsock->p->ref; + addr->addr.id.node = tipc_own_addr; } *uaddr_len = sizeof(*addr); @@ -505,6 +496,8 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) if (likely(dest->addr.name.name.type != TIPC_CFG_SRV)) return -EACCES; + if (!m->msg_iovlen || (m->msg_iov[0].iov_len < sizeof(hdr))) + return -EMSGSIZE; if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) return -EFAULT; if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN))) @@ -542,6 +535,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, if (unlikely((m->msg_namelen < sizeof(*dest)) || (dest->family != AF_TIPC))) return -EINVAL; + if ((total_len > TIPC_MAX_USER_MSG_SIZE) || + (m->msg_iovlen > (unsigned)INT_MAX)) + return -EMSGSIZE; if (iocb) lock_sock(sk); @@ -573,37 +569,38 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, do { if (dest->addrtype == TIPC_ADDR_NAME) { - if ((res = dest_name_check(dest, m))) + res = dest_name_check(dest, m); + if (res) break; res = tipc_send2name(tport->ref, &dest->addr.name.name, dest->addr.name.domain, m->msg_iovlen, - m->msg_iov); - } - else if (dest->addrtype == TIPC_ADDR_ID) { + m->msg_iov, + total_len); + } else if (dest->addrtype == TIPC_ADDR_ID) { res = tipc_send2port(tport->ref, &dest->addr.id, m->msg_iovlen, - m->msg_iov); - } - else if (dest->addrtype == TIPC_ADDR_MCAST) { + m->msg_iov, + total_len); + } else if (dest->addrtype == TIPC_ADDR_MCAST) { if (needs_conn) { res = -EOPNOTSUPP; break; } - if ((res = dest_name_check(dest, m))) + res = dest_name_check(dest, m); + if (res) break; res = tipc_multicast(tport->ref, &dest->addr.nameseq, - 0, m->msg_iovlen, - m->msg_iov); + m->msg_iov, + total_len); } if (likely(res != -ELINKCONG)) { - if (needs_conn && (res >= 0)) { + if (needs_conn && (res >= 0)) sock->state = SS_CONNECTING; - } break; } if (m->msg_flags & MSG_DONTWAIT) { @@ -649,6 +646,10 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, if (unlikely(dest)) return send_msg(iocb, sock, m, total_len); + if ((total_len > TIPC_MAX_USER_MSG_SIZE) || + (m->msg_iovlen > (unsigned)INT_MAX)) + return -EMSGSIZE; + if (iocb) lock_sock(sk); @@ -661,10 +662,10 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, break; } - res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov); - if (likely(res != -ELINKCONG)) { + res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov, + total_len); + if (likely(res != -ELINKCONG)) break; - } if (m->msg_flags & MSG_DONTWAIT) { res = -EWOULDBLOCK; break; @@ -733,6 +734,12 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, goto exit; } + if ((total_len > (unsigned)INT_MAX) || + (m->msg_iovlen > (unsigned)INT_MAX)) { + res = -EMSGSIZE; + goto exit; + } + /* * Send each iovec entry using one or more messages * @@ -763,7 +770,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, bytes_to_send = curr_left; my_iov.iov_base = curr_start; my_iov.iov_len = bytes_to_send; - if ((res = send_packet(NULL, sock, &my_msg, 0)) < 0) { + res = send_packet(NULL, sock, &my_msg, bytes_to_send); + if (res < 0) { if (bytes_sent) res = bytes_sent; goto exit; @@ -823,8 +831,8 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) addr->addrtype = TIPC_ADDR_ID; addr->addr.id.ref = msg_origport(msg); addr->addr.id.node = msg_orignode(msg); - addr->addr.name.domain = 0; /* could leave uninitialized */ - addr->scope = 0; /* could leave uninitialized */ + addr->addr.name.domain = 0; /* could leave uninitialized */ + addr->scope = 0; /* could leave uninitialized */ m->msg_namelen = sizeof(struct sockaddr_tipc); } } @@ -858,12 +866,15 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, if (unlikely(err)) { anc_data[0] = err; anc_data[1] = msg_data_sz(msg); - if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data))) - return res; - if (anc_data[1] && - (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], - msg_data(msg)))) + res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data); + if (res) return res; + if (anc_data[1]) { + res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], + msg_data(msg)); + if (res) + return res; + } } /* Optionally capture message destination object */ @@ -891,9 +902,11 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, default: has_name = 0; } - if (has_name && - (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data))) - return res; + if (has_name) { + res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data); + if (res) + return res; + } return 0; } @@ -918,15 +931,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, struct tipc_port *tport = tipc_sk_port(sk); struct sk_buff *buf; struct tipc_msg *msg; + long timeout; unsigned int sz; u32 err; int res; /* Catch invalid receive requests */ - if (m->msg_iovlen != 1) - return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */ - if (unlikely(!buf_len)) return -EINVAL; @@ -937,6 +948,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, goto exit; } + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: /* Look for a message in receive queue; wait if necessary */ @@ -946,17 +958,15 @@ restart: res = -ENOTCONN; goto exit; } - if (flags & MSG_DONTWAIT) { - res = -EWOULDBLOCK; + if (timeout <= 0L) { + res = timeout ? timeout : -EWOULDBLOCK; goto exit; } release_sock(sk); - res = wait_event_interruptible(*sk_sleep(sk), - (!skb_queue_empty(&sk->sk_receive_queue) || - (sock->state == SS_DISCONNECTING))); + timeout = wait_event_interruptible_timeout(*sk_sleep(sk), + tipc_rx_ready(sock), + timeout); lock_sock(sk); - if (res) - goto exit; } /* Look at first message in receive queue */ @@ -998,11 +1008,10 @@ restart: sz = buf_len; m->msg_flags |= MSG_TRUNC; } - if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), - sz))) { - res = -EFAULT; + res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg), + m->msg_iov, sz); + if (res) goto exit; - } res = sz; } else { if ((sock->state == SS_READY) || @@ -1045,19 +1054,15 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, struct tipc_port *tport = tipc_sk_port(sk); struct sk_buff *buf; struct tipc_msg *msg; + long timeout; unsigned int sz; int sz_to_copy, target, needed; int sz_copied = 0; - char __user *crs = m->msg_iov->iov_base; - unsigned char *buf_crs; u32 err; int res = 0; /* Catch invalid receive attempts */ - if (m->msg_iovlen != 1) - return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */ - if (unlikely(!buf_len)) return -EINVAL; @@ -1070,7 +1075,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, } target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); - + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: /* Look for a message in receive queue; wait if necessary */ @@ -1080,17 +1085,15 @@ restart: res = -ENOTCONN; goto exit; } - if (flags & MSG_DONTWAIT) { - res = -EWOULDBLOCK; + if (timeout <= 0L) { + res = timeout ? timeout : -EWOULDBLOCK; goto exit; } release_sock(sk); - res = wait_event_interruptible(*sk_sleep(sk), - (!skb_queue_empty(&sk->sk_receive_queue) || - (sock->state == SS_DISCONNECTING))); + timeout = wait_event_interruptible_timeout(*sk_sleep(sk), + tipc_rx_ready(sock), + timeout); lock_sock(sk); - if (res) - goto exit; } /* Look at first message in receive queue */ @@ -1119,24 +1122,25 @@ restart: /* Capture message data (if valid) & compute return value (always) */ if (!err) { - buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); - sz = (unsigned char *)msg + msg_size(msg) - buf_crs; + u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle); + sz -= offset; needed = (buf_len - sz_copied); sz_to_copy = (sz <= needed) ? sz : needed; - if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { - res = -EFAULT; + + res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset, + m->msg_iov, sz_to_copy); + if (res) goto exit; - } + sz_copied += sz_to_copy; if (sz_to_copy < sz) { if (!(flags & MSG_PEEK)) - TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; + TIPC_SKB_CB(buf)->handle = + (void *)(unsigned long)(offset + sz_to_copy); goto exit; } - - crs += sz_to_copy; } else { if (sz_copied != 0) goto exit; /* can't add error msg to valid data */ @@ -1226,42 +1230,25 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) */ if (sock->state == SS_READY) { - if (msg_connected(msg)) { - msg_dbg(msg, "dispatch filter 1\n"); + if (msg_connected(msg)) return TIPC_ERR_NO_PORT; - } } else { - if (msg_mcast(msg)) { - msg_dbg(msg, "dispatch filter 2\n"); + if (msg_mcast(msg)) return TIPC_ERR_NO_PORT; - } if (sock->state == SS_CONNECTED) { - if (!msg_connected(msg)) { - msg_dbg(msg, "dispatch filter 3\n"); + if (!msg_connected(msg)) return TIPC_ERR_NO_PORT; - } - } - else if (sock->state == SS_CONNECTING) { - if (!msg_connected(msg) && (msg_errcode(msg) == 0)) { - msg_dbg(msg, "dispatch filter 4\n"); + } else if (sock->state == SS_CONNECTING) { + if (!msg_connected(msg) && (msg_errcode(msg) == 0)) return TIPC_ERR_NO_PORT; - } - } - else if (sock->state == SS_LISTENING) { - if (msg_connected(msg) || msg_errcode(msg)) { - msg_dbg(msg, "dispatch filter 5\n"); + } else if (sock->state == SS_LISTENING) { + if (msg_connected(msg) || msg_errcode(msg)) return TIPC_ERR_NO_PORT; - } - } - else if (sock->state == SS_DISCONNECTING) { - msg_dbg(msg, "dispatch filter 6\n"); + } else if (sock->state == SS_DISCONNECTING) { return TIPC_ERR_NO_PORT; - } - else /* (sock->state == SS_UNCONNECTED) */ { - if (msg_connected(msg) || msg_errcode(msg)) { - msg_dbg(msg, "dispatch filter 7\n"); + } else /* (sock->state == SS_UNCONNECTED) */ { + if (msg_connected(msg) || msg_errcode(msg)) return TIPC_ERR_NO_PORT; - } } } @@ -1280,8 +1267,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) /* Enqueue message (finally!) */ - msg_dbg(msg, "<DISP<: "); - TIPC_SKB_CB(buf)->handle = msg_data(msg); + TIPC_SKB_CB(buf)->handle = 0; atomic_inc(&tipc_queue_size); __skb_queue_tail(&sk->sk_receive_queue, buf); @@ -1441,9 +1427,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, m.msg_name = dest; m.msg_namelen = destlen; res = send_msg(NULL, sock, &m, 0); - if (res < 0) { + if (res < 0) goto exit; - } /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ @@ -1465,11 +1450,10 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, advance_rx_queue(sk); } } else { - if (sock->state == SS_CONNECTED) { + if (sock->state == SS_CONNECTED) res = -EISCONN; - } else { + else res = -ECONNREFUSED; - } } } else { if (res == 0) @@ -1588,7 +1572,6 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) * Respond to 'SYN+' by queuing it on new socket. */ - msg_dbg(msg,"<ACC<: "); if (!msg_data_sz(msg)) { struct msghdr m = {NULL,}; @@ -1636,7 +1619,7 @@ restart: buf = __skb_dequeue(&sk->sk_receive_queue); if (buf) { atomic_dec(&tipc_queue_size); - if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { + if (TIPC_SKB_CB(buf)->handle != 0) { buf_discard(buf); goto restart; } @@ -1696,7 +1679,8 @@ static int setsockopt(struct socket *sock, return -ENOPROTOOPT; if (ol < sizeof(value)) return -EINVAL; - if ((res = get_user(value, (u32 __user *)ov))) + res = get_user(value, (u32 __user *)ov); + if (res) return res; lock_sock(sk); @@ -1754,7 +1738,8 @@ static int getsockopt(struct socket *sock, return put_user(0, ol); if (lvl != SOL_TIPC) return -ENOPROTOOPT; - if ((res = get_user(len, ol))) + res = get_user(len, ol); + if (res) return res; lock_sock(sk); @@ -1773,10 +1758,10 @@ static int getsockopt(struct socket *sock, value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout); /* no need to set "res", since already 0 at this point */ break; - case TIPC_NODE_RECVQ_DEPTH: + case TIPC_NODE_RECVQ_DEPTH: value = (u32)atomic_read(&tipc_queue_size); break; - case TIPC_SOCK_RECVQ_DEPTH: + case TIPC_SOCK_RECVQ_DEPTH: value = skb_queue_len(&sk->sk_receive_queue); break; default: @@ -1785,20 +1770,16 @@ static int getsockopt(struct socket *sock, release_sock(sk); - if (res) { - /* "get" failed */ - } - else if (len < sizeof(value)) { - res = -EINVAL; - } - else if (copy_to_user(ov, &value, sizeof(value))) { - res = -EFAULT; - } - else { - res = put_user(sizeof(value), ol); - } + if (res) + return res; /* "get" failed */ - return res; + if (len < sizeof(value)) + return -EINVAL; + + if (copy_to_user(ov, &value, sizeof(value))) + return -EFAULT; + + return put_user(sizeof(value), ol); } /** @@ -1806,7 +1787,7 @@ static int getsockopt(struct socket *sock, */ static const struct proto_ops msg_ops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .family = AF_TIPC, .release = release, .bind = bind, @@ -1827,7 +1808,7 @@ static const struct proto_ops msg_ops = { }; static const struct proto_ops packet_ops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .family = AF_TIPC, .release = release, .bind = bind, @@ -1848,7 +1829,7 @@ static const struct proto_ops packet_ops = { }; static const struct proto_ops stream_ops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .family = AF_TIPC, .release = release, .bind = bind, @@ -1869,7 +1850,7 @@ static const struct proto_ops stream_ops = { }; static const struct net_proto_family tipc_family_ops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .family = AF_TIPC, .create = tipc_create }; diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 33313961d01..6cf72686348 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -2,7 +2,7 @@ * net/tipc/subscr.c: TIPC network topology service * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005-2007, Wind River Systems + * Copyright (c) 2005-2007, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,10 +35,8 @@ */ #include "core.h" -#include "dbg.h" #include "name_table.h" #include "port.h" -#include "ref.h" #include "subscr.h" /** @@ -66,14 +64,13 @@ struct subscriber { */ struct top_srv { - u32 user_ref; u32 setup_port; atomic_t subscription_count; struct list_head subscriber_list; spinlock_t lock; }; -static struct top_srv topsrv = { 0 }; +static struct top_srv topsrv; /** * htohl - convert value to endianness used by destination @@ -112,7 +109,7 @@ static void subscr_send_event(struct subscription *sub, sub->evt.found_upper = htohl(found_upper, sub->swap); sub->evt.port.ref = htohl(port_ref, sub->swap); sub->evt.port.node = htohl(node, sub->swap); - tipc_send(sub->server_ref, 1, &msg_sect); + tipc_send(sub->server_ref, 1, &msg_sect, msg_sect.iov_len); } /** @@ -163,7 +160,7 @@ void tipc_subscr_report_overlap(struct subscription *sub, static void subscr_timeout(struct subscription *sub) { - struct port *server_port; + struct tipc_port *server_port; /* Validate server port reference (in case subscriber is terminating) */ @@ -252,8 +249,6 @@ static void subscr_terminate(struct subscriber *subscriber) k_cancel_timer(&sub->timer); k_term_timer(&sub->timer); } - dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n", - sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); subscr_del(sub); } @@ -310,8 +305,6 @@ static void subscr_cancel(struct tipc_subscr *s, k_term_timer(&sub->timer); spin_lock_bh(subscriber->lock); } - dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", - sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); subscr_del(sub); } @@ -479,8 +472,6 @@ static void subscr_named_msg_event(void *usr_handle, struct tipc_portid const *orig, struct tipc_name_seq const *dest) { - static struct iovec msg_sect = {NULL, 0}; - struct subscriber *subscriber; u32 server_port_ref; @@ -496,8 +487,7 @@ static void subscr_named_msg_event(void *usr_handle, /* Create server port & establish connection to subscriber */ - tipc_createport(topsrv.user_ref, - subscriber, + tipc_createport(subscriber, importance, NULL, NULL, @@ -516,7 +506,7 @@ static void subscr_named_msg_event(void *usr_handle, /* Lock server port (& save lock address for future use) */ - subscriber->lock = tipc_port_lock(subscriber->port_ref)->publ.lock; + subscriber->lock = tipc_port_lock(subscriber->port_ref)->lock; /* Add subscriber to topology server's subscriber list */ @@ -531,7 +521,7 @@ static void subscr_named_msg_event(void *usr_handle, /* Send an ACK- to complete connection handshaking */ - tipc_send(server_port_ref, 1, &msg_sect); + tipc_send(server_port_ref, 0, NULL, 0); /* Handle optional subscription request */ @@ -544,21 +534,13 @@ static void subscr_named_msg_event(void *usr_handle, int tipc_subscr_start(void) { struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; - int res = -1; + int res; - memset(&topsrv, 0, sizeof (topsrv)); + memset(&topsrv, 0, sizeof(topsrv)); spin_lock_init(&topsrv.lock); INIT_LIST_HEAD(&topsrv.subscriber_list); - spin_lock_bh(&topsrv.lock); - res = tipc_attach(&topsrv.user_ref, NULL, NULL); - if (res) { - spin_unlock_bh(&topsrv.lock); - return res; - } - - res = tipc_createport(topsrv.user_ref, - NULL, + res = tipc_createport(NULL, TIPC_CRITICAL_IMPORTANCE, NULL, NULL, @@ -572,17 +554,16 @@ int tipc_subscr_start(void) goto failed; res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); - if (res) + if (res) { + tipc_deleteport(topsrv.setup_port); + topsrv.setup_port = 0; goto failed; + } - spin_unlock_bh(&topsrv.lock); return 0; failed: err("Failed to create subscription service\n"); - tipc_detach(topsrv.user_ref); - topsrv.user_ref = 0; - spin_unlock_bh(&topsrv.lock); return res; } @@ -592,8 +573,10 @@ void tipc_subscr_stop(void) struct subscriber *subscriber_temp; spinlock_t *subscriber_lock; - if (topsrv.user_ref) { + if (topsrv.setup_port) { tipc_deleteport(topsrv.setup_port); + topsrv.setup_port = 0; + list_for_each_entry_safe(subscriber, subscriber_temp, &topsrv.subscriber_list, subscriber_list) { @@ -602,7 +585,5 @@ void tipc_subscr_stop(void) subscr_terminate(subscriber); spin_unlock_bh(subscriber_lock); } - tipc_detach(topsrv.user_ref); - topsrv.user_ref = 0; } } diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c deleted file mode 100644 index 50692880316..00000000000 --- a/net/tipc/user_reg.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * net/tipc/user_reg.c: TIPC user registry code - * - * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2004-2005, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "core.h" -#include "user_reg.h" - -/* - * TIPC user registry keeps track of users of the tipc_port interface. - * - * The registry utilizes an array of "TIPC user" entries; - * a user's ID is the index of their associated array entry. - * Array entry 0 is not used, so userid 0 is not valid; - * TIPC sometimes uses this value to denote an anonymous user. - * The list of free entries is initially chained from last entry to entry 1. - */ - -/** - * struct tipc_user - registered TIPC user info - * @next: index of next free registry entry (or -1 for an allocated entry) - * @callback: ptr to routine to call when TIPC mode changes (NULL if none) - * @usr_handle: user-defined value passed to callback routine - * @ports: list of user ports owned by the user - */ - -struct tipc_user { - int next; - tipc_mode_event callback; - void *usr_handle; - struct list_head ports; -}; - -#define MAX_USERID 64 -#define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user)) - -static struct tipc_user *users = NULL; -static u32 next_free_user = MAX_USERID + 1; -static DEFINE_SPINLOCK(reg_lock); - -/** - * reg_init - create TIPC user registry (but don't activate it) - * - * If registry has been pre-initialized it is left "as is". - * NOTE: This routine may be called when TIPC is inactive. - */ - -static int reg_init(void) -{ - u32 i; - - spin_lock_bh(®_lock); - if (!users) { - users = kzalloc(USER_LIST_SIZE, GFP_ATOMIC); - if (users) { - for (i = 1; i <= MAX_USERID; i++) { - users[i].next = i - 1; - } - next_free_user = MAX_USERID; - } - } - spin_unlock_bh(®_lock); - return users ? 0 : -ENOMEM; -} - -/** - * reg_callback - inform TIPC user about current operating mode - */ - -static void reg_callback(struct tipc_user *user_ptr) -{ - tipc_mode_event cb; - void *arg; - - spin_lock_bh(®_lock); - cb = user_ptr->callback; - arg = user_ptr->usr_handle; - spin_unlock_bh(®_lock); - - if (cb) - cb(arg, tipc_mode, tipc_own_addr); -} - -/** - * tipc_reg_start - activate TIPC user registry - */ - -int tipc_reg_start(void) -{ - u32 u; - int res; - - if ((res = reg_init())) - return res; - - for (u = 1; u <= MAX_USERID; u++) { - if (users[u].callback) - tipc_k_signal((Handler)reg_callback, - (unsigned long)&users[u]); - } - return 0; -} - -/** - * tipc_reg_stop - shut down & delete TIPC user registry - */ - -void tipc_reg_stop(void) -{ - int id; - - if (!users) - return; - - for (id = 1; id <= MAX_USERID; id++) { - if (users[id].callback) - reg_callback(&users[id]); - } - kfree(users); - users = NULL; -} - -/** - * tipc_attach - register a TIPC user - * - * NOTE: This routine may be called when TIPC is inactive. - */ - -int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle) -{ - struct tipc_user *user_ptr; - - if ((tipc_mode == TIPC_NOT_RUNNING) && !cb) - return -ENOPROTOOPT; - if (!users) - reg_init(); - - spin_lock_bh(®_lock); - if (!next_free_user) { - spin_unlock_bh(®_lock); - return -EBUSY; - } - user_ptr = &users[next_free_user]; - *userid = next_free_user; - next_free_user = user_ptr->next; - user_ptr->next = -1; - spin_unlock_bh(®_lock); - - user_ptr->callback = cb; - user_ptr->usr_handle = usr_handle; - INIT_LIST_HEAD(&user_ptr->ports); - atomic_inc(&tipc_user_count); - - if (cb && (tipc_mode != TIPC_NOT_RUNNING)) - tipc_k_signal((Handler)reg_callback, (unsigned long)user_ptr); - return 0; -} - -/** - * tipc_detach - deregister a TIPC user - */ - -void tipc_detach(u32 userid) -{ - struct tipc_user *user_ptr; - struct list_head ports_temp; - struct user_port *up_ptr, *temp_up_ptr; - - if ((userid == 0) || (userid > MAX_USERID)) - return; - - spin_lock_bh(®_lock); - if ((!users) || (users[userid].next >= 0)) { - spin_unlock_bh(®_lock); - return; - } - - user_ptr = &users[userid]; - user_ptr->callback = NULL; - INIT_LIST_HEAD(&ports_temp); - list_splice(&user_ptr->ports, &ports_temp); - user_ptr->next = next_free_user; - next_free_user = userid; - spin_unlock_bh(®_lock); - - atomic_dec(&tipc_user_count); - - list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) { - tipc_deleteport(up_ptr->ref); - } -} - -/** - * tipc_reg_add_port - register a user's driver port - */ - -int tipc_reg_add_port(struct user_port *up_ptr) -{ - struct tipc_user *user_ptr; - - if (up_ptr->user_ref == 0) - return 0; - if (up_ptr->user_ref > MAX_USERID) - return -EINVAL; - if ((tipc_mode == TIPC_NOT_RUNNING) || !users ) - return -ENOPROTOOPT; - - spin_lock_bh(®_lock); - user_ptr = &users[up_ptr->user_ref]; - list_add(&up_ptr->uport_list, &user_ptr->ports); - spin_unlock_bh(®_lock); - return 0; -} - -/** - * tipc_reg_remove_port - deregister a user's driver port - */ - -int tipc_reg_remove_port(struct user_port *up_ptr) -{ - if (up_ptr->user_ref == 0) - return 0; - if (up_ptr->user_ref > MAX_USERID) - return -EINVAL; - if (!users ) - return -ENOPROTOOPT; - - spin_lock_bh(®_lock); - list_del_init(&up_ptr->uport_list); - spin_unlock_bh(®_lock); - return 0; -} - diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h deleted file mode 100644 index 81dc12e2882..00000000000 --- a/net/tipc/user_reg.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * net/tipc/user_reg.h: Include file for TIPC user registry code - * - * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _TIPC_USER_REG_H -#define _TIPC_USER_REG_H - -#include "port.h" - -int tipc_reg_start(void); -void tipc_reg_stop(void); - -int tipc_reg_add_port(struct user_port *up_ptr); -int tipc_reg_remove_port(struct user_port *up_ptr); - -#endif diff --git a/net/tipc/zone.c b/net/tipc/zone.c deleted file mode 100644 index 83f8b5e91fc..00000000000 --- a/net/tipc/zone.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * net/tipc/zone.c: TIPC zone management routines - * - * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "core.h" -#include "zone.h" -#include "net.h" -#include "addr.h" -#include "node_subscr.h" -#include "cluster.h" -#include "node.h" - -struct _zone *tipc_zone_create(u32 addr) -{ - struct _zone *z_ptr; - u32 z_num; - - if (!tipc_addr_domain_valid(addr)) { - err("Zone creation failed, invalid domain 0x%x\n", addr); - return NULL; - } - - z_ptr = kzalloc(sizeof(*z_ptr), GFP_ATOMIC); - if (!z_ptr) { - warn("Zone creation failed, insufficient memory\n"); - return NULL; - } - - z_num = tipc_zone(addr); - z_ptr->addr = tipc_addr(z_num, 0, 0); - tipc_net.zones[z_num] = z_ptr; - return z_ptr; -} - -void tipc_zone_delete(struct _zone *z_ptr) -{ - u32 c_num; - - if (!z_ptr) - return; - for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { - tipc_cltr_delete(z_ptr->clusters[c_num]); - } - kfree(z_ptr); -} - -void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr) -{ - u32 c_num = tipc_cluster(c_ptr->addr); - - assert(c_ptr->addr); - assert(c_num <= tipc_max_clusters); - assert(z_ptr->clusters[c_num] == NULL); - z_ptr->clusters[c_num] = c_ptr; -} - -void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router) -{ - u32 c_num; - - for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { - if (z_ptr->clusters[c_num]) { - tipc_cltr_remove_as_router(z_ptr->clusters[c_num], - router); - } - } -} - -void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest) -{ - u32 c_num; - - for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { - if (z_ptr->clusters[c_num]) { - if (in_own_cluster(z_ptr->addr)) - continue; - tipc_cltr_send_ext_routes(z_ptr->clusters[c_num], dest); - } - } -} - -struct tipc_node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) -{ - struct cluster *c_ptr; - struct tipc_node *n_ptr; - u32 c_num; - - if (!z_ptr) - return NULL; - c_ptr = z_ptr->clusters[tipc_cluster(addr)]; - if (!c_ptr) - return NULL; - n_ptr = tipc_cltr_select_node(c_ptr, ref); - if (n_ptr) - return n_ptr; - - /* Links to any other clusters within this zone ? */ - for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { - c_ptr = z_ptr->clusters[c_num]; - if (!c_ptr) - return NULL; - n_ptr = tipc_cltr_select_node(c_ptr, ref); - if (n_ptr) - return n_ptr; - } - return NULL; -} - -u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) -{ - struct cluster *c_ptr; - u32 c_num; - u32 router; - - if (!z_ptr) - return 0; - c_ptr = z_ptr->clusters[tipc_cluster(addr)]; - router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0; - if (router) - return router; - - /* Links to any other clusters within the zone? */ - for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { - c_ptr = z_ptr->clusters[c_num]; - router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0; - if (router) - return router; - } - return 0; -} diff --git a/net/tipc/zone.h b/net/tipc/zone.h deleted file mode 100644 index bd1c20ce9d0..00000000000 --- a/net/tipc/zone.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * net/tipc/zone.h: Include file for TIPC zone management routines - * - * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _TIPC_ZONE_H -#define _TIPC_ZONE_H - -#include "node_subscr.h" -#include "net.h" - - -/** - * struct _zone - TIPC zone structure - * @addr: network address of zone - * @clusters: array of pointers to all clusters within zone - * @links: number of (unicast) links to zone - */ - -struct _zone { - u32 addr; - struct cluster *clusters[2]; /* currently limited to just 1 cluster */ - u32 links; -}; - -struct tipc_node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref); -u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref); -void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router); -void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest); -struct _zone *tipc_zone_create(u32 addr); -void tipc_zone_delete(struct _zone *z_ptr); -void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr); - -static inline struct _zone *tipc_zone_find(u32 addr) -{ - return tipc_net.zones[tipc_zone(addr)]; -} - -#endif |