summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Barnea <ibarnea@cisco.com>2016-10-05 10:30:34 +0300
committerIdo Barnea <ibarnea@cisco.com>2016-10-05 10:30:34 +0300
commit15499f72d642b4ed99f4f71d50d04cf70953aeac (patch)
tree1ad6eb98231db1b7d6408a455197a660803c5594
parent432946c5c42e1138bcc2b3ba8731348301d9dc65 (diff)
Implementation of Ipv6Header::getl4Proto + cleanup in Ipv6 files
-rwxr-xr-xlinux/ws_main.py1
-rwxr-xr-xlinux_dpdk/ws_main.py1
-rwxr-xr-xsrc/common/Network/Packet/IPv6Header.cpp89
-rwxr-xr-xsrc/common/Network/Packet/IPv6Header.h301
-rwxr-xr-xsrc/common/Network/Packet/IPv6Header.inl2
-rw-r--r--src/flow_stat_parser.cpp36
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 <common/BigEndianBitManipulation.h>
+
+//--------------------------------
+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; i<IPV6_16b_ADDR_GROUPS; i++) {
+ argDestAddress[i] = PKT_NTOHS(myDestination[i]);
+ }
+}
+
+inline void IPv6Header::setDestIpv6(uint16_t *argDestAddress)
+{
+ uint8_t i;
+ for (i = 0; i < IPV6_16b_ADDR_GROUPS; i++) {
+ myDestination[i] = PKT_HTONS(argDestAddress[i]);
+ }
+}
+
+//--------------------------------
+inline void IPv6Header::updateIpv6Src(uint16_t *ipsrc)
+{
+ uint8_t i;
+ for (i = 0; i < IPV6_16b_ADDR_GROUPS; i++) {
+ mySource[i] = PKT_HTONS(ipsrc[i]);
+ }
+}
+
+inline void IPv6Header::updateIpv6Dst(uint16_t *ipdst)
+{
+ uint8_t i;
+ for (i = 0; i < IPV6_16b_ADDR_GROUPS; i++) {
+ myDestination[i] = PKT_HTONS(ipdst[i]);
+ }
+}
+
+//--------------------------------
+inline void IPv6Header::updateMSBIpv6Src(uint16_t *ipsrc)
+{
+ uint8_t i;
+ for (i=0; i<IPV6_16b_ADDR_GROUPS_MSB; i++) {
+ mySource[i] = PKT_HTONS(ipsrc[i]);
+ }
+}
+
+inline void IPv6Header::updateMSBIpv6Dst(uint16_t *ipdst)
+{
+ uint8_t i;
+ for (i = 0; i < IPV6_16b_ADDR_GROUPS_MSB; i++) {
+ myDestination[i] = PKT_HTONS(ipdst[i]);
+ }
+}
+
+//--------------------------------
+inline void IPv6Header::updateLSBIpv6Src(uint32_t ipsrc)
+{
+ uint32_t *lsb = (uint32_t *)&mySource[6];
+ *lsb = PKT_HTONL(ipsrc);
+}
+
+inline void IPv6Header::updateLSBIpv6Dst(uint32_t ipdst)
+{
+ uint32_t *lsb = (uint32_t *)&myDestination[6];
+ *lsb = PKT_HTONL(ipdst);
+}
+
+//--------------------------------
+inline void IPv6Header::swapSrcDest()
+{
+ uint8_t i;
+ uint16_t tmp[IPV6_16b_ADDR_GROUPS];
+ for (i = 0; i < IPV6_16b_ADDR_GROUPS; i++) {
+ tmp[i] = myDestination[i];
+ myDestination[i] = mySource[i];
+ mySource[i] = tmp[i];
+ }
+}
+
+#endif
diff --git a/src/common/Network/Packet/IPv6Header.inl b/src/common/Network/Packet/IPv6Header.inl
index 5098bc3e..d6f11fdc 100755
--- a/src/common/Network/Packet/IPv6Header.inl
+++ b/src/common/Network/Packet/IPv6Header.inl
@@ -34,7 +34,7 @@ inline uint16_t IPv6Header::getTrafficClass()
return getMaskBit32(PKT_NTOHL(myVer_TrafficClass_FlowLabel), 4, 11);
}
-inline void
+inline void
IPv6Header::setTrafficClass(uint16_t argTrafficClass)
{
uint32_t myTrafficClass = PKT_HTONL(myVer_TrafficClass_FlowLabel);
diff --git a/src/flow_stat_parser.cpp b/src/flow_stat_parser.cpp
index fd0fb80a..b809b0f9 100644
--- a/src/flow_stat_parser.cpp
+++ b/src/flow_stat_parser.cpp
@@ -190,7 +190,6 @@ uint8_t CFlowStatParser::get_ttl(){
// specific cases, while parse is used in many places (including on packet RX path, where we want to be as fast as possible)
int CFlowStatParser::get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload_len) {
uint16_t l2_header_len;
- uint16_t l3_header_len;
uint16_t l4_header_len;
uint8_t *p_l3 = NULL;
uint8_t *p_l4 = NULL;
@@ -202,35 +201,12 @@ int CFlowStatParser::get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload
if (m_ipv4) {
l2_header_len = ((uint8_t *)m_ipv4) - p;
- l3_header_len = m_ipv4->getHeaderLength();
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;
}