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

Generated by: LCOV version 1.14