From 989165fe9e898190f4d8ddf2c5d92c8ce1187ccd Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Sun, 27 Sep 2009 19:38:05 +0000 Subject: [PATCH] Update from Peter Moody. --- pep-3144.txt | 131 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 37 deletions(-) diff --git a/pep-3144.txt b/pep-3144.txt index 9331b48d3..8e04caf05 100644 --- a/pep-3144.txt +++ b/pep-3144.txt @@ -31,40 +31,63 @@ Motivation: Rationale: - - ipaddr was designed with the goal of abstracting out as much of the common - functionality as possible. As mentioned earlier, the similarities between - addresses and networks, IPV6 and IPV4 allows much code to be reused since - python allows for easy (and clean) multiple inheritance. Methods which are - specific to IPV4 or IPV6, addresses or networks are inherited from - appropriately named classes (Basev4, Basev6, BaseNet, BaseIP, etc) to - provide the full functionality of IPv4Address, IPv4Network, IPv6Address and - IPv6Network. + ipaddr was designed with a few basic principals in mind: + + - IPv4 and IPv6 objects are distinct. + - IP addresses and IP networks are distinct. + - the library should be useful and the assumptions obvious to the network + programmer. + - IP networks should be treated as lists (as opposed to some other + python intrinsic) in so far as it makes sense. + - the library should be lightweight and fast without sacrificing + expected functionality. + - Distinct IPV4 and IPV6 objects. While there are many similarities, IPV4 and IPV6 objects are fundamentally different. The similarities allow for easy abstraction of certain operations which affect the bits from both in the same manner, but their - differences mean attempts to combine them into one object would be like - trying to force a round peg into a square hole (or visa versa). + differences mean attempts to combine them into one object yield unexpected + results. According to Vint Cerf, "I have seen a substantial amount of + traffic about IPv4 and IPv6 comparisons and the general consensus is that + these are not comparable." (Vint Cerf [2]). For python versions >= 3.0, + this means that (<, >, <=, >=) comparison operations between IPv4 and IPv6 + objects raise a TypeError per the Ordering Comparisons [3]. - Distinct network and address objects. - Many people think of IP addresses and IP networks as synonymous, while they - are however, distinct. An IPV4 address is a single 32 bit number while the - IPV4 address assigned to a networked computer is a 32 bit address and - associated network. Similarly, an IPV6 address is a 128 bit number while - an IPV6 address assigned to a networked computer is a 128 bit number and - associated network information. The similarities leads to easy abstraction - of some methods and properties, but there are obviously a number of - address/network specific properties which require they be distinct. For - instance, IP networks contain network address (the base address of the - network), broadcast addresses (the upper end of the network, also the - address to which every machine on a given network is supposed listen, hence - the name broadcast), supernetworks and subnetworks, etc. The individual - property addresses in an IP network obviously don't have the same - properties, they're simply 32 or 128 bit numbers. + An IPV4 address is a single 32 bit number while the IPV4 address assigned + to a networked computer is a 32 bit address and associated network. + Similarly, an IPV6 address is a 128 bit number while an IPV6 address + assigned to a networked computer is a 128 bit number and associated network + information. The similarities leads to easy abstraction of some methods + and properties, but there are obviously a number of address/network + specific properties which require they be distinct. For instance, IP + networks contain a network address (the base address of the network), + broadcast address (the upper end of the network, also the address to + which every machine on a given network is supposed listen, hence the name + broadcast), supernetworks and subnetworks, etc. The individual property + addresses in an IP network obviously don't have the same properties, + they're simply 32 or 128 bit numbers. + + - Principal of least confusion for network programmers. + + It should be understood that, above all, this module is designed with the + network administrator in mind. In practice, this means that a number of + assumptions are made with regards to common usage and the library prefers + the usefulness of accepted practice over strict adherence to RFCs. For + example, ipaddr accepts '192.168.1.1/24' as a network definition because + this is a very common way of describing an address + netmask despite the + fact that 192.168.1.1 is actually an IP address on the network + 192.168.1.0/24. Strict adherence would require that networks have all of + the host bits masked to zero, which would require two objects to describe + that IP + network. In practice, a looser interpretation of a network is + a very useful if common abstraction, so ipaddr prefers to make this + available. For the developer who is concerned with strict adherence, + ipaddr provides an optional 'strict' boolean argument to the + IPv(4|6)Network constructors which guarantees that all host bits are masked + down. - Treat network elements as lists (in so far as it's possible). @@ -84,7 +107,7 @@ Rationale: While some network programmers will undoubtedly want more than this library provides, keeping the functionality to strictly what's required from a IP address manipulation module is critical to keeping the code fast, easily - comprehensible and extensible. I've tried to provide enough options in + comprehensible and extensible. It is a goal to provide enough options in terms of functionality to allow the developer to easily do their work without needlessly cluttering the library. Finally, It's important to note that this design doesn't prevent subclassing or otherwise extending to meet @@ -114,15 +137,15 @@ Specification: addresses and networks, both IPv4 and IPv6. In short, there is common functionality shared between (ipaddr class names in parentheses): - 1. all IP addresses and networks, both IPv4 and IPv6. (IPAddrBase) + 1. all IP addresses and networks, both IPv4 and IPv6. (_IPAddrBase) - 2. all IP addresses of both versions. (BaseIP) + 2. all IP addresses of both versions. (_BaseIP) - 3. all IP networks of both version. (BaseNet) + 3. all IP networks of both version. (_BaseNet) - 4. all IPv4 objects, both addresses and networks. (BaseV4) + 4. all IPv4 objects, both addresses and networks. (_BaseV4) - 5. all IPv6 objects, both addresses and networks. (BaseV6) + 5. all IPv6 objects, both addresses and networks. (_BaseV6) Seeing this as a clear hierarchy is important for recognizing how much code is common between the four main classes. For this reason, ipaddr uses @@ -137,9 +160,9 @@ Specification: might guess, return the appropriately typed address or network objects for the given argument. - Finally, there is no meaningful natural ordering between IPv4 and IPv6 - addresses ("these protocols are ships-in-the-night"), so rather than invent - a standard, ipaddr follows Ordering Comparisons [2] and returns a TypeError + Finally, as mentioned earlier, there is no meaningful natural ordering + between IPv4 and IPv6 addresses and networks [2]. Rather than invent a + standard, ipaddr follows Ordering Comparisons and returns a TypeError when asked to compare objects of differing IP versions. In practice, there are many ways a programmer may wish to order the addresses, so this this shouldn't pose a problem for the developer who can easily write: @@ -167,7 +190,9 @@ Specification: In [1]: IPNetwork('1.1.1.1').with_hostmask Out[1]: '1.1.1.1/0.0.0.0' - the same applies to IPv6 + the same applies to IPv6. It should be noted that netmasks and hostmasks + are not commonly used in IPv6, the methods exist for compatibility with + IPv4. - Lazy evaluation combined with aggressive caching of network elements. @@ -308,17 +333,49 @@ Specification: (the same methods exist for IPv4 networks and addresses, but they're just stubs for returning the normal __str__ representation). + - Most other common operations. + + It is a design goal to support all of the common operation expected from + an IP address manipulation module. As such, finding supernets, subnets, + address and network containment etc are all supported. Reference Implementation: A reference implementation is available at: - http://ipaddr-py.googlecode.com/svn/branches/2.0.x + http://ipaddr-py.googlecode.com/svn/trunk References: [1] http://bugs.python.org/issue3959 - [2] http://docs.python.org/dev/3.0/whatsnew/3.0.html#ordering-comparisons + [2] Appealing to authority is a logical fallacy, but Vint Cerf is an + an authority who can't be ignored. Full text of the email follows: + + """ + I have seen a substantial amount of traffic about IPv4 and IPv6 + comparisons and the general consensus is that these are not comparable. + + If we were to take a very simple minded view, we might treat these as + pure integers in which case there is an ordering but not a useful one. + + In the IPv4 world, "length" is important because we take longest (most + specific) address first for routing. Length is determine by the mask, + as you know. + + Assuming that the same style of argument works in IPv6, we would have + to conclude that treating an IPv6 value purely as an integer for + comparison with IPv4 would lead to some really strange results. + + All of IPv4 space would lie in the host space of 0::0/96 prefix of + IPv6. For any useful interpretation of IPv4, this is a non-starter. + + I think the only sensible conclusion is that IPv4 values and IPv6 values + should be treated as non-comparable. + + Vint + """ + + [3] http://docs.python.org/dev/3.0/whatsnew/3.0.html#ordering-comparisons Copyright: