-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shorthand IPv4Network and IPv6Network #128810
Comments
I'm a first time contributor so if I've missed a step please let me know! Thank you for your time. |
The case you mentioned should be abbreviated as Typically, such behavior in network systems should follow the rules outlined below, if I remember correctly. In other words, the non-zero byte portions are retained based on the subnet mask.
|
Hi James,
Oof you are totally right I can’t believe I missed that. I will correct it
today.
Thanks,
Justin
…On Tue, Jan 14, 2025 at 1:33 AM RUANG (James Roy) ***@***.***> wrote:
>>> network = IPv4Network('192.168.0.0/24')
>>> network.shorthand
'192.168/24'
The case you mentioned should be abbreviated as 192.168.0/24 because the
mask is 24. Is it my misunderstanding of the abbreviation rule?
Typically, such behavior in network systems should follow the rules
outlined below, if I remember correctly. In other words, the non-zero byte
portions are retained based on the subnet mask.
192.0.0.0/8 => 192/8192.1.0.0/16 => 192.1/16192.168.1.0/24 => 192.168.1/24192.168.0.0/24 => 192.168.0/24
—
Reply to this email directly, view it on GitHub
<#128810 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AHP5F7WM5G4SUFPNY5G2PJ32KSVSTAVCNFSM6AAAAABVEDNGQSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKOBZGEZTQMBZGU>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Are "shorthand" IPv{4,6}Network standardized or is it just something that network operators came up with? |
It's standard for IPv4, but I'm not sure about IPv6. The relevant RFC is RFC 4632. Though, I'm not really sure it's right to call it "shorthand"--it's really a notation for subnet masks, not necessarily a short version of the address. (Also, if we're going to support generating the notation from an |
Thank you for the comments! I’ll try to update this tonight and include
parsing into an ip_network from an abbreviated prefix, as well as the fixes
from James. What should we call it if not shorthand?
…On Tue, Jan 14, 2025 at 8:27 AM Peter Bierma ***@***.***> wrote:
It's standard for IPv4, but I'm not sure about IPv6. The relevant RFC is RFC
4632 <https://datatracker.ietf.org/doc/html/rfc4632>. Though, I'm not
really sure it's right to call it "shorthand"--it's really a notation for
subnet masks, not necessarily a short version of the address. (Also, if
we're going to support generating the notation from an IPv4Address object
we should support parsing it into one as well.)
—
Reply to this email directly, view it on GitHub
<#128810 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AHP5F7XH72DN55ZAIITMVJ32KUGDRAVCNFSM6AAAAABVEDNGQSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKOBZHEYDQNZYGA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
To be honest, I like the term "shorthand", It perfectly captures this behavior, this notation is called |
It's not the term "shorthand" that I'm worried about. What I'm worried about is whether this is a standardized notation and feature. If this is not, then we shouldn't include it in the standard library. Now, for IPv4 it seems that it is the case. If it's not the case for IPv6, I would prefer to amend the current PR. |
Note that RFC 4632 is currently in "Best Current Practice" and not in the "Standard Tracks". Since BCP tracks may change in the future and evolve, it's not necessarily something that we want in the standard library. Is there a strong motivation to support shorthand notations (or a use case that cannot be achieved with standard notations)? Maybe we can instead add a comparision function that checks if two representations are equal instead. That way we could have more flexibility in the future. |
Bikeshedding: Google is saying that IPv6 supports CIDR notation as well, but yeah, being a "best practice" rather than a standard isn't convincing. |
A thought I had: instead of explicitly adding cases for this, how about we add some sort of converter protocol for IP addresses? So something like: class IPConverter:
def parse_to_ipv4(self, text: str) -> IPv4Address:
...
def convert_from_ipv4(self, address: IPv4Address) -> str:
...
def parse_to_ipv6(self, text: str) -> IPv4Address:
...
def convert_from_ipv6(self, address: IPv6Address) -> str:
...
ipaddress.add_converter(IPConverter()) Then, for this case, we could expose an optional |
How useful would it be if we only have one converter? I would prefer standalone functions rather than a namespace like this. OTOH, when I fixed |
No idea, I'm thinking out loud. We could define a converter for every notation, and just keep the ones that currently exist enabled by default. |
Thank you everyone for your time and comments, they are very insightful. My proposal would be to change this feature and amend the PR as follows: I will fix the issue identified by rruuaanng (great catch!), to bring the proposal in line with RFC 4632, which was identified by ZeroIntensity. ZeroIntensity also brings up a good point, that parsing from this shorthand format defined by RFC 4632 should be supported as well. I will do my best to add that. As far as the naming concerns go, I like ZeroIntensity’s suggestion of cidr_shorthand. I do wonder if the cidr_ part is not a bit redundant though, since this can only be called on a CIDR (IPv4Network or IPv6Network), or am I wrong? Picnixz and ZeroIntensity both point out that IPv6 “shorthand” is not standardized. I agree with them that the IPv6 version should be removed in that case. However, my thought is that we still have a property called cidr_shorthand on the IPv6Network, and just return the string of the class. The reason being that without this, every single call to cidr_shorthand for a generic ip_network would need to be wrapped in some type of try except in case the ip_network happened to be an IPv6Network, which I don’t think makes much sense. Picnixz and ZeroIntensity have also expressed concern that RFC 4632 is the “best current practice” and not in the “Standard Tracks”. Thank you for this feedback. While the RFC is not in the standard tracks, in my experience, the full CIDR notation is very rarely written out when people are familiar with CIDR notation. The shorthand is extremely common in my opinion. From a practical perspective, writing out 1.2/16 is much faster, shorter, and more readable than 1.2.0.0/16 (for people that are familiar with CIDRs), which is why the shorthand is the default notation used by many. This is especially true when drawing diagrams of prefixes sent across autonomous systems, where a long prefix makes the diagram very hard to read. Given how common it is I figured it made sense for this to be supported. ZeroIntensity also brought up an interesting idea of a converter protocol for IP addresses. I agree with picnixz that I prefer a standalone function in this case. I think that offers the easiest use from a user perspective. Just my opinion though :) I’ll do my best to fix the PR although I need another day or two. Thanks again for all the feedback and happy to continue to iterate on this based on further discussion. |
Upon further research and consulting some BGP researchers (Thanks Dr. Amir Herzberg!) it appears that the .with_prefixlen method returns the compressed version of the IPv6 prefix, in line with RFC 5952. This is essentially the cidr_shorthand notation used for IPv6. So I think it likely makes sense to return self.with_prefixlen for the .cidr_shorthand method in the IPv6Network. |
Considering that I had no idea that the CIDR shorthand was already supported by IPv6, perhaps it makes sense to add this to the documentation with a link to the RFC. I'm also quite confused in regards to "with_prefixlen" now. It's not really documented either. In the IPv6Network class, it returns the shortest form of the prefix, in CIDR notation. But in the IPv4Network class, it returns the exact prefix, in CIDR notation - a different behavior than in IPv6. Perhaps the "with_prefixlen of IPv4Network should have been returning the compressed version, and was not? Even if that's the case, I still think it makes sense to do this as a separate method (cidr_shorthand) to avoid any backwards compatibility breaking changes. |
Looking at the source code for "with_prefixlen", I think this is a weird mismatch in behavior. IPv6 returns the compressed version, while IPv4 does not. Both functions are undocumented in the code, and the main docs only have this to say about IPv4, while the IPv6 versions are undocumented: https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Interface.with_prefixlen Also this specific example has an invalid prefix with host bits set unless I am misunderstanding. That should probably also be fixed. I'll open a separate PR for that when this one is done. |
It's not redundant because we don't know how it can evolve in the future. It's better to precise. Remember that we are a standard library, not an application, so we try to follow standards as much as possible.
EDIT: Forget about my answer, I was wrong.
I would like to see numbers to reflect that claim. How many usage of this pattern can you find on GitHub for instance? what about Rust? (AFAICT, https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html does not CIDR shorthand) We need some convincing use cases to include something in the standard library (the reason being is that once a feature is in the standard library, it's more or less frozen and we need to maintain it; we can't change the implementation since it could cause breaking changes so we need to be careful). Honestly, I've never seen CIDR shorthand. Applications may decide to render a shorthand notation or not, but should the standard library decides to follow BCP and nost ST? I'm not really sure (for instance, we rejected RFC 9562 implementations (UUID v6-8) some years ago because it was not in the standard tracks). Now, we also seem to rely on Proposed Standards and not Standard Tracks, so it should be fine (maybe?)
I agree with that.
EDIT: Forget about my answer, I was wrong as well. Compressed IPv6 should also return compressed form here (or should be documented as not returning compressed forms...).
What I see is that:
Let's ask the original code author @ncoghlan |
Cidr_shorthand as the name sounds good to me. As far as IPv6Network’s not having that attribute - I don’t see why this would be the case. To me, the IPv6Network already have a function that returns the CIDR shorthand. While it’s undocumented, this is how with_prefixlen functions. In terms of usage statistics, I haven’t parsed all github repos, but there is an RFC for it (4632). I would say that the most convincing argument is that IPv6Network already does this by default, it’s just strange that IPv4Networks does not, for the same function name (the "with_prefixlen" function). Maybe I’m not understanding something here but I don’t see why CIDR shorthand would be supported and the default in IPv6 networks but not in IPv4 networks. Definitely if the original author could provide some context that would be great. I'm going to wait on further modifications to the PR since it sounds like this feature may be rejected. |
I think it's mainly because the notion of a compressed IPv4 is not defined in the RFC actually. I can see https://datatracker.ietf.org/doc/html/rfc4632#section-3.1 which explains the prefix notation but I don't see the shorthand notation. For IPv6, it's explicitly defined (this may be the reason why we don't have this for IPv4 actually!) |
I've edited my previous answer because I was wrong:
Both IPv4 and IPv6 have the notion of CIDR, but IPv4 does not define what a "compressed" form is.
Different behaviour so we sahould document it. We should be able to return non-compressed forms as well I think and compressed forms when they are well-defined. Now once we decide whether IPv4 shorthand notation can be well-defined or not, then we can move forward. However, I have no answer on this question. For IPv6, omitting parts between |
You're right. I took the RFC at face value, but reading it, while it implies the possibility of an abbreviated notation, it doesn't mention it explicitly. That explains why IPv4 has different behavior. Your comments have all been very insightful and I'm sorry you've spent your time on a PR that ultimately I think should not go through, I should have done better research before and I definitely understand this process a lot better. I think my plan from here is:
Unless anyone is opposed I'm going to close this ticket and the PR |
You're welcome! Feel free to open a new issue and a PR for the docs. It would be much appreciated!
If you have such contacts, or if they can provide confirmation whether there is a standardized way to defined IPv4 shorthands, I would be happy to continue the discussion. |
Thanks a bunch! I'll open a new issue and PR for the docs in the next day or two. |
Feature or enhancement
Proposal:
IPv4Networks and IPv6Networks are often written in shorthand by network operators. For example, 1.2.0.0/16 would be written as 1.2/16. I've added a very simple .shorthand function (along with a few simple tests) to these networks in the hopes that this can be a supported feature.
For the IPv4Network:
For the IPv6Network:
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response
Linked PRs
The text was updated successfully, but these errors were encountered: