blob: c8ef5bd8fefb7618d161d953d1044f88cc4bc2a5 [file] [log] [blame]
Nicolas Costaf46c33b2014-05-15 10:02:00 -05001/*
2 **************************************************************************
Murat Sezginf4f7ab42018-10-12 17:01:46 -07003 * Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
Murat Sezgin3ab259d2015-06-11 14:15:35 -070016#include <linux/version.h>
Nicolas Costaf46c33b2014-05-15 10:02:00 -050017#include <linux/module.h>
Murat Sezginf2b94532014-12-05 14:53:53 -080018#include <linux/of.h>
Murat Sezgin908ecb32015-05-10 20:54:36 -070019#include <linux/debugfs.h>
Murat Sezgin3ab259d2015-06-11 14:15:35 -070020#include <linux/inet.h>
21#include <linux/etherdevice.h>
22#include <net/netfilter/nf_conntrack.h>
23#include <net/ip.h>
24#include <net/ipv6.h>
25/*
26 * Debug output levels
27 * 0 = OFF
28 * 1 = ASSERTS / ERRORS
29 * 2 = 1 + WARN
30 * 3 = 2 + INFO
31 * 4 = 3 + TRACE
32 */
33#define DEBUG_LEVEL ECM_INIT_DEBUG_LEVEL
Nicolas Costaf46c33b2014-05-15 10:02:00 -050034
Murat Sezgin3ab259d2015-06-11 14:15:35 -070035#include "ecm_types.h"
36#include "ecm_db_types.h"
37#include "ecm_state.h"
38#include "ecm_tracker.h"
39#include "ecm_classifier.h"
40#include "ecm_front_end_types.h"
Tushar Mathurd38cacd2015-07-28 12:19:10 +053041#include "ecm_db.h"
Murat Sezgin8d916a12015-03-18 15:56:50 -070042#include "ecm_front_end_ipv4.h"
Murat Sezgin3ab259d2015-06-11 14:15:35 -070043#ifdef ECM_IPV6_ENABLE
44#include "ecm_front_end_ipv6.h"
45#endif
Murat Sezgin5f138492015-06-11 15:18:27 -070046#include "ecm_front_end_common.h"
Murat Sezgindf98fce2016-08-26 17:56:39 -070047#include "ecm_conntrack_notifier.h"
Murat Sezgin8d916a12015-03-18 15:56:50 -070048
Xiaoping Fan86e55cb2016-08-24 17:27:32 -070049int front_end_selection;
50module_param(front_end_selection, int, 0);
51MODULE_PARM_DESC(front_end_selection, "Select front end for ECM");
52
Murat Sezgin908ecb32015-05-10 20:54:36 -070053struct dentry *ecm_dentry; /* Dentry object for top level ecm debugfs directory */
Nicolas Costaf46c33b2014-05-15 10:02:00 -050054
Murat Sezgin908ecb32015-05-10 20:54:36 -070055extern int ecm_db_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050056extern void ecm_db_connection_defunct_all(void);
57extern void ecm_db_exit(void);
58
Murat Sezgin908ecb32015-05-10 20:54:36 -070059extern int ecm_classifier_default_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050060extern void ecm_classifier_default_exit(void);
61
Murat Sezginf4f7ab42018-10-12 17:01:46 -070062#ifdef ECM_CLASSIFIER_MARK_ENABLE
63extern int ecm_classifier_mark_init(struct dentry *dentry);
64extern void ecm_classifier_mark_exit(void);
65#endif
66
Murat Sezginaaaafb42014-11-24 17:02:05 -080067#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070068extern int ecm_classifier_nl_rules_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050069extern void ecm_classifier_nl_rules_exit(void);
Murat Sezginaaaafb42014-11-24 17:02:05 -080070#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -050071
Hai Shalom81f4e202014-06-04 09:30:27 -070072#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070073extern int ecm_classifier_hyfi_rules_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050074extern void ecm_classifier_hyfi_rules_exit(void);
Hai Shalom81f4e202014-06-04 09:30:27 -070075#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -050076
77extern int ecm_interface_init(void);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050078extern void ecm_interface_exit(void);
79
Murat Sezginb3731e82014-11-26 12:20:59 -080080#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070081extern int ecm_classifier_dscp_init(struct dentry *dentry);
Gareth Williams4a02c9b2014-10-10 14:50:33 +010082extern void ecm_classifier_dscp_exit(void);
Murat Sezginb3731e82014-11-26 12:20:59 -080083#endif
Gareth Williams4a02c9b2014-10-10 14:50:33 +010084
Gareth Williamsf98d4192015-03-11 16:55:41 +000085#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070086extern int ecm_state_init(struct dentry *dentry);
Gareth Williamsf98d4192015-03-11 16:55:41 +000087extern void ecm_state_exit(void);
88#endif
89
Gareth Williamsdcda9b92015-05-13 10:08:15 +010090#ifdef ECM_CLASSIFIER_PCC_ENABLE
91extern int ecm_classifier_pcc_init(struct dentry *dentry);
92extern void ecm_classifier_pcc_exit(void);
93#endif
94
Nicolas Costaf46c33b2014-05-15 10:02:00 -050095/*
96 * ecm_init()
97 */
98static int __init ecm_init(void)
99{
100 int ret;
Murat Sezginf2b94532014-12-05 14:53:53 -0800101
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500102 printk(KERN_INFO "ECM init\n");
103
Murat Sezgin908ecb32015-05-10 20:54:36 -0700104 ecm_dentry = debugfs_create_dir("ecm", NULL);
105 if (!ecm_dentry) {
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700106 DEBUG_ERROR("Failed to create ecm directory in debugfs\n");
Murat Sezgin908ecb32015-05-10 20:54:36 -0700107 return -1;
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500108 }
109
Murat Sezgin908ecb32015-05-10 20:54:36 -0700110 ret = ecm_db_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500111 if (0 != ret) {
112 goto err_db;
113 }
114
Murat Sezgin908ecb32015-05-10 20:54:36 -0700115 ret = ecm_classifier_default_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500116 if (0 != ret) {
117 goto err_cls_default;
118 }
119
Murat Sezginaaaafb42014-11-24 17:02:05 -0800120#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700121 ret = ecm_classifier_nl_rules_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500122 if (0 != ret) {
123 goto err_cls_nl;
124 }
Murat Sezginaaaafb42014-11-24 17:02:05 -0800125#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500126
Hai Shalom81f4e202014-06-04 09:30:27 -0700127#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700128 ret = ecm_classifier_hyfi_rules_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500129 if (0 != ret) {
130 goto err_cls_hyfi;
131 }
Hai Shalom81f4e202014-06-04 09:30:27 -0700132#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500133
Murat Sezginb3731e82014-11-26 12:20:59 -0800134#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700135 ret = ecm_classifier_dscp_init(ecm_dentry);
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100136 if (0 != ret) {
137 goto err_cls_dscp;
138 }
Murat Sezginb3731e82014-11-26 12:20:59 -0800139#endif
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100140
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100141#ifdef ECM_CLASSIFIER_PCC_ENABLE
142 ret = ecm_classifier_pcc_init(ecm_dentry);
143 if (0 != ret) {
144 goto err_cls_pcc;
145 }
146#endif
Murat Sezginf4f7ab42018-10-12 17:01:46 -0700147#ifdef ECM_CLASSIFIER_MARK_ENABLE
148 ret = ecm_classifier_mark_init(ecm_dentry);
149 if (0 != ret) {
150 goto err_cls_mark;
151 }
152#endif
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100153
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500154 ret = ecm_interface_init();
155 if (0 != ret) {
156 goto err_iface;
157 }
158
Murat Sezginb3731e82014-11-26 12:20:59 -0800159#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700160 ret = ecm_front_end_bond_notifier_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500161 if (0 != ret) {
162 goto err_bond;
163 }
Murat Sezginb3731e82014-11-26 12:20:59 -0800164#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500165
Murat Sezgin908ecb32015-05-10 20:54:36 -0700166 ret = ecm_front_end_ipv4_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500167 if (0 != ret) {
168 goto err_fe_ipv4;
169 }
170
Gareth Williams8ac34292015-03-17 14:06:58 +0000171#ifdef ECM_IPV6_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700172 ret = ecm_front_end_ipv6_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500173 if (0 != ret) {
174 goto err_fe_ipv6;
175 }
Murat Sezgin49465a42014-11-24 15:37:48 -0800176#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500177
Murat Sezgindf98fce2016-08-26 17:56:39 -0700178 ret = ecm_conntrack_notifier_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500179 if (0 != ret) {
180 goto err_ct;
181 }
182
Gareth Williamsf98d4192015-03-11 16:55:41 +0000183#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700184 ret = ecm_state_init(ecm_dentry);
Gareth Williamsf98d4192015-03-11 16:55:41 +0000185 if (0 != ret) {
186 goto err_state;
187 }
188#endif
189
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500190 printk(KERN_INFO "ECM init complete\n");
191 return 0;
192
Gareth Williamsf98d4192015-03-11 16:55:41 +0000193#ifdef ECM_STATE_OUTPUT_ENABLE
194err_state:
Murat Sezgindf98fce2016-08-26 17:56:39 -0700195 ecm_conntrack_notifier_exit();
Gareth Williamsf98d4192015-03-11 16:55:41 +0000196#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500197err_ct:
Gareth Williams8ac34292015-03-17 14:06:58 +0000198#ifdef ECM_IPV6_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500199 ecm_front_end_ipv6_exit();
200err_fe_ipv6:
Murat Sezgin49465a42014-11-24 15:37:48 -0800201#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500202 ecm_front_end_ipv4_exit();
203err_fe_ipv4:
Murat Sezginb3731e82014-11-26 12:20:59 -0800204#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700205 ecm_front_end_bond_notifier_exit();
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500206err_bond:
Murat Sezginb3731e82014-11-26 12:20:59 -0800207#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500208 ecm_interface_exit();
209err_iface:
Murat Sezginf4f7ab42018-10-12 17:01:46 -0700210#ifdef ECM_CLASSIFIER_MARK_ENABLE
211 ecm_classifier_mark_exit();
212err_cls_mark:
213#endif
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100214#ifdef ECM_CLASSIFIER_PCC_ENABLE
215 ecm_classifier_pcc_exit();
216err_cls_pcc:
217#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800218#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100219 ecm_classifier_dscp_exit();
220err_cls_dscp:
Murat Sezginb3731e82014-11-26 12:20:59 -0800221#endif
Hai Shalom81f4e202014-06-04 09:30:27 -0700222#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500223 ecm_classifier_hyfi_rules_exit();
224err_cls_hyfi:
Hai Shalom81f4e202014-06-04 09:30:27 -0700225#endif
Murat Sezginaaaafb42014-11-24 17:02:05 -0800226#ifdef ECM_CLASSIFIER_NL_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500227 ecm_classifier_nl_rules_exit();
228err_cls_nl:
Murat Sezginaaaafb42014-11-24 17:02:05 -0800229#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500230 ecm_classifier_default_exit();
231err_cls_default:
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500232 ecm_db_exit();
233err_db:
Murat Sezgin908ecb32015-05-10 20:54:36 -0700234 debugfs_remove_recursive(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500235
236 printk(KERN_INFO "ECM init failed: %d\n", ret);
237 return ret;
238}
239
240/*
241 * ecm_exit()
242 */
243static void __exit ecm_exit(void)
244{
245 printk(KERN_INFO "ECM exit\n");
246
247 /* call stop on anything that requires a prepare-to-exit signal */
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700248 DEBUG_INFO("stop conntrack notifier\n");
Murat Sezgindf98fce2016-08-26 17:56:39 -0700249 ecm_conntrack_notifier_stop(1);
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700250 DEBUG_INFO("stop front_end_ipv4\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500251 ecm_front_end_ipv4_stop(1);
Gareth Williams8ac34292015-03-17 14:06:58 +0000252#ifdef ECM_IPV6_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700253 DEBUG_INFO("stop front_end_ipv6\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500254 ecm_front_end_ipv6_stop(1);
Murat Sezgin49465a42014-11-24 15:37:48 -0800255#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800256#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700257 DEBUG_INFO("stop bond notifier\n");
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700258 ecm_front_end_bond_notifier_stop(1);
Murat Sezginb3731e82014-11-26 12:20:59 -0800259#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700260 DEBUG_INFO("defunct all db connections\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500261 ecm_db_connection_defunct_all();
262
263 /* now call exit on each module */
Gareth Williamsf98d4192015-03-11 16:55:41 +0000264#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700265 DEBUG_INFO("stop state\n");
Gareth Williamsf98d4192015-03-11 16:55:41 +0000266 ecm_state_exit();
267#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700268 DEBUG_INFO("exit conntrack notifier\n");
Murat Sezgindf98fce2016-08-26 17:56:39 -0700269 ecm_conntrack_notifier_exit();
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700270 DEBUG_INFO("exit front_end_ipv4\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500271 ecm_front_end_ipv4_exit();
Gareth Williams8ac34292015-03-17 14:06:58 +0000272#ifdef ECM_IPV6_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700273 DEBUG_INFO("exit front_end_ipv6\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500274 ecm_front_end_ipv6_exit();
Murat Sezgin49465a42014-11-24 15:37:48 -0800275#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800276#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700277 DEBUG_INFO("exit bond notifier\n");
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700278 ecm_front_end_bond_notifier_exit();
Murat Sezginb3731e82014-11-26 12:20:59 -0800279#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700280 DEBUG_INFO("exit interface\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500281 ecm_interface_exit();
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100282
283#ifdef ECM_CLASSIFIER_PCC_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700284 DEBUG_INFO("exit pcc classifier\n");
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100285 ecm_classifier_pcc_exit();
286#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800287#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700288 DEBUG_INFO("exit dscp classifier\n");
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100289 ecm_classifier_dscp_exit();
Murat Sezginb3731e82014-11-26 12:20:59 -0800290#endif
Hai Shalom81f4e202014-06-04 09:30:27 -0700291#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700292 DEBUG_INFO("exit hyfi classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500293 ecm_classifier_hyfi_rules_exit();
Hai Shalom81f4e202014-06-04 09:30:27 -0700294#endif
Murat Sezginaaaafb42014-11-24 17:02:05 -0800295#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700296 DEBUG_INFO("exit nl classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500297 ecm_classifier_nl_rules_exit();
Murat Sezginaaaafb42014-11-24 17:02:05 -0800298#endif
Murat Sezginf4f7ab42018-10-12 17:01:46 -0700299#ifdef ECM_CLASSIFIER_MARK_ENABLE
300 DEBUG_INFO("exit mark classifier\n");
301 ecm_classifier_mark_exit();
302#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700303 DEBUG_INFO("exit default classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500304 ecm_classifier_default_exit();
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700305 DEBUG_INFO("exit db\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500306 ecm_db_exit();
Murat Sezgin908ecb32015-05-10 20:54:36 -0700307
308 if (ecm_dentry != NULL) {
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700309 DEBUG_INFO("remove ecm debugfs\n");
Murat Sezgin908ecb32015-05-10 20:54:36 -0700310 debugfs_remove_recursive(ecm_dentry);
311 }
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500312
313 printk(KERN_INFO "ECM exit complete\n");
314}
315
316module_init(ecm_init)
317module_exit(ecm_exit)
318
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500319MODULE_DESCRIPTION("ECM Core");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500320MODULE_LICENSE("Dual BSD/GPL");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500321