aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/tipc/node.c106
-rw-r--r--net/tipc/node.h26
2 files changed, 59 insertions, 73 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 20ec61ceffac..19729645d494 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -142,6 +142,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
142 list_add_tail_rcu(&n_ptr->list, &temp_node->list); 142 list_add_tail_rcu(&n_ptr->list, &temp_node->list);
143 n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; 143 n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN;
144 n_ptr->signature = INVALID_NODE_SIG; 144 n_ptr->signature = INVALID_NODE_SIG;
145 n_ptr->active_links[0] = INVALID_BEARER_ID;
146 n_ptr->active_links[1] = INVALID_BEARER_ID;
145 tipc_node_get(n_ptr); 147 tipc_node_get(n_ptr);
146exit: 148exit:
147 spin_unlock_bh(&tn->node_list_lock); 149 spin_unlock_bh(&tn->node_list_lock);
@@ -227,12 +229,13 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
227 */ 229 */
228void tipc_node_link_up(struct tipc_node *n, int bearer_id) 230void tipc_node_link_up(struct tipc_node *n, int bearer_id)
229{ 231{
230 struct tipc_link_entry **actv = &n->active_links[0]; 232 int *slot0 = &n->active_links[0];
231 struct tipc_link_entry *le = &n->links[bearer_id]; 233 int *slot1 = &n->active_links[1];
232 struct tipc_link *l = le->link; 234 struct tipc_link_entry *links = n->links;
235 struct tipc_link *l = n->links[bearer_id].link;
233 236
234 /* Leave room for tunnel header when returning 'mtu' to users: */ 237 /* Leave room for tunnel header when returning 'mtu' to users: */
235 n->links[bearer_id].mtu = l->mtu - INT_H_SIZE; 238 links[bearer_id].mtu = l->mtu - INT_H_SIZE;
236 239
237 n->working_links++; 240 n->working_links++;
238 n->action_flags |= TIPC_NOTIFY_LINK_UP; 241 n->action_flags |= TIPC_NOTIFY_LINK_UP;
@@ -242,55 +245,30 @@ void tipc_node_link_up(struct tipc_node *n, int bearer_id)
242 l->name, l->net_plane); 245 l->name, l->net_plane);
243 246
244 /* No active links ? => take both active slots */ 247 /* No active links ? => take both active slots */
245 if (!actv[0]) { 248 if (*slot0 < 0) {
246 actv[0] = le; 249 *slot0 = bearer_id;
247 actv[1] = le; 250 *slot1 = bearer_id;
248 node_established_contact(n); 251 node_established_contact(n);
249 return; 252 return;
250 } 253 }
251 if (l->priority < actv[0]->link->priority) { 254
255 /* Lower prio than current active ? => no slot */
256 if (l->priority < links[*slot0].link->priority) {
252 pr_debug("New link <%s> becomes standby\n", l->name); 257 pr_debug("New link <%s> becomes standby\n", l->name);
253 return; 258 return;
254 } 259 }
255 tipc_link_dup_queue_xmit(actv[0]->link, l); 260 tipc_link_dup_queue_xmit(links[*slot0].link, l);
256 261
257 /* Take one active slot if applicable */ 262 /* Same prio as current active ? => take one slot */
258 if (l->priority == actv[0]->link->priority) { 263 if (l->priority == links[*slot0].link->priority) {
259 actv[0] = le; 264 *slot0 = bearer_id;
260 return; 265 return;
261 } 266 }
262 /* Higher prio than current active? => take both active slots */
263 pr_debug("Old l <%s> becomes standby\n", actv[0]->link->name);
264 if (actv[1] != actv[0])
265 pr_debug("Old link <%s> now standby\n", actv[1]->link->name);
266 actv[0] = le;
267 actv[1] = le;
268}
269
270/**
271 * node_select_active_links - select which working links should be active
272 */
273static void node_select_active_links(struct tipc_node *n)
274{
275 struct tipc_link_entry **actv = &n->active_links[0];
276 struct tipc_link *l;
277 u32 b, highest = 0;
278 267
279 actv[0] = NULL; 268 /* Higher prio than current active => take both active slots */
280 actv[1] = NULL; 269 pr_debug("Old link <%s> now standby\n", links[*slot0].link->name);
281 270 *slot0 = bearer_id;
282 for (b = 0; b < MAX_BEARERS; b++) { 271 *slot1 = bearer_id;
283 l = n->links[b].link;
284 if (!l || !tipc_link_is_up(l) || (l->priority < highest))
285 continue;
286 if (l->priority > highest) {
287 highest = l->priority;
288 actv[0] = &n->links[b];
289 actv[1] = &n->links[b];
290 continue;
291 }
292 actv[1] = &n->links[b];
293 }
294} 272}
295 273
296/** 274/**
@@ -298,32 +276,36 @@ static void node_select_active_links(struct tipc_node *n)
298 */ 276 */
299void tipc_node_link_down(struct tipc_node *n, int bearer_id) 277void tipc_node_link_down(struct tipc_node *n, int bearer_id)
300{ 278{
301 struct tipc_link_entry **actv = &n->active_links[0]; 279 int *slot0 = &n->active_links[0];
302 struct tipc_link_entry *le = &n->links[bearer_id]; 280 int *slot1 = &n->active_links[1];
303 struct tipc_link *l = le->link; 281 int i, highest = 0;
282 struct tipc_link *l, *_l;
304 283
284 l = n->links[bearer_id].link;
305 n->working_links--; 285 n->working_links--;
306 n->action_flags |= TIPC_NOTIFY_LINK_DOWN; 286 n->action_flags |= TIPC_NOTIFY_LINK_DOWN;
307 n->link_id = l->peer_bearer_id << 16 | l->bearer_id; 287 n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
308 288
309 if (!tipc_link_is_active(l)) {
310 pr_debug("Lost standby link <%s> on network plane %c\n",
311 l->name, l->net_plane);
312 return;
313 }
314 pr_debug("Lost link <%s> on network plane %c\n", 289 pr_debug("Lost link <%s> on network plane %c\n",
315 l->name, l->net_plane); 290 l->name, l->net_plane);
316 291
317 /* Resdistribute active slots if applicable */ 292 /* Select new active link if any available */
318 if (actv[0] == le) 293 *slot0 = INVALID_BEARER_ID;
319 actv[0] = actv[1]; 294 *slot1 = INVALID_BEARER_ID;
320 if (actv[1] == le) 295 for (i = 0; i < MAX_BEARERS; i++) {
321 actv[1] = actv[0]; 296 _l = n->links[i].link;
322 297 if (!_l || !tipc_link_is_up(_l))
323 /* Last link of this priority? => select other ones if available */ 298 continue;
324 if (actv[0] == le) 299 if (_l->priority < highest)
325 node_select_active_links(n); 300 continue;
326 301 if (_l->priority > highest) {
302 highest = _l->priority;
303 *slot0 = i;
304 *slot1 = i;
305 continue;
306 }
307 *slot1 = i;
308 }
327 if (tipc_node_is_up(n)) 309 if (tipc_node_is_up(n))
328 tipc_link_failover_send_queue(l); 310 tipc_link_failover_send_queue(l);
329 else 311 else
@@ -332,7 +314,7 @@ void tipc_node_link_down(struct tipc_node *n, int bearer_id)
332 314
333bool tipc_node_is_up(struct tipc_node *n) 315bool tipc_node_is_up(struct tipc_node *n)
334{ 316{
335 return n->active_links[0]; 317 return n->active_links[0] != INVALID_BEARER_ID;
336} 318}
337 319
338void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *b, 320void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *b,
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 0657cbf1f5cd..74f278adada3 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -45,6 +45,8 @@
45/* Out-of-range value for node signature */ 45/* Out-of-range value for node signature */
46#define INVALID_NODE_SIG 0x10000 46#define INVALID_NODE_SIG 0x10000
47 47
48#define INVALID_BEARER_ID -1
49
48/* Flags used to take different actions according to flag type 50/* Flags used to take different actions according to flag type
49 * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down 51 * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down
50 * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down 52 * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down
@@ -105,7 +107,7 @@ struct tipc_link_entry {
105 * @hash: links to adjacent nodes in unsorted hash chain 107 * @hash: links to adjacent nodes in unsorted hash chain
106 * @inputq: pointer to input queue containing messages for msg event 108 * @inputq: pointer to input queue containing messages for msg event
107 * @namedq: pointer to name table input queue with name table messages 109 * @namedq: pointer to name table input queue with name table messages
108 * @active_links: pointer into links[] array, identifying which links are active 110 * @active_links: bearer ids of active links, used as index into links[] array
109 * @links: array containing references to all links to node 111 * @links: array containing references to all links to node
110 * @action_flags: bit mask of different types of node actions 112 * @action_flags: bit mask of different types of node actions
111 * @bclink: broadcast-related info 113 * @bclink: broadcast-related info
@@ -126,7 +128,7 @@ struct tipc_node {
126 struct hlist_node hash; 128 struct hlist_node hash;
127 struct sk_buff_head *inputq; 129 struct sk_buff_head *inputq;
128 struct sk_buff_head *namedq; 130 struct sk_buff_head *namedq;
129 struct tipc_link_entry *active_links[2]; 131 int active_links[2];
130 struct tipc_link_entry links[MAX_BEARERS]; 132 struct tipc_link_entry links[MAX_BEARERS];
131 int action_flags; 133 int action_flags;
132 struct tipc_node_bclink bclink; 134 struct tipc_node_bclink bclink;
@@ -176,25 +178,27 @@ static inline bool tipc_node_blocked(struct tipc_node *node)
176 178
177static inline struct tipc_link *node_active_link(struct tipc_node *n, int sel) 179static inline struct tipc_link *node_active_link(struct tipc_node *n, int sel)
178{ 180{
179 struct tipc_link_entry *le = n->active_links[sel & 1]; 181 int bearer_id = n->active_links[sel & 1];
182
183 if (unlikely(bearer_id == INVALID_BEARER_ID))
184 return NULL;
180 185
181 if (likely(le)) 186 return n->links[bearer_id].link;
182 return le->link;
183 return NULL;
184} 187}
185 188
186static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector) 189static inline unsigned int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel)
187{ 190{
188 struct tipc_node *n; 191 struct tipc_node *n;
189 struct tipc_link_entry *le; 192 int bearer_id;
190 unsigned int mtu = MAX_MSG_SIZE; 193 unsigned int mtu = MAX_MSG_SIZE;
191 194
192 n = tipc_node_find(net, addr); 195 n = tipc_node_find(net, addr);
193 if (unlikely(!n)) 196 if (unlikely(!n))
194 return mtu; 197 return mtu;
195 le = n->active_links[selector & 1]; 198
196 if (likely(le)) 199 bearer_id = n->active_links[sel & 1];
197 mtu = le->mtu; 200 if (likely(bearer_id != INVALID_BEARER_ID))
201 mtu = n->links[bearer_id].mtu;
198 tipc_node_put(n); 202 tipc_node_put(n);
199 return mtu; 203 return mtu;
200} 204}