Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Multipath TCP
0003  *
0004  * Copyright (c) 2019, Tessares SA.
0005  */
0006 
0007 #ifdef CONFIG_SYSCTL
0008 #include <linux/sysctl.h>
0009 #endif
0010 
0011 #include <net/net_namespace.h>
0012 #include <net/netns/generic.h>
0013 
0014 #include "protocol.h"
0015 
0016 #define MPTCP_SYSCTL_PATH "net/mptcp"
0017 
0018 static int mptcp_pernet_id;
0019 
0020 #ifdef CONFIG_SYSCTL
0021 static int mptcp_pm_type_max = __MPTCP_PM_TYPE_MAX;
0022 #endif
0023 
0024 struct mptcp_pernet {
0025 #ifdef CONFIG_SYSCTL
0026     struct ctl_table_header *ctl_table_hdr;
0027 #endif
0028 
0029     unsigned int add_addr_timeout;
0030     unsigned int stale_loss_cnt;
0031     u8 mptcp_enabled;
0032     u8 checksum_enabled;
0033     u8 allow_join_initial_addr_port;
0034     u8 pm_type;
0035 };
0036 
0037 static struct mptcp_pernet *mptcp_get_pernet(const struct net *net)
0038 {
0039     return net_generic(net, mptcp_pernet_id);
0040 }
0041 
0042 int mptcp_is_enabled(const struct net *net)
0043 {
0044     return mptcp_get_pernet(net)->mptcp_enabled;
0045 }
0046 
0047 unsigned int mptcp_get_add_addr_timeout(const struct net *net)
0048 {
0049     return mptcp_get_pernet(net)->add_addr_timeout;
0050 }
0051 
0052 int mptcp_is_checksum_enabled(const struct net *net)
0053 {
0054     return mptcp_get_pernet(net)->checksum_enabled;
0055 }
0056 
0057 int mptcp_allow_join_id0(const struct net *net)
0058 {
0059     return mptcp_get_pernet(net)->allow_join_initial_addr_port;
0060 }
0061 
0062 unsigned int mptcp_stale_loss_cnt(const struct net *net)
0063 {
0064     return mptcp_get_pernet(net)->stale_loss_cnt;
0065 }
0066 
0067 int mptcp_get_pm_type(const struct net *net)
0068 {
0069     return mptcp_get_pernet(net)->pm_type;
0070 }
0071 
0072 static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
0073 {
0074     pernet->mptcp_enabled = 1;
0075     pernet->add_addr_timeout = TCP_RTO_MAX;
0076     pernet->checksum_enabled = 0;
0077     pernet->allow_join_initial_addr_port = 1;
0078     pernet->stale_loss_cnt = 4;
0079     pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
0080 }
0081 
0082 #ifdef CONFIG_SYSCTL
0083 static struct ctl_table mptcp_sysctl_table[] = {
0084     {
0085         .procname = "enabled",
0086         .maxlen = sizeof(u8),
0087         .mode = 0644,
0088         /* users with CAP_NET_ADMIN or root (not and) can change this
0089          * value, same as other sysctl or the 'net' tree.
0090          */
0091         .proc_handler = proc_dou8vec_minmax,
0092         .extra1       = SYSCTL_ZERO,
0093         .extra2       = SYSCTL_ONE
0094     },
0095     {
0096         .procname = "add_addr_timeout",
0097         .maxlen = sizeof(unsigned int),
0098         .mode = 0644,
0099         .proc_handler = proc_dointvec_jiffies,
0100     },
0101     {
0102         .procname = "checksum_enabled",
0103         .maxlen = sizeof(u8),
0104         .mode = 0644,
0105         .proc_handler = proc_dou8vec_minmax,
0106         .extra1       = SYSCTL_ZERO,
0107         .extra2       = SYSCTL_ONE
0108     },
0109     {
0110         .procname = "allow_join_initial_addr_port",
0111         .maxlen = sizeof(u8),
0112         .mode = 0644,
0113         .proc_handler = proc_dou8vec_minmax,
0114         .extra1       = SYSCTL_ZERO,
0115         .extra2       = SYSCTL_ONE
0116     },
0117     {
0118         .procname = "stale_loss_cnt",
0119         .maxlen = sizeof(unsigned int),
0120         .mode = 0644,
0121         .proc_handler = proc_douintvec_minmax,
0122     },
0123     {
0124         .procname = "pm_type",
0125         .maxlen = sizeof(u8),
0126         .mode = 0644,
0127         .proc_handler = proc_dou8vec_minmax,
0128         .extra1       = SYSCTL_ZERO,
0129         .extra2       = &mptcp_pm_type_max
0130     },
0131     {}
0132 };
0133 
0134 static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
0135 {
0136     struct ctl_table_header *hdr;
0137     struct ctl_table *table;
0138 
0139     table = mptcp_sysctl_table;
0140     if (!net_eq(net, &init_net)) {
0141         table = kmemdup(table, sizeof(mptcp_sysctl_table), GFP_KERNEL);
0142         if (!table)
0143             goto err_alloc;
0144     }
0145 
0146     table[0].data = &pernet->mptcp_enabled;
0147     table[1].data = &pernet->add_addr_timeout;
0148     table[2].data = &pernet->checksum_enabled;
0149     table[3].data = &pernet->allow_join_initial_addr_port;
0150     table[4].data = &pernet->stale_loss_cnt;
0151     table[5].data = &pernet->pm_type;
0152 
0153     hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
0154     if (!hdr)
0155         goto err_reg;
0156 
0157     pernet->ctl_table_hdr = hdr;
0158 
0159     return 0;
0160 
0161 err_reg:
0162     if (!net_eq(net, &init_net))
0163         kfree(table);
0164 err_alloc:
0165     return -ENOMEM;
0166 }
0167 
0168 static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
0169 {
0170     struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
0171 
0172     unregister_net_sysctl_table(pernet->ctl_table_hdr);
0173 
0174     kfree(table);
0175 }
0176 
0177 #else
0178 
0179 static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
0180 {
0181     return 0;
0182 }
0183 
0184 static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) {}
0185 
0186 #endif /* CONFIG_SYSCTL */
0187 
0188 static int __net_init mptcp_net_init(struct net *net)
0189 {
0190     struct mptcp_pernet *pernet = mptcp_get_pernet(net);
0191 
0192     mptcp_pernet_set_defaults(pernet);
0193 
0194     return mptcp_pernet_new_table(net, pernet);
0195 }
0196 
0197 /* Note: the callback will only be called per extra netns */
0198 static void __net_exit mptcp_net_exit(struct net *net)
0199 {
0200     struct mptcp_pernet *pernet = mptcp_get_pernet(net);
0201 
0202     mptcp_pernet_del_table(pernet);
0203 }
0204 
0205 static struct pernet_operations mptcp_pernet_ops = {
0206     .init = mptcp_net_init,
0207     .exit = mptcp_net_exit,
0208     .id = &mptcp_pernet_id,
0209     .size = sizeof(struct mptcp_pernet),
0210 };
0211 
0212 void __init mptcp_init(void)
0213 {
0214     mptcp_join_cookie_init();
0215     mptcp_proto_init();
0216 
0217     if (register_pernet_subsys(&mptcp_pernet_ops) < 0)
0218         panic("Failed to register MPTCP pernet subsystem.\n");
0219 }
0220 
0221 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
0222 int __init mptcpv6_init(void)
0223 {
0224     int err;
0225 
0226     err = mptcp_proto_v6_init();
0227 
0228     return err;
0229 }
0230 #endif