Commit d7626b5a authored by Tuong Lien's avatar Tuong Lien Committed by David S. Miller

tipc: introduce Gap ACK blocks for broadcast link

As achieved through commit 9195948f ("tipc: improve TIPC throughput
by Gap ACK blocks"), we apply the same mechanism for the broadcast link
as well. The 'Gap ACK blocks' data field in a 'PROTOCOL/STATE_MSG' will
consist of two parts built for both the broadcast and unicast types:

 31                       16 15                        0
+-------------+-------------+-------------+-------------+
|  bgack_cnt  |  ugack_cnt  |            len            |
+-------------+-------------+-------------+-------------+  -
|            gap            |            ack            |   |
+-------------+-------------+-------------+-------------+    > bc gacks
:                           :                           :   |
+-------------+-------------+-------------+-------------+  -
|            gap            |            ack            |   |
+-------------+-------------+-------------+-------------+    > uc gacks
:                           :                           :   |
+-------------+-------------+-------------+-------------+  -

which is "automatically" backward-compatible.

We also increase the max number of Gap ACK blocks to 128, allowing upto
64 blocks per type (total buffer size = 516 bytes).

Besides, the 'tipc_link_advance_transmq()' function is refactored which
is applicable for both the unicast and broadcast cases now, so some old
functions can be removed and the code is optimized.

With the patch, TIPC broadcast is more robust regardless of packet loss
or disorder, latency, ... in the underlying network. Its performance is
boost up significantly.
For example, experiment with a 5% packet loss rate results:

$ time tipc-pipe --mc --rdm --data_size 123 --data_num 1500000
real    0m 42.46s
user    0m 1.16s
sys     0m 17.67s

Without the patch:

$ time tipc-pipe --mc --rdm --data_size 123 --data_num 1500000
real    8m 27.94s
user    0m 0.55s
sys     0m 2.38s
Acked-by: default avatarYing Xue <ying.xue@windriver.com>
Acked-by: default avatarJon Maloy <jmaloy@redhat.com>
Signed-off-by: default avatarTuong Lien <tuong.t.lien@dektech.com.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ff937b91
...@@ -474,7 +474,7 @@ void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, ...@@ -474,7 +474,7 @@ void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
__skb_queue_head_init(&xmitq); __skb_queue_head_init(&xmitq);
tipc_bcast_lock(net); tipc_bcast_lock(net);
tipc_link_bc_ack_rcv(l, acked, &xmitq); tipc_link_bc_ack_rcv(l, acked, 0, NULL, &xmitq);
tipc_bcast_unlock(net); tipc_bcast_unlock(net);
tipc_bcbase_xmit(net, &xmitq); tipc_bcbase_xmit(net, &xmitq);
...@@ -492,6 +492,7 @@ int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l, ...@@ -492,6 +492,7 @@ int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
struct tipc_msg *hdr) struct tipc_msg *hdr)
{ {
struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq; struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq;
struct tipc_gap_ack_blks *ga;
struct sk_buff_head xmitq; struct sk_buff_head xmitq;
int rc = 0; int rc = 0;
...@@ -501,8 +502,10 @@ int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l, ...@@ -501,8 +502,10 @@ int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
if (msg_type(hdr) != STATE_MSG) { if (msg_type(hdr) != STATE_MSG) {
tipc_link_bc_init_rcv(l, hdr); tipc_link_bc_init_rcv(l, hdr);
} else if (!msg_bc_ack_invalid(hdr)) { } else if (!msg_bc_ack_invalid(hdr)) {
tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), &xmitq); tipc_get_gap_ack_blks(&ga, l, hdr, false);
rc = tipc_link_bc_sync_rcv(l, hdr, &xmitq); rc = tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr),
msg_bc_gap(hdr), ga, &xmitq);
rc |= tipc_link_bc_sync_rcv(l, hdr, &xmitq);
} }
tipc_bcast_unlock(net); tipc_bcast_unlock(net);
......
This diff is collapsed.
...@@ -143,8 +143,11 @@ int tipc_link_bc_peers(struct tipc_link *l); ...@@ -143,8 +143,11 @@ int tipc_link_bc_peers(struct tipc_link *l);
void tipc_link_set_mtu(struct tipc_link *l, int mtu); void tipc_link_set_mtu(struct tipc_link *l, int mtu);
int tipc_link_mtu(struct tipc_link *l); int tipc_link_mtu(struct tipc_link *l);
int tipc_link_mss(struct tipc_link *l); int tipc_link_mss(struct tipc_link *l);
void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked, u16 tipc_get_gap_ack_blks(struct tipc_gap_ack_blks **ga, struct tipc_link *l,
struct sk_buff_head *xmitq); struct tipc_msg *hdr, bool uc);
int tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked, u16 gap,
struct tipc_gap_ack_blks *ga,
struct sk_buff_head *xmitq);
void tipc_link_build_bc_sync_msg(struct tipc_link *l, void tipc_link_build_bc_sync_msg(struct tipc_link *l,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr); void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr);
......
...@@ -160,20 +160,39 @@ struct tipc_gap_ack { ...@@ -160,20 +160,39 @@ struct tipc_gap_ack {
/* struct tipc_gap_ack_blks /* struct tipc_gap_ack_blks
* @len: actual length of the record * @len: actual length of the record
* @gack_cnt: number of Gap ACK blocks in the record * @ugack_cnt: number of Gap ACK blocks for unicast (following the broadcast
* ones)
* @start_index: starting index for "valid" broadcast Gap ACK blocks
* @bgack_cnt: number of Gap ACK blocks for broadcast in the record
* @gacks: array of Gap ACK blocks * @gacks: array of Gap ACK blocks
*
* 31 16 15 0
* +-------------+-------------+-------------+-------------+
* | bgack_cnt | ugack_cnt | len |
* +-------------+-------------+-------------+-------------+ -
* | gap | ack | |
* +-------------+-------------+-------------+-------------+ > bc gacks
* : : : |
* +-------------+-------------+-------------+-------------+ -
* | gap | ack | |
* +-------------+-------------+-------------+-------------+ > uc gacks
* : : : |
* +-------------+-------------+-------------+-------------+ -
*/ */
struct tipc_gap_ack_blks { struct tipc_gap_ack_blks {
__be16 len; __be16 len;
u8 gack_cnt; union {
u8 reserved; u8 ugack_cnt;
u8 start_index;
};
u8 bgack_cnt;
struct tipc_gap_ack gacks[]; struct tipc_gap_ack gacks[];
}; };
#define tipc_gap_ack_blks_sz(n) (sizeof(struct tipc_gap_ack_blks) + \ #define tipc_gap_ack_blks_sz(n) (sizeof(struct tipc_gap_ack_blks) + \
sizeof(struct tipc_gap_ack) * (n)) sizeof(struct tipc_gap_ack) * (n))
#define MAX_GAP_ACK_BLKS 32 #define MAX_GAP_ACK_BLKS 128
#define MAX_GAP_ACK_BLKS_SZ tipc_gap_ack_blks_sz(MAX_GAP_ACK_BLKS) #define MAX_GAP_ACK_BLKS_SZ tipc_gap_ack_blks_sz(MAX_GAP_ACK_BLKS)
static inline struct tipc_msg *buf_msg(struct sk_buff *skb) static inline struct tipc_msg *buf_msg(struct sk_buff *skb)
......
...@@ -2071,10 +2071,16 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) ...@@ -2071,10 +2071,16 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
le = &n->links[bearer_id]; le = &n->links[bearer_id];
/* Ensure broadcast reception is in synch with peer's send state */ /* Ensure broadcast reception is in synch with peer's send state */
if (unlikely(usr == LINK_PROTOCOL)) if (unlikely(usr == LINK_PROTOCOL)) {
if (unlikely(skb_linearize(skb))) {
tipc_node_put(n);
goto discard;
}
hdr = buf_msg(skb);
tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq); tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq);
else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) } else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) {
tipc_bcast_ack_rcv(net, n->bc_entry.link, hdr); tipc_bcast_ack_rcv(net, n->bc_entry.link, hdr);
}
/* Receive packet directly if conditions permit */ /* Receive packet directly if conditions permit */
tipc_node_read_lock(n); tipc_node_read_lock(n);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment