blob: a6da26cea5cd62632a65cb68a6fa40b8a9b86ac0 [file] [log] [blame]
Murat Sezginc725ad82016-04-13 17:12:50 -07001/*
2 **************************************************************************
3 * Copyright (c) 2016 The Linux Foundation. All rights reserved.
4 * 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 */
16
17#include <linux/version.h>
18#include <linux/types.h>
19#include <net/ip.h>
20#include <net/ipv6.h>
21#include <linux/inet.h>
22#include <linux/etherdevice.h>
23
24/*
25 * Debug output levels
26 * 0 = OFF
27 * 1 = ASSERTS / ERRORS
28 * 2 = 1 + WARN
29 * 3 = 2 + INFO
30 * 4 = 3 + TRACE
31 */
32#define DEBUG_LEVEL ECM_CLASSIFIER_DEBUG_LEVEL
33
34#include "ecm_types.h"
35#include "ecm_db_types.h"
36#include "ecm_state.h"
37#include "ecm_tracker.h"
38#include "ecm_classifier.h"
Murat Sezginc890e0c2016-09-01 11:17:17 -070039#include "ecm_front_end_types.h"
Murat Sezginc725ad82016-04-13 17:12:50 -070040#include "ecm_db.h"
41#ifdef ECM_CLASSIFIER_NL_ENABLE
42#include "ecm_classifier_nl.h"
43#endif
44#ifdef ECM_CLASSIFIER_HYFI_ENABLE
45#include "ecm_classifier_hyfi.h"
46#endif
47#ifdef ECM_CLASSIFIER_DSCP_ENABLE
48#include "ecm_classifier_dscp.h"
49#endif
50#ifdef ECM_CLASSIFIER_PCC_ENABLE
51#include "ecm_classifier_pcc.h"
52#endif
53
54/*
55 * ecm_classifier_assign_classifier()
56 * Instantiate and assign classifier of type upon the connection, also returning it if it could be allocated.
57 */
58struct ecm_classifier_instance *ecm_classifier_assign_classifier(struct ecm_db_connection_instance *ci, ecm_classifier_type_t type)
59{
60 DEBUG_TRACE("%p: Assign classifier of type: %d\n", ci, type);
61 DEBUG_ASSERT(type != ECM_CLASSIFIER_TYPE_DEFAULT, "Must never need to instantiate default type in this way");
62
63#ifdef ECM_CLASSIFIER_PCC_ENABLE
64 if (type == ECM_CLASSIFIER_TYPE_PCC) {
65 struct ecm_classifier_pcc_instance *pcci;
66 pcci = ecm_classifier_pcc_instance_alloc(ci);
67 if (!pcci) {
68 DEBUG_TRACE("%p: Failed to create Parental Controls classifier\n", ci);
69 return NULL;
70 }
71 DEBUG_TRACE("%p: Created Parental Controls classifier: %p\n", ci, pcci);
72 ecm_db_connection_classifier_assign(ci, (struct ecm_classifier_instance *)pcci);
73 return (struct ecm_classifier_instance *)pcci;
74 }
75#endif
76
77#ifdef ECM_CLASSIFIER_NL_ENABLE
78 if (type == ECM_CLASSIFIER_TYPE_NL) {
79 struct ecm_classifier_nl_instance *cnli;
80 cnli = ecm_classifier_nl_instance_alloc(ci);
81 if (!cnli) {
82 DEBUG_TRACE("%p: Failed to create Netlink classifier\n", ci);
83 return NULL;
84 }
85 DEBUG_TRACE("%p: Created Netlink classifier: %p\n", ci, cnli);
86 ecm_db_connection_classifier_assign(ci, (struct ecm_classifier_instance *)cnli);
87 return (struct ecm_classifier_instance *)cnli;
88 }
89#endif
90
91#ifdef ECM_CLASSIFIER_DSCP_ENABLE
92 if (type == ECM_CLASSIFIER_TYPE_DSCP) {
93 struct ecm_classifier_dscp_instance *cdscpi;
94 cdscpi = ecm_classifier_dscp_instance_alloc(ci);
95 if (!cdscpi) {
96 DEBUG_TRACE("%p: Failed to create DSCP classifier\n", ci);
97 return NULL;
98 }
99 DEBUG_TRACE("%p: Created DSCP classifier: %p\n", ci, cdscpi);
100 ecm_db_connection_classifier_assign(ci, (struct ecm_classifier_instance *)cdscpi);
101 return (struct ecm_classifier_instance *)cdscpi;
102 }
103#endif
104
105#ifdef ECM_CLASSIFIER_HYFI_ENABLE
106 if (type == ECM_CLASSIFIER_TYPE_HYFI) {
107 struct ecm_classifier_hyfi_instance *chfi;
108 chfi = ecm_classifier_hyfi_instance_alloc(ci);
109 if (!chfi) {
110 DEBUG_TRACE("%p: Failed to create HyFi classifier\n", ci);
111 return NULL;
112 }
113 DEBUG_TRACE("%p: Created HyFi classifier: %p\n", ci, chfi);
114 ecm_db_connection_classifier_assign(ci, (struct ecm_classifier_instance *)chfi);
115 return (struct ecm_classifier_instance *)chfi;
116 }
117#endif
118
119 DEBUG_ASSERT(NULL, "%p: Unsupported type: %d\n", ci, type);
120 return NULL;
121}
122
123/*
124 * ecm_classifier_reclassify()
125 * Signal reclassify upon the assigned classifiers.
126 *
127 * Classifiers that unassigned themselves we TRY to re-instantiate them.
128 * Returns false if the function is not able to instantiate all missing classifiers.
129 * This function does not release and references to classifiers in the assignments[].
130 */
131bool ecm_classifier_reclassify(struct ecm_db_connection_instance *ci, int assignment_count, struct ecm_classifier_instance *assignments[])
132{
133 ecm_classifier_type_t classifier_type;
134 int i;
135 bool full_reclassification = true;
136
137 /*
138 * assignment_count will always be <= the number of classifier types available
139 */
140 for (i = 0, classifier_type = ECM_CLASSIFIER_TYPE_DEFAULT; i < assignment_count; ++i, ++classifier_type) {
141 ecm_classifier_type_t aci_type;
142 struct ecm_classifier_instance *aci;
143
144 aci = assignments[i];
145 aci_type = aci->type_get(aci);
146 DEBUG_TRACE("%p: Reclassify: %d\n", ci, aci_type);
147 aci->reclassify(aci);
148
149 /*
150 * If the connection has a full complement of assigned classifiers then these will match 1:1 with the classifier_type (all in same order).
151 * If not, we have to create the missing ones.
152 */
153 if (aci_type == classifier_type) {
154 continue;
155 }
156
157 /*
158 * Need to instantiate the missing classifier types until we get to the same type as aci_type then we are back in sync to continue reclassification
159 */
160 while (classifier_type != aci_type) {
161 struct ecm_classifier_instance *naci;
162 DEBUG_TRACE("%p: Instantiate missing type: %d\n", ci, classifier_type);
163 DEBUG_ASSERT(classifier_type < ECM_CLASSIFIER_TYPES, "Algorithm bad");
164
165 naci = ecm_classifier_assign_classifier(ci, classifier_type);
166 if (!naci) {
167 full_reclassification = false;
168 } else {
169 naci->deref(naci);
170 }
171
172 classifier_type++;
173 }
174 }
175
176 /*
177 * Add missing types
178 */
179 for (; classifier_type < ECM_CLASSIFIER_TYPES; ++classifier_type) {
180 struct ecm_classifier_instance *naci;
181 DEBUG_TRACE("%p: Instantiate missing type: %d\n", ci, classifier_type);
182
183 naci = ecm_classifier_assign_classifier(ci, classifier_type);
184 if (!naci) {
185 full_reclassification = false;
186 } else {
187 naci->deref(naci);
188 }
189 }
190
191 DEBUG_TRACE("%p: reclassify done: %u\n", ci, full_reclassification);
192 return full_reclassification;
193}
194