Skip to content

Commit 6012052

Browse files
Jon Paul Maloydavem330
authored andcommitted
tipc: simplify connection congestion handling
As a consequence of the recently introduced serialized access to the socket in commit 8d94168a761819d10252bab1f8de6d7b202c3baa ("tipc: same receive code path for connection protocol and data messages") we can make a number of simplifications in the detection and handling of connection congestion situations. - We don't need to keep two counters, one for sent messages and one for acked messages. There is no longer any risk for races between acknowledge messages arriving in BH and data message sending running in user context. So we merge this into one counter, 'sent_unacked', which is incremented at sending and subtracted from at acknowledge reception. - We don't need to set the 'congested' field in tipc_port to true before we sent the message, and clear it when sending is successful. (As a matter of fact, it was never necessary; the field was set in link_schedule_port() before any wakeup could arrive anyway.) - We keep the conditions for link congestion and connection connection congestion separated. There would otherwise be a risk that an arriving acknowledge message may wake up a user sleeping because of link congestion. - We can simplify reception of acknowledge messages. We also make some cosmetic/structural changes: - We rename the 'congested' field to the more correct 'link_cong´. - We rename 'conn_unacked' to 'rcv_unacked' - We move the above mentioned fields from struct tipc_port to struct tipc_sock. Signed-off-by: Jon Maloy <[email protected]> Reviewed-by: Erik Hugne <[email protected]> Reviewed-by: Ying Xue <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ac0074e commit 6012052

File tree

5 files changed

+43
-54
lines changed

5 files changed

+43
-54
lines changed

net/tipc/link.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,13 +332,15 @@ void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down)
332332
static int link_schedule_port(struct tipc_link *l_ptr, u32 origport, u32 sz)
333333
{
334334
struct tipc_port *p_ptr;
335+
struct tipc_sock *tsk;
335336

336337
spin_lock_bh(&tipc_port_list_lock);
337338
p_ptr = tipc_port_lock(origport);
338339
if (p_ptr) {
339340
if (!list_empty(&p_ptr->wait_list))
340341
goto exit;
341-
p_ptr->congested = 1;
342+
tsk = tipc_port_to_sock(p_ptr);
343+
tsk->link_cong = 1;
342344
p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt);
343345
list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);
344346
l_ptr->stats.link_congs++;
@@ -352,6 +354,7 @@ static int link_schedule_port(struct tipc_link *l_ptr, u32 origport, u32 sz)
352354
void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all)
353355
{
354356
struct tipc_port *p_ptr;
357+
struct tipc_sock *tsk;
355358
struct tipc_port *temp_p_ptr;
356359
int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size;
357360

@@ -367,10 +370,11 @@ void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all)
367370
wait_list) {
368371
if (win <= 0)
369372
break;
373+
tsk = tipc_port_to_sock(p_ptr);
370374
list_del_init(&p_ptr->wait_list);
371375
spin_lock_bh(p_ptr->lock);
372-
p_ptr->congested = 0;
373-
tipc_port_wakeup(p_ptr);
376+
tsk->link_cong = 0;
377+
tipc_sock_wakeup(tsk);
374378
win -= p_ptr->waiting_pkts;
375379
spin_unlock_bh(p_ptr->lock);
376380
}

net/tipc/port.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,6 @@ void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp)
186186
tipc_port_list_free(dp);
187187
}
188188

189-
190-
void tipc_port_wakeup(struct tipc_port *port)
191-
{
192-
tipc_sock_wakeup(tipc_port_to_sock(port));
193-
}
194-
195189
/* tipc_port_init - intiate TIPC port and lock it
196190
*
197191
* Returns obtained reference if initialization is successful, zero otherwise
@@ -209,7 +203,6 @@ u32 tipc_port_init(struct tipc_port *p_ptr,
209203
}
210204

211205
p_ptr->max_pkt = MAX_PKT_DEFAULT;
212-
p_ptr->sent = 1;
213206
p_ptr->ref = ref;
214207
INIT_LIST_HEAD(&p_ptr->wait_list);
215208
INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
@@ -459,10 +452,9 @@ void tipc_acknowledge(u32 ref, u32 ack)
459452
p_ptr = tipc_port_lock(ref);
460453
if (!p_ptr)
461454
return;
462-
if (p_ptr->connected) {
463-
p_ptr->conn_unacked -= ack;
455+
if (p_ptr->connected)
464456
buf = port_build_proto_msg(p_ptr, CONN_ACK, ack);
465-
}
457+
466458
tipc_port_unlock(p_ptr);
467459
if (!buf)
468460
return;

net/tipc/port.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,13 @@
5353
* @connected: non-zero if port is currently connected to a peer port
5454
* @conn_type: TIPC type used when connection was established
5555
* @conn_instance: TIPC instance used when connection was established
56-
* @conn_unacked: number of unacknowledged messages received from peer port
5756
* @published: non-zero if port has one or more associated names
58-
* @congested: non-zero if cannot send because of link or port congestion
5957
* @max_pkt: maximum packet size "hint" used when building messages sent by port
6058
* @ref: unique reference to port in TIPC object registry
6159
* @phdr: preformatted message header used when sending messages
6260
* @port_list: adjacent ports in TIPC's global list of ports
6361
* @wait_list: adjacent ports in list of ports waiting on link congestion
6462
* @waiting_pkts:
65-
* @sent: # of non-empty messages sent by port
66-
* @acked: # of non-empty message acknowledgements from connected port's peer
6763
* @publications: list of publications for port
6864
* @pub_count: total # of publications port has made during its lifetime
6965
* @probing_state:
@@ -76,17 +72,13 @@ struct tipc_port {
7672
int connected;
7773
u32 conn_type;
7874
u32 conn_instance;
79-
u32 conn_unacked;
8075
int published;
81-
u32 congested;
8276
u32 max_pkt;
8377
u32 ref;
8478
struct tipc_msg phdr;
8579
struct list_head port_list;
8680
struct list_head wait_list;
8781
u32 waiting_pkts;
88-
u32 sent;
89-
u32 acked;
9082
struct list_head publications;
9183
u32 pub_count;
9284
u32 probing_state;
@@ -120,8 +112,6 @@ int tipc_port_disconnect(u32 portref);
120112

121113
int tipc_port_shutdown(u32 ref);
122114

123-
void tipc_port_wakeup(struct tipc_port *port);
124-
125115
/*
126116
* The following routines require that the port be locked on entry
127117
*/
@@ -161,12 +151,6 @@ static inline void tipc_port_unlock(struct tipc_port *p_ptr)
161151
spin_unlock_bh(p_ptr->lock);
162152
}
163153

164-
static inline int tipc_port_congested(struct tipc_port *p_ptr)
165-
{
166-
return ((p_ptr->sent - p_ptr->acked) >= TIPC_FLOWCTRL_WIN);
167-
}
168-
169-
170154
static inline u32 tipc_port_peernode(struct tipc_port *p_ptr)
171155
{
172156
return msg_destnode(&p_ptr->phdr);

net/tipc/socket.c

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
207207
sk->sk_data_ready = tipc_data_ready;
208208
sk->sk_write_space = tipc_write_space;
209209
tsk->conn_timeout = CONN_TIMEOUT_DEFAULT;
210-
tsk->port.sent = 0;
210+
tsk->sent_unacked = 0;
211211
atomic_set(&tsk->dupl_rcvcnt, 0);
212212
tipc_port_unlock(port);
213213

@@ -513,12 +513,12 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
513513

514514
switch ((int)sock->state) {
515515
case SS_UNCONNECTED:
516-
if (!tsk->port.congested)
516+
if (!tsk->link_cong)
517517
mask |= POLLOUT;
518518
break;
519519
case SS_READY:
520520
case SS_CONNECTED:
521-
if (!tsk->port.congested)
521+
if (!tsk->link_cong && !tipc_sk_conn_cong(tsk))
522522
mask |= POLLOUT;
523523
/* fall thru' */
524524
case SS_CONNECTING:
@@ -546,7 +546,7 @@ int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, struct sk_buff *buf)
546546
{
547547
struct tipc_msg *msg = buf_msg(buf);
548548
struct tipc_port *port = &tsk->port;
549-
int wakeable;
549+
int conn_cong;
550550

551551
/* Ignore if connection cannot be validated: */
552552
if (!port->connected || !tipc_port_peer_msg(port, msg))
@@ -555,13 +555,10 @@ int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, struct sk_buff *buf)
555555
port->probing_state = TIPC_CONN_OK;
556556

557557
if (msg_type(msg) == CONN_ACK) {
558-
wakeable = tipc_port_congested(port) && port->congested;
559-
port->acked += msg_msgcnt(msg);
560-
if (!tipc_port_congested(port)) {
561-
port->congested = 0;
562-
if (wakeable)
563-
tipc_port_wakeup(port);
564-
}
558+
conn_cong = tipc_sk_conn_cong(tsk);
559+
tsk->sent_unacked -= msg_msgcnt(msg);
560+
if (conn_cong)
561+
tipc_sock_wakeup(tsk);
565562
} else if (msg_type(msg) == CONN_PROBE) {
566563
if (!tipc_msg_reverse(buf, dnode, TIPC_OK))
567564
return TIPC_OK;
@@ -626,7 +623,7 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
626623
return sock_intr_errno(*timeo_p);
627624

628625
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
629-
done = sk_wait_event(sk, timeo_p, !tsk->port.congested);
626+
done = sk_wait_event(sk, timeo_p, !tsk->link_cong);
630627
finish_wait(sk_sleep(sk), &wait);
631628
} while (!done);
632629
return 0;
@@ -800,7 +797,6 @@ static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
800797
{
801798
struct sock *sk = sock->sk;
802799
struct tipc_sock *tsk = tipc_sk(sk);
803-
struct tipc_port *port = &tsk->port;
804800
DEFINE_WAIT(wait);
805801
int done;
806802

@@ -819,7 +815,9 @@ static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
819815

820816
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
821817
done = sk_wait_event(sk, timeo_p,
822-
(!port->congested || !port->connected));
818+
(!tsk->link_cong &&
819+
!tipc_sk_conn_cong(tsk)) ||
820+
!tsk->port.connected);
823821
finish_wait(sk_sleep(sk), &wait);
824822
} while (!done);
825823
return 0;
@@ -856,7 +854,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
856854
if (unlikely(dest)) {
857855
rc = tipc_sendmsg(iocb, sock, m, dsz);
858856
if (dsz && (dsz == rc))
859-
tsk->port.sent = 1;
857+
tsk->sent_unacked = 1;
860858
return rc;
861859
}
862860
if (dsz > (uint)INT_MAX)
@@ -875,7 +873,6 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
875873

876874
timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
877875
dnode = tipc_port_peernode(port);
878-
port->congested = 1;
879876

880877
next:
881878
mtu = port->max_pkt;
@@ -884,11 +881,10 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
884881
if (unlikely(rc < 0))
885882
goto exit;
886883
do {
887-
port->congested = 1;
888-
if (likely(!tipc_port_congested(port))) {
884+
if (likely(!tipc_sk_conn_cong(tsk))) {
889885
rc = tipc_link_xmit2(buf, dnode, ref);
890886
if (likely(!rc)) {
891-
port->sent++;
887+
tsk->sent_unacked++;
892888
sent += send;
893889
if (sent == dsz)
894890
break;
@@ -903,8 +899,6 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
903899
}
904900
rc = tipc_wait_for_sndpkt(sock, &timeo);
905901
} while (!rc);
906-
907-
port->congested = 0;
908902
exit:
909903
if (iocb)
910904
release_sock(sk);
@@ -1169,8 +1163,10 @@ static int tipc_recvmsg(struct kiocb *iocb, struct socket *sock,
11691163
/* Consume received message (optional) */
11701164
if (likely(!(flags & MSG_PEEK))) {
11711165
if ((sock->state != SS_READY) &&
1172-
(++port->conn_unacked >= TIPC_CONNACK_INTV))
1173-
tipc_acknowledge(port->ref, port->conn_unacked);
1166+
(++tsk->rcv_unacked >= TIPC_CONNACK_INTV)) {
1167+
tipc_acknowledge(port->ref, tsk->rcv_unacked);
1168+
tsk->rcv_unacked = 0;
1169+
}
11741170
advance_rx_queue(sk);
11751171
}
11761172
exit:
@@ -1278,8 +1274,10 @@ static int tipc_recv_stream(struct kiocb *iocb, struct socket *sock,
12781274

12791275
/* Consume received message (optional) */
12801276
if (likely(!(flags & MSG_PEEK))) {
1281-
if (unlikely(++port->conn_unacked >= TIPC_CONNACK_INTV))
1282-
tipc_acknowledge(port->ref, port->conn_unacked);
1277+
if (unlikely(++tsk->rcv_unacked >= TIPC_CONNACK_INTV)) {
1278+
tipc_acknowledge(port->ref, tsk->rcv_unacked);
1279+
tsk->rcv_unacked = 0;
1280+
}
12831281
advance_rx_queue(sk);
12841282
}
12851283

net/tipc/socket.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,19 @@
4848
* @peer_name: the peer of the connection, if any
4949
* @conn_timeout: the time we can wait for an unresponded setup request
5050
* @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue
51+
* @link_cong: non-zero if owner must sleep because of link congestion
52+
* @sent_unacked: # messages sent by socket, and not yet acked by peer
53+
* @rcv_unacked: # messages read by user, but not yet acked back to peer
5154
*/
5255

5356
struct tipc_sock {
5457
struct sock sk;
5558
struct tipc_port port;
5659
unsigned int conn_timeout;
5760
atomic_t dupl_rcvcnt;
61+
int link_cong;
62+
uint sent_unacked;
63+
uint rcv_unacked;
5864
};
5965

6066
static inline struct tipc_sock *tipc_sk(const struct sock *sk)
@@ -72,6 +78,11 @@ static inline void tipc_sock_wakeup(struct tipc_sock *tsk)
7278
tsk->sk.sk_write_space(&tsk->sk);
7379
}
7480

81+
static inline int tipc_sk_conn_cong(struct tipc_sock *tsk)
82+
{
83+
return tsk->sent_unacked >= TIPC_FLOWCTRL_WIN;
84+
}
85+
7586
int tipc_sk_rcv(struct sk_buff *buf);
7687

7788
#endif

0 commit comments

Comments
 (0)