tipc: introduce variable window congestion control
authorJon Maloy <jon.maloy@ericsson.com>
Mon, 9 Dec 2019 23:52:46 +0000 (00:52 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 11 Dec 2019 01:31:15 +0000 (17:31 -0800)
We introduce a simple variable window congestion control for links.
The algorithm is inspired by the Reno algorithm, covering both 'slow
start', 'congestion avoidance', and 'fast recovery' modes.

- We introduce hard lower and upper window limits per link, still
  different and configurable per bearer type.

- We introduce a 'slow start theshold' variable, initially set to
  the maximum window size.

- We let a link start at the minimum congestion window, i.e. in slow
  start mode, and then let is grow rapidly (+1 per rceived ACK) until
  it reaches the slow start threshold and enters congestion avoidance
  mode.

- In congestion avoidance mode we increment the congestion window for
  each window-size number of acked packets, up to a possible maximum
  equal to the configured maximum window.

- For each non-duplicate NACK received, we drop back to fast recovery
  mode, by setting the both the slow start threshold to and the
  congestion window to (current_congestion_window / 2).

- If the timeout handler finds that the transmit queue has not moved
  since the previous timeout, it drops the link back to slow start
  and forces a probe containing the last sent sequence number to the
  sent to the peer, so that this can discover the stale situation.

This change does in reality have effect only on unicast ethernet
transport, as we have seen that there is no room whatsoever for
increasing the window max size for the UDP bearer.
For now, we also choose to keep the limits for the broadcast link
unchanged and equal.

This algorithm seems to give a 50-100% throughput improvement for
messages larger than MTU.

Suggested-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/bcast.c
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/eth_media.c
net/tipc/ib_media.c
net/tipc/link.c
net/tipc/link.h
net/tipc/node.c
net/tipc/udp_media.c

index 55aeba681cf4ede019470b5bf1728a78664daa65..42e01e9cf893ed396fd9ba0a58baff0897f74bbf 100644 (file)
@@ -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,
index d7ec26bd739d70034884255ed0123d299870e8a7..34ca7b789ebaef2dfa9e463e534cf9af886b5092 100644 (file)
@@ -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;
index d0c79cc6c0c209ae1f61db2aecc1d5c733ae76df..bc0023119da2f5c5c8054e0d282b6340a8a27801 100644 (file)
@@ -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;
index f69a2fde9f4a065472f1a14aeee22c6380e07fa4..8b0bb600602de5f3cc1dfc76b116666820461b51 100644 (file)
@@ -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"
index e8c16718e3faea3bf4983f12f2f5fc5c289175eb..7aa9ff88458d6463134503512008ea5368f420eb 100644 (file)
@@ -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"
index 3528181fd0f370a6ba623beebe3b8d5a33ea87d8..94dd48cd70a3d58c8110f4c0933a799da05aca8a 100644 (file)
@@ -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)
 {
+       u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
+       struct sk_buff_head *txq = &l->transmq;
        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;
+       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++;
@@ -1553,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 */
@@ -1571,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)) {
@@ -1608,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;
 }
 
@@ -2084,17 +2154,13 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
                    !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 */
+               rc |= tipc_link_advance_transmq(l, ack, gap, ga, xmitq);
                if (gap)
                        l->stats.recv_nacks++;
-
-               tipc_link_advance_backlog(l, xmitq);
                if (unlikely(!skb_queue_empty(&l->wakeupq)))
                        link_prepare_wakeup(l);
        }
@@ -2313,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;
 }
 
@@ -2374,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;
        }
 
@@ -2613,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;
index c09e9d49d0a34befbafb34ac968b8ecd10b5d0ab..d3c1c3fc16590da198a8e0ce150c0b9e44a190e3 100644 (file)
@@ -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[]);
index ab04e00cb95b53fc7d62e413ef582fa9cad5fc50..99b28b69fc174a09cd6a73db84e7149ba673d51a 100644 (file)
@@ -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);
                }
        }
 
index ed113735c019e2a51a97c6bec274a5d160e3fd9f..d6620ad535461a4d04ed5ba90569ce8b7df9f994 100644 (file)
@@ -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,