X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fbase%2Finet.hh;h=5130a072ca9b0ff2192a9549b7d2a4449ad1d594;hb=d45ab59c29b918753b64f65448cd04b1cc3c6aba;hp=e5d0473f9b135babf7b91fd08c716a1dcefc60a3;hpb=ba2eae5d528487900d1510fc0a160e660f2c394c;p=gem5.git diff --git a/src/base/inet.hh b/src/base/inet.hh index e5d0473f9..5130a072c 100644 --- a/src/base/inet.hh +++ b/src/base/inet.hh @@ -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 @@ -24,6 +37,11 @@ * 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. + * + * Authors: Nathan Binkert + * Steve Reinhardt + * Gabe Black + * Geoffrey Blake */ #ifndef __BASE_INET_HH__ @@ -34,10 +52,8 @@ #include #include -#include "base/range.hh" +#include "base/types.hh" #include "dev/etherpkt.hh" -#include "sim/host.hh" - #include "dnet/os.h" #include "dnet/eth.h" #include "dnet/ip.h" @@ -77,9 +93,18 @@ struct EthAddr : protected eth_addr uint8_t *bytes() { return &data[0]; } const uint8_t *addr() const { return &data[0]; } - bool unicast() const { return data[0] == 0x00; } - bool multicast() const { return data[0] == 0x01; } - bool broadcast() const { return data[0] == 0xff; } + 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; + } + std::string string() const; operator uint64_t() const @@ -101,11 +126,31 @@ bool operator==(const EthAddr &left, const EthAddr &right); struct EthHdr : public eth_hdr { - uint16_t type() const { return ntohs(eth_type); } + 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 { return sizeof(eth_hdr); } + 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(); } @@ -117,6 +162,7 @@ class EthPtr { protected: friend class IpPtr; + friend class Ip6Ptr; EthPacketPtr p; public: @@ -137,11 +183,72 @@ class EthPtr EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } + int off() const { return 0; } + int pstart() const { return off() + ((const EthHdr*)p->data)->size(); } }; /* * IP Stuff */ +struct IpAddress +{ + protected: + uint32_t _ip; + + public: + IpAddress() : _ip(0) + {} + IpAddress(const uint32_t __ip) : _ip(__ip) + {} + + uint32_t ip() const { return _ip; } + + std::string string() const; +}; + +std::ostream &operator<<(std::ostream &stream, const IpAddress &ia); +bool operator==(const IpAddress &left, const IpAddress &right); + +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) + {} + + uint8_t netmask() const { return _netmask; } + + std::string string() const; +}; + +std::ostream &operator<<(std::ostream &stream, const IpNetmask &in); +bool operator==(const IpNetmask &left, const IpNetmask &right); + +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) + {} + + uint8_t port() const { return _port; } + + std::string string() const; +}; + +std::ostream &operator<<(std::ostream &stream, const IpWithPort &iwp); +bool operator==(const IpWithPort &left, const IpWithPort &right); + struct IpOpt; struct IpHdr : public ip_hdr { @@ -159,6 +266,8 @@ struct IpHdr : public ip_hdr 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 &vec) const; @@ -175,33 +284,38 @@ class IpPtr friend class TcpPtr; friend class UdpPtr; EthPacketPtr p; - - const IpHdr *h() const - { return (const IpHdr *)(p->data + sizeof(eth_hdr)); } - IpHdr *h() { return (IpHdr *)(p->data + sizeof(eth_hdr)); } + bool eth_hdr_vlan; void set(const EthPacketPtr &ptr) { - EthHdr *eth = (EthHdr *)ptr->data; - if (eth->type() == ETH_TYPE_IP) - p = ptr; - else - p = 0; + 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: - IpPtr() {} - IpPtr(const EthPacketPtr &ptr) { set(ptr); } - IpPtr(const EthPtr &ptr) { set(ptr.p); } - IpPtr(const IpPtr &ptr) : p(ptr.p) { } - - IpHdr *operator->() { return h(); } - IpHdr &operator*() { return *h(); } - operator IpHdr *() { return h(); } - - const IpHdr *operator->() const { return h(); } - const IpHdr &operator*() const { return *h(); } - operator const IpHdr *() const { return h(); } + 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) { } + + IpHdr *get() { return (IpHdr *)(p->data + sizeof(eth_hdr) + + ((eth_hdr_vlan) ? 4 : 0)); } + IpHdr *operator->() { return get(); } + IpHdr &operator*() { return *get(); } + + 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(); } const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; } const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; } @@ -211,7 +325,8 @@ class IpPtr EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } - operator bool() { return p; } + int off() const { return (sizeof(eth_hdr) + ((eth_hdr_vlan) ? 4 : 0)); } + int pstart() const { return (off() + get()->size()); } }; uint16_t cksum(const IpPtr &ptr); @@ -242,6 +357,152 @@ struct IpOpt : public ip_opt void sdb(std::vector &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: + 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) { } + + 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(); } + + 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; } + + const EthPacketPtr packet() const { return p; } + EthPacketPtr packet() { return p; } + bool operator!() const { return !p; } + operator bool() const { return p; } + int off() const { return sizeof(eth_hdr) + ((eth_hdr_vlan) ? 4 : 0); } + int pstart() const { return off() + get()->size(); } +}; + +// 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; +}; + +#define HOME_ADDRESS_OPTION 0xC9 +struct ip6_opt_dstopts { + uint8_t type; + uint8_t length; + ip6_addr_t addr; +} __attribute__((packed)); + +struct 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; +} __attribute__((packed)); + +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 */ @@ -252,13 +513,15 @@ struct TcpHdr : public tcp_hdr 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; } + 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 &vec) const; @@ -273,47 +536,53 @@ class TcpPtr { protected: EthPacketPtr p; - int off; + int _off; - const TcpHdr *h() const { return (const TcpHdr *)(p->data + off); } - TcpHdr *h() { return (TcpHdr *)(p->data + off); } - - void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } + void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; } void set(const IpPtr &ptr) { - if (ptr->proto() == IP_PROTO_TCP) - set(ptr.p, sizeof(eth_hdr) + ptr->hlen()); + 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: - TcpPtr() {} - TcpPtr(const IpPtr &ptr) { set(ptr); } - TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {} + 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) {} - TcpHdr *operator->() { return h(); } - TcpHdr &operator*() { return *h(); } - operator TcpHdr *() { return h(); } + TcpHdr *get() { return (TcpHdr *)(p->data + _off); } + TcpHdr *operator->() { return get(); } + TcpHdr &operator*() { return *get(); } - const TcpHdr *operator->() const { return h(); } - const TcpHdr &operator*() const { return *h(); } - operator const TcpHdr *() const { return h(); } + const TcpHdr *get() const { return (const TcpHdr *)(p->data + _off); } + const TcpHdr *operator->() const { return get(); } + const TcpHdr &operator*() const { return *get(); } - const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; } - const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; } + const TcpPtr &operator=(const IpPtr &i) + { set(i); return *this; } + const TcpPtr &operator=(const TcpPtr &t) + { set(t.p, t._off); return *this; } const EthPacketPtr packet() const { return p; } EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } - operator bool() { return p; } + int off() const { return _off; } + int pstart() const { return off() + get()->size(); } }; uint16_t cksum(const TcpPtr &ptr); -typedef Range SackRange; - struct TcpOpt : public tcp_opt { uint8_t type() const { return opt_type; } @@ -325,7 +594,6 @@ struct TcpOpt : public tcp_opt uint16_t mss() const { return ntohs(opt_data.mss); } uint8_t wscale() const { return opt_data.wscale; } - bool sack(std::vector &vec) const; 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]); } @@ -351,6 +619,7 @@ struct UdpHdr : public udp_hdr 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; } @@ -363,45 +632,56 @@ class UdpPtr { protected: EthPacketPtr p; - int off; + int _off; - const UdpHdr *h() const { return (const UdpHdr *)(p->data + off); } - UdpHdr *h() { return (UdpHdr *)(p->data + off); } - - void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } + void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; } void set(const IpPtr &ptr) { - if (ptr->proto() == IP_PROTO_UDP) - set(ptr.p, sizeof(eth_hdr) + ptr->hlen()); + 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: - UdpPtr() {} - UdpPtr(const IpPtr &ptr) { set(ptr); } - UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {} + 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) {} - UdpHdr *operator->() { return h(); } - UdpHdr &operator*() { return *h(); } - operator UdpHdr *() { return h(); } + UdpHdr *get() { return (UdpHdr *)(p->data + _off); } + UdpHdr *operator->() { return get(); } + UdpHdr &operator*() { return *get(); } - const UdpHdr *operator->() const { return h(); } - const UdpHdr &operator*() const { return *h(); } - operator const UdpHdr *() const { return h(); } + const UdpHdr *get() const { return (const UdpHdr *)(p->data + _off); } + const UdpHdr *operator->() const { return get(); } + const UdpHdr &operator*() const { return *get(); } const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; } - const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; } + const UdpPtr &operator=(const UdpPtr &t) + { set(t.p, t._off); return *this; } const EthPacketPtr packet() const { return p; } EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } - operator bool() { return p; } + int off() const { return _off; } + int pstart() const { return off() + get()->size(); } }; +uint16_t __tu_cksum6(const Ip6Ptr &ip6); +uint16_t __tu_cksum(const IpPtr &ip); uint16_t cksum(const UdpPtr &ptr); -/* namespace Net */ } +int hsplit(const EthPacketPtr &ptr); + +} // namespace Net #endif // __BASE_INET_HH__