Params: Add parameter types for IP addresses in various forms.
authorGabe Black <gblack@eecs.umich.edu>
Tue, 23 Nov 2010 20:54:43 +0000 (15:54 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Tue, 23 Nov 2010 20:54:43 +0000 (15:54 -0500)
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
src/base/inet.hh
src/python/m5/params.py
src/python/m5/util/convert.py
src/python/swig/inet.i

index 1a280e993041159894544d1345c3f0395dd7d026..93501018ef37fbe3e04dfa7b204ed58af316be4d 100644 (file)
@@ -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)
 {
index ef9a7d81cc03a4e8bc589bf6de1defa4b9c37737..12387087b82ba1cd154a7d2e914cee53999b4360 100644 (file)
@@ -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
 {
index 33ac742c8d6729c8a6fc1e9099eae9b67bb70bba..4e646d3f5faf0f4ae64b23b4594823df8aa61197 100644 (file)
@@ -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',
index bb9e3e1f1feca7d1ab339979cb2878b4be250aa3..5d4ae92b9b937d6f41d1785c4eca43c978ccf906 100644 (file)
@@ -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))
index e92b445977a50a382230364c7c91167e7c3d70a0..bad5488e681822b3cb9b80b0b05c8800fb224eee 100644 (file)
@@ -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);
+};
+
 }