@@ -208,164 +208,177 @@ void Chain::updateChain() {
208208 int startingIndex = index;
209209 Firewall::Program *firstProgramLoaded;
210210 std::vector<Firewall::Program *> newProgramsChain (3 + ModulesConstants::NR_MODULES + 2 );
211- std::map<uint8_t , std::vector<uint64_t >> states;
212- std::map<struct IpAddr , std::vector<uint64_t >> ips;
213- std::map<uint16_t , std::vector<uint64_t >> ports;
214- std::map<int , std::vector<uint64_t >> protocols;
215- std::vector<std::vector<uint64_t >> flags;
216-
217- // Looping through conntrack
218- conntrack_from_rules_to_map (states, rules_);
219- if (!states.empty ()) {
220- // At least one rule requires a matching on conntrack, so it can be
221- // injected.
222- if (!parent_.isContrackActive ()) {
223- logger ()->error (
224- " [{0}] Conntrack is not active, please remember to activate it." ,
225- parent_.getName ());
226- }
227- Firewall::ConntrackMatch *conntrack =
228- new Firewall::ConntrackMatch (index, name, this ->parent_ );
229- newProgramsChain[ModulesConstants::CONNTRACKMATCH] = conntrack;
230- // Now the program is loaded, populate it.
231- conntrack->updateMap (states);
232-
233- // This check is not really needed here, it will always be the first module
234- // to be injected
235- if (index == startingIndex) {
236- firstProgramLoaded = conntrack;
237- }
238- ++index;
239- }
240- states.clear ();
241- // Done looping through conntrack
242-
243- // Looping through IP source
244- ip_from_rules_to_map (SOURCE_TYPE, ips, rules_);
245- if (!ips.empty ()) {
246- // At least one rule requires a matching on ipsource, so inject
247- // the module on the first available position
248- Firewall::IpLookup *iplookup =
249- new Firewall::IpLookup (index, name, SOURCE_TYPE, this ->parent_ );
250- newProgramsChain[ModulesConstants::IPSOURCE] = iplookup;
251- // If this is the first module, adjust parsing to forward to it.
252- if (index == startingIndex) {
253- firstProgramLoaded = iplookup;
211+ std::map<uint8_t , std::vector<uint64_t >> conntrack_map;
212+ std::map<struct IpAddr , std::vector<uint64_t >> ipsrc_map;
213+ std::map<struct IpAddr , std::vector<uint64_t >> ipdst_map;
214+ std::map<uint16_t , std::vector<uint64_t >> portsrc_map;
215+ std::map<uint16_t , std::vector<uint64_t >> portdst_map;
216+ std::map<int , std::vector<uint64_t >> protocol_map;
217+ std::vector<std::vector<uint64_t >> flags_map;
218+
219+
220+ // calculate bitvectors, and check if no wildcard is present.
221+ // if no wildcard is present, we can early break the pipeline.
222+ // so we put modules with _break flags_map, before the others in order
223+ // to maximize probability to early break the pipeline.
224+ bool conntrack_break = conntrackFromRulesToMap (conntrack_map, rules_);
225+ bool ipsrc_break = ipFromRulesToMap (SOURCE_TYPE, ipsrc_map, rules_);
226+ bool ipdst_break = ipFromRulesToMap (DESTINATION_TYPE, ipdst_map, rules_);
227+ bool protocol_break = transportProtoFromRulesToMap (protocol_map, rules_);
228+ bool portsrc_break = portFromRulesToMap (SOURCE_TYPE, portsrc_map, rules_);
229+ bool portdst_break = portFromRulesToMap (DESTINATION_TYPE, portdst_map, rules_);
230+ bool flags_break = flagsFromRulesToMap (flags_map, rules_);
231+
232+ logger ()->debug (
233+ " Early break of pipeline conntrack:{0} ipsrc:{1} ipdst:{2} protocol:{3} "
234+ " portstc:{4} portdst:{5} flags_map:{6} " ,
235+ conntrack_break, ipsrc_break, ipdst_break, protocol_break, portsrc_break,
236+ portdst_break, flags_break);
237+
238+ // first loop iteration pushes program that could early break the pipeline
239+ // second iteration, push others programs
240+
241+ bool second = false ;
242+
243+ for (int j = 0 ; j < 2 ; j++) {
244+ if (j == 1 )
245+ second = true ;
246+
247+ std::cout << " ++++Conntrack Map empty " << conntrack_map.empty () << std::endl;
248+
249+ // Looping through conntrack
250+ if (!conntrack_map.empty () && conntrack_break ^ second) {
251+ // At least one rule requires a matching on conntrack, so it can be
252+ // injected.
253+ if (!parent_.isContrackActive ()) {
254+ logger ()->error (
255+ " [{0}] Conntrack is not active, please remember to activate it." ,
256+ parent_.getName ());
257+ }
258+ Firewall::ConntrackMatch *conntrack =
259+ new Firewall::ConntrackMatch (index, name, this ->parent_ );
260+ newProgramsChain[ModulesConstants::CONNTRACKMATCH] = conntrack;
261+ // Now the program is loaded, populate it.
262+ conntrack->updateMap (conntrack_map);
263+
264+ // This check is not really needed here, it will always be the first module
265+ // to be injected
266+ if (index == startingIndex) {
267+ firstProgramLoaded = conntrack;
268+ }
269+ ++index;
254270 }
255- ++index;
256-
257- // Now the program is loaded, populate it.
258- iplookup->updateMap (ips);
259- }
260- ips.clear ();
261- // Done looping through IP source
262-
263- // Looping through IP destination
264- ip_from_rules_to_map (DESTINATION_TYPE, ips, rules_);
265-
266- if (!ips.empty ()) {
267- // At least one rule requires a matching on ipdestination, so inject
268- // the module on the first available position
269- Firewall::IpLookup *iplookup =
270- new Firewall::IpLookup (index, name, DESTINATION_TYPE, this ->parent_ );
271- newProgramsChain[ModulesConstants::IPDESTINATION] = iplookup;
272- // If this is the first module, adjust parsing to forward to it.
273- if (index == startingIndex) {
274- firstProgramLoaded = iplookup;
271+ // Done looping through conntrack
272+
273+ // Looping through IP source
274+ if (!ipsrc_map.empty () && (ipsrc_break ^ second)) {
275+ // At least one rule requires a matching on ipsource, so inject
276+ // the module on the first available position
277+ Firewall::IpLookup *iplookup =
278+ new Firewall::IpLookup (index, name, SOURCE_TYPE, this ->parent_ );
279+ newProgramsChain[ModulesConstants::IPSOURCE] = iplookup;
280+ // If this is the first module, adjust parsing to forward to it.
281+ if (index == startingIndex) {
282+ firstProgramLoaded = iplookup;
283+ }
284+ ++index;
285+
286+ // Now the program is loaded, populate it.
287+ iplookup->updateMap (ipsrc_map);
275288 }
276- ++index;
277-
278- // Now the program is loaded, populate it.
279- iplookup->updateMap (ips);
280- }
281- ips.clear ();
282- // Done looping through IP destination
283-
284- // Looping through l4 protocol
285- transportproto_from_rules_to_map (protocols, rules_);
286-
287- if (!protocols.empty ()) {
288- // At least one rule requires a matching on
289- // source ports, so inject the module
290- // on the first available position
291- Firewall::L4ProtocolLookup *protocollookup =
292- new Firewall::L4ProtocolLookup (index, name, this ->parent_ );
293- newProgramsChain[ModulesConstants::L4PROTO] = protocollookup;
294- // If this is the first module, adjust parsing to forward to it.
295- if (index == startingIndex) {
296- firstProgramLoaded = protocollookup;
289+ // Done looping through IP source
290+
291+ // Looping through IP destination
292+ if (!ipdst_map.empty () && ipdst_break ^ second) {
293+ // At least one rule requires a matching on ipdestination, so inject
294+ // the module on the first available position
295+ Firewall::IpLookup *iplookup =
296+ new Firewall::IpLookup (index, name, DESTINATION_TYPE, this ->parent_ );
297+ newProgramsChain[ModulesConstants::IPDESTINATION] = iplookup;
298+ // If this is the first module, adjust parsing to forward to it.
299+ if (index == startingIndex) {
300+ firstProgramLoaded = iplookup;
301+ }
302+ ++index;
303+
304+ // Now the program is loaded, populate it.
305+ iplookup->updateMap (ipdst_map);
297306 }
298- ++index;
299-
300- // Now the program is loaded, populate it.
301- protocollookup->updateMap (protocols);
302- }
303- protocols.clear ();
304- // Done looping through l4 protocol
305-
306- // Looping through source port
307- port_from_rules_to_map (SOURCE_TYPE, ports, rules_);
308-
309- if (!ports.empty ()) {
310- // At least one rule requires a matching on source ports,
311- // so inject the module on the first available position
312- Firewall::L4PortLookup *portlookup =
313- new Firewall::L4PortLookup (index, name, SOURCE_TYPE, this ->parent_ );
314- newProgramsChain[ModulesConstants::PORTSOURCE] = portlookup;
315- // If this is the first module, adjust parsing to forward to it.
316- if (index == startingIndex) {
317- firstProgramLoaded = portlookup;
307+ // Done looping through IP destination
308+
309+ // Looping through l4 protocol
310+ if (!protocol_map.empty () && protocol_break ^ second) {
311+ // At least one rule requires a matching on
312+ // source port__map, so inject the module
313+ // on the first available position
314+ Firewall::L4ProtocolLookup *protocollookup =
315+ new Firewall::L4ProtocolLookup (index, name, this ->parent_ );
316+ newProgramsChain[ModulesConstants::L4PROTO] = protocollookup;
317+ // If this is the first module, adjust parsing to forward to it.
318+ if (index == startingIndex) {
319+ firstProgramLoaded = protocollookup;
320+ }
321+ ++index;
322+
323+ // Now the program is loaded, populate it.
324+ protocollookup->updateMap (protocol_map);
318325 }
319- ++index;
320-
321- // Now the program is loaded, populate it.
322- portlookup->updateMap (ports);
323- }
324- ports.clear ();
325- // Done looping through source port
326-
327- // Looping through destination port
328- port_from_rules_to_map (DESTINATION_TYPE, ports, rules_);
329-
330- if (!ports.empty ()) {
331- // At least one rule requires a matching on source ports,
332- // so inject the module on the first available position
333- Firewall::L4PortLookup *portlookup =
334- new Firewall::L4PortLookup (index, name, DESTINATION_TYPE, this ->parent_ );
335- newProgramsChain[ModulesConstants::PORTDESTINATION] = portlookup;
336- // If this is the first module, adjust parsing to forward to it.
337- if (index == startingIndex) {
338- firstProgramLoaded = portlookup;
326+ // Done looping through l4 protocol
327+
328+ // Looping through source port
329+ if (!portsrc_map.empty () && portsrc_break ^ second) {
330+ // At least one rule requires a matching on source port__map,
331+ // so inject the module on the first available position
332+ Firewall::L4PortLookup *portlookup =
333+ new Firewall::L4PortLookup (index, name, SOURCE_TYPE, this ->parent_ , portsrc_map);
334+ newProgramsChain[ModulesConstants::PORTSOURCE] = portlookup;
335+ // If this is the first module, adjust parsing to forward to it.
336+ if (index == startingIndex) {
337+ firstProgramLoaded = portlookup;
338+ }
339+ ++index;
340+
341+ // Now the program is loaded, populate it.
342+ portlookup->updateMap (portsrc_map);
339343 }
340- ++index;
341-
342- // Now the program is loaded, populate it.
343- portlookup->updateMap (ports);
344- }
345- ports.clear ();
346- // Done looping through destination port
347-
348- // Looping through tcp flags
349- flags_from_rules_to_map (flags, rules_);
350-
351- if (!flags.empty ()) {
352- // At least one rule requires a matching on flags,
353- // so inject the module in the first available position
354- Firewall::TcpFlagsLookup *tcpflagslookup =
355- new Firewall::TcpFlagsLookup (index, name, this ->parent_ );
356- newProgramsChain[ModulesConstants::TCPFLAGS] = tcpflagslookup;
357- // If this is the first module, adjust parsing to forward to it.
358- if (index == startingIndex) {
359- firstProgramLoaded = tcpflagslookup;
344+ // Done looping through source port
345+
346+ // Looping through destination port
347+ if (!portdst_map.empty () && portdst_break ^ second) {
348+ // At least one rule requires a matching on source port__map,
349+ // so inject the module on the first available position
350+ Firewall::L4PortLookup *portlookup =
351+ new Firewall::L4PortLookup (index, name, DESTINATION_TYPE, this ->parent_ , portdst_map);
352+ newProgramsChain[ModulesConstants::PORTDESTINATION] = portlookup;
353+ // If this is the first module, adjust parsing to forward to it.
354+ if (index == startingIndex) {
355+ firstProgramLoaded = portlookup;
356+ }
357+ ++index;
358+
359+ // Now the program is loaded, populate it.
360+ portlookup->updateMap (portdst_map);
360361 }
361- ++index;
362+ // Done looping through destination port
363+
364+ // Looping through tcp flags_map
365+ if (!flags_map.empty () && flags_break ^ second) {
366+ // At least one rule requires a matching on flags_map,
367+ // so inject the module in the first available position
368+ Firewall::TcpFlagsLookup *tcpflagslookup =
369+ new Firewall::TcpFlagsLookup (index, name, this ->parent_ );
370+ newProgramsChain[ModulesConstants::TCPFLAGS] = tcpflagslookup;
371+ // If this is the first module, adjust parsing to forward to it.
372+ if (index == startingIndex) {
373+ firstProgramLoaded = tcpflagslookup;
374+ }
375+ ++index;
362376
363- // Now the program is loaded, populate it.
364- tcpflagslookup->updateMap (flags);
377+ // Now the program is loaded, populate it.
378+ tcpflagslookup->updateMap (flags_map);
379+ }
380+ // Done looping through tcp flags_map
365381 }
366- flags.clear ();
367-
368- // Done looping through tcp flags
369382
370383 // Adding bitscan
371384 Firewall::BitScan *bitscan =
0 commit comments