mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 23:24:11 +08:00
Merge branch 'tipc-introduce-variable-window-congestion-control'
Jon Maloy says: ==================== tipc: introduce variable window congestion control We improve thoughput greatly by introducing a variety of the Reno congestion control algorithm at the link level. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
bb9d8454bb
@ -562,18 +562,18 @@ int tipc_bclink_reset_stats(struct net *net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tipc_bc_link_set_queue_limits(struct net *net, u32 limit)
|
||||
static int tipc_bc_link_set_queue_limits(struct net *net, u32 max_win)
|
||||
{
|
||||
struct tipc_link *l = tipc_bc_sndlink(net);
|
||||
|
||||
if (!l)
|
||||
return -ENOPROTOOPT;
|
||||
if (limit < BCLINK_WIN_MIN)
|
||||
limit = BCLINK_WIN_MIN;
|
||||
if (limit > TIPC_MAX_LINK_WIN)
|
||||
if (max_win < BCLINK_WIN_MIN)
|
||||
max_win = BCLINK_WIN_MIN;
|
||||
if (max_win > TIPC_MAX_LINK_WIN)
|
||||
return -EINVAL;
|
||||
tipc_bcast_lock(net);
|
||||
tipc_link_set_queue_limits(l, limit);
|
||||
tipc_link_set_queue_limits(l, BCLINK_WIN_MIN, max_win);
|
||||
tipc_bcast_unlock(net);
|
||||
return 0;
|
||||
}
|
||||
@ -683,6 +683,7 @@ int tipc_bcast_init(struct net *net)
|
||||
if (!tipc_link_bc_create(net, 0, 0,
|
||||
FB_MTU,
|
||||
BCLINK_WIN_DEFAULT,
|
||||
BCLINK_WIN_DEFAULT,
|
||||
0,
|
||||
&bb->inputq,
|
||||
NULL,
|
||||
|
@ -311,7 +311,8 @@ static int tipc_enable_bearer(struct net *net, const char *name,
|
||||
|
||||
b->identity = bearer_id;
|
||||
b->tolerance = m->tolerance;
|
||||
b->window = m->window;
|
||||
b->min_win = m->min_win;
|
||||
b->max_win = m->max_win;
|
||||
b->domain = disc_domain;
|
||||
b->net_plane = bearer_id + 'A';
|
||||
b->priority = prio;
|
||||
@ -796,7 +797,7 @@ static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
|
||||
goto prop_msg_full;
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
|
||||
goto prop_msg_full;
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->max_win))
|
||||
goto prop_msg_full;
|
||||
if (bearer->media->type_id == TIPC_MEDIA_TYPE_UDP)
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_MTU, bearer->mtu))
|
||||
@ -1088,7 +1089,7 @@ int __tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
|
||||
if (props[TIPC_NLA_PROP_PRIO])
|
||||
b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
|
||||
if (props[TIPC_NLA_PROP_WIN])
|
||||
b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
b->max_win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
if (props[TIPC_NLA_PROP_MTU]) {
|
||||
if (b->media->type_id != TIPC_MEDIA_TYPE_UDP)
|
||||
return -EINVAL;
|
||||
@ -1142,7 +1143,7 @@ static int __tipc_nl_add_media(struct tipc_nl_msg *msg,
|
||||
goto prop_msg_full;
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
|
||||
goto prop_msg_full;
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->max_win))
|
||||
goto prop_msg_full;
|
||||
if (media->type_id == TIPC_MEDIA_TYPE_UDP)
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_MTU, media->mtu))
|
||||
@ -1275,7 +1276,7 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
|
||||
if (props[TIPC_NLA_PROP_PRIO])
|
||||
m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
|
||||
if (props[TIPC_NLA_PROP_WIN])
|
||||
m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
m->max_win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
if (props[TIPC_NLA_PROP_MTU]) {
|
||||
if (m->type_id != TIPC_MEDIA_TYPE_UDP)
|
||||
return -EINVAL;
|
||||
|
@ -119,7 +119,8 @@ struct tipc_media {
|
||||
char *raw);
|
||||
u32 priority;
|
||||
u32 tolerance;
|
||||
u32 window;
|
||||
u32 min_win;
|
||||
u32 max_win;
|
||||
u32 mtu;
|
||||
u32 type_id;
|
||||
u32 hwaddr_len;
|
||||
@ -158,7 +159,8 @@ struct tipc_bearer {
|
||||
struct packet_type pt;
|
||||
struct rcu_head rcu;
|
||||
u32 priority;
|
||||
u32 window;
|
||||
u32 min_win;
|
||||
u32 max_win;
|
||||
u32 tolerance;
|
||||
u32 domain;
|
||||
u32 identity;
|
||||
|
@ -92,7 +92,8 @@ struct tipc_media eth_media_info = {
|
||||
.raw2addr = tipc_eth_raw2addr,
|
||||
.priority = TIPC_DEF_LINK_PRI,
|
||||
.tolerance = TIPC_DEF_LINK_TOL,
|
||||
.window = TIPC_DEF_LINK_WIN,
|
||||
.min_win = TIPC_DEF_LINK_WIN,
|
||||
.max_win = TIPC_MAX_LINK_WIN,
|
||||
.type_id = TIPC_MEDIA_TYPE_ETH,
|
||||
.hwaddr_len = ETH_ALEN,
|
||||
.name = "eth"
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include "core.h"
|
||||
#include "bearer.h"
|
||||
|
||||
#define TIPC_MAX_IB_LINK_WIN 500
|
||||
|
||||
/* convert InfiniBand address (media address format) media address to string */
|
||||
static int tipc_ib_addr2str(struct tipc_media_addr *a, char *str_buf,
|
||||
int str_size)
|
||||
@ -94,7 +96,8 @@ struct tipc_media ib_media_info = {
|
||||
.raw2addr = tipc_ib_raw2addr,
|
||||
.priority = TIPC_DEF_LINK_PRI,
|
||||
.tolerance = TIPC_DEF_LINK_TOL,
|
||||
.window = TIPC_DEF_LINK_WIN,
|
||||
.min_win = TIPC_DEF_LINK_WIN,
|
||||
.max_win = TIPC_MAX_IB_LINK_WIN,
|
||||
.type_id = TIPC_MEDIA_TYPE_IB,
|
||||
.hwaddr_len = INFINIBAND_ALEN,
|
||||
.name = "ib"
|
||||
|
193
net/tipc/link.c
193
net/tipc/link.c
@ -164,7 +164,6 @@ struct tipc_link {
|
||||
struct sk_buff *target_bskb;
|
||||
} backlog[5];
|
||||
u16 snd_nxt;
|
||||
u16 window;
|
||||
|
||||
/* Reception */
|
||||
u16 rcv_nxt;
|
||||
@ -175,6 +174,12 @@ struct tipc_link {
|
||||
|
||||
/* Congestion handling */
|
||||
struct sk_buff_head wakeupq;
|
||||
u16 window;
|
||||
u16 min_win;
|
||||
u16 ssthresh;
|
||||
u16 max_win;
|
||||
u16 cong_acks;
|
||||
u16 checkpoint;
|
||||
|
||||
/* Fragmentation/reassembly */
|
||||
struct sk_buff *reasm_buf;
|
||||
@ -244,12 +249,13 @@ static int tipc_link_build_nack_msg(struct tipc_link *l,
|
||||
struct sk_buff_head *xmitq);
|
||||
static void tipc_link_build_bc_init_msg(struct tipc_link *l,
|
||||
struct sk_buff_head *xmitq);
|
||||
static bool tipc_link_release_pkts(struct tipc_link *l, u16 to);
|
||||
static int tipc_link_release_pkts(struct tipc_link *l, u16 to);
|
||||
static u16 tipc_build_gap_ack_blks(struct tipc_link *l, void *data);
|
||||
static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
|
||||
struct tipc_gap_ack_blks *ga,
|
||||
struct sk_buff_head *xmitq);
|
||||
|
||||
static void tipc_link_update_cwin(struct tipc_link *l, int released,
|
||||
bool retransmitted);
|
||||
/*
|
||||
* Simple non-static link routines (i.e. referenced outside this file)
|
||||
*/
|
||||
@ -308,9 +314,14 @@ u32 tipc_link_id(struct tipc_link *l)
|
||||
return l->peer_bearer_id << 16 | l->bearer_id;
|
||||
}
|
||||
|
||||
int tipc_link_window(struct tipc_link *l)
|
||||
int tipc_link_min_win(struct tipc_link *l)
|
||||
{
|
||||
return l->window;
|
||||
return l->min_win;
|
||||
}
|
||||
|
||||
int tipc_link_max_win(struct tipc_link *l)
|
||||
{
|
||||
return l->max_win;
|
||||
}
|
||||
|
||||
int tipc_link_prio(struct tipc_link *l)
|
||||
@ -436,7 +447,8 @@ u32 tipc_link_state(struct tipc_link *l)
|
||||
* @net_plane: network plane (A,B,c..) this link belongs to
|
||||
* @mtu: mtu to be advertised by link
|
||||
* @priority: priority to be used by link
|
||||
* @window: send window to be used by link
|
||||
* @min_win: minimal send window to be used by link
|
||||
* @max_win: maximal send window to be used by link
|
||||
* @session: session to be used by link
|
||||
* @ownnode: identity of own node
|
||||
* @peer: node id of peer node
|
||||
@ -451,7 +463,7 @@ u32 tipc_link_state(struct tipc_link *l)
|
||||
*/
|
||||
bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
|
||||
int tolerance, char net_plane, u32 mtu, int priority,
|
||||
int window, u32 session, u32 self,
|
||||
u32 min_win, u32 max_win, u32 session, u32 self,
|
||||
u32 peer, u8 *peer_id, u16 peer_caps,
|
||||
struct tipc_link *bc_sndlink,
|
||||
struct tipc_link *bc_rcvlink,
|
||||
@ -495,7 +507,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
|
||||
l->advertised_mtu = mtu;
|
||||
l->mtu = mtu;
|
||||
l->priority = priority;
|
||||
tipc_link_set_queue_limits(l, window);
|
||||
tipc_link_set_queue_limits(l, min_win, max_win);
|
||||
l->ackers = 1;
|
||||
l->bc_sndlink = bc_sndlink;
|
||||
l->bc_rcvlink = bc_rcvlink;
|
||||
@ -523,7 +535,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
|
||||
* Returns true if link was created, otherwise false
|
||||
*/
|
||||
bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
|
||||
int mtu, int window, u16 peer_caps,
|
||||
int mtu, u32 min_win, u32 max_win, u16 peer_caps,
|
||||
struct sk_buff_head *inputq,
|
||||
struct sk_buff_head *namedq,
|
||||
struct tipc_link *bc_sndlink,
|
||||
@ -531,9 +543,9 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
|
||||
{
|
||||
struct tipc_link *l;
|
||||
|
||||
if (!tipc_link_create(net, "", MAX_BEARERS, 0, 'Z', mtu, 0, window,
|
||||
0, ownnode, peer, NULL, peer_caps, bc_sndlink,
|
||||
NULL, inputq, namedq, link))
|
||||
if (!tipc_link_create(net, "", MAX_BEARERS, 0, 'Z', mtu, 0, min_win,
|
||||
max_win, 0, ownnode, peer, NULL, peer_caps,
|
||||
bc_sndlink, NULL, inputq, namedq, link))
|
||||
return false;
|
||||
|
||||
l = *link;
|
||||
@ -772,6 +784,8 @@ bool tipc_link_too_silent(struct tipc_link *l)
|
||||
return (l->silent_intv_cnt + 2 > l->abort_limit);
|
||||
}
|
||||
|
||||
static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
|
||||
u16 from, u16 to, struct sk_buff_head *xmitq);
|
||||
/* tipc_link_timeout - perform periodic task as instructed from node timeout
|
||||
*/
|
||||
int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq)
|
||||
@ -804,6 +818,11 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq)
|
||||
probe |= l->silent_intv_cnt;
|
||||
if (probe || mstate->monitoring)
|
||||
l->silent_intv_cnt++;
|
||||
if (l->snd_nxt == l->checkpoint) {
|
||||
tipc_link_update_cwin(l, 0, 0);
|
||||
probe = true;
|
||||
}
|
||||
l->checkpoint = l->snd_nxt;
|
||||
break;
|
||||
case LINK_RESET:
|
||||
setup = l->rst_cnt++ <= 4;
|
||||
@ -959,7 +978,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
|
||||
int pkt_cnt = skb_queue_len(list);
|
||||
int imp = msg_importance(hdr);
|
||||
unsigned int mss = tipc_link_mss(l);
|
||||
unsigned int maxwin = l->window;
|
||||
unsigned int cwin = l->window;
|
||||
unsigned int mtu = l->mtu;
|
||||
bool new_bundle;
|
||||
int rc = 0;
|
||||
@ -988,7 +1007,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
|
||||
|
||||
/* Prepare each packet for sending, and add to relevant queue: */
|
||||
while ((skb = __skb_dequeue(list))) {
|
||||
if (likely(skb_queue_len(transmq) < maxwin)) {
|
||||
if (likely(skb_queue_len(transmq) < cwin)) {
|
||||
hdr = buf_msg(skb);
|
||||
msg_set_seqno(hdr, seqno);
|
||||
msg_set_ack(hdr, ack);
|
||||
@ -1035,17 +1054,61 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void tipc_link_update_cwin(struct tipc_link *l, int released,
|
||||
bool retransmitted)
|
||||
{
|
||||
int bklog_len = skb_queue_len(&l->backlogq);
|
||||
struct sk_buff_head *txq = &l->transmq;
|
||||
int txq_len = skb_queue_len(txq);
|
||||
u16 cwin = l->window;
|
||||
|
||||
/* Enter fast recovery */
|
||||
if (unlikely(retransmitted)) {
|
||||
l->ssthresh = max_t(u16, l->window / 2, 300);
|
||||
l->window = l->ssthresh;
|
||||
return;
|
||||
}
|
||||
/* Enter slow start */
|
||||
if (unlikely(!released)) {
|
||||
l->ssthresh = max_t(u16, l->window / 2, 300);
|
||||
l->window = l->min_win;
|
||||
return;
|
||||
}
|
||||
/* Don't increase window if no pressure on the transmit queue */
|
||||
if (txq_len + bklog_len < cwin)
|
||||
return;
|
||||
|
||||
/* Don't increase window if there are holes the transmit queue */
|
||||
if (txq_len && l->snd_nxt - buf_seqno(skb_peek(txq)) != txq_len)
|
||||
return;
|
||||
|
||||
l->cong_acks += released;
|
||||
|
||||
/* Slow start */
|
||||
if (cwin <= l->ssthresh) {
|
||||
l->window = min_t(u16, cwin + released, l->max_win);
|
||||
return;
|
||||
}
|
||||
/* Congestion avoidance */
|
||||
if (l->cong_acks < cwin)
|
||||
return;
|
||||
l->window = min_t(u16, ++cwin, l->max_win);
|
||||
l->cong_acks = 0;
|
||||
}
|
||||
|
||||
static void tipc_link_advance_backlog(struct tipc_link *l,
|
||||
struct sk_buff_head *xmitq)
|
||||
{
|
||||
struct sk_buff *skb, *_skb;
|
||||
struct tipc_msg *hdr;
|
||||
u16 seqno = l->snd_nxt;
|
||||
u16 ack = l->rcv_nxt - 1;
|
||||
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
|
||||
struct sk_buff_head *txq = &l->transmq;
|
||||
struct sk_buff *skb, *_skb;
|
||||
u16 ack = l->rcv_nxt - 1;
|
||||
u16 seqno = l->snd_nxt;
|
||||
struct tipc_msg *hdr;
|
||||
u16 cwin = l->window;
|
||||
u32 imp;
|
||||
|
||||
while (skb_queue_len(&l->transmq) < l->window) {
|
||||
while (skb_queue_len(txq) < cwin) {
|
||||
skb = skb_peek(&l->backlogq);
|
||||
if (!skb)
|
||||
break;
|
||||
@ -1141,6 +1204,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
|
||||
struct sk_buff *_skb, *skb = skb_peek(&l->transmq);
|
||||
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
|
||||
u16 ack = l->rcv_nxt - 1;
|
||||
int retransmitted = 0;
|
||||
struct tipc_msg *hdr;
|
||||
int rc = 0;
|
||||
|
||||
@ -1160,7 +1224,6 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
|
||||
continue;
|
||||
if (more(msg_seqno(hdr), to))
|
||||
break;
|
||||
|
||||
if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
|
||||
continue;
|
||||
TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
|
||||
@ -1173,11 +1236,12 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
|
||||
_skb->priority = TC_PRIO_CONTROL;
|
||||
__skb_queue_tail(xmitq, _skb);
|
||||
l->stats.retransmitted++;
|
||||
|
||||
retransmitted++;
|
||||
/* Increase actual retrans counter & mark first time */
|
||||
if (!TIPC_SKB_CB(skb)->retr_cnt++)
|
||||
TIPC_SKB_CB(skb)->retr_stamp = jiffies;
|
||||
}
|
||||
tipc_link_update_cwin(l, 0, retransmitted);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1338,9 +1402,9 @@ static int tipc_link_tnl_rcv(struct tipc_link *l, struct sk_buff *skb,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked)
|
||||
static int tipc_link_release_pkts(struct tipc_link *l, u16 acked)
|
||||
{
|
||||
bool released = false;
|
||||
int released = 0;
|
||||
struct sk_buff *skb, *tmp;
|
||||
|
||||
skb_queue_walk_safe(&l->transmq, skb, tmp) {
|
||||
@ -1348,7 +1412,7 @@ static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked)
|
||||
break;
|
||||
__skb_unlink(skb, &l->transmq);
|
||||
kfree_skb(skb);
|
||||
released = true;
|
||||
released++;
|
||||
}
|
||||
return released;
|
||||
}
|
||||
@ -1417,8 +1481,10 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
|
||||
struct sk_buff *skb, *_skb, *tmp;
|
||||
struct tipc_msg *hdr;
|
||||
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
|
||||
bool retransmitted = false;
|
||||
u16 ack = l->rcv_nxt - 1;
|
||||
bool passed = false;
|
||||
u16 released = 0;
|
||||
u16 seqno, n = 0;
|
||||
int rc = 0;
|
||||
|
||||
@ -1430,6 +1496,7 @@ next_gap_ack:
|
||||
/* release skb */
|
||||
__skb_unlink(skb, &l->transmq);
|
||||
kfree_skb(skb);
|
||||
released++;
|
||||
} else if (less_eq(seqno, acked + gap)) {
|
||||
/* First, check if repeated retrans failures occurs? */
|
||||
if (!passed && link_retransmit_failure(l, l, &rc))
|
||||
@ -1449,7 +1516,7 @@ next_gap_ack:
|
||||
_skb->priority = TC_PRIO_CONTROL;
|
||||
__skb_queue_tail(xmitq, _skb);
|
||||
l->stats.retransmitted++;
|
||||
|
||||
retransmitted = true;
|
||||
/* Increase actual retrans counter & mark first time */
|
||||
if (!TIPC_SKB_CB(skb)->retr_cnt++)
|
||||
TIPC_SKB_CB(skb)->retr_stamp = jiffies;
|
||||
@ -1463,7 +1530,10 @@ next_gap_ack:
|
||||
goto next_gap_ack;
|
||||
}
|
||||
}
|
||||
|
||||
if (released || retransmitted)
|
||||
tipc_link_update_cwin(l, released, retransmitted);
|
||||
if (released)
|
||||
tipc_link_advance_backlog(l, xmitq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1487,7 +1557,6 @@ int tipc_link_build_state_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
|
||||
l->snd_nxt = l->rcv_nxt;
|
||||
return TIPC_LINK_SND_STATE;
|
||||
}
|
||||
|
||||
/* Unicast ACK */
|
||||
l->rcv_unacked = 0;
|
||||
l->stats.sent_acks++;
|
||||
@ -1521,7 +1590,8 @@ static int tipc_link_build_nack_msg(struct tipc_link *l,
|
||||
struct sk_buff_head *xmitq)
|
||||
{
|
||||
u32 def_cnt = ++l->stats.deferred_recv;
|
||||
u32 defq_len = skb_queue_len(&l->deferdq);
|
||||
struct sk_buff_head *dfq = &l->deferdq;
|
||||
u32 defq_len = skb_queue_len(dfq);
|
||||
int match1, match2;
|
||||
|
||||
if (link_is_bc_rcvlink(l)) {
|
||||
@ -1532,8 +1602,12 @@ static int tipc_link_build_nack_msg(struct tipc_link *l,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (defq_len >= 3 && !((defq_len - 3) % 16))
|
||||
tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, 0, xmitq);
|
||||
if (defq_len >= 3 && !((defq_len - 3) % 16)) {
|
||||
u16 rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt;
|
||||
|
||||
tipc_link_build_proto_msg(l, STATE_MSG, 0, 0,
|
||||
rcvgap, 0, 0, xmitq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1548,6 +1622,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
|
||||
struct sk_buff_head *defq = &l->deferdq;
|
||||
struct tipc_msg *hdr = buf_msg(skb);
|
||||
u16 seqno, rcv_nxt, win_lim;
|
||||
int released = 0;
|
||||
int rc = 0;
|
||||
|
||||
/* Verify and update link state */
|
||||
@ -1566,21 +1641,17 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
|
||||
if (unlikely(!link_is_up(l))) {
|
||||
if (l->state == LINK_ESTABLISHING)
|
||||
rc = TIPC_LINK_UP_EVT;
|
||||
goto drop;
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Drop if outside receive window */
|
||||
if (unlikely(less(seqno, rcv_nxt) || more(seqno, win_lim))) {
|
||||
l->stats.duplicates++;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Forward queues and wake up waiting users */
|
||||
if (likely(tipc_link_release_pkts(l, msg_ack(hdr)))) {
|
||||
tipc_link_advance_backlog(l, xmitq);
|
||||
if (unlikely(!skb_queue_empty(&l->wakeupq)))
|
||||
link_prepare_wakeup(l);
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
released += tipc_link_release_pkts(l, msg_ack(hdr));
|
||||
|
||||
/* Defer delivery if sequence gap */
|
||||
if (unlikely(seqno != rcv_nxt)) {
|
||||
@ -1603,9 +1674,13 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
|
||||
break;
|
||||
} while ((skb = __tipc_skb_dequeue(defq, l->rcv_nxt)));
|
||||
|
||||
return rc;
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
/* Forward queues and wake up waiting users */
|
||||
if (released) {
|
||||
tipc_link_update_cwin(l, released, 0);
|
||||
tipc_link_advance_backlog(l, xmitq);
|
||||
if (unlikely(!skb_queue_empty(&l->wakeupq)))
|
||||
link_prepare_wakeup(l);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1631,7 +1706,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
|
||||
if (!tipc_link_is_up(l) && (mtyp == STATE_MSG))
|
||||
return;
|
||||
|
||||
if (!skb_queue_empty(dfq))
|
||||
if ((probe || probe_reply) && !skb_queue_empty(dfq))
|
||||
rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt;
|
||||
|
||||
skb = tipc_msg_create(LINK_PROTOCOL, mtyp, INT_H_SIZE,
|
||||
@ -2074,19 +2149,18 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
|
||||
&l->mon_state, l->bearer_id);
|
||||
|
||||
/* Send NACK if peer has sent pkts we haven't received yet */
|
||||
if (more(peers_snd_nxt, rcv_nxt) && !tipc_link_is_synching(l))
|
||||
if ((reply || msg_is_keepalive(hdr)) &&
|
||||
more(peers_snd_nxt, rcv_nxt) &&
|
||||
!tipc_link_is_synching(l) &&
|
||||
skb_queue_empty(&l->deferdq))
|
||||
rcvgap = peers_snd_nxt - l->rcv_nxt;
|
||||
if (rcvgap || reply)
|
||||
tipc_link_build_proto_msg(l, STATE_MSG, 0, reply,
|
||||
rcvgap, 0, 0, xmitq);
|
||||
|
||||
rc |= tipc_link_advance_transmq(l, ack, gap, ga, xmitq);
|
||||
|
||||
/* If NACK, retransmit will now start at right position */
|
||||
if (gap)
|
||||
l->stats.recv_nacks++;
|
||||
|
||||
tipc_link_advance_backlog(l, xmitq);
|
||||
if (unlikely(!skb_queue_empty(&l->wakeupq)))
|
||||
link_prepare_wakeup(l);
|
||||
}
|
||||
@ -2305,15 +2379,18 @@ int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
|
||||
void tipc_link_set_queue_limits(struct tipc_link *l, u32 min_win, u32 max_win)
|
||||
{
|
||||
int max_bulk = TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE);
|
||||
|
||||
l->window = win;
|
||||
l->backlog[TIPC_LOW_IMPORTANCE].limit = max_t(u16, 50, win);
|
||||
l->backlog[TIPC_MEDIUM_IMPORTANCE].limit = max_t(u16, 100, win * 2);
|
||||
l->backlog[TIPC_HIGH_IMPORTANCE].limit = max_t(u16, 150, win * 3);
|
||||
l->backlog[TIPC_CRITICAL_IMPORTANCE].limit = max_t(u16, 200, win * 4);
|
||||
l->min_win = min_win;
|
||||
l->ssthresh = max_win;
|
||||
l->max_win = max_win;
|
||||
l->window = min_win;
|
||||
l->backlog[TIPC_LOW_IMPORTANCE].limit = min_win * 2;
|
||||
l->backlog[TIPC_MEDIUM_IMPORTANCE].limit = min_win * 4;
|
||||
l->backlog[TIPC_HIGH_IMPORTANCE].limit = min_win * 6;
|
||||
l->backlog[TIPC_CRITICAL_IMPORTANCE].limit = min_win * 8;
|
||||
l->backlog[TIPC_SYSTEM_IMPORTANCE].limit = max_bulk;
|
||||
}
|
||||
|
||||
@ -2366,10 +2443,10 @@ int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[])
|
||||
}
|
||||
|
||||
if (props[TIPC_NLA_PROP_WIN]) {
|
||||
u32 win;
|
||||
u32 max_win;
|
||||
|
||||
win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
if ((win < TIPC_MIN_LINK_WIN) || (win > TIPC_MAX_LINK_WIN))
|
||||
max_win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
if (max_win < TIPC_DEF_LINK_WIN || max_win > TIPC_MAX_LINK_WIN)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2605,7 +2682,7 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
|
||||
prop = nla_nest_start_noflag(msg->skb, TIPC_NLA_LINK_PROP);
|
||||
if (!prop)
|
||||
goto attr_msg_full;
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window))
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->max_win))
|
||||
goto prop_msg_full;
|
||||
if (nla_put_u32(msg->skb, TIPC_NLA_PROP_BROADCAST, bc_mode))
|
||||
goto prop_msg_full;
|
||||
|
@ -73,7 +73,7 @@ enum {
|
||||
|
||||
bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
|
||||
int tolerance, char net_plane, u32 mtu, int priority,
|
||||
int window, u32 session, u32 ownnode,
|
||||
u32 min_win, u32 max_win, u32 session, u32 ownnode,
|
||||
u32 peer, u8 *peer_id, u16 peer_caps,
|
||||
struct tipc_link *bc_sndlink,
|
||||
struct tipc_link *bc_rcvlink,
|
||||
@ -81,7 +81,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
|
||||
struct sk_buff_head *namedq,
|
||||
struct tipc_link **link);
|
||||
bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
|
||||
int mtu, int window, u16 peer_caps,
|
||||
int mtu, u32 min_win, u32 max_win, u16 peer_caps,
|
||||
struct sk_buff_head *inputq,
|
||||
struct sk_buff_head *namedq,
|
||||
struct tipc_link *bc_sndlink,
|
||||
@ -115,7 +115,8 @@ char *tipc_link_name_ext(struct tipc_link *l, char *buf);
|
||||
u32 tipc_link_state(struct tipc_link *l);
|
||||
char tipc_link_plane(struct tipc_link *l);
|
||||
int tipc_link_prio(struct tipc_link *l);
|
||||
int tipc_link_window(struct tipc_link *l);
|
||||
int tipc_link_min_win(struct tipc_link *l);
|
||||
int tipc_link_max_win(struct tipc_link *l);
|
||||
void tipc_link_update_caps(struct tipc_link *l, u16 capabilities);
|
||||
bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr);
|
||||
unsigned long tipc_link_tolerance(struct tipc_link *l);
|
||||
@ -124,7 +125,7 @@ void tipc_link_set_tolerance(struct tipc_link *l, u32 tol,
|
||||
void tipc_link_set_prio(struct tipc_link *l, u32 prio,
|
||||
struct sk_buff_head *xmitq);
|
||||
void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit);
|
||||
void tipc_link_set_queue_limits(struct tipc_link *l, u32 window);
|
||||
void tipc_link_set_queue_limits(struct tipc_link *l, u32 min_win, u32 max_win);
|
||||
int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
|
||||
struct tipc_link *link, int nlflags);
|
||||
int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
|
||||
|
@ -1139,7 +1139,8 @@ void tipc_node_check_dest(struct net *net, u32 addr,
|
||||
snd_l = tipc_bc_sndlink(net);
|
||||
if (!tipc_link_bc_create(net, tipc_own_addr(net),
|
||||
addr, U16_MAX,
|
||||
tipc_link_window(snd_l),
|
||||
tipc_link_min_win(snd_l),
|
||||
tipc_link_max_win(snd_l),
|
||||
n->capabilities,
|
||||
&n->bc_entry.inputq1,
|
||||
&n->bc_entry.namedq, snd_l,
|
||||
@ -1233,7 +1234,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
|
||||
get_random_bytes(&session, sizeof(u16));
|
||||
if (!tipc_link_create(net, if_name, b->identity, b->tolerance,
|
||||
b->net_plane, b->mtu, b->priority,
|
||||
b->window, session,
|
||||
b->min_win, b->max_win, session,
|
||||
tipc_own_addr(net), addr, peer_id,
|
||||
n->capabilities,
|
||||
tipc_bc_sndlink(n->net), n->bc_entry.link,
|
||||
@ -2360,8 +2361,7 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
|
||||
if (attrs[TIPC_NLA_LINK_PROP]) {
|
||||
struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
|
||||
|
||||
err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP],
|
||||
props);
|
||||
err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], props);
|
||||
if (err) {
|
||||
res = err;
|
||||
goto out;
|
||||
@ -2380,10 +2380,12 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
|
||||
tipc_link_set_prio(link, prio, &xmitq);
|
||||
}
|
||||
if (props[TIPC_NLA_PROP_WIN]) {
|
||||
u32 win;
|
||||
u32 max_win;
|
||||
|
||||
win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
tipc_link_set_queue_limits(link, win);
|
||||
max_win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
|
||||
tipc_link_set_queue_limits(link,
|
||||
tipc_link_min_win(link),
|
||||
max_win);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -828,7 +828,8 @@ struct tipc_media udp_media_info = {
|
||||
.msg2addr = tipc_udp_msg2addr,
|
||||
.priority = TIPC_DEF_LINK_PRI,
|
||||
.tolerance = TIPC_DEF_LINK_TOL,
|
||||
.window = TIPC_DEF_LINK_WIN,
|
||||
.min_win = TIPC_DEF_LINK_WIN,
|
||||
.max_win = TIPC_DEF_LINK_WIN,
|
||||
.mtu = TIPC_DEF_LINK_UDP_MTU,
|
||||
.type_id = TIPC_MEDIA_TYPE_UDP,
|
||||
.hwaddr_len = 0,
|
||||
|
Loading…
Reference in New Issue
Block a user