Apply the gem5 namespace to the codebase. Some anonymous namespaces could theoretically be removed, but since this change's main goal was to keep conflicts at a minimum, it was decided not to modify much the general shape of the files. A few missing comments of the form "// namespace X" that occurred before the newly added "} // namespace gem5" have been added for consistency. std out should not be included in the gem5 namespace, so they weren't. ProtoMessage has not been included in the gem5 namespace, since I'm not familiar with how proto works. Regarding the SystemC files, although they belong to gem5, they actually perform integration between gem5 and SystemC; therefore, it deserved its own separate namespace. Files that are automatically generated have been included in the gem5 namespace. The .isa files currently are limited to a single namespace. This limitation should be later removed to make it easier to accomodate a better API. Regarding the files in util, gem5:: was prepended where suitable. Notice that this patch was tested as much as possible given that most of these were already not previously compiling. Change-Id: Ia53d404ec79c46edaa98f654e23bc3b0e179fe2d Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/46323 Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu> Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu> Reviewed-by: Matthew Poremba <matthew.poremba@amd.com> Tested-by: kokoro <noreply+kokoro@google.com>
840 lines
24 KiB
C++
840 lines
24 KiB
C++
/*
|
|
* 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
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution;
|
|
* neither the name of the copyright holders nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef __BASE_INET_HH__
|
|
#define __BASE_INET_HH__
|
|
|
|
#include <iosfwd>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "base/compiler.hh"
|
|
#include "base/types.hh"
|
|
#include "dev/net/etherpkt.hh"
|
|
#include "dnet/os.h"
|
|
#include "dnet/eth.h"
|
|
#include "dnet/ip.h"
|
|
#include "dnet/ip6.h"
|
|
#include "dnet/addr.h"
|
|
#include "dnet/arp.h"
|
|
#include "dnet/icmp.h"
|
|
#include "dnet/tcp.h"
|
|
#include "dnet/udp.h"
|
|
#include "dnet/intf.h"
|
|
#include "dnet/route.h"
|
|
#include "dnet/fw.h"
|
|
#include "dnet/blob.h"
|
|
#include "dnet/rand.h"
|
|
|
|
namespace gem5
|
|
{
|
|
|
|
GEM5_DEPRECATED_NAMESPACE(Net, networking);
|
|
namespace networking
|
|
{
|
|
|
|
/*
|
|
* Ethernet Stuff
|
|
*/
|
|
struct EthAddr : protected eth_addr
|
|
{
|
|
protected:
|
|
void parse(const std::string &addr);
|
|
|
|
public:
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
EthAddr();
|
|
EthAddr(const uint8_t ea[ETH_ADDR_LEN]);
|
|
EthAddr(const eth_addr &ea);
|
|
EthAddr(const std::string &addr);
|
|
const EthAddr &operator=(const eth_addr &ea);
|
|
const EthAddr &operator=(const std::string &addr);
|
|
/** @} */ // end of api_inet
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
int size() const { return sizeof(eth_addr); }
|
|
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const uint8_t *bytes() const { return &data[0]; }
|
|
uint8_t *bytes() { return &data[0]; }
|
|
/** @} */ // end of api_inet
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const uint8_t *addr() const { return &data[0]; }
|
|
bool unicast() const { return !(data[0] & 0x01); }
|
|
bool multicast() const { return !unicast() && !broadcast(); }
|
|
bool broadcast() const
|
|
{
|
|
bool isBroadcast = true;
|
|
for (int i = 0; i < ETH_ADDR_LEN; ++i) {
|
|
isBroadcast = isBroadcast && data[i] == 0xff;
|
|
}
|
|
|
|
return isBroadcast;
|
|
}
|
|
/** @} */ // end of api_inet
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
std::string string() const;
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
operator uint64_t() const
|
|
{
|
|
uint64_t reg = 0;
|
|
reg |= ((uint64_t)data[0]) << 40;
|
|
reg |= ((uint64_t)data[1]) << 32;
|
|
reg |= ((uint64_t)data[2]) << 24;
|
|
reg |= ((uint64_t)data[3]) << 16;
|
|
reg |= ((uint64_t)data[4]) << 8;
|
|
reg |= ((uint64_t)data[5]) << 0;
|
|
return reg;
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
std::ostream &operator<<(std::ostream &stream, const EthAddr &ea);
|
|
bool operator==(const EthAddr &left, const EthAddr &right);
|
|
/** @} */ // end of api_inet
|
|
|
|
struct EthHdr : public eth_hdr
|
|
{
|
|
bool isVlan() const { return (ntohs(eth_type) == ETH_TYPE_8021Q); }
|
|
uint16_t type() const {
|
|
if (!isVlan())
|
|
return ntohs(eth_type);
|
|
else
|
|
// L3 type is now 16 bytes into the hdr with 802.1Q
|
|
// instead of 12. dnet/eth.h only supports 802.1
|
|
return ntohs(*((uint16_t*)(((uint8_t *)this) + 16)));
|
|
}
|
|
uint16_t vlanId() const {
|
|
if (isVlan())
|
|
return ntohs(*((uint16_t*)(((uint8_t *)this) + 14)));
|
|
else
|
|
return 0x0000;
|
|
}
|
|
|
|
const EthAddr &src() const { return *(EthAddr *)ð_src; }
|
|
const EthAddr &dst() const { return *(EthAddr *)ð_dst; }
|
|
|
|
int size() const {
|
|
if (!isVlan())
|
|
return sizeof(eth_hdr);
|
|
else
|
|
return (sizeof(eth_hdr)+4);
|
|
}
|
|
|
|
const uint8_t *bytes() const { return (const uint8_t *)this; }
|
|
const uint8_t *payload() const { return bytes() + size(); }
|
|
uint8_t *bytes() { return (uint8_t *)this; }
|
|
uint8_t *payload() { return bytes() + size(); }
|
|
};
|
|
|
|
class EthPtr
|
|
{
|
|
protected:
|
|
friend class IpPtr;
|
|
friend class Ip6Ptr;
|
|
EthPacketPtr p;
|
|
|
|
public:
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
EthPtr() {}
|
|
EthPtr(const EthPacketPtr &ptr) : p(ptr) { }
|
|
/** @} */ // end of api_inet
|
|
|
|
EthHdr *operator->() { return (EthHdr *)p->data; }
|
|
EthHdr &operator*() { return *(EthHdr *)p->data; }
|
|
operator EthHdr *() { return (EthHdr *)p->data; }
|
|
|
|
const EthHdr *operator->() const { return (const EthHdr *)p->data; }
|
|
const EthHdr &operator*() const { return *(const EthHdr *)p->data; }
|
|
operator const EthHdr *() const { return (const EthHdr *)p->data; }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
const EthPtr &operator=(const EthPacketPtr &ptr) { p = ptr; return *this; }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const EthPacketPtr packet() const { return p; }
|
|
EthPacketPtr packet() { return p; }
|
|
bool operator!() const { return !p; }
|
|
operator bool() const { return (p != nullptr); }
|
|
int off() const { return 0; }
|
|
int pstart() const { return off() + ((const EthHdr*)p->data)->size(); }
|
|
/** @} */ // end of api_inet
|
|
};
|
|
|
|
/*
|
|
* IP Stuff
|
|
*/
|
|
struct IpAddress
|
|
{
|
|
protected:
|
|
uint32_t _ip;
|
|
|
|
public:
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
IpAddress() : _ip(0)
|
|
{}
|
|
IpAddress(const uint32_t __ip) : _ip(__ip)
|
|
{}
|
|
/** @} */ // end of api_net
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
uint32_t ip() const { return _ip; }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
std::string string() const;
|
|
};
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
std::ostream &operator<<(std::ostream &stream, const IpAddress &ia);
|
|
bool operator==(const IpAddress &left, const IpAddress &right);
|
|
/** @} */ // end of api_inet
|
|
|
|
struct IpNetmask : public IpAddress
|
|
{
|
|
protected:
|
|
uint8_t _netmask;
|
|
|
|
public:
|
|
IpNetmask() : IpAddress(), _netmask(0)
|
|
{}
|
|
IpNetmask(const uint32_t __ip, const uint8_t __netmask) :
|
|
IpAddress(__ip), _netmask(__netmask)
|
|
{}
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
uint8_t netmask() const { return _netmask; }
|
|
|
|
std::string string() const;
|
|
};
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
std::ostream &operator<<(std::ostream &stream, const IpNetmask &in);
|
|
bool operator==(const IpNetmask &left, const IpNetmask &right);
|
|
/** @} */ // end of api_inet
|
|
|
|
struct IpWithPort : public IpAddress
|
|
{
|
|
protected:
|
|
uint16_t _port;
|
|
|
|
public:
|
|
IpWithPort() : IpAddress(), _port(0)
|
|
{}
|
|
IpWithPort(const uint32_t __ip, const uint16_t __port) :
|
|
IpAddress(__ip), _port(__port)
|
|
{}
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
uint8_t port() const { return _port; }
|
|
|
|
std::string string() const;
|
|
};
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
std::ostream &operator<<(std::ostream &stream, const IpWithPort &iwp);
|
|
bool operator==(const IpWithPort &left, const IpWithPort &right);
|
|
/** @} */ // end of api_inet
|
|
|
|
struct IpOpt;
|
|
struct IpHdr : public ip_hdr
|
|
{
|
|
uint8_t version() const { return ip_v; }
|
|
uint8_t hlen() const { return ip_hl * 4; }
|
|
uint8_t tos() const { return ip_tos; }
|
|
uint16_t len() const { return ntohs(ip_len); }
|
|
uint16_t id() const { return ntohs(ip_id); }
|
|
uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
|
|
uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
|
|
uint8_t ttl() const { return ip_ttl; }
|
|
uint8_t proto() const { return ip_p; }
|
|
uint16_t sum() const { return ip_sum; }
|
|
uint32_t src() const { return ntohl(ip_src); }
|
|
uint32_t dst() const { return ntohl(ip_dst); }
|
|
|
|
void sum(uint16_t sum) { ip_sum = sum; }
|
|
void id(uint16_t _id) { ip_id = htons(_id); }
|
|
void len(uint16_t _len) { ip_len = htons(_len); }
|
|
|
|
bool options(std::vector<const IpOpt *> &vec) const;
|
|
|
|
int size() const { return hlen(); }
|
|
const uint8_t *bytes() const { return (const uint8_t *)this; }
|
|
const uint8_t *payload() const { return bytes() + size(); }
|
|
uint8_t *bytes() { return (uint8_t *)this; }
|
|
uint8_t *payload() { return bytes() + size(); }
|
|
};
|
|
|
|
class IpPtr
|
|
{
|
|
protected:
|
|
friend class TcpPtr;
|
|
friend class UdpPtr;
|
|
EthPacketPtr p;
|
|
bool eth_hdr_vlan;
|
|
|
|
void set(const EthPacketPtr &ptr)
|
|
{
|
|
p = 0;
|
|
eth_hdr_vlan = false;
|
|
|
|
if (ptr) {
|
|
EthHdr *eth = (EthHdr *)ptr->data;
|
|
if (eth->type() == ETH_TYPE_IP)
|
|
p = ptr;
|
|
if (eth->isVlan())
|
|
eth_hdr_vlan = true;
|
|
}
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
IpPtr() : p(0), eth_hdr_vlan(false) {}
|
|
IpPtr(const EthPacketPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr); }
|
|
IpPtr(const EthPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr.p); }
|
|
IpPtr(const IpPtr &ptr) : p(ptr.p), eth_hdr_vlan(ptr.eth_hdr_vlan) { }
|
|
/** @} */ // end of api_inet
|
|
|
|
IpHdr *get() { return (IpHdr *)(p->data + sizeof(eth_hdr) +
|
|
((eth_hdr_vlan) ? 4 : 0)); }
|
|
IpHdr *operator->() { return get(); }
|
|
IpHdr &operator*() { return *get(); }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const IpHdr *get() const
|
|
{ return (const IpHdr *)(p->data + sizeof(eth_hdr) +
|
|
((eth_hdr_vlan) ? 4 : 0)); }
|
|
const IpHdr *operator->() const { return get(); }
|
|
const IpHdr &operator*() const { return *get(); }
|
|
/** @} */ // end of api_inet
|
|
|
|
const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; }
|
|
const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; }
|
|
const IpPtr &operator=(const IpPtr &ptr) { p = ptr.p; return *this; }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const EthPacketPtr packet() const { return p; }
|
|
EthPacketPtr packet() { return p; }
|
|
bool operator!() const { return !p; }
|
|
operator bool() const { return (p != nullptr); }
|
|
int off() const { return (sizeof(eth_hdr) + ((eth_hdr_vlan) ? 4 : 0)); }
|
|
int pstart() const { return (off() + get()->size()); }
|
|
/** @} */ // end of api_inet
|
|
};
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
uint16_t cksum(const IpPtr &ptr);
|
|
|
|
struct IpOpt : public ip_opt
|
|
{
|
|
uint8_t type() const { return opt_type; }
|
|
uint8_t typeNumber() const { return IP_OPT_NUMBER(opt_type); }
|
|
uint8_t typeClass() const { return IP_OPT_CLASS(opt_type); }
|
|
uint8_t typeCopied() const { return IP_OPT_COPIED(opt_type); }
|
|
uint8_t len() const { return IP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
|
|
|
|
bool isNumber(int num) const { return typeNumber() == IP_OPT_NUMBER(num); }
|
|
bool isClass(int cls) const { return typeClass() == IP_OPT_CLASS(cls); }
|
|
bool isCopied(int cpy) const { return typeCopied() == IP_OPT_COPIED(cpy); }
|
|
|
|
const uint8_t *data() const { return opt_data.data8; }
|
|
void sec(ip_opt_data_sec &sec) const;
|
|
void lsrr(ip_opt_data_rr &rr) const;
|
|
void ssrr(ip_opt_data_rr &rr) const;
|
|
void ts(ip_opt_data_ts &ts) const;
|
|
uint16_t satid() const { return ntohs(opt_data.satid); }
|
|
uint16_t mtup() const { return ntohs(opt_data.mtu); }
|
|
uint16_t mtur() const { return ntohs(opt_data.mtu); }
|
|
void tr(ip_opt_data_tr &tr) const;
|
|
uint16_t rtralt() const { return ntohs(opt_data.rtralt); }
|
|
void sdb(std::vector<uint32_t> &vec) const;
|
|
};
|
|
|
|
/*
|
|
* Ip6 Classes
|
|
*/
|
|
struct Ip6Opt;
|
|
struct Ip6Hdr : public ip6_hdr
|
|
{
|
|
uint8_t version() const { return ip6_vfc; }
|
|
uint32_t flow() const { return ntohl(ip6_flow); }
|
|
uint16_t plen() const { return ntohs(ip6_plen); }
|
|
uint16_t hlen() const { return IP6_HDR_LEN; }
|
|
uint8_t nxt() const { return ip6_nxt; }
|
|
uint8_t hlim() const { return ip6_hlim; }
|
|
|
|
const uint8_t* src() const { return ip6_src.data; }
|
|
const uint8_t* dst() const { return ip6_dst.data; }
|
|
|
|
int extensionLength() const;
|
|
const Ip6Opt* getExt(uint8_t ext) const;
|
|
const Ip6Opt* fragmentExt() const { return getExt(IP_PROTO_FRAGMENT); }
|
|
const Ip6Opt* rtTypeExt() const { return getExt(IP_PROTO_ROUTING); }
|
|
const Ip6Opt* dstOptExt() const { return getExt(IP_PROTO_DSTOPTS); }
|
|
uint8_t proto() const;
|
|
|
|
void plen(uint16_t _plen) { ip6_plen = htons(_plen); }
|
|
|
|
int size() const { return IP6_HDR_LEN + extensionLength(); }
|
|
const uint8_t *bytes() const { return (const uint8_t *)this; }
|
|
const uint8_t *payload() const { return bytes() + IP6_HDR_LEN
|
|
+ extensionLength(); }
|
|
uint8_t *bytes() { return (uint8_t *)this; }
|
|
uint8_t *payload() { return bytes() + IP6_HDR_LEN
|
|
+ extensionLength(); }
|
|
};
|
|
|
|
class Ip6Ptr
|
|
{
|
|
protected:
|
|
friend class TcpPtr;
|
|
friend class UdpPtr;
|
|
EthPacketPtr p;
|
|
bool eth_hdr_vlan;
|
|
|
|
void set(const EthPacketPtr &ptr)
|
|
{
|
|
p = 0;
|
|
eth_hdr_vlan = false;
|
|
|
|
if (ptr) {
|
|
EthHdr *eth = (EthHdr *)ptr->data;
|
|
if (eth->type() == ETH_TYPE_IPV6)
|
|
p = ptr;
|
|
if (eth->isVlan())
|
|
eth_hdr_vlan = true;
|
|
}
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
Ip6Ptr() : p(0), eth_hdr_vlan(false) {}
|
|
Ip6Ptr(const EthPacketPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr); }
|
|
Ip6Ptr(const EthPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr.p); }
|
|
Ip6Ptr(const Ip6Ptr &ptr) : p(ptr.p), eth_hdr_vlan(ptr.eth_hdr_vlan) { }
|
|
/** @} */ // end of api_inet
|
|
|
|
Ip6Hdr *get() { return (Ip6Hdr *)(p->data + sizeof(eth_hdr)
|
|
+ ((eth_hdr_vlan) ? 4 : 0)); }
|
|
Ip6Hdr *operator->() { return get(); }
|
|
Ip6Hdr &operator*() { return *get(); }
|
|
|
|
const Ip6Hdr *get() const
|
|
{ return (const Ip6Hdr *)(p->data + sizeof(eth_hdr)
|
|
+ ((eth_hdr_vlan) ? 4 : 0)); }
|
|
const Ip6Hdr *operator->() const { return get(); }
|
|
const Ip6Hdr &operator*() const { return *get(); }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const Ip6Ptr &operator=(const EthPacketPtr &ptr)
|
|
{ set(ptr); return *this; }
|
|
const Ip6Ptr &operator=(const EthPtr &ptr)
|
|
{ set(ptr.p); return *this; }
|
|
const Ip6Ptr &operator=(const Ip6Ptr &ptr)
|
|
{ p = ptr.p; return *this; }
|
|
/** @} */ // end of api_inet
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const EthPacketPtr packet() const { return p; }
|
|
EthPacketPtr packet() { return p; }
|
|
bool operator!() const { return !p; }
|
|
operator bool() const { return (p != nullptr); }
|
|
int off() const { return sizeof(eth_hdr) + ((eth_hdr_vlan) ? 4 : 0); }
|
|
int pstart() const { return off() + get()->size(); }
|
|
/** @} */ // end of api_inet
|
|
};
|
|
|
|
// Dnet supplied ipv6 opt header is incomplete and
|
|
// newer NIC card filters expect a more robust
|
|
// ipv6 header option declaration.
|
|
struct ip6_opt_fragment
|
|
{
|
|
uint16_t offlg;
|
|
uint32_t ident;
|
|
};
|
|
|
|
struct ip6_opt_routing_type2
|
|
{
|
|
uint8_t type;
|
|
uint8_t segleft;
|
|
uint32_t reserved;
|
|
ip6_addr_t addr;
|
|
};
|
|
|
|
struct GEM5_PACKED ip6_opt_dstopts
|
|
{
|
|
uint8_t type;
|
|
uint8_t length;
|
|
ip6_addr_t addr;
|
|
};
|
|
|
|
struct GEM5_PACKED ip6_opt_hdr
|
|
{
|
|
uint8_t ext_nxt;
|
|
uint8_t ext_len;
|
|
union
|
|
{
|
|
struct ip6_opt_fragment fragment;
|
|
struct ip6_opt_routing_type2 rtType2;
|
|
struct ip6_opt_dstopts dstOpts;
|
|
} ext_data;
|
|
};
|
|
|
|
struct Ip6Opt : public ip6_opt_hdr
|
|
{
|
|
uint8_t nxt() const { return ext_nxt; }
|
|
uint8_t extlen() const { return ext_len; }
|
|
uint8_t len() const { return extlen() + 8; }
|
|
|
|
// Supporting the types of header extensions likely to be encountered:
|
|
// fragment, routing type 2 and dstopts.
|
|
|
|
// Routing type 2
|
|
uint8_t rtType2Type() const { return ext_data.rtType2.type; }
|
|
uint8_t rtType2SegLft() const { return ext_data.rtType2.segleft; }
|
|
const uint8_t* rtType2Addr() const { return ext_data.rtType2.addr.data; }
|
|
|
|
// Fragment
|
|
uint16_t fragmentOfflg() const { return ntohs(ext_data.fragment.offlg); }
|
|
uint32_t fragmentIdent() const { return ntohl(ext_data.fragment.ident); }
|
|
|
|
// Dst Options/Home Address Option
|
|
uint8_t dstOptType() const { return ext_data.dstOpts.type; }
|
|
uint8_t dstOptLength() const { return ext_data.dstOpts.length; }
|
|
const uint8_t* dstOptAddr() const { return ext_data.dstOpts.addr.data; }
|
|
};
|
|
|
|
|
|
/*
|
|
* TCP Stuff
|
|
*/
|
|
struct TcpOpt;
|
|
struct TcpHdr : public tcp_hdr
|
|
{
|
|
uint16_t sport() const { return ntohs(th_sport); }
|
|
uint16_t dport() const { return ntohs(th_dport); }
|
|
uint32_t seq() const { return ntohl(th_seq); }
|
|
uint32_t ack() const { return ntohl(th_ack); }
|
|
uint8_t off() const { return th_off*4; }
|
|
uint8_t flags() const { return th_flags & 0x3f; }
|
|
uint16_t win() const { return ntohs(th_win); }
|
|
uint16_t sum() const { return th_sum; }
|
|
uint16_t urp() const { return ntohs(th_urp); }
|
|
|
|
void sum(uint16_t sum) { th_sum = sum; }
|
|
void seq(uint32_t _seq) { th_seq = htonl(_seq); }
|
|
void flags(uint8_t _flags) { th_flags = _flags; }
|
|
|
|
bool options(std::vector<const TcpOpt *> &vec) const;
|
|
|
|
int size() const { return off(); }
|
|
const uint8_t *bytes() const { return (const uint8_t *)this; }
|
|
const uint8_t *payload() const { return bytes() + size(); }
|
|
uint8_t *bytes() { return (uint8_t *)this; }
|
|
uint8_t *payload() { return bytes() + size(); }
|
|
};
|
|
|
|
class TcpPtr
|
|
{
|
|
protected:
|
|
EthPacketPtr p;
|
|
int _off;
|
|
|
|
void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
|
|
void set(const IpPtr &ptr)
|
|
{
|
|
if (ptr && ptr->proto() == IP_PROTO_TCP)
|
|
set(ptr.p, ptr.pstart());
|
|
else
|
|
set(0, 0);
|
|
}
|
|
void set(const Ip6Ptr &ptr)
|
|
{
|
|
if (ptr && ptr->proto() == IP_PROTO_TCP)
|
|
set(ptr.p, ptr.pstart());
|
|
else
|
|
set(0, 0);
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
TcpPtr() : p(0), _off(0) {}
|
|
TcpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
|
|
TcpPtr(const Ip6Ptr &ptr) : p(0), _off(0) { set(ptr); }
|
|
TcpPtr(const TcpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
|
|
/** @} */ // end of api_inet
|
|
|
|
TcpHdr *get() { return (TcpHdr *)(p->data + _off); }
|
|
TcpHdr *operator->() { return get(); }
|
|
TcpHdr &operator*() { return *get(); }
|
|
|
|
const TcpHdr *get() const { return (const TcpHdr *)(p->data + _off); }
|
|
const TcpHdr *operator->() const { return get(); }
|
|
const TcpHdr &operator*() const { return *get(); }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const TcpPtr &operator=(const IpPtr &i)
|
|
{ set(i); return *this; }
|
|
const TcpPtr &operator=(const TcpPtr &t)
|
|
{ set(t.p, t._off); return *this; }
|
|
/** @} */ // end of api_inet
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const EthPacketPtr packet() const { return p; }
|
|
EthPacketPtr packet() { return p; }
|
|
bool operator!() const { return !p; }
|
|
operator bool() const { return (p != nullptr); }
|
|
int off() const { return _off; }
|
|
int pstart() const { return off() + get()->size(); }
|
|
/** @} */ // end of api_inet
|
|
};
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
uint16_t cksum(const TcpPtr &ptr);
|
|
|
|
struct TcpOpt : public tcp_opt
|
|
{
|
|
uint8_t type() const { return opt_type; }
|
|
uint8_t len() const { return TCP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
|
|
|
|
bool isopt(int opt) const { return type() == opt; }
|
|
|
|
const uint8_t *data() const { return opt_data.data8; }
|
|
|
|
uint16_t mss() const { return ntohs(opt_data.mss); }
|
|
uint8_t wscale() const { return opt_data.wscale; }
|
|
uint32_t echo() const { return ntohl(opt_data.echo); }
|
|
uint32_t tsval() const { return ntohl(opt_data.timestamp[0]); }
|
|
uint32_t tsecr() const { return ntohl(opt_data.timestamp[1]); }
|
|
uint32_t cc() const { return ntohl(opt_data.cc); }
|
|
uint8_t cksum() const{ return opt_data.cksum; }
|
|
const uint8_t *md5() const { return opt_data.md5; }
|
|
|
|
int size() const { return len(); }
|
|
const uint8_t *bytes() const { return (const uint8_t *)this; }
|
|
const uint8_t *payload() const { return bytes() + size(); }
|
|
uint8_t *bytes() { return (uint8_t *)this; }
|
|
uint8_t *payload() { return bytes() + size(); }
|
|
};
|
|
|
|
/*
|
|
* UDP Stuff
|
|
*/
|
|
struct UdpHdr : public udp_hdr
|
|
{
|
|
uint16_t sport() const { return ntohs(uh_sport); }
|
|
uint16_t dport() const { return ntohs(uh_dport); }
|
|
uint16_t len() const { return ntohs(uh_ulen); }
|
|
uint16_t sum() const { return uh_sum; }
|
|
|
|
void sum(uint16_t sum) { uh_sum = sum; }
|
|
void len(uint16_t _len) { uh_ulen = htons(_len); }
|
|
|
|
int size() const { return sizeof(udp_hdr); }
|
|
const uint8_t *bytes() const { return (const uint8_t *)this; }
|
|
const uint8_t *payload() const { return bytes() + size(); }
|
|
uint8_t *bytes() { return (uint8_t *)this; }
|
|
uint8_t *payload() { return bytes() + size(); }
|
|
};
|
|
|
|
class UdpPtr
|
|
{
|
|
protected:
|
|
EthPacketPtr p;
|
|
int _off;
|
|
|
|
void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
|
|
void set(const IpPtr &ptr)
|
|
{
|
|
if (ptr && ptr->proto() == IP_PROTO_UDP)
|
|
set(ptr.p, ptr.pstart());
|
|
else
|
|
set(0, 0);
|
|
}
|
|
void set(const Ip6Ptr &ptr)
|
|
{
|
|
if (ptr && ptr->proto() == IP_PROTO_UDP)
|
|
set(ptr.p, ptr.pstart());
|
|
else
|
|
set(0, 0);
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
UdpPtr() : p(0), _off(0) {}
|
|
UdpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
|
|
UdpPtr(const Ip6Ptr &ptr) : p(0), _off(0) { set(ptr); }
|
|
UdpPtr(const UdpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
|
|
/** @} */ // end of api_inet
|
|
|
|
UdpHdr *get() { return (UdpHdr *)(p->data + _off); }
|
|
UdpHdr *operator->() { return get(); }
|
|
UdpHdr &operator*() { return *get(); }
|
|
|
|
const UdpHdr *get() const { return (const UdpHdr *)(p->data + _off); }
|
|
const UdpHdr *operator->() const { return get(); }
|
|
const UdpHdr &operator*() const { return *get(); }
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; }
|
|
const UdpPtr &operator=(const UdpPtr &t)
|
|
{ set(t.p, t._off); return *this; }
|
|
/** @} */ // end of api_inet
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
const EthPacketPtr packet() const { return p; }
|
|
EthPacketPtr packet() { return p; }
|
|
bool operator!() const { return !p; }
|
|
operator bool() const { return (p != nullptr); }
|
|
int off() const { return _off; }
|
|
int pstart() const { return off() + get()->size(); }
|
|
/** @} */ // end of api_inet
|
|
};
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
* @{
|
|
*/
|
|
uint16_t __tu_cksum6(const Ip6Ptr &ip6);
|
|
uint16_t __tu_cksum(const IpPtr &ip);
|
|
uint16_t cksum(const UdpPtr &ptr);
|
|
/** @} */ // end of api_inet
|
|
|
|
/**
|
|
* @ingroup api_inet
|
|
*/
|
|
int hsplit(const EthPacketPtr &ptr);
|
|
|
|
} // namespace networking
|
|
} // namespace gem5
|
|
|
|
#endif // __BASE_INET_HH__
|