x86: Adjust the size of the values written to the x87 misc registers
[gem5.git] / src / base / inet.cc
index 8c3240fa6fdf00456e93d96e61c1240a5de23d8c..190a7a11ee22cbfe7c38ce7a1f015e427e34ec8b 100644 (file)
@@ -1,5 +1,18 @@
 /*
+ * Copyright (c) 2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2010 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Nathan Binkert
+ *          Gabe Black
+ *          Geoffrey Blake
  */
 
+#include <cstddef>
+#include <cstdio>
 #include <sstream>
 #include <string>
 
 #include "base/cprintf.hh"
-#include "sim/host.hh"
 #include "base/inet.hh"
+#include "base/types.hh"
 
 using namespace std;
 namespace Net {
@@ -45,12 +62,14 @@ EthAddr::EthAddr()
 
 EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
 {
-    *data = *ea;
+    for (int i = 0; i < ETH_ADDR_LEN; ++i)
+        data[i] = ea[i];
 }
 
 EthAddr::EthAddr(const eth_addr &ea)
 {
-    *data = *ea.data;
+    for (int i = 0; i < ETH_ADDR_LEN; ++i)
+        data[i] = ea.data[i];
 }
 
 EthAddr::EthAddr(const std::string &addr)
@@ -105,7 +124,7 @@ EthAddr::string() const
 bool
 operator==(const EthAddr &left, const EthAddr &right)
 {
-    return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
+    return !memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
 }
 
 ostream &
@@ -116,6 +135,73 @@ operator<<(ostream &stream, const EthAddr &ea)
     return stream;
 }
 
+string
+IpAddress::string() const
+{
+    stringstream stream;
+    stream << *this;
+    return stream.str();
+}
+
+bool
+operator==(const IpAddress &left, const IpAddress &right)
+{
+    return left.ip() == right.ip();
+}
+
+ostream &
+operator<<(ostream &stream, const IpAddress &ia)
+{
+    uint32_t ip = ia.ip();
+    ccprintf(stream, "%x.%x.%x.%x",
+            (uint8_t)(ip >> 24), (uint8_t)(ip >> 16),
+            (uint8_t)(ip >> 8),  (uint8_t)(ip >> 0));
+    return stream;
+}
+
+string
+IpNetmask::string() const
+{
+    stringstream stream;
+    stream << *this;
+    return stream.str();
+}
+
+bool
+operator==(const IpNetmask &left, const IpNetmask &right)
+{
+    return (left.ip() == right.ip()) &&
+        (left.netmask() == right.netmask());
+}
+
+ostream &
+operator<<(ostream &stream, const IpNetmask &in)
+{
+    ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask());
+    return stream;
+}
+
+string
+IpWithPort::string() const
+{
+    stringstream stream;
+    stream << *this;
+    return stream.str();
+}
+
+bool
+operator==(const IpWithPort &left, const IpWithPort &right)
+{
+    return (left.ip() == right.ip()) && (left.port() == right.port());
+}
+
+ostream &
+operator<<(ostream &stream, const IpWithPort &iwp)
+{
+    ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port());
+    return stream;
+}
+
 uint16_t
 cksum(const IpPtr &ptr)
 {
@@ -133,13 +219,42 @@ __tu_cksum(const IpPtr &ip)
     return ip_cksum_carry(sum);
 }
 
+uint16_t
+__tu_cksum6(const Ip6Ptr &ip6)
+{
+   int tcplen = ip6->plen() - ip6->extensionLength();
+   int sum = ip_cksum_add(ip6->payload(), tcplen, 0);
+   sum = ip_cksum_add(ip6->src(), 32, sum);
+   sum += htons(ip6->proto() + tcplen);
+   return ip_cksum_carry(sum);
+}
+
 uint16_t
 cksum(const TcpPtr &tcp)
-{ return __tu_cksum(IpPtr(tcp.packet())); }
+{
+    if (IpPtr(tcp.packet())) {
+        return __tu_cksum(IpPtr(tcp.packet()));
+    } else if (Ip6Ptr(tcp.packet())) {
+        return __tu_cksum6(Ip6Ptr(tcp.packet()));
+    } else {
+        assert(0);
+    }
+    // Should never reach here
+    return 0;
+}
 
 uint16_t
 cksum(const UdpPtr &udp)
-{ return __tu_cksum(IpPtr(udp.packet())); }
+{
+    if (IpPtr(udp.packet())) {
+        return __tu_cksum(IpPtr(udp.packet()));
+    } else if (Ip6Ptr(udp.packet())) {
+        return __tu_cksum6(Ip6Ptr(udp.packet()));
+    } else {
+        assert(0);
+    }
+    return 0;
+}
 
 bool
 IpHdr::options(vector<const IpOpt *> &vec) const
@@ -162,6 +277,82 @@ IpHdr::options(vector<const IpOpt *> &vec) const
     return true;
 }
 
+#define IP6_EXTENSION(nxt) (nxt == IP_PROTO_HOPOPTS) ? true : \
+                           (nxt == IP_PROTO_ROUTING) ? true : \
+                           (nxt == IP_PROTO_FRAGMENT) ? true : \
+                           (nxt == IP_PROTO_AH) ? true : \
+                           (nxt == IP_PROTO_ESP) ? true: \
+                           (nxt == IP_PROTO_DSTOPTS) ? true : false
+
+/* Scan the IP6 header for all header extensions
+ * and return the number of headers found
+ */
+int
+Ip6Hdr::extensionLength() const
+{
+    const uint8_t *data = bytes() + IP6_HDR_LEN;
+    uint8_t nxt = ip6_nxt;
+    int len = 0;
+    int all = plen();
+
+    while (IP6_EXTENSION(nxt)) {
+        const Ip6Opt *ext = (const Ip6Opt *)data;
+        nxt = ext->nxt();
+        len += ext->len();
+        data += ext->len();
+        all -= ext->len();
+        assert(all >= 0);
+    }
+    return len;
+}
+
+/* Scan the IP6 header for a particular extension
+ * header type and return a pointer to it if it
+ * exists, otherwise return NULL
+ */
+const Ip6Opt*
+Ip6Hdr::getExt(uint8_t ext_type) const
+{
+    const uint8_t *data = bytes() + IP6_HDR_LEN;
+    uint8_t nxt = ip6_nxt;
+    Ip6Opt* opt = NULL;
+    int all = plen();
+
+    while (IP6_EXTENSION(nxt)) {
+        opt = (Ip6Opt *)data;
+        if (nxt == ext_type) {
+            break;
+        }
+        nxt = opt->nxt();
+        data += opt->len();
+        all -= opt->len();
+        opt = NULL;
+        assert(all >= 0);
+    }
+    return (const Ip6Opt*)opt;
+}
+
+/* Scan the IP6 header and any extension headers
+ * to find what type of Layer 4 header exists
+ * after this header
+ */
+uint8_t
+Ip6Hdr::proto() const
+{
+    const uint8_t *data = bytes() + IP6_HDR_LEN;
+    uint8_t nxt = ip6_nxt;
+    int all = plen();
+
+    while (IP6_EXTENSION(nxt)) {
+        const Ip6Opt *ext = (const Ip6Opt *)data;
+        nxt = ext->nxt();
+        data += ext->len();
+        all -= ext->len();
+        assert(all >= 0);
+    }
+    return nxt;
+}
+
 bool
 TcpHdr::options(vector<const TcpOpt *> &vec) const
 {
@@ -183,35 +374,13 @@ TcpHdr::options(vector<const TcpOpt *> &vec) const
     return true;
 }
 
-bool
-TcpOpt::sack(vector<SackRange> &vec) const
-{
-    vec.clear();
-
-    const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
-    int all = len() - offsetof(tcp_opt, opt_data.sack);
-    while (all > 0) {
-        const uint16_t *sack = (const uint16_t *)data;
-        int len = sizeof(uint16_t) * 2;
-        if (all < len) {
-            vec.clear();
-            return false;
-        }
-
-        vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
-        all -= len;
-        data += len;
-    }
-
-    return false;
-}
-
 int 
 hsplit(const EthPacketPtr &ptr)
 {
     int split_point = 0;
 
     IpPtr ip(ptr);
+    Ip6Ptr ip6(ptr);
     if (ip) {
         split_point = ip.pstart();
 
@@ -222,9 +391,18 @@ hsplit(const EthPacketPtr &ptr)
         UdpPtr udp(ip);
         if (udp)
             split_point = udp.pstart();
+    } else if (ip6) {
+        split_point = ip6.pstart();
+
+        TcpPtr tcp(ip6);
+        if (tcp)
+            split_point = tcp.pstart();
+        UdpPtr udp(ip6);
+        if (udp)
+            split_point = udp.pstart();
     }
     return split_point;
 }
 
 
-/* namespace Net */ }
+} // namespace Net