LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - proto_handler.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 157 0.0 %
Date: 2026-06-18 01:51:13 Functions: 0 27 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <stdint.h>
       6             : #include "base/os.h"
       7             : #include "vr_defs.h"
       8             : #include "pkt/proto_handler.h"
       9             : #include "pkt/pkt_init.h"
      10             : #include "pkt/packet_buffer.h"
      11             : 
      12             : ///////////////////////////////////////////////////////////////////////////////
      13             : 
      14           0 : ProtoHandler::ProtoHandler(Agent *agent, boost::shared_ptr<PktInfo> info,
      15           0 :                            boost::asio::io_context &io)
      16           0 :     : agent_(agent), pkt_info_(info), io_(io) {}
      17             : 
      18           0 : ProtoHandler::~ProtoHandler() {
      19           0 : }
      20             : 
      21           0 : uint32_t ProtoHandler::EncapHeaderLen() const {
      22           0 :     return agent_->pkt()->pkt_handler()->EncapHeaderLen();
      23             : }
      24             : 
      25             : // send packet to the pkt0 interface
      26           0 : void ProtoHandler::Send(uint32_t itf, uint32_t vrf, uint16_t cmd,
      27             :                         PktHandler::PktModuleName mod) {
      28           0 :     Send(itf, vrf, cmd, 0, 0, mod);
      29           0 : }
      30             : 
      31           0 : void ProtoHandler::Send(uint32_t itf, uint32_t vrf, uint16_t cmd,
      32             :                         uint32_t param1, uint32_t param2,
      33             :                         PktHandler::PktModuleName mod) {
      34             :     // If pkt_info_->pkt is non-NULL, pkt is freed in destructor of pkt_info_
      35           0 :     if (agent_->pkt()->pkt_handler() == NULL) {
      36           0 :         return;
      37             :     }
      38             : 
      39           0 :     AgentHdr hdr(itf, vrf, cmd, param1, param2);
      40           0 :     agent_->pkt()->pkt_handler()->Send(hdr, pkt_info_->packet_buffer_ptr());
      41           0 : }
      42             : 
      43           0 : int ProtoHandler::EthHdr(char *buff, uint16_t len, const MacAddress &src,
      44             :                          const MacAddress &dest, const uint16_t proto,
      45             :                          uint16_t vlan_id) {
      46           0 :     struct ether_header *eth = (struct ether_header *)buff;
      47           0 :     uint16_t encap_len = sizeof(struct ether_header);
      48             : 
      49           0 :     if (vlan_id != VmInterface::kInvalidVlanId) {
      50           0 :         encap_len += 4;
      51             :     }
      52             : 
      53           0 :     if (len < encap_len) {
      54           0 :         return 0;
      55             :     }
      56             : 
      57           0 :     dest.ToArray(eth->ether_dhost, sizeof(eth->ether_dhost));
      58           0 :     src.ToArray(eth->ether_shost, sizeof(eth->ether_shost));
      59             : 
      60           0 :     uint16_t *ptr = (uint16_t *) (buff + ETHER_ADDR_LEN * 2);
      61           0 :     if (vlan_id != VmInterface::kInvalidVlanId) {
      62           0 :         *ptr = htons(ETHERTYPE_VLAN);
      63           0 :         ptr++;
      64           0 :         *ptr = htons(vlan_id & 0xFFF);
      65           0 :         ptr++;
      66             :     }
      67             : 
      68           0 :     *ptr = htons(proto);
      69           0 :     return encap_len;
      70             : }
      71             : 
      72           0 : int ProtoHandler::EthHdr(const MacAddress &src, const MacAddress &dest,
      73             :                          const uint16_t proto) {
      74           0 :     return EthHdr((char *)pkt_info_->eth, sizeof(struct ether_header), src,
      75           0 :                   dest, proto, VmInterface::kInvalidVlanId);
      76             : }
      77             : 
      78           0 : int ProtoHandler::EthHdr(char *buff, uint16_t len, const Interface *intrface,
      79             :                          const MacAddress &src, const MacAddress &dest,
      80             :                          const uint16_t proto) {
      81           0 :     uint16_t vlan_id = VmInterface::kInvalidVlanId;
      82           0 :     if (intrface && intrface->type() == Interface::VM_INTERFACE &&
      83           0 :            !(agent_->tsn_enabled())) {
      84           0 :         vlan_id = static_cast<const VmInterface *>(intrface)->tx_vlan_id();
      85             :     }
      86             : 
      87           0 :     return EthHdr(buff, len, src, dest, proto, vlan_id);
      88             : }
      89             : 
      90           0 : int ProtoHandler::EthHdr(char *buff, uint16_t len, uint32_t ifindex,
      91             :                          const MacAddress &src, const MacAddress &dest,
      92             :                          const uint16_t proto) {
      93           0 :     const Interface *intf = agent()->interface_table()->FindInterface(ifindex);
      94           0 :     return EthHdr(buff, len, intf, src, dest, proto);
      95             : }
      96             : 
      97           0 : void ProtoHandler::VlanHdr(uint8_t *ptr, uint16_t tci) {
      98           0 :     vlanhdr *vlan = reinterpret_cast<vlanhdr *>(ptr);
      99           0 :     vlan->tpid = htons(0x8100);
     100           0 :     vlan->tci = htons(tci);
     101           0 :     vlan += 1;
     102           0 :     vlan->tpid = htons(0x800);
     103           0 :     return;
     104             : }
     105             : 
     106           0 : uint16_t ProtoHandler::IpHdr(char *buff, uint16_t buf_len, uint16_t len,
     107             :                              in_addr_t src, in_addr_t dest, uint8_t protocol,
     108             :                              uint16_t id, uint8_t ttl) {
     109           0 :     struct ip *ip = (struct ip *)buff;
     110           0 :     if (buf_len < sizeof(struct ip))
     111           0 :         return 0;
     112             : 
     113           0 :     ip->ip_hl = 5;
     114           0 :     ip->ip_v = 4;
     115           0 :     ip->ip_tos = 0;
     116           0 :     ip->ip_len = htons(len);
     117           0 :     ip->ip_id = htons(id);
     118           0 :     ip->ip_off = 0;
     119           0 :     ip->ip_ttl = ttl;
     120           0 :     ip->ip_p = protocol;
     121           0 :     ip->ip_sum = 0;
     122           0 :     ip->ip_src.s_addr = src;
     123           0 :     ip->ip_dst.s_addr = dest;
     124             : 
     125           0 :     ip->ip_sum = Csum((uint16_t *)ip, ip->ip_hl * 4, 0);
     126           0 :     return sizeof(struct ip);
     127             : }
     128             : 
     129           0 : void ProtoHandler::IpHdr(uint16_t len, in_addr_t src, in_addr_t dest,
     130             :                          uint8_t protocol, uint16_t id, uint8_t ttl) {
     131             : 
     132           0 :     IpHdr((char *)pkt_info_->ip, sizeof(struct ip), len,
     133             :           src, dest, protocol, id, ttl);
     134           0 : }
     135             : 
     136           0 : void ProtoHandler::Ip6Hdr(ip6_hdr *ip, uint16_t plen, uint8_t next_header,
     137             :                           uint8_t hlim, uint8_t *src, uint8_t *dest) {
     138           0 :     ip->ip6_flow = htonl(0x60000000); // version 6, TC and Flow set to 0
     139           0 :     ip->ip6_plen = htons(plen);
     140           0 :     ip->ip6_nxt = next_header;
     141           0 :     ip->ip6_hlim= hlim;
     142           0 :     memcpy(ip->ip6_src.s6_addr, src, 16);
     143           0 :     memcpy(ip->ip6_dst.s6_addr, dest, 16);
     144           0 : }
     145             : 
     146           0 : void ProtoHandler::FillUdpHdr(udphdr *udp, uint16_t len,
     147             :                               uint16_t src_port, uint16_t dest_port) {
     148           0 :     udp->uh_sport = htons(src_port);
     149           0 :     udp->uh_dport = htons(dest_port);
     150           0 :     udp->uh_ulen = htons(len);
     151           0 :     udp->uh_sum = 0;
     152           0 : }
     153             : 
     154           0 : uint16_t ProtoHandler::UdpHdr(udphdr *udp, uint16_t buf_len, uint16_t len,
     155             :                               in_addr_t src, uint16_t src_port, in_addr_t dest,
     156             :                               uint16_t dest_port) {
     157           0 :     if (buf_len < sizeof(udphdr))
     158           0 :         return 0;
     159             : 
     160           0 :     FillUdpHdr(udp, len, src_port, dest_port);
     161             : #ifdef VNSW_AGENT_UDP_CSUM
     162             :     udp->uh_sum = UdpCsum(src, dest, len, udp);
     163             : #endif
     164             : 
     165           0 :     return sizeof(udphdr);
     166             : }
     167             : 
     168           0 : void ProtoHandler::UdpHdr(uint16_t len, in_addr_t src, uint16_t src_port,
     169             :                           in_addr_t dest, uint16_t dest_port) {
     170           0 :     UdpHdr(pkt_info_->transp.udp, sizeof(udphdr), len, src, src_port,
     171             :            dest, dest_port);
     172           0 : }
     173             : 
     174           0 : uint16_t ProtoHandler::IcmpHdr(char *buff, uint16_t buf_len, uint8_t type,
     175             :                                uint8_t code, uint16_t word1, uint16_t word2) {
     176           0 :     struct icmp *hdr = ((struct icmp *)buff);
     177           0 :     if (buf_len < sizeof(hdr))
     178           0 :         return 0;
     179             : 
     180           0 :     memset(hdr, 0, sizeof(struct icmp));
     181             : 
     182           0 :     hdr->icmp_type = type;
     183           0 :     hdr->icmp_code = code;
     184           0 :     if(type != ICMP_UNREACH) {
     185           0 :         LOG(ERROR,
     186             :           "Error type != ICMP_UNREACH. BackTrace: " << AgentBackTrace(1));
     187           0 :         return 0;
     188             :     }
     189           0 :     hdr->icmp_nextmtu = htons(word2);
     190           0 :     hdr->icmp_cksum = 0;
     191           0 :     if (type == ICMP_UNREACH)
     192           0 :         return ICMP_UNREACH_HDR_LEN;
     193           0 :     return 0;
     194             : }
     195             : 
     196           0 : void ProtoHandler::IcmpChecksum(char *buff, uint16_t buf_len) {
     197           0 :     struct icmp *hdr = ((struct icmp *)buff);
     198           0 :     hdr->icmp_cksum = Csum((uint16_t *)buff, buf_len, 0);
     199           0 : }
     200             : 
     201           0 : void ProtoHandler::IgmpChecksum(char *buff, uint16_t buf_len) {
     202           0 :     struct igmp *hdr = ((struct igmp *)buff);
     203           0 :     hdr->igmp_cksum = Csum((uint16_t *)buff, buf_len, 0);
     204           0 : }
     205             : 
     206           0 : void ProtoHandler::UdpHdr(udphdr *udp ,uint16_t len, const uint8_t *src,
     207             :                           uint16_t src_port, const uint8_t *dest,
     208             :                           uint16_t dest_port, uint8_t next_hdr) {
     209           0 :     FillUdpHdr(udp, len, src_port, dest_port);
     210           0 :     pkt_info_->transp.udp->uh_sum = Ipv6Csum(src, dest, len, next_hdr,
     211           0 :                                             (uint16_t *)pkt_info_->transp.udp);
     212           0 : }
     213             : 
     214           0 : void ProtoHandler::UdpHdr(uint16_t len, const uint8_t *src, uint16_t src_port,
     215             :                           const uint8_t *dest, uint16_t dest_port,
     216             :                           uint8_t next_hdr) {
     217           0 :     FillUdpHdr(pkt_info_->transp.udp, len, src_port, dest_port);
     218           0 :     pkt_info_->transp.udp->uh_sum = Ipv6Csum(src, dest, len, next_hdr,
     219           0 :                                             (uint16_t *)pkt_info_->transp.udp);
     220           0 : }
     221             : 
     222           0 : uint32_t ProtoHandler::Sum(uint16_t *ptr, std::size_t len, uint32_t sum) const {
     223           0 :     while (len > 1) {
     224           0 :         sum += *ptr++;
     225           0 :         len -= 2;
     226           0 :         if (sum & 0x80000000)
     227           0 :             sum = (sum & 0xFFFF) + (sum >> 16);
     228             :     }
     229             : 
     230           0 :     if (len > 0)
     231           0 :         sum += *(uint8_t *)ptr;
     232             : 
     233           0 :     return sum;
     234             : }
     235             : 
     236           0 : uint16_t ProtoHandler::Csum(uint16_t *ptr, std::size_t len, uint32_t sum) const{
     237           0 :     sum = Sum(ptr, len, sum);
     238             : 
     239           0 :     while (sum >> 16)
     240           0 :         sum = (sum & 0xFFFF) + (sum >> 16);
     241             : 
     242           0 :     return ~sum;
     243             : }
     244             : 
     245           0 : uint16_t ProtoHandler::UdpCsum(in_addr_t src, in_addr_t dest,
     246             :                                std::size_t len, udphdr *udp) const {
     247           0 :     uint32_t sum = 0;
     248           0 :     PseudoUdpHdr phdr(src, dest, IPPROTO_UDP, htons(len));
     249           0 :     sum = Sum((uint16_t *)&phdr, sizeof(PseudoUdpHdr), sum);
     250           0 :     return Csum((uint16_t *)udp, len, sum);
     251             : }
     252             : 
     253           0 : uint16_t ProtoHandler::Ipv6Csum(const uint8_t *src, const uint8_t *dest,
     254             :                                 uint16_t plen, uint8_t next_hdr,
     255             :                                 uint16_t *hdr) const {
     256           0 :     uint32_t len = htonl((uint32_t)plen);
     257           0 :     uint32_t next = htonl((uint32_t)next_hdr);
     258             : 
     259           0 :     uint32_t pseudo = 0;
     260           0 :     pseudo = Sum((uint16_t *)src, 16, 0);
     261           0 :     pseudo = Sum((uint16_t *)dest, 16, pseudo);
     262           0 :     pseudo = Sum((uint16_t *)&len, 4, pseudo);
     263           0 :     pseudo = Sum((uint16_t *)&next, 4, pseudo);
     264           0 :     return Csum(hdr, plen, pseudo);
     265             : }
     266             : 
     267           0 : uint16_t ProtoHandler::Icmpv6Csum(const uint8_t *src, const uint8_t *dest,
     268             :                                   icmp6_hdr *icmp, uint16_t plen) const {
     269           0 :     return Ipv6Csum(src, dest, plen, IPPROTO_ICMPV6, (uint16_t *)icmp);
     270             : }
     271             : 
     272             : ///////////////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.14