inet.cc revision 8607
12SN/A/*
21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
37778Sgblack@eecs.umich.edu * Copyright (c) 2010 Advanced Micro Devices, Inc.
42SN/A * All rights reserved.
52SN/A *
62SN/A * Redistribution and use in source and binary forms, with or without
72SN/A * modification, are permitted provided that the following conditions are
82SN/A * met: redistributions of source code must retain the above copyright
92SN/A * notice, this list of conditions and the following disclaimer;
102SN/A * redistributions in binary form must reproduce the above copyright
112SN/A * notice, this list of conditions and the following disclaimer in the
122SN/A * documentation and/or other materials provided with the distribution;
132SN/A * neither the name of the copyright holders nor the names of its
142SN/A * contributors may be used to endorse or promote products derived from
152SN/A * this software without specific prior written permission.
162SN/A *
172SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu *
292665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
307778Sgblack@eecs.umich.edu *          Gabe Black
312SN/A */
322SN/A
338607Sgblack@eecs.umich.edu#include <cstddef>
346712Snate@binkert.org#include <cstdio>
352SN/A#include <sstream>
362SN/A#include <string>
372SN/A
3856SN/A#include "base/cprintf.hh"
396216Snate@binkert.org#include "base/inet.hh"
406214Snate@binkert.org#include "base/types.hh"
412SN/A
421078SN/Ausing namespace std;
431114SN/Anamespace Net {
441114SN/A
451114SN/AEthAddr::EthAddr()
461114SN/A{
471114SN/A    memset(data, 0, ETH_ADDR_LEN);
481114SN/A}
491114SN/A
501114SN/AEthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
511114SN/A{
521114SN/A    *data = *ea;
531114SN/A}
541114SN/A
551114SN/AEthAddr::EthAddr(const eth_addr &ea)
561114SN/A{
571114SN/A    *data = *ea.data;
581114SN/A}
591114SN/A
601114SN/AEthAddr::EthAddr(const std::string &addr)
611114SN/A{
621114SN/A    parse(addr);
631114SN/A}
641114SN/A
651114SN/Aconst EthAddr &
661114SN/AEthAddr::operator=(const eth_addr &ea)
671114SN/A{
681114SN/A    *data = *ea.data;
691114SN/A    return *this;
701114SN/A}
711114SN/A
721114SN/Aconst EthAddr &
731114SN/AEthAddr::operator=(const std::string &addr)
741114SN/A{
751114SN/A    parse(addr);
761114SN/A    return *this;
771114SN/A}
781114SN/A
791114SN/Avoid
801114SN/AEthAddr::parse(const std::string &addr)
811114SN/A{
821114SN/A    // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
831114SN/A    // the sscanf function won't work.
841114SN/A    int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
851114SN/A    if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
861114SN/A               &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
871114SN/A        memset(data, 0xff, ETH_ADDR_LEN);
881114SN/A        return;
891114SN/A    }
901114SN/A
911114SN/A    for (int i = 0; i < ETH_ADDR_LEN; ++i) {
921114SN/A        if (bytes[i] & ~0xff) {
931114SN/A            memset(data, 0xff, ETH_ADDR_LEN);
941114SN/A            return;
951114SN/A        }
961114SN/A
971114SN/A        data[i] = bytes[i];
981114SN/A    }
991114SN/A}
1001114SN/A
1012SN/Astring
1021114SN/AEthAddr::string() const
1032SN/A{
1042SN/A    stringstream stream;
1051114SN/A    stream << *this;
1062SN/A    return stream.str();
1072SN/A}
1082SN/A
1091114SN/Abool
1101114SN/Aoperator==(const EthAddr &left, const EthAddr &right)
1112SN/A{
1121114SN/A    return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
1131114SN/A}
1141114SN/A
1151114SN/Aostream &
1161114SN/Aoperator<<(ostream &stream, const EthAddr &ea)
1171114SN/A{
1181114SN/A    const uint8_t *a = ea.addr();
1191114SN/A    ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
1201114SN/A    return stream;
1212SN/A}
1222SN/A
1237777Sgblack@eecs.umich.edustring
1247777Sgblack@eecs.umich.eduIpAddress::string() const
1257777Sgblack@eecs.umich.edu{
1267777Sgblack@eecs.umich.edu    stringstream stream;
1277777Sgblack@eecs.umich.edu    stream << *this;
1287777Sgblack@eecs.umich.edu    return stream.str();
1297777Sgblack@eecs.umich.edu}
1307777Sgblack@eecs.umich.edu
1317777Sgblack@eecs.umich.edubool
1327777Sgblack@eecs.umich.eduoperator==(const IpAddress &left, const IpAddress &right)
1337777Sgblack@eecs.umich.edu{
1347777Sgblack@eecs.umich.edu    return left.ip() == right.ip();
1357777Sgblack@eecs.umich.edu}
1367777Sgblack@eecs.umich.edu
1377777Sgblack@eecs.umich.eduostream &
1387777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpAddress &ia)
1397777Sgblack@eecs.umich.edu{
1407777Sgblack@eecs.umich.edu    uint32_t ip = ia.ip();
1417777Sgblack@eecs.umich.edu    ccprintf(stream, "%x.%x.%x.%x",
1427814Sgblack@eecs.umich.edu            (uint8_t)(ip >> 24), (uint8_t)(ip >> 16),
1437814Sgblack@eecs.umich.edu            (uint8_t)(ip >> 8),  (uint8_t)(ip >> 0));
1447777Sgblack@eecs.umich.edu    return stream;
1457777Sgblack@eecs.umich.edu}
1467777Sgblack@eecs.umich.edu
1477777Sgblack@eecs.umich.edustring
1487777Sgblack@eecs.umich.eduIpNetmask::string() const
1497777Sgblack@eecs.umich.edu{
1507777Sgblack@eecs.umich.edu    stringstream stream;
1517777Sgblack@eecs.umich.edu    stream << *this;
1527777Sgblack@eecs.umich.edu    return stream.str();
1537777Sgblack@eecs.umich.edu}
1547777Sgblack@eecs.umich.edu
1557777Sgblack@eecs.umich.edubool
1567777Sgblack@eecs.umich.eduoperator==(const IpNetmask &left, const IpNetmask &right)
1577777Sgblack@eecs.umich.edu{
1587777Sgblack@eecs.umich.edu    return (left.ip() == right.ip()) &&
1597777Sgblack@eecs.umich.edu        (left.netmask() == right.netmask());
1607777Sgblack@eecs.umich.edu}
1617777Sgblack@eecs.umich.edu
1627777Sgblack@eecs.umich.eduostream &
1637777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpNetmask &in)
1647777Sgblack@eecs.umich.edu{
1657777Sgblack@eecs.umich.edu    ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask());
1667777Sgblack@eecs.umich.edu    return stream;
1677777Sgblack@eecs.umich.edu}
1687777Sgblack@eecs.umich.edu
1697777Sgblack@eecs.umich.edustring
1707777Sgblack@eecs.umich.eduIpWithPort::string() const
1717777Sgblack@eecs.umich.edu{
1727777Sgblack@eecs.umich.edu    stringstream stream;
1737777Sgblack@eecs.umich.edu    stream << *this;
1747777Sgblack@eecs.umich.edu    return stream.str();
1757777Sgblack@eecs.umich.edu}
1767777Sgblack@eecs.umich.edu
1777777Sgblack@eecs.umich.edubool
1787777Sgblack@eecs.umich.eduoperator==(const IpWithPort &left, const IpWithPort &right)
1797777Sgblack@eecs.umich.edu{
1807777Sgblack@eecs.umich.edu    return (left.ip() == right.ip()) && (left.port() == right.port());
1817777Sgblack@eecs.umich.edu}
1827777Sgblack@eecs.umich.edu
1837777Sgblack@eecs.umich.eduostream &
1847777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpWithPort &iwp)
1857777Sgblack@eecs.umich.edu{
1867777Sgblack@eecs.umich.edu    ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port());
1877777Sgblack@eecs.umich.edu    return stream;
1887777Sgblack@eecs.umich.edu}
1897777Sgblack@eecs.umich.edu
1901078SN/Auint16_t
1911114SN/Acksum(const IpPtr &ptr)
1921078SN/A{
1931114SN/A    int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
1941114SN/A    return ip_cksum_carry(sum);
1951078SN/A}
1961114SN/A
1971114SN/Auint16_t
1981114SN/A__tu_cksum(const IpPtr &ip)
1991114SN/A{
2001114SN/A    int tcplen = ip->len() - ip->hlen();
2011114SN/A    int sum = ip_cksum_add(ip->payload(), tcplen, 0);
2021114SN/A    sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
2031114SN/A    sum += htons(ip->ip_p + tcplen);
2041114SN/A    return ip_cksum_carry(sum);
2051114SN/A}
2061114SN/A
2071114SN/Auint16_t
2081114SN/Acksum(const TcpPtr &tcp)
2091114SN/A{ return __tu_cksum(IpPtr(tcp.packet())); }
2101114SN/A
2111114SN/Auint16_t
2121114SN/Acksum(const UdpPtr &udp)
2131114SN/A{ return __tu_cksum(IpPtr(udp.packet())); }
2141114SN/A
2151114SN/Abool
2161114SN/AIpHdr::options(vector<const IpOpt *> &vec) const
2171114SN/A{
2181114SN/A    vec.clear();
2191114SN/A
2201114SN/A    const uint8_t *data = bytes() + sizeof(struct ip_hdr);
2211114SN/A    int all = hlen() - sizeof(struct ip_hdr);
2221114SN/A    while (all > 0) {
2231114SN/A        const IpOpt *opt = (const IpOpt *)data;
2241114SN/A        int len = opt->len();
2251114SN/A        if (all < len)
2261114SN/A            return false;
2271114SN/A
2281114SN/A        vec.push_back(opt);
2291114SN/A        all -= len;
2301114SN/A        data += len;
2311114SN/A    }
2321114SN/A
2331114SN/A    return true;
2341114SN/A}
2351114SN/A
2361114SN/Abool
2371114SN/ATcpHdr::options(vector<const TcpOpt *> &vec) const
2381114SN/A{
2391114SN/A    vec.clear();
2401114SN/A
2411114SN/A    const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
2421114SN/A    int all = off() - sizeof(struct tcp_hdr);
2431114SN/A    while (all > 0) {
2441114SN/A        const TcpOpt *opt = (const TcpOpt *)data;
2451114SN/A        int len = opt->len();
2461114SN/A        if (all < len)
2471114SN/A            return false;
2481114SN/A
2491114SN/A        vec.push_back(opt);
2501114SN/A        all -= len;
2511114SN/A        data += len;
2521114SN/A    }
2531114SN/A
2541114SN/A    return true;
2551114SN/A}
2561114SN/A
2571114SN/Abool
2581114SN/ATcpOpt::sack(vector<SackRange> &vec) const
2591114SN/A{
2601114SN/A    vec.clear();
2611114SN/A
2621114SN/A    const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
2631114SN/A    int all = len() - offsetof(tcp_opt, opt_data.sack);
2641114SN/A    while (all > 0) {
2651114SN/A        const uint16_t *sack = (const uint16_t *)data;
2661114SN/A        int len = sizeof(uint16_t) * 2;
2671114SN/A        if (all < len) {
2681114SN/A            vec.clear();
2691114SN/A            return false;
2701114SN/A        }
2711114SN/A
2721114SN/A        vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
2731114SN/A        all -= len;
2741114SN/A        data += len;
2751114SN/A    }
2761114SN/A
2771114SN/A    return false;
2781114SN/A}
2791114SN/A
2805782Ssaidi@eecs.umich.eduint
2815782Ssaidi@eecs.umich.eduhsplit(const EthPacketPtr &ptr)
2825782Ssaidi@eecs.umich.edu{
2835782Ssaidi@eecs.umich.edu    int split_point = 0;
2845782Ssaidi@eecs.umich.edu
2855782Ssaidi@eecs.umich.edu    IpPtr ip(ptr);
2865782Ssaidi@eecs.umich.edu    if (ip) {
2875782Ssaidi@eecs.umich.edu        split_point = ip.pstart();
2885782Ssaidi@eecs.umich.edu
2895782Ssaidi@eecs.umich.edu        TcpPtr tcp(ip);
2905782Ssaidi@eecs.umich.edu        if (tcp)
2915782Ssaidi@eecs.umich.edu            split_point = tcp.pstart();
2925782Ssaidi@eecs.umich.edu
2935782Ssaidi@eecs.umich.edu        UdpPtr udp(ip);
2945782Ssaidi@eecs.umich.edu        if (udp)
2955782Ssaidi@eecs.umich.edu            split_point = udp.pstart();
2965782Ssaidi@eecs.umich.edu    }
2975782Ssaidi@eecs.umich.edu    return split_point;
2985782Ssaidi@eecs.umich.edu}
2995782Ssaidi@eecs.umich.edu
3005782Ssaidi@eecs.umich.edu
3017811Ssteve.reinhardt@amd.com} // namespace Net
302