diff options
| -rw-r--r-- | net/tipc/node.c | 106 | ||||
| -rw-r--r-- | net/tipc/node.h | 26 |
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); |
| 146 | exit: | 148 | exit: |
| 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 | */ |
| 228 | void tipc_node_link_up(struct tipc_node *n, int bearer_id) | 230 | void 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 | */ | ||
| 273 | static 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 | */ |
| 299 | void tipc_node_link_down(struct tipc_node *n, int bearer_id) | 277 | void 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 | ||
| 333 | bool tipc_node_is_up(struct tipc_node *n) | 315 | bool 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 | ||
| 338 | void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *b, | 320 | void 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 | ||
| 177 | static inline struct tipc_link *node_active_link(struct tipc_node *n, int sel) | 179 | static 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 | ||
| 186 | static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector) | 189 | static 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 | } |
