Implementation of Ipv6Header::getl4Proto + cleanup in Ipv6 files
authorIdo Barnea <[email protected]>
Wed, 5 Oct 2016 07:30:34 +0000 (10:30 +0300)
committerIdo Barnea <[email protected]>
Wed, 5 Oct 2016 07:30:34 +0000 (10:30 +0300)
linux/ws_main.py
linux_dpdk/ws_main.py
src/common/Network/Packet/IPv6Header.cpp
src/common/Network/Packet/IPv6Header.h
src/common/Network/Packet/IPv6Header.inl
src/flow_stat_parser.cpp

index a140e17..f20afcc 100755 (executable)
@@ -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',
index f895204..dc169f1 100755 (executable)
@@ -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',
index cf1f632..3856120 100755 (executable)
@@ -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;
 }
-
-
-
index 8a24635..05653bd 100755 (executable)
@@ -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
index 5098bc3..d6f11fd 100755 (executable)
@@ -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);
index fd0fb80..b809b0f 100644 (file)
@@ -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;
 }