]> git.ipfire.org Git - people/ms/libloc.git/commitdiff
importer: Parse aggregated networks
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 5 Mar 2022 11:56:40 +0000 (11:56 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 5 Mar 2022 11:56:40 +0000 (11:56 +0000)
This patch adds code to parse any aggregated networks.

Bird does not automatically show the last ASN of the path, but we can
collect all networks that we can see without any ASN and perform
"show route <network> all" on them to gather this information.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/python/location-importer.in

index fe13482e75961e04c5a895219bfe77b4d166f815..e1b9aabdeaf47ea26485d08009c0204347bb415d 100644 (file)
@@ -978,10 +978,12 @@ class CLI(object):
 
        def _handle_update_announcements_from_bird(self, server):
                # Pre-compile the regular expression for faster searching
-               route = re.compile(b"^\s(.+?)\s+.+?\[AS(.*?).\]$")
+               route = re.compile(b"^\s(.+?)\s+.+?\[(?:AS(.*?))?.\]$")
 
                log.info("Requesting routing table from Bird (%s)" % server)
 
+               aggregated_networks = []
+
                # Send command to list all routes
                for line in self._bird_cmd(server, "show route"):
                        m = route.match(line)
@@ -992,13 +994,47 @@ class CLI(object):
                        # Fetch the extracted network and ASN
                        network, autnum = m.groups()
 
+                       # Decode into strings
+                       if network:
+                               network = network.decode()
+                       if autnum:
+                               autnum = autnum.decode()
+
+                       # Collect all aggregated networks
+                       if not autnum:
+                               log.debug("%s is an aggregated network" % network)
+                               aggregated_networks.append(network)
+                               continue
+
                        # Insert it into the database
                        self.db.execute("INSERT INTO announcements(network, autnum) \
                                VALUES(%s, %s) ON CONFLICT (network) DO \
                                UPDATE SET autnum = excluded.autnum, last_seen_at = CURRENT_TIMESTAMP",
-                               network.decode(), autnum.decode(),
+                               network, autnum,
                        )
 
+               # Process any aggregated networks
+               for network in aggregated_networks:
+                       log.debug("Processing aggregated network %s" % network)
+
+                       # Run "show route all" for each network
+                       for line in self._bird_cmd(server, "show route %s all" % network):
+                               # Try finding the path
+                               m = re.match(b"\s+BGP\.as_path:.* (\d+) {\d+}$", line)
+                               if m:
+                                       # Select the last AS number in the path
+                                       autnum = m.group(1).decode()
+
+                                       # Insert it into the database
+                                       self.db.execute("INSERT INTO announcements(network, autnum) \
+                                               VALUES(%s, %s) ON CONFLICT (network) DO \
+                                               UPDATE SET autnum = excluded.autnum, last_seen_at = CURRENT_TIMESTAMP",
+                                               network, autnum,
+                                       )
+
+                                       # We don't need to process any more
+                                       break
+
        def _handle_update_announcements_from_telnet(self, server):
                # Pre-compile regular expression for routes
                route = re.compile(b"^\*[\s\>]i([^\s]+).+?(\d+)\si\r\n", re.MULTILINE|re.DOTALL)