From 5e726900380cfff50436ca6c5e08b35b3357d82a Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 23 May 2011 13:14:18 -0400 Subject: [PATCH 01/20] tipc: Convert fatal broadcast sanity check to non-fatal check Modifies the existing broadcast link sanity check that detects an attempt to send a message off-node when there are no available destinations so that it no longer causes a kernel panic; instead, the check now issues a warning and stack trace and then returns without sending the message anywhere. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bcast.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index fa68d1e9ff4b..759b318b5ffb 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -552,12 +552,16 @@ static int tipc_bcbearer_send(struct sk_buff *buf, if (likely(!msg_non_seq(buf_msg(buf)))) { struct tipc_msg *msg; - assert(tipc_bcast_nmap.count != 0); bcbuf_set_acks(buf, tipc_bcast_nmap.count); msg = buf_msg(buf); msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tipc_net_id); bcl->stats.sent_info++; + + if (WARN_ON(!tipc_bcast_nmap.count)) { + dump_stack(); + return 0; + } } /* Send buffer over bearers until all targets reached */ From 7ae4738e9e46a2f88e5d1332b7397bb96c527c44 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 23 May 2011 13:38:39 -0400 Subject: [PATCH 02/20] tipc: Remove unused sanity test macro Eliminates a TIPC-specific assert() macro that is no longer used. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/core.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/tipc/core.h b/net/tipc/core.h index 436dda1159d2..d234a98a460a 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -61,12 +61,6 @@ struct tipc_msg; /* msg.h */ struct print_buf; /* log.h */ -/* - * TIPC sanity test macros - */ - -#define assert(i) BUG_ON(!(i)) - /* * TIPC system monitoring code */ From acc631bf6f597b36f3f014e12e69c710da610027 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 23 May 2011 13:47:44 -0400 Subject: [PATCH 03/20] tipc: Standardize exit logic for message rejection handling Modifies the routine that handles the rejection of payload messages so that it has a single exit point that frees up the rejected message, thereby eliminating some duplicated code. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index c68dc956a423..3946b5b10c74 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -367,10 +367,8 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) imp++; /* discard rejected message if it shouldn't be returned to sender */ - if (msg_errcode(msg) || msg_dest_droppable(msg)) { - buf_discard(buf); - return data_sz; - } + if (msg_errcode(msg) || msg_dest_droppable(msg)) + goto exit; /* construct rejected message */ if (msg_mcast(msg)) @@ -378,10 +376,9 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) else hdr_sz = LONG_H_SIZE; rbuf = tipc_buf_acquire(data_sz + hdr_sz); - if (rbuf == NULL) { - buf_discard(buf); - return data_sz; - } + if (rbuf == NULL) + goto exit; + rmsg = buf_msg(rbuf); tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); msg_set_errcode(rmsg, err); @@ -411,9 +408,11 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) tipc_net_route_msg(abuf); } - /* send rejected message */ - buf_discard(buf); + /* send returned message & dispose of rejected message */ + tipc_net_route_msg(rbuf); +exit: + buf_discard(buf); return data_sz; } From 76d12527f74ad1b42b068252fdd2056c8ae48a99 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 23 May 2011 13:57:25 -0400 Subject: [PATCH 04/20] tipc: Add sanity check to detect rejection of non-payload messages Introduces an internal sanity check to ensure that the only undeliverable messages TIPC attempts to return to their origin are application payload messages. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/tipc/port.c b/net/tipc/port.c index 3946b5b10c74..756e64cbff96 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -367,6 +367,12 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) imp++; /* discard rejected message if it shouldn't be returned to sender */ + + if (WARN(!msg_isdata(msg), + "attempt to reject message with user=%u", msg_user(msg))) { + dump_stack(); + goto exit; + } if (msg_errcode(msg) || msg_dest_droppable(msg)) goto exit; From 017dac31dc8a25ad45421715d88c3869e299fd35 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 24 May 2011 13:20:09 -0400 Subject: [PATCH 05/20] tipc: Optimize routing of returned payload messages Reduces the work involved in transmitting a returned payload message by doing only the work necessary to route such a message directly to the specified destination port, rather than invoking the code used to route an arbitrary message to an arbitrary destination. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index 756e64cbff96..70ecdfdf6e3a 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -360,6 +360,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) int hdr_sz; u32 imp = msg_importance(msg); u32 data_sz = msg_data_sz(msg); + u32 src_node; if (data_sz > MAX_REJECT_SIZE) data_sz = MAX_REJECT_SIZE; @@ -416,7 +417,11 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) /* send returned message & dispose of rejected message */ - tipc_net_route_msg(rbuf); + src_node = msg_prevnode(msg); + if (src_node == tipc_own_addr) + tipc_port_recv_msg(rbuf); + else + tipc_link_send(rbuf, src_node, msg_link_selector(rmsg)); exit: buf_discard(buf); return data_sz; From 7dd1bf28ccc44ef205c64aab618863faa914daa9 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 23 May 2011 16:23:32 -0400 Subject: [PATCH 06/20] tipc: Optimizations & corrections to message rejection Optimizes the creation of a returned payload message by duplicating the original message and then updating the small number of fields that need to be adjusted, rather than building the new message header from scratch. In addition, certain operations that are not always required are relocated so that they are only done if needed. These optimizations also have the effect of addressing other issues that were present previously: 1) Fixes a bug that caused the socket send routines to return the size of the returned message, rather than the size of the sent message, when a returnable payload message was sent to a non-existent destination port. 2) The message header of the returned message now matches that of the original message more closely. The header is now always the same size as the original header, and some message header fields that weren't being initialized in the returned message header are now populated correctly -- namely the "d" and "s" bits, and the upper bound of a multicast name instance (where present). Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index 70ecdfdf6e3a..53118171b7e6 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -358,14 +358,10 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) struct sk_buff *rbuf; struct tipc_msg *rmsg; int hdr_sz; - u32 imp = msg_importance(msg); + u32 imp; u32 data_sz = msg_data_sz(msg); u32 src_node; - - if (data_sz > MAX_REJECT_SIZE) - data_sz = MAX_REJECT_SIZE; - if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE)) - imp++; + u32 rmsg_sz; /* discard rejected message if it shouldn't be returned to sender */ @@ -377,30 +373,33 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) if (msg_errcode(msg) || msg_dest_droppable(msg)) goto exit; - /* construct rejected message */ - if (msg_mcast(msg)) - hdr_sz = MCAST_H_SIZE; - else - hdr_sz = LONG_H_SIZE; - rbuf = tipc_buf_acquire(data_sz + hdr_sz); + /* + * construct returned message by copying rejected message header and + * data (or subset), then updating header fields that need adjusting + */ + + hdr_sz = msg_hdr_sz(msg); + rmsg_sz = hdr_sz + min_t(u32, data_sz, MAX_REJECT_SIZE); + + rbuf = tipc_buf_acquire(rmsg_sz); if (rbuf == NULL) goto exit; rmsg = buf_msg(rbuf); - tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); - msg_set_errcode(rmsg, err); - msg_set_destport(rmsg, msg_origport(msg)); - msg_set_origport(rmsg, msg_destport(msg)); - if (msg_short(msg)) { - msg_set_orignode(rmsg, tipc_own_addr); - /* leave name type & instance as zeroes */ - } else { - msg_set_orignode(rmsg, msg_destnode(msg)); - msg_set_nametype(rmsg, msg_nametype(msg)); - msg_set_nameinst(rmsg, msg_nameinst(msg)); + skb_copy_to_linear_data(rbuf, msg, rmsg_sz); + + if (msg_connected(rmsg)) { + imp = msg_importance(rmsg); + if (imp < TIPC_CRITICAL_IMPORTANCE) + msg_set_importance(rmsg, ++imp); } - msg_set_size(rmsg, data_sz + hdr_sz); - skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz); + msg_set_non_seq(rmsg, 0); + msg_set_size(rmsg, rmsg_sz); + msg_set_errcode(rmsg, err); + msg_set_prevnode(rmsg, tipc_own_addr); + msg_swap_words(rmsg, 4, 5); + if (!msg_short(rmsg)) + msg_swap_words(rmsg, 6, 7); /* send self-abort message when rejecting on a connected port */ if (msg_connected(msg)) { From 74d33b32deaa9ec864d6db3255b3a17a459f75fe Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 24 May 2011 14:44:56 -0400 Subject: [PATCH 07/20] tipc: Eliminate message header routines for caching destination node Gets rid of a pair of routines that provide support for temporarily caching the destination node for a message in the associated message buffer's application handle, since this capability is no longer used. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/msg.h | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 8452454731fa..11b74dc253f5 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -310,26 +310,6 @@ static inline void msg_set_seqno(struct tipc_msg *m, u32 n) msg_set_bits(m, 2, 0, 0xffff, n); } -/* - * TIPC may utilize the "link ack #" and "link seq #" fields of a short - * message header to hold the destination node for the message, since the - * normal "dest node" field isn't present. This cache is only referenced - * when required, so populating the cache of a longer message header is - * harmless (as long as the header has the two link sequence fields present). - * - * Note: Host byte order is OK here, since the info never goes off-card. - */ - -static inline u32 msg_destnode_cache(struct tipc_msg *m) -{ - return m->hdr[2]; -} - -static inline void msg_set_destnode_cache(struct tipc_msg *m, u32 dnode) -{ - m->hdr[2] = dnode; -} - /* * Words 3-10 */ From 7eb878ed8e0eae67269439bfd82234f9ba52ffe4 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 25 May 2011 13:28:27 -0400 Subject: [PATCH 08/20] tipc: Eliminate redundant masking in message header routines Gets rid of unnecessary masking in two routines that set TIPC message header fields. (The msg_set_bits() routine already takes care of masking the new value to the correct size.) Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/msg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 11b74dc253f5..a58975ced222 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -615,7 +615,7 @@ static inline u32 msg_link_selector(struct tipc_msg *m) static inline void msg_set_link_selector(struct tipc_msg *m, u32 n) { - msg_set_bits(m, 4, 0, 1, (n & 1)); + msg_set_bits(m, 4, 0, 1, n); } /* @@ -639,7 +639,7 @@ static inline u32 msg_probe(struct tipc_msg *m) static inline void msg_set_probe(struct tipc_msg *m, u32 val) { - msg_set_bits(m, 5, 0, 1, (val & 1)); + msg_set_bits(m, 5, 0, 1, val); } static inline char msg_net_plane(struct tipc_msg *m) From b52124a50fa7b870a3d1a18a8ff56273c7d690dd Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 30 May 2011 09:44:38 -0400 Subject: [PATCH 09/20] tipc: Partition name table instance array info into two parts Modifies the name table array structure that contains the name sequence instances for a given name type so that the publication lists associated with a given instance are stored in a dynamically allocated structure, rather than being embedded within the array entry itself. This change is being done for several reasons: 1) It reduces the amount of data that needs to be copied whenever a given array is expanded or contracted to accommodate the first publication of a new name sequence or the removal of the last publication of an existing name sequence. 2) It reduces the amount of memory associated with array entries that are currently unused. 3) It facilitates the upcoming conversion of the publication lists from TIPC-specific circular lists to standard kernel lists. (Standard lists cannot be used with the former array structure because the relocation of array entries during array expansion and contraction would corrupt the lists.) Note that, aside from introducing a small amount of code to dynamically allocate and free the structure that now holds publication list info, this change is largely a simple renaming exercise that replaces references to "sseq->LIST" with "sseq->info->LIST" (or "info->LIST"). Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/name_table.c | 150 +++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 61 deletions(-) diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 205ed4a4e186..9cd58f8318f1 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -44,9 +44,7 @@ static int tipc_nametbl_size = 1024; /* must be a power of 2 */ /** - * struct sub_seq - container for all published instances of a name sequence - * @lower: name sequence lower bound - * @upper: name sequence upper bound + * struct name_info - name sequence publication info * @node_list: circular list of publications made by own node * @cluster_list: circular list of publications made by own cluster * @zone_list: circular list of publications made by own zone @@ -59,9 +57,7 @@ static int tipc_nametbl_size = 1024; /* must be a power of 2 */ * (The cluster and node lists may be empty.) */ -struct sub_seq { - u32 lower; - u32 upper; +struct name_info { struct publication *node_list; struct publication *cluster_list; struct publication *zone_list; @@ -70,6 +66,19 @@ struct sub_seq { u32 zone_list_size; }; +/** + * struct sub_seq - container for all published instances of a name sequence + * @lower: name sequence lower bound + * @upper: name sequence upper bound + * @info: pointer to name sequence publication info + */ + +struct sub_seq { + u32 lower; + u32 upper; + struct name_info *info; +}; + /** * struct name_seq - container for all published instances of a name type * @type: 32 bit 'type' value for name sequence @@ -246,6 +255,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, struct subscription *st; struct publication *publ; struct sub_seq *sseq; + struct name_info *info; int created_subseq = 0; sseq = nameseq_find_subseq(nseq, lower); @@ -258,6 +268,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, type, lower, upper); return NULL; } + + info = sseq->info; } else { u32 inspos; struct sub_seq *freesseq; @@ -292,6 +304,13 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, nseq->alloc *= 2; } + info = kzalloc(sizeof(*info), GFP_ATOMIC); + if (!info) { + warn("Cannot publish {%u,%u,%u}, no memory\n", + type, lower, upper); + return NULL; + } + /* Insert new sub-sequence */ sseq = &nseq->sseqs[inspos]; @@ -301,6 +320,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, nseq->first_free++; sseq->lower = lower; sseq->upper = upper; + sseq->info = info; created_subseq = 1; } @@ -310,32 +330,32 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, if (!publ) return NULL; - sseq->zone_list_size++; - if (!sseq->zone_list) - sseq->zone_list = publ->zone_list_next = publ; + info->zone_list_size++; + if (!info->zone_list) + info->zone_list = publ->zone_list_next = publ; else { - publ->zone_list_next = sseq->zone_list->zone_list_next; - sseq->zone_list->zone_list_next = publ; + publ->zone_list_next = info->zone_list->zone_list_next; + info->zone_list->zone_list_next = publ; } if (in_own_cluster(node)) { - sseq->cluster_list_size++; - if (!sseq->cluster_list) - sseq->cluster_list = publ->cluster_list_next = publ; + info->cluster_list_size++; + if (!info->cluster_list) + info->cluster_list = publ->cluster_list_next = publ; else { publ->cluster_list_next = - sseq->cluster_list->cluster_list_next; - sseq->cluster_list->cluster_list_next = publ; + info->cluster_list->cluster_list_next; + info->cluster_list->cluster_list_next = publ; } } if (node == tipc_own_addr) { - sseq->node_list_size++; - if (!sseq->node_list) - sseq->node_list = publ->node_list_next = publ; + info->node_list_size++; + if (!info->node_list) + info->node_list = publ->node_list_next = publ; else { - publ->node_list_next = sseq->node_list->node_list_next; - sseq->node_list->node_list_next = publ; + publ->node_list_next = info->node_list->node_list_next; + info->node_list->node_list_next = publ; } } @@ -373,6 +393,7 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i struct publication *curr; struct publication *prev; struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); + struct name_info *info; struct sub_seq *free; struct subscription *s, *st; int removed_subseq = 0; @@ -380,40 +401,42 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i if (!sseq) return NULL; + info = sseq->info; + /* Remove publication from zone scope list */ - prev = sseq->zone_list; - publ = sseq->zone_list->zone_list_next; + prev = info->zone_list; + publ = info->zone_list->zone_list_next; while ((publ->key != key) || (publ->ref != ref) || (publ->node && (publ->node != node))) { prev = publ; publ = publ->zone_list_next; - if (prev == sseq->zone_list) { + if (prev == info->zone_list) { /* Prevent endless loop if publication not found */ return NULL; } } - if (publ != sseq->zone_list) + if (publ != info->zone_list) prev->zone_list_next = publ->zone_list_next; else if (publ->zone_list_next != publ) { prev->zone_list_next = publ->zone_list_next; - sseq->zone_list = publ->zone_list_next; + info->zone_list = publ->zone_list_next; } else { - sseq->zone_list = NULL; + info->zone_list = NULL; } - sseq->zone_list_size--; + info->zone_list_size--; /* Remove publication from cluster scope list, if present */ if (in_own_cluster(node)) { - prev = sseq->cluster_list; - curr = sseq->cluster_list->cluster_list_next; + prev = info->cluster_list; + curr = info->cluster_list->cluster_list_next; while (curr != publ) { prev = curr; curr = curr->cluster_list_next; - if (prev == sseq->cluster_list) { + if (prev == info->cluster_list) { /* Prevent endless loop for malformed list */ @@ -424,27 +447,27 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i goto end_cluster; } } - if (publ != sseq->cluster_list) + if (publ != info->cluster_list) prev->cluster_list_next = publ->cluster_list_next; else if (publ->cluster_list_next != publ) { prev->cluster_list_next = publ->cluster_list_next; - sseq->cluster_list = publ->cluster_list_next; + info->cluster_list = publ->cluster_list_next; } else { - sseq->cluster_list = NULL; + info->cluster_list = NULL; } - sseq->cluster_list_size--; + info->cluster_list_size--; } end_cluster: /* Remove publication from node scope list, if present */ if (node == tipc_own_addr) { - prev = sseq->node_list; - curr = sseq->node_list->node_list_next; + prev = info->node_list; + curr = info->node_list->node_list_next; while (curr != publ) { prev = curr; curr = curr->node_list_next; - if (prev == sseq->node_list) { + if (prev == info->node_list) { /* Prevent endless loop for malformed list */ @@ -455,21 +478,22 @@ end_cluster: goto end_node; } } - if (publ != sseq->node_list) + if (publ != info->node_list) prev->node_list_next = publ->node_list_next; else if (publ->node_list_next != publ) { prev->node_list_next = publ->node_list_next; - sseq->node_list = publ->node_list_next; + info->node_list = publ->node_list_next; } else { - sseq->node_list = NULL; + info->node_list = NULL; } - sseq->node_list_size--; + info->node_list_size--; } end_node: /* Contract subseq list if no more publications for that subseq */ - if (!sseq->zone_list) { + if (!info->zone_list) { + kfree(info); free = &nseq->sseqs[nseq->first_free--]; memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq)); removed_subseq = 1; @@ -506,7 +530,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s return; while (sseq != &nseq->sseqs[nseq->first_free]) { - struct publication *zl = sseq->zone_list; + struct publication *zl = sseq->info->zone_list; if (zl && tipc_subscr_overlap(s, sseq->lower, sseq->upper)) { struct publication *crs = zl; int must_report = 1; @@ -591,6 +615,7 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) { struct sub_seq *sseq; + struct name_info *info; struct publication *publ = NULL; struct name_seq *seq; u32 ref; @@ -606,12 +631,13 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) if (unlikely(!sseq)) goto not_found; spin_lock_bh(&seq->lock); + info = sseq->info; /* Closest-First Algorithm: */ if (likely(!*destnode)) { - publ = sseq->node_list; + publ = info->node_list; if (publ) { - sseq->node_list = publ->node_list_next; + info->node_list = publ->node_list_next; found: ref = publ->ref; *destnode = publ->node; @@ -619,35 +645,35 @@ found: read_unlock_bh(&tipc_nametbl_lock); return ref; } - publ = sseq->cluster_list; + publ = info->cluster_list; if (publ) { - sseq->cluster_list = publ->cluster_list_next; + info->cluster_list = publ->cluster_list_next; goto found; } - publ = sseq->zone_list; + publ = info->zone_list; if (publ) { - sseq->zone_list = publ->zone_list_next; + info->zone_list = publ->zone_list_next; goto found; } } /* Round-Robin Algorithm: */ else if (*destnode == tipc_own_addr) { - publ = sseq->node_list; + publ = info->node_list; if (publ) { - sseq->node_list = publ->node_list_next; + info->node_list = publ->node_list_next; goto found; } } else if (in_own_cluster(*destnode)) { - publ = sseq->cluster_list; + publ = info->cluster_list; if (publ) { - sseq->cluster_list = publ->cluster_list_next; + info->cluster_list = publ->cluster_list_next; goto found; } } else { - publ = sseq->zone_list; + publ = info->zone_list; if (publ) { - sseq->zone_list = publ->zone_list_next; + info->zone_list = publ->zone_list_next; goto found; } } @@ -676,6 +702,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, struct name_seq *seq; struct sub_seq *sseq; struct sub_seq *sseq_stop; + struct name_info *info; int res = 0; read_lock_bh(&tipc_nametbl_lock); @@ -693,16 +720,17 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, if (sseq->lower > upper) break; - publ = sseq->node_list; + info = sseq->info; + publ = info->node_list; if (publ) { do { if (publ->scope <= limit) tipc_port_list_add(dports, publ->ref); publ = publ->node_list_next; - } while (publ != sseq->node_list); + } while (publ != info->node_list); } - if (sseq->cluster_list_size != sseq->node_list_size) + if (info->cluster_list_size != info->node_list_size) res = 1; } @@ -840,7 +868,7 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, { char portIdStr[27]; const char *scope_str[] = {"", " zone", " cluster", " node"}; - struct publication *publ = sseq->zone_list; + struct publication *publ = sseq->info->zone_list; tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); @@ -860,7 +888,7 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, } publ = publ->zone_list_next; - if (publ == sseq->zone_list) + if (publ == sseq->info->zone_list) break; tipc_printf(buf, "\n%33s", " "); From f6f0a4d2d05f758f011a506731e84160d140304b Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 30 May 2011 10:48:48 -0400 Subject: [PATCH 10/20] tipc: Convert name table publication lists to standard kernel lists Modifies the main circular linked lists of publications used in TIPC's name table to use the standard kernel linked list type. This change simplifies the deletion of an existing publication by eliminating the need to search up to three lists to locate the publication. The use of standard list routines also helps improve the readability of the name table code by make it clearer what each list operation being performed is actually doing. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/name_table.c | 242 +++++++++++++++--------------------------- net/tipc/name_table.h | 14 +-- 2 files changed, 91 insertions(+), 165 deletions(-) diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 9cd58f8318f1..7d85cc1ace0e 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -2,7 +2,7 @@ * net/tipc/name_table.c: TIPC name table code * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2004-2008, Wind River Systems + * Copyright (c) 2004-2008, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,9 +58,9 @@ static int tipc_nametbl_size = 1024; /* must be a power of 2 */ */ struct name_info { - struct publication *node_list; - struct publication *cluster_list; - struct publication *zone_list; + struct list_head node_list; + struct list_head cluster_list; + struct list_head zone_list; u32 node_list_size; u32 cluster_list_size; u32 zone_list_size; @@ -311,6 +311,10 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, return NULL; } + INIT_LIST_HEAD(&info->node_list); + INIT_LIST_HEAD(&info->cluster_list); + INIT_LIST_HEAD(&info->zone_list); + /* Insert new sub-sequence */ sseq = &nseq->sseqs[inspos]; @@ -330,33 +334,17 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, if (!publ) return NULL; + list_add(&publ->zone_list, &info->zone_list); info->zone_list_size++; - if (!info->zone_list) - info->zone_list = publ->zone_list_next = publ; - else { - publ->zone_list_next = info->zone_list->zone_list_next; - info->zone_list->zone_list_next = publ; - } if (in_own_cluster(node)) { + list_add(&publ->cluster_list, &info->cluster_list); info->cluster_list_size++; - if (!info->cluster_list) - info->cluster_list = publ->cluster_list_next = publ; - else { - publ->cluster_list_next = - info->cluster_list->cluster_list_next; - info->cluster_list->cluster_list_next = publ; - } } if (node == tipc_own_addr) { + list_add(&publ->node_list, &info->node_list); info->node_list_size++; - if (!info->node_list) - info->node_list = publ->node_list_next = publ; - else { - publ->node_list_next = info->node_list->node_list_next; - info->node_list->node_list_next = publ; - } } /* @@ -390,8 +378,6 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i u32 node, u32 ref, u32 key) { struct publication *publ; - struct publication *curr; - struct publication *prev; struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); struct name_info *info; struct sub_seq *free; @@ -403,96 +389,38 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i info = sseq->info; + /* Locate publication, if it exists */ + + list_for_each_entry(publ, &info->zone_list, zone_list) { + if ((publ->key == key) && (publ->ref == ref) && + (!publ->node || (publ->node == node))) + goto found; + } + return NULL; + +found: /* Remove publication from zone scope list */ - prev = info->zone_list; - publ = info->zone_list->zone_list_next; - while ((publ->key != key) || (publ->ref != ref) || - (publ->node && (publ->node != node))) { - prev = publ; - publ = publ->zone_list_next; - if (prev == info->zone_list) { - - /* Prevent endless loop if publication not found */ - - return NULL; - } - } - if (publ != info->zone_list) - prev->zone_list_next = publ->zone_list_next; - else if (publ->zone_list_next != publ) { - prev->zone_list_next = publ->zone_list_next; - info->zone_list = publ->zone_list_next; - } else { - info->zone_list = NULL; - } + list_del(&publ->zone_list); info->zone_list_size--; /* Remove publication from cluster scope list, if present */ if (in_own_cluster(node)) { - prev = info->cluster_list; - curr = info->cluster_list->cluster_list_next; - while (curr != publ) { - prev = curr; - curr = curr->cluster_list_next; - if (prev == info->cluster_list) { - - /* Prevent endless loop for malformed list */ - - err("Unable to de-list cluster publication\n" - "{%u%u}, node=0x%x, ref=%u, key=%u)\n", - publ->type, publ->lower, publ->node, - publ->ref, publ->key); - goto end_cluster; - } - } - if (publ != info->cluster_list) - prev->cluster_list_next = publ->cluster_list_next; - else if (publ->cluster_list_next != publ) { - prev->cluster_list_next = publ->cluster_list_next; - info->cluster_list = publ->cluster_list_next; - } else { - info->cluster_list = NULL; - } + list_del(&publ->cluster_list); info->cluster_list_size--; } -end_cluster: /* Remove publication from node scope list, if present */ if (node == tipc_own_addr) { - prev = info->node_list; - curr = info->node_list->node_list_next; - while (curr != publ) { - prev = curr; - curr = curr->node_list_next; - if (prev == info->node_list) { - - /* Prevent endless loop for malformed list */ - - err("Unable to de-list node publication\n" - "{%u%u}, node=0x%x, ref=%u, key=%u)\n", - publ->type, publ->lower, publ->node, - publ->ref, publ->key); - goto end_node; - } - } - if (publ != info->node_list) - prev->node_list_next = publ->node_list_next; - else if (publ->node_list_next != publ) { - prev->node_list_next = publ->node_list_next; - info->node_list = publ->node_list_next; - } else { - info->node_list = NULL; - } + list_del(&publ->node_list); info->node_list_size--; } -end_node: /* Contract subseq list if no more publications for that subseq */ - if (!info->zone_list) { + if (list_empty(&info->zone_list)) { kfree(info); free = &nseq->sseqs[nseq->first_free--]; memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq)); @@ -530,12 +458,12 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s return; while (sseq != &nseq->sseqs[nseq->first_free]) { - struct publication *zl = sseq->info->zone_list; - if (zl && tipc_subscr_overlap(s, sseq->lower, sseq->upper)) { - struct publication *crs = zl; + if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) { + struct publication *crs; + struct name_info *info = sseq->info; int must_report = 1; - do { + list_for_each_entry(crs, &info->zone_list, zone_list) { tipc_subscr_report_overlap(s, sseq->lower, sseq->upper, @@ -544,8 +472,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s crs->node, must_report); must_report = 0; - crs = crs->zone_list_next; - } while (crs != zl); + } } sseq++; } @@ -616,9 +543,9 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) { struct sub_seq *sseq; struct name_info *info; - struct publication *publ = NULL; + struct publication *publ; struct name_seq *seq; - u32 ref; + u32 ref = 0; if (!tipc_in_scope(*destnode, tipc_own_addr)) return 0; @@ -635,52 +562,56 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) /* Closest-First Algorithm: */ if (likely(!*destnode)) { - publ = info->node_list; - if (publ) { - info->node_list = publ->node_list_next; -found: - ref = publ->ref; - *destnode = publ->node; - spin_unlock_bh(&seq->lock); - read_unlock_bh(&tipc_nametbl_lock); - return ref; - } - publ = info->cluster_list; - if (publ) { - info->cluster_list = publ->cluster_list_next; - goto found; - } - publ = info->zone_list; - if (publ) { - info->zone_list = publ->zone_list_next; - goto found; - } + if (!list_empty(&info->node_list)) { + publ = list_first_entry(&info->node_list, + struct publication, + node_list); + list_move_tail(&publ->node_list, + &info->node_list); + } else if (!list_empty(&info->cluster_list)) { + publ = list_first_entry(&info->cluster_list, + struct publication, + cluster_list); + list_move_tail(&publ->cluster_list, + &info->cluster_list); + } else if (!list_empty(&info->zone_list)) { + publ = list_first_entry(&info->zone_list, + struct publication, + zone_list); + list_move_tail(&publ->zone_list, + &info->zone_list); + } else + goto no_match; } /* Round-Robin Algorithm: */ else if (*destnode == tipc_own_addr) { - publ = info->node_list; - if (publ) { - info->node_list = publ->node_list_next; - goto found; - } + if (list_empty(&info->node_list)) + goto no_match; + publ = list_first_entry(&info->node_list, struct publication, + node_list); + list_move_tail(&publ->node_list, &info->node_list); } else if (in_own_cluster(*destnode)) { - publ = info->cluster_list; - if (publ) { - info->cluster_list = publ->cluster_list_next; - goto found; - } + if (list_empty(&info->cluster_list)) + goto no_match; + publ = list_first_entry(&info->cluster_list, struct publication, + cluster_list); + list_move_tail(&publ->cluster_list, &info->cluster_list); } else { - publ = info->zone_list; - if (publ) { - info->zone_list = publ->zone_list_next; - goto found; - } + if (list_empty(&info->zone_list)) + goto no_match; + publ = list_first_entry(&info->zone_list, struct publication, + zone_list); + list_move_tail(&publ->zone_list, &info->zone_list); } + + ref = publ->ref; + *destnode = publ->node; +no_match: spin_unlock_bh(&seq->lock); not_found: read_unlock_bh(&tipc_nametbl_lock); - return 0; + return ref; } /** @@ -721,13 +652,9 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, break; info = sseq->info; - publ = info->node_list; - if (publ) { - do { - if (publ->scope <= limit) - tipc_port_list_add(dports, publ->ref); - publ = publ->node_list_next; - } while (publ != info->node_list); + list_for_each_entry(publ, &info->node_list, node_list) { + if (publ->scope <= limit) + tipc_port_list_add(dports, publ->ref); } if (info->cluster_list_size != info->node_list_size) @@ -868,16 +795,19 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, { char portIdStr[27]; const char *scope_str[] = {"", " zone", " cluster", " node"}; - struct publication *publ = sseq->info->zone_list; + struct publication *publ; + struct name_info *info; tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); - if (depth == 2 || !publ) { + if (depth == 2) { tipc_printf(buf, "\n"); return; } - do { + info = sseq->info; + + list_for_each_entry(publ, &info->zone_list, zone_list) { sprintf(portIdStr, "<%u.%u.%u:%u>", tipc_zone(publ->node), tipc_cluster(publ->node), tipc_node(publ->node), publ->ref); @@ -886,13 +816,9 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, tipc_printf(buf, "%-10u %s", publ->key, scope_str[publ->scope]); } - - publ = publ->zone_list_next; - if (publ == sseq->info->zone_list) - break; - - tipc_printf(buf, "\n%33s", " "); - } while (1); + if (!list_is_last(&publ->zone_list, &info->zone_list)) + tipc_printf(buf, "\n%33s", " "); + }; tipc_printf(buf, "\n"); } diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index d228bd682655..62d77e5e902e 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -2,7 +2,7 @@ * net/tipc/name_table.h: Include file for TIPC name table code * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2004-2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,9 +61,9 @@ struct port_list; * @subscr: subscription to "node down" event (for off-node publications only) * @local_list: adjacent entries in list of publications made by this node * @pport_list: adjacent entries in list of publications made by this port - * @node_list: next matching name seq publication with >= node scope - * @cluster_list: next matching name seq publication with >= cluster scope - * @zone_list: next matching name seq publication with >= zone scope + * @node_list: adjacent matching name seq publications with >= node scope + * @cluster_list: adjacent matching name seq publications with >= cluster scope + * @zone_list: adjacent matching name seq publications with >= zone scope * * Note that the node list, cluster list, and zone list are circular lists. */ @@ -79,9 +79,9 @@ struct publication { struct tipc_node_subscr subscr; struct list_head local_list; struct list_head pport_list; - struct publication *node_list_next; - struct publication *cluster_list_next; - struct publication *zone_list_next; + struct list_head node_list; + struct list_head cluster_list; + struct list_head zone_list; }; From 8af4638a297b43c4929fdc01456b7f0698de0c0e Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 30 May 2011 11:27:50 -0400 Subject: [PATCH 11/20] tipc: Eliminate checks for empty zone list during name translation Gets rid of a pair of checks to see if a name sequence entry in TIPC's name table has an empty zone list. These checks are pointless since the zone list can never be empty (i.e. as soon as the list becomes empty the associated name sequence entry is deleted). Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/name_table.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 7d85cc1ace0e..46e6b6c2ecc9 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -574,14 +574,13 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) cluster_list); list_move_tail(&publ->cluster_list, &info->cluster_list); - } else if (!list_empty(&info->zone_list)) { + } else { publ = list_first_entry(&info->zone_list, struct publication, zone_list); list_move_tail(&publ->zone_list, &info->zone_list); - } else - goto no_match; + } } /* Round-Robin Algorithm: */ @@ -598,8 +597,6 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) cluster_list); list_move_tail(&publ->cluster_list, &info->cluster_list); } else { - if (list_empty(&info->zone_list)) - goto no_match; publ = list_first_entry(&info->zone_list, struct publication, zone_list); list_move_tail(&publ->zone_list, &info->zone_list); From 0f305bf4218c75b6fd1283105bd88736157aa5d2 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 30 May 2011 15:36:56 -0400 Subject: [PATCH 12/20] tipc: Correct typo in link statistics output Fixes a minor error in the title of one of the message size profiling values printed as part of TIPC's link statistics. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 5ed4b4f7452d..5bfe000b2a6b 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2882,7 +2882,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) profile_total = 1; tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n" " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " - "-16354:%u%% -32768:%u%% -66000:%u%%\n", + "-16384:%u%% -32768:%u%% -66000:%u%%\n", l_ptr->stats.msg_length_counts, l_ptr->stats.msg_lengths_total / profile_total, percent(l_ptr->stats.msg_length_profile[0], profile_total), From f01a2b6378f757727b205419b677d45edfcc5a3b Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 30 May 2011 15:43:02 -0400 Subject: [PATCH 13/20] tipc: Eliminate unused field in bearer structure Gets rid of counter that records the number of times a bearer has resumed after congestion or blocking, since the value is never referenced anywhere. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bearer.c | 1 - net/tipc/bearer.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 85209eadfae6..85eba9c08ee9 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -402,7 +402,6 @@ void tipc_bearer_lock_push(struct tipc_bearer *b_ptr) void tipc_continue(struct tipc_bearer *b_ptr) { spin_lock_bh(&b_ptr->lock); - b_ptr->continue_count++; if (!list_empty(&b_ptr->cong_links)) tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr); b_ptr->blocked = 0; diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 31d6172b20fd..5ad70eff1ebf 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -107,7 +107,6 @@ struct media { * @link_req: ptr to (optional) structure making periodic link setup requests * @links: list of non-congested links associated with bearer * @cong_links: list of congested links associated with bearer - * @continue_count: # of times bearer has resumed after congestion or blocking * @active: non-zero if bearer structure is represents a bearer * @net_plane: network plane ('A' through 'H') currently associated with bearer * @nodes: indicates which nodes in cluster can be reached through bearer @@ -129,7 +128,6 @@ struct tipc_bearer { struct link_req *link_req; struct list_head links; struct list_head cong_links; - u32 continue_count; int active; char net_plane; struct tipc_node_map nodes; From a9948ba24f764694413207812d2b2dae46eb7275 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 30 May 2011 15:50:35 -0400 Subject: [PATCH 14/20] tipc: Remove unnecessary includes in socket code Eliminates a pair of #include statements for files that are brought in automatically by including core.h. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/socket.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 338837396642..adb2eff4a102 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -36,9 +36,6 @@ #include -#include -#include - #include "core.h" #include "port.h" From 15f4e2b30372695573bc46102790094a92b3eb11 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 31 May 2011 14:35:18 -0400 Subject: [PATCH 15/20] tipc: Eliminate useless check when creating internal message Gets rid of code that allows tipc_msg_init() to create a short payload message header. This optimization is possible because there are no longer any callers who require this capability. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/msg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 03e57bf92c73..83d50967910c 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -61,10 +61,8 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, msg_set_size(m, hsize); msg_set_prevnode(m, tipc_own_addr); msg_set_type(m, type); - if (!msg_short(m)) { - msg_set_orignode(m, tipc_own_addr); - msg_set_destnode(m, destnode); - } + msg_set_orignode(m, tipc_own_addr); + msg_set_destnode(m, destnode); } /** From 741d9eb7b8f352071f56aacb77f5245b4e2a4fbe Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 31 May 2011 15:03:18 -0400 Subject: [PATCH 16/20] tipc: Cleanup of message header size terminology Performs cosmetic cleanup of the symbolic names used to specify TIPC payload message header sizes. The revised names now more accurately reflect the payload messages in which they can appear. In addition, several places where these payload message symbol names were being used to create non-payload messages have been updated to use the proper internal message symbolic name. No functional changes are introduced by this rework. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 4 ++-- net/tipc/msg.h | 10 +++++----- net/tipc/name_distr.c | 6 +++--- net/tipc/port.c | 20 ++++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 5bfe000b2a6b..f89570c54f54 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1572,7 +1572,7 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr, static int link_recv_buf_validate(struct sk_buff *buf) { static u32 min_data_hdr_size[8] = { - SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE, + SHORT_H_SIZE, MCAST_H_SIZE, NAMED_H_SIZE, BASIC_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE }; @@ -2553,7 +2553,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, u32 msg_sz = msg_size(imsg); u32 fragm_sz = msg_data_sz(fragm); u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz); - u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE; + u32 max = TIPC_MAX_USER_MSG_SIZE + NAMED_H_SIZE; if (msg_type(imsg) == TIPC_MCAST_MSG) max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; if (msg_size(imsg) > max) { diff --git a/net/tipc/msg.h b/net/tipc/msg.h index a58975ced222..d93178f2e852 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -68,10 +68,10 @@ * Message header sizes */ -#define SHORT_H_SIZE 24 /* Connected, in-cluster messages */ -#define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ -#define LONG_H_SIZE 40 /* Named messages */ -#define MCAST_H_SIZE 44 /* Multicast messages */ +#define SHORT_H_SIZE 24 /* In-cluster basic payload message */ +#define BASIC_H_SIZE 32 /* Basic payload message */ +#define NAMED_H_SIZE 40 /* Named payload message */ +#define MCAST_H_SIZE 44 /* Multicast payload message */ #define INT_H_SIZE 40 /* Internal messages */ #define MIN_H_SIZE 24 /* Smallest legal TIPC header size */ #define MAX_H_SIZE 60 /* Largest possible TIPC header size */ @@ -357,7 +357,7 @@ static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) static inline int msg_short(struct tipc_msg *m) { - return msg_hdr_sz(m) == 24; + return msg_hdr_sz(m) == SHORT_H_SIZE; } static inline u32 msg_orignode(struct tipc_msg *m) diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 80025a1b3bfd..cd356e504332 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -94,13 +94,13 @@ static void publ_to_item(struct distr_item *i, struct publication *p) static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) { - struct sk_buff *buf = tipc_buf_acquire(LONG_H_SIZE + size); + struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size); struct tipc_msg *msg; if (buf != NULL) { msg = buf_msg(buf); - tipc_msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest); - msg_set_size(msg, LONG_H_SIZE + size); + tipc_msg_init(msg, NAME_DISTRIBUTOR, type, INT_H_SIZE, dest); + msg_set_size(msg, INT_H_SIZE + size); } return buf; } diff --git a/net/tipc/port.c b/net/tipc/port.c index 53118171b7e6..70e9de577113 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -222,7 +222,7 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, p_ptr->max_pkt = MAX_PKT_DEFAULT; p_ptr->ref = ref; msg = &p_ptr->phdr; - tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); + tipc_msg_init(msg, importance, TIPC_NAMED_MSG, NAMED_H_SIZE, 0); msg_set_origport(msg, ref); INIT_LIST_HEAD(&p_ptr->wait_list); INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); @@ -339,10 +339,10 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, struct sk_buff *buf; struct tipc_msg *msg; - buf = tipc_buf_acquire(LONG_H_SIZE); + buf = tipc_buf_acquire(INT_H_SIZE); if (buf) { msg = buf_msg(buf); - tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode); + tipc_msg_init(msg, usr, type, INT_H_SIZE, destnode); msg_set_errcode(msg, err); msg_set_destport(msg, destport); msg_set_origport(msg, origport); @@ -1247,7 +1247,7 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, msg_set_type(msg, TIPC_NAMED_MSG); msg_set_orignode(msg, tipc_own_addr); msg_set_origport(msg, ref); - msg_set_hdr_sz(msg, LONG_H_SIZE); + msg_set_hdr_sz(msg, NAMED_H_SIZE); msg_set_nametype(msg, name->type); msg_set_nameinst(msg, name->instance); msg_set_lookup_scope(msg, tipc_addr_scope(domain)); @@ -1300,7 +1300,7 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, msg_set_origport(msg, ref); msg_set_destnode(msg, dest->node); msg_set_destport(msg, dest->ref); - msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); + msg_set_hdr_sz(msg, BASIC_H_SIZE); if (dest->node == tipc_own_addr) res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, @@ -1340,13 +1340,13 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, msg_set_origport(msg, ref); msg_set_destnode(msg, dest->node); msg_set_destport(msg, dest->ref); - msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); - msg_set_size(msg, DIR_MSG_H_SIZE + dsz); - if (skb_cow(buf, DIR_MSG_H_SIZE)) + msg_set_hdr_sz(msg, BASIC_H_SIZE); + msg_set_size(msg, BASIC_H_SIZE + dsz); + if (skb_cow(buf, BASIC_H_SIZE)) return -ENOMEM; - skb_push(buf, DIR_MSG_H_SIZE); - skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE); + skb_push(buf, BASIC_H_SIZE); + skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE); if (dest->node == tipc_own_addr) res = tipc_port_recv_msg(buf); From e244a915ff7676b1567ba68102c9b53011f5b766 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 31 May 2011 16:10:08 -0400 Subject: [PATCH 17/20] tipc: Optimize creation of FIN messages Speeds up the creation of the FIN message that terminates a TIPC connection. The typical peer termination message is now created by duplicating the terminating port's standard payload message header and adjusting the message size, importance, and error code fields, rather than building all fields of the message from scratch. A FIN message that is directed to the port itself is created the same way. but also requires swapping the origin and destination address fields. In addition to reducing the work required to create FIN messages, these changes eliminate several instances of duplicated code, Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 61 +++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index 70e9de577113..8be68e0bf300 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -489,39 +489,38 @@ static void port_handle_node_down(unsigned long ref) static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err) { - u32 imp = msg_importance(&p_ptr->phdr); + struct sk_buff *buf = port_build_peer_abort_msg(p_ptr, err); - if (!p_ptr->connected) - return NULL; - if (imp < TIPC_CRITICAL_IMPORTANCE) - imp++; - return port_build_proto_msg(p_ptr->ref, - tipc_own_addr, - port_peerport(p_ptr), - port_peernode(p_ptr), - imp, - TIPC_CONN_MSG, - err, - 0); + if (buf) { + struct tipc_msg *msg = buf_msg(buf); + msg_swap_words(msg, 4, 5); + msg_swap_words(msg, 6, 7); + } + return buf; } static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err) { - u32 imp = msg_importance(&p_ptr->phdr); + struct sk_buff *buf; + struct tipc_msg *msg; + u32 imp; if (!p_ptr->connected) return NULL; - if (imp < TIPC_CRITICAL_IMPORTANCE) - imp++; - return port_build_proto_msg(port_peerport(p_ptr), - port_peernode(p_ptr), - p_ptr->ref, - tipc_own_addr, - imp, - TIPC_CONN_MSG, - err, - 0); + + buf = tipc_buf_acquire(BASIC_H_SIZE); + if (buf) { + msg = buf_msg(buf); + memcpy(msg, &p_ptr->phdr, BASIC_H_SIZE); + msg_set_hdr_sz(msg, BASIC_H_SIZE); + msg_set_size(msg, BASIC_H_SIZE); + imp = msg_importance(msg); + if (imp < TIPC_CRITICAL_IMPORTANCE) + msg_set_importance(msg, ++imp); + msg_set_errcode(msg, err); + } + return buf; } void tipc_port_recv_proto_msg(struct sk_buff *buf) @@ -1149,19 +1148,7 @@ int tipc_shutdown(u32 ref) if (!p_ptr) return -EINVAL; - if (p_ptr->connected) { - u32 imp = msg_importance(&p_ptr->phdr); - if (imp < TIPC_CRITICAL_IMPORTANCE) - imp++; - buf = port_build_proto_msg(port_peerport(p_ptr), - port_peernode(p_ptr), - ref, - tipc_own_addr, - imp, - TIPC_CONN_MSG, - TIPC_CONN_SHUTDOWN, - 0); - } + buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN); tipc_port_unlock(p_ptr); tipc_net_route_msg(buf); return tipc_disconnect(ref); From 1c1a551acb8b65f842824900b283a96462f907ab Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 1 Jun 2011 15:08:10 -0400 Subject: [PATCH 18/20] tipc: Reject connection protocol message sent to unconnected port Restructures the logic used in tipc_port_recv_proto_msg() to ensure that incoming connection protocol messages are handled properly. The routine now uses a two-stage process that first ensures the message applies on an existing connection and then processes the request. This corrects a loophole that allowed a connection probe request to be processed if it was sent to an unconnected port that had no names bound to it. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 77 +++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index 8be68e0bf300..1b20b963a2fc 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -526,62 +526,63 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er void tipc_port_recv_proto_msg(struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); - struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); - u32 err = TIPC_OK; + struct tipc_port *p_ptr; struct sk_buff *r_buf = NULL; - struct sk_buff *abort_buf = NULL; + u32 orignode = msg_orignode(msg); + u32 origport = msg_origport(msg); + u32 destport = msg_destport(msg); + int wakeable; - if (!p_ptr) { - err = TIPC_ERR_NO_PORT; - } else if (p_ptr->connected) { - if ((port_peernode(p_ptr) != msg_orignode(msg)) || - (port_peerport(p_ptr) != msg_origport(msg))) { - err = TIPC_ERR_NO_PORT; - } else if (msg_type(msg) == CONN_ACK) { - int wakeup = tipc_port_congested(p_ptr) && - p_ptr->congested && - p_ptr->wakeup; - p_ptr->acked += msg_msgcnt(msg); - if (tipc_port_congested(p_ptr)) - goto exit; - p_ptr->congested = 0; - if (!wakeup) - goto exit; - p_ptr->wakeup(p_ptr); - goto exit; - } - } else if (p_ptr->published) { - err = TIPC_ERR_NO_PORT; - } - if (err) { - r_buf = port_build_proto_msg(msg_origport(msg), - msg_orignode(msg), - msg_destport(msg), + /* Validate connection */ + + p_ptr = tipc_port_lock(destport); + if (!p_ptr || !p_ptr->connected || + (port_peernode(p_ptr) != orignode) || + (port_peerport(p_ptr) != origport)) { + r_buf = port_build_proto_msg(origport, + orignode, + destport, tipc_own_addr, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG, - err, + TIPC_ERR_NO_PORT, 0); + if (p_ptr) + tipc_port_unlock(p_ptr); goto exit; } - /* All is fine */ - if (msg_type(msg) == CONN_PROBE) { - r_buf = port_build_proto_msg(msg_origport(msg), - msg_orignode(msg), - msg_destport(msg), + /* Process protocol message sent by peer */ + + switch (msg_type(msg)) { + case CONN_ACK: + wakeable = tipc_port_congested(p_ptr) && p_ptr->congested && + p_ptr->wakeup; + p_ptr->acked += msg_msgcnt(msg); + if (!tipc_port_congested(p_ptr)) { + p_ptr->congested = 0; + if (wakeable) + p_ptr->wakeup(p_ptr); + } + break; + case CONN_PROBE: + r_buf = port_build_proto_msg(origport, + orignode, + destport, tipc_own_addr, CONN_MANAGER, CONN_PROBE_REPLY, TIPC_OK, 0); + break; + default: + /* CONN_PROBE_REPLY or unrecognized - no action required */ + break; } p_ptr->probing_state = CONFIRMED; + tipc_port_unlock(p_ptr); exit: - if (p_ptr) - tipc_port_unlock(p_ptr); tipc_net_route_msg(r_buf); - tipc_net_route_msg(abort_buf); buf_discard(buf); } From f55b564054e35dcd171e1191a477327528271f95 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 1 Jun 2011 15:48:42 -0400 Subject: [PATCH 19/20] tipc: Don't create payload message using connection protocol routine Modifies the logic that creates a connection termination payload message so that it no longer (mis)uses a routine that creates a connection protocol message. The revised code is now more easily understood, and avoids setting several fields that are either not present in payload messages or were being set more than once. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index 1b20b963a2fc..ab0a8e97e315 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -539,14 +539,15 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) if (!p_ptr || !p_ptr->connected || (port_peernode(p_ptr) != orignode) || (port_peerport(p_ptr) != origport)) { - r_buf = port_build_proto_msg(origport, - orignode, - destport, - tipc_own_addr, - TIPC_HIGH_IMPORTANCE, - TIPC_CONN_MSG, - TIPC_ERR_NO_PORT, - 0); + r_buf = tipc_buf_acquire(BASIC_H_SIZE); + if (r_buf) { + msg = buf_msg(r_buf); + tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG, + BASIC_H_SIZE, orignode); + msg_set_errcode(msg, TIPC_ERR_NO_PORT); + msg_set_origport(msg, destport); + msg_set_destport(msg, origport); + } if (p_ptr) tipc_port_unlock(p_ptr); goto exit; From e4a0aee47e1823025972b8f3defde432e485b7b9 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 1 Jun 2011 16:21:12 -0400 Subject: [PATCH 20/20] tipc: Optimize creation of connection protocol messages Simplifies the creation of connection protocol messages by eliminating the passing of information that is no longer required, is constant, or is contained within the port structure that is issuing the message. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 48 ++++++++++++------------------------------------ 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index ab0a8e97e315..54d812a5a4d9 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -327,14 +327,12 @@ int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) } /* - * port_build_proto_msg(): build a port level protocol - * or a connection abortion message. Called with - * tipc_port lock on. + * port_build_proto_msg(): create connection protocol message for port + * + * On entry the port must be locked and connected. */ -static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, - u32 origport, u32 orignode, - u32 usr, u32 type, u32 err, - u32 ack) +static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr, + u32 type, u32 ack) { struct sk_buff *buf; struct tipc_msg *msg; @@ -342,11 +340,10 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, buf = tipc_buf_acquire(INT_H_SIZE); if (buf) { msg = buf_msg(buf); - tipc_msg_init(msg, usr, type, INT_H_SIZE, destnode); - msg_set_errcode(msg, err); - msg_set_destport(msg, destport); - msg_set_origport(msg, origport); - msg_set_orignode(msg, orignode); + tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE, + port_peernode(p_ptr)); + msg_set_destport(msg, port_peerport(p_ptr)); + msg_set_origport(msg, p_ptr->ref); msg_set_msgcnt(msg, ack); } return buf; @@ -458,14 +455,7 @@ static void port_timeout(unsigned long ref) if (p_ptr->probing_state == PROBING) { buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); } else { - buf = port_build_proto_msg(port_peerport(p_ptr), - port_peernode(p_ptr), - p_ptr->ref, - tipc_own_addr, - CONN_MANAGER, - CONN_PROBE, - TIPC_OK, - 0); + buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0); p_ptr->probing_state = PROBING; k_start_timer(&p_ptr->timer, p_ptr->probing_interval); } @@ -567,14 +557,7 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) } break; case CONN_PROBE: - r_buf = port_build_proto_msg(origport, - orignode, - destport, - tipc_own_addr, - CONN_MANAGER, - CONN_PROBE_REPLY, - TIPC_OK, - 0); + r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0); break; default: /* CONN_PROBE_REPLY or unrecognized - no action required */ @@ -899,14 +882,7 @@ void tipc_acknowledge(u32 ref, u32 ack) return; if (p_ptr->connected) { p_ptr->conn_unacked -= ack; - buf = port_build_proto_msg(port_peerport(p_ptr), - port_peernode(p_ptr), - ref, - tipc_own_addr, - CONN_MANAGER, - CONN_ACK, - TIPC_OK, - ack); + buf = port_build_proto_msg(p_ptr, CONN_ACK, ack); } tipc_port_unlock(p_ptr); tipc_net_route_msg(buf);