@@ -138,10 +138,18 @@ ChainResetCountersOutputJsonObject Chain::resetCounters() {
138138 ChainResetCountersOutputJsonObject result;
139139 try {
140140 std::vector<Firewall::Program *> *programs;
141+
142+ bool * horus_runtime_enabled_;
143+ bool * horus_swap_;
144+
141145 if (name == ChainNameEnum::INGRESS) {
142146 programs = &parent_.ingress_programs ;
147+ horus_runtime_enabled_ = &parent_.horus_runtime_enabled_ingress_ ;
148+ horus_swap_ = &parent_.horus_swap_ingress_ ;
143149 } else if (name == ChainNameEnum::EGRESS) {
144- programs = &parent_.egress_programs ;
150+ programs = &parent_.egress_programs ;
151+ horus_runtime_enabled_ = &parent_.horus_runtime_enabled_egress_ ;
152+ horus_swap_ = &parent_.horus_swap_egress_ ;
145153 } else {
146154 return result;
147155 }
@@ -153,12 +161,25 @@ ChainResetCountersOutputJsonObject Chain::resetCounters() {
153161 auto actionProgram = dynamic_cast <Firewall::ActionLookup *>(
154162 programs->at (ModulesConstants::ACTION));
155163
164+ Firewall::Horus * horusProgram;
165+
166+ if (*horus_runtime_enabled_) {
167+ if (!(*horus_swap_)) {
168+ horusProgram = dynamic_cast <Firewall::Horus *>(programs->at (ModulesConstants::HORUS_INGRESS));
169+ } else {
170+ horusProgram = dynamic_cast <Firewall::Horus *>(programs->at (ModulesConstants::HORUS_INGRESS_SWAP));
171+ }
172+ }
173+
156174 for (auto cr : rules_) {
157175 actionProgram->flushCounters (cr->getId ());
176+ if (*horus_runtime_enabled_){
177+ horusProgram->flushCounters (cr->getId ());
178+ }
158179 }
159180
160181 dynamic_cast <Firewall::DefaultAction *>(
161- programs->at (ModulesConstants::DEFAULTACTION))->flushCounters (name);
182+ programs->at (ModulesConstants::DEFAULTACTION))->flushCounters (name);
162183
163184 counters_.clear ();
164185
@@ -189,10 +210,17 @@ uint32_t Chain::getNrRules() {
189210
190211void Chain::updateChain () {
191212 std::vector<Firewall::Program *> *programs;
213+ bool * horus_runtime_enabled_;
214+ bool * horus_swap_;
215+
192216 if (name == ChainNameEnum::INGRESS) {
193217 programs = &parent_.ingress_programs ;
218+ horus_runtime_enabled_ = &parent_.horus_runtime_enabled_ingress_ ;
219+ horus_swap_ = &parent_.horus_swap_ingress_ ;
194220 } else if (name == ChainNameEnum::EGRESS) {
195221 programs = &parent_.egress_programs ;
222+ horus_runtime_enabled_ = &parent_.horus_runtime_enabled_egress_ ;
223+ horus_swap_ = &parent_.horus_swap_egress_ ;
196224 } else {
197225 return ;
198226 }
@@ -203,11 +231,11 @@ void Chain::updateChain() {
203231 // std::lock_guard<std::mutex> lkBpf(parent_.bpfInjectMutex);
204232 auto start = std::chrono::high_resolution_clock::now ();
205233
206- int index = 3 + (chainNumber * ModulesConstants::NR_MODULES);
234+ int index = ModulesConstants::NR_INITIAL_MODULES + (chainNumber * ModulesConstants::NR_MODULES);
207235
208236 int startingIndex = index;
209237 Firewall::Program *firstProgramLoaded;
210- std::vector<Firewall::Program *> newProgramsChain (3 + ModulesConstants::NR_MODULES + 2 );
238+ std::vector<Firewall::Program *> newProgramsChain (ModulesConstants::NR_INITIAL_MODULES + ModulesConstants::NR_MODULES + 1 );
211239 std::map<uint8_t , std::vector<uint64_t >> conntrack_map;
212240 std::map<struct IpAddr , std::vector<uint64_t >> ipsrc_map;
213241 std::map<struct IpAddr , std::vector<uint64_t >> ipdst_map;
@@ -216,6 +244,105 @@ void Chain::updateChain() {
216244 std::map<int , std::vector<uint64_t >> protocol_map;
217245 std::vector<std::vector<uint64_t >> flags_map;
218246
247+ std::map<struct HorusRule , struct HorusValue > horus;
248+
249+
250+ /*
251+ * HORUS - Homogeneous RUleset analySis
252+ *
253+ * Horus optimization allows to
254+ * a) offload a group of contiguous rules matching on same field
255+ * b) match the group of offloaded rules with complexity O(1) - single hashmap lookup
256+ * c) dynamically adapting to different groups of rules, matching each
257+ * combination of ipsrc/dst, portsrc/dst, tcpflags
258+ * d) dynamically check when the optimization is possible according to current
259+ * ruleset. It means check orthogonality
260+ * of rules before the offloaded group, respect to the group itself.
261+ *
262+ * each pkt received by the program, is looked-up vs the HORUS HASHMAP.
263+ * hit ->
264+ * -DROP action: drop the packet;
265+ * -ACCEPT action: goto CTLABELING and CTTABLEUPDATE without going through pipeline
266+ * miss ->
267+ * -GOTO all pipeline steps
268+ */
269+
270+ *horus_runtime_enabled_ = false ;
271+
272+ // Apply Horus optimization only if it is enabled
273+ if (parent_.horus_enabled ) {
274+ // if len Chain >= MIN_RULES_HORUS_OPTIMIZATION
275+ if (getRuleList ().size () >= HorusConst::MIN_RULE_SIZE_FOR_HORUS) {
276+ // calculate horus ruleset
277+ horusFromRulesToMap (horus, getRuleList ());
278+
279+ // if horus.size() >= MIN_RULES_HORUS_OPTIMIZATION
280+ if (horus.size () >= HorusConst::MIN_RULE_SIZE_FOR_HORUS) {
281+ logger ()->info (" Horus Optimization ENABLED for this rule-set" );
282+
283+ *horus_runtime_enabled_ = true ;
284+
285+ // SWAP indexes
286+ *horus_swap_ = !(*horus_swap_);
287+
288+ uint8_t horus_index_new = -1 ;
289+ uint8_t horus_index_old = -1 ;
290+
291+ // Apply Horus optimization
292+
293+ // Calculate current new/old indexes
294+ if (*horus_swap_) {
295+ horus_index_new = ModulesConstants::HORUS_INGRESS_SWAP;
296+ horus_index_old = ModulesConstants::HORUS_INGRESS;
297+ } else {
298+ horus_index_old = ModulesConstants::HORUS_INGRESS_SWAP;
299+ horus_index_new = ModulesConstants::HORUS_INGRESS;
300+ }
301+
302+ // Compile and inject program
303+
304+ std::vector<Firewall::Program *> *prog;
305+
306+ if (name == ChainNameEnum::INGRESS) {
307+ prog = &parent_.ingress_programs ;
308+ } else if (name == ChainNameEnum::EGRESS) {
309+ prog = &parent_.egress_programs ;
310+ } else {
311+ throw std::runtime_error (" No ingress/egress chain" );
312+ }
313+
314+ Firewall::Horus * horusptr =
315+ new Firewall::Horus (horus_index_new, parent_, name, horus);
316+ prog->at (horus_index_new) = horusptr;
317+
318+ auto horusProgram = dynamic_cast <Firewall::Horus *>(
319+ programs->at (horus_index_new));
320+
321+ horusProgram->updateMap (horus);
322+
323+ auto parserIngress = dynamic_cast <Firewall::Parser *>(programs->at (ModulesConstants::PARSER));
324+ parserIngress->reload ();
325+
326+ // Delete old Horus, if present
327+
328+ if (programs->at (horus_index_old) != nullptr ) {
329+ delete programs->at (horus_index_old);
330+ }
331+ programs->at (horus_index_old) = nullptr ;
332+ }
333+ }
334+ }
335+ if (*horus_runtime_enabled_ == false ) {
336+ auto parserIngress = dynamic_cast <Firewall::Parser *>(programs->at (ModulesConstants::PARSER));
337+ parserIngress->reload ();
338+
339+ // Delete old Horus, if present
340+ delete programs->at (ModulesConstants::HORUS_INGRESS);
341+ delete programs->at (ModulesConstants::HORUS_INGRESS_SWAP);
342+ programs->at (ModulesConstants::HORUS_INGRESS) = nullptr ;
343+ programs->at (ModulesConstants::HORUS_INGRESS_SWAP) = nullptr ;
344+ }
345+
219346
220347 // calculate bitvectors, and check if no wildcard is present.
221348 // if no wildcard is present, we can early break the pipeline.
0 commit comments