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 427778Sgblack@eecs.umich.edu * Gabe Black 439955SGeoffrey.Blake@arm.com * Geoffrey Blake 442SN/A */ 452SN/A 4611793Sbrandon.potter@amd.com#include "base/inet.hh" 4711793Sbrandon.potter@amd.com 488607Sgblack@eecs.umich.edu#include <cstddef> 496712Snate@binkert.org#include <cstdio> 502SN/A#include <sstream> 512SN/A#include <string> 522SN/A 5356SN/A#include "base/cprintf.hh" 5413449Sgabeblack@google.com#include "base/logging.hh" 556214Snate@binkert.org#include "base/types.hh" 562SN/A 571078SN/Ausing namespace std; 581114SN/Anamespace Net { 591114SN/A 601114SN/AEthAddr::EthAddr() 611114SN/A{ 621114SN/A memset(data, 0, ETH_ADDR_LEN); 631114SN/A} 641114SN/A 651114SN/AEthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN]) 661114SN/A{ 6710251Satgutier@umich.edu for (int i = 0; i < ETH_ADDR_LEN; ++i) 6810251Satgutier@umich.edu data[i] = ea[i]; 691114SN/A} 701114SN/A 711114SN/AEthAddr::EthAddr(const eth_addr &ea) 721114SN/A{ 7310251Satgutier@umich.edu for (int i = 0; i < ETH_ADDR_LEN; ++i) 7410251Satgutier@umich.edu data[i] = ea.data[i]; 751114SN/A} 761114SN/A 771114SN/AEthAddr::EthAddr(const std::string &addr) 781114SN/A{ 791114SN/A parse(addr); 801114SN/A} 811114SN/A 821114SN/Aconst EthAddr & 831114SN/AEthAddr::operator=(const eth_addr &ea) 841114SN/A{ 851114SN/A *data = *ea.data; 861114SN/A return *this; 871114SN/A} 881114SN/A 891114SN/Aconst EthAddr & 901114SN/AEthAddr::operator=(const std::string &addr) 911114SN/A{ 921114SN/A parse(addr); 931114SN/A return *this; 941114SN/A} 951114SN/A 961114SN/Avoid 971114SN/AEthAddr::parse(const std::string &addr) 981114SN/A{ 991114SN/A // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise 1001114SN/A // the sscanf function won't work. 1011114SN/A int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1]; 1021114SN/A if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1], 1031114SN/A &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) { 1041114SN/A memset(data, 0xff, ETH_ADDR_LEN); 1051114SN/A return; 1061114SN/A } 1071114SN/A 1081114SN/A for (int i = 0; i < ETH_ADDR_LEN; ++i) { 1091114SN/A if (bytes[i] & ~0xff) { 1101114SN/A memset(data, 0xff, ETH_ADDR_LEN); 1111114SN/A return; 1121114SN/A } 1131114SN/A 1141114SN/A data[i] = bytes[i]; 1151114SN/A } 1161114SN/A} 1171114SN/A 1182SN/Astring 1191114SN/AEthAddr::string() const 1202SN/A{ 1212SN/A stringstream stream; 1221114SN/A stream << *this; 1232SN/A return stream.str(); 1242SN/A} 1252SN/A 1261114SN/Abool 1271114SN/Aoperator==(const EthAddr &left, const EthAddr &right) 1282SN/A{ 12910252Satgutier@umich.edu return !memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN); 1301114SN/A} 1311114SN/A 1321114SN/Aostream & 1331114SN/Aoperator<<(ostream &stream, const EthAddr &ea) 1341114SN/A{ 1351114SN/A const uint8_t *a = ea.addr(); 1361114SN/A ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 1371114SN/A return stream; 1382SN/A} 1392SN/A 1407777Sgblack@eecs.umich.edustring 1417777Sgblack@eecs.umich.eduIpAddress::string() const 1427777Sgblack@eecs.umich.edu{ 1437777Sgblack@eecs.umich.edu stringstream stream; 1447777Sgblack@eecs.umich.edu stream << *this; 1457777Sgblack@eecs.umich.edu return stream.str(); 1467777Sgblack@eecs.umich.edu} 1477777Sgblack@eecs.umich.edu 1487777Sgblack@eecs.umich.edubool 1497777Sgblack@eecs.umich.eduoperator==(const IpAddress &left, const IpAddress &right) 1507777Sgblack@eecs.umich.edu{ 1517777Sgblack@eecs.umich.edu return left.ip() == right.ip(); 1527777Sgblack@eecs.umich.edu} 1537777Sgblack@eecs.umich.edu 1547777Sgblack@eecs.umich.eduostream & 1557777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpAddress &ia) 1567777Sgblack@eecs.umich.edu{ 1577777Sgblack@eecs.umich.edu uint32_t ip = ia.ip(); 1587777Sgblack@eecs.umich.edu ccprintf(stream, "%x.%x.%x.%x", 1597814Sgblack@eecs.umich.edu (uint8_t)(ip >> 24), (uint8_t)(ip >> 16), 1607814Sgblack@eecs.umich.edu (uint8_t)(ip >> 8), (uint8_t)(ip >> 0)); 1617777Sgblack@eecs.umich.edu return stream; 1627777Sgblack@eecs.umich.edu} 1637777Sgblack@eecs.umich.edu 1647777Sgblack@eecs.umich.edustring 1657777Sgblack@eecs.umich.eduIpNetmask::string() const 1667777Sgblack@eecs.umich.edu{ 1677777Sgblack@eecs.umich.edu stringstream stream; 1687777Sgblack@eecs.umich.edu stream << *this; 1697777Sgblack@eecs.umich.edu return stream.str(); 1707777Sgblack@eecs.umich.edu} 1717777Sgblack@eecs.umich.edu 1727777Sgblack@eecs.umich.edubool 1737777Sgblack@eecs.umich.eduoperator==(const IpNetmask &left, const IpNetmask &right) 1747777Sgblack@eecs.umich.edu{ 1757777Sgblack@eecs.umich.edu return (left.ip() == right.ip()) && 1767777Sgblack@eecs.umich.edu (left.netmask() == right.netmask()); 1777777Sgblack@eecs.umich.edu} 1787777Sgblack@eecs.umich.edu 1797777Sgblack@eecs.umich.eduostream & 1807777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpNetmask &in) 1817777Sgblack@eecs.umich.edu{ 1827777Sgblack@eecs.umich.edu ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask()); 1837777Sgblack@eecs.umich.edu return stream; 1847777Sgblack@eecs.umich.edu} 1857777Sgblack@eecs.umich.edu 1867777Sgblack@eecs.umich.edustring 1877777Sgblack@eecs.umich.eduIpWithPort::string() const 1887777Sgblack@eecs.umich.edu{ 1897777Sgblack@eecs.umich.edu stringstream stream; 1907777Sgblack@eecs.umich.edu stream << *this; 1917777Sgblack@eecs.umich.edu return stream.str(); 1927777Sgblack@eecs.umich.edu} 1937777Sgblack@eecs.umich.edu 1947777Sgblack@eecs.umich.edubool 1957777Sgblack@eecs.umich.eduoperator==(const IpWithPort &left, const IpWithPort &right) 1967777Sgblack@eecs.umich.edu{ 1977777Sgblack@eecs.umich.edu return (left.ip() == right.ip()) && (left.port() == right.port()); 1987777Sgblack@eecs.umich.edu} 1997777Sgblack@eecs.umich.edu 2007777Sgblack@eecs.umich.eduostream & 2017777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpWithPort &iwp) 2027777Sgblack@eecs.umich.edu{ 2037777Sgblack@eecs.umich.edu ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port()); 2047777Sgblack@eecs.umich.edu return stream; 2057777Sgblack@eecs.umich.edu} 2067777Sgblack@eecs.umich.edu 2071078SN/Auint16_t 2081114SN/Acksum(const IpPtr &ptr) 2091078SN/A{ 2101114SN/A int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0); 2111114SN/A return ip_cksum_carry(sum); 2121078SN/A} 2131114SN/A 2141114SN/Auint16_t 2151114SN/A__tu_cksum(const IpPtr &ip) 2161114SN/A{ 2171114SN/A int tcplen = ip->len() - ip->hlen(); 2181114SN/A int sum = ip_cksum_add(ip->payload(), tcplen, 0); 2191114SN/A sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination 2201114SN/A sum += htons(ip->ip_p + tcplen); 2211114SN/A return ip_cksum_carry(sum); 2221114SN/A} 2231114SN/A 2241114SN/Auint16_t 2259955SGeoffrey.Blake@arm.com__tu_cksum6(const Ip6Ptr &ip6) 2269955SGeoffrey.Blake@arm.com{ 2279955SGeoffrey.Blake@arm.com int tcplen = ip6->plen() - ip6->extensionLength(); 2289955SGeoffrey.Blake@arm.com int sum = ip_cksum_add(ip6->payload(), tcplen, 0); 2299955SGeoffrey.Blake@arm.com sum = ip_cksum_add(ip6->src(), 32, sum); 2309955SGeoffrey.Blake@arm.com sum += htons(ip6->proto() + tcplen); 2319955SGeoffrey.Blake@arm.com return ip_cksum_carry(sum); 2329955SGeoffrey.Blake@arm.com} 2339955SGeoffrey.Blake@arm.com 2349955SGeoffrey.Blake@arm.comuint16_t 2351114SN/Acksum(const TcpPtr &tcp) 2369955SGeoffrey.Blake@arm.com{ 2379955SGeoffrey.Blake@arm.com if (IpPtr(tcp.packet())) { 2389955SGeoffrey.Blake@arm.com return __tu_cksum(IpPtr(tcp.packet())); 2399955SGeoffrey.Blake@arm.com } else if (Ip6Ptr(tcp.packet())) { 2409955SGeoffrey.Blake@arm.com return __tu_cksum6(Ip6Ptr(tcp.packet())); 2419955SGeoffrey.Blake@arm.com } else { 24213449Sgabeblack@google.com panic("Unrecognized IP packet format"); 2439955SGeoffrey.Blake@arm.com } 2449955SGeoffrey.Blake@arm.com // Should never reach here 2459955SGeoffrey.Blake@arm.com return 0; 2469955SGeoffrey.Blake@arm.com} 2471114SN/A 2481114SN/Auint16_t 2491114SN/Acksum(const UdpPtr &udp) 2509955SGeoffrey.Blake@arm.com{ 2519955SGeoffrey.Blake@arm.com if (IpPtr(udp.packet())) { 2529955SGeoffrey.Blake@arm.com return __tu_cksum(IpPtr(udp.packet())); 2539955SGeoffrey.Blake@arm.com } else if (Ip6Ptr(udp.packet())) { 2549955SGeoffrey.Blake@arm.com return __tu_cksum6(Ip6Ptr(udp.packet())); 2559955SGeoffrey.Blake@arm.com } else { 25613449Sgabeblack@google.com panic("Unrecognized IP packet format"); 2579955SGeoffrey.Blake@arm.com } 2589955SGeoffrey.Blake@arm.com return 0; 2599955SGeoffrey.Blake@arm.com} 2601114SN/A 2611114SN/Abool 2621114SN/AIpHdr::options(vector<const IpOpt *> &vec) const 2631114SN/A{ 2641114SN/A vec.clear(); 2651114SN/A 2661114SN/A const uint8_t *data = bytes() + sizeof(struct ip_hdr); 2671114SN/A int all = hlen() - sizeof(struct ip_hdr); 2681114SN/A while (all > 0) { 2691114SN/A const IpOpt *opt = (const IpOpt *)data; 2701114SN/A int len = opt->len(); 2711114SN/A if (all < len) 2721114SN/A return false; 2731114SN/A 2741114SN/A vec.push_back(opt); 2751114SN/A all -= len; 2761114SN/A data += len; 2771114SN/A } 2781114SN/A 2791114SN/A return true; 2801114SN/A} 2811114SN/A 2829955SGeoffrey.Blake@arm.com#define IP6_EXTENSION(nxt) (nxt == IP_PROTO_HOPOPTS) ? true : \ 2839955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_ROUTING) ? true : \ 2849955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_FRAGMENT) ? true : \ 2859955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_AH) ? true : \ 2869955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_ESP) ? true: \ 2879955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_DSTOPTS) ? true : false 2889955SGeoffrey.Blake@arm.com 2899955SGeoffrey.Blake@arm.com/* Scan the IP6 header for all header extensions 2909955SGeoffrey.Blake@arm.com * and return the number of headers found 2919955SGeoffrey.Blake@arm.com */ 2929955SGeoffrey.Blake@arm.comint 2939955SGeoffrey.Blake@arm.comIp6Hdr::extensionLength() const 2949955SGeoffrey.Blake@arm.com{ 2959955SGeoffrey.Blake@arm.com const uint8_t *data = bytes() + IP6_HDR_LEN; 2969955SGeoffrey.Blake@arm.com uint8_t nxt = ip6_nxt; 2979955SGeoffrey.Blake@arm.com int len = 0; 2989955SGeoffrey.Blake@arm.com int all = plen(); 2999955SGeoffrey.Blake@arm.com 3009955SGeoffrey.Blake@arm.com while (IP6_EXTENSION(nxt)) { 3019955SGeoffrey.Blake@arm.com const Ip6Opt *ext = (const Ip6Opt *)data; 3029955SGeoffrey.Blake@arm.com nxt = ext->nxt(); 3039955SGeoffrey.Blake@arm.com len += ext->len(); 3049955SGeoffrey.Blake@arm.com data += ext->len(); 3059955SGeoffrey.Blake@arm.com all -= ext->len(); 3069955SGeoffrey.Blake@arm.com assert(all >= 0); 3079955SGeoffrey.Blake@arm.com } 3089955SGeoffrey.Blake@arm.com return len; 3099955SGeoffrey.Blake@arm.com} 3109955SGeoffrey.Blake@arm.com 3119955SGeoffrey.Blake@arm.com/* Scan the IP6 header for a particular extension 3129955SGeoffrey.Blake@arm.com * header type and return a pointer to it if it 3139955SGeoffrey.Blake@arm.com * exists, otherwise return NULL 3149955SGeoffrey.Blake@arm.com */ 3159955SGeoffrey.Blake@arm.comconst Ip6Opt* 3169955SGeoffrey.Blake@arm.comIp6Hdr::getExt(uint8_t ext_type) const 3179955SGeoffrey.Blake@arm.com{ 3189955SGeoffrey.Blake@arm.com const uint8_t *data = bytes() + IP6_HDR_LEN; 3199955SGeoffrey.Blake@arm.com uint8_t nxt = ip6_nxt; 3209955SGeoffrey.Blake@arm.com Ip6Opt* opt = NULL; 3219955SGeoffrey.Blake@arm.com int all = plen(); 3229955SGeoffrey.Blake@arm.com 3239955SGeoffrey.Blake@arm.com while (IP6_EXTENSION(nxt)) { 3249955SGeoffrey.Blake@arm.com opt = (Ip6Opt *)data; 3259955SGeoffrey.Blake@arm.com if (nxt == ext_type) { 3269955SGeoffrey.Blake@arm.com break; 3279955SGeoffrey.Blake@arm.com } 3289955SGeoffrey.Blake@arm.com nxt = opt->nxt(); 3299955SGeoffrey.Blake@arm.com data += opt->len(); 3309955SGeoffrey.Blake@arm.com all -= opt->len(); 3319955SGeoffrey.Blake@arm.com opt = NULL; 3329955SGeoffrey.Blake@arm.com assert(all >= 0); 3339955SGeoffrey.Blake@arm.com } 3349955SGeoffrey.Blake@arm.com return (const Ip6Opt*)opt; 3359955SGeoffrey.Blake@arm.com} 3369955SGeoffrey.Blake@arm.com 3379955SGeoffrey.Blake@arm.com/* Scan the IP6 header and any extension headers 3389955SGeoffrey.Blake@arm.com * to find what type of Layer 4 header exists 3399955SGeoffrey.Blake@arm.com * after this header 3409955SGeoffrey.Blake@arm.com */ 3419955SGeoffrey.Blake@arm.comuint8_t 3429955SGeoffrey.Blake@arm.comIp6Hdr::proto() const 3439955SGeoffrey.Blake@arm.com{ 3449955SGeoffrey.Blake@arm.com const uint8_t *data = bytes() + IP6_HDR_LEN; 3459955SGeoffrey.Blake@arm.com uint8_t nxt = ip6_nxt; 3469955SGeoffrey.Blake@arm.com int all = plen(); 3479955SGeoffrey.Blake@arm.com 3489955SGeoffrey.Blake@arm.com while (IP6_EXTENSION(nxt)) { 3499955SGeoffrey.Blake@arm.com const Ip6Opt *ext = (const Ip6Opt *)data; 3509955SGeoffrey.Blake@arm.com nxt = ext->nxt(); 3519955SGeoffrey.Blake@arm.com data += ext->len(); 3529955SGeoffrey.Blake@arm.com all -= ext->len(); 3539955SGeoffrey.Blake@arm.com assert(all >= 0); 3549955SGeoffrey.Blake@arm.com } 3559955SGeoffrey.Blake@arm.com return nxt; 3569955SGeoffrey.Blake@arm.com} 3579955SGeoffrey.Blake@arm.com 3581114SN/Abool 3591114SN/ATcpHdr::options(vector<const TcpOpt *> &vec) const 3601114SN/A{ 3611114SN/A vec.clear(); 3621114SN/A 3631114SN/A const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 3641114SN/A int all = off() - sizeof(struct tcp_hdr); 3651114SN/A while (all > 0) { 3661114SN/A const TcpOpt *opt = (const TcpOpt *)data; 3671114SN/A int len = opt->len(); 3681114SN/A if (all < len) 3691114SN/A return false; 3701114SN/A 3711114SN/A vec.push_back(opt); 3721114SN/A all -= len; 3731114SN/A data += len; 3741114SN/A } 3751114SN/A 3761114SN/A return true; 3771114SN/A} 3781114SN/A 37911320Ssteve.reinhardt@amd.comint 3805782Ssaidi@eecs.umich.eduhsplit(const EthPacketPtr &ptr) 3815782Ssaidi@eecs.umich.edu{ 3825782Ssaidi@eecs.umich.edu int split_point = 0; 3835782Ssaidi@eecs.umich.edu 3845782Ssaidi@eecs.umich.edu IpPtr ip(ptr); 3859955SGeoffrey.Blake@arm.com Ip6Ptr ip6(ptr); 3865782Ssaidi@eecs.umich.edu if (ip) { 3875782Ssaidi@eecs.umich.edu split_point = ip.pstart(); 3885782Ssaidi@eecs.umich.edu 3895782Ssaidi@eecs.umich.edu TcpPtr tcp(ip); 3905782Ssaidi@eecs.umich.edu if (tcp) 3915782Ssaidi@eecs.umich.edu split_point = tcp.pstart(); 3925782Ssaidi@eecs.umich.edu 3935782Ssaidi@eecs.umich.edu UdpPtr udp(ip); 3945782Ssaidi@eecs.umich.edu if (udp) 3955782Ssaidi@eecs.umich.edu split_point = udp.pstart(); 3969955SGeoffrey.Blake@arm.com } else if (ip6) { 3979955SGeoffrey.Blake@arm.com split_point = ip6.pstart(); 3989955SGeoffrey.Blake@arm.com 3999955SGeoffrey.Blake@arm.com TcpPtr tcp(ip6); 4009955SGeoffrey.Blake@arm.com if (tcp) 4019955SGeoffrey.Blake@arm.com split_point = tcp.pstart(); 4029955SGeoffrey.Blake@arm.com UdpPtr udp(ip6); 4039955SGeoffrey.Blake@arm.com if (udp) 4049955SGeoffrey.Blake@arm.com split_point = udp.pstart(); 4055782Ssaidi@eecs.umich.edu } 4065782Ssaidi@eecs.umich.edu return split_point; 4075782Ssaidi@eecs.umich.edu} 4085782Ssaidi@eecs.umich.edu 4095782Ssaidi@eecs.umich.edu 4107811Ssteve.reinhardt@amd.com} // namespace Net 411