From b3de4855c3dba9df80cca4540c4ee6625c26f9e1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 23 Nov 2010 15:54:43 -0500 Subject: Params: Add parameter types for IP addresses in various forms. New parameter forms are: IP address in the format "a.b.c.d" where a-d are from decimal 0 to 255. IP address with netmask which is an IP followed by "/n" where n is a netmask length in bits from decimal 0 to 32 or by "/e.f.g.h" where e-h are from decimal 0 to 255 and which is all 1 bits followed by all 0 bits when represented in binary. These can also be specified as an integral IP and netmask passed in separately. IP address with port which is an IP followed by ":p" where p is a port index from decimal 0 to 65535. These can also be specified as an integral IP and port value passed in separately. --- src/base/inet.cc | 67 ++++++++++++++++++ src/base/inet.hh | 59 ++++++++++++++++ src/python/m5/params.py | 158 ++++++++++++++++++++++++++++++++++++++++++ src/python/m5/util/convert.py | 49 +++++++++++++ src/python/swig/inet.i | 19 +++++ 5 files changed, 352 insertions(+) diff --git a/src/base/inet.cc b/src/base/inet.cc index 1a280e993..93501018e 100644 --- a/src/base/inet.cc +++ b/src/base/inet.cc @@ -117,6 +117,73 @@ operator<<(ostream &stream, const EthAddr &ea) return stream; } +string +IpAddress::string() const +{ + stringstream stream; + stream << *this; + return stream.str(); +} + +bool +operator==(const IpAddress &left, const IpAddress &right) +{ + return left.ip() == right.ip(); +} + +ostream & +operator<<(ostream &stream, const IpAddress &ia) +{ + uint32_t ip = ia.ip(); + ccprintf(stream, "%x.%x.%x.%x", + (uint8_t)(ip >> 0), (uint8_t)(ip >> 8), + (uint8_t)(ip >> 16), (uint8_t)(ip >> 24)); + return stream; +} + +string +IpNetmask::string() const +{ + stringstream stream; + stream << *this; + return stream.str(); +} + +bool +operator==(const IpNetmask &left, const IpNetmask &right) +{ + return (left.ip() == right.ip()) && + (left.netmask() == right.netmask()); +} + +ostream & +operator<<(ostream &stream, const IpNetmask &in) +{ + ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask()); + return stream; +} + +string +IpWithPort::string() const +{ + stringstream stream; + stream << *this; + return stream.str(); +} + +bool +operator==(const IpWithPort &left, const IpWithPort &right) +{ + return (left.ip() == right.ip()) && (left.port() == right.port()); +} + +ostream & +operator<<(ostream &stream, const IpWithPort &iwp) +{ + ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port()); + return stream; +} + uint16_t cksum(const IpPtr &ptr) { diff --git a/src/base/inet.hh b/src/base/inet.hh index ef9a7d81c..12387087b 100644 --- a/src/base/inet.hh +++ b/src/base/inet.hh @@ -147,6 +147,65 @@ class EthPtr /* * 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 { diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 33ac742c8..4e646d3f5 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -675,6 +675,163 @@ class EthernetAddr(ParamValue): def ini_str(self): return self.value +# When initializing an IpAddress, pass in an existing IpAddress, a string of +# the form "a.b.c.d", or an integer representing an IP. +class IpAddress(ParamValue): + cxx_type = 'Net::IpAddress' + + @classmethod + def cxx_predecls(cls, code): + code('#include "base/inet.hh"') + + @classmethod + def swig_predecls(cls, code): + code('%include "python/swig/inet.i"') + + def __init__(self, value): + if isinstance(value, IpAddress): + self.ip = value.ip + else: + try: + self.ip = convert.toIpAddress(value) + except TypeError: + self.ip = long(value) + self.verifyIp() + + def verifyIp(self): + if self.ip < 0 or self.ip >= (1 << 32): + raise TypeError, "invalid ip address %#08x" % ip + + def getValue(self): + from m5.internal.params import IpAddress + return IpAddress(self.ip) + + def ini_str(self): + return self.ip + +# When initializing an IpNetmask, pass in an existing IpNetmask, a string of +# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as +# positional or keyword arguments. +class IpNetmask(IpAddress): + cxx_type = 'Net::IpNetmask' + + @classmethod + def cxx_predecls(cls, code): + code('#include "base/inet.hh"') + + @classmethod + def swig_predecls(cls, code): + code('%include "python/swig/inet.i"') + + def __init__(self, *args, **kwargs): + def handle_kwarg(self, kwargs, key, elseVal = None): + if key in kwargs: + setattr(self, key, kwargs.pop(key)) + elif elseVal: + setattr(self, key, elseVal) + else: + raise TypeError, "No value set for %s" % key + + if len(args) == 0: + handle_kwarg(self, kwargs, 'ip') + handle_kwarg(self, kwargs, 'netmask') + + elif len(args) == 1: + if kwargs: + if not 'ip' in kwargs and not 'netmask' in kwargs: + raise TypeError, "Invalid arguments" + handle_kwarg(self, kwargs, 'ip', args[0]) + handle_kwarg(self, kwargs, 'netmask', args[0]) + elif isinstance(args[0], IpNetmask): + self.ip = args[0].ip + self.netmask = args[0].netmask + else: + (self.ip, self.netmask) = convert.toIpNetmask(args[0]) + + elif len(args) == 2: + self.ip = args[0] + self.netmask = args[1] + else: + raise TypeError, "Too many arguments specified" + + if kwargs: + raise TypeError, "Too many keywords: %s" % kwargs.keys() + + self.verify() + + def verify(self): + self.verifyIp() + if self.netmask < 0 or self.netmask > 32: + raise TypeError, "invalid netmask %d" % netmask + + def getValue(self): + from m5.internal.params import IpNetmask + return IpNetmask(self.ip, self.netmask) + + def ini_str(self): + return "%08x/%d" % (self.ip, self.netmask) + +# When initializing an IpWithPort, pass in an existing IpWithPort, a string of +# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. +class IpWithPort(IpAddress): + cxx_type = 'Net::IpWithPort' + + @classmethod + def cxx_predecls(cls, code): + code('#include "base/inet.hh"') + + @classmethod + def swig_predecls(cls, code): + code('%include "python/swig/inet.i"') + + def __init__(self, *args, **kwargs): + def handle_kwarg(self, kwargs, key, elseVal = None): + if key in kwargs: + setattr(self, key, kwargs.pop(key)) + elif elseVal: + setattr(self, key, elseVal) + else: + raise TypeError, "No value set for %s" % key + + if len(args) == 0: + handle_kwarg(self, kwargs, 'ip') + handle_kwarg(self, kwargs, 'port') + + elif len(args) == 1: + if kwargs: + if not 'ip' in kwargs and not 'port' in kwargs: + raise TypeError, "Invalid arguments" + handle_kwarg(self, kwargs, 'ip', args[0]) + handle_kwarg(self, kwargs, 'port', args[0]) + elif isinstance(args[0], IpWithPort): + self.ip = args[0].ip + self.port = args[0].port + else: + (self.ip, self.port) = convert.toIpWithPort(args[0]) + + elif len(args) == 2: + self.ip = args[0] + self.port = args[1] + else: + raise TypeError, "Too many arguments specified" + + if kwargs: + raise TypeError, "Too many keywords: %s" % kwargs.keys() + + self.verify() + + def verify(self): + self.verifyIp() + if self.port < 0 or self.port > 0xffff: + raise TypeError, "invalid port %d" % self.port + + def getValue(self): + from m5.internal.params import IpWithPort + return IpWithPort(self.ip, self.port) + + def ini_str(self): + return "%08x:%d" % (self.ip, self.port) + time_formats = [ "%a %b %d %H:%M:%S %Z %Y", "%a %b %d %H:%M:%S %Z %Y", "%Y/%m/%d %H:%M:%S", @@ -1317,6 +1474,7 @@ __all__ = ['Param', 'VectorParam', 'Int32', 'UInt32', 'Int64', 'UInt64', 'Counter', 'Addr', 'Tick', 'Percent', 'TcpPort', 'UdpPort', 'EthernetAddr', + 'IpAddress', 'IpNetmask', 'IpWithPort', 'MemorySize', 'MemorySize32', 'Latency', 'Frequency', 'Clock', 'NetworkBandwidth', 'MemoryBandwidth', diff --git a/src/python/m5/util/convert.py b/src/python/m5/util/convert.py index bb9e3e1f1..5d4ae92b9 100644 --- a/src/python/m5/util/convert.py +++ b/src/python/m5/util/convert.py @@ -248,3 +248,52 @@ def toMemorySize(value): return long(value[:-1]) raise ValueError, "cannot convert '%s' to memory size" % value + +def toIpAddress(value): + if not isinstance(value, str): + raise TypeError, "wrong type '%s' should be str" % type(value) + + bytes = value.split('.') + if len(bytes) != 4: + raise ValueError, 'invalid ip address %s' % value + + for byte in bytes: + if not 0 <= int(byte) <= 0xff: + raise ValueError, 'invalid ip address %s' % value + + return (int(bytes[0]) << 24) | (int(bytes[1]) << 16) | \ + (int(bytes[2]) << 8) | (int(bytes[3]) << 0) + +def toIpNetmask(value): + if not isinstance(value, str): + raise TypeError, "wrong type '%s' should be str" % type(value) + + (ip, netmask) = value.split('/') + ip = toIpAddress(ip) + netmaskParts = netmask.split('.') + if len(netmaskParts) == 1: + if not 0 <= int(netmask) <= 32: + raise ValueError, 'invalid netmask %s' % netmask + return (ip, int(netmask)) + elif len(netmaskParts) == 4: + netmaskNum = toIpAddress(netmask) + if netmaskNum == 0: + return (ip, 0) + testVal = 0 + for i in range(32): + testVal |= (1 << (31 - i)) + if testVal == netmaskNum: + return (ip, i + 1) + raise ValueError, 'invalid netmask %s' % netmask + else: + raise ValueError, 'invalid netmask %s' % netmask + +def toIpWithPort(value): + if not isinstance(value, str): + raise TypeError, "wrong type '%s' should be str" % type(value) + + (ip, port) = value.split(':') + ip = toIpAddress(ip) + if not 0 <= int(port) <= 0xffff: + raise ValueError, 'invalid port %s' % port + return (ip, int(port)) diff --git a/src/python/swig/inet.i b/src/python/swig/inet.i index e92b44597..bad5488e6 100644 --- a/src/python/swig/inet.i +++ b/src/python/swig/inet.i @@ -42,5 +42,24 @@ struct EthAddr EthAddr(const uint8_t ea[6]); EthAddr(const std::string &addr); }; + +struct IpAddress +{ + IpAddress(); + IpAddress(const uint32_t __addr); +}; + +struct IpNetmask : IpAddress +{ + IpNetmask(); + IpNetmask(const uint32_t __addr, const uint8_t __netmask); +}; + +struct IpWithPort : IpAddress +{ + IpWithPort(); + IpWithPort(const uint32_t __addr, const uint16_t __port); +}; + } -- cgit v1.2.3