From 15499f72d642b4ed99f4f71d50d04cf70953aeac Mon Sep 17 00:00:00 2001 From: Ido Barnea Date: Wed, 5 Oct 2016 10:30:34 +0300 Subject: Implementation of Ipv6Header::getl4Proto + cleanup in Ipv6 files --- linux/ws_main.py | 1 + linux_dpdk/ws_main.py | 1 + src/common/Network/Packet/IPv6Header.cpp | 89 ++++----- src/common/Network/Packet/IPv6Header.h | 301 +++++++++++++++++++++++-------- src/common/Network/Packet/IPv6Header.inl | 2 +- src/flow_stat_parser.cpp | 36 +--- 6 files changed, 275 insertions(+), 155 deletions(-) diff --git a/linux/ws_main.py b/linux/ws_main.py index a140e174..f20afcce 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -148,6 +148,7 @@ net_src = SrcGroup(dir='src/common/Network/Packet', 'CPktCmn.cpp', 'EthernetHeader.cpp', 'IPHeader.cpp', + 'IPv6Header.cpp', 'TCPHeader.cpp', 'TCPOptions.cpp', 'UDPHeader.cpp', diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index f895204c..dc169f11 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -150,6 +150,7 @@ net_src = SrcGroup(dir='src/common/Network/Packet', 'CPktCmn.cpp', 'EthernetHeader.cpp', 'IPHeader.cpp', + 'IPv6Header.cpp', 'TCPHeader.cpp', 'TCPOptions.cpp', 'UDPHeader.cpp', diff --git a/src/common/Network/Packet/IPv6Header.cpp b/src/common/Network/Packet/IPv6Header.cpp index cf1f632a..3856120f 100755 --- a/src/common/Network/Packet/IPv6Header.cpp +++ b/src/common/Network/Packet/IPv6Header.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-2015 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. @@ -16,56 +16,39 @@ limitations under the License. #include "IPv6Header.h" - -char * IPv6Header::Protocol::interpretIpProtocolName(uint8_t argType) -{ - switch (argType) - { - case TCP: - return (char *)"TCP"; - break; - case UDP: - return (char *)"UDP"; - break; - case IP: - return (char *)"IP"; - break; - case ICMP: - return (char *)"ICMP"; - break; - case ESP: - return (char *)"ESP"; - break; - case AH: - return (char *)"AH"; - break; - case IGMP: - return (char *)"IGMP"; - break; - default: - return (char *)NULL; - break; - } -} - -void IPv6Header::dump(FILE *fd) -{ - fprintf(fd, "\nIPv6Header"); - fprintf(fd, "\nSource 0x%.8lX, Destination 0x%.8lX, Protocol 0x%.1X", - getSourceIp(), getDestIp(), getProtocol()); - fprintf(fd, "\nTTL : %d, Id : 0x%.2X, Ver %d, Header Length %d, Total Length %d", - getTimeToLive(), getId(), getVersion(), getHeaderLength(), getTotalLength()); - if(isFragmented()) - { - fprintf(fd,"\nIsFirst %d, IsMiddle %d, IsLast %d, Offset %d", - isFirstFragment(), isMiddleFragment(), isLastFragment(), getFragmentOffset()); - } - else - { - fprintf(fd, "\nDont fragment %d", isDontFragment()); - } - fprintf(fd, "\n"); +/* + * Return l4 type of Ipv6 packet + * pkt - pointer to start of packet data (including header) + * pkt_len - length of packet (including header) + * p_l4 - return pointer to start of l4 header + */ +uint8_t IPv6Header::getl4Proto(uint8_t *pkt, uint16_t pkt_len, uint8_t *&p_l4) { + bool stop = false; + uint8_t *next_header = pkt + IPV6_HDR_LEN;; + uint8_t next_header_type = myNextHdr; + uint16_t len_left = pkt_len - IPV6_HDR_LEN; + uint16_t curr_header_len; + + do { + switch(next_header_type) { + case IPPROTO_HOPOPTS: + case IPPROTO_ROUTING: + case IPPROTO_ENCAP_SEC: + case IPPROTO_AUTH: + case IPPROTO_FRAGMENT: + case IPPROTO_DSTOPTS: + case IPPROTO_MH: + next_header_type = next_header[0]; + curr_header_len = (next_header[1] + 1) * 8; + next_header += curr_header_len; + len_left -= curr_header_len; + break; + default: + stop = true; + break; + } + } while ((! stop) && len_left >= 2); + + p_l4 = next_header; + return next_header_type; } - - - diff --git a/src/common/Network/Packet/IPv6Header.h b/src/common/Network/Packet/IPv6Header.h index 8a246359..05653bdd 100755 --- a/src/common/Network/Packet/IPv6Header.h +++ b/src/common/Network/Packet/IPv6Header.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-2015 Cisco Systems, Inc. +Copyright (c) 2015-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. @@ -22,14 +22,25 @@ limitations under the License. #define IPV6_16b_ADDR_GROUPS 8 #define IPV6_16b_ADDR_GROUPS_MSB 6 #define IPV6_HDR_LEN 40 -static uint16_t default_ipv6[8] = { 0xDEAD, 0xBEEF, - 0xDEAD, 0xBEEF, - 0xDEAD, 0xBEEF, - 0xDEAD, 0xBEEF }; - +static uint16_t default_ipv6[8] = { 0xDEAD, 0xBEEF, 0xDEAD, 0xBEEF, + 0xDEAD, 0xBEEF, 0xDEAD, 0xBEEF }; class IPv6Header { +/* + * IPV6 extension headers + */ + enum ext_headers_e { + IPPROTO_HOPOPTS = 0, /* IPv6 hop-by-hop options */ + IPPROTO_ROUTING = 43, /* IPv6 routing header */ + IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header */ + IPPROTO_ENCAP_SEC = 50, /* IPv6 encapsulation security paylod header */ + IPPROTO_AUTH = 51, /* IPv6 authentication header */ + IPPROTO_ICMPV6 = 58, /* ICMPv6 */ + IPPROTO_NONE = 59, /* IPv6 no next header */ + IPPROTO_DSTOPTS = 60, /* IPv6 destination options */ + IPPROTO_MH = 135, /* IPv6 mobility header */ + }; public: IPv6Header() @@ -38,10 +49,8 @@ public: setSourceIpv6(default_ipv6); setTrafficClass(0xDD); }; - - IPv6Header (uint16_t *argSource, - uint16_t *argDestinaction, - uint8_t argTrafficClass) + + IPv6Header (uint16_t *argSource, uint16_t *argDestinaction, uint8_t argTrafficClass) { setDestIpv6(argDestinaction); setSourceIpv6(argSource); @@ -53,69 +62,51 @@ public: DefaultSize = 40 }; - -public: - - inline uint8_t getVersion (); - inline void setVersion (uint8_t); - - inline uint8_t getHeaderLength (){return (IPV6_HDR_LEN);} - - inline uint16_t getTrafficClass (); - inline void setTrafficClass (uint16_t); - - inline uint32_t getFlowLabel (); - inline void setFlowLabel (uint32_t); - - inline uint16_t getPayloadLen (); - inline void setPayloadLen (uint16_t); - - inline uint8_t getNextHdr (); - inline void setNextHdr (uint8_t); - - inline uint8_t getHopLimit (); - inline void setHopLimit (uint8_t); - - inline void getSourceIpv6 (uint16_t *); - inline void setSourceIpv6 (uint16_t *); - - inline void getDestIpv6 (uint16_t *); - inline void setDestIpv6 (uint16_t *); - public: - - inline void updateTrafficClass(uint8_t newclass); - inline void updatePayloadLength(uint16_t newlen); - inline void updateIpv6Src(uint16_t *ipsrc); - inline void updateIpv6Dst(uint16_t *ipdst); - inline void updateMSBIpv6Src(uint16_t *ipsrc); - inline void updateMSBIpv6Dst(uint16_t *ipdst); - inline void updateLSBIpv6Src(uint32_t ipsrc); - inline void updateLSBIpv6Dst(uint32_t ipdst); - - inline void swapSrcDest(); + inline uint8_t getVersion(); + inline void setVersion(uint8_t); + inline uint8_t getHeaderLength() {return IPV6_HDR_LEN;} + inline uint16_t getTrafficClass(); + inline void setTrafficClass(uint16_t); + inline uint32_t getFlowLabel(); + inline void setFlowLabel(uint32_t); + inline uint16_t getPayloadLen(); + inline void setPayloadLen(uint16_t); + inline uint8_t getNextHdr(); + inline void setNextHdr(uint8_t); + inline uint8_t getHopLimit(); + inline void setHopLimit(uint8_t); + inline void getSourceIpv6(uint16_t *); + inline void setSourceIpv6(uint16_t *); + inline void getDestIpv6(uint16_t *); + inline void setDestIpv6(uint16_t *); + uint8_t getl4Proto(uint8_t *pkt, uint16_t pkt_len, uint8_t *&p_l4); + inline void updateTrafficClass(uint8_t newclass); + inline void updatePayloadLength(uint16_t newlen); + inline void updateIpv6Src(uint16_t *ipsrc); + inline void updateIpv6Dst(uint16_t *ipdst); + inline void updateMSBIpv6Src(uint16_t *ipsrc); + inline void updateMSBIpv6Dst(uint16_t *ipdst); + inline void updateLSBIpv6Src(uint32_t ipsrc); + inline void updateLSBIpv6Dst(uint32_t ipdst); + inline void swapSrcDest(); //////////////////////////////////////////////////////////////////////////////////////// // Common Header Interface //////////////////////////////////////////////////////////////////////////////////////// -public: +public: inline uint8_t* getPointer (){return (uint8_t*)this;} inline uint32_t getSize (){return getHeaderLength();} - void dump (FILE* fd); - - public: - uint32_t myVer_TrafficClass_FlowLabel; - - uint16_t myPayloadLen; - uint8_t myNextHdr; - uint8_t myHopLimit; - - uint16_t mySource[IPV6_16b_ADDR_GROUPS]; - uint16_t myDestination[IPV6_16b_ADDR_GROUPS]; - uint32_t myOption[1]; + uint32_t myVer_TrafficClass_FlowLabel; + uint16_t myPayloadLen; + uint8_t myNextHdr; + uint8_t myHopLimit; + uint16_t mySource[IPV6_16b_ADDR_GROUPS]; + uint16_t myDestination[IPV6_16b_ADDR_GROUPS]; + uint32_t myOption[1]; }; @@ -124,19 +115,187 @@ class IPv6PseudoHeader public: uint32_t m_source_ip; uint32_t m_dest_ip; - uint8_t m_zero; - uint8_t m_protocol; - uint16_t m_length; + uint8_t m_zero; + uint8_t m_protocol; + uint16_t m_length; + public: inline uint8_t* getPointer(){return (uint8_t*)this;} + inline uint32_t getSize(); + inline uint16_t inetChecksum(); +}; - inline uint32_t getSize(); - inline uint16_t inetChecksum(); -}; +///////////////////////////////////////////// +// inline functions implementation +///////////////////////////////////////////// + +#include + +//-------------------------------- +inline uint8_t IPv6Header::getVersion() +{ + return getMaskBit32(PKT_NTOHL(myVer_TrafficClass_FlowLabel), 0, 3); +} + +inline void IPv6Header::setVersion(uint8_t argVersion) +{ + uint32_t myVer = PKT_HTONL(myVer_TrafficClass_FlowLabel); + setMaskBit32(myVer, 0, 3, argVersion); + myVer_TrafficClass_FlowLabel = PKT_NTOHL(myVer); +} +//-------------------------------- +inline uint16_t IPv6Header::getTrafficClass() +{ + return getMaskBit32(PKT_NTOHL(myVer_TrafficClass_FlowLabel), 4, 11); +} + +inline void +IPv6Header::setTrafficClass(uint16_t argTrafficClass) +{ + uint32_t myTrafficClass = PKT_HTONL(myVer_TrafficClass_FlowLabel); + setMaskBit32(myTrafficClass, 4, 11, argTrafficClass); + myVer_TrafficClass_FlowLabel = PKT_NTOHL(myTrafficClass); +} -#include "IPv6Header.inl" +//-------------------------------- +inline uint32_t IPv6Header::getFlowLabel() +{ + return getMaskBit32(PKT_NTOHL(myVer_TrafficClass_FlowLabel), 12, 31); +} -#endif +inline void IPv6Header::setFlowLabel(uint32_t argFlowLabel) +{ + uint32_t myFlowLabel = PKT_HTONL(myVer_TrafficClass_FlowLabel); + setMaskBit32(myFlowLabel, 12, 31, argFlowLabel); + myVer_TrafficClass_FlowLabel = PKT_NTOHL(myFlowLabel); +} + +//-------------------------------- +inline uint16_t IPv6Header::getPayloadLen() +{ + return PKT_NTOHS(myPayloadLen); +} +inline void IPv6Header::setPayloadLen(uint16_t argPayloadLen) +{ + myPayloadLen = PKT_HTONS(argPayloadLen); +} + +//-------------------------------- +inline uint8_t IPv6Header::getNextHdr() +{ + return myNextHdr; +} + +inline void IPv6Header::setNextHdr(uint8_t argNextHdr) +{ + myNextHdr = argNextHdr; +} + +//-------------------------------- +inline uint8_t IPv6Header::getHopLimit() +{ + return myHopLimit; +} + +inline void IPv6Header::setHopLimit(uint8_t argHopLimit) +{ + myHopLimit = argHopLimit; +} + +//-------------------------------- +inline void IPv6Header::getSourceIpv6(uint16_t *argSourceAddress) +{ + uint8_t i; + for (i = 0; i < IPV6_16b_ADDR_GROUPS; i++) { + argSourceAddress[i] = PKT_NTOHS(mySource[i]); + } +} + +inline void IPv6Header::setSourceIpv6(uint16_t *argSourceAddress) +{ + uint8_t i; + for (i = 0; i < IPV6_16b_ADDR_GROUPS; i++) { + mySource[i] = PKT_HTONS(argSourceAddress[i]); + } +} + +//-------------------------------- +inline void IPv6Header::getDestIpv6(uint16_t *argDestAddress) +{ + uint8_t i; + for (i=0; igetHeaderLength(); m_l4_proto = m_ipv4->getProtocol(); p_l3 = (uint8_t *)m_ipv4; + p_l4 = p_l3 + m_ipv4->getHeaderLength(); } else if (m_ipv6) { - uint8_t *next_header; - uint8_t next_header_type; - uint16_t len_left; - - p_l3 = (uint8_t *)m_ipv6; l2_header_len = ((uint8_t *)m_ipv6) - p; - next_header_type = m_ipv6->getNextHdr(); - next_header = p_l3 + IPV6_HDR_LEN; - l3_header_len = IPV6_HDR_LEN; - len_left = len - IPV6_HDR_LEN; - while ((next_header_type != IPPROTO_UDP) && (next_header_type != IPPROTO_TCP) && - (next_header_type != IPPROTO_NONE) && (len_left >= 2)) { - next_header_type = next_header[0]; - uint16_t curr_header_len = (next_header[1] + 1) * 8; - next_header += curr_header_len; - l3_header_len += curr_header_len; - len_left -= curr_header_len; - } - if ((next_header_type != IPPROTO_UDP) && (next_header_type != IPPROTO_TCP)) { - // L4 type we don't know. Assume everyting after IPv6 header is L4 - l3_header_len = IPV6_HDR_LEN; - m_l4_proto = m_ipv6->getNextHdr(); - } else { - m_l4_proto = next_header_type; - } + m_l4_proto = m_ipv6->getl4Proto((uint8_t *)m_ipv6, len - l2_header_len, p_l4); } switch (m_l4_proto) { @@ -238,7 +214,6 @@ int CFlowStatParser::get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload l4_header_len = 8; break; case IPPROTO_TCP: - p_l4 = p_l3 + l3_header_len; if ((p_l4 + TCP_HEADER_LEN) > (p + len)) { //Not enough space for TCP header payload_len = 0; @@ -252,15 +227,16 @@ int CFlowStatParser::get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload break; default: l4_header_len = 0; + break; } - if (len < l2_header_len + l3_header_len + l4_header_len) { + payload_len = len - (p_l4 - p) - l4_header_len; + + if (payload_len <= 0) { payload_len = 0; return -3; } - payload_len = len - l2_header_len - l3_header_len - l4_header_len; - return 0; } -- cgit 1.2.3-korg