2020-01-22 03:56:28 +03:00
// SPDX-License-Identifier: GPL-2.0
/* Multipath TCP
*
* Copyright ( c ) 2019 , Tessares SA .
*/
2021-05-28 02:54:29 +03:00
# ifdef CONFIG_SYSCTL
2020-01-22 03:56:28 +03:00
# include <linux/sysctl.h>
2021-05-28 02:54:29 +03:00
# endif
2020-01-22 03:56:28 +03:00
# include <net/net_namespace.h>
# include <net/netns/generic.h>
# include "protocol.h"
# define MPTCP_SYSCTL_PATH "net / mptcp"
static int mptcp_pernet_id ;
2022-04-28 01:50:01 +03:00
# ifdef CONFIG_SYSCTL
static int mptcp_pm_type_max = __MPTCP_PM_TYPE_MAX ;
# endif
2020-01-22 03:56:28 +03:00
struct mptcp_pernet {
2021-05-28 02:54:29 +03:00
# ifdef CONFIG_SYSCTL
2020-01-22 03:56:28 +03:00
struct ctl_table_header * ctl_table_hdr ;
2021-05-28 02:54:29 +03:00
# endif
2020-01-22 03:56:28 +03:00
2020-11-03 22:05:07 +03:00
unsigned int add_addr_timeout ;
2021-08-14 01:15:45 +03:00
unsigned int stale_loss_cnt ;
2021-08-14 01:15:44 +03:00
u8 mptcp_enabled ;
2021-06-18 02:46:19 +03:00
u8 checksum_enabled ;
2021-06-22 22:25:18 +03:00
u8 allow_join_initial_addr_port ;
2022-04-28 01:50:01 +03:00
u8 pm_type ;
2023-08-22 01:25:15 +03:00
char scheduler [ MPTCP_SCHED_NAME_MAX ] ;
2020-01-22 03:56:28 +03:00
} ;
2021-08-14 01:15:44 +03:00
static struct mptcp_pernet * mptcp_get_pernet ( const struct net * net )
2020-01-22 03:56:28 +03:00
{
return net_generic ( net , mptcp_pernet_id ) ;
}
2021-08-14 01:15:44 +03:00
int mptcp_is_enabled ( const struct net * net )
2020-01-22 03:56:28 +03:00
{
return mptcp_get_pernet ( net ) - > mptcp_enabled ;
}
2021-08-14 01:15:44 +03:00
unsigned int mptcp_get_add_addr_timeout ( const struct net * net )
2020-11-03 22:05:07 +03:00
{
return mptcp_get_pernet ( net ) - > add_addr_timeout ;
}
2021-08-14 01:15:44 +03:00
int mptcp_is_checksum_enabled ( const struct net * net )
2021-06-18 02:46:19 +03:00
{
return mptcp_get_pernet ( net ) - > checksum_enabled ;
}
2021-08-14 01:15:44 +03:00
int mptcp_allow_join_id0 ( const struct net * net )
2021-06-22 22:25:18 +03:00
{
return mptcp_get_pernet ( net ) - > allow_join_initial_addr_port ;
}
2021-08-14 01:15:45 +03:00
unsigned int mptcp_stale_loss_cnt ( const struct net * net )
{
return mptcp_get_pernet ( net ) - > stale_loss_cnt ;
}
2022-04-28 01:50:01 +03:00
int mptcp_get_pm_type ( const struct net * net )
{
return mptcp_get_pernet ( net ) - > pm_type ;
}
2023-08-22 01:25:15 +03:00
const char * mptcp_get_scheduler ( const struct net * net )
{
return mptcp_get_pernet ( net ) - > scheduler ;
}
2021-05-28 02:54:29 +03:00
static void mptcp_pernet_set_defaults ( struct mptcp_pernet * pernet )
{
pernet - > mptcp_enabled = 1 ;
pernet - > add_addr_timeout = TCP_RTO_MAX ;
2021-06-18 02:46:19 +03:00
pernet - > checksum_enabled = 0 ;
2021-06-22 22:25:18 +03:00
pernet - > allow_join_initial_addr_port = 1 ;
2021-08-14 01:15:45 +03:00
pernet - > stale_loss_cnt = 4 ;
2022-04-28 01:50:01 +03:00
pernet - > pm_type = MPTCP_PM_TYPE_KERNEL ;
2023-08-22 01:25:15 +03:00
strcpy ( pernet - > scheduler , " default " ) ;
2021-05-28 02:54:29 +03:00
}
# ifdef CONFIG_SYSCTL
2020-01-22 03:56:28 +03:00
static struct ctl_table mptcp_sysctl_table [ ] = {
{
. procname = " enabled " ,
2021-05-28 02:54:30 +03:00
. maxlen = sizeof ( u8 ) ,
2020-01-22 03:56:28 +03:00
. mode = 0644 ,
/* users with CAP_NET_ADMIN or root (not and) can change this
* value , same as other sysctl or the ' net ' tree .
*/
2021-05-28 02:54:30 +03:00
. proc_handler = proc_dou8vec_minmax ,
. extra1 = SYSCTL_ZERO ,
. extra2 = SYSCTL_ONE
2020-01-22 03:56:28 +03:00
} ,
2020-11-03 22:05:07 +03:00
{
. procname = " add_addr_timeout " ,
. maxlen = sizeof ( unsigned int ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec_jiffies ,
} ,
2021-06-18 02:46:19 +03:00
{
. procname = " checksum_enabled " ,
. maxlen = sizeof ( u8 ) ,
. mode = 0644 ,
. proc_handler = proc_dou8vec_minmax ,
. extra1 = SYSCTL_ZERO ,
. extra2 = SYSCTL_ONE
} ,
2021-06-22 22:25:18 +03:00
{
. procname = " allow_join_initial_addr_port " ,
. maxlen = sizeof ( u8 ) ,
. mode = 0644 ,
. proc_handler = proc_dou8vec_minmax ,
. extra1 = SYSCTL_ZERO ,
. extra2 = SYSCTL_ONE
} ,
2021-08-14 01:15:45 +03:00
{
. procname = " stale_loss_cnt " ,
. maxlen = sizeof ( unsigned int ) ,
. mode = 0644 ,
. proc_handler = proc_douintvec_minmax ,
} ,
2022-04-28 01:50:01 +03:00
{
. procname = " pm_type " ,
. maxlen = sizeof ( u8 ) ,
. mode = 0644 ,
. proc_handler = proc_dou8vec_minmax ,
. extra1 = SYSCTL_ZERO ,
. extra2 = & mptcp_pm_type_max
} ,
2023-08-22 01:25:15 +03:00
{
. procname = " scheduler " ,
. maxlen = MPTCP_SCHED_NAME_MAX ,
. mode = 0644 ,
. proc_handler = proc_dostring ,
} ,
2020-01-22 03:56:28 +03:00
{ }
} ;
static int mptcp_pernet_new_table ( struct net * net , struct mptcp_pernet * pernet )
{
struct ctl_table_header * hdr ;
struct ctl_table * table ;
table = mptcp_sysctl_table ;
if ( ! net_eq ( net , & init_net ) ) {
table = kmemdup ( table , sizeof ( mptcp_sysctl_table ) , GFP_KERNEL ) ;
if ( ! table )
goto err_alloc ;
}
table [ 0 ] . data = & pernet - > mptcp_enabled ;
2020-11-03 22:05:07 +03:00
table [ 1 ] . data = & pernet - > add_addr_timeout ;
2021-06-18 02:46:19 +03:00
table [ 2 ] . data = & pernet - > checksum_enabled ;
2021-06-22 22:25:18 +03:00
table [ 3 ] . data = & pernet - > allow_join_initial_addr_port ;
2021-08-14 01:15:45 +03:00
table [ 4 ] . data = & pernet - > stale_loss_cnt ;
2022-04-28 01:50:01 +03:00
table [ 5 ] . data = & pernet - > pm_type ;
2023-08-22 01:25:15 +03:00
table [ 6 ] . data = & pernet - > scheduler ;
2020-01-22 03:56:28 +03:00
2023-08-09 13:50:03 +03:00
hdr = register_net_sysctl_sz ( net , MPTCP_SYSCTL_PATH , table ,
ARRAY_SIZE ( mptcp_sysctl_table ) ) ;
2020-01-22 03:56:28 +03:00
if ( ! hdr )
goto err_reg ;
pernet - > ctl_table_hdr = hdr ;
return 0 ;
err_reg :
if ( ! net_eq ( net , & init_net ) )
kfree ( table ) ;
err_alloc :
return - ENOMEM ;
}
static void mptcp_pernet_del_table ( struct mptcp_pernet * pernet )
{
struct ctl_table * table = pernet - > ctl_table_hdr - > ctl_table_arg ;
unregister_net_sysctl_table ( pernet - > ctl_table_hdr ) ;
kfree ( table ) ;
}
2021-05-28 02:54:29 +03:00
# else
static int mptcp_pernet_new_table ( struct net * net , struct mptcp_pernet * pernet )
{
return 0 ;
}
static void mptcp_pernet_del_table ( struct mptcp_pernet * pernet ) { }
# endif /* CONFIG_SYSCTL */
2020-01-22 03:56:28 +03:00
static int __net_init mptcp_net_init ( struct net * net )
{
struct mptcp_pernet * pernet = mptcp_get_pernet ( net ) ;
mptcp_pernet_set_defaults ( pernet ) ;
return mptcp_pernet_new_table ( net , pernet ) ;
}
/* Note: the callback will only be called per extra netns */
static void __net_exit mptcp_net_exit ( struct net * net )
{
struct mptcp_pernet * pernet = mptcp_get_pernet ( net ) ;
mptcp_pernet_del_table ( pernet ) ;
}
static struct pernet_operations mptcp_pernet_ops = {
. init = mptcp_net_init ,
. exit = mptcp_net_exit ,
. id = & mptcp_pernet_id ,
. size = sizeof ( struct mptcp_pernet ) ,
} ;
void __init mptcp_init ( void )
{
2020-07-30 22:25:56 +03:00
mptcp_join_cookie_init ( ) ;
2020-01-22 03:56:28 +03:00
mptcp_proto_init ( ) ;
if ( register_pernet_subsys ( & mptcp_pernet_ops ) < 0 )
panic ( " Failed to register MPTCP pernet subsystem. \n " ) ;
}
# if IS_ENABLED(CONFIG_MPTCP_IPV6)
int __init mptcpv6_init ( void )
{
int err ;
err = mptcp_proto_v6_init ( ) ;
return err ;
}
# endif