LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - flow_handler.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 95 0.0 %
Date: 2026-06-22 02:21:21 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #include <base/address.h>
       5             : #include <base/address_util.h>
       6             : #include "pkt/proto.h"
       7             : #include "pkt/proto_handler.h"
       8             : #include "pkt/pkt_init.h"
       9             : #include "pkt/pkt_handler.h"
      10             : #include "pkt/flow_table.h"
      11             : #include "pkt/flow_proto.h"
      12             : #include "pkt/flow_handler.h"
      13             : 
      14             : SandeshTraceBufferPtr PktFlowTraceBuf(SandeshTraceBufferCreate("FlowHandler", 5000));
      15             : 
      16           0 : static const VmEntry *InterfaceToVm(const Interface *intf) {
      17           0 :     if (intf->type() != Interface::VM_INTERFACE)
      18           0 :         return NULL;
      19             : 
      20           0 :     const VmInterface *vm_port = static_cast<const VmInterface *>(intf);
      21           0 :     return vm_port->vm();
      22             : }
      23             : 
      24             : // Compute L2/L3 forwarding mode for pacekt.
      25             : // Forwarding mode is L3 if,
      26             : // - Packet uses L3 label
      27             : // - Packet uses L2 Label and DMAC hits a route with L2-Receive NH
      28             : // Else forwarding mode is L2
      29           0 : bool FlowHandler::IsL3ModeFlow() const {
      30             :     const Interface *intf =
      31           0 :         agent_->interface_table()->FindInterface(pkt_info_->agent_hdr.ifindex);
      32             :     // here return true/false does not make any difference as flow processing
      33             :     // will be aborted due to invalid interface in subsequent processing.
      34           0 :     if (intf == NULL) {
      35           0 :         return false;
      36             :     }
      37           0 :     if (intf->type() == Interface::INET) {
      38           0 :         return true;
      39             :     }
      40             : 
      41           0 :     if (intf->type() == Interface::VM_INTERFACE) {
      42           0 :         const VmInterface *vm_intf =
      43             :             static_cast<const VmInterface *>(intf);
      44           0 :         if (vm_intf == agent_->vhost_interface()) {
      45           0 :             return true;
      46             :         }
      47             :     }
      48             : 
      49           0 :     if (pkt_info_->l3_label) {
      50           0 :         return true;
      51             :     }
      52             : 
      53           0 :     VrfTable *table = static_cast<VrfTable *>(agent_->vrf_table());
      54           0 :     VrfEntry *vrf = table->FindVrfFromId(pkt_info_->agent_hdr.vrf);
      55           0 :     if (vrf == NULL) {
      56           0 :         return false;
      57             :     }
      58             :     BridgeAgentRouteTable *l2_table = static_cast<BridgeAgentRouteTable *>
      59           0 :         (vrf->GetBridgeRouteTable());
      60             :     AgentRoute *rt = static_cast<AgentRoute *>
      61           0 :         (l2_table->FindRouteNoLock(pkt_info_->dmac));
      62           0 :     if (rt == NULL) {
      63           0 :         return false;
      64             :     }
      65             : 
      66           0 :     const NextHop *nh = rt->GetActiveNextHop();
      67           0 :     if (nh == NULL) {
      68           0 :         return false;
      69             :     }
      70             : 
      71           0 :     if (nh->GetType() == NextHop::L2_RECEIVE) {
      72           0 :         return true;
      73             :     }
      74           0 :     return false;
      75             : }
      76             : 
      77           0 : bool FlowHandler::Run() {
      78           0 :     PktControlInfo in;
      79           0 :     PktControlInfo out;
      80           0 :     PktFlowInfo info(agent_, pkt_info_,
      81           0 :                      flow_proto_->GetTable(flow_table_index_));
      82           0 :     std::unique_ptr<FlowTaskMsg> ipc;
      83           0 :     bool allow_reentrant = true;
      84           0 :     if (pkt_info_->type == PktType::INVALID) {
      85           0 :         info.SetPktInfo(pkt_info_);
      86           0 :         info.l3_flow = IsL3ModeFlow();
      87           0 :     } else if (pkt_info_->type == PktType::MESSAGE) {
      88             :         // we don't allow reentrancy to different partition if it is
      89             :         // a reevaluation for an existing flow which will only exist
      90             :         // in this partition
      91           0 :         allow_reentrant = false;
      92           0 :         ipc = std::unique_ptr<FlowTaskMsg>(static_cast<FlowTaskMsg *>(pkt_info_->ipc));
      93           0 :         pkt_info_->ipc = NULL;
      94           0 :         FlowEntry *fe = ipc->fe_ptr.get();
      95             :         // take lock on flow entry before accessing it, since we need to read
      96             :         // forward flow only take lock only on forward flow
      97           0 :         std::scoped_lock lock1(fe->mutex());
      98           0 :         assert(flow_table_index_ == fe->flow_table()->table_index());
      99             : 
     100           0 :         if (fe->deleted() || fe->is_flags_set(FlowEntry::ShortFlow)) {
     101           0 :             return true;
     102             :         }
     103             : 
     104             :         // We dont support revaluation of linklocal flows
     105           0 :         if (fe->is_flags_set(FlowEntry::LinkLocalFlow)) {
     106           0 :             return true;
     107             :         }
     108             : 
     109           0 :         info.flow_entry = fe;
     110           0 :         pkt_info_->agent_hdr.cmd = AGENT_TRAP_FLOW_MISS;
     111           0 :         pkt_info_->agent_hdr.cmd_param = fe->flow_handle();
     112           0 :         pkt_info_->agent_hdr.ifindex = fe->data().if_index_info;
     113           0 :         pkt_info_->tunnel = fe->data().tunnel_info;
     114           0 :         pkt_info_->agent_hdr.nh = fe->key().nh;
     115           0 :         pkt_info_->agent_hdr.vrf = fe->data().vrf;
     116           0 :         pkt_info_->family =
     117           0 :             fe->key().src_addr.is_v4() ? Address::INET : Address::INET6;
     118           0 :         pkt_info_->smac = fe->data().smac;
     119           0 :         pkt_info_->dmac = fe->data().dmac;
     120           0 :         pkt_info_->ip_saddr = fe->key().src_addr;
     121           0 :         pkt_info_->ip_daddr = fe->key().dst_addr;
     122           0 :         pkt_info_->ip_proto = fe->key().protocol;
     123           0 :         pkt_info_->sport = fe->key().src_port;
     124           0 :         pkt_info_->dport = fe->key().dst_port;
     125           0 :         pkt_info_->tcp_ack = fe->is_flags_set(FlowEntry::TcpAckFlow);
     126           0 :         pkt_info_->vrf = fe->data().vrf;
     127           0 :         pkt_info_->ttl = fe->data().ttl;
     128           0 :         info.l3_flow = fe->l3_flow();
     129           0 :         info.out_component_nh_idx = fe->data().component_nh_idx;
     130           0 :     }
     131             : 
     132           0 :     if (info.Process(pkt_info_.get(), &in, &out) == false) {
     133           0 :         info.short_flow = true;
     134             :     }
     135             : 
     136             :     // Flows that change port-numbers are always processed in thread-0.
     137             :     // Identify flows that change port and enqueue to thread-0
     138           0 :     if (allow_reentrant && ((pkt_info_->sport != info.nat_sport) ||
     139           0 :                             (pkt_info_->dport != info.nat_dport))) {
     140           0 :         if ((info.nat_sport != 0 || info.nat_dport != 0)) {
     141           0 :             if (flow_table_index_ != FlowTable::kPortNatFlowTableInstance) {
     142             :                 // Enqueue flow evaluation to
     143             :                 // FlowTable::kPortNatFlowTableInstance instance.
     144           0 :                 flow_proto_->EnqueueReentrant
     145           0 :                     (pkt_info_, FlowTable::kPortNatFlowTableInstance);
     146           0 :                 return true;
     147             :             }
     148             :         }
     149             :     }
     150             : 
     151           0 :     if (in.intf_ && ((in.intf_->type() != Interface::VM_INTERFACE) &&
     152           0 :                      (in.intf_->type() != Interface::INET))) {
     153           0 :         in.intf_ = NULL;
     154             :     }
     155             : 
     156           0 :     if (in.intf_ && out.intf_) {
     157           0 :         info.local_flow = true;
     158             :     }
     159             : 
     160           0 :     if (in.intf_) {
     161           0 :         in.vm_ = InterfaceToVm(in.intf_);
     162             :     }
     163             : 
     164           0 :     if (out.intf_) {
     165           0 :         out.vm_ = InterfaceToVm(out.intf_);
     166             :     }
     167             : 
     168           0 :     info.Add(pkt_info_.get(), &in, &out);
     169           0 :     return true;
     170           0 : }

Generated by: LCOV version 1.14