12SN/A/*
29955SGeoffrey.Blake@arm.com * Copyright (c) 2013 ARM Limited
39955SGeoffrey.Blake@arm.com * All rights reserved
49955SGeoffrey.Blake@arm.com *
59955SGeoffrey.Blake@arm.com * The license below extends only to copyright in the software and shall
69955SGeoffrey.Blake@arm.com * not be construed as granting a license to any other intellectual
79955SGeoffrey.Blake@arm.com * property including but not limited to intellectual property relating
89955SGeoffrey.Blake@arm.com * to a hardware implementation of the functionality of the software
99955SGeoffrey.Blake@arm.com * licensed hereunder.  You may use the software subject to the license
109955SGeoffrey.Blake@arm.com * terms below provided that you ensure that this notice is replicated
119955SGeoffrey.Blake@arm.com * unmodified and in its entirety in all distributions of the software,
129955SGeoffrey.Blake@arm.com * modified or unmodified, in source code or in binary form.
139955SGeoffrey.Blake@arm.com *
141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
157778Sgblack@eecs.umich.edu * Copyright (c) 2010 Advanced Micro Devices, Inc.
162SN/A * All rights reserved.
172SN/A *
182SN/A * Redistribution and use in source and binary forms, with or without
192SN/A * modification, are permitted provided that the following conditions are
202SN/A * met: redistributions of source code must retain the above copyright
212SN/A * notice, this list of conditions and the following disclaimer;
222SN/A * redistributions in binary form must reproduce the above copyright
232SN/A * notice, this list of conditions and the following disclaimer in the
242SN/A * documentation and/or other materials provided with the distribution;
252SN/A * neither the name of the copyright holders nor the names of its
262SN/A * contributors may be used to endorse or promote products derived from
272SN/A * this software without specific prior written permission.
282SN/A *
292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402665Ssaidi@eecs.umich.edu *
412665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
422665Ssaidi@eecs.umich.edu *          Steve Reinhardt
437778Sgblack@eecs.umich.edu *          Gabe Black
449955SGeoffrey.Blake@arm.com *          Geoffrey Blake
452SN/A */
462SN/A
471078SN/A#ifndef __BASE_INET_HH__
481078SN/A#define __BASE_INET_HH__
491078SN/A
501114SN/A#include <iosfwd>
511078SN/A#include <string>
521114SN/A#include <utility>
531114SN/A#include <vector>
541114SN/A
556216Snate@binkert.org#include "base/types.hh"
5611263Sandreas.sandberg@arm.com#include "dev/net/etherpkt.hh"
571078SN/A#include "dnet/os.h"
581078SN/A#include "dnet/eth.h"
591078SN/A#include "dnet/ip.h"
601078SN/A#include "dnet/ip6.h"
611078SN/A#include "dnet/addr.h"
621078SN/A#include "dnet/arp.h"
631078SN/A#include "dnet/icmp.h"
641078SN/A#include "dnet/tcp.h"
651078SN/A#include "dnet/udp.h"
661078SN/A#include "dnet/intf.h"
671078SN/A#include "dnet/route.h"
681078SN/A#include "dnet/fw.h"
691078SN/A#include "dnet/blob.h"
701078SN/A#include "dnet/rand.h"
712SN/A
721114SN/Anamespace Net {
732SN/A
741114SN/A/*
751114SN/A * Ethernet Stuff
761114SN/A */
771114SN/Astruct EthAddr : protected eth_addr
781114SN/A{
791114SN/A  protected:
801114SN/A    void parse(const std::string &addr);
811078SN/A
821114SN/A  public:
831114SN/A    EthAddr();
841114SN/A    EthAddr(const uint8_t ea[ETH_ADDR_LEN]);
851114SN/A    EthAddr(const eth_addr &ea);
861114SN/A    EthAddr(const std::string &addr);
871114SN/A    const EthAddr &operator=(const eth_addr &ea);
881114SN/A    const EthAddr &operator=(const std::string &addr);
891079SN/A
901114SN/A    int size() const { return sizeof(eth_addr); }
911114SN/A
921114SN/A    const uint8_t *bytes() const { return &data[0]; }
931114SN/A    uint8_t *bytes() { return &data[0]; }
941114SN/A
951114SN/A    const uint8_t *addr() const { return &data[0]; }
9610251Satgutier@umich.edu    bool unicast() const { return !(data[0] & 0x01); }
9710251Satgutier@umich.edu    bool multicast() const { return !unicast() && !broadcast(); }
9810251Satgutier@umich.edu    bool broadcast() const
9910251Satgutier@umich.edu    {
10010251Satgutier@umich.edu        bool isBroadcast = true;
10110251Satgutier@umich.edu        for (int i = 0; i < ETH_ADDR_LEN; ++i) {
10210251Satgutier@umich.edu            isBroadcast = isBroadcast && data[i] == 0xff;
10310251Satgutier@umich.edu        }
10410251Satgutier@umich.edu
10510251Satgutier@umich.edu        return isBroadcast;
10610251Satgutier@umich.edu    }
10710251Satgutier@umich.edu
1081114SN/A    std::string string() const;
1091137SN/A
1101137SN/A    operator uint64_t() const
1111137SN/A    {
1121137SN/A        uint64_t reg = 0;
1131137SN/A        reg |= ((uint64_t)data[0]) << 40;
1141137SN/A        reg |= ((uint64_t)data[1]) << 32;
1151137SN/A        reg |= ((uint64_t)data[2]) << 24;
1161137SN/A        reg |= ((uint64_t)data[3]) << 16;
1171137SN/A        reg |= ((uint64_t)data[4]) << 8;
1181137SN/A        reg |= ((uint64_t)data[5]) << 0;
1191137SN/A        return reg;
1201137SN/A    }
1211137SN/A
1221114SN/A};
1231114SN/A
1241114SN/Astd::ostream &operator<<(std::ostream &stream, const EthAddr &ea);
1251114SN/Abool operator==(const EthAddr &left, const EthAddr &right);
1261114SN/A
1271114SN/Astruct EthHdr : public eth_hdr
1281078SN/A{
1299955SGeoffrey.Blake@arm.com    bool isVlan() const { return (ntohs(eth_type) == ETH_TYPE_8021Q); }
1309955SGeoffrey.Blake@arm.com    uint16_t type() const {
1319955SGeoffrey.Blake@arm.com        if (!isVlan())
1329955SGeoffrey.Blake@arm.com            return ntohs(eth_type);
1339955SGeoffrey.Blake@arm.com        else
1349955SGeoffrey.Blake@arm.com            // L3 type is now 16 bytes into the hdr with 802.1Q
1359955SGeoffrey.Blake@arm.com            // instead of 12.  dnet/eth.h only supports 802.1
1369955SGeoffrey.Blake@arm.com            return ntohs(*((uint16_t*)(((uint8_t *)this) + 16)));
1379955SGeoffrey.Blake@arm.com    }
1389955SGeoffrey.Blake@arm.com    uint16_t vlanId() const {
1399955SGeoffrey.Blake@arm.com        if (isVlan())
1409955SGeoffrey.Blake@arm.com            return ntohs(*((uint16_t*)(((uint8_t *)this) + 14)));
1419955SGeoffrey.Blake@arm.com        else
1429955SGeoffrey.Blake@arm.com            return 0x0000;
1439955SGeoffrey.Blake@arm.com    }
1449955SGeoffrey.Blake@arm.com
1451114SN/A    const EthAddr &src() const { return *(EthAddr *)&eth_src; }
1461114SN/A    const EthAddr &dst() const { return *(EthAddr *)&eth_dst; }
1471079SN/A
1489955SGeoffrey.Blake@arm.com    int size() const {
1499955SGeoffrey.Blake@arm.com        if (!isVlan())
1509955SGeoffrey.Blake@arm.com            return sizeof(eth_hdr);
1519955SGeoffrey.Blake@arm.com        else
1529955SGeoffrey.Blake@arm.com            return (sizeof(eth_hdr)+4);
1539955SGeoffrey.Blake@arm.com    }
1541079SN/A
1551079SN/A    const uint8_t *bytes() const { return (const uint8_t *)this; }
1561079SN/A    const uint8_t *payload() const { return bytes() + size(); }
1571079SN/A    uint8_t *bytes() { return (uint8_t *)this; }
1581079SN/A    uint8_t *payload() { return bytes() + size(); }
1591078SN/A};
1601078SN/A
1611114SN/Aclass EthPtr
1621114SN/A{
1631114SN/A  protected:
1641114SN/A    friend class IpPtr;
1659955SGeoffrey.Blake@arm.com    friend class Ip6Ptr;
1662566SN/A    EthPacketPtr p;
1671114SN/A
1681114SN/A  public:
1691114SN/A    EthPtr() {}
1702566SN/A    EthPtr(const EthPacketPtr &ptr) : p(ptr) { }
1711114SN/A
1721114SN/A    EthHdr *operator->() { return (EthHdr *)p->data; }
1731114SN/A    EthHdr &operator*() { return *(EthHdr *)p->data; }
1741114SN/A    operator EthHdr *() { return (EthHdr *)p->data; }
1751114SN/A
1761114SN/A    const EthHdr *operator->() const { return (const EthHdr *)p->data; }
1771114SN/A    const EthHdr &operator*() const { return *(const EthHdr *)p->data; }
1781114SN/A    operator const EthHdr *() const { return (const EthHdr *)p->data; }
1791114SN/A
1802566SN/A    const EthPtr &operator=(const EthPacketPtr &ptr) { p = ptr; return *this; }
1811114SN/A
1822566SN/A    const EthPacketPtr packet() const { return p; }
1832566SN/A    EthPacketPtr packet() { return p; }
1841114SN/A    bool operator!() const { return !p; }
18510469Sandreas.hansson@arm.com    operator bool() const { return (p != nullptr); }
1865782Ssaidi@eecs.umich.edu    int off() const { return 0; }
1875782Ssaidi@eecs.umich.edu    int pstart() const { return off() + ((const EthHdr*)p->data)->size(); }
1881114SN/A};
1891114SN/A
1901114SN/A/*
1911114SN/A * IP Stuff
1921114SN/A */
1937777Sgblack@eecs.umich.edustruct IpAddress
1947777Sgblack@eecs.umich.edu{
1957777Sgblack@eecs.umich.edu  protected:
1967777Sgblack@eecs.umich.edu    uint32_t _ip;
1977777Sgblack@eecs.umich.edu
1987777Sgblack@eecs.umich.edu  public:
1997777Sgblack@eecs.umich.edu    IpAddress() : _ip(0)
2007777Sgblack@eecs.umich.edu    {}
2017777Sgblack@eecs.umich.edu    IpAddress(const uint32_t __ip) : _ip(__ip)
2027777Sgblack@eecs.umich.edu    {}
2037777Sgblack@eecs.umich.edu
2047777Sgblack@eecs.umich.edu    uint32_t ip() const { return _ip; }
2057777Sgblack@eecs.umich.edu
2067777Sgblack@eecs.umich.edu    std::string string() const;
2077777Sgblack@eecs.umich.edu};
2087777Sgblack@eecs.umich.edu
2097777Sgblack@eecs.umich.edustd::ostream &operator<<(std::ostream &stream, const IpAddress &ia);
2107777Sgblack@eecs.umich.edubool operator==(const IpAddress &left, const IpAddress &right);
2117777Sgblack@eecs.umich.edu
2127777Sgblack@eecs.umich.edustruct IpNetmask : public IpAddress
2137777Sgblack@eecs.umich.edu{
2147777Sgblack@eecs.umich.edu  protected:
2157777Sgblack@eecs.umich.edu    uint8_t _netmask;
2167777Sgblack@eecs.umich.edu
2177777Sgblack@eecs.umich.edu  public:
2187777Sgblack@eecs.umich.edu    IpNetmask() : IpAddress(), _netmask(0)
2197777Sgblack@eecs.umich.edu    {}
2207777Sgblack@eecs.umich.edu    IpNetmask(const uint32_t __ip, const uint8_t __netmask) :
2217777Sgblack@eecs.umich.edu        IpAddress(__ip), _netmask(__netmask)
2227777Sgblack@eecs.umich.edu    {}
2237777Sgblack@eecs.umich.edu
2247777Sgblack@eecs.umich.edu    uint8_t netmask() const { return _netmask; }
2257777Sgblack@eecs.umich.edu
2267777Sgblack@eecs.umich.edu    std::string string() const;
2277777Sgblack@eecs.umich.edu};
2287777Sgblack@eecs.umich.edu
2297777Sgblack@eecs.umich.edustd::ostream &operator<<(std::ostream &stream, const IpNetmask &in);
2307777Sgblack@eecs.umich.edubool operator==(const IpNetmask &left, const IpNetmask &right);
2317777Sgblack@eecs.umich.edu
2327777Sgblack@eecs.umich.edustruct IpWithPort : public IpAddress
2337777Sgblack@eecs.umich.edu{
2347777Sgblack@eecs.umich.edu  protected:
2357777Sgblack@eecs.umich.edu    uint16_t _port;
2367777Sgblack@eecs.umich.edu
2377777Sgblack@eecs.umich.edu  public:
2387777Sgblack@eecs.umich.edu    IpWithPort() : IpAddress(), _port(0)
2397777Sgblack@eecs.umich.edu    {}
2407777Sgblack@eecs.umich.edu    IpWithPort(const uint32_t __ip, const uint16_t __port) :
2417777Sgblack@eecs.umich.edu        IpAddress(__ip), _port(__port)
2427777Sgblack@eecs.umich.edu    {}
2437777Sgblack@eecs.umich.edu
2447777Sgblack@eecs.umich.edu    uint8_t port() const { return _port; }
2457777Sgblack@eecs.umich.edu
2467777Sgblack@eecs.umich.edu    std::string string() const;
2477777Sgblack@eecs.umich.edu};
2487777Sgblack@eecs.umich.edu
2497777Sgblack@eecs.umich.edustd::ostream &operator<<(std::ostream &stream, const IpWithPort &iwp);
2507777Sgblack@eecs.umich.edubool operator==(const IpWithPort &left, const IpWithPort &right);
2517777Sgblack@eecs.umich.edu
2521114SN/Astruct IpOpt;
2531114SN/Astruct IpHdr : public ip_hdr
2541078SN/A{
2551078SN/A    uint8_t  version() const { return ip_v; }
2561092SN/A    uint8_t  hlen() const { return ip_hl * 4; }
2571078SN/A    uint8_t  tos() const { return ip_tos; }
2581078SN/A    uint16_t len() const { return ntohs(ip_len); }
2591078SN/A    uint16_t id() const { return ntohs(ip_id); }
2601078SN/A    uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
2611078SN/A    uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
2621078SN/A    uint8_t  ttl() const { return ip_ttl; }
2631078SN/A    uint8_t  proto() const { return ip_p; }
2641092SN/A    uint16_t sum() const { return ip_sum; }
2651078SN/A    uint32_t src() const { return ntohl(ip_src); }
2661078SN/A    uint32_t dst() const { return ntohl(ip_dst); }
2671078SN/A
2681092SN/A    void sum(uint16_t sum) { ip_sum = sum; }
2695761Ssaidi@eecs.umich.edu    void id(uint16_t _id) { ip_id = htons(_id); }
2705761Ssaidi@eecs.umich.edu    void len(uint16_t _len) { ip_len = htons(_len); }
2715761Ssaidi@eecs.umich.edu
2721114SN/A    bool options(std::vector<const IpOpt *> &vec) const;
2731079SN/A
2741079SN/A    int size() const { return hlen(); }
2751079SN/A    const uint8_t *bytes() const { return (const uint8_t *)this; }
2761079SN/A    const uint8_t *payload() const { return bytes() + size(); }
2771079SN/A    uint8_t *bytes() { return (uint8_t *)this; }
2781079SN/A    uint8_t *payload() { return bytes() + size(); }
2791078SN/A};
2801078SN/A
2811114SN/Aclass IpPtr
2821114SN/A{
2831114SN/A  protected:
2841114SN/A    friend class TcpPtr;
2851114SN/A    friend class UdpPtr;
2862566SN/A    EthPacketPtr p;
2879955SGeoffrey.Blake@arm.com    bool eth_hdr_vlan;
2881114SN/A
2892566SN/A    void set(const EthPacketPtr &ptr)
2901114SN/A    {
2915484Snate@binkert.org        p = 0;
2929955SGeoffrey.Blake@arm.com        eth_hdr_vlan = false;
2935484Snate@binkert.org
2945484Snate@binkert.org        if (ptr) {
2955484Snate@binkert.org            EthHdr *eth = (EthHdr *)ptr->data;
2965484Snate@binkert.org            if (eth->type() == ETH_TYPE_IP)
2975484Snate@binkert.org                p = ptr;
2989955SGeoffrey.Blake@arm.com            if (eth->isVlan())
2999955SGeoffrey.Blake@arm.com                eth_hdr_vlan = true;
3005484Snate@binkert.org        }
3011114SN/A    }
3021114SN/A
3031114SN/A  public:
3049955SGeoffrey.Blake@arm.com    IpPtr() : p(0), eth_hdr_vlan(false) {}
3059955SGeoffrey.Blake@arm.com    IpPtr(const EthPacketPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr); }
3069955SGeoffrey.Blake@arm.com    IpPtr(const EthPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr.p); }
3079955SGeoffrey.Blake@arm.com    IpPtr(const IpPtr &ptr) : p(ptr.p), eth_hdr_vlan(ptr.eth_hdr_vlan) { }
3081114SN/A
3099955SGeoffrey.Blake@arm.com    IpHdr *get() { return (IpHdr *)(p->data + sizeof(eth_hdr) +
3109955SGeoffrey.Blake@arm.com                                   ((eth_hdr_vlan) ? 4 : 0)); }
3115484Snate@binkert.org    IpHdr *operator->() { return get(); }
3125484Snate@binkert.org    IpHdr &operator*() { return *get(); }
3131114SN/A
3145484Snate@binkert.org    const IpHdr *get() const
3159955SGeoffrey.Blake@arm.com    { return (const IpHdr *)(p->data + sizeof(eth_hdr) +
3169955SGeoffrey.Blake@arm.com                            ((eth_hdr_vlan) ? 4 : 0)); }
3175484Snate@binkert.org    const IpHdr *operator->() const { return get(); }
3185484Snate@binkert.org    const IpHdr &operator*() const { return *get(); }
3191114SN/A
3202566SN/A    const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; }
3211114SN/A    const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; }
3221114SN/A    const IpPtr &operator=(const IpPtr &ptr) { p = ptr.p; return *this; }
3231114SN/A
3242566SN/A    const EthPacketPtr packet() const { return p; }
3252566SN/A    EthPacketPtr packet() { return p; }
3261114SN/A    bool operator!() const { return !p; }
32710469Sandreas.hansson@arm.com    operator bool() const { return (p != nullptr); }
3289955SGeoffrey.Blake@arm.com    int off() const { return (sizeof(eth_hdr) + ((eth_hdr_vlan) ? 4 : 0)); }
3299955SGeoffrey.Blake@arm.com    int pstart() const { return (off() + get()->size()); }
3301114SN/A};
3311114SN/A
3321114SN/Auint16_t cksum(const IpPtr &ptr);
3331114SN/A
3341114SN/Astruct IpOpt : public ip_opt
3351114SN/A{
3361114SN/A    uint8_t type() const { return opt_type; }
3371114SN/A    uint8_t typeNumber() const { return IP_OPT_NUMBER(opt_type); }
3381114SN/A    uint8_t typeClass() const { return IP_OPT_CLASS(opt_type); }
3391114SN/A    uint8_t typeCopied() const { return IP_OPT_COPIED(opt_type); }
3401114SN/A    uint8_t len() const { return IP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
3411114SN/A
3421114SN/A    bool isNumber(int num) const { return typeNumber() == IP_OPT_NUMBER(num); }
3431114SN/A    bool isClass(int cls) const { return typeClass() == IP_OPT_CLASS(cls); }
3441114SN/A    bool isCopied(int cpy) const { return typeCopied() == IP_OPT_COPIED(cpy); }
3451114SN/A
3461114SN/A    const uint8_t *data() const { return opt_data.data8; }
3471114SN/A    void sec(ip_opt_data_sec &sec) const;
3481114SN/A    void lsrr(ip_opt_data_rr &rr) const;
3491114SN/A    void ssrr(ip_opt_data_rr &rr) const;
3501114SN/A    void ts(ip_opt_data_ts &ts) const;
3511114SN/A    uint16_t satid() const { return ntohs(opt_data.satid); }
3521114SN/A    uint16_t mtup() const { return ntohs(opt_data.mtu); }
3531114SN/A    uint16_t mtur() const { return ntohs(opt_data.mtu); }
3541114SN/A    void tr(ip_opt_data_tr &tr) const;
3551114SN/A    const uint32_t *addext() const { return &opt_data.addext[0]; }
3561114SN/A    uint16_t rtralt() const { return ntohs(opt_data.rtralt); }
3571114SN/A    void sdb(std::vector<uint32_t> &vec) const;
3581114SN/A};
3591114SN/A
3601114SN/A/*
3619955SGeoffrey.Blake@arm.com * Ip6 Classes
3629955SGeoffrey.Blake@arm.com */
3639955SGeoffrey.Blake@arm.comstruct Ip6Opt;
3649955SGeoffrey.Blake@arm.comstruct Ip6Hdr : public ip6_hdr
3659955SGeoffrey.Blake@arm.com{
3669955SGeoffrey.Blake@arm.com    uint8_t version() const { return ip6_vfc; }
3679955SGeoffrey.Blake@arm.com    uint32_t flow() const { return ntohl(ip6_flow); }
3689955SGeoffrey.Blake@arm.com    uint16_t plen() const { return ntohs(ip6_plen); }
3699955SGeoffrey.Blake@arm.com    uint16_t hlen() const { return IP6_HDR_LEN; }
3709955SGeoffrey.Blake@arm.com    uint8_t nxt() const { return ip6_nxt; }
3719955SGeoffrey.Blake@arm.com    uint8_t hlim() const { return ip6_hlim; }
3729955SGeoffrey.Blake@arm.com
3739955SGeoffrey.Blake@arm.com    const uint8_t* src() const { return ip6_src.data; }
3749955SGeoffrey.Blake@arm.com    const uint8_t* dst() const { return ip6_dst.data; }
3759955SGeoffrey.Blake@arm.com
3769955SGeoffrey.Blake@arm.com    int extensionLength() const;
3779955SGeoffrey.Blake@arm.com    const Ip6Opt* getExt(uint8_t ext) const;
3789955SGeoffrey.Blake@arm.com    const Ip6Opt* fragmentExt() const { return getExt(IP_PROTO_FRAGMENT); }
3799955SGeoffrey.Blake@arm.com    const Ip6Opt* rtTypeExt() const { return getExt(IP_PROTO_ROUTING); }
3809955SGeoffrey.Blake@arm.com    const Ip6Opt* dstOptExt() const { return getExt(IP_PROTO_DSTOPTS); }
3819955SGeoffrey.Blake@arm.com    uint8_t proto() const;
3829955SGeoffrey.Blake@arm.com
3839955SGeoffrey.Blake@arm.com    void plen(uint16_t _plen) { ip6_plen = htons(_plen); }
3849955SGeoffrey.Blake@arm.com
3859955SGeoffrey.Blake@arm.com    int size() const { return IP6_HDR_LEN + extensionLength(); }
3869955SGeoffrey.Blake@arm.com    const uint8_t *bytes() const { return (const uint8_t *)this; }
3879955SGeoffrey.Blake@arm.com    const uint8_t *payload() const { return bytes() + IP6_HDR_LEN
3889955SGeoffrey.Blake@arm.com                                            + extensionLength(); }
3899955SGeoffrey.Blake@arm.com    uint8_t *bytes() { return (uint8_t *)this; }
3909955SGeoffrey.Blake@arm.com    uint8_t *payload() { return bytes() + IP6_HDR_LEN
3919955SGeoffrey.Blake@arm.com                                + extensionLength(); }
3929955SGeoffrey.Blake@arm.com};
3939955SGeoffrey.Blake@arm.com
3949955SGeoffrey.Blake@arm.comclass Ip6Ptr
3959955SGeoffrey.Blake@arm.com{
3969955SGeoffrey.Blake@arm.com  protected:
3979955SGeoffrey.Blake@arm.com    friend class TcpPtr;
3989955SGeoffrey.Blake@arm.com    friend class UdpPtr;
3999955SGeoffrey.Blake@arm.com    EthPacketPtr p;
4009955SGeoffrey.Blake@arm.com    bool eth_hdr_vlan;
4019955SGeoffrey.Blake@arm.com
4029955SGeoffrey.Blake@arm.com    void set(const EthPacketPtr &ptr)
4039955SGeoffrey.Blake@arm.com    {
4049955SGeoffrey.Blake@arm.com        p = 0;
4059955SGeoffrey.Blake@arm.com        eth_hdr_vlan = false;
4069955SGeoffrey.Blake@arm.com
4079955SGeoffrey.Blake@arm.com        if (ptr) {
4089955SGeoffrey.Blake@arm.com            EthHdr *eth = (EthHdr *)ptr->data;
4099955SGeoffrey.Blake@arm.com            if (eth->type() == ETH_TYPE_IPV6)
4109955SGeoffrey.Blake@arm.com                p = ptr;
4119955SGeoffrey.Blake@arm.com            if (eth->isVlan())
4129955SGeoffrey.Blake@arm.com                eth_hdr_vlan = true;
4139955SGeoffrey.Blake@arm.com        }
4149955SGeoffrey.Blake@arm.com    }
4159955SGeoffrey.Blake@arm.com
4169955SGeoffrey.Blake@arm.com  public:
4179955SGeoffrey.Blake@arm.com    Ip6Ptr() : p(0), eth_hdr_vlan(false) {}
4189955SGeoffrey.Blake@arm.com    Ip6Ptr(const EthPacketPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr); }
4199955SGeoffrey.Blake@arm.com    Ip6Ptr(const EthPtr &ptr) : p(0), eth_hdr_vlan(false) { set(ptr.p); }
4209955SGeoffrey.Blake@arm.com    Ip6Ptr(const Ip6Ptr &ptr) : p(ptr.p), eth_hdr_vlan(ptr.eth_hdr_vlan) { }
4219955SGeoffrey.Blake@arm.com
4229955SGeoffrey.Blake@arm.com    Ip6Hdr *get() { return (Ip6Hdr *)(p->data + sizeof(eth_hdr)
4239955SGeoffrey.Blake@arm.com                                      + ((eth_hdr_vlan) ? 4 : 0)); }
4249955SGeoffrey.Blake@arm.com    Ip6Hdr *operator->() { return get(); }
4259955SGeoffrey.Blake@arm.com    Ip6Hdr &operator*() { return *get(); }
4269955SGeoffrey.Blake@arm.com
4279955SGeoffrey.Blake@arm.com    const Ip6Hdr *get() const
4289955SGeoffrey.Blake@arm.com    { return (const Ip6Hdr *)(p->data + sizeof(eth_hdr)
4299955SGeoffrey.Blake@arm.com                              + ((eth_hdr_vlan) ? 4 : 0)); }
4309955SGeoffrey.Blake@arm.com    const Ip6Hdr *operator->() const { return get(); }
4319955SGeoffrey.Blake@arm.com    const Ip6Hdr &operator*() const { return *get(); }
4329955SGeoffrey.Blake@arm.com
4339955SGeoffrey.Blake@arm.com    const Ip6Ptr &operator=(const EthPacketPtr &ptr)
4349955SGeoffrey.Blake@arm.com    { set(ptr); return *this; }
4359955SGeoffrey.Blake@arm.com    const Ip6Ptr &operator=(const EthPtr &ptr)
4369955SGeoffrey.Blake@arm.com    { set(ptr.p); return *this; }
4379955SGeoffrey.Blake@arm.com    const Ip6Ptr &operator=(const Ip6Ptr &ptr)
4389955SGeoffrey.Blake@arm.com    { p = ptr.p; return *this; }
4399955SGeoffrey.Blake@arm.com
4409955SGeoffrey.Blake@arm.com    const EthPacketPtr packet() const { return p; }
4419955SGeoffrey.Blake@arm.com    EthPacketPtr packet() { return p; }
4429955SGeoffrey.Blake@arm.com    bool operator!() const { return !p; }
44310469Sandreas.hansson@arm.com    operator bool() const { return (p != nullptr); }
4449955SGeoffrey.Blake@arm.com    int off() const { return sizeof(eth_hdr) + ((eth_hdr_vlan) ? 4 : 0); }
4459955SGeoffrey.Blake@arm.com    int pstart() const { return off() + get()->size(); }
4469955SGeoffrey.Blake@arm.com};
4479955SGeoffrey.Blake@arm.com
4489955SGeoffrey.Blake@arm.com// Dnet supplied ipv6 opt header is incomplete and
4499955SGeoffrey.Blake@arm.com// newer NIC card filters expect a more robust
4509955SGeoffrey.Blake@arm.com// ipv6 header option declaration.
4519955SGeoffrey.Blake@arm.comstruct ip6_opt_fragment {
4529955SGeoffrey.Blake@arm.com    uint16_t offlg;
4539955SGeoffrey.Blake@arm.com    uint32_t ident;
4549955SGeoffrey.Blake@arm.com};
4559955SGeoffrey.Blake@arm.com
4569955SGeoffrey.Blake@arm.comstruct ip6_opt_routing_type2 {
4579955SGeoffrey.Blake@arm.com    uint8_t type;
4589955SGeoffrey.Blake@arm.com    uint8_t segleft;
4599955SGeoffrey.Blake@arm.com    uint32_t reserved;
4609955SGeoffrey.Blake@arm.com    ip6_addr_t addr;
4619955SGeoffrey.Blake@arm.com};
4629955SGeoffrey.Blake@arm.com
4639955SGeoffrey.Blake@arm.com#define HOME_ADDRESS_OPTION 0xC9
4649955SGeoffrey.Blake@arm.comstruct ip6_opt_dstopts {
4659955SGeoffrey.Blake@arm.com    uint8_t type;
4669955SGeoffrey.Blake@arm.com    uint8_t length;
4679955SGeoffrey.Blake@arm.com    ip6_addr_t addr;
4689955SGeoffrey.Blake@arm.com} __attribute__((packed));
4699955SGeoffrey.Blake@arm.com
4709955SGeoffrey.Blake@arm.comstruct ip6_opt_hdr
4719955SGeoffrey.Blake@arm.com{
4729955SGeoffrey.Blake@arm.com    uint8_t ext_nxt;
4739955SGeoffrey.Blake@arm.com    uint8_t ext_len;
4749955SGeoffrey.Blake@arm.com    union {
4759955SGeoffrey.Blake@arm.com        struct ip6_opt_fragment fragment;
4769955SGeoffrey.Blake@arm.com        struct ip6_opt_routing_type2 rtType2;
4779955SGeoffrey.Blake@arm.com        struct ip6_opt_dstopts dstOpts;
4789955SGeoffrey.Blake@arm.com    } ext_data;
4799955SGeoffrey.Blake@arm.com} __attribute__((packed));
4809955SGeoffrey.Blake@arm.com
4819955SGeoffrey.Blake@arm.comstruct Ip6Opt : public ip6_opt_hdr
4829955SGeoffrey.Blake@arm.com{
4839955SGeoffrey.Blake@arm.com    uint8_t nxt() const { return ext_nxt; }
4849955SGeoffrey.Blake@arm.com    uint8_t extlen() const { return ext_len; }
4859955SGeoffrey.Blake@arm.com    uint8_t len() const { return extlen() + 8; }
4869955SGeoffrey.Blake@arm.com
4879955SGeoffrey.Blake@arm.com    // Supporting the types of header extensions likely to be encountered:
4889955SGeoffrey.Blake@arm.com    // fragment, routing type 2 and dstopts.
4899955SGeoffrey.Blake@arm.com
4909955SGeoffrey.Blake@arm.com    // Routing type 2
4919955SGeoffrey.Blake@arm.com    uint8_t  rtType2Type() const { return ext_data.rtType2.type; }
4929955SGeoffrey.Blake@arm.com    uint8_t  rtType2SegLft() const { return ext_data.rtType2.segleft; }
4939955SGeoffrey.Blake@arm.com    const uint8_t* rtType2Addr() const { return ext_data.rtType2.addr.data; }
4949955SGeoffrey.Blake@arm.com
4959955SGeoffrey.Blake@arm.com    // Fragment
4969955SGeoffrey.Blake@arm.com    uint16_t fragmentOfflg() const { return ntohs(ext_data.fragment.offlg); }
4979955SGeoffrey.Blake@arm.com    uint32_t fragmentIdent() const { return ntohl(ext_data.fragment.ident); }
4989955SGeoffrey.Blake@arm.com
4999955SGeoffrey.Blake@arm.com    // Dst Options/Home Address Option
5009955SGeoffrey.Blake@arm.com    uint8_t dstOptType() const { return ext_data.dstOpts.type; }
5019955SGeoffrey.Blake@arm.com    uint8_t dstOptLength() const { return ext_data.dstOpts.length; }
5029955SGeoffrey.Blake@arm.com    const uint8_t* dstOptAddr() const { return ext_data.dstOpts.addr.data; }
5039955SGeoffrey.Blake@arm.com};
5049955SGeoffrey.Blake@arm.com
5059955SGeoffrey.Blake@arm.com
5069955SGeoffrey.Blake@arm.com/*
5071114SN/A * TCP Stuff
5081114SN/A */
5091114SN/Astruct TcpOpt;
5101114SN/Astruct TcpHdr : public tcp_hdr
5111078SN/A{
5121078SN/A    uint16_t sport() const { return ntohs(th_sport); }
5131078SN/A    uint16_t dport() const { return ntohs(th_dport); }
5141078SN/A    uint32_t seq() const { return ntohl(th_seq); }
5151078SN/A    uint32_t ack() const { return ntohl(th_ack); }
5169955SGeoffrey.Blake@arm.com    uint8_t  off() const { return th_off*4; }
5171078SN/A    uint8_t  flags() const { return th_flags & 0x3f; }
5181078SN/A    uint16_t win() const { return ntohs(th_win); }
5191092SN/A    uint16_t sum() const { return th_sum; }
5201078SN/A    uint16_t urp() const { return ntohs(th_urp); }
5211078SN/A
5221092SN/A    void sum(uint16_t sum) { th_sum = sum; }
5235761Ssaidi@eecs.umich.edu    void seq(uint32_t _seq) { th_seq = htonl(_seq); }
52411320Ssteve.reinhardt@amd.com    void flags(uint8_t _flags) { th_flags  = _flags; }
5251078SN/A
5261114SN/A    bool options(std::vector<const TcpOpt *> &vec) const;
5271114SN/A
5281079SN/A    int size() const { return off(); }
5291079SN/A    const uint8_t *bytes() const { return (const uint8_t *)this; }
5301079SN/A    const uint8_t *payload() const { return bytes() + size(); }
5311079SN/A    uint8_t *bytes() { return (uint8_t *)this; }
5321079SN/A    uint8_t *payload() { return bytes() + size(); }
5331078SN/A};
5341078SN/A
5351114SN/Aclass TcpPtr
5361114SN/A{
5371114SN/A  protected:
5382566SN/A    EthPacketPtr p;
5395782Ssaidi@eecs.umich.edu    int _off;
5401114SN/A
5415782Ssaidi@eecs.umich.edu    void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
5421114SN/A    void set(const IpPtr &ptr)
5431114SN/A    {
5445484Snate@binkert.org        if (ptr && ptr->proto() == IP_PROTO_TCP)
5459955SGeoffrey.Blake@arm.com            set(ptr.p, ptr.pstart());
5469955SGeoffrey.Blake@arm.com        else
5479955SGeoffrey.Blake@arm.com            set(0, 0);
5489955SGeoffrey.Blake@arm.com    }
5499955SGeoffrey.Blake@arm.com    void set(const Ip6Ptr &ptr)
5509955SGeoffrey.Blake@arm.com    {
5519955SGeoffrey.Blake@arm.com        if (ptr && ptr->proto() == IP_PROTO_TCP)
5529955SGeoffrey.Blake@arm.com            set(ptr.p, ptr.pstart());
5531114SN/A        else
5541114SN/A            set(0, 0);
5551114SN/A    }
5561114SN/A
5571114SN/A  public:
5585782Ssaidi@eecs.umich.edu    TcpPtr() : p(0), _off(0) {}
5595782Ssaidi@eecs.umich.edu    TcpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
5609955SGeoffrey.Blake@arm.com    TcpPtr(const Ip6Ptr &ptr) : p(0), _off(0) { set(ptr); }
5615782Ssaidi@eecs.umich.edu    TcpPtr(const TcpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
5621114SN/A
5635782Ssaidi@eecs.umich.edu    TcpHdr *get() { return (TcpHdr *)(p->data + _off); }
5645484Snate@binkert.org    TcpHdr *operator->() { return get(); }
5655484Snate@binkert.org    TcpHdr &operator*() { return *get(); }
5661114SN/A
5675782Ssaidi@eecs.umich.edu    const TcpHdr *get() const { return (const TcpHdr *)(p->data + _off); }
5685484Snate@binkert.org    const TcpHdr *operator->() const { return get(); }
5695484Snate@binkert.org    const TcpHdr &operator*() const { return *get(); }
5701114SN/A
5719955SGeoffrey.Blake@arm.com    const TcpPtr &operator=(const IpPtr &i)
5729955SGeoffrey.Blake@arm.com    { set(i); return *this; }
5739955SGeoffrey.Blake@arm.com    const TcpPtr &operator=(const TcpPtr &t)
5749955SGeoffrey.Blake@arm.com    { set(t.p, t._off); return *this; }
5751114SN/A
5762566SN/A    const EthPacketPtr packet() const { return p; }
5772566SN/A    EthPacketPtr packet() { return p; }
5781114SN/A    bool operator!() const { return !p; }
57910469Sandreas.hansson@arm.com    operator bool() const { return (p != nullptr); }
5805782Ssaidi@eecs.umich.edu    int off() const { return _off; }
5815782Ssaidi@eecs.umich.edu    int pstart() const { return off() + get()->size(); }
5821114SN/A};
5831114SN/A
5841114SN/Auint16_t cksum(const TcpPtr &ptr);
5851114SN/A
5861114SN/Astruct TcpOpt : public tcp_opt
5871114SN/A{
5881114SN/A    uint8_t type() const { return opt_type; }
5891114SN/A    uint8_t len() const { return TCP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
5901114SN/A
5911114SN/A    bool isopt(int opt) const { return type() == opt; }
5921114SN/A
5931114SN/A    const uint8_t *data() const { return opt_data.data8; }
5941114SN/A
5951114SN/A    uint16_t mss() const { return ntohs(opt_data.mss); }
5961114SN/A    uint8_t wscale() const { return opt_data.wscale; }
5971114SN/A    uint32_t echo() const { return ntohl(opt_data.echo); }
5981114SN/A    uint32_t tsval() const { return ntohl(opt_data.timestamp[0]); }
5991114SN/A    uint32_t tsecr() const { return ntohl(opt_data.timestamp[1]); }
6001114SN/A    uint32_t cc() const { return ntohl(opt_data.cc); }
6011114SN/A    uint8_t cksum() const{ return opt_data.cksum; }
6021114SN/A    const uint8_t *md5() const { return opt_data.md5; }
6031114SN/A
6041114SN/A    int size() const { return len(); }
6051114SN/A    const uint8_t *bytes() const { return (const uint8_t *)this; }
6061114SN/A    const uint8_t *payload() const { return bytes() + size(); }
6071114SN/A    uint8_t *bytes() { return (uint8_t *)this; }
6081114SN/A    uint8_t *payload() { return bytes() + size(); }
6091114SN/A};
6101114SN/A
6111114SN/A/*
6121114SN/A * UDP Stuff
6131114SN/A */
6141114SN/Astruct UdpHdr : public udp_hdr
6151078SN/A{
6161078SN/A    uint16_t sport() const { return ntohs(uh_sport); }
6171078SN/A    uint16_t dport() const { return ntohs(uh_dport); }
6181078SN/A    uint16_t len() const { return ntohs(uh_ulen); }
6191171SN/A    uint16_t sum() const { return uh_sum; }
6201078SN/A
6211171SN/A    void sum(uint16_t sum) { uh_sum = sum; }
6225761Ssaidi@eecs.umich.edu    void len(uint16_t _len) { uh_ulen = htons(_len); }
6231078SN/A
6241114SN/A    int size() const { return sizeof(udp_hdr); }
6251079SN/A    const uint8_t *bytes() const { return (const uint8_t *)this; }
6261079SN/A    const uint8_t *payload() const { return bytes() + size(); }
6271079SN/A    uint8_t *bytes() { return (uint8_t *)this; }
6281079SN/A    uint8_t *payload() { return bytes() + size(); }
6291078SN/A};
6301078SN/A
6311114SN/Aclass UdpPtr
6321114SN/A{
6331114SN/A  protected:
6342566SN/A    EthPacketPtr p;
6355782Ssaidi@eecs.umich.edu    int _off;
6361114SN/A
6375782Ssaidi@eecs.umich.edu    void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
6381114SN/A    void set(const IpPtr &ptr)
6391114SN/A    {
6405484Snate@binkert.org        if (ptr && ptr->proto() == IP_PROTO_UDP)
6419955SGeoffrey.Blake@arm.com            set(ptr.p, ptr.pstart());
6429955SGeoffrey.Blake@arm.com        else
6439955SGeoffrey.Blake@arm.com            set(0, 0);
6449955SGeoffrey.Blake@arm.com    }
6459955SGeoffrey.Blake@arm.com    void set(const Ip6Ptr &ptr)
6469955SGeoffrey.Blake@arm.com    {
6479955SGeoffrey.Blake@arm.com        if (ptr && ptr->proto() == IP_PROTO_UDP)
6489955SGeoffrey.Blake@arm.com            set(ptr.p, ptr.pstart());
6491114SN/A        else
6501114SN/A            set(0, 0);
6511114SN/A    }
6521114SN/A
6531114SN/A  public:
6545782Ssaidi@eecs.umich.edu    UdpPtr() : p(0), _off(0) {}
6555782Ssaidi@eecs.umich.edu    UdpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
6569955SGeoffrey.Blake@arm.com    UdpPtr(const Ip6Ptr &ptr) : p(0), _off(0) { set(ptr); }
6575782Ssaidi@eecs.umich.edu    UdpPtr(const UdpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
6581114SN/A
6595782Ssaidi@eecs.umich.edu    UdpHdr *get() { return (UdpHdr *)(p->data + _off); }
6605484Snate@binkert.org    UdpHdr *operator->() { return get(); }
6615484Snate@binkert.org    UdpHdr &operator*() { return *get(); }
6621114SN/A
6635782Ssaidi@eecs.umich.edu    const UdpHdr *get() const { return (const UdpHdr *)(p->data + _off); }
6645484Snate@binkert.org    const UdpHdr *operator->() const { return get(); }
6655484Snate@binkert.org    const UdpHdr &operator*() const { return *get(); }
6661114SN/A
6671114SN/A    const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; }
6689955SGeoffrey.Blake@arm.com    const UdpPtr &operator=(const UdpPtr &t)
6699955SGeoffrey.Blake@arm.com    { set(t.p, t._off); return *this; }
6701114SN/A
6712566SN/A    const EthPacketPtr packet() const { return p; }
6722566SN/A    EthPacketPtr packet() { return p; }
6731114SN/A    bool operator!() const { return !p; }
67410469Sandreas.hansson@arm.com    operator bool() const { return (p != nullptr); }
6755782Ssaidi@eecs.umich.edu    int off() const { return _off; }
6765782Ssaidi@eecs.umich.edu    int pstart() const { return off() + get()->size(); }
6771114SN/A};
6781114SN/A
6799955SGeoffrey.Blake@arm.comuint16_t __tu_cksum6(const Ip6Ptr &ip6);
6809554Sandreas.hansson@arm.comuint16_t __tu_cksum(const IpPtr &ip);
6811114SN/Auint16_t cksum(const UdpPtr &ptr);
6821114SN/A
6835782Ssaidi@eecs.umich.eduint hsplit(const EthPacketPtr &ptr);
6845782Ssaidi@eecs.umich.edu
6857811Ssteve.reinhardt@amd.com} // namespace Net
6861114SN/A
6871078SN/A#endif // __BASE_INET_HH__
688