LCOV - code coverage report
Current view: top level - root/contrail/vrouter/include - vr_packet.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 300 442 67.9 %
Date: 2026-11-09 02:10:49 Functions: 55 67 82.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_packet.h -- packet handling functionality of vrouter
       3             :  *
       4             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       5             :  * Copyright Contributors to the OpenSDN project
       6             :  */
       7             : #ifndef __VR_PACKET_H__
       8             : #define __VR_PACKET_H__
       9             : 
      10             : #include "vr_defs.h"
      11             : #include "vr_qos.h"
      12             : #include "vr_flow.h"
      13             : #include "vrouter.h"
      14             : #include "vr_btable.h"
      15             : #include "vr_bridge.h"
      16             : #include "vr_mirror.h"
      17             : #include "vr_os.h"
      18             : #include "vr_pkt_droplog.h"
      19             : #include "vr_hash.h"
      20             : 
      21             : /* ethernet header */
      22             : #define VR_ETHER_DMAC_OFF       0
      23             : #define VR_ETHER_SMAC_OFF       6
      24             : #define VR_ETHER_PROTO_OFF      12
      25             : #define VR_ETHER_VLAN_PROTO_OFF 16
      26             : 
      27             : #define VR_ETHER_PROTO_MAC_OFF  1
      28             : #define VR_ETHER_PROTO_MAC_LEN  2
      29             : 
      30             : #define VR_IP_PROTO_ICMP        1
      31             : #define VR_IP_PROTO_IGMP        2
      32             : #define VR_IP_PROTO_TCP         6
      33             : #define VR_IP_PROTO_UDP         17
      34             : #define VR_IP_PROTO_GRE         47
      35             : #define VR_IP_PROTO_ICMP6       58
      36             : #define VR_IP_PROTO_SCTP        132
      37             : 
      38             : #define VR_GRE_FLAG_CSUM        (ntohs(0x8000))
      39             : #define VR_GRE_FLAG_KEY         (ntohs(0x2000))
      40             : 
      41             : #define VR_DHCP_SRC_PORT        68
      42             : #define VR_DHCP6_SRC_PORT       546
      43             : 
      44             : #define VR_BFD_SINGLE_HOP_PORT  3784
      45             : #define VR_BFD_STATE_FLAG_MASK  0xc0
      46             : 
      47             : /* Size of basic GRE header */
      48             : #define VR_GRE_BASIC_HDR_LEN    4
      49             : 
      50             : /* Size of GRE header with checksum */
      51             : #define VR_GRE_CKSUM_HDR_LEN    8
      52             : 
      53             : /* Size of GRE header with key */
      54             : #define VR_GRE_KEY_HDR_LEN      8
      55             : 
      56             : #define VR_DYNAMIC_PORT_START   0
      57             : #define VR_DYNAMIC_PORT_END     65535
      58             : 
      59             : /*
      60             :  * Overlay length used for TCP MSS adjust. For UDP outer header, overlay
      61             :  * len is 20 (IP header) + 8 (UDP) + 4 (MPLS). For GRE, it is 20 (IP header)
      62             :  * + 8 (GRE header + key) + 4 (MPLS). Instead of allowing for only one
      63             :  * label, we will allow a maximum of 3 labels, so we end up with 40 bytes
      64             :  * of overleay headers.
      65             :  */
      66             : #define VROUTER_OVERLAY_LEN 40
      67             : 
      68             : /*
      69             :  * Over lay length is going to be ethernet header bytes more incase of L2 packet
      70             :  */
      71             : #define VROUTER_L2_OVERLAY_LEN  62
      72             : 
      73             : 
      74             : /* packets originated by DP. For eg: mirrored packets */
      75             : #define VP_FLAG_FROM_DP         (1 << 0)
      76             : #define VP_FLAG_TO_ME           (1 << 1)
      77             : /* request policy lookup - for components other than interfaces */
      78             : #define VP_FLAG_FLOW_GET        (1 << 2)
      79             : /* packet already went through one round of policy lookup */
      80             : #define VP_FLAG_FLOW_SET        (1 << 3)
      81             : #define VP_FLAG_MULTICAST       (1 << 4)
      82             : /* Partially checksummed by VM */
      83             : #define VP_FLAG_CSUM_PARTIAL    (1 << 5)
      84             : /* Attempt to do receive offload on inner packet */
      85             : #define VP_FLAG_GRO             (1 << 6)
      86             : /* Attempt to do segmentation on inner packet */
      87             : #define VP_FLAG_GSO             (1 << 7)
      88             : /* Diagnostic packet */
      89             : #define VP_FLAG_DIAG            (1 << 8)
      90             : #define VP_FLAG_GROED           (1 << 9)
      91             : 
      92             : /*
      93             :  * possible 256 values of what a packet can be. currently, this value is
      94             :  * used only as an aid in fragmentation.
      95             :  */
      96             : #define VP_TYPE_NULL            0
      97             : 
      98             : #define VP_TYPE_ARP             1
      99             : #define VP_TYPE_IP              2
     100             : #define VP_TYPE_IP6             3
     101             : 
     102             : #define VP_TYPE_IPOIP           4
     103             : #define VP_TYPE_IP6OIP          5
     104             : 
     105             : #define VP_TYPE_AGENT           6
     106             : #define VP_TYPE_PBB             7
     107             : #define VP_TYPE_UNKNOWN         8
     108             : #define VP_TYPE_MAX             VP_TYPE_UNKNOWN
     109             : 
     110             : 
     111             : /*
     112             :  * Values to define how to proceed with handling a packet.
     113             :  */
     114             : #define PKT_RET_FAST_PATH           1
     115             : #define PKT_RET_SLOW_PATH           2
     116             : #define PKT_RET_ERROR               3
     117             : #define PKT_RET_UNHANDLED           4
     118             : 
     119             : /*
     120             :  * Values to define the MPLS tunnel type
     121             :  */
     122             : #define PKT_MPLS_TUNNEL_INVALID               0x00
     123             : #define PKT_MPLS_TUNNEL_L3                    0x01
     124             : #define PKT_MPLS_TUNNEL_L2_UCAST              0x02
     125             : #define PKT_MPLS_TUNNEL_L2_MCAST              0x03
     126             : #define PKT_MPLS_TUNNEL_L2_CONTROL_DATA       0x04
     127             : 
     128             : 
     129             : /*
     130             :  * Values to defaine the srouce of Multicast packet
     131             :  */
     132             : #define PKT_SRC_TOR_REPL_TREE      0x1
     133             : #define PKT_SRC_INGRESS_REPL_TREE  0x2
     134             : #define PKT_SRC_EDGE_REPL_TREE     0x4
     135             : #define PKT_SRC_ANY_REPL_TREE      (PKT_SRC_TOR_REPL_TREE | \
     136             :                 PKT_SRC_SRC_REPL_TREE | PKT_SRC_EDGE_REPL_TREE)
     137             : 
     138             : 
     139             : /*
     140             :  * Values to define the encap type of outgoing packet
     141             :  */
     142             : #define PKT_ENCAP_MPLS          0x01
     143             : #define PKT_ENCAP_VXLAN         0x02
     144             : 
     145             : /*
     146             :  * NOTE: Please do not add any more fields without ensuring
     147             :  * that the size is <= 48 bytes in 64 bit systems.
     148             :  */
     149             : struct vr_packet {
     150             :     unsigned char *vp_head;
     151             :     struct vr_interface *vp_if;
     152             :     struct vr_nexthop *vp_nh;
     153             :     unsigned short vp_data;
     154             :     unsigned short vp_tail;
     155             :     unsigned short vp_len;
     156             :     unsigned short vp_end;
     157             :     unsigned short vp_network_h;
     158             :     unsigned short vp_flags;
     159             :     unsigned short vp_inner_network_h;
     160             :     unsigned char vp_cpu;
     161             :     unsigned char vp_type;
     162             :     unsigned char vp_ttl;
     163             :     unsigned char vp_queue;
     164             :     unsigned char vp_priority:4,
     165             :                   vp_rx_pass:1,
     166             :                   vp_notused:3;
     167             : };
     168             : 
     169             : 
     170             : #define VP_QUEUE_INVALID    0xFF
     171             : #define VP_PRIORITY_INVALID 0xF
     172             : 
     173             : extern void pkt_reset(struct vr_packet *);
     174             : extern struct vr_packet *pkt_copy(struct vr_packet *, unsigned short,
     175             :         unsigned short);
     176             : extern struct vr_packet *pkt_cow(struct vr_packet *, unsigned short);
     177             : extern int vr_myip(struct vr_interface *, unsigned int);
     178             : extern unsigned int vr_get_pkt_hash(struct vr_packet *);
     179             : 
     180             : typedef enum {
     181             :     L4_TYPE_UNKNOWN,
     182             :     L4_TYPE_DHCP_REQUEST,
     183             :     L4_TYPE_ROUTER_SOLICITATION,
     184             :     L4_TYPE_NEIGHBOUR_SOLICITATION,
     185             :     L4_TYPE_NEIGHBOUR_ADVERTISEMENT,
     186             :     L4_TYPE_IGMP,
     187             : } l4_pkt_type_t;
     188             : 
     189             : __attribute__packed__open__
     190             : struct vr_eth {
     191             :     unsigned char eth_dmac[VR_ETHER_ALEN];
     192             :     unsigned char eth_smac[VR_ETHER_ALEN];
     193             :     unsigned short eth_proto;
     194             : } __attribute__packed__close__;
     195             : 
     196             : #define VLAN_ID_INVALID         0xFFFF
     197             : #define VLAN_ID_MAX             0xFFFF
     198             : #define VR_VLAN_PRIORITY_SHIFT  13
     199             : 
     200             : __attribute__packed__open__
     201             : struct vr_vlan_hdr {
     202             :     unsigned short vlan_tag;
     203             :     unsigned short vlan_proto;
     204             : } __attribute__packed__close__;
     205             : 
     206             : __attribute__packed__open__
     207             : struct vr_pbb_itag {
     208             :     uint8_t    pbbi_pcp:3,
     209             :                pbbi_dei:1,
     210             :                pbbi_uca:1,
     211             :                pbbi_res:3;
     212             :     uint32_t   pbbi_isid:24;
     213             : } __attribute__packed__close__;
     214             : 
     215             : __attribute__packed__open__
     216             : struct vr_eth_hbs_md {
     217             :     unsigned short magic_dmac;
     218             :     unsigned int flow_id_dmac;
     219             :     unsigned short magic_smac;
     220             :     unsigned int flow_id_smac;
     221             :     unsigned short eth_proto;
     222             : } __attribute__packed__close__;
     223             : 
     224             : #define VR_ARP_HW_LEN           6
     225             : #define VR_ARP_OP_REQUEST       1
     226             : #define VR_ARP_OP_REPLY         2
     227             : 
     228             : #define VR_ETH_PROTO_ARP        0x806
     229             : #define VR_ETH_PROTO_IP         0x800
     230             : #define VR_ETH_PROTO_IP6        0x86DD
     231             : #define VR_ETH_PROTO_VLAN       0x8100
     232             : #define VR_ETH_PROTO_PBB        0x88E7
     233             : 
     234             : #define VR_DIAG_CSUM         0xffff
     235             : #define VR_UDP_PORT_RANGE_START 49152
     236             : #define VR_UDP_PORT_RANGE_END   65535
     237             : 
     238             : #define VR_INVALID_MTU  0xFFFF
     239             : 
     240             : static inline int8_t
     241           4 : vr_vlan_get_tos(uint8_t *eth_data)
     242             : {
     243           4 :     struct vr_eth *eth = (struct vr_eth *)eth_data;
     244             :     struct vr_vlan_hdr *vlan;
     245             : 
     246           4 :     if (ntohs(eth->eth_proto) != VR_ETH_PROTO_VLAN)
     247           4 :         return -1;
     248             : 
     249           0 :     vlan = (struct vr_vlan_hdr *)(eth + 1);
     250           0 :     return (ntohs(vlan->vlan_tag) >> VR_VLAN_PRIORITY_SHIFT);
     251             : }
     252             : 
     253             : #ifdef arp_op
     254             : #undef arp_op
     255             : #endif
     256             : 
     257             : #define VR_ARP_HW_TYPE_ETHER    1
     258             : #define VR_ARP_PROTO_LEN_IPV4   4
     259             : 
     260             : __attribute__packed__open__
     261             : struct vr_arp {
     262             :     unsigned short arp_hw;
     263             :     unsigned short arp_proto;
     264             :     unsigned char arp_hwlen;
     265             :     unsigned char arp_protolen;
     266             :     unsigned short arp_op;
     267             :     unsigned char arp_sha[VR_ARP_HW_LEN];
     268             :     unsigned int arp_spa;
     269             :     unsigned char arp_dha[VR_ARP_HW_LEN];
     270             :     unsigned int arp_dpa;
     271             : } __attribute__packed__close__;
     272             : 
     273             : static inline bool
     274          12 : vr_grat_arp(struct vr_arp *sarp)
     275             : {
     276             :     /*
     277             :      * Treat below two as Gratuitous ARP
     278             :      * Null source IP - ARP Probe
     279             :      * Source IP same as dest IP - ARP Announcement
     280             :      */
     281          12 :     if ((!sarp->arp_spa) || (sarp->arp_spa == sarp->arp_dpa))
     282           0 :         return true;
     283          12 :     return false;
     284             : }
     285             : 
     286             : #define VR_IP_DF                (0x1 << 14)
     287             : #define VR_IP_MF                (0x1 << 13)
     288             : #define VR_IP_FRAG_OFFSET_MASK  (VR_IP_MF - 1)
     289             : #define VR_IP_DSCP(val)         ((val) << 2)
     290             : 
     291             : #define VR_IP_ADDRESS_LEN       4
     292             : 
     293             : #define VR_IP6_MF               0x1
     294             : #define VR_IP6_FRAG_OFFSET_BITS 3
     295             : 
     296             : __attribute__packed__open__
     297             : struct vr_ip {
     298             : #if defined(__KERNEL__) && defined(__linux__)
     299             : #if defined(__LITTLE_ENDIAN_BITFIELD)
     300             :    unsigned char ip_hl:4,
     301             :                  ip_version:4;
     302             : #elif defined(__BIG_ENDIAN_BITFIELD)
     303             :    unsigned char ip_version:4,
     304             :                  ip_hl:4;
     305             : #endif
     306             : #else
     307             : #if (__BYTE_ORDER == __LITTLE_ENDIAN)
     308             :    unsigned char ip_hl:4,
     309             :                  ip_version:4;
     310             : #elif (__BYTE_ORDER == __BIG_ENDIAN)
     311             :    unsigned char ip_version:4,
     312             :                  ip_hl:4;
     313             : #endif
     314             : #endif
     315             :     unsigned char ip_tos;
     316             :     unsigned short ip_len;
     317             :     unsigned short ip_id;
     318             :     unsigned short ip_frag_off;
     319             :     unsigned char ip_ttl;
     320             :     unsigned char ip_proto;
     321             :     unsigned short ip_csum;
     322             :     unsigned int ip_saddr;
     323             :     unsigned int ip_daddr;
     324             : } __attribute__packed__close__;
     325             : 
     326             : static inline void
     327          58 : vr_incremental_diff(unsigned int oldval, unsigned int newval,
     328             :         unsigned int *diff)
     329             : {
     330             :     unsigned int tmp;
     331             : 
     332          58 :     tmp = ~oldval + newval;
     333          58 :     if (tmp < newval)
     334           5 :         tmp += 1;
     335             : 
     336          58 :     *diff += tmp;
     337          58 :     if (*diff < tmp)
     338           6 :         *diff += 1;
     339             : 
     340          58 :     return;
     341             : }
     342             : 
     343             : static inline void
     344          48 : vr_ip_incremental_csum(struct vr_ip *ip, unsigned int diff)
     345             : {
     346             :     unsigned int csum;
     347             : 
     348          48 :     diff = (diff >> 16) + (diff & 0xffff);
     349          48 :     if (diff >> 16) {
     350          46 :         diff &= 0xffff;
     351          46 :         diff += 1;
     352             :     }
     353             : 
     354          48 :     csum = ~(ip->ip_csum) & 0xffff;
     355          48 :     csum += diff;
     356          48 :     csum = (csum >> 16) + (csum & 0xffff);
     357          48 :     if (csum >> 16)
     358           0 :         csum = (csum & 0xffff) + 1;
     359             : 
     360          48 :     ip->ip_csum = (~csum & 0xffff);
     361          48 :     return;
     362             : }
     363             : 
     364             : static inline uint8_t
     365         106 : vr_inet_get_tos(struct vr_ip *iph)
     366             : {
     367         106 :     return (iph->ip_tos & 0xFC) >> 2;
     368             : }
     369             : 
     370             : static inline void
     371           0 : vr_inet_set_tos(struct vr_ip *iph, uint8_t tos)
     372             : {
     373           0 :     unsigned int diff = 0;
     374             : 
     375           0 :     if (iph->ip_tos == tos)
     376           0 :         return;
     377             : 
     378           0 :     vr_incremental_diff(iph->ip_tos << 8, tos << 8, &diff);
     379           0 :     iph->ip_tos = tos;
     380           0 :     vr_ip_incremental_csum(iph, diff);
     381             : 
     382           0 :     return;
     383             : }
     384             : 
     385             : 
     386             : #define SOURCE_LINK_LAYER_ADDRESS_OPTION    1
     387             : #define TARGET_LINK_LAYER_ADDRESS_OPTION    2
     388             : 
     389             : __attribute__packed__open__
     390             : struct vr_neighbor_option {
     391             :     uint8_t vno_type;
     392             :     uint8_t vno_length;
     393             :     uint8_t vno_value[];
     394             : } __attribute__packed__close__;
     395             : 
     396             : __attribute__packed__open__
     397             : struct vr_ip6_frag {
     398             :     uint8_t ip6_frag_nxt;
     399             :     uint8_t ip6_frag_res;
     400             :     uint16_t ip6_frag_offset;
     401             :     uint32_t ip6_frag_id;
     402             : } __attribute__packed__close__;
     403             : 
     404             : __attribute__packed__open__
     405             : struct vr_ip6_pseudo {
     406             :     unsigned char ip6_src[VR_IP6_ADDRESS_LEN];
     407             :     unsigned char ip6_dst[VR_IP6_ADDRESS_LEN];
     408             :     unsigned short ip6_l4_length;
     409             :     unsigned short ip6_zero;
     410             :     unsigned int ip6_zero_nh;
     411             : } __attribute__packed__close__;
     412             : 
     413             : 
     414             : __attribute__packed__open__
     415             : struct vr_ip6 {
     416             : #ifdef __KERNEL__
     417             : #if defined(__LITTLE_ENDIAN_BITFIELD)
     418             :     uint8_t         ip6_priority_h:4,
     419             :                     ip6_version:4;
     420             :     uint8_t         ip6_flow_h:4,
     421             :                     ip6_priority_l:4;
     422             : #elif defined(__BIG_ENDIAN_BITFIELD)
     423             :     uint8_t         ip6_version:4,
     424             :                     ip6_priority_h:4;
     425             :     uint8_t         ip6_priority_l:4,
     426             :                     ip6_flow_h:4;
     427             : #endif
     428             : #else
     429             : #if (__BYTE_ORDER == __LITTLE_ENDIAN)
     430             :     uint8_t         ip6_priority_h:4,
     431             :                     ip6_version:4;
     432             :     uint8_t         ip6_flow_h:4,
     433             :                     ip6_priority_l:4;
     434             : #elif (__BYTE_ORDER == __BIG_ENDIAN)
     435             :     uint8_t         ip6_version:4,
     436             :                     ip6_priority_h:4;
     437             :     uint8_t         ip6_priority_l:4,
     438             :                     ip6_flow_h:4;
     439             : #endif
     440             : #endif
     441             :     uint16_t        ip6_flow_l;
     442             :     uint16_t        ip6_plen;
     443             :     uint8_t         ip6_nxt;
     444             :     uint8_t         ip6_hlim;
     445             :     uint8_t         ip6_src[VR_IP6_ADDRESS_LEN];
     446             :     uint8_t         ip6_dst[VR_IP6_ADDRESS_LEN];
     447             : } __attribute__packed__close__;
     448             : 
     449             : #define VR_IP4_MAPPED_IP6_ZERO_BYTES    10
     450             : #define VR_IP4_MAPPED_IP6_ONE_BYTES     2
     451             : 
     452             : static inline uint8_t
     453           9 : vr_inet6_get_tos(struct vr_ip6 *ip6h)
     454             : {
     455           9 :     return ((((ip6h->ip6_priority_h << 4) | (ip6h->ip6_priority_l)) >> 2) & 0x3F);
     456             : }
     457             : 
     458             : static inline void
     459           0 : vr_inet6_set_tos(struct vr_ip6 *ip6h, uint8_t tos)
     460             : {
     461           0 :     ip6h->ip6_priority_h = ((tos << 2) >> 4);
     462           0 :     ip6h->ip6_priority_l = ((tos << 2) & 0xF);
     463             : 
     464           0 :     return;
     465             : }
     466             : 
     467             : static inline void
     468             : vr_inet6_generate_ip6(uint8_t *ip6, uint32_t ip)
     469             : {
     470             :     memset(ip6, 0, VR_IP4_MAPPED_IP6_ZERO_BYTES);
     471             :     memset(ip6 + VR_IP4_MAPPED_IP6_ZERO_BYTES, 1,
     472             :             VR_IP4_MAPPED_IP6_ONE_BYTES);
     473             :     memcpy(ip6 + VR_IP4_MAPPED_IP6_ZERO_BYTES + VR_IP4_MAPPED_IP6_ONE_BYTES,
     474             :             &ip, sizeof(ip));
     475             : 
     476             :     return;
     477             : }
     478             : 
     479             : struct tcphdr;
     480             : 
     481             : bool vr_ip_proto_pull(struct vr_ip *);
     482             : bool vr_ip6_proto_pull(struct vr_ip6 *);
     483             : 
     484             : int vr_ip_transport_parse(struct vr_ip *iph, struct vr_ip6 *ip6h,
     485             :             void **thp, unsigned int frag_size,
     486             :             void (do_tcp_mss_adj)(struct tcphdr *, unsigned short, unsigned char),
     487             :             unsigned int *hlenp, unsigned short *th_csump, unsigned int *tcph_pull_lenp,
     488             :             unsigned int *pull_lenp);
     489             : int vr_inner_pkt_parse(unsigned char *va,
     490             :             int (*tunnel_type_cb)(unsigned int, unsigned int, unsigned short *),
     491             :             int *encap_type, int *pkt_typep, unsigned int *pull_lenp,
     492             :             unsigned int frag_size, struct vr_ip **iphp, struct vr_ip6 **ip6hp,
     493             :             unsigned short gre_udp_encap, unsigned char ip_proto);
     494             : 
     495             : #define MCAST_IP                        (0xE0000000)
     496             : #define MCAST_IP_MASK                   (0xF0000000)
     497             : #define IS_BMCAST_IP(ip) \
     498             :             (((ntohl(ip) & MCAST_IP_MASK) == MCAST_IP) || (ip == 0xFFFFFFFF))
     499             : 
     500             : static inline void
     501           0 : vr_mcast_mac_from_isid(uint32_t isid, uint8_t *mac)
     502             : {
     503           0 :     if (!mac)
     504           0 :         return;
     505             : 
     506           0 :     mac[0] = 1;
     507           0 :     mac[1] = 0x1E;
     508           0 :     mac[2] = 0x83;
     509           0 :     mac[3] = 0xFF & (isid >> 16);
     510           0 :     mac[4] = 0xFF & (isid >> 8);
     511           0 :     mac[5] = 0xFF & isid;
     512             : 
     513           0 :     return;
     514             : }
     515             : 
     516             : #define VR_IP_ADDR_SIZE(type) \
     517             :         ((type == VP_TYPE_IP6) ? VR_IP6_ADDRESS_LEN \
     518             :                                : VR_IP_ADDRESS_LEN)
     519             : 
     520             : static inline unsigned char
     521         161 : vr_eth_proto_to_pkt_type(unsigned short eth_proto)
     522             : {
     523         161 :     if (eth_proto == VR_ETH_PROTO_IP)
     524         126 :         return VP_TYPE_IP;
     525          35 :     else if (eth_proto == VR_ETH_PROTO_IP6)
     526          24 :         return VP_TYPE_IP6;
     527          11 :     else if (eth_proto == VR_ETH_PROTO_ARP)
     528          11 :         return VP_TYPE_ARP;
     529           0 :     else if (eth_proto == VR_ETH_PROTO_PBB)
     530           0 :         return VP_TYPE_PBB;
     531             : 
     532           0 :     return VP_TYPE_UNKNOWN;
     533             : }
     534             : 
     535             : static inline bool
     536         703 : vr_ip_is_ip4(struct vr_ip *iph)
     537             : {
     538         703 :     if ((iph->ip_version & 0xf) == 0x4)
     539         694 :         return true;
     540           9 :     return false;
     541             : }
     542             : 
     543             : static inline bool
     544         177 : vr_ip_is_ip6(struct vr_ip *iph)
     545             : {
     546         177 :     if ((iph->ip_version & 0xf) == 0x6)
     547           9 :         return true;
     548         168 :     return false;
     549             : }
     550             : static inline unsigned char *pkt_network_header(struct vr_packet *);
     551             : 
     552             : static inline bool
     553           1 : vr_ip_dont_fragment_set(struct vr_packet *pkt)
     554             : {
     555             :     struct vr_ip *ip;
     556             : 
     557           1 :     ip = (struct vr_ip *)pkt_network_header(pkt);
     558           1 :     if (vr_ip_is_ip6(ip))
     559           0 :         return true;
     560             : 
     561           1 :     if (ntohs(ip->ip_frag_off) & VR_IP_DF)
     562           0 :         return true;
     563             : 
     564           1 :     return false;
     565             : }
     566             : 
     567             : static inline bool
     568          20 : vr_ip_fragment_tail(struct vr_ip *iph)
     569             : {
     570          20 :     unsigned short frag = ntohs(iph->ip_frag_off);
     571          20 :     bool more = (frag & VR_IP_MF) ? true : false;
     572          20 :     unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
     573             : 
     574          20 :     if (!vr_ip_is_ip4(iph))
     575           0 :         return false;
     576             : 
     577          20 :     if (!more && offset)
     578           5 :         return true;
     579             : 
     580          15 :     return false;
     581             : }
     582             : 
     583             : static inline bool
     584           0 : vr_pkt_is_ip(struct vr_packet *pkt)
     585             : {
     586           0 :     if (pkt->vp_type == VP_TYPE_IPOIP || pkt->vp_type == VP_TYPE_IP ||
     587           0 :               pkt->vp_type == VP_TYPE_IP6OIP)
     588           0 :         return true;
     589             : 
     590           0 :     return false;
     591             : }
     592             : 
     593             : static inline bool
     594         384 : vr_pkt_type_is_overlay(unsigned short type)
     595             : {
     596         384 :     if (type == VP_TYPE_IPOIP || type == VP_TYPE_IP6OIP)
     597         189 :         return true;
     598             : 
     599         195 :     return false;
     600             : }
     601             : 
     602             : static inline bool
     603             : vr_pkt_needs_csum_gso_update(struct vr_packet *pkt)
     604             : {
     605             :     if (pkt->vp_flags & VP_FLAG_FROM_DP) {
     606             :         if (pkt->vp_flags & (VP_FLAG_CSUM_PARTIAL | VP_FLAG_GSO))
     607             :             return true;
     608             :     }
     609             : 
     610             :     return false;
     611             : }
     612             : 
     613             : static inline bool
     614         132 : vr_pkt_is_diag(struct vr_packet *pkt)
     615             : {
     616         132 :     if (pkt->vp_flags & VP_FLAG_DIAG)
     617           0 :         return true;
     618         132 :     return false;
     619             : }
     620             : 
     621             : static inline void
     622             : vr_pkt_set_diag(struct vr_packet *pkt)
     623             : {
     624             :     pkt->vp_flags |= VP_FLAG_DIAG;
     625             :     return;
     626             : }
     627             : 
     628             : static inline bool
     629         104 : vr_pkt_is_gro(struct vr_packet *pkt)
     630             : {
     631         104 :     if (pkt->vp_flags & VP_FLAG_GRO)
     632           4 :         return true;
     633         100 :     return false;
     634             : }
     635             : 
     636             : static inline void
     637           8 : vr_pkt_set_gro(struct vr_packet *pkt)
     638             : {
     639           8 :     pkt->vp_flags |= VP_FLAG_GRO;
     640           8 :     return;
     641             : }
     642             : 
     643             : static inline void
     644          60 : vr_pkt_unset_gro(struct vr_packet *pkt)
     645             : {
     646          60 :     pkt->vp_flags &= ~VP_FLAG_GRO;
     647          60 :     return;
     648             : }
     649             : 
     650             : static inline bool
     651         114 : vr_ip_fragment_head(struct vr_ip *iph)
     652             : {
     653         114 :     unsigned short frag = ntohs(iph->ip_frag_off);
     654         114 :     bool more = (frag & VR_IP_MF) ? true : false;
     655         114 :     unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
     656             : 
     657         114 :     if (!vr_ip_is_ip4(iph))
     658           0 :         return false;
     659             : 
     660         114 :     if (more && !offset)
     661          12 :         return true;
     662             : 
     663         102 :     return false;
     664             : }
     665             : 
     666             : static inline bool
     667         136 : vr_ip_fragment(struct vr_ip *iph)
     668             : {
     669         136 :     unsigned short frag = ntohs(iph->ip_frag_off);
     670         136 :     bool more = (frag & VR_IP_MF) ? true : false;
     671         136 :     unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
     672             : 
     673         136 :     if (!vr_ip_is_ip4(iph))
     674           1 :         return false;
     675             : 
     676         135 :     if (offset || more)
     677          43 :         return true;
     678             : 
     679          92 :     return false;
     680             : }
     681             : 
     682             : static inline bool
     683         201 : vr_ip_transport_header_valid(struct vr_ip *iph)
     684             : {
     685         201 :     unsigned short frag = ntohs(iph->ip_frag_off);
     686         201 :     unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
     687             : 
     688         201 :     if (!vr_ip_is_ip4(iph))
     689           0 :         return true;
     690             : 
     691         201 :     if (offset)
     692          64 :         return false;
     693             : 
     694         137 :     return true;
     695             : }
     696             : 
     697             : 
     698             : #define VR_TCP_FLAG_FIN         0x0001
     699             : #define VR_TCP_FLAG_SYN         0x0002
     700             : #define VR_TCP_FLAG_RST         0x0004
     701             : #define VR_TCP_FLAG_PSH         0x0008
     702             : #define VR_TCP_FLAG_ACK         0x0010
     703             : #define VR_TCP_FLAG_URG         0x0020
     704             : #define VR_TCP_FLAG_ECN         0x0040
     705             : #define VR_TCP_FLAG_CWR         0x0080
     706             : 
     707             : #define VR_TCP_OPT_EOL          0
     708             : #define VR_TCP_OPT_NOP          1
     709             : #define VR_TCP_OPT_MSS          2
     710             : 
     711             : #define VR_TCP_OLEN_MSS         4
     712             : 
     713             : #define VR_TCP_OFFSET(field)    ((ntohs(field) & 0xF000) >> 12)
     714             : #define VR_TCP_FLAGS(field)     (ntohs(field) & 0x01FF)
     715             : 
     716             : __attribute__packed__open__
     717             : struct vr_tcp {
     718             :     unsigned short tcp_sport;
     719             :     unsigned short tcp_dport;
     720             :     unsigned int tcp_seq;
     721             :     unsigned int tcp_ack;
     722             :     union {
     723             :         uint16_t tcp_offset_r_flags;
     724             :         struct {
     725             :             uint16_t
     726             :                 tcp_res1:4,
     727             :                 tcp_doff:4,
     728             :                 tcp_flag_fin:1,
     729             :                 tcp_flag_syn:1,
     730             :                 tcp_flag_rst:1,
     731             :                 tcp_flag_psh:1,
     732             :                 tcp_flag_ack:1,
     733             :                 tcp_flag_urg:1,
     734             :                 tcp_flag_ece:1,
     735             :                 tcp_flag_cwr:1;
     736             :         };
     737             :     };
     738             :     unsigned short tcp_win;
     739             :     unsigned short tcp_csum;
     740             :     unsigned short tcp_urg;
     741             : } __attribute__packed__close__;
     742             : 
     743             : __attribute__packed__open__
     744             : struct vr_udp {
     745             :     unsigned short udp_sport;
     746             :     unsigned short udp_dport;
     747             :     unsigned short udp_length;
     748             :     unsigned short udp_csum;
     749             : } __attribute__packed__close__;
     750             : 
     751             : __attribute__packed__open__
     752             : struct vr_sctp {
     753             :     unsigned short sctp_sport;
     754             :     unsigned short sctp_dport;
     755             :     unsigned int sctp_vtag;
     756             :     unsigned int sctp_csum;
     757             : } __attribute__packed__close__;
     758             : 
     759             : bool vr_adjust_tcp_mss(struct vr_tcp *tcph, uint16_t len_overhead, uint16_t *old_mss, uint16_t *new_mss);
     760             : 
     761             : bool __vr_adjust_tcp_mss(struct vr_tcp *tcph, uint16_t len_overhead, uint16_t eth_mtu, uint16_t *old_mss, uint16_t *new_mss);
     762             : 
     763             : #define VR_ICMP_TYPE_ECHO_REPLY     0
     764             : #define VR_ICMP_TYPE_DEST_UNREACH   3
     765             : #define VR_ICMP_TYPE_ECHO           8
     766             : #define VR_ICMP_TYPE_TIME_EXCEEDED 11
     767             : 
     768             : #define VR_ICMP6_TYPE_PKT_TOO_BIG  2
     769             : #define VR_ICMP6_TYPE_ECHO_REQ     128
     770             : #define VR_ICMP6_TYPE_ECHO_REPLY   129
     771             : #define VR_ICMP6_TYPE_ROUTER_SOL   133
     772             : #define VR_ICMP6_TYPE_ROUTER_AD    134
     773             : #define VR_ICMP6_TYPE_NEIGH_SOL    135
     774             : #define VR_ICMP6_TYPE_NEIGH_AD     136
     775             : #define VR_ICMP6_TYPE_REDIRECT     137
     776             : 
     777             : #define VR_ICMP6_NEIGH_AD_FLAG_ROUTER   0x8000
     778             : #define VR_ICMP6_NEIGH_AD_FLAG_SOLCITED 0x4000
     779             : #define VR_ICMP6_NEIGH_AD_FLAG_OVERRIDE 0x2000
     780             : 
     781             : #define VR_ICMP6_NEIGH_AD_FLAG_ROUTER   0x8000
     782             : #define VR_ICMP6_NEIGH_AD_FLAG_SOLCITED 0x4000
     783             : #define VR_ICMP6_NEIGH_AD_FLAG_OVERRIDE 0x2000
     784             : 
     785             : #define VR_IP6_PROTO_FRAG          44
     786             : 
     787             : __attribute__packed__open__
     788             : struct vr_icmp {
     789             :     uint8_t icmp_type;
     790             :     uint8_t icmp_code;
     791             :     uint16_t icmp_csum;
     792             :     /* now only for icmp echo */
     793             :     uint16_t icmp_eid;
     794             :     uint16_t icmp_eseq;
     795             :     uint8_t  icmp_data[]; /* compatibility with ICMPv6 */
     796             : } __attribute__packed__close__;
     797             : 
     798             : static inline bool
     799          33 : vr_icmp_echo(struct vr_icmp *icmph)
     800             : {
     801          33 :     uint8_t type = icmph->icmp_type;
     802             : 
     803          33 :     if ((type == VR_ICMP_TYPE_ECHO) ||
     804             :             (type == VR_ICMP_TYPE_ECHO_REPLY))
     805          33 :         return true;
     806             : 
     807           0 :     return false;
     808             : }
     809             : 
     810             : static inline bool
     811           0 : vr_v6_prefix_is_ll(uint8_t *prefix)
     812             : {
     813           0 :     if (prefix && (prefix[0] == 0xFE) && (prefix[1] == 0x80))
     814           0 :         return true;
     815             : 
     816           0 :     return false;
     817             : }
     818             : 
     819             : static inline bool
     820           2 : vr_v6_prefix_null(uint8_t *prefix)
     821             : {
     822           2 :     uint64_t *p = (uint64_t *)(prefix);
     823           2 :     if (p && (!p[0]) && (!p[1]))
     824           0 :         return true;
     825             : 
     826           2 :     return false;
     827             : }
     828             : 
     829             : static inline bool
     830          38 : vr_icmp_error(struct vr_icmp *icmph)
     831             : {
     832          38 :     uint8_t type = icmph->icmp_type;
     833             : 
     834          38 :     if ((type == VR_ICMP_TYPE_DEST_UNREACH) ||
     835             :             (type == VR_ICMP_TYPE_TIME_EXCEEDED))
     836           1 :         return true;
     837             : 
     838          37 :     return false;
     839             : }
     840             : 
     841             : static inline bool
     842          14 : vr_ip6_transport_header_valid(struct vr_ip6 *ip6)
     843             : {
     844             :     struct vr_ip6_frag *frag;
     845             :     unsigned short offset;
     846             : 
     847          14 :     if (ip6->ip6_nxt != VR_IP6_PROTO_FRAG)
     848          14 :         return true;
     849             : 
     850           0 :     frag = (struct vr_ip6_frag *)(ip6 + 1);
     851           0 :     offset = (ntohs(frag->ip6_frag_offset)) >> VR_IP6_FRAG_OFFSET_BITS;
     852           0 :     if (offset)
     853           0 :         return false;
     854             : 
     855           0 :     return true;
     856             : }
     857             : 
     858             : static inline bool
     859           1 : vr_ip6_fragment(struct vr_ip6 *ip6)
     860             : {
     861           1 :     if (ip6->ip6_nxt == VR_IP6_PROTO_FRAG)
     862           0 :         return true;
     863             : 
     864           1 :     return false;
     865             : }
     866             : 
     867             : static inline bool
     868           4 : vr_ip6_fragment_head(struct vr_ip6 *ip6)
     869             : {
     870             :     struct vr_ip6_frag *frag;
     871             :     unsigned short offset;
     872             :     bool more;
     873             : 
     874           4 :     if (ip6->ip6_nxt != VR_IP6_PROTO_FRAG)
     875           4 :         return false;
     876             : 
     877           0 :     frag = (struct vr_ip6_frag *)(ip6 + 1);
     878           0 :     offset = ntohs(frag->ip6_frag_offset);
     879           0 :     more = (offset & VR_IP6_MF) ? true : false;
     880           0 :     offset = offset >> VR_IP6_FRAG_OFFSET_BITS;
     881             : 
     882           0 :     if (more && !offset)
     883           0 :         return true;
     884             : 
     885           0 :     return false;
     886             : }
     887             : 
     888             : 
     889             : static inline bool
     890           2 : vr_icmp6_error(struct vr_icmp *icmp6)
     891             : {
     892           2 :     uint8_t type = icmp6->icmp_type;
     893             : 
     894           2 :     if (type < 128)
     895           0 :         return true;
     896             : 
     897           2 :     return false;
     898             : }
     899             : 
     900             : __attribute__packed__open__
     901             : struct vr_gre {
     902             :     unsigned short gre_flags;
     903             :     unsigned short gre_proto;
     904             : } __attribute__packed__close__;
     905             : 
     906             : __attribute__packed__open__
     907             : struct vr_gre_key {
     908             :     struct vr_gre gre_comm_hdr;
     909             :     unsigned int gre_key;
     910             : } __attribute__packed__close__;
     911             : 
     912             : struct vr_pcap {
     913             :     /* timestamp seconds */
     914             :     unsigned int pcap_ts_sec;
     915             :     /* timestamp microseconds */
     916             :     unsigned int pcap_ts_usec;
     917             :     /* number of octets of packet saved in file */
     918             :     unsigned int pcap_incl_len;
     919             :     /* actual length of packet */
     920             :     unsigned int pcap_orig_len;
     921             : };
     922             : 
     923             : __attribute__packed__open__
     924             : struct vr_vxlan {
     925             :     unsigned int vxlan_flags;
     926             :     unsigned int vxlan_vnid;
     927             : } __attribute__packed__close__;
     928             : 
     929             : #define VR_VXLAN_IBIT               0x08000000
     930             : #define VR_VXLAN_RABIT              0x01000000
     931             : 
     932             : /*
     933             :  * Mcast packet adds the following before replicating
     934             :  * Original Transport + IP Header
     935             :  * New Mpls header (4 bytes)
     936             :  * New Udp header (It could be GRE Mpls or Udp Mpls tunnel. Wee need to
     937             :  * take the maximum of two )
     938             :  * New IP header
     939             :  * New L2 header (eth + vlan)
     940             :  */
     941             : #define VR_L3_MCAST_PKT_HEAD_SPACE      (sizeof(struct vr_eth) + \
     942             :                                         sizeof(struct vr_vlan_hdr) + \
     943             :                                         sizeof(struct vr_ip) + \
     944             :                                         sizeof(struct vr_udp) + 4)
     945             : 
     946             : /*
     947             :  * The complete VXlan header contains IP and UDP header
     948             :  */
     949             : #define VR_VXLAN_HDR_LEN        (sizeof(struct vr_vxlan) + \
     950             :                                     sizeof(struct vr_ip) + sizeof(struct vr_udp))
     951             : 
     952             : #define VR_VXLAN_PKT_LEN        (sizeof(struct vr_eth) + \
     953             :                                     sizeof(struct vr_ip) + \
     954             :                                     sizeof(struct vr_udp) + \
     955             :                                     sizeof(struct vr_vxlan))
     956             : 
     957             : #define VR_L2_CTRL_DATA           (0x0000)
     958             : #define VR_L2_CTRL_DATA_LEN       4
     959             : 
     960             : /*
     961             :  * The L2 mcast head space contains Vxlan header and 4 bytes of control
     962             :  * word inaddtion to L3 mcast head space
     963             :  */
     964             : #define VR_L2_MCAST_PKT_HEAD_SPACE  (VR_L3_MCAST_PKT_HEAD_SPACE + \
     965             :                                       VR_VXLAN_HDR_LEN + \
     966             :                                         VR_L2_CTRL_DATA_LEN)
     967             : 
     968             : 
     969             : extern unsigned short vr_ip_csum(struct vr_ip *);
     970             : extern unsigned short vr_generate_unique_ip_id(void);
     971             : extern void vr_proto_fragment(struct vr_interface *, struct vr_packet *);
     972             : extern unsigned short vr_ip_partial_csum(struct vr_ip *);
     973             : extern unsigned short vr_ip6_partial_csum(struct vr_ip6 *);
     974             : 
     975             : enum {
     976             :     UNKNOWN_SOURCE,
     977             :     TOR_SOURCE,
     978             :     TOR_EVPN_SOURCE,
     979             : };
     980             : 
     981             : enum {
     982             :     VR_LABEL_TYPE_UNKNOWN,
     983             :     VR_LABEL_TYPE_MPLS,
     984             :     VR_LABEL_TYPE_VXLAN_ID
     985             : };
     986             : 
     987             : /*
     988             :  * forwarding metadata is something that is carried through out the
     989             :  * forwarding path. we are constrained by what can be held in the
     990             :  * packet, and hence this structure should be of great use. mostly
     991             :  * a local variable (in stack), this should not cause performance
     992             :  * degradation, if so used. please also watch what you are doing with
     993             :  * this variable
     994             :  */
     995             : #define FMD_FLAG_LABEL_IS_VXLAN_ID      0x01
     996             : #define FMD_FLAG_MAC_IS_MY_MAC          0x02
     997             : #define FMD_FLAG_ETREE_ENABLE           0x04
     998             : #define FMD_FLAG_ETREE_ROOT             0x08
     999             : #define FMD_FLAG_L2_CONTROL_DATA        0x10
    1000             : 
    1001             : /*
    1002             :  * 16 bits of fmd_mirror_data constitutes the below
    1003             :  * MSB - 0 - last 12 bits indicate Vlan id
    1004             :  * MSB - 1 - Last 13 bits are interface id
    1005             :  *       2 bits after MSB - Mirror type
    1006             :  */
    1007             : 
    1008             : #define FMD_MIRROR_INVALID_DATA 0xFFFF
    1009             : 
    1010             : /* We don't expect packet to loop through the same set
    1011             :  * of functions more than twice. To be conservative,
    1012             :  * make it value as 4
    1013             :  */
    1014             : #define FMD_PKT_LOOP_TTL 4
    1015             : 
    1016             : struct vr_forwarding_md {
    1017             :     struct vr_flow_entry *fmd_fe;
    1018             :     int32_t fmd_flow_index;
    1019             :     int32_t fmd_label;
    1020             :     int8_t fmd_ecmp_nh_index;
    1021             :     int8_t fmd_ecmp_src_nh_index;
    1022             :     int16_t fmd_dvrf;
    1023             :     uint32_t fmd_outer_src_ip;
    1024             :     uint16_t fmd_vlan;
    1025             :     uint16_t fmd_mirror_data;
    1026             :     uint16_t fmd_udp_src_port;
    1027             :     uint8_t fmd_to_me;
    1028             :     uint8_t fmd_src;
    1029             :     uint8_t fmd_flags;
    1030             :     int8_t fmd_dscp;
    1031             :     int8_t fmd_dotonep;
    1032             :     int8_t fmd_dmac[VR_ETHER_ALEN];
    1033             :     int8_t fmd_smac[VR_ETHER_ALEN];
    1034             :     int8_t fmd_local_ttl;
    1035             :     int8_t fmd_underlay_ecmp_index;
    1036             : };
    1037             : 
    1038             : static inline void
    1039         510 : vr_init_forwarding_md(struct vr_forwarding_md *fmd)
    1040             : {
    1041         510 :     fmd->fmd_fe = NULL;
    1042         510 :     fmd->fmd_flow_index = -1;
    1043         510 :     fmd->fmd_ecmp_nh_index = -1;
    1044         510 :     fmd->fmd_ecmp_src_nh_index = -1;
    1045         510 :     fmd->fmd_label = -1;
    1046         510 :     fmd->fmd_dvrf = -1;
    1047         510 :     fmd->fmd_outer_src_ip = 0;
    1048         510 :     fmd->fmd_vlan = VLAN_ID_INVALID;
    1049         510 :     fmd->fmd_mirror_data = FMD_MIRROR_INVALID_DATA;
    1050         510 :     fmd->fmd_udp_src_port = 0;
    1051         510 :     fmd->fmd_to_me = 0;
    1052         510 :     fmd->fmd_src = 0;
    1053         510 :     fmd->fmd_flags = 0;
    1054         510 :     fmd->fmd_dscp = -1;
    1055         510 :     fmd->fmd_dotonep = -1;
    1056         510 :     fmd->fmd_local_ttl = FMD_PKT_LOOP_TTL;
    1057         510 :     fmd->fmd_underlay_ecmp_index = -1;
    1058         510 :     VR_MAC_RESET(fmd->fmd_dmac);
    1059         510 :     VR_MAC_RESET(fmd->fmd_smac);
    1060             : 
    1061         510 :     return;
    1062             : }
    1063             : 
    1064             : static inline bool
    1065          29 : vr_fmd_label_is_vxlan_id(struct vr_forwarding_md *fmd)
    1066             : {
    1067          29 :     if (fmd->fmd_flags & FMD_FLAG_LABEL_IS_VXLAN_ID)
    1068           0 :         return true;
    1069          29 :     return false;
    1070             : }
    1071             : 
    1072             : static inline void
    1073           0 : vr_fmd_update_etree(struct vr_forwarding_md *fmd, bool valid)
    1074             : {
    1075           0 :     if (valid)
    1076           0 :         fmd->fmd_flags |= FMD_FLAG_ETREE_ENABLE;
    1077             :     else
    1078           0 :         fmd->fmd_flags &= ~FMD_FLAG_ETREE_ENABLE;
    1079             : 
    1080           0 :     return;
    1081             : }
    1082             : 
    1083             : static inline void
    1084          55 : vr_fmd_update_etree_root(struct vr_forwarding_md *fmd, bool root)
    1085             : {
    1086          55 :     if (root)
    1087          35 :         fmd->fmd_flags |= FMD_FLAG_ETREE_ROOT;
    1088             :     else
    1089          20 :         fmd->fmd_flags &= ~FMD_FLAG_ETREE_ROOT;
    1090             : 
    1091          55 :     return;
    1092             : }
    1093             : 
    1094             : static inline bool
    1095          14 : vr_fmd_etree_is_enabled(struct vr_forwarding_md *fmd)
    1096             : {
    1097          14 :     if (fmd->fmd_flags & FMD_FLAG_ETREE_ENABLE)
    1098           0 :         return true;
    1099             : 
    1100          14 :     return false;
    1101             : }
    1102             : 
    1103             : static inline bool
    1104           0 : vr_fmd_etree_is_root(struct vr_forwarding_md *fmd)
    1105             : {
    1106           0 :     if (fmd->fmd_flags & FMD_FLAG_ETREE_ROOT)
    1107           0 :         return true;
    1108             : 
    1109           0 :     return false;
    1110             : }
    1111             : 
    1112             : static inline void
    1113         192 : vr_fmd_update_label_type(struct vr_forwarding_md *fmd,
    1114             :         unsigned int type)
    1115             : {
    1116         192 :     if (type == VR_LABEL_TYPE_VXLAN_ID) {
    1117           9 :         fmd->fmd_flags |= FMD_FLAG_LABEL_IS_VXLAN_ID;
    1118             :     } else {
    1119         183 :         fmd->fmd_flags &= ~FMD_FLAG_LABEL_IS_VXLAN_ID;
    1120             :     }
    1121             : 
    1122         192 :     return;
    1123             : }
    1124             : 
    1125             : static inline void
    1126         127 : vr_fmd_set_label(struct vr_forwarding_md *fmd, unsigned int label,
    1127             :         unsigned int type)
    1128             : {
    1129         127 :     fmd->fmd_label = label;
    1130         127 :     vr_fmd_update_label_type(fmd, type);
    1131             : 
    1132         127 :     return;
    1133             : }
    1134             : 
    1135             : static inline void
    1136           2 : vr_fmd_update_l2_control_data(struct vr_forwarding_md *fmd, bool enable)
    1137             : {
    1138           2 :     if (enable)
    1139           0 :         fmd->fmd_flags |= FMD_FLAG_L2_CONTROL_DATA;
    1140             :     else
    1141           2 :         fmd->fmd_flags &= ~FMD_FLAG_L2_CONTROL_DATA;
    1142             : 
    1143           2 :     return;
    1144             : }
    1145             : 
    1146             : static inline bool
    1147         114 : vr_fmd_l2_control_data_is_enabled(struct vr_forwarding_md *fmd)
    1148             : {
    1149         114 :     if (fmd->fmd_flags & FMD_FLAG_L2_CONTROL_DATA)
    1150           0 :         return true;
    1151             : 
    1152         114 :     return false;
    1153             : }
    1154             : 
    1155             : static inline uint16_t
    1156          66 : vr_fmd_get_mirror_vlan(struct vr_forwarding_md *fmd)
    1157             : {
    1158          66 :     if (fmd->fmd_mirror_data != FMD_MIRROR_INVALID_DATA) {
    1159           0 :         if (!(fmd->fmd_mirror_data & 0x8000))
    1160           0 :             return (fmd->fmd_mirror_data & 0x0FFF);
    1161             :     }
    1162             : 
    1163          66 :     return FMD_MIRROR_INVALID_DATA;
    1164             : }
    1165             : 
    1166             : static inline mirror_type_t
    1167           0 : vr_fmd_get_mirror_type(struct vr_forwarding_md *fmd)
    1168             : {
    1169           0 :     if (fmd->fmd_mirror_data != FMD_MIRROR_INVALID_DATA) {
    1170           0 :         if (fmd->fmd_mirror_data & 0x8000)
    1171           0 :             return (((fmd->fmd_mirror_data & 0x6000) >> 13) & 0x0003);
    1172             :     }
    1173             : 
    1174           0 :     return MIRROR_TYPE_UNKNOWN;
    1175             : }
    1176             : 
    1177             : static inline uint16_t
    1178           2 : vr_fmd_get_mirror_if_id(struct vr_forwarding_md *fmd)
    1179             : {
    1180           2 :     uint16_t intf_id = FMD_MIRROR_INVALID_DATA;
    1181             : 
    1182           2 :     if (fmd->fmd_mirror_data != FMD_MIRROR_INVALID_DATA) {
    1183           0 :         if (fmd->fmd_mirror_data & 0x8000) {
    1184           0 :             intf_id = fmd->fmd_mirror_data & 0x1FFF;
    1185           0 :             if (intf_id == 0x1FFF)
    1186           0 :                 intf_id = FMD_MIRROR_INVALID_DATA;
    1187             :         }
    1188             :     }
    1189             : 
    1190           2 :     return intf_id;
    1191             : }
    1192             : 
    1193             : static inline void
    1194           0 : vr_fmd_put_mirror_vlan(struct vr_forwarding_md *fmd, uint16_t vlan)
    1195             : {
    1196           0 :     fmd->fmd_mirror_data = vlan & 0x0FFF;
    1197             : 
    1198           0 :     return;
    1199             : }
    1200             : 
    1201             : 
    1202             : static inline void
    1203           2 : vr_fmd_put_mirror_type(struct vr_forwarding_md *fmd, mirror_type_t type)
    1204             : {
    1205           2 :     uint16_t intf_id = vr_fmd_get_mirror_if_id(fmd);
    1206           2 :     fmd->fmd_mirror_data = 0x8000 | ((type & 0x3) << 13) | (intf_id & 0x1FFF);
    1207             : 
    1208           2 :     return;
    1209             : }
    1210             : 
    1211             : static inline void
    1212           0 : vr_fmd_put_mirror_if_id(struct vr_forwarding_md *fmd, uint16_t if_id)
    1213             : {
    1214           0 :     mirror_type_t type = vr_fmd_get_mirror_type(fmd);
    1215           0 :     fmd->fmd_mirror_data = 0x8000 | ((type & 0x3) << 13) | (if_id & 0x1FFF);
    1216             : 
    1217           0 :     return;
    1218             : }
    1219             : 
    1220             : 
    1221             : /*
    1222             :  * Size is : 2 Transport ports,
    1223             :  *            IPV6 header which carried the above transport,
    1224             :  *            ICMPV6 + IPV6 header generated by source of ICMP error,
    1225             :  *            Fabric Tunnel headers, 2 ethernet headers and agent hdr
    1226             :  */
    1227             : #define VR_AGENT_MIN_PACKET_LEN     ((2 * sizeof(unsigned short)) + \
    1228             :                                     sizeof(struct vr_ip6) + \
    1229             :                                     sizeof(struct vr_icmp) + \
    1230             :                                     sizeof(struct vr_ip6) + VR_VXLAN_HDR_LEN + \
    1231             :                                     VR_L2_CTRL_DATA_LEN + \
    1232             :                                     (2 * VR_ETHER_HLEN) + sizeof(struct agent_hdr))
    1233             : 
    1234             : static inline bool
    1235          72 : pkt_is_gso(struct vr_packet *pkt)
    1236             : {
    1237          72 :     if (vr_pgso_size && vr_pgso_size(pkt))
    1238           0 :         return true;
    1239          72 :     return false;
    1240             : }
    1241             : 
    1242             : static inline unsigned char *
    1243         366 : pkt_data_at_offset(struct vr_packet *pkt, unsigned short off)
    1244             : {
    1245         366 :     if (off < pkt->vp_end)
    1246         366 :         return pkt->vp_head + off;
    1247             : 
    1248           0 :     return vr_data_at_offset(pkt, off);
    1249             : }
    1250             : 
    1251             : static inline unsigned char *
    1252        1896 : pkt_data(struct vr_packet *pkt)
    1253             : {
    1254        1896 :     return pkt->vp_head + pkt->vp_data;
    1255             : }
    1256             : 
    1257             : static inline void
    1258             : pkt_set_data(struct vr_packet *pkt, unsigned short off)
    1259             : {
    1260             :     if (pkt->vp_data == off)
    1261             :         return;
    1262             : 
    1263             :     pkt->vp_data = off;
    1264             :     pkt->vp_len = pkt->vp_tail - pkt->vp_data;
    1265             : 
    1266             :     return;
    1267             : }
    1268             : 
    1269             : static inline void
    1270         177 : pkt_set_inner_network_header(struct vr_packet *pkt, unsigned short off)
    1271             : {
    1272         177 :     pkt->vp_inner_network_h = off;
    1273         177 :     return;
    1274             : }
    1275             : 
    1276             : static inline unsigned short
    1277          62 : pkt_get_inner_network_header_off(struct vr_packet *pkt)
    1278             : {
    1279          62 :     return pkt->vp_inner_network_h;
    1280             : 
    1281             : }
    1282             : 
    1283             : static inline unsigned char *
    1284          28 : pkt_inner_network_header(struct vr_packet *pkt)
    1285             : {
    1286          28 :     if (pkt->vp_inner_network_h < pkt->vp_end)
    1287          28 :         return pkt->vp_head + pkt->vp_inner_network_h;
    1288             : 
    1289           0 :     return NULL;
    1290             : }
    1291             : 
    1292             : static inline void
    1293         240 : pkt_set_network_header(struct vr_packet *pkt, unsigned short off)
    1294             : {
    1295         240 :     pkt->vp_network_h = off;
    1296         240 :     return;
    1297             : }
    1298             : 
    1299             : static inline unsigned short
    1300         168 : pkt_get_network_header_off(struct vr_packet *pkt)
    1301             : {
    1302         168 :     return pkt->vp_network_h;
    1303             : }
    1304             : 
    1305             : static inline unsigned char *
    1306         874 : pkt_network_header(struct vr_packet *pkt)
    1307             : {
    1308         874 :     if (pkt->vp_network_h < pkt->vp_end)
    1309         874 :         return pkt->vp_head + pkt->vp_network_h;
    1310             : 
    1311           0 :     return vr_network_header(pkt);
    1312             : }
    1313             : 
    1314             : static inline unsigned char *
    1315         208 : pkt_pull(struct vr_packet *pkt, unsigned int len)
    1316             : {
    1317         208 :     if (pkt->vp_data + len > pkt->vp_tail)
    1318           0 :         return NULL;
    1319             : 
    1320         208 :     pkt->vp_data += len;
    1321         208 :     pkt->vp_len -= len;
    1322             : 
    1323         208 :     return pkt_data(pkt);
    1324             : }
    1325             : 
    1326             : static inline unsigned char *
    1327           0 : pkt_pull_tail(struct vr_packet *pkt, unsigned int len)
    1328             : {
    1329           0 :     if (pkt->vp_tail + len > pkt->vp_end)
    1330           0 :         return NULL;
    1331             : 
    1332           0 :     pkt->vp_tail += len;
    1333           0 :     pkt->vp_len += len;
    1334             : 
    1335           0 :     return pkt->vp_head + pkt->vp_tail;
    1336             : }
    1337             : 
    1338             : static inline unsigned char *
    1339         437 : pkt_push(struct vr_packet *pkt, unsigned int len)
    1340             : {
    1341         437 :     if (len > pkt->vp_data)
    1342           0 :         return NULL;
    1343             : 
    1344         437 :     pkt->vp_data -= len;
    1345         437 :     pkt->vp_len += len;
    1346             : 
    1347         437 :     return pkt_data(pkt);
    1348             : }
    1349             : 
    1350             : static inline unsigned short
    1351        1071 : pkt_head_len(struct vr_packet *pkt)
    1352             : {
    1353        1071 :     return pkt->vp_len;
    1354             : }
    1355             : 
    1356             : static inline unsigned int
    1357         771 : pkt_len(struct vr_packet *pkt)
    1358             : {
    1359         771 :     return pkt_head_len(pkt) + vr_pfrag_len(pkt);
    1360             : }
    1361             : 
    1362             : static inline unsigned char *
    1363             : pkt_reserve_head_space(struct vr_packet *pkt, unsigned short len)
    1364             : {
    1365             :     if (pkt->vp_data + len > pkt->vp_end)
    1366             :         return NULL;
    1367             : 
    1368             :     if (pkt->vp_data == pkt->vp_tail)
    1369             :         pkt->vp_tail += len;
    1370             : 
    1371             :     if (pkt->vp_data + len > pkt->vp_tail)
    1372             :         return NULL;
    1373             : 
    1374             :     pkt->vp_data += len;
    1375             : 
    1376             :     return pkt_data(pkt);
    1377             : }
    1378             : 
    1379             : static inline unsigned short
    1380         484 : pkt_head_space(struct vr_packet *pkt)
    1381             : {
    1382         484 :     return pkt->vp_data;
    1383             : }
    1384             : 
    1385             : static inline bool
    1386          33 : vr_is_ipv6_nd_packet(struct vr_packet *pkt)
    1387             : {
    1388             :     struct vr_ip6 *ip6;
    1389             :     struct vr_icmp *icmp6;
    1390             : 
    1391          33 :     if (pkt->vp_type == VP_TYPE_IP6) {
    1392          15 :         ip6 = (struct vr_ip6 *)pkt_network_header(pkt);
    1393          15 :         if (ip6->ip6_nxt == VR_IP_PROTO_ICMP6) {
    1394          12 :             icmp6 = (struct vr_icmp *)((unsigned char *)ip6 +
    1395             :                                         sizeof(struct vr_ip6));
    1396          24 :             return (icmp6->icmp_type >= VR_ICMP6_TYPE_ROUTER_SOL &&
    1397          12 :                     icmp6->icmp_type <= VR_ICMP6_TYPE_REDIRECT);
    1398             :         }
    1399             :     }
    1400          21 :     return false;
    1401             : }
    1402             : 
    1403             : static inline void
    1404             : pkt_init_fragment(struct vr_packet *dst, struct vr_packet *src)
    1405             : {
    1406             :     dst->vp_if = src->vp_if;
    1407             :     dst->vp_nh = src->vp_nh;
    1408             :     dst->vp_cpu = src->vp_cpu;
    1409             :     dst->vp_flags = src->vp_flags;
    1410             : 
    1411             :     return;
    1412             : }
    1413             : 
    1414             : static inline void
    1415          39 : pkt_drop_stats(struct vr_interface *vif, unsigned short reason, int cpu)
    1416             : {
    1417             :     uint8_t *data;
    1418          39 :     unsigned int count = 1;
    1419          39 :     struct vrouter *router = vrouter_get(0);
    1420             : 
    1421             :     /*
    1422             :      * Lets log the errors as of now, till we are sure that nothing is
    1423             :      * un accounted
    1424             :      */
    1425          39 :     if (reason >= VP_DROP_MAX) {
    1426           0 :         vr_printf("Vrouter: vr_pdrop_stats invalid reason %d\n", reason);
    1427           0 :         return;
    1428             :     }
    1429             : 
    1430          39 :     if (cpu < 0) {
    1431           0 :         vr_printf("Vrouter: vr_pdrop_stats invalid CPU %d"
    1432             :                    " reason %d\n", cpu, reason);
    1433           0 :         return;
    1434             :     }
    1435             : 
    1436             :     /* Lets increment the per cpu global stats */
    1437          39 :     if (router)
    1438          39 :         ((uint64_t *)(router->vr_pdrop_stats[cpu]))[reason]++;
    1439             : 
    1440             :     /* If vif is NULL, no accounting can be done against the vif. So return */
    1441          39 :     if (!vif)
    1442           5 :         return;
    1443             : 
    1444             :     /* Increment per cpu stats */
    1445          34 :     if (vif->vif_pcpu_drop_stats) {
    1446          34 :         data = vr_btable_get(vif->vif_pcpu_drop_stats,
    1447          34 :                             ((cpu * VP_DROP_MAX) + reason));
    1448          34 :         if (data) {
    1449          34 :             count = ++(*data);
    1450          34 :             if (count < 255)
    1451          34 :                 return;
    1452           0 :             *data = 0;
    1453             :         }
    1454             :     }
    1455             : 
    1456             :     /*
    1457             :      * Fall through, either for failure of per cpu stat or for carry
    1458             :      * over
    1459             :      */
    1460           0 :     if (vif->vif_drop_stats) {
    1461           0 :         (void)vr_sync_add_and_fetch_64u(vif->vif_drop_stats + reason, count);
    1462             :     }
    1463             : 
    1464           0 :     return;
    1465             : }
    1466             : 
    1467             : static inline bool
    1468           0 : vr_pkt_is_bfd(struct vr_packet *pkt, uint8_t *bfd_state)
    1469             : {
    1470             :     struct vr_ip *iph;
    1471             :     struct vr_udp *udph;
    1472             :     int pkt_off;
    1473             :     uint8_t *bfd_data;
    1474             : 
    1475           0 :     if (vr_pkt_is_ip(pkt)) {
    1476           0 :         iph = (struct vr_ip *)pkt_network_header(pkt);
    1477           0 :         if (iph->ip_proto == VR_IP_PROTO_UDP) {
    1478           0 :             pkt_off = pkt_get_network_header_off(pkt) + (iph->ip_hl << 2);
    1479           0 :             udph = (struct vr_udp *)(pkt_data_at_offset(pkt, pkt_off));
    1480           0 :             if (ntohs(udph->udp_dport) == VR_BFD_SINGLE_HOP_PORT) {
    1481           0 :                 pkt_off += sizeof(struct vr_udp);
    1482           0 :                 bfd_data = (uint8_t *)(pkt_data_at_offset(pkt, pkt_off));
    1483             :                 // decode the BFD-state info from the packet
    1484           0 :                 *bfd_state = bfd_data[1] & VR_BFD_STATE_FLAG_MASK;
    1485           0 :                 return true;
    1486             :             }
    1487             :         }
    1488             :     }
    1489           0 :     return false;
    1490             : }
    1491             : 
    1492             : /* Below function logs the packet drops by getting packet information from vr_packet & vr_flow
    1493             :  * and logs in corresponding core */
    1494          42 : static inline void vr_pkt_drop_log_func(unsigned short drop_reason, struct vr_packet *pkt,
    1495             :  struct vr_flow *flow, map_t file, unsigned int line)
    1496             : {
    1497          42 :     int cpu = vr_get_cpu();
    1498          42 :     uint64_t m_sec = 0, n_sec = 0;
    1499          42 :     struct vr_ip *ip = NULL;
    1500          42 :     struct vr_ip6 *ip6 = NULL;
    1501             : 
    1502          42 :     struct vrouter *router = vrouter_get(0);
    1503          42 :     struct vr_pkt_drop_st *vr_pkt_drop = router->vr_pkt_drop;
    1504             : 
    1505             :     /* Copying index valjue from circular buffer of corresponding core*/
    1506          42 :     int buf_idx = vr_pkt_drop->vr_pkt_drop_log_buffer_index[cpu];
    1507          42 :     vr_pkt_drop_log_t **vr_pkt_drop_log_buffer = vr_pkt_drop->vr_pkt_drop_log;
    1508             : 
    1509             :     /* if Drop type is already set then droping other drop reasons
    1510             :      */
    1511          42 :     if ((vr_pkt_droplog_type != VP_DROP_MAX) &&
    1512           0 :         (vr_pkt_droplog_type != drop_reason)) {
    1513           0 :         return;
    1514             :     }
    1515             : 
    1516             : 
    1517          42 :     memset(vr_pkt_drop_log_buffer[cpu] + buf_idx, 0, sizeof(vr_pkt_drop_log_t));
    1518             : 
    1519             :     /* Check Packet drop log enabled at load time*/
    1520          42 :     if(vr_pkt_droplog_buf_en == 1)
    1521             :     {
    1522             :         /* Get the current time in epoch format */
    1523          42 :         vr_get_time(&m_sec, &n_sec);
    1524             : 
    1525             :         /* Copying epoch time into timestamp structure */
    1526          42 :         PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].timestamp, (unsigned int)m_sec)
    1527             : 
    1528          42 :         PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].drop_reason, drop_reason)
    1529             : 
    1530          42 :         PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].drop_loc.file, file)
    1531          42 :         PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].drop_loc.line, line)
    1532             : 
    1533          42 :         if(pkt != NULL)
    1534             :         {
    1535             :             /* Check if dropped packet is IPV6 */
    1536          42 :             if (pkt->vp_type == VP_TYPE_IP6)
    1537             :             {
    1538           1 :                 ip6 = (struct vr_ip6 *)pkt_network_header(pkt);
    1539           1 :                 if(!ip6)
    1540           0 :                     return;
    1541           1 :                 memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].src.ipv6.s6_addr, ip6->ip6_src,
    1542             :                         sizeof(ip6->ip6_src));
    1543           1 :                 memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].dst.ipv6.s6_addr, ip6->ip6_dst,
    1544             :                         sizeof(ip6->ip6_dst));
    1545             : 
    1546           1 :                 if(flow != NULL && flow->flow6_sport != 0) {
    1547           0 :                     vr_pkt_drop_log_buffer[cpu][buf_idx].sport = flow->flow6_sport;
    1548           0 :                     vr_pkt_drop_log_buffer[cpu][buf_idx].dport = flow->flow6_dport;
    1549             :                 }
    1550             :             }
    1551             :             /* Check if dropped packet is IPV4*/
    1552          41 :             else if (pkt->vp_type != VP_TYPE_NULL) {
    1553          41 :                 ip = (struct vr_ip *)pkt_network_header(pkt);
    1554          41 :                 if(!ip)
    1555           0 :                     return;
    1556             : 
    1557             :                 /* Copying Source & destination address from IPV4 packet header*/
    1558          41 :                 PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].src.ipv4.s_addr,
    1559             :                         ip->ip_saddr)
    1560          41 :                 PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].dst.ipv4.s_addr,
    1561             :                         ip->ip_daddr)
    1562             : 
    1563             :                 /* If flow is available, copy source port and destination port*/
    1564          41 :                 if(flow != NULL && flow->flow4_sport != 0) {
    1565           0 :                     vr_pkt_drop_log_buffer[cpu][buf_idx].sport = flow->flow4_sport;
    1566           0 :                     vr_pkt_drop_log_buffer[cpu][buf_idx].dport = flow->flow4_dport;
    1567             :                 }
    1568             :             }
    1569          42 :             PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].vp_type, pkt->vp_type)
    1570             : 
    1571             :             /* Log packet details into buffer, when drop least is diabled */
    1572          42 :             if(vr_pkt_droplog_min_sysctl_en != 1)
    1573             :             {
    1574           0 :                 if(pkt->vp_if != NULL) {
    1575           0 :                     PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].vif_idx,
    1576             :                         pkt->vp_if->vif_idx)
    1577             :                 }
    1578           0 :                 if(pkt->vp_nh != NULL) {
    1579           0 :                     PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].nh_id, pkt->vp_nh->nh_id)
    1580             :                 }
    1581           0 :                     PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].pkt_len, pkt->vp_len)
    1582           0 :                 if(pkt->vp_len < 100)
    1583           0 :                     memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].pkt_header,
    1584           0 :                         pkt_network_header(pkt), pkt->vp_len);
    1585             :                 else
    1586           0 :                     memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].pkt_header,
    1587           0 :                         pkt_network_header(pkt), 100);
    1588             :             }
    1589             :         }
    1590             :         /* Circular buffer - buf_idx counter increments for every packet log, when it reaches max.
    1591             :          * configured value, it will start from zero and reach till max buffer size.
    1592             :          * circular buffer maintained for each core */
    1593          42 :         vr_pkt_drop->vr_pkt_drop_log_buffer_index[cpu] = ((++buf_idx) % vr_pkt_droplog_bufsz);
    1594             :     }
    1595             : }
    1596             : 
    1597             : #define MAX_BUF_SIZE 512
    1598             : static inline void
    1599           2 : pkt_dump (struct vr_packet *pkt)
    1600             : {
    1601           2 :     int i = 0;
    1602             :     unsigned char *pstart;
    1603           2 :     char buf[MAX_BUF_SIZE] = {0};
    1604           2 :     int buf_off = 0, sz = 0;
    1605           2 :     int plen = 0;
    1606             : 
    1607           2 :     vr_printf("pkt %p head %p data %d len %d\n", pkt, pkt->vp_head,
    1608           2 :                  pkt->vp_data, pkt->vp_len);
    1609           2 :     pstart = pkt_data(pkt);
    1610           2 :     plen = pkt_len(pkt);
    1611           2 :     if (pkt_data(pkt) == pkt_network_header(pkt)) {
    1612             :         // start from eth header
    1613           2 :         pstart -= 14;
    1614           2 :         plen += 14;
    1615             :     }
    1616          86 :     for (i = 0; i < plen; i++) {
    1617          84 :          if ((buf_off + 10) >= MAX_BUF_SIZE) {
    1618           0 :              break;
    1619             :          }
    1620          84 :          sz = sprintf(buf+buf_off, "0x%02x ", *(pstart + i));
    1621          84 :          if (sz < 0) break;
    1622          84 :          buf_off += sz;
    1623             :     }
    1624           2 :     vr_printf("pkt %p: %s\n", pkt, buf);
    1625           2 : }
    1626             : 
    1627             : #endif /* __VR_PACKET_H__ */

Generated by: LCOV version 1.14