LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - pkt_handler.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 41 50 82.0 %
Date: 2026-11-09 02:10:49 Functions: 20 26 76.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #ifndef vnsw_agent_pkt_handler_hpp
       7             : #define vnsw_agent_pkt_handler_hpp
       8             : 
       9             : #include <net/if.h>
      10             : #include <sys/socket.h>
      11             : #include <netinet/if_ether.h>
      12             : #include <netinet/ip.h>
      13             : #include <netinet/ip6.h>
      14             : #include <netinet/ip_icmp.h>
      15             : #include <netinet/igmp.h>
      16             : 
      17             : #include <boost/array.hpp>
      18             : 
      19             : #include <base/address.h>
      20             : #include <net/mac_address.h>
      21             : #include <oper/mirror_table.h>
      22             : #include <oper/nexthop.h>
      23             : #include <pkt/pkt_trace.h>
      24             : #include <pkt/packet_buffer.h>
      25             : 
      26             : #include "vr_defs.h"
      27             : 
      28             : #define DNS_SERVER_PORT              53
      29             : #define DHCP_SERVER_PORT             67
      30             : #define DHCP_CLIENT_PORT             68
      31             : #define DHCPV6_SERVER_PORT           547
      32             : #define DHCPV6_CLIENT_PORT           546
      33             : #define BFD_SINGLEHOP_CONTROL_PORT   3784
      34             : #define BFD_ECHO_PORT                3785
      35             : #define BFD_MULTIHOP_CONTROL_PORT    4784
      36             : #define VXLAN_UDP_DEST_PORT          4789
      37             : #define IANA_MPLS_OVER_UDP_DEST_PORT 6635
      38             : #define MPLS_OVER_UDP_DEST_PORT      51234
      39             : 
      40             : #define IPv4_ALEN           4
      41             : #define ARP_TX_BUFF_LEN     128
      42             : #define IPC_HDR_LEN        (sizeof(struct ether_header) + sizeof(struct agent_hdr))
      43             : #define VLAN_PROTOCOL      0x8100
      44             : #define DEFAULT_IP_TTL     64
      45             : //Ideally VM is one hop away but traffic gets routed so use 2.
      46             : #define BGP_SERVICE_TTL_REV_FLOW 2
      47             : #define BGP_SERVICE_TTL_FWD_FLOW 255
      48             : #define DEFAULT_IP_ID      0
      49             : #define VLAN_HDR_LEN       4
      50             : 
      51             : #define ICMP_UNREACH_HDR_LEN 8
      52             : 
      53             : #define ETHERTYPE_QINQ    0x88A8
      54             : #define ETHERTYPE_PBB     0x88E7
      55             : #define PBB_HEADER_LEN    4
      56             : 
      57             : struct PktInfo;
      58             : struct agent_hdr;
      59             : class PacketBuffer;
      60             : class Proto;
      61             : class EcmpLoadBalance;
      62             : typedef boost::shared_ptr<PktInfo> PktInfoPtr;
      63             : 
      64             : struct InterTaskMsg {
      65        1111 :     InterTaskMsg(uint16_t command): cmd(command) {}
      66        1111 :     virtual ~InterTaskMsg() {}
      67             : 
      68             :     uint16_t cmd;
      69             : };
      70             : 
      71             : struct GreHdr {
      72             :     GreHdr() : flags(), protocol() {}
      73             :     ~GreHdr() {}
      74             : 
      75             :     uint16_t flags;
      76             :     uint16_t protocol;
      77             : };
      78             : 
      79             : struct MplsHdr {
      80             :     MplsHdr() : hdr() {}
      81             :     ~MplsHdr() {}
      82             : 
      83             :     uint32_t hdr;
      84             : };
      85             : 
      86             : struct VxlanHdr {
      87             :     VxlanHdr() : reserved(0), vxlan_id(0) { }
      88           7 :     VxlanHdr(uint32_t id) : reserved(0), vxlan_id((id) << 8) { }
      89           7 :     ~VxlanHdr() { }
      90             : 
      91             :     uint32_t reserved;
      92             :     uint32_t vxlan_id;
      93             : };
      94             : 
      95             : struct PktType {
      96             :     enum Type {
      97             :         INVALID,
      98             :         ARP,
      99             :         IP,
     100             :         UDP,
     101             :         TCP,
     102             :         ICMP,
     103             :         ICMPV6,
     104             :         NON_IP,
     105             :         MESSAGE,
     106             :         SCTP,
     107             :         IGMP,
     108             :     };
     109             : };
     110             : 
     111             : struct PktStatsType {
     112             :     enum Type {
     113             :         PKT_RX,
     114             :         PKT_RX_ENQUEUE,
     115             :         PKT_RX_DROP_STATS,
     116             :         PKT_TX,
     117             :         PKT_TX_ERROR,
     118             :     };
     119             : };
     120             : 
     121             : struct sctphdr {
     122             :     u_int16_t th_sport;
     123             :     u_int16_t th_dport;
     124             :     u_int32_t vtag;
     125             : };
     126             : 
     127             : struct AgentHdr {
     128             :     // Packet commands between agent and vrouter. The values must be in-sync
     129             :     // with vrouter/include/vr_defs.h
     130             :     enum PktCommand {
     131             :         TX_SWITCH = AGENT_CMD_SWITCH,
     132             :         TX_ROUTE = AGENT_CMD_ROUTE,
     133             :         TRAP_ARP = AGENT_TRAP_ARP,
     134             :         TRAP_L2_PROTOCOL = AGENT_TRAP_L2_PROTOCOLS,
     135             :         TRAP_NEXTHOP = AGENT_TRAP_NEXTHOP,
     136             :         TRAP_RESOLVE = AGENT_TRAP_RESOLVE,
     137             :         TRAP_FLOW_MISS = AGENT_TRAP_FLOW_MISS,
     138             :         TRAP_L3_PROTOCOLS = AGENT_TRAP_L3_PROTOCOLS,
     139             :         TRAP_DIAG = AGENT_TRAP_DIAG,
     140             :         TRAP_UNUSED_1,
     141             :         TRAP_SOURCE_MISMATCH = AGENT_TRAP_SOURCE_MISMATCH,
     142             :         TRAP_HANDLE_DF = AGENT_TRAP_HANDLE_DF,
     143             :         TRAP_TOR_CONTROL_PKT = AGENT_TRAP_TOR_CONTROL_PKT,
     144             :         TRAP_ZERO_TTL = AGENT_TRAP_ZERO_TTL,
     145             :         TRAP_ICMP_ERROR = AGENT_TRAP_ICMP_ERROR,
     146             :         TRAP_FLOW_ACTION_HOLD = AGENT_TRAP_FLOW_ACTION_HOLD,
     147             :         TRAP_ROUTER_ALERT = AGENT_TRAP_ROUTER_ALERT,
     148             :         TRAP_MAC_LEARN = AGENT_TRAP_MAC_LEARN,
     149             :         TRAP_MAC_MOVE = AGENT_TRAP_MAC_MOVE,
     150             :         TRAP_MAC_IP_LEARNING = AGENT_TRAP_MAC_IP_LEARNING,
     151             :         TRAP_BFD = AGENT_TRAP_BFD,
     152             :         INVALID = MAX_AGENT_HDR_COMMANDS
     153             :     };
     154             : 
     155             :     enum PktCommandParams {
     156             :         PACKET_CMD_PARAM_CTRL = CMD_PARAM_PACKET_CTRL,
     157             :         PACKET_CMD_PARAM_DIAG = CMD_PARAM_1_DIAG,
     158             :         MAX_PACKET_CMD_PARAM  = MAX_CMD_PARAMS,
     159             :     };
     160             : 
     161        3701 :     AgentHdr() :
     162        3701 :         ifindex(-1), vrf(-1), cmd(-1), cmd_param(-1), cmd_param_1(-1),
     163        3701 :         cmd_param_2(0), cmd_param_3(0), cmd_param_4(0), cmd_param_5(0),
     164        3701 :         nh(-1), flow_index(-1), mtu(0) {}
     165             : 
     166             :     AgentHdr(uint32_t ifindex_p, uint32_t vrf_p, uint16_t cmd_p) :
     167             :         ifindex(ifindex_p), vrf(vrf_p), cmd(cmd_p), cmd_param(-1),
     168             :         cmd_param_1(-1), cmd_param_2(0), cmd_param_3(0), cmd_param_4(0),
     169             :         cmd_param_5(0), nh(-1), flow_index(-1), mtu(0) {}
     170             : 
     171        2204 :     AgentHdr(uint32_t ifindex_p, uint32_t vrf_p, uint16_t cmd_p,
     172        2204 :              uint32_t param1, uint32_t param2) :
     173        2204 :         ifindex(ifindex_p), vrf(vrf_p), cmd(cmd_p), cmd_param(param1),
     174        2204 :         cmd_param_1(param2), cmd_param_2(0), cmd_param_3(0), cmd_param_4(0),
     175        2204 :         cmd_param_5(0), nh(-1), flow_index(-1), mtu(0) {}
     176             : 
     177        5980 :     ~AgentHdr() {}
     178             : 
     179             :     // Fields from agent_hdr
     180             :     uint32_t            ifindex;
     181             :     uint32_t            vrf;
     182             :     uint16_t            cmd;
     183             :     uint32_t            cmd_param;
     184             :     uint32_t            cmd_param_1;
     185             :     uint32_t            cmd_param_2;
     186             :     uint32_t            cmd_param_3;
     187             :     uint32_t            cmd_param_4;
     188             :     uint8_t             cmd_param_5;
     189             :     uint32_t            nh;
     190             :     uint32_t            flow_index;
     191             :     uint16_t            mtu;
     192             : };
     193             : 
     194             : // Tunnel header decoded from the MPLSoGRE/MPLSoUDP encapsulated packet on
     195             : // fabric. Supports only IPv4 addresses since only IPv4 is supported on fabric
     196             : struct TunnelInfo {
     197       13623 :     TunnelInfo() : type(TunnelType::INVALID) { Reset(); }
     198       13623 :     ~TunnelInfo() {}
     199             : 
     200       44071 :     void Reset() {
     201       44071 :         type = TunnelType::INVALID;
     202       44071 :         label = -1;
     203       44071 :         vxlan_id = -1;
     204       44071 :         src_port = 0;
     205       44071 :         ip_saddr = 0;
     206       44071 :         ip_daddr = 0;
     207       44071 :         eth = NULL;
     208       44071 :         ip = NULL;
     209       44071 :     }
     210             : 
     211             :     TunnelType          type;
     212             :     uint32_t            label;      // Valid only for MPLSoGRE and MPLSoUDP
     213             :     uint32_t            vxlan_id;   // Valid only for VXLAN
     214             :     uint16_t            src_port;   // Valid only for VXLAN and MPLSoUDP
     215             :     uint32_t            ip_saddr;
     216             :     uint32_t            ip_daddr;
     217             :     struct ether_header *eth;
     218             :     struct ip           *ip;
     219             : };
     220             : 
     221             : // Receive packets from the pkt0 (tap) interface, parse and send the packet to
     222             : // appropriate protocol task. Also, protocol tasks can send packets to pkt0
     223             : // or to other tasks.
     224             : class PktHandler {
     225             : public:
     226             :     typedef boost::function<bool(boost::shared_ptr<PktInfo>)> RcvQueueFunc;
     227             :     typedef boost::function<void(PktTrace::Pkt &)> PktTraceCallback;
     228             : 
     229             :     static const uint32_t kMulticastControlWord = 0;
     230             :     static const uint32_t kMulticastControlWordSize = 4;
     231             :     enum PktModuleName {
     232             :         INVALID,
     233             :         FLOW,
     234             :         ARP,
     235             :         DHCP,
     236             :         DHCPV6,
     237             :         DNS,
     238             :         ICMP,
     239             :         ICMPV6,
     240             :         DIAG,
     241             :         ICMP_ERROR,
     242             :         ICMPV6_ERROR,
     243             :         RX_PACKET,
     244             :         MAC_LEARNING,
     245             :         BFD,
     246             :         IGMP,
     247             :         MAC_IP_LEARNING,
     248             :         MAX_MODULES
     249             :     };
     250             : 
     251             :     struct PktStats {
     252             :         uint32_t sent[MAX_MODULES];
     253             :         uint32_t received[MAX_MODULES];
     254             :         uint32_t q_threshold_exceeded[MAX_MODULES];
     255             :         uint32_t dropped;
     256           2 :         void Reset() {
     257          34 :             for (int i = 0; i < MAX_MODULES; ++i) {
     258          32 :                 sent[i] = received[i] = q_threshold_exceeded[i] = 0;
     259             :             }
     260           2 :             dropped = 0;
     261           2 :         }
     262           2 :         PktStats() { Reset(); }
     263             :         void PktRcvd(PktModuleName mod);
     264             :         void PktSent(PktModuleName mod);
     265             :         void PktQThresholdExceeded(PktModuleName mod);
     266             :     };
     267             : 
     268             :     struct PacketBufferEnqueueItem {
     269             :         const AgentHdr hdr;
     270             :         const PacketBufferPtr buff;
     271             : 
     272          75 :         PacketBufferEnqueueItem(const AgentHdr &h, const PacketBufferPtr &b)
     273          75 :             : hdr(h), buff(b) {}
     274             :     };
     275             :     typedef WorkQueue<boost::shared_ptr<PacketBufferEnqueueItem> >
     276             :         PktHandlerQueue;
     277             : 
     278             :     PktHandler(Agent *, PktModule *pkt_module);
     279             :     virtual ~PktHandler();
     280             : 
     281             :     void Register(PktModuleName type, RcvQueueFunc cb);
     282             :     void Register(PktModuleName type, Proto *proto);
     283             : 
     284             :     void Send(const AgentHdr &hdr, const PacketBufferPtr &buff);
     285             : 
     286             :     PktModuleName ParsePacket(const AgentHdr &hdr, PktInfo *pkt_info,
     287             :                               uint8_t *pkt);
     288             :     PktModuleName ParseBfdDataPacket(const AgentHdr &hdr, PktInfo *pkt_info,
     289             :                               uint8_t *pkt);
     290             :     int ParseUserPkt(PktInfo *pkt_info, Interface *intf,
     291             :                      PktType::Type &pkt_type, uint8_t *pkt);
     292             :     bool ProcessPacket(boost::shared_ptr<PacketBufferEnqueueItem> item);
     293             :     bool ProcessBfdDataPacket(boost::shared_ptr<PacketBufferEnqueueItem> item);
     294             : // identify pkt type and send to the registered handler
     295             :     void HandleRcvPkt(const AgentHdr &hdr, const PacketBufferPtr &buff);
     296             :     void SendMessage(PktModuleName mod, InterTaskMsg *msg);
     297             : 
     298             :     bool IsGwPacket(const Interface *intf, const IpAddress &dst_ip);
     299             : 
     300          12 :     const PktStats &GetStats() const { return stats_; }
     301           0 :     void ClearStats() { stats_.Reset(); }
     302             :     void PktTraceIterate(PktModuleName mod, PktTraceCallback cb);
     303           0 :     void PktTraceClear(PktModuleName mod) { pkt_trace_.at(mod).Clear(); }
     304           0 :     void PktTraceBuffers(PktModuleName mod, uint32_t buffers) {
     305           0 :         pkt_trace_.at(mod).set_num_buffers(buffers);
     306           0 :     }
     307           0 :     uint32_t PktTraceBuffers(PktModuleName mod) const {
     308           0 :         return pkt_trace_.at(mod).num_buffers();
     309             :     }
     310           0 :     uint32_t PktTraceSize(PktModuleName mod) const {
     311           0 :         return pkt_trace_.at(mod).pkt_trace_size();
     312             :     }
     313             :     void AddPktTrace(PktModuleName module, PktTrace::Direction dir,
     314             :                      const PktInfo *pkt);
     315             : 
     316             :     uint32_t EncapHeaderLen() const;
     317          79 :     Agent *agent() const { return agent_; }
     318             :     PktModule *pkt_module() const { return pkt_module_; }
     319             :     void Enqueue(PktModuleName module, boost::shared_ptr<PktInfo> pkt_info);
     320             :     bool IsFlowPacket(PktInfo *pkt_info);
     321             :     void CalculatePortIP(PktInfo *pkt_info);
     322           5 :     const PktHandlerQueue *work_queue() const { return &work_queue_; }
     323             : 
     324             :     bool IsBFDHealthCheckPacket(const PktInfo *pkt_info,
     325             :                                 const Interface *interface);
     326             :     bool IsSegmentHealthCheckPacket(const PktInfo *pkt_info,
     327             :                                     const Interface *interface);
     328             : 
     329          12 :     uint64_t GetBfdKaEnqueueCount() {return work_queue_bfd_ka_.NumEnqueues(); }
     330          12 :     uint64_t GetPktEnqueueCount() {return work_queue_.NumEnqueues(); }
     331             : 
     332             : private:
     333             :     void PktModuleEnqueue(PktModuleName mod, const AgentHdr &hdr,
     334             :                           boost::shared_ptr<PktInfo> pkt_info, uint8_t *pkt);
     335             :     int ParseEthernetHeader(PktInfo *pkt_info, uint8_t *pkt);
     336             :     int ParseMplsHdr(PktInfo *pkt_info, uint8_t *pkt);
     337             :     int ParseIpPacket(PktInfo *pkt_info, PktType::Type &pkt_type,
     338             :                       uint8_t *ptr);
     339             : 
     340             :     int ParseMPLSoGRE(PktInfo *pkt_info, uint8_t *pkt);
     341             :     int ParseMPLSoUDP(PktInfo *pkt_info, uint8_t *pkt);
     342             :     int ParseControlWord(PktInfo *pkt_info, uint8_t *pkt,
     343             :                          const MplsLabel *mpls);
     344             :     int ParseUDPTunnels(PktInfo *pkt_info, uint8_t *pkt);
     345             :     int ParseVxlan(PktInfo *pkt_info, uint8_t *pkt);
     346             :     int ParseUdp(PktInfo *pkt_info, uint8_t *pkt);
     347             :     bool ComputeForwardingMode(PktInfo *pkt_info, const Interface *intf) const;
     348             : 
     349             :     void SetOuterIp(PktInfo *pkt_info, uint8_t *pkt);
     350             :     void SetOuterMac(PktInfo *pkt_info);
     351             :     bool IgnoreFragmentedPacket(PktInfo *pkt_info);
     352             :     bool IsDHCPPacket(PktInfo *pkt_info);
     353             :     bool IsValidInterface(uint32_t ifindex, Interface **interface);
     354             :     bool IsToRDevice(uint32_t vrf_id, const IpAddress &ip);
     355             :     bool IsManagedTORPacket(Interface *intf, PktInfo *pkt_info,
     356             :                             PktType::Type &pkt_type, uint8_t *pkt,
     357             :                             bool *pkt_ok);
     358             :     bool IsFlowPacket(const AgentHdr &agent_hdr);
     359             :     bool IsDiagPacket(PktInfo *pkt_info);
     360             :     bool ValidateIpPacket(PktInfo *pkt_info);
     361             : 
     362             :     boost::array<Proto *, MAX_MODULES> proto_list_;
     363             :     Proto *bfd_keepalive_proto_;
     364             : 
     365             :     PktStats stats_;
     366             :     boost::array<PktTrace, MAX_MODULES> pkt_trace_;
     367             :     DBTableBase::ListenerId iid_;
     368             : 
     369             :     Agent *agent_;
     370             :     PktModule *pkt_module_;
     371             :     PktHandlerQueue work_queue_;
     372             :     PktHandlerQueue work_queue_bfd_ka_;
     373             :     DISALLOW_COPY_AND_ASSIGN(PktHandler);
     374             : };
     375             : 
     376             : // Info from the parsed packet
     377             : struct PktInfo {
     378             :     PktHandler::PktModuleName module;
     379             :     uint8_t             *pkt;
     380             :     uint16_t            len;
     381             :     uint16_t            max_pkt_len;
     382             : 
     383             :     uint8_t             *data;
     384             :     InterTaskMsg        *ipc;
     385             : 
     386             :     Address::Family     family;
     387             :     PktType::Type       type;
     388             :     AgentHdr            agent_hdr;
     389             :     uint16_t            ether_type;
     390             :     // Fields extracted for processing in agent
     391             :     uint32_t            vrf;
     392             :     MacAddress          smac;
     393             :     MacAddress          dmac;
     394             :     IpAddress           ip_saddr;
     395             :     IpAddress           ip_daddr;
     396             :     uint8_t             ip_proto;
     397             :     uint32_t            sport;
     398             :     uint32_t            dport;
     399             :     uint32_t            ttl;
     400             :     uint16_t            icmp_chksum;
     401             : 
     402             :     MacAddress          b_smac;
     403             :     MacAddress          b_dmac;
     404             :     uint32_t            i_sid;
     405             : 
     406             :     bool                tcp_ack;
     407             :     TunnelInfo          tunnel;
     408             :     bool                l3_label;
     409             :     bool                multicast_label;
     410             :     bool                is_bfd_keepalive;  // bfd keepalive packet
     411             :     bool                is_segment_hc_pkt;
     412             :     VmInterface::FatFlowIgnoreAddressType ignore_address; //fat-flow config
     413             :     bool                same_port_number;
     414             :     bool                is_fat_flow_src_prefix; // indicates fat flow with src prefix
     415             :     IpAddress           ip_ff_src_prefix; // fat flow src prefix
     416             :     bool                is_fat_flow_dst_prefix; // indicates fat flow with dst prefix
     417             :     IpAddress           ip_ff_dst_prefix; // fat flow dst prefix
     418             : 
     419             :     // Pointer to different headers in user packet
     420             :     struct ether_header *eth;
     421             :     uint32_t            *pbb_header;
     422             :     struct ether_arp    *arp;
     423             :     struct ip           *ip;
     424             :     struct ip6_hdr      *ip6;
     425             :     union {
     426             :         struct tcphdr   *tcp;
     427             :         struct udphdr   *udp;
     428             :         struct icmp     *icmp;
     429             :         struct icmp6_hdr *icmp6;
     430             :         struct sctphdr *sctp;
     431             :         struct igmp     *igmp;
     432             :     } transp;
     433             : 
     434             :     PktInfo(Agent *agent, uint32_t buff_len, PktHandler::PktModuleName module,
     435             :             uint32_t mdata);
     436             :     PktInfo(const PacketBufferPtr &buff);
     437             :     PktInfo(const PacketBufferPtr &buff, const AgentHdr &hdr);
     438             :     PktInfo(PktHandler::PktModuleName module, InterTaskMsg *msg);
     439             :     virtual ~PktInfo();
     440             : 
     441             :     const AgentHdr &GetAgentHdr() const;
     442             :     void UpdateHeaderPtr();
     443             :     std::size_t hash(const Agent *agent,
     444             :              const EcmpLoadBalance &ecmp_has_fields_to_use) const;
     445             : 
     446        8891 :     PacketBuffer *packet_buffer() const { return packet_buffer_.get(); }
     447        2204 :     PacketBufferPtr packet_buffer_ptr() const { return packet_buffer_; }
     448             :     void AllocPacketBuffer(Agent *agent, uint32_t module, uint16_t len,
     449             :                            uint32_t mdata);
     450             :     void set_len(uint32_t len);
     451             :     void reset_packet_buffer();
     452             : 
     453             :     uint32_t GetUdpPayloadLength() const;
     454             : 
     455             : private:
     456             :     PacketBufferPtr     packet_buffer_;
     457             : };
     458             : 
     459             : #endif

Generated by: LCOV version 1.14