diff options
Diffstat (limited to 'src/flow_stat_parser.h')
-rw-r--r-- | src/flow_stat_parser.h | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/flow_stat_parser.h b/src/flow_stat_parser.h new file mode 100644 index 00000000..df70e4ec --- /dev/null +++ b/src/flow_stat_parser.h @@ -0,0 +1,175 @@ +/* + Ido Barnea + Cisco Systems, Inc. +*/ + +/* + Copyright (c) 2016-2016 Cisco Systems, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef __FLOW_STAT_PARSER_H__ +#define __FLOW_STAT_PARSER_H__ + +#include <arpa/inet.h> +#include "common/Network/Packet/IPHeader.h" +#include "common/Network/Packet/IPv6Header.h" +#include "common/Network/Packet/TcpHeader.h" +#include "mbuf.h" + +// Basic flow stat parser. Relevant for xl710/x710/x350 cards +class CFlowStatParser { + friend class CFlowStatParserTest; + public: + virtual ~CFlowStatParser() {} + virtual void reset(); + virtual int parse(uint8_t *pkt, uint16_t len); + virtual bool is_stat_supported() {return m_stat_supported == true;} + virtual int get_ip_id(uint32_t &ip_id); + virtual int set_ip_id(uint32_t ip_id); + virtual int get_l3_proto(uint16_t &proto); + virtual int get_l4_proto(uint8_t &proto); + virtual int get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload_len); + virtual uint16_t get_pkt_size(); + virtual uint8_t get_ttl(); + uint8_t *get_l3() { + if (m_ipv4) + return (uint8_t *)m_ipv4; + else + return (uint8_t *)m_ipv6; + } + uint8_t * get_l4() {return m_l4;} + + inline bool IsNatInfoPkt(bool &first) { + if (!m_ipv4 || (m_l4_proto != IPPROTO_TCP)) { + return false; + } + if ((m_l4 + TCP_HEADER_LEN) > (uint8_t *)m_ipv4 + get_pkt_size()) { + return false; + } + // If we are here, relevant fields from tcp header are inside the packet boundaries + // We want to handle SYN and SYN+ACK packets + TCPHeader *tcp = (TCPHeader *)m_l4; + if (! tcp->getSynFlag()) + return false; + + if (! tcp->getAckFlag()) { + first = true; + } else { + first = false; + } + return true; + } + + private: + char *create_test_pkt(int ip_ver, uint16_t l4_proto, uint8_t ttl + , uint32_t ip_id, uint16_t flags, int &pkt_size); + + protected: + uint8_t *m_start; + uint16_t m_len; + IPHeader *m_ipv4; + IPv6Header *m_ipv6; + uint8_t *m_l4; + bool m_stat_supported; + uint8_t m_l4_proto; + uint8_t m_vlan_offset; +}; + +// relevant for 82599 card +class C82599Parser : public CFlowStatParser { + public: + C82599Parser(bool vlan_supported) {m_vlan_supported = vlan_supported;} + ~C82599Parser() {} + int parse(uint8_t *pkt, uint16_t len); + + private: + bool m_vlan_supported; +}; + +class CPassAllParser : public CFlowStatParser { + public: + virtual int parse(uint8_t *pkt, uint16_t len); + virtual bool is_stat_supported() {return true;} + virtual int get_ip_id(uint32_t &ip_id) { ip_id = 0; return 0;} + virtual int set_ip_id(uint32_t ip_id){return 0;} + virtual int get_l3_proto(uint16_t &proto){proto = 0; return 0;} + virtual int get_l4_proto(uint8_t &proto) {proto = 0; return 0;} + virtual int get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload_len) {payload_len = m_len; return 0;} +}; + +// Used for latency statefull packets. Need to be merged with above parser +class CSimplePacketParser { + public: + CSimplePacketParser(rte_mbuf_t * m){ + m_m = m; + m_l4 = NULL; + } + bool Parse(); + + // Check if this packet contains NAT info in TCP ack + // first - set to true if this is the first packet of the flow. false otherwise. + // relevant only if return value is true + inline bool IsNatInfoPkt(bool &first) { + if (!m_ipv4 || (m_protocol != IPPROTO_TCP)) { + return false; + } + if (! m_l4 || (m_l4 - rte_pktmbuf_mtod(m_m, uint8_t*) + TCP_HEADER_LEN) > m_m->data_len) { + return false; + } + // If we are here, relevant fields from tcp header are guaranteed to be in first mbuf + // We want to handle SYN and SYN+ACK packets + TCPHeader *tcp = (TCPHeader *)m_l4; + if (! tcp->getSynFlag()) + return false; + + if (! tcp->getAckFlag()) { + first = true; + } else { + first = false; + } + return true; + } + + public: + IPHeader * m_ipv4; + IPv6Header * m_ipv6; + uint8_t m_protocol; + uint16_t m_vlan_offset; + uint8_t * m_l4; + private: + rte_mbuf_t * m_m; +}; + +class CFlowStatParserTest { + enum { + P_OK = 0x1, + P_BAD = 0x2, + P82599_OK = 0x4, + P82599_BAD = 0x8, + P82599_VLAN_OK = 0x10, + P82599_VLAN_BAD = 0x20, + }; + + public: + int test(); + + private: + int test_one_pkt(const char *name, uint16_t ether_type, uint8_t l4_proto, bool is_vlan, uint16_t verify_flags); + int verify_pkt(uint8_t *p, uint16_t pkt_size, uint16_t payload_len, uint32_t ip_id, uint8_t l4_proto, uint16_t flags); + int verify_pkt_one_parser(uint8_t * p, uint16_t pkt_size, uint16_t payload_len, uint32_t ip_id, uint8_t l4_proto + , CFlowStatParser &parser, bool sup_pkt); +}; + +#endif |