LCOV - code coverage report
Current view: top level - vnsw/agent/vrouter/ksync - ksync_flow_memory.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 83 174 47.7 %
Date: 2026-11-09 02:10:49 Functions: 14 24 58.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <sys/socket.h>
       7             : #if defined(__linux__)
       8             : #include <linux/netlink.h>
       9             : #endif
      10             : #include <fcntl.h>
      11             : #include <sys/mman.h>
      12             : #include <sys/types.h>
      13             : #include <sys/ipc.h>
      14             : #include <sys/shm.h>
      15             : #include <asm/types.h>
      16             : #include <boost/asio.hpp>
      17             : 
      18             : #include <base/timer.h>
      19             : #include <base/task_trigger.h>
      20             : #include <base/address_util.h>
      21             : #include <cmn/agent_cmn.h>
      22             : #include <services/services_init.h>
      23             : #include <uve/stats_collector.h>
      24             : #include <services/icmp_error_proto.h>
      25             : #include <pkt/flow_proto.h>
      26             : #include <ksync/ksync_index.h>
      27             : #include <ksync/ksync_entry.h>
      28             : #include <ksync/ksync_object.h>
      29             : #include <ksync/ksync_netlink.h>
      30             : #include <ksync/ksync_sock.h>
      31             : #include <ksync/ksync_sock_user.h>
      32             : #include <vrouter/flow_stats/flow_stats_collector.h>
      33             : 
      34             : #include <vr_types.h>
      35             : #include <nl_util.h>
      36             : #include <vr_flow.h>
      37             : #include <vr_genetlink.h>
      38             : 
      39             : #include "ksync_init.h"
      40             : #include "ksync_flow_memory.h"
      41             : #include "sandesh_ksync.h"
      42             : 
      43             : using namespace boost::asio::ip;
      44             : static const int kTestFlowTableSize = 131072 * sizeof(vr_flow_entry);
      45             : 
      46           2 : KSyncFlowMemory::KSyncFlowMemory(KSync *ksync, uint32_t minor_id) :
      47           2 :     KSyncMemory(ksync, minor_id) {
      48           2 :     table_path_ = FLOW_TABLE_DEV;
      49           2 :     hold_flow_counter_ = 0;
      50           2 : }
      51             : 
      52           0 : void KSyncFlowMemory::Init() {
      53           0 :     IcmpErrorProto *proto = ksync_->agent()->services()->icmp_error_proto();
      54           0 :     proto->Register(boost::bind(&KSyncFlowMemory::GetFlowKey, this, _1, _2, _3));
      55             : 
      56           0 :     KSyncMemory::Init();
      57           0 : }
      58             : 
      59           0 : int KSyncFlowMemory::EncodeReq(struct nl_client *cl, uint32_t attr_len) {
      60             :     int encode_len, error;
      61             : 
      62           0 :     vr_flow_table_data info;
      63           0 :     info.set_ftable_op(flow_op::FLOW_TABLE_GET);
      64           0 :     info.set_ftable_size(0);
      65           0 :     info.set_ftable_dev(0);
      66           0 :     info.set_ftable_file_path("");
      67           0 :     info.set_ftable_processed(0);
      68           0 :     info.set_ftable_hold_oflows(0);
      69           0 :     info.set_ftable_added(0);
      70           0 :     info.set_ftable_cpus(0);
      71           0 :     info.set_ftable_created(0);
      72           0 :     info.set_ftable_oflow_entries(0);
      73           0 :     encode_len = info.WriteBinary(nl_get_buf_ptr(cl) + attr_len,
      74             :                                   nl_get_buf_len(cl), &error);
      75           0 :     return encode_len;
      76           0 : }
      77             : 
      78           2 : int KSyncFlowMemory::get_entry_size() {
      79           2 :     return sizeof(vr_flow_entry);
      80             : }
      81             : 
      82           2 : void KSyncFlowMemory::SetTableSize() {
      83           2 :     ksync_->agent()->set_flow_table_size(table_entries_count_);
      84           2 :     flow_table_ = static_cast<vr_flow_entry *>(table_);
      85           2 : }
      86             : 
      87           0 : void KSyncFlowMemory::CreateProtoAuditEntry(uint32_t idx, uint8_t gen_id) {
      88           0 :     const vr_flow_entry *ventry = GetKernelFlowEntry(idx, false);
      89             :     // Audit and remove  entry if its still in HOLD state
      90           0 :     if (ventry && ventry->fe_gen_id == gen_id &&
      91           0 :         ventry->fe_action == VR_FLOW_ACTION_HOLD) {
      92           0 :         IpAddress sip, dip;
      93           0 :         VrFlowToIp(ventry, &sip, &dip);
      94           0 :         FlowKey key(ventry->fe_key.flow_nh_id, sip, dip,
      95           0 :                 ventry->fe_key.flow_proto,
      96           0 :                 ntohs(ventry->fe_key.flow_sport),
      97           0 :                 ntohs(ventry->fe_key.flow_dport));
      98             : 
      99           0 :         FlowProto *proto = ksync_->agent()->pkt()->get_flow_proto();
     100           0 :         proto->CreateAuditEntry(key, idx, gen_id);
     101             :     }
     102           0 : }
     103             : 
     104           0 : void KSyncFlowMemory::DecrementHoldFlowCounter() {
     105           0 :     hold_flow_counter_--;
     106           0 :     return;
     107             : }
     108             : 
     109           0 : void KSyncFlowMemory::IncrementHoldFlowCounter() {
     110           0 :     hold_flow_counter_++;
     111           0 :     return;
     112             : }
     113             : 
     114           0 : void KSyncFlowMemory::UpdateAgentHoldFlowCounter() {
     115           0 :     ksync_->agent()->stats()->update_hold_flow_count(hold_flow_counter_);
     116           0 :     hold_flow_counter_ = 0;
     117           0 :     return;
     118             : }
     119             : 
     120           0 : bool KSyncFlowMemory::IsInactiveEntry(uint32_t audit_idx, uint8_t &gen_id) {
     121             :     const vr_flow_entry *vflow_entry =
     122           0 :         GetKernelFlowEntry(audit_idx, false);
     123           0 :     if (vflow_entry && vflow_entry->fe_action == VR_FLOW_ACTION_HOLD) {
     124           0 :         gen_id = vflow_entry->fe_gen_id;
     125           0 :         return true;
     126             :     }
     127           0 :     return false;
     128             : }
     129             : 
     130           3 : void KSyncFlowMemory::VrFlowToIp(const vr_flow_entry *kflow, IpAddress *sip,
     131             :                                  IpAddress *dip) {
     132           3 :     if (kflow->fe_key.flow_family == AF_INET) {
     133           3 :         *sip = Ip4Address(ntohl(kflow->fe_key.key_u.ip4_key.ip4_sip));
     134           3 :         *dip = Ip4Address(ntohl(kflow->fe_key.key_u.ip4_key.ip4_dip));
     135             :     } else {
     136           0 :         const unsigned char *k_sip = kflow->fe_key.key_u.ip6_key.ip6_sip;
     137           0 :         const unsigned char *k_dip = kflow->fe_key.key_u.ip6_key.ip6_dip;
     138             :         Ip6Address::bytes_type sbytes;
     139             :         Ip6Address::bytes_type dbytes;
     140           0 :         for (int i = 0; i < 16; i++) {
     141           0 :             sbytes[i] = k_sip[i];
     142           0 :             dbytes[i] = k_dip[i];
     143             :         }
     144           0 :         *sip = Ip6Address(sbytes);
     145           0 :         *dip = Ip6Address(dbytes);
     146             :     }
     147           3 : }
     148             : 
     149           3 : void KSyncFlowMemory::KFlow2FlowKey(const vr_flow_entry *kflow,
     150             :                                     FlowKey *key) const {
     151           3 :     key->nh = kflow->fe_key.flow4_nh_id;
     152           3 :     Address::Family family = (kflow->fe_key.flow_family == AF_INET)?
     153             :                               Address::INET : Address::INET6;
     154           3 :     VrFlowToIp(kflow, &key->src_addr, &key->dst_addr);
     155           3 :     key->src_port = ntohs(kflow->fe_key.flow4_sport);
     156           3 :     key->dst_port = ntohs(kflow->fe_key.flow4_dport);
     157           3 :     key->protocol = kflow->fe_key.flow4_proto;
     158           3 :     key->family = family;
     159           3 : }
     160             : 
     161         194 : const vr_flow_entry *KSyncFlowMemory::GetValidKFlowEntry(const FlowKey &key,
     162             :                                                          uint32_t idx,
     163             :                                                          uint8_t gen_id) const {
     164         194 :     const vr_flow_entry *kflow = GetKernelFlowEntry(idx, false);
     165         194 :     if (!kflow) {
     166         110 :         return NULL;
     167             :     }
     168          84 :     if (key.protocol == IPPROTO_TCP) {
     169           0 :         FlowKey rhs;
     170           0 :         KFlow2FlowKey(kflow, &rhs);
     171           0 :         if (!key.IsEqual(rhs)) {
     172           0 :             return NULL;
     173             :         }
     174           0 :         if (kflow->fe_gen_id != gen_id) {
     175           0 :             return NULL;
     176             :         }
     177             :     }
     178          84 :     return kflow;
     179             : }
     180             : 
     181         396 : const vr_flow_entry *KSyncFlowMemory::GetKernelFlowEntry
     182             :     (uint32_t idx, bool ignore_active_status) const {
     183         396 :     if (idx == FlowEntry::kInvalidFlowHandle) {
     184          37 :         return NULL;
     185             :     }
     186             : 
     187         359 :     if (idx >= table_entries_count_) {
     188             :         /* if index is outside the range of flow table entries return NULL */
     189           0 :         return NULL;
     190             :     }
     191             : 
     192         359 :     if (ignore_active_status) {
     193           0 :         return &flow_table_[idx];
     194             :     }
     195             : 
     196         359 :     if (flow_table_[idx].fe_flags & VR_FLOW_FLAG_ACTIVE) {
     197         187 :         return &flow_table_[idx];
     198             :     }
     199         172 :     return NULL;
     200             : }
     201             : 
     202           0 : bool KSyncFlowMemory::GetFlowKey(uint32_t index, FlowKey *key, bool *is_nat_flow) {
     203           0 :     const vr_flow_entry *kflow = GetKernelFlowEntry(index, false);
     204           0 :     if (!kflow) {
     205           0 :         return false;
     206             :     }
     207           0 :     key->nh = kflow->fe_key.flow4_nh_id;
     208           0 :     Address::Family family = (kflow->fe_key.flow_family == AF_INET)?
     209             :                               Address::INET : Address::INET6;
     210           0 :     VrFlowToIp(kflow, &key->src_addr, &key->dst_addr);
     211           0 :     key->src_port = ntohs(kflow->fe_key.flow4_sport);
     212           0 :     key->dst_port = ntohs(kflow->fe_key.flow4_dport);
     213           0 :     key->protocol = kflow->fe_key.flow4_proto;
     214           0 :     key->family = family;
     215           0 :     if (kflow->fe_action == VR_FLOW_ACTION_NAT) {
     216           0 :         *is_nat_flow = true;
     217             :     } else {
     218           0 :         *is_nat_flow = false;
     219             :     }
     220           0 :     return true;
     221             : }
     222             : 
     223           0 : bool KSyncFlowMemory::IsEvictionMarked(const vr_flow_entry *entry,
     224             :                                        uint16_t flags) const {
     225           0 :     if (!entry) {
     226           0 :         return false;
     227             :     }
     228           0 :     if (flags & VR_FLOW_FLAG_EVICTED) {
     229           0 :         return true;
     230             :     }
     231           0 :     return false;
     232             : }
     233             : 
     234         152 : const vr_flow_entry *KSyncFlowMemory::GetKFlowStats(const FlowKey &key,
     235             :                                                     uint32_t idx,
     236             :                                                     uint8_t gen_id,
     237             :                                                     vr_flow_stats *stat) const {
     238         152 :     const vr_flow_entry *kflow = GetValidKFlowEntry(key, idx, gen_id);
     239         152 :     if (!kflow) {
     240         110 :         return NULL;
     241             :     }
     242          42 :     *stat = kflow->fe_stats;
     243          42 :     kflow = GetValidKFlowEntry(key, idx, gen_id);
     244          42 :     return kflow;
     245             : }
     246             : 
     247         103 : void KSyncFlowMemory::ReadFlowInfo(const vr_flow_entry *kflow,
     248             :                                    vr_flow_stats *stat, KFlowData *info) const {
     249         103 :     *stat = kflow->fe_stats;
     250         103 :     info->underlay_src_port = kflow->fe_udp_src_port;
     251         103 :     info->tcp_flags = kflow->fe_tcp_flags;
     252         103 :     info->flags = kflow->fe_flags;
     253         103 : }
     254             : 
     255         202 : const vr_flow_entry *KSyncFlowMemory::GetKFlowStatsAndInfo(const FlowKey &key,
     256             :                                                            uint32_t idx,
     257             :                                                            uint8_t gen_id,
     258             :                                                            vr_flow_stats *stats,
     259             :                                                            KFlowData *info)
     260             :     const {
     261         202 :     const vr_flow_entry *kflow = GetKernelFlowEntry(idx, false);
     262         202 :     if (!kflow) {
     263          99 :         return NULL;
     264             :     }
     265         103 :     if (key.protocol == IPPROTO_TCP) {
     266           3 :         FlowKey rhs;
     267           3 :         KFlow2FlowKey(kflow, &rhs);
     268           3 :         if (!key.IsEqual(rhs)) {
     269           0 :             return NULL;
     270             :         }
     271             : 
     272           3 :         ReadFlowInfo(kflow, stats, info);
     273             : 
     274           3 :         if (kflow->fe_gen_id != gen_id) {
     275           0 :             return NULL;
     276             :         }
     277             :     } else {
     278         100 :         ReadFlowInfo(kflow, stats, info);
     279             :     }
     280         103 :     return kflow;
     281             : }
     282             : 
     283           2 : void KSyncFlowMemory::InitTest() {
     284           2 :     table_ = KSyncSockTypeMap::FlowMmapAlloc(kTestFlowTableSize);
     285           2 :     memset(table_, 0, kTestFlowTableSize);
     286           2 :     table_entries_count_ = kTestFlowTableSize / get_entry_size();
     287           2 :     audit_yield_ = table_entries_count_;
     288           2 :     audit_timeout_ = 100 * 1000; // timout immediately.
     289           2 :     SetTableSize();
     290           2 : }
     291             : 
     292           2 : void KSyncFlowMemory::Shutdown() {
     293           2 :     KSyncSockTypeMap::FlowMmapFree();
     294           2 : }
     295             : 
     296         378 : void vr_flow_req::Process(SandeshContext *context) {
     297         378 :     AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
     298         378 :     ioc->FlowMsgHandler(this);
     299         378 : }
     300             : 
     301         378 : void vr_flow_response::Process(SandeshContext *context) {
     302         378 :     AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
     303         378 :     ioc->FlowResponseHandler(this);
     304         378 : }
     305             : 
     306           0 : void vr_flow_table_data::Process(SandeshContext *context) {
     307           0 :     AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
     308           0 :     ioc->FlowTableInfoHandler(this);
     309           0 : }

Generated by: LCOV version 1.14