ctrl.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Multipath TCP
  3. *
  4. * Copyright (c) 2019, Tessares SA.
  5. */
  6. #ifdef CONFIG_SYSCTL
  7. #include <linux/sysctl.h>
  8. #endif
  9. #include <net/net_namespace.h>
  10. #include <net/netns/generic.h>
  11. #include "protocol.h"
  12. #define MPTCP_SYSCTL_PATH "net/mptcp"
  13. static int mptcp_pernet_id;
  14. #ifdef CONFIG_SYSCTL
  15. static int mptcp_pm_type_max = __MPTCP_PM_TYPE_MAX;
  16. #endif
  17. struct mptcp_pernet {
  18. #ifdef CONFIG_SYSCTL
  19. struct ctl_table_header *ctl_table_hdr;
  20. #endif
  21. unsigned int add_addr_timeout;
  22. unsigned int stale_loss_cnt;
  23. u8 mptcp_enabled;
  24. u8 checksum_enabled;
  25. u8 allow_join_initial_addr_port;
  26. u8 pm_type;
  27. };
  28. static struct mptcp_pernet *mptcp_get_pernet(const struct net *net)
  29. {
  30. return net_generic(net, mptcp_pernet_id);
  31. }
  32. int mptcp_is_enabled(const struct net *net)
  33. {
  34. return mptcp_get_pernet(net)->mptcp_enabled;
  35. }
  36. unsigned int mptcp_get_add_addr_timeout(const struct net *net)
  37. {
  38. return mptcp_get_pernet(net)->add_addr_timeout;
  39. }
  40. int mptcp_is_checksum_enabled(const struct net *net)
  41. {
  42. return mptcp_get_pernet(net)->checksum_enabled;
  43. }
  44. int mptcp_allow_join_id0(const struct net *net)
  45. {
  46. return mptcp_get_pernet(net)->allow_join_initial_addr_port;
  47. }
  48. unsigned int mptcp_stale_loss_cnt(const struct net *net)
  49. {
  50. return mptcp_get_pernet(net)->stale_loss_cnt;
  51. }
  52. int mptcp_get_pm_type(const struct net *net)
  53. {
  54. return mptcp_get_pernet(net)->pm_type;
  55. }
  56. static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
  57. {
  58. pernet->mptcp_enabled = 1;
  59. pernet->add_addr_timeout = TCP_RTO_MAX;
  60. pernet->checksum_enabled = 0;
  61. pernet->allow_join_initial_addr_port = 1;
  62. pernet->stale_loss_cnt = 4;
  63. pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
  64. }
  65. #ifdef CONFIG_SYSCTL
  66. static struct ctl_table mptcp_sysctl_table[] = {
  67. {
  68. .procname = "enabled",
  69. .maxlen = sizeof(u8),
  70. .mode = 0644,
  71. /* users with CAP_NET_ADMIN or root (not and) can change this
  72. * value, same as other sysctl or the 'net' tree.
  73. */
  74. .proc_handler = proc_dou8vec_minmax,
  75. .extra1 = SYSCTL_ZERO,
  76. .extra2 = SYSCTL_ONE
  77. },
  78. {
  79. .procname = "add_addr_timeout",
  80. .maxlen = sizeof(unsigned int),
  81. .mode = 0644,
  82. .proc_handler = proc_dointvec_jiffies,
  83. },
  84. {
  85. .procname = "checksum_enabled",
  86. .maxlen = sizeof(u8),
  87. .mode = 0644,
  88. .proc_handler = proc_dou8vec_minmax,
  89. .extra1 = SYSCTL_ZERO,
  90. .extra2 = SYSCTL_ONE
  91. },
  92. {
  93. .procname = "allow_join_initial_addr_port",
  94. .maxlen = sizeof(u8),
  95. .mode = 0644,
  96. .proc_handler = proc_dou8vec_minmax,
  97. .extra1 = SYSCTL_ZERO,
  98. .extra2 = SYSCTL_ONE
  99. },
  100. {
  101. .procname = "stale_loss_cnt",
  102. .maxlen = sizeof(unsigned int),
  103. .mode = 0644,
  104. .proc_handler = proc_douintvec_minmax,
  105. },
  106. {
  107. .procname = "pm_type",
  108. .maxlen = sizeof(u8),
  109. .mode = 0644,
  110. .proc_handler = proc_dou8vec_minmax,
  111. .extra1 = SYSCTL_ZERO,
  112. .extra2 = &mptcp_pm_type_max
  113. },
  114. {}
  115. };
  116. static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
  117. {
  118. struct ctl_table_header *hdr;
  119. struct ctl_table *table;
  120. table = mptcp_sysctl_table;
  121. if (!net_eq(net, &init_net)) {
  122. table = kmemdup(table, sizeof(mptcp_sysctl_table), GFP_KERNEL);
  123. if (!table)
  124. goto err_alloc;
  125. }
  126. table[0].data = &pernet->mptcp_enabled;
  127. table[1].data = &pernet->add_addr_timeout;
  128. table[2].data = &pernet->checksum_enabled;
  129. table[3].data = &pernet->allow_join_initial_addr_port;
  130. table[4].data = &pernet->stale_loss_cnt;
  131. table[5].data = &pernet->pm_type;
  132. hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
  133. if (!hdr)
  134. goto err_reg;
  135. pernet->ctl_table_hdr = hdr;
  136. return 0;
  137. err_reg:
  138. if (!net_eq(net, &init_net))
  139. kfree(table);
  140. err_alloc:
  141. return -ENOMEM;
  142. }
  143. static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
  144. {
  145. struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
  146. unregister_net_sysctl_table(pernet->ctl_table_hdr);
  147. kfree(table);
  148. }
  149. #else
  150. static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
  151. {
  152. return 0;
  153. }
  154. static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) {}
  155. #endif /* CONFIG_SYSCTL */
  156. static int __net_init mptcp_net_init(struct net *net)
  157. {
  158. struct mptcp_pernet *pernet = mptcp_get_pernet(net);
  159. mptcp_pernet_set_defaults(pernet);
  160. return mptcp_pernet_new_table(net, pernet);
  161. }
  162. /* Note: the callback will only be called per extra netns */
  163. static void __net_exit mptcp_net_exit(struct net *net)
  164. {
  165. struct mptcp_pernet *pernet = mptcp_get_pernet(net);
  166. mptcp_pernet_del_table(pernet);
  167. }
  168. static struct pernet_operations mptcp_pernet_ops = {
  169. .init = mptcp_net_init,
  170. .exit = mptcp_net_exit,
  171. .id = &mptcp_pernet_id,
  172. .size = sizeof(struct mptcp_pernet),
  173. };
  174. void __init mptcp_init(void)
  175. {
  176. mptcp_join_cookie_init();
  177. mptcp_proto_init();
  178. if (register_pernet_subsys(&mptcp_pernet_ops) < 0)
  179. panic("Failed to register MPTCP pernet subsystem.\n");
  180. }
  181. #if IS_ENABLED(CONFIG_MPTCP_IPV6)
  182. int __init mptcpv6_init(void)
  183. {
  184. int err;
  185. err = mptcp_proto_v6_init();
  186. return err;
  187. }
  188. #endif