Skip to content

Commit dff29b1

Browse files
Jon Paul Maloydavem330
authored andcommitted
tipc: eliminate delayed link deletion at link failover
When a bearer is disabled manually, all its links have to be reset and deleted. However, if there is a remaining, parallel link ready to take over a deleted link's traffic, we currently delay the delete of the removed link until the failover procedure is finished. This is because the remaining link needs to access state from the reset link, such as the last received packet number, and any partially reassembled buffer, in order to perform a successful failover. In this commit, we do instead move the state data over to the new link, so that it can fulfill the procedure autonomously, without accessing any data on the old link. This means that we can now proceed and delete all pertaining links immediately when a bearer is disabled. This saves us from some unnecessary complexity in such situations. We also choose to change the confusing definitions CHANGEOVER_PROTOCOL, ORIGINAL_MSG and DUPLICATE_MSG to the more descriptive TUNNEL_PROTOCOL, FAILOVER_MSG and SYNCH_MSG respectively. Reviewed-by: Ying Xue <[email protected]> Signed-off-by: Jon Maloy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2da7142 commit dff29b1

File tree

5 files changed

+78
-90
lines changed

5 files changed

+78
-90
lines changed

net/tipc/link.c

Lines changed: 56 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,9 @@ static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
8989
#define TIMEOUT_EVT 560817u /* link timer expired */
9090

9191
/*
92-
* The following two 'message types' is really just implementation
93-
* data conveniently stored in the message header.
94-
* They must not be considered part of the protocol
92+
* State value stored in 'failover_pkts'
9593
*/
96-
#define OPEN_MSG 0
97-
#define CLOSED_MSG 1
98-
99-
/*
100-
* State value stored in 'exp_msg_count'
101-
*/
102-
#define START_CHANGEOVER 100000u
94+
#define FIRST_FAILOVER 0xffffu
10395

10496
static void link_handle_out_of_seq_msg(struct tipc_link *link,
10597
struct sk_buff *skb);
@@ -113,8 +105,7 @@ static void tipc_link_sync_xmit(struct tipc_link *l);
113105
static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf);
114106
static void tipc_link_input(struct tipc_link *l, struct sk_buff *skb);
115107
static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb);
116-
static bool tipc_link_failover_rcv(struct tipc_node *node,
117-
struct sk_buff **skb);
108+
static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb);
118109
/*
119110
* Simple link routines
120111
*/
@@ -332,15 +323,19 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
332323
}
333324

334325
/**
335-
* link_delete - Conditional deletion of link.
336-
* If timer still running, real delete is done when it expires
337-
* @link: link to be deleted
326+
* tipc_link_delete - Delete a link
327+
* @l: link to be deleted
338328
*/
339-
void tipc_link_delete(struct tipc_link *link)
329+
void tipc_link_delete(struct tipc_link *l)
340330
{
341-
tipc_link_reset_fragments(link);
342-
tipc_node_detach_link(link->owner, link);
343-
tipc_link_put(link);
331+
tipc_link_reset(l);
332+
if (del_timer(&l->timer))
333+
tipc_link_put(l);
334+
l->flags |= LINK_STOPPED;
335+
/* Delete link now, or when timer is finished: */
336+
tipc_link_reset_fragments(l);
337+
tipc_node_detach_link(l->owner, l);
338+
tipc_link_put(l);
344339
}
345340

346341
void tipc_link_delete_list(struct net *net, unsigned int bearer_id,
@@ -349,23 +344,12 @@ void tipc_link_delete_list(struct net *net, unsigned int bearer_id,
349344
struct tipc_net *tn = net_generic(net, tipc_net_id);
350345
struct tipc_link *link;
351346
struct tipc_node *node;
352-
bool del_link;
353347

354348
rcu_read_lock();
355349
list_for_each_entry_rcu(node, &tn->node_list, list) {
356350
tipc_node_lock(node);
357351
link = node->links[bearer_id];
358-
if (!link) {
359-
tipc_node_unlock(node);
360-
continue;
361-
}
362-
del_link = !tipc_link_is_up(link) && !link->exp_msg_count;
363-
tipc_link_reset(link);
364-
if (del_timer(&link->timer))
365-
tipc_link_put(link);
366-
link->flags |= LINK_STOPPED;
367-
/* Delete link now, or when failover is finished: */
368-
if (shutting_down || !tipc_node_is_up(node) || del_link)
352+
if (link)
369353
tipc_link_delete(link);
370354
tipc_node_unlock(node);
371355
}
@@ -472,9 +456,9 @@ void tipc_link_purge_queues(struct tipc_link *l_ptr)
472456
void tipc_link_reset(struct tipc_link *l_ptr)
473457
{
474458
u32 prev_state = l_ptr->state;
475-
u32 checkpoint = l_ptr->next_in_no;
476459
int was_active_link = tipc_link_is_active(l_ptr);
477460
struct tipc_node *owner = l_ptr->owner;
461+
struct tipc_link *pl = tipc_parallel_link(l_ptr);
478462

479463
msg_set_session(l_ptr->pmsg, ((msg_session(l_ptr->pmsg) + 1) & 0xffff));
480464

@@ -492,11 +476,15 @@ void tipc_link_reset(struct tipc_link *l_ptr)
492476
tipc_node_link_down(l_ptr->owner, l_ptr);
493477
tipc_bearer_remove_dest(owner->net, l_ptr->bearer_id, l_ptr->addr);
494478

495-
if (was_active_link && tipc_node_active_links(l_ptr->owner)) {
496-
l_ptr->reset_checkpoint = checkpoint;
497-
l_ptr->exp_msg_count = START_CHANGEOVER;
479+
if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) {
480+
l_ptr->flags |= LINK_FAILINGOVER;
481+
l_ptr->failover_checkpt = l_ptr->next_in_no;
482+
pl->failover_pkts = FIRST_FAILOVER;
483+
pl->failover_checkpt = l_ptr->next_in_no;
484+
pl->failover_skb = l_ptr->reasm_buf;
485+
} else {
486+
kfree_skb(l_ptr->reasm_buf);
498487
}
499-
500488
/* Clean up all queues, except inputq: */
501489
__skb_queue_purge(&l_ptr->transmq);
502490
__skb_queue_purge(&l_ptr->deferdq);
@@ -506,6 +494,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
506494
if (!skb_queue_empty(owner->inputq))
507495
owner->action_flags |= TIPC_MSG_EVT;
508496
tipc_link_purge_backlog(l_ptr);
497+
l_ptr->reasm_buf = NULL;
509498
l_ptr->rcv_unacked = 0;
510499
l_ptr->checkpoint = 1;
511500
l_ptr->next_out_no = 1;
@@ -557,8 +546,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
557546
if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT))
558547
return; /* Not yet. */
559548

560-
/* Check whether changeover is going on */
561-
if (l_ptr->exp_msg_count) {
549+
if (l_ptr->flags & LINK_FAILINGOVER) {
562550
if (event == TIMEOUT_EVT)
563551
link_set_timer(l_ptr, cont_intv);
564552
return;
@@ -1242,7 +1230,7 @@ static bool tipc_data_input(struct tipc_link *link, struct sk_buff *skb)
12421230
node->action_flags |= TIPC_NAMED_MSG_EVT;
12431231
return true;
12441232
case MSG_BUNDLER:
1245-
case CHANGEOVER_PROTOCOL:
1233+
case TUNNEL_PROTOCOL:
12461234
case MSG_FRAGMENTER:
12471235
case BCAST_PROTOCOL:
12481236
return false;
@@ -1269,14 +1257,14 @@ static void tipc_link_input(struct tipc_link *link, struct sk_buff *skb)
12691257
return;
12701258

12711259
switch (msg_user(msg)) {
1272-
case CHANGEOVER_PROTOCOL:
1260+
case TUNNEL_PROTOCOL:
12731261
if (msg_dup(msg)) {
12741262
link->flags |= LINK_SYNCHING;
12751263
link->synch_point = msg_seqno(msg_get_wrapped(msg));
12761264
kfree_skb(skb);
12771265
break;
12781266
}
1279-
if (!tipc_link_failover_rcv(node, &skb))
1267+
if (!tipc_link_failover_rcv(link, &skb))
12801268
break;
12811269
if (msg_user(buf_msg(skb)) != MSG_BUNDLER) {
12821270
tipc_data_input(link, skb);
@@ -1391,8 +1379,8 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
13911379
u32 msg_size = sizeof(l_ptr->proto_msg);
13921380
int r_flag;
13931381

1394-
/* Don't send protocol message during link changeover */
1395-
if (l_ptr->exp_msg_count)
1382+
/* Don't send protocol message during link failover */
1383+
if (l_ptr->flags & LINK_FAILINGOVER)
13961384
return;
13971385

13981386
/* Abort non-RESET send if communication with node is prohibited */
@@ -1444,7 +1432,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
14441432
}
14451433
l_ptr->stats.sent_states++;
14461434
} else { /* RESET_MSG or ACTIVATE_MSG */
1447-
msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1));
1435+
msg_set_ack(msg, mod(l_ptr->failover_checkpt - 1));
14481436
msg_set_seq_gap(msg, 0);
14491437
msg_set_next_sent(msg, 1);
14501438
msg_set_probe(msg, 0);
@@ -1486,8 +1474,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
14861474
u32 msg_tol;
14871475
struct tipc_msg *msg = buf_msg(buf);
14881476

1489-
/* Discard protocol message during link changeover */
1490-
if (l_ptr->exp_msg_count)
1477+
if (l_ptr->flags & LINK_FAILINGOVER)
14911478
goto exit;
14921479

14931480
if (l_ptr->net_plane != msg_net_plane(msg))
@@ -1659,8 +1646,8 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr)
16591646
if (!tunnel)
16601647
return;
16611648

1662-
tipc_msg_init(link_own_addr(l_ptr), &tunnel_hdr, CHANGEOVER_PROTOCOL,
1663-
ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr);
1649+
tipc_msg_init(link_own_addr(l_ptr), &tunnel_hdr, TUNNEL_PROTOCOL,
1650+
FAILOVER_MSG, INT_H_SIZE, l_ptr->addr);
16641651
skb_queue_splice_tail_init(&l_ptr->backlogq, &l_ptr->transmq);
16651652
tipc_link_purge_backlog(l_ptr);
16661653
msgcount = skb_queue_len(&l_ptr->transmq);
@@ -1722,8 +1709,8 @@ void tipc_link_dup_queue_xmit(struct tipc_link *link,
17221709
struct sk_buff_head *queue = &link->transmq;
17231710
int mcnt;
17241711

1725-
tipc_msg_init(link_own_addr(link), &tnl_hdr, CHANGEOVER_PROTOCOL,
1726-
DUPLICATE_MSG, INT_H_SIZE, link->addr);
1712+
tipc_msg_init(link_own_addr(link), &tnl_hdr, TUNNEL_PROTOCOL,
1713+
SYNCH_MSG, INT_H_SIZE, link->addr);
17271714
mcnt = skb_queue_len(&link->transmq) + skb_queue_len(&link->backlogq);
17281715
msg_set_msgcnt(&tnl_hdr, mcnt);
17291716
msg_set_bearer_id(&tnl_hdr, link->peer_bearer_id);
@@ -1756,59 +1743,60 @@ void tipc_link_dup_queue_xmit(struct tipc_link *link,
17561743
goto tunnel_queue;
17571744
}
17581745

1759-
/* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet
1746+
/* tipc_link_failover_rcv(): Receive a tunnelled FAILOVER_MSG packet
17601747
* Owner node is locked.
17611748
*/
1762-
static bool tipc_link_failover_rcv(struct tipc_node *node,
1749+
static bool tipc_link_failover_rcv(struct tipc_link *link,
17631750
struct sk_buff **skb)
17641751
{
17651752
struct tipc_msg *msg = buf_msg(*skb);
17661753
struct sk_buff *iskb = NULL;
1767-
struct tipc_link *link = NULL;
1754+
struct tipc_link *pl = NULL;
17681755
int bearer_id = msg_bearer_id(msg);
17691756
int pos = 0;
17701757

1771-
if (msg_type(msg) != ORIGINAL_MSG) {
1758+
if (msg_type(msg) != FAILOVER_MSG) {
17721759
pr_warn("%sunknown tunnel pkt received\n", link_co_err);
17731760
goto exit;
17741761
}
17751762
if (bearer_id >= MAX_BEARERS)
17761763
goto exit;
1777-
link = node->links[bearer_id];
1778-
if (!link)
1764+
1765+
if (bearer_id == link->bearer_id)
17791766
goto exit;
1780-
if (tipc_link_is_up(link))
1781-
tipc_link_reset(link);
17821767

1783-
/* First failover packet? */
1784-
if (link->exp_msg_count == START_CHANGEOVER)
1785-
link->exp_msg_count = msg_msgcnt(msg);
1768+
pl = link->owner->links[bearer_id];
1769+
if (pl && tipc_link_is_up(pl))
1770+
tipc_link_reset(pl);
1771+
1772+
if (link->failover_pkts == FIRST_FAILOVER)
1773+
link->failover_pkts = msg_msgcnt(msg);
17861774

17871775
/* Should we expect an inner packet? */
1788-
if (!link->exp_msg_count)
1776+
if (!link->failover_pkts)
17891777
goto exit;
17901778

17911779
if (!tipc_msg_extract(*skb, &iskb, &pos)) {
17921780
pr_warn("%sno inner failover pkt\n", link_co_err);
17931781
*skb = NULL;
17941782
goto exit;
17951783
}
1796-
link->exp_msg_count--;
1784+
link->failover_pkts--;
17971785
*skb = NULL;
17981786

1799-
/* Was packet already delivered? */
1800-
if (less(buf_seqno(iskb), link->reset_checkpoint)) {
1787+
/* Was this packet already delivered? */
1788+
if (less(buf_seqno(iskb), link->failover_checkpt)) {
18011789
kfree_skb(iskb);
18021790
iskb = NULL;
18031791
goto exit;
18041792
}
18051793
if (msg_user(buf_msg(iskb)) == MSG_FRAGMENTER) {
18061794
link->stats.recv_fragments++;
1807-
tipc_buf_append(&link->reasm_buf, &iskb);
1795+
tipc_buf_append(&link->failover_skb, &iskb);
18081796
}
18091797
exit:
1810-
if (link && (!link->exp_msg_count) && (link->flags & LINK_STOPPED))
1811-
tipc_link_delete(link);
1798+
if (!link->failover_pkts && pl)
1799+
pl->flags &= ~LINK_FAILINGOVER;
18121800
kfree_skb(*skb);
18131801
*skb = iskb;
18141802
return *skb;

net/tipc/link.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@
5858

5959
/* Link endpoint execution states
6060
*/
61-
#define LINK_STARTED 0x0001
62-
#define LINK_STOPPED 0x0002
63-
#define LINK_SYNCHING 0x0004
61+
#define LINK_STARTED 0x0001
62+
#define LINK_STOPPED 0x0002
63+
#define LINK_SYNCHING 0x0004
64+
#define LINK_FAILINGOVER 0x0008
6465

6566
/* Starting value for maximum packet size negotiation on unicast links
6667
* (unless bearer MTU is less)
@@ -167,11 +168,12 @@ struct tipc_link {
167168
struct tipc_msg *pmsg;
168169
u32 priority;
169170
char net_plane;
171+
u16 synch_point;
170172

171-
/* Changeover */
172-
u32 exp_msg_count;
173-
u32 reset_checkpoint;
174-
u32 synch_point;
173+
/* Failover */
174+
u16 failover_pkts;
175+
u16 failover_checkpt;
176+
struct sk_buff *failover_skb;
175177

176178
/* Max packet negotiation */
177179
u32 max_pkt;
@@ -201,7 +203,6 @@ struct tipc_link {
201203
struct sk_buff_head wakeupq;
202204

203205
/* Fragmentation/reassembly */
204-
u32 long_msg_seq_no;
205206
struct sk_buff *reasm_buf;
206207

207208
/* Statistics */

net/tipc/msg.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ bool tipc_msg_bundle(struct sk_buff *bskb, struct sk_buff *skb, u32 mtu)
355355
start = align(bsz);
356356
pad = start - bsz;
357357

358-
if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL))
358+
if (unlikely(msg_user(msg) == TUNNEL_PROTOCOL))
359359
return false;
360360
if (unlikely(msg_user(msg) == BCAST_PROTOCOL))
361361
return false;
@@ -433,7 +433,7 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, u32 mtu, u32 dnode)
433433

434434
if (msg_user(msg) == MSG_FRAGMENTER)
435435
return false;
436-
if (msg_user(msg) == CHANGEOVER_PROTOCOL)
436+
if (msg_user(msg) == TUNNEL_PROTOCOL)
437437
return false;
438438
if (msg_user(msg) == BCAST_PROTOCOL)
439439
return false;

net/tipc/msg.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ struct plist;
7272
#define MSG_BUNDLER 6
7373
#define LINK_PROTOCOL 7
7474
#define CONN_MANAGER 8
75-
#define CHANGEOVER_PROTOCOL 10
75+
#define TUNNEL_PROTOCOL 10
7676
#define NAME_DISTRIBUTOR 11
7777
#define MSG_FRAGMENTER 12
7878
#define LINK_CONFIG 13
@@ -512,8 +512,8 @@ static inline void msg_set_nameupper(struct tipc_msg *m, u32 n)
512512
/*
513513
* Changeover tunnel message types
514514
*/
515-
#define DUPLICATE_MSG 0
516-
#define ORIGINAL_MSG 1
515+
#define SYNCH_MSG 0
516+
#define FAILOVER_MSG 1
517517

518518
/*
519519
* Config protocol message types
@@ -556,9 +556,9 @@ static inline void msg_set_node_capabilities(struct tipc_msg *m, u32 n)
556556

557557
static inline bool msg_dup(struct tipc_msg *m)
558558
{
559-
if (likely(msg_user(m) != CHANGEOVER_PROTOCOL))
559+
if (likely(msg_user(m) != TUNNEL_PROTOCOL))
560560
return false;
561-
if (msg_type(m) != DUPLICATE_MSG)
561+
if (msg_type(m) != SYNCH_MSG)
562562
return false;
563563
return true;
564564
}

0 commit comments

Comments
 (0)