From 66a799661eab04180344106b8d64d32b8e5c3b25 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 8 Apr 2020 14:40:26 +0200 Subject: [PATCH] gw,tft: move traffic flow template matching into own class this prepares the reuse of the matching functions for the TTCN3 DUT. create own matcher class that the GW uses. --- srsue/hdr/stack/upper/gw.h | 7 +--- srsue/hdr/stack/upper/tft_packet_filter.h | 25 ++++++++++++ srsue/src/stack/upper/gw.cc | 42 +++----------------- srsue/src/stack/upper/tft_packet_filter.cc | 45 ++++++++++++++++++++++ 4 files changed, 76 insertions(+), 43 deletions(-) diff --git a/srsue/hdr/stack/upper/gw.h b/srsue/hdr/stack/upper/gw.h index b34adf43d..651d0d80d 100644 --- a/srsue/hdr/stack/upper/gw.h +++ b/srsue/hdr/stack/upper/gw.h @@ -31,7 +31,6 @@ #include "srslte/common/threads.h" #include "srslte/interfaces/ue_interfaces.h" #include "tft_packet_filter.h" -#include #include namespace srsue { @@ -108,11 +107,7 @@ private: uint32_t mbsfn_ports[SRSLTE_N_MCH_LCIDS] = {}; // Target ports for MBSFN data // TFT - std::mutex tft_mutex; - typedef std::map tft_filter_map_t; - tft_filter_map_t tft_filter_map; - - uint8_t check_tft_filter_match(const srslte::unique_byte_buffer_t& pdu); + tft_pdu_matcher tft_matcher; }; } // namespace srsue diff --git a/srsue/hdr/stack/upper/tft_packet_filter.h b/srsue/hdr/stack/upper/tft_packet_filter.h index 2dcc79af5..bb9ee8402 100644 --- a/srsue/hdr/stack/upper/tft_packet_filter.h +++ b/srsue/hdr/stack/upper/tft_packet_filter.h @@ -25,6 +25,8 @@ #include "srslte/asn1/liblte_mme.h" #include "srslte/common/buffer_pool.h" #include "srslte/common/log.h" +#include "srslte/common/log_filter.h" +#include namespace srsue { @@ -101,6 +103,29 @@ public: bool match_port(const srslte::unique_byte_buffer_t& pdu); }; +/** + * TFT PDU matcher class used by GW and TTCN3 DUT testloop handler + */ +class tft_pdu_matcher +{ +public: + tft_pdu_matcher(srslte::log_filter* log_) : log(log_){}; + ~tft_pdu_matcher(){}; + + void set_default_lcid(const uint8_t lcid); + uint8_t check_tft_filter_match(const srslte::unique_byte_buffer_t& pdu); + int apply_traffic_flow_template(const uint8_t& erab_id, + const uint8_t& lcid, + const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); + +private: + srslte::log_filter* log = nullptr; + uint8_t default_lcid = 0; + std::mutex tft_mutex; + typedef std::map tft_filter_map_t; + tft_filter_map_t tft_filter_map; +}; + } // namespace srsue #endif // SRSUE_TFT_PACKET_FILTER_H diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index 971da25ea..d77b4afae 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -34,7 +34,7 @@ namespace srsue { -gw::gw() : thread("GW"), pool(srslte::byte_buffer_pool::get_instance()) {} +gw::gw() : thread("GW"), pool(srslte::byte_buffer_pool::get_instance()), tft_matcher(&log) {} int gw::init(const gw_args_t& args_, srslte::logger* logger_, stack_interface_gw* stack_) { @@ -123,7 +123,6 @@ void gw::write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) } else { // Only handle IPv4 and IPv6 packets struct iphdr* ip_pkt = (struct iphdr*)pdu->msg; - struct ipv6hdr* ip6_pkt = (struct ipv6hdr*)pdu->msg; if (ip_pkt->version == 4 || ip_pkt->version == 6) { int n = write(tun_fd, pdu->msg, pdu->N_bytes); if (n > 0 && (pdu->N_bytes != (uint32_t)n)) { @@ -179,6 +178,7 @@ int gw::setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t } default_lcid = lcid; + tft_matcher.set_default_lcid(lcid); // Setup a thread to receive packets from the TUN device start(GW_THREAD_PRIO); @@ -189,24 +189,7 @@ int gw::apply_traffic_flow_template(const uint8_t& const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) { - std::lock_guard lock(tft_mutex); - switch (tft->tft_op_code) { - case LIBLTE_MME_TFT_OPERATION_CODE_CREATE_NEW_TFT: - for (int i = 0; i < tft->packet_filter_list_size; i++) { - log.info("New packet filter for TFT\n"); - tft_packet_filter_t filter(erab_id, lcid, tft->packet_filter_list[i], &log); - auto it = tft_filter_map.insert(std::make_pair(filter.eval_precedence, filter)); - if (it.second == false) { - log.error("Error inserting TFT Packet Filter\n"); - return SRSLTE_ERROR_CANT_START; - } - } - break; - default: - log.error("Unhandled TFT OP code\n"); - return SRSLTE_ERROR_CANT_START; - } - return SRSLTE_SUCCESS; + return tft_matcher.apply_traffic_flow_template(erab_id, lcid, tft); } /******************************************************************************* @@ -285,7 +268,7 @@ void gw::run_thread() break; } - uint8_t lcid = check_tft_filter_match(pdu); + uint8_t lcid = tft_matcher.check_tft_filter_match(pdu); // Send PDU directly to PDCP if (stack->is_lcid_enabled(lcid)) { pdu->set_timestamp(); @@ -318,21 +301,6 @@ void gw::run_thread() log.info("GW IP receiver thread exiting.\n"); } -uint8_t gw::check_tft_filter_match(const srslte::unique_byte_buffer_t& pdu) -{ - std::lock_guard lock(tft_mutex); - uint8_t lcid = default_lcid; - for (std::pair& filter_pair : tft_filter_map) { - bool match = filter_pair.second.match(pdu); - if (match) { - lcid = filter_pair.second.lcid; - log.debug("Found filter match -- EPS bearer Id %d, LCID %d\n", filter_pair.second.eps_bearer_id, lcid); - break; - } - } - return lcid; -} - /**************************/ /* TUN Interface Helpers */ /**************************/ @@ -538,7 +506,7 @@ bool gw::find_ipv6_addr(struct in6_addr* in6_out) req.r.ifa_family = AF_INET6; // Fill up all the attributes for the rtnetlink header. - // The lenght is important. 16 signifies we are requesting IPv6 addresses + // The length is important. 16 signifies we are requesting IPv6 addresses rta = (struct rtattr*)(((char*)&req) + NLMSG_ALIGN(req.n.nlmsg_len)); rta->rta_len = RTA_LENGTH(16); diff --git a/srsue/src/stack/upper/tft_packet_filter.cc b/srsue/src/stack/upper/tft_packet_filter.cc index 24a2e747b..7f97a8b69 100644 --- a/srsue/src/stack/upper/tft_packet_filter.cc +++ b/srsue/src/stack/upper/tft_packet_filter.cc @@ -247,4 +247,49 @@ bool tft_packet_filter_t::match_port(const srslte::unique_byte_buffer_t& pdu) } return true; } + +uint8_t tft_pdu_matcher::check_tft_filter_match(const srslte::unique_byte_buffer_t& pdu) +{ + std::lock_guard lock(tft_mutex); + uint8_t lcid = default_lcid; + for (std::pair& filter_pair : tft_filter_map) { + bool match = filter_pair.second.match(pdu); + if (match) { + lcid = filter_pair.second.lcid; + log->debug("Found filter match -- EPS bearer Id %d, LCID %d\n", filter_pair.second.eps_bearer_id, lcid); + break; + } + } + return lcid; +} + +int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& erab_id, + const uint8_t& lcid, + const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) +{ + std::lock_guard lock(tft_mutex); + switch (tft->tft_op_code) { + case LIBLTE_MME_TFT_OPERATION_CODE_CREATE_NEW_TFT: + for (int i = 0; i < tft->packet_filter_list_size; i++) { + log->info("New packet filter for TFT\n"); + tft_packet_filter_t filter(erab_id, lcid, tft->packet_filter_list[i], log); + auto it = tft_filter_map.insert(std::make_pair(filter.eval_precedence, filter)); + if (it.second == false) { + log->error("Error inserting TFT Packet Filter\n"); + return SRSLTE_ERROR_CANT_START; + } + } + break; + default: + log->error("Unhandled TFT OP code\n"); + return SRSLTE_ERROR_CANT_START; + } + return SRSLTE_SUCCESS; +} + +void tft_pdu_matcher::set_default_lcid(const uint8_t lcid) +{ + default_lcid = lcid; +} + } // namespace srsue