From 80e7bedecf4b7e5bb1eca74a2fb88b7c0f79d85f Mon Sep 17 00:00:00 2001
From: Your Name <you@example.com>
Date: Wed, 18 Mar 2015 15:09:40 +0100
Subject: [PATCH] Testing membership aggregation.

---
 mcproxy/include/parser/configuration.hpp      |   1 +
 mcproxy/include/parser/interface.hpp          |   2 +
 mcproxy/include/parser/parser.hpp             |   1 +
 mcproxy/include/proxy/check_if.hpp            |   1 +
 mcproxy/include/proxy/check_kernel.hpp        |   2 +
 mcproxy/include/proxy/igmp_receiver.hpp       |   1 +
 mcproxy/include/proxy/igmp_sender.hpp         |   1 +
 mcproxy/include/proxy/interfaces.hpp          |   2 +-
 mcproxy/include/proxy/message_queue.hpp       |   9 +
 mcproxy/include/proxy/mld_receiver.hpp        |   1 +
 mcproxy/include/proxy/mld_sender.hpp          |   1 +
 mcproxy/include/proxy/routing.hpp             |   2 +-
 .../proxy/simple_membership_aggregation.hpp   |   3 +
 mcproxy/include/proxy/simple_routing_data.hpp |   1 +
 .../proxy/simple_routing_management.hpp       |   1 +
 mcproxy/src/parser/configuration.cpp          |   6 +
 mcproxy/src/parser/interface.cpp              |  11 +
 mcproxy/src/parser/parser.cpp                 |   4 +
 mcproxy/src/proxy/check_if.cpp                |   5 +
 mcproxy/src/proxy/check_kernel.cpp            |   6 +
 mcproxy/src/proxy/igmp_receiver.cpp           |  59 ++--
 mcproxy/src/proxy/igmp_sender.cpp             |   5 +
 mcproxy/src/proxy/interfaces.cpp              |   1 -
 mcproxy/src/proxy/mld_receiver.cpp            |   5 +
 mcproxy/src/proxy/mld_sender.cpp              |   5 +
 mcproxy/src/proxy/sender.cpp                  |   1 -
 .../proxy/simple_membership_aggregation.cpp   | 223 +++------------
 mcproxy/src/proxy/simple_routing_data.cpp     |  19 +-
 .../src/proxy/simple_routing_management.cpp   |   5 +
 .../testing/test_membership_aggregation.hpp   | 261 +++++++++++++++---
 mcproxy/testing/ut_minimal.hpp                |  45 +--
 references/parser/membership_aggregation      |   2 +-
 references/parser/test_first_mem_aggr.conf    | 138 +++++++++
 33 files changed, 548 insertions(+), 282 deletions(-)
 create mode 100644 references/parser/test_first_mem_aggr.conf

diff --git a/mcproxy/include/parser/configuration.hpp b/mcproxy/include/parser/configuration.hpp
index 37e7f93..0c179a4 100644
--- a/mcproxy/include/parser/configuration.hpp
+++ b/mcproxy/include/parser/configuration.hpp
@@ -60,6 +60,7 @@ private:
     friend struct test_membership_aggregation; 
     friend struct test_parser;
 public:
+    virtual ~configuration();
     configuration(const std::string& path, bool reset_reverse_path_filter);
 
 
diff --git a/mcproxy/include/parser/interface.hpp b/mcproxy/include/parser/interface.hpp
index b3bda63..0a0f907 100644
--- a/mcproxy/include/parser/interface.hpp
+++ b/mcproxy/include/parser/interface.hpp
@@ -166,6 +166,7 @@ private:
     std::string to_string_rule_matching() const;
 
 public:
+    virtual ~rule_binding();
     rule_binding(const std::string& instance_name, rb_interface_type interface_type, const std::string& if_name, rb_interface_direction filter_direction, rb_filter_type filter_type, std::unique_ptr<table> filter_table);
     rule_binding(const std::string& instance_name, rb_interface_type interface_type, const std::string& if_name, rb_interface_direction filter_direction, rb_rule_matching_type rule_matching_type, const std::chrono::milliseconds& timeout);
 
@@ -196,6 +197,7 @@ class interface
     bool is_source_allowed(const std::string& input_if_name, const addr_storage& gaddr, const addr_storage& saddr, const std::unique_ptr<rule_binding>& filter, bool excplicit_if_name) const;
 
 public:
+    virtual ~interface();
     interface(const std::string& if_name);
     std::string get_if_name() const;
 
diff --git a/mcproxy/include/parser/parser.hpp b/mcproxy/include/parser/parser.hpp
index b041026..4aaa393 100644
--- a/mcproxy/include/parser/parser.hpp
+++ b/mcproxy/include/parser/parser.hpp
@@ -57,6 +57,7 @@ private:
     void parse_interface_rule_match_binding(std::string&& instance_name, rb_interface_type interface_type, std::string&& if_name, rb_interface_direction filter_direction, const inst_def_set& ids);
 
 public:
+    virtual ~parser();
     parser(unsigned int current_line, const std::string& cmd);
     parser_type get_parser_type();
 
diff --git a/mcproxy/include/proxy/check_if.hpp b/mcproxy/include/proxy/check_if.hpp
index 168595e..5fb588e 100644
--- a/mcproxy/include/proxy/check_if.hpp
+++ b/mcproxy/include/proxy/check_if.hpp
@@ -48,6 +48,7 @@ private:
     std::vector<int> m_swap_to_down;
 
 public:
+    virtual ~check_if();
 
     /**
      * @brief Create a check_if instance.
diff --git a/mcproxy/include/proxy/check_kernel.hpp b/mcproxy/include/proxy/check_kernel.hpp
index 0fb25a5..4587982 100644
--- a/mcproxy/include/proxy/check_kernel.hpp
+++ b/mcproxy/include/proxy/check_kernel.hpp
@@ -41,6 +41,8 @@ private:
     void check_routing_tables(mroute_socket& ms, std::string version);
     void check_kernel_limits(mroute_socket& ms, std::string version);
 public:
+    virtual ~check_kernel();
+
     /**
      * @brief Check the currently available kernel features.
      */
diff --git a/mcproxy/include/proxy/igmp_receiver.hpp b/mcproxy/include/proxy/igmp_receiver.hpp
index 5ca5b84..f68c4b6 100644
--- a/mcproxy/include/proxy/igmp_receiver.hpp
+++ b/mcproxy/include/proxy/igmp_receiver.hpp
@@ -52,6 +52,7 @@ private:
     void analyse_packet(struct msghdr* msg, int info_size) override;
 
 public:
+    virtual ~igmp_receiver();
     /**
      * @brief Create an igmp_receiver.
      */
diff --git a/mcproxy/include/proxy/igmp_sender.hpp b/mcproxy/include/proxy/igmp_sender.hpp
index 3e917ea..99aae3d 100644
--- a/mcproxy/include/proxy/igmp_sender.hpp
+++ b/mcproxy/include/proxy/igmp_sender.hpp
@@ -39,6 +39,7 @@ private:
     bool send_igmpv3_query(unsigned int if_index, const timers_values& tv, const addr_storage& gaddr, bool s_flag, const source_list<source>& slist) const;
 
 public:
+    virtual ~igmp_sender();
     igmp_sender(const std::shared_ptr<const interfaces>& interfaces);
 
     bool send_record(unsigned int if_index, mc_filter filter_mode, const addr_storage& gaddr, const source_list<source>& slist) const override;
diff --git a/mcproxy/include/proxy/interfaces.hpp b/mcproxy/include/proxy/interfaces.hpp
index 9bbefd3..2977ac2 100644
--- a/mcproxy/include/proxy/interfaces.hpp
+++ b/mcproxy/include/proxy/interfaces.hpp
@@ -59,7 +59,7 @@ private:
 
 public:
     interfaces(int addr_family, bool reset_reverse_path_filter);
-    ~interfaces();
+    virtual ~interfaces();
 
     bool refresh_network_interfaces();
 
diff --git a/mcproxy/include/proxy/message_queue.hpp b/mcproxy/include/proxy/message_queue.hpp
index 347a616..4e36e78 100644
--- a/mcproxy/include/proxy/message_queue.hpp
+++ b/mcproxy/include/proxy/message_queue.hpp
@@ -51,6 +51,8 @@ private:
     std::condition_variable cond_empty;
 
 public:
+    virtual ~message_queue();
+
     /**
       * @brief Create a message_queue with a maximum size.
       * @param size size of the message_queue.
@@ -88,6 +90,13 @@ public:
     T dequeue(void);
 };
 
+
+template<typename T, typename Compare>
+message_queue<T, Compare>::~message_queue()
+{
+    HC_LOG_TRACE("");
+}
+
 template<typename T, typename Compare>
 message_queue<T, Compare>::message_queue(int size, Compare compare)
     : m_q(compare)
diff --git a/mcproxy/include/proxy/mld_receiver.hpp b/mcproxy/include/proxy/mld_receiver.hpp
index 4eadce4..d84d559 100644
--- a/mcproxy/include/proxy/mld_receiver.hpp
+++ b/mcproxy/include/proxy/mld_receiver.hpp
@@ -46,6 +46,7 @@ private:
     void analyse_packet(struct msghdr* msg, int info_size) override;
 
 public:
+    virtual ~mld_receiver();
     mld_receiver(proxy_instance* pr_i, std::shared_ptr<const mroute_socket> mrt_sock, std::shared_ptr<const interfaces> interfaces, bool in_debug_testing_mode);
 };
 
diff --git a/mcproxy/include/proxy/mld_sender.hpp b/mcproxy/include/proxy/mld_sender.hpp
index 9720f0d..a130564 100644
--- a/mcproxy/include/proxy/mld_sender.hpp
+++ b/mcproxy/include/proxy/mld_sender.hpp
@@ -56,6 +56,7 @@ private:
     bool send_mldv2_query(unsigned int if_index, const timers_values& tv, const addr_storage& gaddr, bool s_flag, const source_list<source>& slist) const;
 
 public:
+    virtual ~mld_sender();
     mld_sender(const std::shared_ptr<const interfaces>& interfaces);
 
     bool send_record(unsigned int if_index, mc_filter filter_mode, const addr_storage& gaddr, const source_list<source>& slist) const override;
diff --git a/mcproxy/include/proxy/routing.hpp b/mcproxy/include/proxy/routing.hpp
index 6c83a60..94506eb 100644
--- a/mcproxy/include/proxy/routing.hpp
+++ b/mcproxy/include/proxy/routing.hpp
@@ -56,9 +56,9 @@ private:
     mutable std::set<unsigned int> m_added_ifs; 
 
 public:
+    virtual ~routing();
     routing(int addr_family, std::shared_ptr<const mroute_socket> mrt_sock, std::shared_ptr<const interfaces> interfaces, int table_number);
 
-    virtual ~routing();
     /**
       * @brief Add a virtual interface to the linux kernel table.
       * @return Return true on success.
diff --git a/mcproxy/include/proxy/simple_membership_aggregation.hpp b/mcproxy/include/proxy/simple_membership_aggregation.hpp
index d4f78db..9bd3783 100644
--- a/mcproxy/include/proxy/simple_membership_aggregation.hpp
+++ b/mcproxy/include/proxy/simple_membership_aggregation.hpp
@@ -97,7 +97,10 @@ private:
     simple_membership_aggregation(group_mem_protocol group_mem_protocol);
 
     friend struct test_membership_aggregation;
+
 public:
+    virtual ~simple_membership_aggregation();
+
     simple_membership_aggregation(rb_rule_matching_type upstream_in_rule_matching_type, const addr_storage& gaddr, const std::shared_ptr<const simple_routing_data>& routing_data, group_mem_protocol group_mem_protocol, const std::shared_ptr<const interface_infos>& interface_infos);
 
     std::pair<mc_filter, const source_list<source>&> get_group_memberships(unsigned int upstream_if_index) const;
diff --git a/mcproxy/include/proxy/simple_routing_data.hpp b/mcproxy/include/proxy/simple_routing_data.hpp
index 0c4d35d..9c55b19 100644
--- a/mcproxy/include/proxy/simple_routing_data.hpp
+++ b/mcproxy/include/proxy/simple_routing_data.hpp
@@ -60,6 +60,7 @@ private:
     unsigned long get_current_packet_count(const addr_storage& gaddr, const addr_storage& saddr);
 
 public:
+    virtual ~simple_routing_data();
     simple_routing_data(group_mem_protocol group_mem_protocol, const std::shared_ptr<const mroute_socket>& mrt_sock);
 
     void set_source(unsigned int if_index, const addr_storage& gaddr, const source& saddr);
diff --git a/mcproxy/include/proxy/simple_routing_management.hpp b/mcproxy/include/proxy/simple_routing_management.hpp
index 6f21b2d..7bcc430 100644
--- a/mcproxy/include/proxy/simple_routing_management.hpp
+++ b/mcproxy/include/proxy/simple_routing_management.hpp
@@ -79,6 +79,7 @@ private:
     void process_membership_aggregation(rb_rule_matching_type rule_matching_type, const addr_storage& gaddr);
 
 public:
+    virtual ~simple_routing_management();
     simple_routing_management(const worker* msg_worker, group_mem_protocol group_mem_protocol, const std::shared_ptr<const mroute_socket>& mrt_sock, const std::shared_ptr<const sender>& sender, const std::shared_ptr<const routing>& routing, const std::shared_ptr<timing>& timing, const std::shared_ptr<const interface_infos>& interface_infos, const std::shared_ptr<const interfaces> interfaces);
 
     void event_new_source(const std::shared_ptr<proxy_msg>& msg) override;
diff --git a/mcproxy/src/parser/configuration.cpp b/mcproxy/src/parser/configuration.cpp
index 4966b58..d1e2701 100644
--- a/mcproxy/src/parser/configuration.cpp
+++ b/mcproxy/src/parser/configuration.cpp
@@ -51,6 +51,12 @@ configuration::configuration(std::string&& test_configuration)
 
 configuration::configuration()
 {
+    HC_LOG_TRACE("");
+}
+
+configuration::~configuration()
+{
+    HC_LOG_TRACE("");
 }
 
 // trim from start
diff --git a/mcproxy/src/parser/interface.cpp b/mcproxy/src/parser/interface.cpp
index 3d64b71..c2f8e27 100644
--- a/mcproxy/src/parser/interface.cpp
+++ b/mcproxy/src/parser/interface.cpp
@@ -215,6 +215,7 @@ const table* global_table_set::get_table(const std::string& table_name) const
     if (it != std::end(m_table_set)) {
         return it->get();
     } else {
+        HC_LOG_ERROR("Table " <<  table_name << " not found.");
         return nullptr;
     }
 }
@@ -274,6 +275,11 @@ std::string get_rb_filter_type_name(rb_filter_type ft)
     return name_map[ft];
 }
 
+rule_binding::~rule_binding()
+{
+    HC_LOG_TRACE("");
+}
+
 rule_binding::rule_binding(const std::string& instance_name, rb_interface_type interface_type, const std::string& if_name, rb_interface_direction filter_direction, rb_filter_type filter_type, std::unique_ptr<table> filter_table)
     : m_rule_binding_type(RBT_FILTER)
     , m_instance_name(instance_name)
@@ -454,6 +460,11 @@ interface::interface(const std::string& if_name)
     HC_LOG_TRACE("");
 }
 
+interface::~interface()
+{
+    HC_LOG_TRACE("");
+}
+
 std::string interface::get_if_name() const
 {
     HC_LOG_TRACE("");
diff --git a/mcproxy/src/parser/parser.cpp b/mcproxy/src/parser/parser.cpp
index 81e9eab..9681f31 100644
--- a/mcproxy/src/parser/parser.cpp
+++ b/mcproxy/src/parser/parser.cpp
@@ -34,6 +34,10 @@ parser::parser(unsigned int current_line, const std::string& cmd)
     get_next_token();
 }
 
+parser::~parser(){
+    HC_LOG_TRACE("");
+}
+
 parser_type parser::get_parser_type()
 {
     if (m_current_token.get_type() == TT_PROTOCOL) {
diff --git a/mcproxy/src/proxy/check_if.cpp b/mcproxy/src/proxy/check_if.cpp
index 5b598d6..ab6106b 100644
--- a/mcproxy/src/proxy/check_if.cpp
+++ b/mcproxy/src/proxy/check_if.cpp
@@ -32,6 +32,11 @@ check_if::check_if()
     HC_LOG_TRACE("");
 }
 
+check_if::~check_if()
+{
+    HC_LOG_TRACE("");
+}
+
 std::vector<int> check_if::init(std::vector<int>& check_lst, int addr_family)
 {
     HC_LOG_TRACE("");
diff --git a/mcproxy/src/proxy/check_kernel.cpp b/mcproxy/src/proxy/check_kernel.cpp
index 8d160b6..c7d88fb 100644
--- a/mcproxy/src/proxy/check_kernel.cpp
+++ b/mcproxy/src/proxy/check_kernel.cpp
@@ -30,6 +30,12 @@
 #include <unistd.h>
 #include <netinet/in.h>
 
+
+check_kernel::~check_kernel()
+{
+    HC_LOG_TRACE("");
+}
+
 void check_kernel::check_kernel_features()
 {
     using namespace std;
diff --git a/mcproxy/src/proxy/igmp_receiver.cpp b/mcproxy/src/proxy/igmp_receiver.cpp
index cc6b35e..9c19017 100644
--- a/mcproxy/src/proxy/igmp_receiver.cpp
+++ b/mcproxy/src/proxy/igmp_receiver.cpp
@@ -33,44 +33,44 @@
 
 #ifdef DEBUG_MODE
 extern "C" {
-void print_buf(const unsigned char * buf, unsigned int size)
-{
+    void print_buf(const unsigned char * buf, unsigned int size)
+    {
 
-    for (unsigned int i = 0; i < size; i += 16) {
-        for (unsigned int j = i; j < 16 + i && j < size; j++) {
+        for (unsigned int i = 0; i < size; i += 16) {
+            for (unsigned int j = i; j < 16 + i && j < size; j++) {
 
-            if (j % 8 == 0 && j % 16 != 0 && j != 0) {
-                printf(" ");
-            }
+                if (j % 8 == 0 && j % 16 != 0 && j != 0) {
+                    printf(" ");
+                }
 
-            if (buf[j] == 0) {
-                printf("00 ");
-            } else if (buf[j] < 16 && buf[j] > 0) {
-                printf("0%X ", buf[j]);
-            } else {
-                printf("%X ", buf[j]);
+                if (buf[j] == 0) {
+                    printf("00 ");
+                } else if (buf[j] < 16 && buf[j] > 0) {
+                    printf("0%X ", buf[j]);
+                } else {
+                    printf("%X ", buf[j]);
+                }
             }
-        }
 
-        printf("   ");
+            printf("   ");
 
-        for (unsigned int j = i; j < 16 + i && j < size; j++) {
+            for (unsigned int j = i; j < 16 + i && j < size; j++) {
 
-            if (j % 8 == 0 && j % 16 != 0 && j != 0) {
-                printf(" ");
-            }
+                if (j % 8 == 0 && j % 16 != 0 && j != 0) {
+                    printf(" ");
+                }
 
-            if (buf[j] == 0) {
-                printf(".");
-            } else {
-                printf("%c", buf[j]);
+                if (buf[j] == 0) {
+                    printf(".");
+                } else {
+                    printf("%c", buf[j]);
+                }
             }
-        }
 
+            printf("\n");
+        }
         printf("\n");
     }
-    printf("\n");
-}
 }
 #endif /* DEBUG_MODE */
 
@@ -81,6 +81,11 @@ igmp_receiver::igmp_receiver(proxy_instance* pr_i, const std::shared_ptr<const m
     start();
 }
 
+igmp_receiver::~igmp_receiver()
+{
+    HC_LOG_TRACE("");
+}
+
 int igmp_receiver::get_iov_min_size()
 {
     HC_LOG_TRACE("");
@@ -167,7 +172,7 @@ void igmp_receiver::analyse_packet(struct msghdr* msg, int)
                 HC_LOG_DEBUG("\tleave group received");
                 m_proxy_instance->add_msg(std::make_shared<group_record_msg>(if_index, CHANGE_TO_INCLUDE_MODE, gaddr, source_list<source>(), IGMPv2));
             } else {
-                HC_LOG_ERROR("unkown igmp type: " << igmp_hdr->igmp_type); 
+                HC_LOG_ERROR("unkown igmp type: " << igmp_hdr->igmp_type);
             }
         } else if (igmp_hdr->igmp_type == IGMP_V3_MEMBERSHIP_REPORT) {
             HC_LOG_DEBUG("IGMP_V3_MEMBERSHIP_REPORT received");
diff --git a/mcproxy/src/proxy/igmp_sender.cpp b/mcproxy/src/proxy/igmp_sender.cpp
index d428adb..8f8d3c4 100644
--- a/mcproxy/src/proxy/igmp_sender.cpp
+++ b/mcproxy/src/proxy/igmp_sender.cpp
@@ -46,6 +46,11 @@ igmp_sender::igmp_sender(const std::shared_ptr<const interfaces>& interfaces): s
     }
 }
 
+igmp_sender::~igmp_sender()
+{
+    HC_LOG_TRACE("");
+}
+
 bool igmp_sender::send_record(unsigned int if_index, mc_filter filter_mode, const addr_storage& gaddr, const source_list<source>& slist) const
 {
     HC_LOG_TRACE("");
diff --git a/mcproxy/src/proxy/interfaces.cpp b/mcproxy/src/proxy/interfaces.cpp
index 093ad97..3767ed6 100644
--- a/mcproxy/src/proxy/interfaces.cpp
+++ b/mcproxy/src/proxy/interfaces.cpp
@@ -50,7 +50,6 @@ interfaces::interfaces(int addr_family, bool reset_reverse_path_filter)
 interfaces::~interfaces()
 {
     HC_LOG_TRACE("");
-
 }
 
 bool interfaces::add_interface(const std::string& if_name)
diff --git a/mcproxy/src/proxy/mld_receiver.cpp b/mcproxy/src/proxy/mld_receiver.cpp
index 31b183d..5b404f2 100644
--- a/mcproxy/src/proxy/mld_receiver.cpp
+++ b/mcproxy/src/proxy/mld_receiver.cpp
@@ -49,6 +49,11 @@ mld_receiver::mld_receiver(proxy_instance* pr_i, const std::shared_ptr<const mro
     start();
 }
 
+mld_receiver::~mld_receiver()
+{
+    HC_LOG_TRACE("");
+}
+
 int mld_receiver::get_iov_min_size()
 {
     HC_LOG_TRACE("");
diff --git a/mcproxy/src/proxy/mld_sender.cpp b/mcproxy/src/proxy/mld_sender.cpp
index 7dbc3ee..5ea42ed 100644
--- a/mcproxy/src/proxy/mld_sender.cpp
+++ b/mcproxy/src/proxy/mld_sender.cpp
@@ -48,6 +48,11 @@ mld_sender::mld_sender(const std::shared_ptr<const interfaces>& interfaces): sen
     }
 }
 
+mld_sender::~mld_sender()
+{
+    HC_LOG_TRACE("");
+}
+
 bool mld_sender::send_record(unsigned int if_index, mc_filter filter_mode, const addr_storage& gaddr, const source_list<source>& slist) const
 {
     HC_LOG_TRACE("");
diff --git a/mcproxy/src/proxy/sender.cpp b/mcproxy/src/proxy/sender.cpp
index f7de539..a424c33 100644
--- a/mcproxy/src/proxy/sender.cpp
+++ b/mcproxy/src/proxy/sender.cpp
@@ -161,5 +161,4 @@ bool sender::send_mc_addr_and_src_specific_query(unsigned int, const timers_valu
 sender::~sender()
 {
     HC_LOG_TRACE("");
-
 }
diff --git a/mcproxy/src/proxy/simple_membership_aggregation.cpp b/mcproxy/src/proxy/simple_membership_aggregation.cpp
index d1d6ac6..2c03433 100644
--- a/mcproxy/src/proxy/simple_membership_aggregation.cpp
+++ b/mcproxy/src/proxy/simple_membership_aggregation.cpp
@@ -22,6 +22,8 @@
 
 #include "include/hamcast_logging.h"
 #include "include/proxy/simple_membership_aggregation.hpp"
+
+//is this necessary?????????????
 #include "include/proxy/proxy_instance.hpp"
 #include "include/proxy/simple_routing_data.hpp"
 
@@ -269,8 +271,8 @@ mem_source_state& simple_membership_aggregation::disjoin_group_memberships(mem_s
         if (merge_from_mc_group.m_mc_filter == INCLUDE_MODE) {
             merge_to_mc_group.m_source_list += merge_from_mc_group.m_source_list;
         } else if (merge_from_mc_group.m_mc_filter == EXCLUDE_MODE) {
+            merge_to_mc_group.m_source_list = merge_from_mc_group.m_source_list - merge_to_mc_group.m_source_list;
             merge_to_mc_group.m_mc_filter = INCLUDE_MODE;
-            merge_to_mc_group.m_source_list -= merge_from_mc_group.m_source_list;
         } else {
             HC_LOG_ERROR("unknown mc filter mode in parameter merge_from_mc_group");
             set_to_block_all(merge_to_mc_group);
@@ -299,7 +301,7 @@ filter_source_state simple_membership_aggregation::get_source_filter(rb_interfac
 {
     HC_LOG_TRACE("");
     rb_filter_type tmp_ft = iface->get_filter_type(if_direction);
-    const source_list<source>& tmp_srcl = get_source_list(iface->get_saddr_set(ID_IN, input_if_name, gaddr, explicit_if_name));
+    source_list<source> tmp_srcl = get_source_list(iface->get_saddr_set(if_direction, input_if_name, gaddr, explicit_if_name));
     return filter_source_state(tmp_ft, tmp_srcl);
 }
 
@@ -318,6 +320,7 @@ std::map<unsigned int, mem_source_state> simple_membership_aggregation::get_merg
         auto filter = get_source_filter(ID_OUT, input_if_name, dstream.second.m_interface, gaddr, explicit_if_name);
         auto gmem_src = get_mem_source_state(dstream.second.m_querier, gaddr);
         merge_memberships_filter(gmem_src, filter); //(p1)
+        std::cout << "get_filtered_mem: " <<  dstream.second.m_interface->get_if_name() << " " << gmem_src.to_string() << std::endl;
         return gmem_src;
     };
 
@@ -329,14 +332,17 @@ std::map<unsigned int, mem_source_state> simple_membership_aggregation::get_merg
         merge_group_memberships(downstreams_merge_empty_if, get_filtered_mem(dstream, "", false)); //(p2)
     }
 
+    std::cout << "downstreams_merge_empty_if: "  << downstreams_merge_empty_if.to_string() << std::endl;
+
     for (auto & ustream : m_ii->m_upstreams) {
         mem_source_state if_specific_merge;
         std::string uif_name = ustream.m_interface->get_if_name();
         for (auto & dstream : m_ii->m_downstreams) {
+            //get_filtered_mem --> get_mem_source_state is called twice ??????
             merge_group_memberships(if_specific_merge, get_filtered_mem(dstream, uif_name, true)); //(p2)
         }
         merge_group_memberships(if_specific_merge, downstreams_merge_empty_if);
-        downstreams_mem_merge.insert(std::make_pair(ustream.m_if_index, std::move(if_specific_merge)));
+        downstreams_mem_merge.insert({ustream.m_if_index, std::move(if_specific_merge)});
     }
 
     return downstreams_mem_merge;
@@ -346,14 +352,18 @@ std::map<unsigned int, mem_source_state> simple_membership_aggregation::get_merg
 void simple_membership_aggregation::process_upstream_in_first(const addr_storage& gaddr)
 {
     HC_LOG_TRACE("");
-    std::map<unsigned int, mem_source_state> downstreams_mem_merge = get_merged_mem(gaddr); //(p3) and result
+    std::cout << "in process_upstream_in_first" << std::endl;
+    std::map<unsigned int, mem_source_state> upstream_mem_merge = get_merged_mem(gaddr); //(p3) and result
+    for(auto & e: upstream_mem_merge){
+        std::cout << "uif: " << e.first << " " << e.second.to_string() << std::endl;
+    }
 
     mem_source_state disjoiner;
     for (auto & ustream : m_ii->m_upstreams) {
-        auto d_mem_merge_it = downstreams_mem_merge.find(ustream.m_if_index);
-        if (d_mem_merge_it == downstreams_mem_merge.end()) {
+        auto d_mem_merge_it = upstream_mem_merge.find(ustream.m_if_index);
+        if (d_mem_merge_it == upstream_mem_merge.end()) {
             HC_LOG_ERROR("upstream interface index (" << ustream.m_if_index << ") not found");
-            downstreams_mem_merge.erase(d_mem_merge_it);
+            upstream_mem_merge.erase(d_mem_merge_it);
             continue;
         }
 
@@ -365,13 +375,13 @@ void simple_membership_aggregation::process_upstream_in_first(const addr_storage
         merge_group_memberships(disjoiner, d_mem_merge);
     }
 
-    m_data = std::move(downstreams_mem_merge);
+    m_data = std::move(upstream_mem_merge);
 }
 
 
 void simple_membership_aggregation::process_upstream_in_mutex(const addr_storage& gaddr)
 {
-    std::map<unsigned int, mem_source_state> downstreams_mem_merge = get_merged_mem(gaddr); //(p3) and result
+    std::map<unsigned int, mem_source_state> upstream_mem_merge = get_merged_mem(gaddr); //(p3) and result
     std::map<unsigned int, mem_source_state> ustream_recvd_source_map;
     mem_source_state dstream_recvd_sources;
 
@@ -379,7 +389,7 @@ void simple_membership_aggregation::process_upstream_in_mutex(const addr_storage
 
     //1.) convert m_routing_data->get_interface_map(gaddr) to up- and downstream_recvd_source;
     for (auto & ustream : m_ii->m_upstreams) {
-        ustream_recvd_source_map.insert(std::make_pair(ustream.m_if_index, mem_source_state(INCLUDE_MODE, source_list<source> {})));
+        ustream_recvd_source_map.insert({ustream.m_if_index, mem_source_state(INCLUDE_MODE, source_list<source> {})});
     }
 
     for (auto & e : tmp_if_map) {
@@ -397,10 +407,10 @@ void simple_membership_aggregation::process_upstream_in_mutex(const addr_storage
 
     //2.) disjoin and merge with interface filters
     for (auto & ustream : m_ii->m_upstreams) {
-        auto d_mem_merge_it = downstreams_mem_merge.find(ustream.m_if_index);
-        if (d_mem_merge_it == downstreams_mem_merge.end()) {
-            HC_LOG_ERROR("upstream interface index (" << ustream.m_if_index << ") in downstreams_mem_merge not found");
-            downstreams_mem_merge.erase(d_mem_merge_it);
+        auto d_mem_merge_it = upstream_mem_merge.find(ustream.m_if_index);
+        if (d_mem_merge_it == upstream_mem_merge.end()) {
+            HC_LOG_ERROR("upstream interface index (" << ustream.m_if_index << ") in upstream_mem_merge not found");
+            upstream_mem_merge.erase(d_mem_merge_it);
             continue;
         }
 
@@ -418,7 +428,7 @@ void simple_membership_aggregation::process_upstream_in_mutex(const addr_storage
         merge_memberships_filter(d_mem_merge, filter);
     }
 
-    m_data = std::move(downstreams_mem_merge);
+    m_data = std::move(upstream_mem_merge);
 }
 
 std::pair<mc_filter, const source_list<source>&> simple_membership_aggregation::get_group_memberships(unsigned int upstream_if_index) const
@@ -426,185 +436,28 @@ std::pair<mc_filter, const source_list<source>&> simple_membership_aggregation::
     HC_LOG_TRACE("");
     auto tmp_it = m_data.find(upstream_if_index);
     if (tmp_it != m_data.end()) {
-        return std::make_pair(tmp_it->second.m_mc_filter, tmp_it->second.m_source_list);
+        return {tmp_it->second.m_mc_filter, tmp_it->second.m_source_list};
     } else {
         HC_LOG_ERROR("upstream if index " << upstream_if_index << " not found");
-        return std::make_pair(INCLUDE_MODE, m_fallback_list);
+        return {INCLUDE_MODE, m_fallback_list};
     }
 }
 
-//void simple_membership_aggregation::process_upstream_in_first(const addr_storage& gaddr)
-//{
-//HC_LOG_TRACE("");
-
-//state_list init_sstate_list;
-//for (auto & downs_e : m_ii->m_downstreams) {
-//init_sstate_list.push_back(state_pair(source_state(downs_e.second.m_querier->get_group_membership_infos(gaddr)), downs_e.second.m_interface));
-//}
-
-////init and fill database
-//for (auto & upstr_e : m_ii->m_upstreams) {
-
-//state_list tmp_sstate_list;
-
-//for (auto & cs : init_sstate_list) {
-
-//source_state tmp_sstate;
-//tmp_sstate.m_mc_filter = cs.first.m_mc_filter;
-
-////sort out all unwanted sources
-//for (auto source_it = cs.first.m_source_list.begin(); source_it != cs.first.m_source_list.end();) {
-
-////downstream out TODO: old code match
-////if (!cs.second->match_output_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) {
-////source_it = cs.first.m_source_list.erase(source_it);
-////continue;
-////}
-
-////upstream in TODO: old code match
-////if (!upstr_e.m_interface->match_input_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) {
-////tmp_sstate.m_source_list.insert(*source_it);
-////source_it = cs.first.m_source_list.erase(source_it);
-////continue;
-////}
-
-//++source_it;
-//}
-
-//if (!tmp_sstate.m_source_list.empty()) {
-//tmp_sstate_list.push_back(state_pair(tmp_sstate, cs.second));
-//}
-
-//}
-
-//std::list<source_state> ret_source_list;
-//for (auto & e : init_sstate_list) {
-//ret_source_list.push_back(std::move(e.first));
-//}
-//m_data.push_back(std::pair<unsigned int, std::list<source_state>>(upstr_e.m_if_index, std::move(ret_source_list)));
-//init_sstate_list = std::move(tmp_sstate_list);
-//}
-
-//}
-
-//void simple_membership_aggregation::process_upstream_in_mutex(const addr_storage& gaddr)
-//{
-//HC_LOG_TRACE("");
-
-//state_list ref_sstate_list;
-
-//for (auto & downs_e : m_ii->m_downstreams) {
-//ref_sstate_list.push_back(state_pair(source_state(downs_e.second.m_querier->get_group_membership_infos(gaddr)), downs_e.second.m_interface));
-//}
-////print(ref_sstate_list);
-
-////init and fill database
-//for (auto & upstr_e : m_ii->m_upstreams) {
-
-//std::list<source_state> tmp_sstate_list;
-
-////for every downstream interface
-//for (auto cs_it = ref_sstate_list.begin(); cs_it != ref_sstate_list.end();) {
-
-//source_state tmp_sstate;
-//tmp_sstate.m_mc_filter = cs_it->first.m_mc_filter;
-
-////sort out all unwanted sources
-//for (auto source_it = cs_it->first.m_source_list.begin(); source_it != cs_it->first.m_source_list.end();) {
-
-////downstream out TODO: old code match
-////if (!cs_it->second->match_output_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) {
-////++source_it;
-////continue;
-////}
-
-////upstream in TODO: old code match
-////if (!upstr_e.m_interface->match_input_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) {
-////++source_it;
-////continue;
-////}
-
-//const std::map<addr_storage, unsigned int>& available_sources = m_routing_data->get_interface_map(gaddr);
-//auto av_src_it = available_sources.find(source_it->saddr);
-//if (av_src_it != available_sources.end()) {
-
-//if (m_ii->is_upstream(av_src_it->second)) {
-//tmp_sstate.m_source_list.insert(*source_it);
-//}
-
-////clean this->m_data
-//for (auto & data_e : m_data) {
-//for (auto sstate_it = data_e.second.begin(); sstate_it != data_e.second.end();) {
-
-//auto s_it = sstate_it->m_source_list.find(*source_it);
-//if (s_it != sstate_it->m_source_list.end()) {
-//sstate_it->m_source_list.erase(s_it);
-//}
-
-//if (sstate_it->m_source_list.empty()) {
-//sstate_it = data_e.second.erase(sstate_it);
-//continue;
-//}
-//++sstate_it;
-//}
-//}
-
-//source_it = cs_it->first.m_source_list.erase(source_it);
-//continue;
-
-//} else {
-//tmp_sstate.m_source_list.insert(*source_it);
-//}
-
-//++source_it;
-//}
-
-//if (!tmp_sstate.m_source_list.empty()) {
-//tmp_sstate_list.push_back(tmp_sstate);
-//}
-
-//if (cs_it->first.m_source_list.empty()) {
-//cs_it = ref_sstate_list.erase(cs_it);
-//continue;
-//}
-
-//++cs_it;
-//}
-
-//m_data.push_back(std::pair<unsigned int, std::list<source_state>>(upstr_e.m_if_index, std::move(tmp_sstate_list)));
-//}
-
-//}
-
-//std::pair<mc_filter, const source_list<source>&> simple_membership_aggregation::get_group_memberships(unsigned int upstream_if_index)
-//{
-//HC_LOG_TRACE("");
-
-//source_state result;
-//auto data_it = m_data.begin();
-//if (data_it != m_data.end() && data_it->first != upstream_if_index) {
-//HC_LOG_ERROR("unexpected upstream interface " << interfaces::get_if_name(upstream_if_index));
-//return result.get_mc_source_list();
-//}
-
-//for (auto & e : data_it->second) {
-////TODO
-////merge_membership_infos(result, e);
-//}
-
-//m_data.pop_front();
-//return result.get_mc_source_list();
-//}
+simple_membership_aggregation::~simple_membership_aggregation()
+{
+    HC_LOG_TRACE("");
+}
 
 std::string simple_membership_aggregation::to_string() const
 {
     std::ostringstream s;
-    //for (auto & e : m_data) {
-    //s << interfaces::get_if_name(e.first) <<  ":";
-    //for (auto & f : e.second) {
-    //s << std::endl << indention(f.to_string());
-    //}
-    //}
+    for (auto & e : m_ii->m_upstreams) {
+        s <<  e.m_interface->get_if_name() << "(" << e.m_if_index << ")" << ":";
+        auto smem_it = m_data.find(e.m_if_index);
+        if (smem_it != m_data.end()) {
+            s << std::endl << indention(smem_it->second.to_string());
+        }
+    }
     return s.str();
 }
 
diff --git a/mcproxy/src/proxy/simple_routing_data.cpp b/mcproxy/src/proxy/simple_routing_data.cpp
index b05e099..a193c1b 100644
--- a/mcproxy/src/proxy/simple_routing_data.cpp
+++ b/mcproxy/src/proxy/simple_routing_data.cpp
@@ -33,6 +33,11 @@ simple_routing_data::simple_routing_data(group_mem_protocol group_mem_protocol,
     HC_LOG_TRACE("");
 }
 
+simple_routing_data::~simple_routing_data()
+{
+    HC_LOG_TRACE("");
+}
+
 unsigned long simple_routing_data::get_current_packet_count(const addr_storage& gaddr, const addr_storage& saddr)
 {
     HC_LOG_TRACE("");
@@ -132,10 +137,10 @@ const source_list<source>& simple_routing_data::get_available_sources(const addr
 
     auto gaddr_it = m_data.find(gaddr);
     if (gaddr_it != std::end(m_data)) {
-        return gaddr_it->second.m_source_list;       
-    }else{
+        return gaddr_it->second.m_source_list;
+    } else {
         static source_list<source> result;
-        result.clear(); 
+        result.clear();
         return result;;
     }
 }
@@ -163,11 +168,11 @@ const std::map<addr_storage, unsigned int>& simple_routing_data::get_interface_m
 {
     HC_LOG_TRACE("");
     auto it = m_data.find(gaddr);
-    if(it != std::end(m_data)){
-        return it->second.m_if_map; 
-    }else{
+    if (it != std::end(m_data)) {
+        return it->second.m_if_map;
+    } else {
         const static std::map<addr_storage, unsigned int> result;
-        return result; 
+        return result;
     }
 }
 
diff --git a/mcproxy/src/proxy/simple_routing_management.cpp b/mcproxy/src/proxy/simple_routing_management.cpp
index 6337999..1c1a32a 100644
--- a/mcproxy/src/proxy/simple_routing_management.cpp
+++ b/mcproxy/src/proxy/simple_routing_management.cpp
@@ -50,6 +50,11 @@ simple_routing_management::simple_routing_management(const worker* msg_worker, g
     HC_LOG_TRACE("");
 }
 
+simple_routing_management::~simple_routing_management()
+{
+    HC_LOG_TRACE("");
+}
+
 std::chrono::seconds simple_routing_management::get_source_life_time()
 {
     HC_LOG_TRACE("");
diff --git a/mcproxy/testing/test_membership_aggregation.hpp b/mcproxy/testing/test_membership_aggregation.hpp
index 0bbd07b..b3a5111 100644
--- a/mcproxy/testing/test_membership_aggregation.hpp
+++ b/mcproxy/testing/test_membership_aggregation.hpp
@@ -203,23 +203,32 @@ struct test_membership_aggregation {
         UT_CHECK(check_disjoin_group_memberships(in_a, in_b, mss(INCLUDE_MODE, sl {s2})));
         UT_CHECK(check_disjoin_group_memberships(in_a, ex_b, mss(INCLUDE_MODE, sl {s1})));
         UT_CHECK(check_disjoin_group_memberships(ex_a, in_b, mss(EXCLUDE_MODE, sl {s1, s2, s3})));
-        UT_CHECK(check_disjoin_group_memberships(ex_a, ex_b, mss(INCLUDE_MODE, sl {s2})));
+        UT_CHECK(check_disjoin_group_memberships(ex_a, ex_b, mss(INCLUDE_MODE, sl {s3})));
 
         UT_SUMMARY;
     }
 
-    simple_membership_aggregation get_simple_membership_aggregation_mockup(std::string&& test_conf, std::shared_ptr<group_record_msg> grecord_for_qd4, std::shared_ptr<group_record_msg> grecord_for_qd5, const addr_storage& gaddr, group_mem_protocol gmp, std::list <std::pair<unsigned int, addr_storage>> routing_data) {
+    simple_membership_aggregation get_simple_membership_aggregation_mockup(std::string&& test_conf, std::shared_ptr<group_record_msg> grecord_for_qd4, std::shared_ptr<group_record_msg> grecord_for_qd5, std::shared_ptr<group_record_msg> grecord_for_qd6, const addr_storage& gaddr, group_mem_protocol gmp, std::list <std::pair<unsigned int, addr_storage>> routing_data) {
+        HC_LOG_TRACE("");
+        UT_INITIALISATION;
+
         std::string test_conf_basic = {" \
 protocol IGMPv3; \n \
-pinstance pinst: u1 u2 u3 ==> d4 d5; \n \
-#interface index: 1  2  3 ==>  4  5 \n \
+pinstance pinst: u1 u2 u3 ==> d4 d5 d6; \n \
+#interface index: 1  2  3 ==>  4  5  6  \n \
 #interface prio:  1  2  3 ==> ...   \n \
 "
                                       };
         test_conf_basic += test_conf;
+        std::string tmp_config = test_conf_basic;
+        std::unique_ptr<configuration> c;
+        try {
+            c = std::unique_ptr<configuration>(new configuration(std::move(test_conf_basic)));
+        } catch (const char* e) {
+            UT_FAIL("Incorrect configuration(see logfile for detailed info): " << std::endl << tmp_config);
+        }
 
-        configuration c(std::move(test_conf_basic));
-        auto inst_def_set = c.get_inst_def_set();
+        auto inst_def_set = c->get_inst_def_set();
         auto pinstance = *(inst_def_set.begin());
 
         auto upstreams = pinstance->get_upstreams();
@@ -256,6 +265,9 @@ pinstance pinst: u1 u2 u3 ==> d4 d5; \n \
         std::unique_ptr<querier> qd5(new querier(IGMPv3, 5, dtiming, [](unsigned int, const addr_storage&) {}));
         qd5->receive_record(grecord_for_qd5);
         ii->m_downstreams.insert(std::make_pair(5, downstream_infos(std::move(qd5), *(++downstreams.begin()))));
+        std::unique_ptr<querier> qd6(new querier(IGMPv3, 6, dtiming, [](unsigned int, const addr_storage&) {}));
+        qd6->receive_record(grecord_for_qd6);
+        ii->m_downstreams.insert(std::make_pair(6, downstream_infos(std::move(qd6), *(++(++downstreams.begin())))));
 
         if (global_settings.size() >= 1) {
             auto gs_it1 = global_settings.begin();
@@ -295,7 +307,7 @@ pinstance pinst: u1 u2 u3 ==> d4 d5; \n \
 
         std::string test_conf = {" \
 #protocol IGMPv3; DO NOT USE!!! \n \
-#pinstance pinst: u1 u2 u3 ==> d4 d5; DO NOT USE!!! \n \
+#pinstance pinst: u1 u2 u3 ==> d4 d5 d6; DO NOT USE!!! \n \
 \n \
 pinstance pinst upstream * in rulematching mutex 10; \n \
 pinstance pinst upstream * out rulematching first; \n \
@@ -318,12 +330,13 @@ pinstance pinst downstream d5 out whitelist table {(*|*)}; \n \
                                 };
 
         source_list<source> slist_d4 {addr_storage("1.1.1.1")};
-        mcast_addr_record_type mode_d4 = MODE_IS_INCLUDE;
-        auto grecord_for_qd4 = std::make_shared<group_record_msg>(4, mode_d4, gaddr, std::move(slist_d4), gmp);
+        auto grecord_for_qd4 = std::make_shared<group_record_msg>(4, MODE_IS_INCLUDE, gaddr, std::move(slist_d4), gmp);
 
         source_list<source> slist_d5 {addr_storage("2.2.2.2")};
-        mcast_addr_record_type mode_d5 = MODE_IS_EXCLUDE;
-        auto grecord_for_qd5 = std::make_shared<group_record_msg>(5, mode_d5, gaddr, std::move(slist_d5), gmp);
+        auto grecord_for_qd5 = std::make_shared<group_record_msg>(5, MODE_IS_EXCLUDE, gaddr, std::move(slist_d5), gmp);
+
+        source_list<source> slist_d6 {addr_storage("3.3.3.3")};
+        auto grecord_for_qd6 = std::make_shared<group_record_msg>(6, MODE_IS_EXCLUDE, gaddr, std::move(slist_d6), gmp);
 
         std::list < std::pair<unsigned int, addr_storage>> routing_data {
             std::make_pair<unsigned int, addr_storage>(1, addr_storage("3.3.3.3")),
@@ -331,15 +344,15 @@ pinstance pinst downstream d5 out whitelist table {(*|*)}; \n \
             std::make_pair<unsigned int, addr_storage>(2, addr_storage("5.5.5.5"))
         };
 
-        auto sma = get_simple_membership_aggregation_mockup(std::move(test_conf), grecord_for_qd4, grecord_for_qd5, gaddr, gmp, routing_data);
+        auto sma = get_simple_membership_aggregation_mockup(std::move(test_conf), grecord_for_qd4, grecord_for_qd5, grecord_for_qd6, gaddr, gmp, routing_data);
 
-        UT_CHECK(sma.m_routing_data->get_available_sources(gaddr) == (source_list<source>{addr_storage("3.3.3.3"), addr_storage("4.4.4.4"), addr_storage("5.5.5.5")}));
+        UT_CHECK(sma.m_routing_data->get_available_sources(gaddr) == (source_list<source> {addr_storage("3.3.3.3"), addr_storage("4.4.4.4"), addr_storage("5.5.5.5")}));
 
         UT_CHECK(sma.m_group_mem_protocol == IGMPv3);
 
         auto& if_infos = sma.m_ii;
         UT_CHECK(if_infos->m_upstreams.size() == 3);
-        UT_CHECK(if_infos->m_downstreams.size() == 2);
+        UT_CHECK(if_infos->m_downstreams.size() == 3);
 
         UT_CHECK(if_infos->m_upstream_input_rule->get_rule_binding_type() == RBT_RULE_MATCHING);
         UT_CHECK(if_infos->m_upstream_input_rule->get_interface_direction() == ID_IN);
@@ -372,9 +385,11 @@ pinstance pinst downstream d5 out whitelist table {(*|*)}; \n \
 
         auto& d4 = *(if_infos->m_downstreams.begin());
         auto& d5 = *(++if_infos->m_downstreams.begin());
+        auto& d6 = *(++(++if_infos->m_downstreams.begin()));
 
         UT_CHECK(d4.second.m_interface->get_if_name().compare("d4") == 0);
         UT_CHECK(d5.second.m_interface->get_if_name().compare("d5") == 0);
+        UT_CHECK(d6.second.m_interface->get_if_name().compare("d6") == 0);
 
         UT_CHECK(d4.second.m_interface->get_filter_type(ID_IN) == FT_WHITELIST);
         UT_CHECK(d4.second.m_interface->get_filter_type(ID_OUT) == FT_BLACKLIST);
@@ -382,52 +397,223 @@ pinstance pinst downstream d5 out whitelist table {(*|*)}; \n \
         UT_CHECK(d5.second.m_interface->get_filter_type(ID_IN) == FT_BLACKLIST);
         UT_CHECK(d5.second.m_interface->get_filter_type(ID_OUT) == FT_WHITELIST);
 
+        UT_CHECK(d6.second.m_interface->get_filter_type(ID_IN) == FT_BLACKLIST);
+        UT_CHECK(d6.second.m_interface->get_filter_type(ID_OUT) == FT_BLACKLIST);
+
         UT_CHECK(d4.second.m_querier->get_group_membership_infos(gaddr).first == INCLUDE_MODE);
         UT_CHECK(d4.second.m_querier->get_group_membership_infos(gaddr).second == source_list<source> {addr_storage("1.1.1.1")});
 
         UT_CHECK(d5.second.m_querier->get_group_membership_infos(gaddr).first == EXCLUDE_MODE);
         UT_CHECK(d5.second.m_querier->get_group_membership_infos(gaddr).second == source_list<source> {addr_storage("2.2.2.2")});
 
+        UT_CHECK(d6.second.m_querier->get_group_membership_infos(gaddr).first == EXCLUDE_MODE);
+        UT_CHECK(d6.second.m_querier->get_group_membership_infos(gaddr).second == source_list<source> {addr_storage("3.3.3.3")});
+
         UT_SUMMARY;
     }
 
 
-    test_status test_first_mutex_aggregation() {
+    test_status test_simple_membership_aggregation_first_whitelist() {
         HC_LOG_TRACE("");
         UT_INITIALISATION;
 
         addr_storage gaddr("239.99.99.99");
         group_mem_protocol gmp = IGMPv3;
 
+        using slist = source_list<source>;
+        using addr = addr_storage;
+
         std::string test_conf = {" \
 #protocol IGMPv3; DO NOT USE!!! \n \
-#pinstance pinst: u1 u2 u3 ==> d4 d5; DO NOT USE!!! \n \
-\n \
-\n \
-#table random_stuff { \n \
-#   yyy(239.1.1.1| 1.1.1.1) \n \
-#}; \n \
-\n \
+#pinstance pinst: u1 u2 u3 ==> d4 d5 d6; DO NOT USE!!! \n \
+#interface index: 1  2  3 ==>  4  5  6 \n \
+#interface prio:  1  2  3 ==> ...      \n \
+ \n \
+table tu1 { \n \
+    (239.99.99.99 | 4.4.4.4) #(a) \n \
+    (239.99.99.99 | 16.16.16.16) #(b) \n \
+}; \n \
+ \n \
+table tu2 { \n \
+    u2 (239.99.99.99 | 5.5.5.5) #(a) \n \
+    (239.99.99.99 | 14.14.14.14) #(b) \n \
+    (239.99.99.99 | 15.15.15.15) #(b) \n \
+}; \n \
+ \n \
+table tu3 { \n \
+#   (239.99.99.99 | 6.6.6.6) #a) block 6.6.6.6 \n \
+    (239.99.99.99 | 17.17.17.17) #(b) \n \
+    (239.99.99.99 | 24.24.24.24) #(c) \n \
+}; \n \
+ \n \
+table td4 { \n \
+    u1 (239.99.99.99 | 4.4.4.4) #(a) \n \
+    (239.99.99.99 | 14.14.14.14) #(b) \n \
+    (239.99.99.99 | 24.24.24.24) #(c) \n \
+    (239.99.99.99 | 25.25.25.25) #(c) \n \
+}; \n \
+ \n \
+table td5 { \n \
+    u2 (239.99.99.99 | 5.5.5.5) #(a) \n \
+    (239.99.99.99 | 15.15.15.15) #(b) \n \
+}; \n \
+ \n \
+table td6 { \n \
+   u3 (239.99.99.99 | 6.6.6.6) #(a) \n \
+    (239.99.99.99 | 16.16.16.16) #(b) \n \
+    (239.99.99.99 | 17.17.17.17) #(b) \n \
+}; \n \
+ \n \
+ \n \
 pinstance pinst upstream * in rulematching first; \n \
-\n \
-#pinstance pinst upstream ifa in blacklist table allx; \n \
-#pinstance pinst upstream ifa out whitelist table {(table random_stuff) (table allx)}; \n \
-#pinstance pinst downstream ifa in blacklist table {asdf(*| 5.5.5.5)}; \n \
+ \n \
+pinstance pinst upstream u1 in whitelist table tu1; \n \
+pinstance pinst upstream u2 in whitelist table tu2; \n \
+pinstance pinst upstream u3 in whitelist table tu3; \n \
+ \n \
+pinstance pinst downstream d4 out whitelist table td4; \n \
+pinstance pinst downstream d5 out whitelist table td5; \n \
+pinstance pinst downstream d6 out whitelist table td6; \n \
+ \n \
+#Scenario: \n \
+#       (a)                    (b)                     (c) \n \
+#       +-----------------+    +-----------------+     +-----------------+ \n \
+#       | 1      2      3 |    | 1      2      3 |     | 1      2      3 | \n \
+#       | ^      ^      ^ |    | ^    ^ ^      ^ |     |              ^  | \n \
+#       | |      |      | |    | |   /  |      | |     |             / x | \n \
+#       | |      |      | |    | +--+---+----+ | |     |   ---------- /  | \n \
+#       | |      |      | |    |   /    |    | | |     |  / ----------   | \n \
+#       | 4      5      6 |    | 4      5      6 |     | 4      5      6 | \n \
+#       +-----------------+    +-----------------+     +-----------------+ \n \
+#Addr:    4      5      5       14     15    16/17     24/25 \n \
+#        in     in     in       in     in     in        in  \n \
         "
                                 };
 
-        source_list<source> slist_d4 {addr_storage("1.1.1.1")};
-        mcast_addr_record_type mode_d4 = MODE_IS_INCLUDE;
-        auto grecord_for_qd4 = std::make_shared<group_record_msg>(4, mode_d4, gaddr, std::move(slist_d4), gmp );
+        slist slist_d4 {addr("4.4.4.4"), addr("14.14.14.14"), addr("24.24.24.24"), addr("25.25.25.25")};
+        auto grecord_for_qd4 = std::make_shared<group_record_msg>(4, MODE_IS_INCLUDE, gaddr, std::move(slist_d4), gmp);
 
-        source_list<source> slist_d5 {addr_storage("2.2.2.2")};
-        mcast_addr_record_type mode_d5 = MODE_IS_EXCLUDE;
-        auto grecord_for_qd5 = std::make_shared<group_record_msg>(5, mode_d5, gaddr, std::move(slist_d5), gmp );
+        slist slist_d5 {addr("5.5.5.5"), addr("15.15.15.15")};
+        auto grecord_for_qd5 = std::make_shared<group_record_msg>(5, MODE_IS_INCLUDE, gaddr, std::move(slist_d5), gmp);
+
+        slist slist_d6 {addr("6.6.6.6"), addr("16.16.16.16"), addr("17.17.17.17")};
+        auto grecord_for_qd6 = std::make_shared<group_record_msg>(6, MODE_IS_INCLUDE, gaddr, std::move(slist_d6), gmp);
+
+        std::list < std::pair<unsigned int, addr_storage>> routing_data;
+
+        auto sma = get_simple_membership_aggregation_mockup(std::move(test_conf), grecord_for_qd4, grecord_for_qd5, grecord_for_qd6, gaddr, gmp, routing_data);
+
+        auto gmem_u1 = sma.get_group_memberships(1);
+        auto gmem_u2 = sma.get_group_memberships(2);
+        auto gmem_u3 = sma.get_group_memberships(3);
+  
+        UT_CHECK(gmem_u1.first == INCLUDE_MODE); 
+        UT_CHECK(gmem_u1.second == (slist{addr("4.4.4.4"), addr("16.16.16.16")})); 
+
+        UT_CHECK(gmem_u2.first == INCLUDE_MODE); 
+        UT_CHECK(gmem_u2.second == (slist{addr("5.5.5.5"), addr("14.14.14.14"), addr("15.15.15.15")})); 
+
+        UT_CHECK(gmem_u3.first == INCLUDE_MODE); 
+        UT_CHECK(gmem_u3.second == (slist{addr("17.17.17.17"), addr("24.24.24.24")})); 
 
-        //auto sma = get_simple_membership_aggregation_mockup(std::move(test_conf), grecord_for_qd4, grecord_for_qd5, gaddr, gmp);
         UT_SUMMARY;
     }
 
+    test_status test_simple_membership_aggregation_first_blacklist() {
+        HC_LOG_TRACE("");
+        UT_INITIALISATION;
+
+        addr_storage gaddr("239.99.99.99");
+        group_mem_protocol gmp = IGMPv3;
+
+        using slist = source_list<source>;
+        using addr = addr_storage;
+
+        std::string test_conf = {" \
+#protocol IGMPv3; DO NOT USE!!! \n \
+#pinstance pinst: u1 u2 u3 ==> d4 d5 d6; DO NOT USE!!! \n \
+#interface index: 1  2  3 ==>  4  5  6 \n \
+#interface prio:  1  2  3 ==> ...      \n \
+ \n \
+table tu1 { \n \
+    (239.99.99.70 - 239.99.99.110 | 5.5.5.5)  #(b) \n \
+    (239.99.99.99 | 6.6.6.6) #(b) \n \
+    (239.99.99.99 | 7.7.7.7) #(c) \n \
+    (239.99.99.99 | 8.8.8.8) #(d) \n \
+    (239.99.99.99 | 9.9.9.9) #(d) \n \
+    (239.99.99.99 | 10.10.10.10) #(d) \n \
+}; \n \
+ \n \
+table tu2 { \n \
+    (239.99.99.99 | 6.6.6.6) #(b) \n \
+#    (239.99.99.99 | 7.7.7.7) #(c) allready blocked in (a) \n \
+    (239.99.99.99 | 9.9.9.9) #(d) \n \
+}; \n \
+ \n \
+table tu3 { \n \
+#    (239.99.99.99 | 9.9.9.9) #(d) allready blocked in (a) \n \
+}; \n \
+ \n \
+ \n \
+table td4 { \n \
+    u2 ( * | * ) #(a) \n \
+}; \n \
+ \n \
+table td5 { \n \
+    (239.99.99.99 | 10.10.10.10) #(d) \n \
+     \n \
+}; \n \
+ \n \
+table td6 { \n \
+    u3 ( 239.99.99.0/24 | * ) #(a) \n \
+}; \n \
+ \n \
+pinstance pinst upstream * in rulematching first; \n \
+ \n \
+pinstance pinst upstream u1 in blacklist table tu1; \n \
+pinstance pinst upstream u2 in blacklist table tu2; \n \
+pinstance pinst upstream u3 in blacklist table tu3; \n \
+ \n \
+pinstance pinst downstream d4 out blacklist table td4; \n \
+pinstance pinst downstream d5 out blacklist table td5; \n \
+pinstance pinst downstream d6 out blacklist table td6; \n \
+        "
+                                };
+
+        slist slist_d4 {addr("4.4.4.4"), addr("7.7.7.7")};
+        auto grecord_for_qd4 = std::make_shared<group_record_msg>(4, MODE_IS_EXCLUDE, gaddr, std::move(slist_d4), gmp);
+
+        slist slist_d5 {addr("5.5.5.5"), addr("7.7.7.7"), addr("8.8.8.8"), addr("10.10.10.10")};
+        auto grecord_for_qd5 = std::make_shared<group_record_msg>(5, MODE_IS_INCLUDE, gaddr, std::move(slist_d5), gmp);
+
+        slist slist_d6 {addr("6.6.6.6"), addr("9.9.9.9")};
+        auto grecord_for_qd6 = std::make_shared<group_record_msg>(6, MODE_IS_EXCLUDE, gaddr, std::move(slist_d6), gmp);
+
+        std::list < std::pair<unsigned int, addr_storage>> routing_data;
+
+        std::cout << std::endl << "##########Start################"  << std::endl;
+        auto sma = get_simple_membership_aggregation_mockup(std::move(test_conf), grecord_for_qd4, grecord_for_qd5, grecord_for_qd6, gaddr, gmp, routing_data);
+
+        auto gmem_u1 = sma.get_group_memberships(1);
+        auto gmem_u2 = sma.get_group_memberships(2);
+        auto gmem_u3 = sma.get_group_memberships(3);
+  
+        UT_CHECK(gmem_u1.first == EXCLUDE_MODE); 
+        UT_CHECK(gmem_u1.second == (slist{addr("4.4.4.4"), addr("5.5.5.5"), addr("6.6.6.6"), addr("7.7.7.7"), addr("8.8.8.8"), addr("9.9.9.9"), addr("10.10.10.10")})); 
+        std::cout << "gmem_u1: " << gmem_u1.second << std::endl;
+        
+
+        UT_CHECK(gmem_u2.first == INCLUDE_MODE); 
+        UT_CHECK(gmem_u2.second == (slist{addr("5.5.5.5"), addr("8.8.8.8")})); 
+        std::cout << "gmem_u2: " << gmem_u2.second << std::endl;
+
+
+        UT_CHECK(gmem_u3.first == INCLUDE_MODE); 
+        UT_CHECK(gmem_u3.second == (slist{addr("7.7.7.7")})); 
+        std::cout << "gmem_u3:" << gmem_u3.second << std::endl;
+
+        UT_SUMMARY;
+    }
 
 
 };
@@ -443,10 +629,13 @@ std::list<std::tuple<ut_test_fun, ut_effort>> test_membership_aggregation_functi
         }, 1),
         std::make_tuple([&p]() {
             return p.test_simple_membership_aggregation_mockup();
+        }, 1),
+        std::make_tuple([&p]() {
+            return p.test_simple_membership_aggregation_first_whitelist();
+        }, 1),
+        std::make_tuple([&p]() {
+            return p.test_simple_membership_aggregation_first_blacklist();
         }, 1)
-        //std::make_tuple([&p]() {
-        //return p.test_first_mutex_aggregation();
-        //}, 1)
     };
 }
 
diff --git a/mcproxy/testing/ut_minimal.hpp b/mcproxy/testing/ut_minimal.hpp
index 95e45c9..d6ab351 100644
--- a/mcproxy/testing/ut_minimal.hpp
+++ b/mcproxy/testing/ut_minimal.hpp
@@ -90,37 +90,38 @@ public:
     }
 };
 
-#define UT_CHECK(expression) (expression) \
-    ? ut_test_status__.inrement_test_counter() \
-    : report_error(ut_test_status__, "CHECK FAILED", #expression, __FILE__, __LINE__, false);
-
-#define UT_REQUIRE(expression) (expression) \
-    ? ut_test_status__.inrement_test_counter() \
-    : report_error(ut_test_status__, "REQUIRE FAILED", #expression, __FILE__, __LINE__, true);
+#define REPORT_ERROR(ts, fun, msg, file, line, stop_testing)                                                       \
+    {                                                                                                              \
+        ts.inrement_error_counter();                                                                               \
+        ts.inrement_test_counter();                                                                                \
+                                                                                                                   \
+        char vt100_clearline[] = { 27, '[' , '2', 'K', '\0'};                                                      \
+        std::cout << vt100_clearline << "\r" << fun << " " << file << "(" << line << "): " << msg << std::endl;    \
+                                                                                                                   \
+        if (stop_testing) {                                                                                        \
+            throw unit_test_error(ts);                                                                             \
+        }                                                                                                          \
+    } 
+
+
+#define UT_CHECK(expression) if (expression) { \
+    ut_test_status__.inrement_test_counter();  \
+    } else REPORT_ERROR(ut_test_status__, "CHECK FAILED", #expression, __FILE__, __LINE__, false)
+
+#define UT_REQUIRE(expression) if (expression) { \
+    ut_test_status__.inrement_test_counter();    \
+    } else REPORT_ERROR(ut_test_status__, "CHECK FAILED", #expression, __FILE__, __LINE__, true)
 
 #define UT_ERROR(message) \
-    report_error(ut_test_status__, "ERROR", #message, __FILE__, __LINE__, false);
+    REPORT_ERROR(ut_test_status__, "ERROR", message, __FILE__, __LINE__, false)
 
 #define UT_FAIL(message) \
-    report_error(ut_test_status__, "FAILED", #message, __FILE__, __LINE__, true);
+    REPORT_ERROR(ut_test_status__, "FAILED", message, __FILE__, __LINE__, true)
 
 
 #define UT_INITIALISATION test_status ut_test_status__(std::string(__FUNCTION__));
 #define UT_SUMMARY return ut_test_status__ ;
 
-inline void report_error(test_status& ts, std::string&& fun, std::string&& msg, std::string&& file, int line, bool stop_testing)
-{
-    ts.inrement_error_counter();
-    ts.inrement_test_counter();
-
-    char vt100_clearline[] = { 27, '[' , '2', 'K', '\0'};
-    std::cout << vt100_clearline << "\r" << fun << " " << file << "(" << line << "): " << msg << std::endl;
-
-    if (stop_testing) {
-        throw unit_test_error(ts);
-    }
-}
-
 #endif //UNIT_TESTS
 
 #endif //UT_MINIMAL_HPP
diff --git a/references/parser/membership_aggregation b/references/parser/membership_aggregation
index 31d4587..d8ed8e8 100644
--- a/references/parser/membership_aggregation
+++ b/references/parser/membership_aggregation
@@ -74,4 +74,4 @@ EX{s1,s2} merge with BL{s2-s4,s6} = EX{s1-s4,s6}, R(IN{s3,s4,s6})     EX{A + B},
 IN{s1,s2} without IN{s1,s3} = IN{s2}              IN{A - B}
 IN{s1,s2} without EX{s1,s3} = IN{s1}              IN{A * B}
 EX{s1,s2} without IN{s1,s3} = EX{s1,s2,s3}        EX{A + B}
-EX{s1,s2} without EX{s1,s3} = IN{s2}              In{A - B}
+EX{s1,s2} without EX{s1,s3} = IN{s3}              In{B - A}
diff --git a/references/parser/test_first_mem_aggr.conf b/references/parser/test_first_mem_aggr.conf
new file mode 100644
index 0000000..38ebc9c
--- /dev/null
+++ b/references/parser/test_first_mem_aggr.conf
@@ -0,0 +1,138 @@
+##################################################################################
+##################################################################################
+## ~ test_simple_membership_aggregation_first_whitelist: 
+#protocol IGMPv3; DO NOT USE!!! \n \
+#pinstance pinst: u1 u2 u3 ==> d4 d5;
+#interface index: 1  2  3 ==>  4  5
+#interface prio:  1  2  3 ==> ... 
+
+table tu1 {
+    (239.99.99.99 | 4.4.4.4) #(a)
+    (239.99.99.99 | 16.16.16.16) #(b)
+};
+
+table tu2 {
+    u2 (239.99.99.99 | 5.5.5.5) #(a)
+    (239.99.99.99 | 14.14.14.14) #(b)
+    (239.99.99.99 | 15.15.15.15) #(b)
+};
+
+table tu3 {
+#   (239.99.99.99 | 6.6.6.6) #a) block 6.6.6.6
+    (239.99.99.99 | 17.17.17.17) #(b)
+    (239.99.99.99 | 24.24.24.24) #(c)
+};
+
+table td4 {
+    u1 (239.99.99.99 | 4.4.4.4) #(a)
+    (239.99.99.99 | 14.14.14.14) #(b)
+    (239.99.99.99 | 24.24.24.24) #(c)
+    (239.99.99.99 | 25.25.25.25) #(c)
+};
+
+table td5 {
+    u2 (239.99.99.99 | 5.5.5.5) #(a)
+    (239.99.99.99 | 15.15.15.15) #(b)
+};
+
+table td6 {
+   u3 (239.99.99.99 | 6.6.6.6) #(a)
+    (239.99.99.99 | 16.16.16.16) #(b)
+    (239.99.99.99 | 17.17.17.17) #(b)
+};
+
+
+pinstance pinst upstream * in rulematching first;
+
+pinstance pinst upstream u1 in whitelist table tu1;
+pinstance pinst upstream u2 in whitelist table tu2;
+pinstance pinst upstream u3 in whitelist table tu3;
+
+pinstance pinst downstream d4 out whitelist table td4;
+pinstance pinst downstream d5 out whitelist table td5;
+pinstance pinst downstream d6 out whitelist table td6;
+
+
+Scenario: \n \
+       (a)                    (b)                     (c) \n \
+       +-----------------+    +-----------------+     +-----------------+ \n \
+       | 1      2      3 |    | 1      2      3 |     | 1      2      3 | \n \
+       | ^      ^      ^ |    | ^    ^ ^      ^ |     |              ^  | \n \
+       | |      |      | |    | |   /  |      | |     |             / x | \n \
+       | |      |      | |    | +--+---+----+ | |     |   ---------- /  | \n \
+       | |      |      | |    |   /    |    | | |     |  / ----------   | \n \
+       | 4      5      6 |    | 4      5      6 |     | 4      5      6 | \n \
+       +-----------------+    +-----------------+     +-----------------+ \n \
+Addr:    4      5      5       14     15    16/17     24/25 \n \
+        in     in     in       in     in     in        in  \n \
+
+
+
+
+
+##################################################################################
+##################################################################################
+## ~ test_simple_membership_aggregation_first_blacklist: 
+#protocol IGMPv3; DO NOT USE!!! \n \
+#pinstance pinst: u1 u2 u3 ==> d4 d5;
+#interface index: 1  2  3 ==>  4  5
+#interface prio:  1  2  3 ==> ... 
+
+table tu1 {
+    (239.99.99.70 - 239.99.99.110 | 5.5.5.5)  #(b)
+    (239.99.99.99 | 6.6.6.6) #(b)
+    (239.99.99.99 | 7.7.7.7) #(c)
+    (239.99.99.99 | 8.8.8.8) #(d)
+    (239.99.99.99 | 9.9.9.9) #(d)
+    (239.99.99.99 | 10.10.10.10) #(d)
+};
+
+table tu2 {
+    u2 (239.99.99.99 | 6.6.6.6) #(b)
+#    (239.99.99.99 | 7.7.7.7) #(c) allready blocked in (a)
+    (239.99.99.99 | 9.9.9.9) #(d)
+};
+
+table tu3 {
+#    (239.99.99.99 | 9.9.9.9) #(d) allready blocked in (a)
+};
+
+
+table td4 {
+    u2 ( * | * ) #(a)
+};
+
+table td5 {
+    (239.99.99.99 | 10.10.10.10) #(d)
+    
+};
+
+table td6 {
+    u3 ( 239.99.99.0/24 | * ) #(a)
+};
+
+pinstance pinst upstream * in rulematching first;
+
+pinstance pinst upstream u1 in blacklist table tu1;
+pinstance pinst upstream u2 in blacklist table tu2;
+pinstance pinst upstream u3 in blacklist table tu3;
+
+pinstance pinst downstream d4 out blacklist table td4;
+pinstance pinst downstream d5 out blacklist table td5;
+pinstance pinst downstream d6 out blacklist table td6;
+
+
+
+
+
+    # I think this is the result
+    #UT_CHECK(gmem_u1.first == EXCLUDE_MODE); 
+    #UT_CHECK(gmem_u1.second == (slist{addr("4.4.4.4"), addr("5.5.5.5"), addr("6.6.6.6"), addr("7.7.7.7"), addr("8.8.8.8"), addr("9.9.9.9"), addr("10.10.10.10")})); 
+    
+
+    #UT_CHECK(gmem_u2.first == INCLUDE_MODE); 
+    #UT_CHECK(gmem_u2.second == (slist{addr("5.5.5.5"), addr("8.8.8.8")})); 
+
+
+    #UT_CHECK(gmem_u3.first == INCLUDE_MODE); 
+    #UT_CHECK(gmem_u3.second == (slist{addr("7.7.7.7")})); 
-- 
GitLab