1 | import { Route } from '../types/routing'
|
2 | import { create as createLogger } from '../common/log'
|
3 | const log = createLogger('dragon')
|
4 | import { Relation, getRelationPriority } from './relation'
|
5 | import ForwardingRoutingTable from '../services/forwarding-routing-table'
|
6 |
|
7 | /**
|
8 | * Check whether a route can be filtered out based on DRAGON rules.
|
9 | *
|
10 | * See http://route-aggregation.net/.
|
11 | *
|
12 | * The basic idea is that if we have a more general route that is as good as a
|
13 | * more specific route, we don't need to advertise the more specific route.
|
14 | *
|
15 | * This removes a lot of routing updates across a large network and has basically
|
16 | * no downside.
|
17 | *
|
18 | * Note that we use DRAGON filtering, but *not* DRAGON aggregation. There are
|
19 | * several reasons for this:
|
20 | *
|
21 | * * ILP address space is a lot less dense than IPv4 address space, so
|
22 | * DRAGON aggregation would not be a significant optimization.
|
23 | *
|
24 | * * We may want to secure our routing protocol using a mechanism similar to
|
25 | * BGPsec, which precludes aggregation.
|
26 | *
|
27 | * * We will recommend that owners of tier-1 ILP address space are also real
|
28 | * connectors which participate in the routing protocol and originate a route
|
29 | * advertisement for their tier-1 prefix. This will enable DRAGON filtering
|
30 | * to apply to a lot more situations where otherwise only DRAGON aggregation
|
31 | * would be applicable.
|
32 | */
|
33 | export function canDragonFilter (
|
34 | routingTable: ForwardingRoutingTable,
|
35 | getRelation: (prefix: string) => Relation,
|
36 | prefix: string,
|
37 | route: Route
|
38 | ): boolean {
|
39 | // Find any less specific route
|
40 | for (const parentPrefix of routingTable.getKeysPrefixesOf(prefix)) {
|
41 | const parentRouteUpdate = routingTable.get(parentPrefix)
|
42 |
|
43 | if (!parentRouteUpdate || !parentRouteUpdate.route) {
|
44 | log.warn('found a parent prefix, but no parent route; this should never happen. prefix=%s parentPrefix=%s', prefix, parentPrefix)
|
45 | continue
|
46 | }
|
47 |
|
48 | const parentRoute = parentRouteUpdate.route
|
49 |
|
50 | if (parentRoute.nextHop === '') {
|
51 | // We are the origin of the parent route, cannot DRAGON filter
|
52 | continue
|
53 | }
|
54 |
|
55 | const parentRelation = getRelation(parentRoute.nextHop)
|
56 | const childRelation = getRelation(route.nextHop)
|
57 | if (getRelationPriority(parentRelation) < getRelationPriority(childRelation)) {
|
58 | // The more specific route is better for us, so we keep it
|
59 | continue
|
60 | }
|
61 |
|
62 | log.trace('applied DRAGON route filter. prefix=%s parentPrefix=%s', prefix, parentPrefix)
|
63 | return true
|
64 | }
|
65 |
|
66 | return false
|
67 | }
|