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