blob: 68ee5568b5406677b4667c89414c5a423e51cf3c [file] [log] [blame]
Nicolas Costaf46c33b2014-05-15 10:02:00 -05001/*
2 **************************************************************************
Murat Sezgindf98fce2016-08-26 17:56:39 -07003 * Copyright (c) 2014-2016, 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 Sezginaaaafb42014-11-24 17:02:05 -080062#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070063extern int ecm_classifier_nl_rules_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050064extern void ecm_classifier_nl_rules_exit(void);
Murat Sezginaaaafb42014-11-24 17:02:05 -080065#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -050066
Hai Shalom81f4e202014-06-04 09:30:27 -070067#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070068extern int ecm_classifier_hyfi_rules_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050069extern void ecm_classifier_hyfi_rules_exit(void);
Hai Shalom81f4e202014-06-04 09:30:27 -070070#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -050071
72extern int ecm_interface_init(void);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050073extern void ecm_interface_exit(void);
74
Murat Sezginb3731e82014-11-26 12:20:59 -080075#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070076extern int ecm_classifier_dscp_init(struct dentry *dentry);
Gareth Williams4a02c9b2014-10-10 14:50:33 +010077extern void ecm_classifier_dscp_exit(void);
Murat Sezginb3731e82014-11-26 12:20:59 -080078#endif
Gareth Williams4a02c9b2014-10-10 14:50:33 +010079
Gareth Williamsf98d4192015-03-11 16:55:41 +000080#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070081extern int ecm_state_init(struct dentry *dentry);
Gareth Williamsf98d4192015-03-11 16:55:41 +000082extern void ecm_state_exit(void);
83#endif
84
Gareth Williamsdcda9b92015-05-13 10:08:15 +010085#ifdef ECM_CLASSIFIER_PCC_ENABLE
86extern int ecm_classifier_pcc_init(struct dentry *dentry);
87extern void ecm_classifier_pcc_exit(void);
88#endif
89
Nicolas Costaf46c33b2014-05-15 10:02:00 -050090/*
91 * ecm_init()
92 */
93static int __init ecm_init(void)
94{
95 int ret;
Murat Sezginf2b94532014-12-05 14:53:53 -080096
Nicolas Costaf46c33b2014-05-15 10:02:00 -050097 printk(KERN_INFO "ECM init\n");
98
Murat Sezgin908ecb32015-05-10 20:54:36 -070099 ecm_dentry = debugfs_create_dir("ecm", NULL);
100 if (!ecm_dentry) {
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700101 DEBUG_ERROR("Failed to create ecm directory in debugfs\n");
Murat Sezgin908ecb32015-05-10 20:54:36 -0700102 return -1;
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500103 }
104
Murat Sezgin908ecb32015-05-10 20:54:36 -0700105 ret = ecm_db_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500106 if (0 != ret) {
107 goto err_db;
108 }
109
Murat Sezgin908ecb32015-05-10 20:54:36 -0700110 ret = ecm_classifier_default_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500111 if (0 != ret) {
112 goto err_cls_default;
113 }
114
Murat Sezginaaaafb42014-11-24 17:02:05 -0800115#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700116 ret = ecm_classifier_nl_rules_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500117 if (0 != ret) {
118 goto err_cls_nl;
119 }
Murat Sezginaaaafb42014-11-24 17:02:05 -0800120#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500121
Hai Shalom81f4e202014-06-04 09:30:27 -0700122#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700123 ret = ecm_classifier_hyfi_rules_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500124 if (0 != ret) {
125 goto err_cls_hyfi;
126 }
Hai Shalom81f4e202014-06-04 09:30:27 -0700127#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500128
Murat Sezginb3731e82014-11-26 12:20:59 -0800129#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700130 ret = ecm_classifier_dscp_init(ecm_dentry);
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100131 if (0 != ret) {
132 goto err_cls_dscp;
133 }
Murat Sezginb3731e82014-11-26 12:20:59 -0800134#endif
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100135
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100136#ifdef ECM_CLASSIFIER_PCC_ENABLE
137 ret = ecm_classifier_pcc_init(ecm_dentry);
138 if (0 != ret) {
139 goto err_cls_pcc;
140 }
141#endif
142
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500143 ret = ecm_interface_init();
144 if (0 != ret) {
145 goto err_iface;
146 }
147
Murat Sezginb3731e82014-11-26 12:20:59 -0800148#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700149 ret = ecm_front_end_bond_notifier_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500150 if (0 != ret) {
151 goto err_bond;
152 }
Murat Sezginb3731e82014-11-26 12:20:59 -0800153#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500154
Murat Sezgin908ecb32015-05-10 20:54:36 -0700155 ret = ecm_front_end_ipv4_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500156 if (0 != ret) {
157 goto err_fe_ipv4;
158 }
159
Gareth Williams8ac34292015-03-17 14:06:58 +0000160#ifdef ECM_IPV6_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700161 ret = ecm_front_end_ipv6_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500162 if (0 != ret) {
163 goto err_fe_ipv6;
164 }
Murat Sezgin49465a42014-11-24 15:37:48 -0800165#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500166
Murat Sezgindf98fce2016-08-26 17:56:39 -0700167 ret = ecm_conntrack_notifier_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500168 if (0 != ret) {
169 goto err_ct;
170 }
171
Gareth Williamsf98d4192015-03-11 16:55:41 +0000172#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700173 ret = ecm_state_init(ecm_dentry);
Gareth Williamsf98d4192015-03-11 16:55:41 +0000174 if (0 != ret) {
175 goto err_state;
176 }
177#endif
178
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500179 printk(KERN_INFO "ECM init complete\n");
180 return 0;
181
Gareth Williamsf98d4192015-03-11 16:55:41 +0000182#ifdef ECM_STATE_OUTPUT_ENABLE
183err_state:
Murat Sezgindf98fce2016-08-26 17:56:39 -0700184 ecm_conntrack_notifier_exit();
Gareth Williamsf98d4192015-03-11 16:55:41 +0000185#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500186err_ct:
Gareth Williams8ac34292015-03-17 14:06:58 +0000187#ifdef ECM_IPV6_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500188 ecm_front_end_ipv6_exit();
189err_fe_ipv6:
Murat Sezgin49465a42014-11-24 15:37:48 -0800190#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500191 ecm_front_end_ipv4_exit();
192err_fe_ipv4:
Murat Sezginb3731e82014-11-26 12:20:59 -0800193#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700194 ecm_front_end_bond_notifier_exit();
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500195err_bond:
Murat Sezginb3731e82014-11-26 12:20:59 -0800196#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500197 ecm_interface_exit();
198err_iface:
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100199#ifdef ECM_CLASSIFIER_PCC_ENABLE
200 ecm_classifier_pcc_exit();
201err_cls_pcc:
202#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800203#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100204 ecm_classifier_dscp_exit();
205err_cls_dscp:
Murat Sezginb3731e82014-11-26 12:20:59 -0800206#endif
Hai Shalom81f4e202014-06-04 09:30:27 -0700207#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500208 ecm_classifier_hyfi_rules_exit();
209err_cls_hyfi:
Hai Shalom81f4e202014-06-04 09:30:27 -0700210#endif
Murat Sezginaaaafb42014-11-24 17:02:05 -0800211#ifdef ECM_CLASSIFIER_NL_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500212 ecm_classifier_nl_rules_exit();
213err_cls_nl:
Murat Sezginaaaafb42014-11-24 17:02:05 -0800214#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500215 ecm_classifier_default_exit();
216err_cls_default:
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500217 ecm_db_exit();
218err_db:
Murat Sezgin908ecb32015-05-10 20:54:36 -0700219 debugfs_remove_recursive(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500220
221 printk(KERN_INFO "ECM init failed: %d\n", ret);
222 return ret;
223}
224
225/*
226 * ecm_exit()
227 */
228static void __exit ecm_exit(void)
229{
230 printk(KERN_INFO "ECM exit\n");
231
232 /* call stop on anything that requires a prepare-to-exit signal */
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700233 DEBUG_INFO("stop conntrack notifier\n");
Murat Sezgindf98fce2016-08-26 17:56:39 -0700234 ecm_conntrack_notifier_stop(1);
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700235 DEBUG_INFO("stop front_end_ipv4\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500236 ecm_front_end_ipv4_stop(1);
Gareth Williams8ac34292015-03-17 14:06:58 +0000237#ifdef ECM_IPV6_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700238 DEBUG_INFO("stop front_end_ipv6\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500239 ecm_front_end_ipv6_stop(1);
Murat Sezgin49465a42014-11-24 15:37:48 -0800240#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800241#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700242 DEBUG_INFO("stop bond notifier\n");
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700243 ecm_front_end_bond_notifier_stop(1);
Murat Sezginb3731e82014-11-26 12:20:59 -0800244#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700245 DEBUG_INFO("defunct all db connections\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500246 ecm_db_connection_defunct_all();
247
248 /* now call exit on each module */
Gareth Williamsf98d4192015-03-11 16:55:41 +0000249#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700250 DEBUG_INFO("stop state\n");
Gareth Williamsf98d4192015-03-11 16:55:41 +0000251 ecm_state_exit();
252#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700253 DEBUG_INFO("exit conntrack notifier\n");
Murat Sezgindf98fce2016-08-26 17:56:39 -0700254 ecm_conntrack_notifier_exit();
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700255 DEBUG_INFO("exit front_end_ipv4\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500256 ecm_front_end_ipv4_exit();
Gareth Williams8ac34292015-03-17 14:06:58 +0000257#ifdef ECM_IPV6_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700258 DEBUG_INFO("exit front_end_ipv6\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500259 ecm_front_end_ipv6_exit();
Murat Sezgin49465a42014-11-24 15:37:48 -0800260#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800261#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700262 DEBUG_INFO("exit bond notifier\n");
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700263 ecm_front_end_bond_notifier_exit();
Murat Sezginb3731e82014-11-26 12:20:59 -0800264#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700265 DEBUG_INFO("exit interface\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500266 ecm_interface_exit();
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100267
268#ifdef ECM_CLASSIFIER_PCC_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700269 DEBUG_INFO("exit pcc classifier\n");
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100270 ecm_classifier_pcc_exit();
271#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800272#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700273 DEBUG_INFO("exit dscp classifier\n");
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100274 ecm_classifier_dscp_exit();
Murat Sezginb3731e82014-11-26 12:20:59 -0800275#endif
Hai Shalom81f4e202014-06-04 09:30:27 -0700276#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700277 DEBUG_INFO("exit hyfi classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500278 ecm_classifier_hyfi_rules_exit();
Hai Shalom81f4e202014-06-04 09:30:27 -0700279#endif
Murat Sezginaaaafb42014-11-24 17:02:05 -0800280#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700281 DEBUG_INFO("exit nl classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500282 ecm_classifier_nl_rules_exit();
Murat Sezginaaaafb42014-11-24 17:02:05 -0800283#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700284 DEBUG_INFO("exit default classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500285 ecm_classifier_default_exit();
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700286 DEBUG_INFO("exit db\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500287 ecm_db_exit();
Murat Sezgin908ecb32015-05-10 20:54:36 -0700288
289 if (ecm_dentry != NULL) {
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700290 DEBUG_INFO("remove ecm debugfs\n");
Murat Sezgin908ecb32015-05-10 20:54:36 -0700291 debugfs_remove_recursive(ecm_dentry);
292 }
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500293
294 printk(KERN_INFO "ECM exit complete\n");
295}
296
297module_init(ecm_init)
298module_exit(ecm_exit)
299
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500300MODULE_DESCRIPTION("ECM Core");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500301MODULE_LICENSE("Dual BSD/GPL");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500302