aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2011-10-28 17:30:08 -0400
committerPaul Gortmaker <paul.gortmaker@windriver.com>2012-02-24 17:05:13 -0500
commit97878a405c0ffe0f6433e1fb51834d4619ece025 (patch)
tree1893ca2ba6775bcac3cc336e41fe96dac10fd96f /net/tipc
parentfc0eea691a06ba8516795fb7a198239fb9db1cfc (diff)
tipc: Detect duplicate nodes using different network interfaces
Utilizes the new "node signature" field in neighbor discovery messages to ensure that all links TIPC associates with a given <Z.C.N> network address belong to the same neighboring node. (Previously, TIPC could not tell if link setup requests arriving on different interfaces were from the same node or from two different nodes that has mistakenly been assigned the same network address.) The revised algorithm for detecting a duplicate node considers both the node signature and the network interface adddress specified in a request message when deciding how to respond to a link setup request. This prevents false alarms that might otherwise arise during normal network operation under the following scenarios: a) A neighboring node reboots. (The node's signature changes, but the network interface address remains unchanged.) b) A neighboring node's network interface is replaced. (The node's signature remains unchanged, but the network interface address changes.) c) A neighboring node is completely replaced. (The node's signature and network interface address both change.) The algorithm also handles cases in which a node reboots and re-establishes its links to TIPC (or begins re-establishing those links) before TIPC detects that it is using a new node signature. In such cases of "delayed rediscovery" TIPC simply accepts the new signature without disrupting communication that is already underway over the links. Thanks to Laser [gotolaser@gmail.com] for his contributions to the development of this enhancement. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/discover.c72
1 files changed, 58 insertions, 14 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 7ae1b4c33aeb..f5f9bf7a0436 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -122,7 +122,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
122{ 122{
123 struct tipc_node *n_ptr; 123 struct tipc_node *n_ptr;
124 struct tipc_link *link; 124 struct tipc_link *link;
125 struct tipc_media_addr media_addr, *addr; 125 struct tipc_media_addr media_addr;
126 struct sk_buff *rbuf; 126 struct sk_buff *rbuf;
127 struct tipc_msg *msg = buf_msg(buf); 127 struct tipc_msg *msg = buf_msg(buf);
128 u32 dest = msg_dest_domain(msg); 128 u32 dest = msg_dest_domain(msg);
@@ -130,13 +130,14 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
130 u32 net_id = msg_bc_netid(msg); 130 u32 net_id = msg_bc_netid(msg);
131 u32 type = msg_type(msg); 131 u32 type = msg_type(msg);
132 u32 signature = msg_node_sig(msg); 132 u32 signature = msg_node_sig(msg);
133 int addr_mismatch;
133 int link_fully_up; 134 int link_fully_up;
134 135
135 media_addr.broadcast = 1; 136 media_addr.broadcast = 1;
136 b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg)); 137 b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg));
137 buf_discard(buf); 138 buf_discard(buf);
138 139
139 /* Validate discovery message from requesting node */ 140 /* Ensure message from node is valid and communication is permitted */
140 if (net_id != tipc_net_id) 141 if (net_id != tipc_net_id)
141 return; 142 return;
142 if (media_addr.broadcast) 143 if (media_addr.broadcast)
@@ -164,15 +165,50 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
164 } 165 }
165 tipc_node_lock(n_ptr); 166 tipc_node_lock(n_ptr);
166 167
168 /* Prepare to validate requesting node's signature and media address */
167 link = n_ptr->links[b_ptr->identity]; 169 link = n_ptr->links[b_ptr->identity];
170 addr_mismatch = (link != NULL) &&
171 memcmp(&link->media_addr, &media_addr, sizeof(media_addr));
168 172
169 /* Create a link endpoint for this bearer, if necessary */ 173 /*
170 if (!link) { 174 * Ensure discovery message's signature is correct
171 link = tipc_link_create(n_ptr, b_ptr, &media_addr); 175 *
172 if (!link) { 176 * If signature is incorrect and there is no working link to the node,
177 * accept the new signature but invalidate all existing links to the
178 * node so they won't re-activate without a new discovery message.
179 *
180 * If signature is incorrect and the requested link to the node is
181 * working, accept the new signature. (This is an instance of delayed
182 * rediscovery, where a link endpoint was able to re-establish contact
183 * with its peer endpoint on a node that rebooted before receiving a
184 * discovery message from that node.)
185 *
186 * If signature is incorrect and there is a working link to the node
187 * that is not the requested link, reject the request (must be from
188 * a duplicate node).
189 */
190 if (signature != n_ptr->signature) {
191 if (n_ptr->working_links == 0) {
192 struct tipc_link *curr_link;
193 int i;
194
195 for (i = 0; i < MAX_BEARERS; i++) {
196 curr_link = n_ptr->links[i];
197 if (curr_link) {
198 memset(&curr_link->media_addr, 0,
199 sizeof(media_addr));
200 tipc_link_reset(curr_link);
201 }
202 }
203 addr_mismatch = (link != NULL);
204 } else if (tipc_link_is_up(link) && !addr_mismatch) {
205 /* delayed rediscovery */
206 } else {
207 disc_dupl_alert(b_ptr, orig, &media_addr);
173 tipc_node_unlock(n_ptr); 208 tipc_node_unlock(n_ptr);
174 return; 209 return;
175 } 210 }
211 n_ptr->signature = signature;
176 } 212 }
177 213
178 /* 214 /*
@@ -185,21 +221,29 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
185 * the new media address and reset the link to ensure it starts up 221 * the new media address and reset the link to ensure it starts up
186 * cleanly. 222 * cleanly.
187 */ 223 */
188 addr = &link->media_addr; 224
189 if (memcmp(addr, &media_addr, sizeof(*addr))) { 225 if (addr_mismatch) {
190 if (tipc_link_is_up(link) || (!link->started)) { 226 if (tipc_link_is_up(link)) {
191 disc_dupl_alert(b_ptr, orig, &media_addr); 227 disc_dupl_alert(b_ptr, orig, &media_addr);
192 tipc_node_unlock(n_ptr); 228 tipc_node_unlock(n_ptr);
193 return; 229 return;
230 } else {
231 memcpy(&link->media_addr, &media_addr,
232 sizeof(media_addr));
233 tipc_link_reset(link);
234 }
235 }
236
237 /* Create a link endpoint for this bearer, if necessary */
238 if (!link) {
239 link = tipc_link_create(n_ptr, b_ptr, &media_addr);
240 if (!link) {
241 tipc_node_unlock(n_ptr);
242 return;
194 } 243 }
195 warn("Resetting link <%s>, peer interface address changed\n",
196 link->name);
197 memcpy(addr, &media_addr, sizeof(*addr));
198 tipc_link_reset(link);
199 } 244 }
200 245
201 /* Accept discovery message & send response, if necessary */ 246 /* Accept discovery message & send response, if necessary */
202 n_ptr->signature = signature;
203 link_fully_up = link_working_working(link); 247 link_fully_up = link_working_working(link);
204 248
205 if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) { 249 if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {