LCOV - code coverage report
Current view: top level - vnsw/agent/services - icmpv6_error_handler.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 62 0.0 %
Date: 2026-11-09 02:10:49 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : #include "base/os.h"
       6             : #include <netinet/icmp6.h>
       7             : #include <vr_defs.h>
       8             : #include <cmn/agent_cmn.h>
       9             : #include <oper/interface_common.h>
      10             : #include <oper/vn.h>
      11             : #include <pkt/pkt_init.h>
      12             : #include <services/icmpv6_error_proto.h>
      13             : #include <services/icmpv6_error_handler.h>
      14             : #include <services/icmpv6_handler.h>
      15             : #include <services/services_init.h>
      16             : #include <services/icmpv6_proto.h>
      17             : 
      18             : 
      19             : extern SandeshTraceBufferPtr Icmpv6TraceBuf;
      20             : 
      21           0 : Icmpv6ErrorHandler::Icmpv6ErrorHandler(Agent *agent, Icmpv6ErrorProto *proto,
      22             :                                        boost::shared_ptr<PktInfo> info,
      23           0 :                                        boost::asio::io_context *io) :
      24           0 :     ProtoHandler(agent, info, *io), proto_(proto) {
      25           0 : }
      26             : 
      27           0 : Icmpv6ErrorHandler::~Icmpv6ErrorHandler() {
      28           0 : }
      29             : 
      30           0 : bool Icmpv6ErrorHandler::ValidatePacket() {
      31           0 :     if (pkt_info_->len < (sizeof(struct ether_header) + sizeof(struct ip6_hdr)))
      32           0 :         return false;
      33           0 :     return true;
      34             : }
      35             : 
      36           0 : bool Icmpv6ErrorHandler::Run() {
      37             : 
      38           0 :     if (ValidatePacket() == false) {
      39           0 :         proto_->increment_drops();
      40           0 :         return true;
      41             :     }
      42             : 
      43           0 :     VmInterface *vm_itf = dynamic_cast<VmInterface *>
      44           0 :         (agent()->interface_table()->FindInterface(GetInterfaceIndex()));
      45           0 :     if (vm_itf == NULL || vm_itf->layer3_forwarding() == false ||
      46           0 :         vm_itf->IsActive() == false) {
      47           0 :         proto_->increment_interface_errors();
      48           0 :         return true;
      49             :     }
      50           0 :     return SendIcmpv6Error(vm_itf);
      51             : }
      52             : 
      53             : // Generate ICMP error
      54           0 : bool Icmpv6ErrorHandler::SendIcmpv6Error(VmInterface *intf) {
      55             : 
      56           0 :     char *buff = (char *)pkt_info_->pkt;
      57           0 :     uint16_t buff_len = pkt_info_->packet_buffer()->data_len();
      58             :     char data[ICMPV6_PAYLOAD_LEN];
      59           0 :     int len = ntohs(pkt_info_->ip6->ip6_plen);
      60             : 
      61           0 :     if (len > ICMPV6_PAYLOAD_LEN)
      62           0 :         len = ICMPV6_PAYLOAD_LEN;
      63             : 
      64           0 :     memcpy(data, pkt_info_->ip6, len);
      65             : 
      66           0 :     Ip6Address source_address;
      67           0 :     boost::system::error_code ec;
      68           0 :     const VnIpam *ipam = intf->vn()->GetIpam(pkt_info_->ip_saddr.to_v6());
      69           0 :     if (ipam != NULL) {
      70           0 :         if (ipam->default_gw.is_v6())
      71           0 :             source_address = ipam->default_gw.to_v6();
      72             :     }
      73             :     // If source address is not found, use vhost address mapped v6 address.
      74             :     // vrouter forwards the icmp error packets as part of the original flow.
      75           0 :     if (source_address.is_unspecified())
      76           0 :         source_address = Ip6Address::v4_mapped(agent()->router_id());
      77             : 
      78             :     uint32_t interface =
      79           0 :         (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
      80           0 :         pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex();
      81             : 
      82           0 :     uint16_t eth_len = EthHdr(buff, buff_len, interface,
      83             :                               agent()->vhost_interface()->mac(),
      84           0 :                               MacAddress(pkt_info_->eth->ether_shost),
      85           0 :                               ETHERTYPE_IPV6);
      86             : 
      87           0 :     pkt_info_->ip6 = (struct ip6_hdr *)(buff + eth_len);
      88           0 :     Ip6Hdr(pkt_info_->ip6, len+ICMP_UNREACH_HDR_LEN, IPV6_ICMP_NEXT_HEADER,
      89           0 :            255, source_address.to_bytes().data(),
      90           0 :            pkt_info_->ip_saddr.to_v6().to_bytes().data());
      91             : 
      92           0 :     icmp6_hdr *icmp = pkt_info_->transp.icmp6 =
      93           0 :         (icmp6_hdr *)(pkt_info_->pkt + eth_len
      94           0 :                       + sizeof(ip6_hdr));
      95           0 :     icmp->icmp6_type = ICMP6_PACKET_TOO_BIG;
      96           0 :     icmp->icmp6_code = 0;
      97           0 :     icmp->icmp6_mtu = htonl(pkt_info_->agent_hdr.mtu);
      98           0 :     icmp->icmp6_cksum = 0;
      99           0 :     memcpy(buff + sizeof(ip6_hdr) + eth_len+ICMP_UNREACH_HDR_LEN, data, len);
     100           0 :     icmp->icmp6_cksum =
     101           0 :         Icmpv6Csum(source_address.to_bytes().data(),
     102           0 :                    pkt_info_->ip_saddr.to_v6().to_bytes().data(),
     103           0 :                    icmp, len + ICMP_UNREACH_HDR_LEN);
     104           0 :     pkt_info_->set_len(len + sizeof(ip6_hdr) + eth_len+ICMP_UNREACH_HDR_LEN);
     105             : 
     106             :     uint16_t command =
     107           0 :         (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
     108           0 :         (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH;
     109             : 
     110           0 :     Send(GetInterfaceIndex(), pkt_info_->vrf, command,
     111             :          PktHandler::ICMPV6);
     112           0 :     return true;
     113             : }

Generated by: LCOV version 1.14