LCOV - code coverage report
Current view: top level - vnsw/agent/diag - overlay_ping.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 173 0.0 %
Date: 2026-06-08 02:02:55 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include <stdint.h>
       2             : #include "base/os.h"
       3             : #include "pkt/proto.h"
       4             : #include "pkt/proto_handler.h"
       5             : #include "diag/diag_types.h"
       6             : #include "diag/diag_pkt_handler.h"
       7             : #include "diag/diag.h"
       8             : #include "diag/overlay_ping.h"
       9             : #include <oper/route_common.h>
      10             : #include <oper/vrf_assign.h>
      11             : #include <oper/tunnel_nh.h>
      12             : 
      13             : using namespace boost::posix_time;
      14             : extern void time_duration_to_string(time_duration &td, std::string &str);
      15             : const MacAddress OverlayPing::in_dst_mac_(0x00, 0x00, 0x5E, 0x90, 0x00, 0x01);
      16             : const MacAddress OverlayPing::in_source_mac_(0x00, 0x00, 0x5E, 0x90, 0x00, 0x02);
      17             : 
      18           0 : OverlayPing::OverlayPing(const OverlayPingReq *ping_req, DiagTable *diag_table):
      19             :    DiagEntry(ping_req->get_source_ip(), ping_req->get_dest_ip(),
      20           0 :             ping_req->get_protocol(), ping_req->get_source_port(),
      21           0 :             ping_req->get_dest_port(), Agent::GetInstance()->fabric_vrf_name(),
      22           0 :             ping_req->get_interval() * 100, ping_req->get_count(), diag_table),
      23           0 :             vn_uuid_(StringToUuid(ping_req->get_vn_uuid())),
      24           0 :             remote_vm_mac_(ping_req->get_vm_remote_mac()),
      25           0 :             data_len_(ping_req->get_packet_size()),
      26           0 :             context_(ping_req->context()),
      27           0 :             pkt_lost_count_(0) {
      28             : 
      29           0 : }
      30             : /*
      31             :  * Get the L2 Route entry to find the Tunnel NH
      32             :  */
      33             : BridgeRouteEntry *
      34           0 : OverlayPing::L2RouteGet(VxLanId* vxlan, string remotemac, Agent *agent)
      35             : {
      36           0 :     string vrf_name;
      37           0 :     const VrfNH *vrf_nh = dynamic_cast<const VrfNH *>(vxlan->nexthop());
      38           0 :     VrfEntry *vrf = NULL;
      39           0 :     if (vrf_nh) {
      40           0 :         vrf = const_cast<VrfEntry*> (vrf_nh->GetVrf());
      41           0 :         if (!vrf || vrf->IsDeleted()) {
      42           0 :             return NULL;
      43             :         } else {
      44           0 :             vrf_name = vrf->GetName();
      45             :         }
      46             :     } else {
      47           0 :         return NULL;
      48             :     }
      49           0 :     MacAddress mac = MacAddress::FromString(remotemac);
      50           0 :     BridgeRouteKey key(agent->local_vm_peer(), vrf_name, mac);
      51             :     BridgeRouteEntry *rt =  static_cast<BridgeRouteEntry *>
      52             :             (static_cast<BridgeAgentRouteTable *>
      53           0 :              (vrf->GetBridgeRouteTable())->FindActiveEntry(&key));
      54           0 :     return rt;
      55           0 : }
      56             : 
      57           0 : void OverlayPingReq::HandleRequest() const {
      58           0 :     std::string err_str;
      59           0 :     boost::system::error_code ec;
      60           0 :     OverlayPing *overlayping = NULL;
      61             :     {
      62           0 :     Agent *agent = Agent::GetInstance();
      63           0 :     boost::uuids::uuid vn_uuid = StringToUuid(get_vn_uuid());
      64           0 :     IpAddress sip(IpAddress::from_string(get_source_ip(), ec));
      65           0 :     if (ec.failed()) {
      66           0 :         err_str = "Invalid source IP";
      67           0 :         goto error;
      68             :     }
      69             : 
      70           0 :     if (!sip.is_v4()) {
      71           0 :         err_str = "V6 is not supported";
      72           0 :         goto error;
      73             :     }
      74             : 
      75           0 :     IpAddress dip(IpAddress::from_string(get_dest_ip(), ec));
      76           0 :     if (ec.failed()) {
      77           0 :         err_str = "Invalid destination IP";
      78           0 :         goto error;
      79             :     }
      80             : 
      81           0 :     if (!dip.is_v4()) {
      82           0 :         err_str = "V6 is not supported";
      83           0 :         goto error;
      84             :     }
      85             : 
      86           0 :     uint8_t proto = get_protocol();
      87           0 :     if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
      88           0 :         err_str = "Invalid protocol. Valid Protocols are TCP & UDP";
      89           0 :         goto error;
      90             :     }
      91             : 
      92           0 :     VnEntry *vn  = agent->vn_table()->Find(vn_uuid);
      93           0 :     if (!vn) {
      94           0 :         err_str = "Invalid VN segment";
      95           0 :         goto error;
      96             :     }
      97             : 
      98           0 :     int vxlan_id = vn->GetVxLanId();
      99           0 :     VxLanId* vxlan = agent->vxlan_table()->Find(vxlan_id);
     100             : 
     101           0 :     if (!vxlan) {
     102           0 :         err_str = "Invalid vxlan segment";
     103           0 :         goto error;
     104             :     }
     105             : 
     106           0 :     BridgeRouteEntry *rt = OverlayPing::L2RouteGet(vxlan, get_vm_remote_mac(),
     107             :                                                    agent);
     108           0 :     if (!rt) {
     109           0 :         err_str = "Invalid remote mac";
     110           0 :         goto error;
     111             :     }
     112             :     }
     113           0 :     overlayping = new OverlayPing(this, Agent::GetInstance()->diag_table());
     114           0 :     overlayping->Init();
     115           0 :     return;
     116           0 : error:
     117           0 :     PingErrResp *resp = new PingErrResp;
     118           0 :     resp->set_error_response(err_str);
     119           0 :     resp->set_context(context());
     120           0 :     resp->Response();
     121           0 :     return;
     122           0 : }
     123             : 
     124           0 : OverlayPing::~OverlayPing() {
     125             : 
     126           0 : }
     127             : 
     128             : /*
     129             :  * Creat Overlay VXlan packet.
     130             :  * Set the Route alert bit to indicate Overlay OAM packet
     131             :  */
     132           0 : void OverlayPing::SendRequest() {
     133             :     // Create VxLan packet
     134           0 :     Agent *agent = diag_table_->agent();
     135           0 :     Ip4Address tunneldst;
     136           0 :     Ip4Address tunnelsrc;
     137           0 :     seq_no_++;
     138           0 :     string vrf_name;
     139           0 :     boost::system::error_code ec;
     140             : 
     141           0 :     int vxlan_id = agent->vn_table()->Find(vn_uuid_)->GetVxLanId();
     142           0 :     VxLanId *vxlan = agent->vxlan_table()->Find(vxlan_id);
     143           0 :     if (!vxlan)
     144           0 :         return;
     145             : 
     146           0 :     BridgeRouteEntry *rt = L2RouteGet(vxlan, remote_vm_mac_.ToString(), agent);
     147           0 :     if (!rt)
     148           0 :         return;
     149           0 :     const AgentPath *path = rt->GetActivePath();
     150           0 :     const TunnelNH *nh = static_cast<const TunnelNH *>(path->nexthop());
     151             : 
     152           0 :     tunneldst = *nh->GetDip();
     153           0 :     tunnelsrc = *nh->GetSip();
     154           0 :     len_ = kOverlayUdpHdrLength + data_len_;
     155           0 :     boost::shared_ptr<PktInfo> pkt_info(new PktInfo(agent, len_,
     156           0 :                                                         PktHandler::DIAG, 0));
     157           0 :     uint8_t *buf = pkt_info->packet_buffer()->data();
     158           0 :     memset(buf, 0, len_);
     159           0 :     OverlayOamPktData *pktdata = NULL;
     160           0 :     pktdata = (OverlayOamPktData *)(buf + kOverlayUdpHdrLength);
     161           0 :     memset(pktdata, 0, sizeof(OverlayOamPktData));
     162             : 
     163           0 :     senttime_ = microsec_clock::universal_time();
     164           0 :     FillOamPktHeader(pktdata, vxlan_id, senttime_);
     165           0 :     DiagPktHandler *pkt_handler = new DiagPktHandler(diag_table_->agent(), pkt_info,
     166           0 :                                    *(diag_table_->agent()->event_manager())->io_service());
     167             :     // Fill outer header
     168           0 :     pkt_info->eth = (struct ether_header *)(buf);
     169           0 :     pkt_handler->EthHdr(agent->vhost_interface()->mac(), *nh->GetDmac(),
     170             :                         ETHERTYPE_IP);
     171           0 :     pkt_info->ip = (struct ip *)(pkt_info->eth +1);
     172           0 :     pkt_info->transp.udp = (struct udphdr *)(pkt_info->ip + 1);
     173             :     uint8_t  len;
     174           0 :     len = data_len_+2 * sizeof(udphdr)+sizeof(VxlanHdr)+
     175           0 :                             sizeof(struct ip) + sizeof(struct ether_header);
     176           0 :     pkt_handler->UdpHdr(len, ntohl(tunnelsrc.to_ulong()), HashValUdpSourcePort(),
     177           0 :                         ntohl(tunneldst.to_ulong()), VXLAN_UDP_DEST_PORT);
     178             : 
     179           0 :     pkt_handler->IpHdr(len + sizeof(struct ip), ntohl(tunnelsrc.to_ulong()),
     180           0 :                        ntohl(tunneldst.to_ulong()), IPPROTO_UDP,
     181             :                        DEFAULT_IP_ID, DEFAULT_IP_TTL );
     182             :    // Fill VxLan Header
     183           0 :     VxlanHdr *vxlanhdr = (VxlanHdr *)(buf + sizeof(udphdr)+ sizeof(struct ip)
     184             :                                    + sizeof(struct ether_header));
     185           0 :     vxlanhdr->vxlan_id =  ntohl(vxlan_id << 8);
     186           0 :     vxlanhdr->reserved = ntohl(kVxlanRABit | kVxlanIBit);
     187             : 
     188             :     //Fill  inner packet details.
     189           0 :     pkt_info->eth = (struct ether_header *)(vxlanhdr + 1);
     190             : 
     191           0 :     pkt_handler->EthHdr(in_source_mac_, in_dst_mac_,
     192             :                         ETHERTYPE_IP);
     193             : 
     194           0 :     pkt_info->ip = (struct ip *)(pkt_info->eth +1);
     195           0 :     Ip4Address dip = Ip4Address::from_string("127.0.0.1", ec);
     196           0 :     pkt_info->transp.udp = (struct udphdr *)(pkt_info->ip + 1);
     197           0 :     len = data_len_+sizeof(struct udphdr);
     198           0 :     pkt_handler->UdpHdr(len, sip_.to_v4().to_ulong(), sport_, dip.to_ulong(),
     199             :                         VXLAN_UDP_DEST_PORT);
     200           0 :     pkt_handler->IpHdr(len + sizeof(struct ip), ntohl(sip_.to_v4().to_ulong()),
     201           0 :                        ntohl(dip.to_ulong()), proto_,
     202             :                        DEFAULT_IP_ID, DEFAULT_IP_TTL);
     203             :     //pkt_handler->SetDiagChkSum();
     204           0 :     pkt_handler->pkt_info()->set_len(len_);
     205           0 :     PhysicalInterfaceKey key1(agent->fabric_interface_name());
     206           0 :     Interface *intf = static_cast<Interface *>
     207           0 :                 (agent->interface_table()->Find(&key1, true));
     208           0 :     pkt_handler->Send(intf->id(), agent->fabric_vrf()->vrf_id(),
     209             :                       AgentHdr::TX_SWITCH, CMD_PARAM_PACKET_CTRL,
     210             :                       CMD_PARAM_1_DIAG, PktHandler::DIAG);
     211             : 
     212           0 :     delete pkt_handler;
     213           0 :     return;
     214           0 : }
     215             : 
     216           0 : void OverlayPing::HandleReply(DiagPktHandler *handler) {
     217           0 :     PingResp *resp = new PingResp();
     218           0 :     OverlayOamPktData *pktdata = (OverlayOamPktData*) handler->GetData();
     219           0 :     resp->set_seq_no(ntohl(pktdata->seq_no_));
     220           0 :     boost::posix_time::ptime time = microsec_clock::universal_time();
     221           0 :     boost::posix_time::time_duration rtt = time - senttime_;
     222           0 :     avg_rtt_ += rtt;
     223           0 :     std::string rtt_str;
     224           0 :     time_duration_to_string(rtt, rtt_str);
     225           0 :     resp->set_rtt(rtt_str);
     226           0 :     resp->set_resp("Success");
     227           0 :     resp->set_context(context_);
     228           0 :     resp->set_more(true);
     229           0 :     resp->Response();
     230           0 : }
     231             : 
     232           0 : void OverlayPing::RequestTimedOut(uint32_t seq_no) {
     233           0 :     PingResp *resp = new PingResp();
     234           0 :     pkt_lost_count_++;
     235           0 :     resp->set_resp("Timed Out");
     236           0 :     resp->set_seq_no(seq_no_);
     237           0 :     resp->set_context(context_);
     238           0 :     resp->set_more(true);
     239           0 :     resp->Response();
     240           0 : }
     241             : 
     242           0 : void OverlayPing::SendSummary(){
     243           0 : PingSummaryResp *resp = new PingSummaryResp();
     244             : 
     245           0 : if (pkt_lost_count_ != GetMaxAttempts()) {
     246             :         //If we had some succesful replies, send in
     247             :         //average rtt for succesful ping requests
     248           0 :         avg_rtt_ = (avg_rtt_ / (seq_no_ - pkt_lost_count_));
     249           0 :         std::string avg_rtt_string;
     250           0 :         time_duration_to_string(avg_rtt_, avg_rtt_string);
     251           0 :         resp->set_average_rtt(avg_rtt_string);
     252           0 :     }
     253           0 :     resp->set_request_sent(seq_no_);
     254           0 :     resp->set_response_received(seq_no_ - pkt_lost_count_);
     255           0 :     uint32_t pkt_loss_percent = (pkt_lost_count_ * 100/seq_no_);
     256           0 :     resp->set_pkt_loss(pkt_loss_percent);
     257           0 :     resp->set_context(context_);
     258           0 :     resp->Response();
     259           0 : }

Generated by: LCOV version 1.14