blob: 0fbaef93549329745761c69fb0fdf2ee346c87f3 [file] [log] [blame]
Nicolas Costaf46c33b2014-05-15 10:02:00 -05001/*
2 **************************************************************************
Gareth Williamsd5618a82015-05-20 11:13:32 +01003 * Copyright (c) 2014-2015, 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 Sezgin8d916a12015-03-18 15:56:50 -070047
Murat Sezgin908ecb32015-05-10 20:54:36 -070048struct dentry *ecm_dentry; /* Dentry object for top level ecm debugfs directory */
Nicolas Costaf46c33b2014-05-15 10:02:00 -050049
Murat Sezgin908ecb32015-05-10 20:54:36 -070050extern int ecm_db_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050051extern void ecm_db_connection_defunct_all(void);
52extern void ecm_db_exit(void);
53
Murat Sezgin908ecb32015-05-10 20:54:36 -070054extern int ecm_classifier_default_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050055extern void ecm_classifier_default_exit(void);
56
Murat Sezginaaaafb42014-11-24 17:02:05 -080057#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070058extern int ecm_classifier_nl_rules_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050059extern void ecm_classifier_nl_rules_exit(void);
Murat Sezginaaaafb42014-11-24 17:02:05 -080060#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -050061
Hai Shalom81f4e202014-06-04 09:30:27 -070062#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070063extern int ecm_classifier_hyfi_rules_init(struct dentry *dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050064extern void ecm_classifier_hyfi_rules_exit(void);
Hai Shalom81f4e202014-06-04 09:30:27 -070065#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -050066
67extern int ecm_interface_init(void);
Nicolas Costaf46c33b2014-05-15 10:02:00 -050068extern void ecm_interface_exit(void);
69
Murat Sezginb3731e82014-11-26 12:20:59 -080070#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070071extern int ecm_classifier_dscp_init(struct dentry *dentry);
Gareth Williams4a02c9b2014-10-10 14:50:33 +010072extern void ecm_classifier_dscp_exit(void);
Murat Sezginb3731e82014-11-26 12:20:59 -080073#endif
Gareth Williams4a02c9b2014-10-10 14:50:33 +010074
Gareth Williamsf98d4192015-03-11 16:55:41 +000075#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -070076extern int ecm_state_init(struct dentry *dentry);
Gareth Williamsf98d4192015-03-11 16:55:41 +000077extern void ecm_state_exit(void);
78#endif
79
Gareth Williamsdcda9b92015-05-13 10:08:15 +010080#ifdef ECM_CLASSIFIER_PCC_ENABLE
81extern int ecm_classifier_pcc_init(struct dentry *dentry);
82extern void ecm_classifier_pcc_exit(void);
83#endif
84
Nicolas Costaf46c33b2014-05-15 10:02:00 -050085/*
86 * ecm_init()
87 */
88static int __init ecm_init(void)
89{
90 int ret;
Murat Sezginf2b94532014-12-05 14:53:53 -080091
Nicolas Costaf46c33b2014-05-15 10:02:00 -050092 printk(KERN_INFO "ECM init\n");
93
Murat Sezgin908ecb32015-05-10 20:54:36 -070094 ecm_dentry = debugfs_create_dir("ecm", NULL);
95 if (!ecm_dentry) {
Murat Sezgin3ab259d2015-06-11 14:15:35 -070096 DEBUG_ERROR("Failed to create ecm directory in debugfs\n");
Murat Sezgin908ecb32015-05-10 20:54:36 -070097 return -1;
Nicolas Costaf46c33b2014-05-15 10:02:00 -050098 }
99
Murat Sezgin908ecb32015-05-10 20:54:36 -0700100 ret = ecm_db_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500101 if (0 != ret) {
102 goto err_db;
103 }
104
Murat Sezgin908ecb32015-05-10 20:54:36 -0700105 ret = ecm_classifier_default_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500106 if (0 != ret) {
107 goto err_cls_default;
108 }
109
Murat Sezginaaaafb42014-11-24 17:02:05 -0800110#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700111 ret = ecm_classifier_nl_rules_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500112 if (0 != ret) {
113 goto err_cls_nl;
114 }
Murat Sezginaaaafb42014-11-24 17:02:05 -0800115#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500116
Hai Shalom81f4e202014-06-04 09:30:27 -0700117#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700118 ret = ecm_classifier_hyfi_rules_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500119 if (0 != ret) {
120 goto err_cls_hyfi;
121 }
Hai Shalom81f4e202014-06-04 09:30:27 -0700122#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500123
Murat Sezginb3731e82014-11-26 12:20:59 -0800124#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700125 ret = ecm_classifier_dscp_init(ecm_dentry);
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100126 if (0 != ret) {
127 goto err_cls_dscp;
128 }
Murat Sezginb3731e82014-11-26 12:20:59 -0800129#endif
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100130
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100131#ifdef ECM_CLASSIFIER_PCC_ENABLE
132 ret = ecm_classifier_pcc_init(ecm_dentry);
133 if (0 != ret) {
134 goto err_cls_pcc;
135 }
136#endif
137
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500138 ret = ecm_interface_init();
139 if (0 != ret) {
140 goto err_iface;
141 }
142
Murat Sezginb3731e82014-11-26 12:20:59 -0800143#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700144 ret = ecm_front_end_bond_notifier_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500145 if (0 != ret) {
146 goto err_bond;
147 }
Murat Sezginb3731e82014-11-26 12:20:59 -0800148#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500149
Murat Sezgin908ecb32015-05-10 20:54:36 -0700150 ret = ecm_front_end_ipv4_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500151 if (0 != ret) {
152 goto err_fe_ipv4;
153 }
154
Gareth Williams8ac34292015-03-17 14:06:58 +0000155#ifdef ECM_IPV6_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700156 ret = ecm_front_end_ipv6_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500157 if (0 != ret) {
158 goto err_fe_ipv6;
159 }
Murat Sezgin49465a42014-11-24 15:37:48 -0800160#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500161
Murat Sezgin5f138492015-06-11 15:18:27 -0700162 ret = ecm_front_end_conntrack_notifier_init(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500163 if (0 != ret) {
164 goto err_ct;
165 }
166
Gareth Williamsf98d4192015-03-11 16:55:41 +0000167#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin908ecb32015-05-10 20:54:36 -0700168 ret = ecm_state_init(ecm_dentry);
Gareth Williamsf98d4192015-03-11 16:55:41 +0000169 if (0 != ret) {
170 goto err_state;
171 }
172#endif
173
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500174 printk(KERN_INFO "ECM init complete\n");
175 return 0;
176
Gareth Williamsf98d4192015-03-11 16:55:41 +0000177#ifdef ECM_STATE_OUTPUT_ENABLE
178err_state:
Murat Sezgin5f138492015-06-11 15:18:27 -0700179 ecm_front_end_conntrack_notifier_exit();
Gareth Williamsf98d4192015-03-11 16:55:41 +0000180#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500181err_ct:
Gareth Williams8ac34292015-03-17 14:06:58 +0000182#ifdef ECM_IPV6_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500183 ecm_front_end_ipv6_exit();
184err_fe_ipv6:
Murat Sezgin49465a42014-11-24 15:37:48 -0800185#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500186 ecm_front_end_ipv4_exit();
187err_fe_ipv4:
Murat Sezginb3731e82014-11-26 12:20:59 -0800188#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700189 ecm_front_end_bond_notifier_exit();
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500190err_bond:
Murat Sezginb3731e82014-11-26 12:20:59 -0800191#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500192 ecm_interface_exit();
193err_iface:
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100194#ifdef ECM_CLASSIFIER_PCC_ENABLE
195 ecm_classifier_pcc_exit();
196err_cls_pcc:
197#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800198#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100199 ecm_classifier_dscp_exit();
200err_cls_dscp:
Murat Sezginb3731e82014-11-26 12:20:59 -0800201#endif
Hai Shalom81f4e202014-06-04 09:30:27 -0700202#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500203 ecm_classifier_hyfi_rules_exit();
204err_cls_hyfi:
Hai Shalom81f4e202014-06-04 09:30:27 -0700205#endif
Murat Sezginaaaafb42014-11-24 17:02:05 -0800206#ifdef ECM_CLASSIFIER_NL_ENABLE
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500207 ecm_classifier_nl_rules_exit();
208err_cls_nl:
Murat Sezginaaaafb42014-11-24 17:02:05 -0800209#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500210 ecm_classifier_default_exit();
211err_cls_default:
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500212 ecm_db_exit();
213err_db:
Murat Sezgin908ecb32015-05-10 20:54:36 -0700214 debugfs_remove_recursive(ecm_dentry);
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500215
216 printk(KERN_INFO "ECM init failed: %d\n", ret);
217 return ret;
218}
219
220/*
221 * ecm_exit()
222 */
223static void __exit ecm_exit(void)
224{
225 printk(KERN_INFO "ECM exit\n");
226
227 /* call stop on anything that requires a prepare-to-exit signal */
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700228 DEBUG_INFO("stop conntrack notifier\n");
Murat Sezgin5f138492015-06-11 15:18:27 -0700229 ecm_front_end_conntrack_notifier_stop(1);
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700230 DEBUG_INFO("stop front_end_ipv4\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500231 ecm_front_end_ipv4_stop(1);
Gareth Williams8ac34292015-03-17 14:06:58 +0000232#ifdef ECM_IPV6_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700233 DEBUG_INFO("stop front_end_ipv6\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500234 ecm_front_end_ipv6_stop(1);
Murat Sezgin49465a42014-11-24 15:37:48 -0800235#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800236#ifdef ECM_INTERFACE_BOND_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700237 DEBUG_INFO("stop bond notifier\n");
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700238 ecm_front_end_bond_notifier_stop(1);
Murat Sezginb3731e82014-11-26 12:20:59 -0800239#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700240 DEBUG_INFO("defunct all db connections\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500241 ecm_db_connection_defunct_all();
242
243 /* now call exit on each module */
Gareth Williamsf98d4192015-03-11 16:55:41 +0000244#ifdef ECM_STATE_OUTPUT_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700245 DEBUG_INFO("stop state\n");
Gareth Williamsf98d4192015-03-11 16:55:41 +0000246 ecm_state_exit();
247#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700248 DEBUG_INFO("exit conntrack notifier\n");
Murat Sezgin5f138492015-06-11 15:18:27 -0700249 ecm_front_end_conntrack_notifier_exit();
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700250 DEBUG_INFO("exit front_end_ipv4\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500251 ecm_front_end_ipv4_exit();
Gareth Williams8ac34292015-03-17 14:06:58 +0000252#ifdef ECM_IPV6_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700253 DEBUG_INFO("exit front_end_ipv6\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500254 ecm_front_end_ipv6_exit();
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("exit bond notifier\n");
Murat Sezgin8e10a7c2015-06-11 15:49:24 -0700258 ecm_front_end_bond_notifier_exit();
Murat Sezginb3731e82014-11-26 12:20:59 -0800259#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700260 DEBUG_INFO("exit interface\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500261 ecm_interface_exit();
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100262
263#ifdef ECM_CLASSIFIER_PCC_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700264 DEBUG_INFO("exit pcc classifier\n");
Gareth Williamsdcda9b92015-05-13 10:08:15 +0100265 ecm_classifier_pcc_exit();
266#endif
Murat Sezginb3731e82014-11-26 12:20:59 -0800267#ifdef ECM_CLASSIFIER_DSCP_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700268 DEBUG_INFO("exit dscp classifier\n");
Gareth Williams4a02c9b2014-10-10 14:50:33 +0100269 ecm_classifier_dscp_exit();
Murat Sezginb3731e82014-11-26 12:20:59 -0800270#endif
Hai Shalom81f4e202014-06-04 09:30:27 -0700271#ifdef ECM_CLASSIFIER_HYFI_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700272 DEBUG_INFO("exit hyfi classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500273 ecm_classifier_hyfi_rules_exit();
Hai Shalom81f4e202014-06-04 09:30:27 -0700274#endif
Murat Sezginaaaafb42014-11-24 17:02:05 -0800275#ifdef ECM_CLASSIFIER_NL_ENABLE
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700276 DEBUG_INFO("exit nl classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500277 ecm_classifier_nl_rules_exit();
Murat Sezginaaaafb42014-11-24 17:02:05 -0800278#endif
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700279 DEBUG_INFO("exit default classifier\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500280 ecm_classifier_default_exit();
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700281 DEBUG_INFO("exit db\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500282 ecm_db_exit();
Murat Sezgin908ecb32015-05-10 20:54:36 -0700283
284 if (ecm_dentry != NULL) {
Murat Sezgin3ab259d2015-06-11 14:15:35 -0700285 DEBUG_INFO("remove ecm debugfs\n");
Murat Sezgin908ecb32015-05-10 20:54:36 -0700286 debugfs_remove_recursive(ecm_dentry);
287 }
Nicolas Costaf46c33b2014-05-15 10:02:00 -0500288
289 printk(KERN_INFO "ECM exit complete\n");
290}
291
292module_init(ecm_init)
293module_exit(ecm_exit)
294
295MODULE_AUTHOR("Qualcomm Atheros, Inc.");
296MODULE_DESCRIPTION("ECM Core");
297#ifdef MODULE_LICENSE
298MODULE_LICENSE("Dual BSD/GPL");
299#endif
300