Skip to content

Commit 8752b5c

Browse files
committed
Merge branch 'tipc'
Jon Maloy says: ==================== tipc: link setup and failover improvements This series consists of four unrelated commits with different purposes. - Commit #1 is purely cosmetic and pedagogic, hopefully making the failover/tunneling logics slightly easier to understand. - Commit #2 fixes a bug that has always been in the code, but was not discovered until very recently. - Commit #3 fixes a non-fatal race issue in the neighbour discovery code. - Commit #4 removes an unnecessary indirection step during link startup. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents fd44b93 + 581465f commit 8752b5c

File tree

8 files changed

+73
-64
lines changed

8 files changed

+73
-64
lines changed

net/tipc/bcast.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ void tipc_bclink_init(void)
794794
void tipc_bclink_stop(void)
795795
{
796796
spin_lock_bh(&bc_lock);
797-
tipc_link_stop(bcl);
797+
tipc_link_purge_queues(bcl);
798798
spin_unlock_bh(&bc_lock);
799799

800800
memset(bclink, 0, sizeof(*bclink));

net/tipc/bearer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
541541
if (likely(b_ptr)) {
542542
if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
543543
buf->next = NULL;
544-
tipc_recv_msg(buf, b_ptr);
544+
tipc_rcv(buf, b_ptr);
545545
rcu_read_unlock();
546546
return NET_RX_SUCCESS;
547547
}

net/tipc/bearer.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@ extern struct tipc_bearer tipc_bearers[];
161161
* TIPC routines available to supported media types
162162
*/
163163

164-
void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
165-
164+
void tipc_rcv(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
166165
int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
167166
int tipc_disable_bearer(const char *name);
168167

net/tipc/discover.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
* @dest: destination address for request messages
5151
* @domain: network domain to which links can be established
5252
* @num_nodes: number of nodes currently discovered (i.e. with an active link)
53+
* @lock: spinlock for controlling access to requests
5354
* @buf: request message to be (repeatedly) sent
5455
* @timer: timer governing period between requests
5556
* @timer_intv: current interval between requests (in ms)
@@ -59,6 +60,7 @@ struct tipc_link_req {
5960
struct tipc_media_addr dest;
6061
u32 domain;
6162
int num_nodes;
63+
spinlock_t lock;
6264
struct sk_buff *buf;
6365
struct timer_list timer;
6466
unsigned int timer_intv;
@@ -274,7 +276,9 @@ static void disc_update(struct tipc_link_req *req)
274276
*/
275277
void tipc_disc_add_dest(struct tipc_link_req *req)
276278
{
279+
spin_lock_bh(&req->lock);
277280
req->num_nodes++;
281+
spin_unlock_bh(&req->lock);
278282
}
279283

280284
/**
@@ -283,8 +287,10 @@ void tipc_disc_add_dest(struct tipc_link_req *req)
283287
*/
284288
void tipc_disc_remove_dest(struct tipc_link_req *req)
285289
{
290+
spin_lock_bh(&req->lock);
286291
req->num_nodes--;
287292
disc_update(req);
293+
spin_unlock_bh(&req->lock);
288294
}
289295

290296
/**
@@ -297,7 +303,7 @@ static void disc_timeout(struct tipc_link_req *req)
297303
{
298304
int max_delay;
299305

300-
spin_lock_bh(&req->bearer->lock);
306+
spin_lock_bh(&req->lock);
301307

302308
/* Stop searching if only desired node has been found */
303309
if (tipc_node(req->domain) && req->num_nodes) {
@@ -325,7 +331,7 @@ static void disc_timeout(struct tipc_link_req *req)
325331

326332
k_start_timer(&req->timer, req->timer_intv);
327333
exit:
328-
spin_unlock_bh(&req->bearer->lock);
334+
spin_unlock_bh(&req->lock);
329335
}
330336

331337
/**
@@ -356,6 +362,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest,
356362
req->domain = dest_domain;
357363
req->num_nodes = 0;
358364
req->timer_intv = TIPC_LINK_REQ_INIT;
365+
spin_lock_init(&req->lock);
359366
k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
360367
k_start_timer(&req->timer, req->timer_intv);
361368
b_ptr->link_req = req;

net/tipc/link.c

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* net/tipc/link.c: TIPC link code
33
*
4-
* Copyright (c) 1996-2007, 2012, Ericsson AB
4+
* Copyright (c) 1996-2007, 2012-2014, Ericsson AB
55
* Copyright (c) 2004-2007, 2010-2013, Wind River Systems
66
* All rights reserved.
77
*
@@ -78,16 +78,15 @@ static const char *link_unk_evt = "Unknown link event ";
7878
static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
7979
struct sk_buff *buf);
8080
static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf);
81-
static int link_recv_changeover_msg(struct tipc_link **l_ptr,
82-
struct sk_buff **buf);
81+
static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
82+
struct sk_buff **buf);
8383
static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance);
8484
static int link_send_sections_long(struct tipc_port *sender,
8585
struct iovec const *msg_sect,
8686
unsigned int len, u32 destnode);
8787
static void link_state_event(struct tipc_link *l_ptr, u32 event);
8888
static void link_reset_statistics(struct tipc_link *l_ptr);
8989
static void link_print(struct tipc_link *l_ptr, const char *str);
90-
static void link_start(struct tipc_link *l_ptr);
9190
static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
9291
static void tipc_link_send_sync(struct tipc_link *l);
9392
static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf);
@@ -278,9 +277,11 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
278277

279278
tipc_node_attach_link(n_ptr, l_ptr);
280279

281-
k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
280+
k_init_timer(&l_ptr->timer, (Handler)link_timeout,
281+
(unsigned long)l_ptr);
282282
list_add_tail(&l_ptr->link_list, &b_ptr->links);
283-
tipc_k_signal((Handler)link_start, (unsigned long)l_ptr);
283+
284+
link_state_event(l_ptr, STARTING_EVT);
284285

285286
return l_ptr;
286287
}
@@ -305,19 +306,13 @@ void tipc_link_delete(struct tipc_link *l_ptr)
305306
tipc_node_lock(l_ptr->owner);
306307
tipc_link_reset(l_ptr);
307308
tipc_node_detach_link(l_ptr->owner, l_ptr);
308-
tipc_link_stop(l_ptr);
309+
tipc_link_purge_queues(l_ptr);
309310
list_del_init(&l_ptr->link_list);
310311
tipc_node_unlock(l_ptr->owner);
311312
k_term_timer(&l_ptr->timer);
312313
kfree(l_ptr);
313314
}
314315

315-
static void link_start(struct tipc_link *l_ptr)
316-
{
317-
tipc_node_lock(l_ptr->owner);
318-
link_state_event(l_ptr, STARTING_EVT);
319-
tipc_node_unlock(l_ptr->owner);
320-
}
321316

322317
/**
323318
* link_schedule_port - schedule port for deferred sending
@@ -403,10 +398,10 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr)
403398
}
404399

405400
/**
406-
* tipc_link_stop - purge all inbound and outbound messages associated with link
401+
* tipc_link_purge_queues - purge all pkt queues associated with link
407402
* @l_ptr: pointer to link
408403
*/
409-
void tipc_link_stop(struct tipc_link *l_ptr)
404+
void tipc_link_purge_queues(struct tipc_link *l_ptr)
410405
{
411406
kfree_skb_list(l_ptr->oldest_deferred_in);
412407
kfree_skb_list(l_ptr->first_out);
@@ -437,8 +432,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
437432
tipc_node_link_down(l_ptr->owner, l_ptr);
438433
tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
439434

440-
if (was_active_link && tipc_node_active_links(l_ptr->owner) &&
441-
l_ptr->owner->permit_changeover) {
435+
if (was_active_link && tipc_node_active_links(l_ptr->owner)) {
442436
l_ptr->reset_checkpoint = checkpoint;
443437
l_ptr->exp_msg_count = START_CHANGEOVER;
444438
}
@@ -1422,14 +1416,14 @@ static int link_recv_buf_validate(struct sk_buff *buf)
14221416
}
14231417

14241418
/**
1425-
* tipc_recv_msg - process TIPC messages arriving from off-node
1419+
* tipc_rcv - process TIPC packets/messages arriving from off-node
14261420
* @head: pointer to message buffer chain
14271421
* @tb_ptr: pointer to bearer message arrived on
14281422
*
14291423
* Invoked with no locks held. Bearer pointer must point to a valid bearer
14301424
* structure (i.e. cannot be NULL), but bearer can be inactive.
14311425
*/
1432-
void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
1426+
void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr)
14331427
{
14341428
read_lock_bh(&tipc_net_lock);
14351429
while (head) {
@@ -1603,7 +1597,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
16031597
continue;
16041598
case CHANGEOVER_PROTOCOL:
16051599
type = msg_type(msg);
1606-
if (link_recv_changeover_msg(&l_ptr, &buf)) {
1600+
if (tipc_link_tunnel_rcv(&l_ptr, &buf)) {
16071601
msg = buf_msg(buf);
16081602
seq_no = msg_seqno(msg);
16091603
if (type == ORIGINAL_MSG)
@@ -1837,8 +1831,6 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
18371831
if (tipc_own_addr > msg_prevnode(msg))
18381832
l_ptr->b_ptr->net_plane = msg_net_plane(msg);
18391833

1840-
l_ptr->owner->permit_changeover = msg_redundant_link(msg);
1841-
18421834
switch (msg_type(msg)) {
18431835

18441836
case RESET_MSG:
@@ -1954,13 +1946,13 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
19541946
}
19551947

19561948

1957-
/*
1958-
* tipc_link_tunnel(): Send one message via a link belonging to
1959-
* another bearer. Owner node is locked.
1949+
/* tipc_link_tunnel_xmit(): Tunnel one packet via a link belonging to
1950+
* a different bearer. Owner node is locked.
19601951
*/
1961-
static void tipc_link_tunnel(struct tipc_link *l_ptr,
1962-
struct tipc_msg *tunnel_hdr, struct tipc_msg *msg,
1963-
u32 selector)
1952+
static void tipc_link_tunnel_xmit(struct tipc_link *l_ptr,
1953+
struct tipc_msg *tunnel_hdr,
1954+
struct tipc_msg *msg,
1955+
u32 selector)
19641956
{
19651957
struct tipc_link *tunnel;
19661958
struct sk_buff *buf;
@@ -1983,12 +1975,13 @@ static void tipc_link_tunnel(struct tipc_link *l_ptr,
19831975
}
19841976

19851977

1986-
1987-
/*
1988-
* changeover(): Send whole message queue via the remaining link
1989-
* Owner node is locked.
1978+
/* tipc_link_failover_send_queue(): A link has gone down, but a second
1979+
* link is still active. We can do failover. Tunnel the failing link's
1980+
* whole send queue via the remaining link. This way, we don't lose
1981+
* any packets, and sequence order is preserved for subsequent traffic
1982+
* sent over the remaining link. Owner node is locked.
19901983
*/
1991-
void tipc_link_changeover(struct tipc_link *l_ptr)
1984+
void tipc_link_failover_send_queue(struct tipc_link *l_ptr)
19921985
{
19931986
u32 msgcount = l_ptr->out_queue_size;
19941987
struct sk_buff *crs = l_ptr->first_out;
@@ -1999,11 +1992,6 @@ void tipc_link_changeover(struct tipc_link *l_ptr)
19991992
if (!tunnel)
20001993
return;
20011994

2002-
if (!l_ptr->owner->permit_changeover) {
2003-
pr_warn("%speer did not permit changeover\n", link_co_err);
2004-
return;
2005-
}
2006-
20071995
tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
20081996
ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr);
20091997
msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
@@ -2037,20 +2025,30 @@ void tipc_link_changeover(struct tipc_link *l_ptr)
20372025
msgcount = msg_msgcnt(msg);
20382026
while (msgcount--) {
20392027
msg_set_seqno(m, msg_seqno(msg));
2040-
tipc_link_tunnel(l_ptr, &tunnel_hdr, m,
2041-
msg_link_selector(m));
2028+
tipc_link_tunnel_xmit(l_ptr, &tunnel_hdr, m,
2029+
msg_link_selector(m));
20422030
pos += align(msg_size(m));
20432031
m = (struct tipc_msg *)pos;
20442032
}
20452033
} else {
2046-
tipc_link_tunnel(l_ptr, &tunnel_hdr, msg,
2047-
msg_link_selector(msg));
2034+
tipc_link_tunnel_xmit(l_ptr, &tunnel_hdr, msg,
2035+
msg_link_selector(msg));
20482036
}
20492037
crs = crs->next;
20502038
}
20512039
}
20522040

2053-
void tipc_link_send_duplicate(struct tipc_link *l_ptr, struct tipc_link *tunnel)
2041+
/* tipc_link_dup_send_queue(): A second link has become active. Tunnel a
2042+
* duplicate of the first link's send queue via the new link. This way, we
2043+
* are guaranteed that currently queued packets from a socket are delivered
2044+
* before future traffic from the same socket, even if this is using the
2045+
* new link. The last arriving copy of each duplicate packet is dropped at
2046+
* the receiving end by the regular protocol check, so packet cardinality
2047+
* and sequence order is preserved per sender/receiver socket pair.
2048+
* Owner node is locked.
2049+
*/
2050+
void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
2051+
struct tipc_link *tunnel)
20542052
{
20552053
struct sk_buff *iter;
20562054
struct tipc_msg tunnel_hdr;
@@ -2106,12 +2104,14 @@ static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos)
21062104
return eb;
21072105
}
21082106

2109-
/*
2110-
* link_recv_changeover_msg(): Receive tunneled packet sent
2111-
* via other link. Node is locked. Return extracted buffer.
2107+
/* tipc_link_tunnel_rcv(): Receive a tunneled packet, sent
2108+
* via other link as result of a failover (ORIGINAL_MSG) or
2109+
* a new active link (DUPLICATE_MSG). Failover packets are
2110+
* returned to the active link for delivery upwards.
2111+
* Owner node is locked.
21122112
*/
2113-
static int link_recv_changeover_msg(struct tipc_link **l_ptr,
2114-
struct sk_buff **buf)
2113+
static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
2114+
struct sk_buff **buf)
21152115
{
21162116
struct sk_buff *tunnel_buf = *buf;
21172117
struct tipc_link *dest_link;

net/tipc/link.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,20 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
216216
struct tipc_bearer *b_ptr,
217217
const struct tipc_media_addr *media_addr);
218218
void tipc_link_delete(struct tipc_link *l_ptr);
219-
void tipc_link_changeover(struct tipc_link *l_ptr);
220-
void tipc_link_send_duplicate(struct tipc_link *l_ptr, struct tipc_link *dest);
219+
void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
220+
void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
221+
struct tipc_link *dest);
221222
void tipc_link_reset_fragments(struct tipc_link *l_ptr);
222223
int tipc_link_is_up(struct tipc_link *l_ptr);
223224
int tipc_link_is_active(struct tipc_link *l_ptr);
224-
void tipc_link_stop(struct tipc_link *l_ptr);
225-
struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
226-
struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
227-
struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
225+
void tipc_link_purge_queues(struct tipc_link *l_ptr);
226+
struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area,
227+
int req_tlv_space,
228+
u16 cmd);
229+
struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area,
230+
int req_tlv_space);
231+
struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area,
232+
int req_tlv_space);
228233
void tipc_link_reset(struct tipc_link *l_ptr);
229234
int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
230235
void tipc_link_send_names(struct list_head *message_list, u32 dest);

net/tipc/node.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
162162
pr_info("New link <%s> becomes standby\n", l_ptr->name);
163163
return;
164164
}
165-
tipc_link_send_duplicate(active[0], l_ptr);
165+
tipc_link_dup_send_queue(active[0], l_ptr);
166166
if (l_ptr->priority == active[0]->priority) {
167167
active[0] = l_ptr;
168168
return;
@@ -225,7 +225,7 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
225225
if (active[0] == l_ptr)
226226
node_select_active_links(n_ptr);
227227
if (tipc_node_is_up(n_ptr))
228-
tipc_link_changeover(l_ptr);
228+
tipc_link_failover_send_queue(l_ptr);
229229
else
230230
node_lost_contact(n_ptr);
231231
}

net/tipc/node.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
* @working_links: number of working links to node (both active and standby)
6565
* @block_setup: bit mask of conditions preventing link establishment to node
6666
* @link_cnt: number of links to node
67-
* @permit_changeover: non-zero if node has redundant links to this system
6867
* @signature: node instance identifier
6968
* @bclink: broadcast-related info
7069
* @acked: sequence # of last outbound b'cast message acknowledged by node
@@ -89,7 +88,6 @@ struct tipc_node {
8988
int link_cnt;
9089
int working_links;
9190
int block_setup;
92-
int permit_changeover;
9391
u32 signature;
9492
struct {
9593
u32 acked;

0 commit comments

Comments
 (0)