Package: cidr-bottle
CIDR-BottleCIDR-Bottle is yet another implementation of a Patricia Trie for handling network routing information (such as ROAs & Routing Tables) for reconciliation.
However, unlike other implementations it supports both sub-tree checking and longest-prefix matching.CIDR-Bottle was designed specifically to be used for reconciling RIR Allocation & Assignment records with actual BGP Announcements.
It isn't designed to be the fastest (it's written in pure python), but it should be the most full-featured implementation.
That said, unless you're writing a routing engine in python (in which case I'd be really interested to know why), speed shouldn't be a significant issue.DependenciesCIDR-ManThwip, Thwip!UsageInitialisationBy default, a CIDR-Bottle is in IPv4 mode, to use IPv6 mode you must supply an IPv6 CIDR.The root Bottle does not need to be the entire IP space, it can be any subnet.fromcidr_bottleimportBottlefromipaddressimportIPv4Network,IPv6Network## Defaults to IPv4root=Bottle()# 0.0.0.0/0## IPv6 mode is initialised by passing an IPv6 CIDR (either as an instance of ipaddress.IPv6Network)root6=Bottle(prefix=IPv6Network("::/0"))# ::/0## Supports detached (not starting at either 0.0.0.0/0 or ::/0) rootsdetached_root=Bottle(prefix=IPv4Network("198.51.100.0/24"))Racking a Bottle (Inserting a node)## Supports insert with strroot.insert("198.51.100.0/24")## Supports insert with instances of ipaddress.IPv4Networkroot.insert(IPv4Network("198.51.100.0/24"))## Supports insert with instances of ipaddress.IPv6Networkroot.insert(IPv6Network("2001:db8::/48"))## Supports attaching any json serializable objects to nodes **This is important for future planned releases**root.insert("198.51.100.0/24",{"example":"dict"})root.insert("198.51.100.0/24","string example")## Supports automatic aggregation on insert.root.insert(CIDR("192.0.2.128/25"),value="a")root.insert(CIDR("192.0.2.0/25"),value="b",aggregate=True)root.insert(CIDR("192.0.3.0/24"),value="c",aggregate=True)ifroot.get(CIDR("192.0.2.0/23")).value=="c":## This will evaluate as True as the two /25's will trigger the creation of the /24 and the addition of the other adjacent /24## will trigger the creation of the /23## Supports dict-style indexingroot["198.51.100.0/24"]="string example"Note: Settingaggregate=Truewill (ifnode.parent.leftandnode.parent.rightare populated) insert the node as normal, automatically set the parent object topassing=False,
and copy thevaluefrom the current insert to theparent.Contains CIDR?ReturnsTruewhere there is a covering prefix, otherwise false.NOTE: This means that it returns true 100% of the time when the root is0.0.0.0/0or::/0if"198.51.100.0/24"inroot:## do something### orifroot.contains("198.51.100.0/24"):## do somethingYou can enforce exact matches by passingexact=Trueto thecontainsmethod.ifnotroot.contains("198.51.100.128/25",exact=True):## do somethingDrinking a Bottle (Get node)This will return a matching covering prefix if present.
In the case of a detached root, this means that it can returnNoneif no such covering prefix exists.NOTE: This is longest prefix matchingprint(root["198.51.100.0/24"])### orprint(root.get("198.51.100.0/24"))Similar to the.contains(...)method, you can enforce exact matches by passingexact=Trueto thegetmethod.
This will raise aKeyErrorif there is no exact match.print(root.get("198.51.100.128/25"),exact=True)# will raise a KeyError("no exact match found")Children / Sub-Tree checkingWith CIDR-Bottle you can retrieve all the defined children of a bottle(node).root.insert("198.51.100.0/25")root.insert("198.51.100.128/25")print(root["198.51.100.0/24"].children())Smashing bottles (Deleting Nodes)Deleting an edge node removes it completely.Deleting an intermediate node, converts it into a "passing" node, and does not affect any descendants of that node.delroot["198.51.100.0/24"]### orroot.delete("198.51.100.0/24")More SpeedIf you want to squeeze out every last drop of performance and don't mind the limitation of being forced to useCIDR-Man'sCIDRthen you can useFastBottleinstead ofBottle.Installation (from pip):pipinstallcidr_bottleInstallation (from source):gitclonehttps://gitlab.com/geoip.network/cidr_bottle
poetryinstall