Skip to content

Use trie in merge process#123

Open
jurraca wants to merge 5 commits into
asmap:masterfrom
jurraca:add-trie-merge
Open

Use trie in merge process#123
jurraca wants to merge 5 commits into
asmap:masterfrom
jurraca:add-trie-merge

Conversation

@jurraca

@jurraca jurraca commented Feb 11, 2026

Copy link
Copy Markdown
Collaborator

Use the trie implementation in the merge process, replacing the concurrent, chunked, map-based process.

It turns out there was a bug in our implementation. When we called contains_row to check whether a network was included in the base, it only checks whether that candidate / incoming network is a subnet. But it could also be a super-net, i.e. a shorter prefix. In that case both would exist in the merged output, but would be logically conflicting; we want to consider the base (RPKI) entry as the valid one, and reject the candidate. 5b0eea3 ensures we never overwrite base/RPKI entries, whether the candidate is a subnet or supernet of an existing entry.

Running a reproduction run against the latest collab run, the new final_result file is 3254 entries longer. A diff of the original final_result and the new one gives 15699 entries (1% of total), 95% (15003) of which were previously unassigned. This sounds about right, because we keep the RPKI entries which are often most specific. I'm not sure though.
The count of entries and file size stay about the same, as does the encoded (filled or unfilled) file size.

Minimal test changes, probably should add some edge case testing, but the merge tests pass without changes.

Overall, this makes the merge code simpler and removes some dependencies. We can probably remove pandas entirely next with a few more changes. It also speeds up the merge process.

However this will break our reproducibility CI check.

@fjahr fjahr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out there was a bug in our implementation. When we called contains_row to check whether a network was included in the base, it only checks whether that candidate / incoming network is a subnet. But it could also be a super-net, i.e. a shorter prefix. In that case both would exist in the merged output, but would be logically conflicting; we want to consider the base (RPKI) entry as the valid one, and reject the candidate. 5b0eea3 ensures we never overwrite base/RPKI entries, whether the candidate is a subnet or supernet of an existing entry.

If I understand correctly what you are saying I don't think this is a bug. When we have overlapping coverage in our resulting asmap we use the most precise (longest) prefix for the ASN. If there is an overlapping, shorter entry we only use it for the additional coverage that it gets us aside from the one we got from the longer one. So these supernets never "overwrite" the RPKI coverage, they only add coverage where RPKI didn't apply. But maybe there is a misunderstanding about the issue on my side and an example might help, I didn't dig deeper into the code and resulting files on this yet.

Running a reproduction run against the latest collab run, the new final_result file is 3254 entries longer. A diff of the original final_result and the new one gives 15699 entries (1% of total), 95% (15003) of which were previously unassigned. This sounds about right, because we keep the RPKI entries which are often most specific. I'm not sure though.
The count of entries and file size stay about the same, as does the encoded (filled or unfilled) file size.

This result seems counterintuitive since there are more entries even though you are saying we reject more now. If you insist the new approach is better it would be good to find out why this is the case. I haven't looked into it but the only explanation that would make sense to me is that with the approach we are using in master now, we add these supernets from IRR which are usually shorter and add larger areas of coverage for a smaller number of lines. This leads to many potential entries from Routeviews being rejected which are longer than what we got from IRR but don't offer additional coverage. Since RV essentially is BGP traffic it makes sense that it is a lot more fractured than IRR which is used for filters etc. So after the code change here rejects these supernets from IRR this leaves the door open for all these longer routeviews entries to get into the result file, which results in more entries.

This is just an educated guess, I have not looked at the data yet to verify if this is what happens.

Comment thread kartograf/merge.py
Merge lists of IP networks into a base file.
"""
print("Merging extra prefixes that were not included in the base file.")
print("Creating network index from base file.")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add this additional logging? I think we just recently removed similar lines to that extend, so I think keeping the logging as is would be better.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just changing the text, not a new log message. This is one of the messages we decided to keep.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line just looks like it's only changing the text but below on L133 the old log message still exists: 1010890#diff-db4db3f74df857bf1194562bdeaa881b0f91197d4185f45345ca7eee6e2cf50eR133 So there are now two logs where there used to be one.

Comment thread kartograf/trie.py Outdated
Comment thread kartograf/trie.py Outdated
@jurraca

jurraca commented Mar 18, 2026

Copy link
Copy Markdown
Collaborator Author

When we have overlapping coverage in our resulting asmap we use the most precise (longest) prefix for the ASN.

thanks, you're right, I was overthinking it. Longest prefix match wins. I removed the clause and function that attempted to check for a supernet of the checked network. Now it's just subset checking, but doesn't need the root_net index as the previous merge process did, so it's more general.

Watching repro run CI...

@jurraca

jurraca commented Mar 18, 2026

Copy link
Copy Markdown
Collaborator Author

a diff against a run with this version still yields about a 15k diff, with mostly unassigned as with the previous run. Even after encoding with --fill the diffs are still about 7k. Looking into it.

jurraca added 5 commits June 5, 2026 15:22
when looking up a network, return an ASN if there is a network with a
shorter prefix or a longer prefix than the candidate network (i.e. any
overlap). This enforces the idea that the base index is the source of
truth, and a base network should not be superseded by an incoming
network.
@jurraca

jurraca commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

After looking further, I found the bug, documented here.

To reproduce, using the latest run bitcoin-core/asmap-data#51 , you can run a reproduction run with this branch then run a diff between the result files. It's about 16k line diff file, with 16076 out of 16855 (95%) in the diff are "previously unassigned". It's a bit misleading because the "unassigned" being reported in the diff are just getting rolled up into the larger network, and are not individually assigned in the trie-based result.

The lines with previously assigned AS help show the issue. For example, there's the line: 12.0.224.0/21 AS7018 # was AS2386 so this network was assigned AS2386 in the master branch code and AS7018 in this branch's trie-based code. In both runs, the network assignment comes from routeviews collectors/pfx2asn_clean.txt with the AS3286 assignment. RPKI has 12.0.0.0/22, and that is the base file. In both runs, IRR gives us 12.0.0.0/8 AS7018. Because of the bug, this IRR assignment does not get merged in. The merge process should see the 12.0.0.0/8 AS7018 assignment, and judge that the 12.0.224.0/21 network is already covered by the IRR entry. In the trie case, this is the case. But in the original merge, this is not the case, resulting in the 12.0.224.0/21 AS2386 assignment, since it does not overlap with the base file's 12.0.0.0/22 entry.

Either way the trie impl is better if it caught this. While it would be nice to be able to "reproduce" any old ASmap, the correctness seems more valuable.

added a small merge test to make this behavior explicit and to sanity-check myself; we can remove later if necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants