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

Generated by: LCOV version 1.14