Skip to content

Commit 9512515

Browse files
committed
Merge branch 'mptcp-small-improvements-fix-and-clean-ups'
Mat Martineau says: ==================== mptcp: small improvements, fix and clean-ups This series contain mostly unrelated patches: - The two first patches can be seen as "fixes". They are part of this series for -next because it looks like the last batch of fixes for v6.9 has already been sent. These fixes are not urgent, so they can wait if an unlikely v6.9-rc8 is published. About the two patches: - Patch 1 fixes getsockopt(SO_KEEPALIVE) support on MPTCP sockets - Patch 2 makes sure the full TCP keep-alive feature is supported, not just SO_KEEPALIVE. - Patch 3 is a small optimisation when getsockopt(MPTCP_INFO) is used without buffer, just to check if MPTCP is still being used: no fallback to TCP. - Patch 4 adds net.mptcp.available_schedulers sysctl knob to list packet schedulers, similar to net.ipv4.tcp_available_congestion_control. - Patch 5 and 6 fix CheckPatch warnings: "prefer strscpy over strcpy" and "else is not generally useful after a break or return". - Patch 7 and 8 remove and add header includes to avoid unused ones, and add missing ones to be self-contained. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 40a1d11 + 7fad5b3 commit 9512515

File tree

10 files changed

+143
-24
lines changed

10 files changed

+143
-24
lines changed

include/net/mptcp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ struct mptcp_out_options {
9797
};
9898

9999
#define MPTCP_SCHED_NAME_MAX 16
100+
#define MPTCP_SCHED_MAX 128
101+
#define MPTCP_SCHED_BUF_MAX (MPTCP_SCHED_NAME_MAX * MPTCP_SCHED_MAX)
102+
100103
#define MPTCP_SUBFLOWS_MAX 8
101104

102105
struct mptcp_sched_data {

net/mptcp/ctrl.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
9292
pernet->allow_join_initial_addr_port = 1;
9393
pernet->stale_loss_cnt = 4;
9494
pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
95-
strcpy(pernet->scheduler, "default");
95+
strscpy(pernet->scheduler, "default", sizeof(pernet->scheduler));
9696
}
9797

9898
#ifdef CONFIG_SYSCTL
@@ -133,6 +133,24 @@ static int proc_scheduler(struct ctl_table *ctl, int write,
133133
return ret;
134134
}
135135

136+
static int proc_available_schedulers(struct ctl_table *ctl,
137+
int write, void *buffer,
138+
size_t *lenp, loff_t *ppos)
139+
{
140+
struct ctl_table tbl = { .maxlen = MPTCP_SCHED_BUF_MAX, };
141+
int ret;
142+
143+
tbl.data = kmalloc(tbl.maxlen, GFP_USER);
144+
if (!tbl.data)
145+
return -ENOMEM;
146+
147+
mptcp_get_available_schedulers(tbl.data, MPTCP_SCHED_BUF_MAX);
148+
ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
149+
kfree(tbl.data);
150+
151+
return ret;
152+
}
153+
136154
static struct ctl_table mptcp_sysctl_table[] = {
137155
{
138156
.procname = "enabled",
@@ -187,6 +205,12 @@ static struct ctl_table mptcp_sysctl_table[] = {
187205
.mode = 0644,
188206
.proc_handler = proc_scheduler,
189207
},
208+
{
209+
.procname = "available_schedulers",
210+
.maxlen = MPTCP_SCHED_BUF_MAX,
211+
.mode = 0644,
212+
.proc_handler = proc_available_schedulers,
213+
},
190214
{
191215
.procname = "close_timeout",
192216
.maxlen = sizeof(unsigned int),
@@ -214,7 +238,8 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
214238
table[4].data = &pernet->stale_loss_cnt;
215239
table[5].data = &pernet->pm_type;
216240
table[6].data = &pernet->scheduler;
217-
table[7].data = &pernet->close_timeout;
241+
/* table[7] is for available_schedulers which is read-only info */
242+
table[8].data = &pernet->close_timeout;
218243

219244
hdr = register_net_sysctl_sz(net, MPTCP_SYSCTL_PATH, table,
220245
ARRAY_SIZE(mptcp_sysctl_table));

net/mptcp/mib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0-or-later */
22

3+
#include <net/inet_common.h>
4+
35
enum linux_mptcp_mib_field {
46
MPTCP_MIB_NUM = 0,
57
MPTCP_MIB_MPCAPABLEPASSIVE, /* Received SYN with MP_CAPABLE */

net/mptcp/pm_netlink.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "protocol.h"
1616
#include "mib.h"
17+
#include "mptcp_pm_gen.h"
1718

1819
static int pm_nl_pernet_id;
1920

net/mptcp/pm_userspace.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "protocol.h"
88
#include "mib.h"
9+
#include "mptcp_pm_gen.h"
910

1011
void mptcp_free_local_addr_list(struct mptcp_sock *msk)
1112
{

net/mptcp/protocol.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,7 +2814,8 @@ static void mptcp_ca_reset(struct sock *sk)
28142814
struct inet_connection_sock *icsk = inet_csk(sk);
28152815

28162816
tcp_assign_congestion_control(sk);
2817-
strcpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name);
2817+
strscpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name,
2818+
sizeof(mptcp_sk(sk)->ca_name));
28182819

28192820
/* no need to keep a reference to the ops, the name will suffice */
28202821
tcp_cleanup_congestion_control(sk);
@@ -4169,7 +4170,7 @@ int __init mptcp_proto_v6_init(void)
41694170
int err;
41704171

41714172
mptcp_v6_prot = mptcp_prot;
4172-
strcpy(mptcp_v6_prot.name, "MPTCPv6");
4173+
strscpy(mptcp_v6_prot.name, "MPTCPv6", sizeof(mptcp_v6_prot.name));
41734174
mptcp_v6_prot.slab = NULL;
41744175
mptcp_v6_prot.obj_size = sizeof(struct mptcp6_sock);
41754176
mptcp_v6_prot.ipv6_pinfo_offset = offsetof(struct mptcp6_sock, np);

net/mptcp/protocol.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#include <net/genetlink.h>
1515
#include <net/rstreason.h>
1616

17-
#include "mptcp_pm_gen.h"
18-
1917
#define MPTCP_SUPPORTED_VERSION 1
2018

2119
/* MPTCP option bits */
@@ -312,6 +310,9 @@ struct mptcp_sock {
312310
free_first:1,
313311
rcvspace_init:1;
314312
u32 notsent_lowat;
313+
int keepalive_cnt;
314+
int keepalive_idle;
315+
int keepalive_intvl;
315316
struct work_struct work;
316317
struct sk_buff *ooo_last_skb;
317318
struct rb_root out_of_order_queue;
@@ -683,6 +684,7 @@ unsigned int mptcp_stale_loss_cnt(const struct net *net);
683684
unsigned int mptcp_close_timeout(const struct sock *sk);
684685
int mptcp_get_pm_type(const struct net *net);
685686
const char *mptcp_get_scheduler(const struct net *net);
687+
void mptcp_get_available_schedulers(char *buf, size_t maxlen);
686688
void __mptcp_subflow_fully_established(struct mptcp_sock *msk,
687689
struct mptcp_subflow_context *subflow,
688690
const struct mptcp_options_received *mp_opt);

net/mptcp/sched.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,28 @@ struct mptcp_sched_ops *mptcp_sched_find(const char *name)
5151
return ret;
5252
}
5353

54+
/* Build string with list of available scheduler values.
55+
* Similar to tcp_get_available_congestion_control()
56+
*/
57+
void mptcp_get_available_schedulers(char *buf, size_t maxlen)
58+
{
59+
struct mptcp_sched_ops *sched;
60+
size_t offs = 0;
61+
62+
rcu_read_lock();
63+
spin_lock(&mptcp_sched_list_lock);
64+
list_for_each_entry_rcu(sched, &mptcp_sched_list, list) {
65+
offs += snprintf(buf + offs, maxlen - offs,
66+
"%s%s",
67+
offs == 0 ? "" : " ", sched->name);
68+
69+
if (WARN_ON_ONCE(offs >= maxlen))
70+
break;
71+
}
72+
spin_unlock(&mptcp_sched_list_lock);
73+
rcu_read_unlock();
74+
}
75+
5476
int mptcp_register_scheduler(struct mptcp_sched_ops *sched)
5577
{
5678
if (!sched->get_subflow)

net/mptcp/sockopt.c

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,6 @@ static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname,
181181

182182
switch (optname) {
183183
case SO_KEEPALIVE:
184-
mptcp_sol_socket_sync_intval(msk, optname, val);
185-
return 0;
186184
case SO_DEBUG:
187185
case SO_MARK:
188186
case SO_PRIORITY:
@@ -618,12 +616,37 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
618616
}
619617

620618
if (ret == 0)
621-
strcpy(msk->ca_name, name);
619+
strscpy(msk->ca_name, name, sizeof(msk->ca_name));
622620

623621
release_sock(sk);
624622
return ret;
625623
}
626624

625+
static int __mptcp_setsockopt_set_val(struct mptcp_sock *msk, int max,
626+
int (*set_val)(struct sock *, int),
627+
int *msk_val, int val)
628+
{
629+
struct mptcp_subflow_context *subflow;
630+
int err = 0;
631+
632+
mptcp_for_each_subflow(msk, subflow) {
633+
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
634+
int ret;
635+
636+
lock_sock(ssk);
637+
ret = set_val(ssk, val);
638+
err = err ? : ret;
639+
release_sock(ssk);
640+
}
641+
642+
if (!err) {
643+
*msk_val = val;
644+
sockopt_seq_inc(msk);
645+
}
646+
647+
return err;
648+
}
649+
627650
static int __mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, int val)
628651
{
629652
struct mptcp_subflow_context *subflow;
@@ -820,6 +843,22 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
820843
case TCP_NODELAY:
821844
ret = __mptcp_setsockopt_sol_tcp_nodelay(msk, val);
822845
break;
846+
case TCP_KEEPIDLE:
847+
ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPIDLE,
848+
&tcp_sock_set_keepidle_locked,
849+
&msk->keepalive_idle, val);
850+
break;
851+
case TCP_KEEPINTVL:
852+
ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPINTVL,
853+
&tcp_sock_set_keepintvl,
854+
&msk->keepalive_intvl, val);
855+
break;
856+
case TCP_KEEPCNT:
857+
ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPCNT,
858+
&tcp_sock_set_keepcnt,
859+
&msk->keepalive_cnt,
860+
val);
861+
break;
823862
default:
824863
ret = -ENOPROTOOPT;
825864
}
@@ -960,6 +999,10 @@ static int mptcp_getsockopt_info(struct mptcp_sock *msk, char __user *optval, in
960999
if (get_user(len, optlen))
9611000
return -EFAULT;
9621001

1002+
/* When used only to check if a fallback to TCP happened. */
1003+
if (len == 0)
1004+
return 0;
1005+
9631006
len = min_t(unsigned int, len, sizeof(struct mptcp_info));
9641007

9651008
mptcp_diag_fill_info(msk, &m_info);
@@ -1328,6 +1371,8 @@ static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval,
13281371
static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
13291372
char __user *optval, int __user *optlen)
13301373
{
1374+
struct sock *sk = (void *)msk;
1375+
13311376
switch (optname) {
13321377
case TCP_ULP:
13331378
case TCP_CONGESTION:
@@ -1346,6 +1391,18 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
13461391
return mptcp_put_int_option(msk, optval, optlen, msk->cork);
13471392
case TCP_NODELAY:
13481393
return mptcp_put_int_option(msk, optval, optlen, msk->nodelay);
1394+
case TCP_KEEPIDLE:
1395+
return mptcp_put_int_option(msk, optval, optlen,
1396+
msk->keepalive_idle ? :
1397+
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_time) / HZ);
1398+
case TCP_KEEPINTVL:
1399+
return mptcp_put_int_option(msk, optval, optlen,
1400+
msk->keepalive_intvl ? :
1401+
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_intvl) / HZ);
1402+
case TCP_KEEPCNT:
1403+
return mptcp_put_int_option(msk, optval, optlen,
1404+
msk->keepalive_cnt ? :
1405+
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_probes));
13491406
case TCP_NOTSENT_LOWAT:
13501407
return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat);
13511408
case TCP_IS_MPTCP:
@@ -1465,6 +1522,9 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
14651522
tcp_set_congestion_control(ssk, msk->ca_name, false, true);
14661523
__tcp_sock_set_cork(ssk, !!msk->cork);
14671524
__tcp_sock_set_nodelay(ssk, !!msk->nodelay);
1525+
tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle);
1526+
tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl);
1527+
tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt);
14681528

14691529
inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
14701530
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));

net/mptcp/subflow.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,8 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
11191119
}
11201120

11211121
if (mpext->data_fin == 1) {
1122+
u64 data_fin_seq;
1123+
11221124
if (data_len == 1) {
11231125
bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq,
11241126
mpext->dsn64);
@@ -1131,26 +1133,26 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
11311133
*/
11321134
skb_ext_del(skb, SKB_EXT_MPTCP);
11331135
return MAPPING_OK;
1134-
} else {
1135-
if (updated)
1136-
mptcp_schedule_work((struct sock *)msk);
1137-
1138-
return MAPPING_DATA_FIN;
11391136
}
1140-
} else {
1141-
u64 data_fin_seq = mpext->data_seq + data_len - 1;
11421137

1143-
/* If mpext->data_seq is a 32-bit value, data_fin_seq
1144-
* must also be limited to 32 bits.
1145-
*/
1146-
if (!mpext->dsn64)
1147-
data_fin_seq &= GENMASK_ULL(31, 0);
1138+
if (updated)
1139+
mptcp_schedule_work((struct sock *)msk);
11481140

1149-
mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64);
1150-
pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d",
1151-
data_fin_seq, mpext->dsn64);
1141+
return MAPPING_DATA_FIN;
11521142
}
11531143

1144+
data_fin_seq = mpext->data_seq + data_len - 1;
1145+
1146+
/* If mpext->data_seq is a 32-bit value, data_fin_seq must also
1147+
* be limited to 32 bits.
1148+
*/
1149+
if (!mpext->dsn64)
1150+
data_fin_seq &= GENMASK_ULL(31, 0);
1151+
1152+
mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64);
1153+
pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d",
1154+
data_fin_seq, mpext->dsn64);
1155+
11541156
/* Adjust for DATA_FIN using 1 byte of sequence space */
11551157
data_len--;
11561158
}

0 commit comments

Comments
 (0)