@takodotid/circuit 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/presets/index.js +65 -65
- package/dist/types/presets/index.d.ts +14 -18
- package/package.json +1 -1
- package/src/presets/index.ts +93 -89
package/dist/presets/index.js
CHANGED
|
@@ -160,22 +160,15 @@ function communityScheme(scheme) {
|
|
|
160
160
|
const community = (fn, parameter) => `${asn}:${fn}:${parameter}`;
|
|
161
161
|
const ours = { standard: [`${asn}:*`], large: [`${asn}:*:*`] };
|
|
162
162
|
const information = [scheme.learned_from?.function, scheme.learned_at?.function, scheme.learned_from_as].filter((fn) => fn !== undefined);
|
|
163
|
-
const requests = [
|
|
164
|
-
{ functions: [scheme.do_not_announce?.function], trusted: scheme.do_not_announce?.trusted },
|
|
165
|
-
{ functions: PREPENDS.map(([name]) => scheme.prepend?.[name]), trusted: scheme.prepend?.trusted },
|
|
166
|
-
{ functions: [scheme.blackhole?.function], trusted: scheme.blackhole?.trusted }
|
|
167
|
-
].map(({ functions, trusted }) => ({ functions: functions.filter((fn) => fn !== undefined), trusted: trusted ?? [] }));
|
|
168
163
|
const tag = (neighborClass, neighborAs, options = {}) => {
|
|
169
|
-
const { site } = options;
|
|
170
|
-
const untrusted = requests.filter((request) => !request.trusted.includes(neighborClass)).flatMap((request) => request.functions);
|
|
171
|
-
const trustedForAny = requests.some((request) => request.functions.length && request.trusted.includes(neighborClass));
|
|
164
|
+
const { site, trusted = false } = options;
|
|
172
165
|
if (scheme.learned_at && site === undefined)
|
|
173
166
|
throw new Error(`communityScheme: tag for AS${neighborAs} needs a site, for learned_at`);
|
|
174
167
|
return {
|
|
175
168
|
description: `Learned from AS${neighborAs}`,
|
|
176
169
|
set: {
|
|
177
170
|
remove_communities: ours.standard,
|
|
178
|
-
remove_large_communities:
|
|
171
|
+
remove_large_communities: trusted ? information.map((fn) => community(fn, "*")) : ours.large,
|
|
179
172
|
add_large_communities: [
|
|
180
173
|
...scheme.learned_from ? [community(scheme.learned_from.function, scheme.learned_from.classes[neighborClass])] : [],
|
|
181
174
|
...scheme.learned_at ? [community(scheme.learned_at.function, site)] : [],
|
|
@@ -184,67 +177,69 @@ function communityScheme(scheme) {
|
|
|
184
177
|
}
|
|
185
178
|
};
|
|
186
179
|
};
|
|
187
|
-
const blackhole = (
|
|
188
|
-
|
|
180
|
+
const blackhole = (prefixSets) => {
|
|
181
|
+
const fn = scheme.blackhole?.function;
|
|
182
|
+
if (fn === undefined)
|
|
189
183
|
throw new Error("communityScheme: blackhole needs a function number in the scheme");
|
|
190
|
-
|
|
191
|
-
throw new Error(`communityScheme: ${neighborClass} is not trusted to ask for a blackhole`);
|
|
192
|
-
return {
|
|
184
|
+
return prefixSets.map((prefixSet) => ({
|
|
193
185
|
description: "Blackhole, asked by the neighbor",
|
|
194
|
-
match: { large_community: community(
|
|
186
|
+
match: { large_community: community(fn, 0), prefix_set: prefixSet },
|
|
195
187
|
set: { blackhole: true },
|
|
196
188
|
action: "accept"
|
|
197
|
-
};
|
|
189
|
+
}));
|
|
198
190
|
};
|
|
199
|
-
const actions = (neighborAs
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
description: `Asked not to be announced to AS${neighborAs}`,
|
|
215
|
-
match: { large_community: community(scheme.do_not_announce.function, neighborAs) },
|
|
216
|
-
action: "reject"
|
|
217
|
-
}
|
|
218
|
-
] : [],
|
|
219
|
-
...scheme.blackhole !== undefined && options.blackhole ? [
|
|
220
|
-
{
|
|
221
|
-
description: `Blackhole passed on to AS${neighborAs}`,
|
|
222
|
-
match: { large_community: community(scheme.blackhole.function, 0) },
|
|
223
|
-
set: {
|
|
224
|
-
remove_communities: ours.standard,
|
|
225
|
-
remove_large_communities: ours.large,
|
|
226
|
-
add_communities: [options.blackhole]
|
|
191
|
+
const actions = (neighborAs) => {
|
|
192
|
+
const passOn = scheme.blackhole?.upstreams?.[neighborAs];
|
|
193
|
+
return [
|
|
194
|
+
...scheme.blackhole !== undefined && !passOn ? [
|
|
195
|
+
{
|
|
196
|
+
description: "Blackholed here, never announced",
|
|
197
|
+
match: { large_community: community(scheme.blackhole.function, 0) },
|
|
198
|
+
action: "reject"
|
|
199
|
+
}
|
|
200
|
+
] : [],
|
|
201
|
+
...scheme.do_not_announce !== undefined ? [
|
|
202
|
+
{
|
|
203
|
+
description: "Asked not to be announced anywhere",
|
|
204
|
+
match: { large_community: community(scheme.do_not_announce, 0) },
|
|
205
|
+
action: "reject"
|
|
227
206
|
},
|
|
228
|
-
action: "accept"
|
|
229
|
-
}
|
|
230
|
-
] : [],
|
|
231
|
-
...PREPENDS.flatMap(([name, times]) => {
|
|
232
|
-
const fn = scheme.prepend?.[name];
|
|
233
|
-
if (fn === undefined)
|
|
234
|
-
return [];
|
|
235
|
-
return [
|
|
236
207
|
{
|
|
237
|
-
description: `Asked to
|
|
238
|
-
match: { large_community: community(
|
|
239
|
-
|
|
208
|
+
description: `Asked not to be announced to AS${neighborAs}`,
|
|
209
|
+
match: { large_community: community(scheme.do_not_announce, neighborAs) },
|
|
210
|
+
action: "reject"
|
|
240
211
|
}
|
|
241
|
-
]
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
212
|
+
] : [],
|
|
213
|
+
...scheme.blackhole !== undefined && passOn ? [
|
|
214
|
+
{
|
|
215
|
+
description: `Blackhole passed on to AS${neighborAs}`,
|
|
216
|
+
match: { large_community: community(scheme.blackhole.function, 0) },
|
|
217
|
+
set: {
|
|
218
|
+
remove_communities: ours.standard,
|
|
219
|
+
remove_large_communities: ours.large,
|
|
220
|
+
add_communities: [passOn]
|
|
221
|
+
},
|
|
222
|
+
action: "accept"
|
|
223
|
+
}
|
|
224
|
+
] : [],
|
|
225
|
+
...PREPENDS.flatMap(([name, times]) => {
|
|
226
|
+
const fn = scheme.prepend?.[name];
|
|
227
|
+
if (fn === undefined)
|
|
228
|
+
return [];
|
|
229
|
+
return [
|
|
230
|
+
{
|
|
231
|
+
description: `Asked to prepend ${name.replace("_", " ")} to AS${neighborAs}`,
|
|
232
|
+
match: { large_community: community(fn, neighborAs) },
|
|
233
|
+
set: { prepend: times }
|
|
234
|
+
}
|
|
235
|
+
];
|
|
236
|
+
}),
|
|
237
|
+
{
|
|
238
|
+
description: "Our communities stay inside our network",
|
|
239
|
+
set: { remove_communities: ours.standard, remove_large_communities: ours.large }
|
|
240
|
+
}
|
|
241
|
+
];
|
|
242
|
+
};
|
|
248
243
|
const catalogue = [
|
|
249
244
|
...Object.entries(scheme.learned_from?.classes ?? {}).map(([name, value]) => ({
|
|
250
245
|
community: community(scheme.learned_from.function, value),
|
|
@@ -259,14 +254,19 @@ function communityScheme(scheme) {
|
|
|
259
254
|
] : [],
|
|
260
255
|
...scheme.learned_from_as !== undefined ? [{ community: community(scheme.learned_from_as, "nnn"), description: "Learned from AS$0" }] : [],
|
|
261
256
|
...scheme.do_not_announce !== undefined ? [
|
|
262
|
-
{ community: community(scheme.do_not_announce
|
|
263
|
-
{ community: community(scheme.do_not_announce
|
|
257
|
+
{ community: community(scheme.do_not_announce, 0), description: "Do not announce to anyone" },
|
|
258
|
+
{ community: community(scheme.do_not_announce, "nnn"), description: "Do not announce to AS$0" }
|
|
264
259
|
] : [],
|
|
265
260
|
...PREPENDS.flatMap(([name]) => {
|
|
266
261
|
const fn = scheme.prepend?.[name];
|
|
267
262
|
return fn === undefined ? [] : [{ community: community(fn, "nnn"), description: `Prepend ${name.replace("_", " ")} to AS$0` }];
|
|
268
263
|
}),
|
|
269
|
-
...scheme.blackhole !== undefined ? [
|
|
264
|
+
...scheme.blackhole !== undefined ? [
|
|
265
|
+
{
|
|
266
|
+
community: community(scheme.blackhole.function, 0),
|
|
267
|
+
description: Object.keys(scheme.blackhole.upstreams ?? {}).length ? `Blackhole: dropped in AS${asn} and by its upstreams that take it` : `Blackhole: dropped in AS${asn}, not announced further`
|
|
268
|
+
}
|
|
269
|
+
] : []
|
|
270
270
|
];
|
|
271
271
|
return { community, tag, actions, blackhole, catalogue };
|
|
272
272
|
}
|
|
@@ -72,42 +72,39 @@ export type CommunityScheme<Class extends string = string> = {
|
|
|
72
72
|
/** Set on import: the AS a route was learned from, `asn:function:asn`. */
|
|
73
73
|
learned_from_as?: number;
|
|
74
74
|
/** A neighbor asks: do not announce the route to an AS, `asn:function:asn`, or to anyone, `asn:function:0`. */
|
|
75
|
-
do_not_announce?:
|
|
76
|
-
function: number;
|
|
77
|
-
};
|
|
75
|
+
do_not_announce?: number;
|
|
78
76
|
/** A neighbor asks: prepend toward an AS once, twice or three times, `asn:function:asn`. */
|
|
79
|
-
prepend?:
|
|
77
|
+
prepend?: {
|
|
80
78
|
once?: number;
|
|
81
79
|
twice?: number;
|
|
82
80
|
three_times?: number;
|
|
83
81
|
};
|
|
84
|
-
/**
|
|
85
|
-
|
|
82
|
+
/**
|
|
83
|
+
* A neighbor asks: drop all traffic to this route, `asn:function:0`, usually one address under attack. Your router drops it, and so does every upstream in `upstreams`.
|
|
84
|
+
*
|
|
85
|
+
* `upstreams` maps an upstream's AS to its own blackhole community, as its NOC gives it. The route is passed to that upstream with it, so the traffic stops before it reaches your links. An upstream not listed never receives the route.
|
|
86
|
+
*/
|
|
87
|
+
blackhole?: {
|
|
86
88
|
function: number;
|
|
89
|
+
upstreams?: Readonly<Record<number, string>>;
|
|
87
90
|
};
|
|
88
91
|
};
|
|
89
|
-
/** Something a neighbor can ask you for, and who may. */
|
|
90
|
-
type Request<Class extends string> = {
|
|
91
|
-
/** The classes allowed to ask for it, from `learned_from.classes`. From anyone else, the request is removed when the route comes in. */
|
|
92
|
-
trusted: readonly NoInfer<Class>[];
|
|
93
|
-
};
|
|
94
92
|
/**
|
|
95
93
|
* Policy rules and a catalogue from one community scheme, so the communities your routers set, the ones they act on, and the ones you publish never disagree.
|
|
96
94
|
*
|
|
97
|
-
* - `tag(neighborClass, neighborAs, { site })`: a rule for an import policy. It removes your communities a neighbor set, then adds where the route was learned. A neighbor keeps
|
|
95
|
+
* - `tag(neighborClass, neighborAs, { site, trusted })`: a rule for an import policy. It removes your communities a neighbor set, then adds where the route was learned. A `trusted` neighbor keeps its requests: do not announce, prepend, blackhole. `site` is needed when the scheme has `learned_at`.
|
|
98
96
|
* - `actions(neighborAs, { blackhole })`: rules for an export policy toward one neighbor. They act on a customer's action communities, then remove all of yours. Place them before the rules that accept. A blackholed route goes no further, unless `blackhole` names the neighbor's own blackhole community: then it is passed on with it, so the neighbor drops the traffic too.
|
|
99
|
-
* - `blackhole(
|
|
97
|
+
* - `blackhole(prefixSets)`: rules for the import policy of a neighbor you trust with blackholes, before anything that rejects long prefixes. They take a route the neighbor asked to blackhole, but only inside `prefixSets`, its own space, and drop traffic to it here. One rule per set, so one call covers both families.
|
|
100
98
|
* - `catalogue`: every community, for `communities` in `defineNetwork`.
|
|
101
99
|
*/
|
|
102
100
|
export declare function communityScheme<const Class extends string>(scheme: CommunityScheme<Class>): {
|
|
103
101
|
community: (fn: number, parameter: number | string) => string;
|
|
104
102
|
tag: (neighborClass: Class, neighborAs: number, options?: {
|
|
105
103
|
site?: number;
|
|
104
|
+
trusted?: boolean;
|
|
106
105
|
}) => PolicyRule<never, never>;
|
|
107
|
-
actions: (neighborAs: number,
|
|
108
|
-
|
|
109
|
-
}) => PolicyRule<never, never>[];
|
|
110
|
-
blackhole: <S extends string>(neighborClass: Class, prefixSet: S) => PolicyRule<never, S>;
|
|
106
|
+
actions: (neighborAs: number) => PolicyRule<never, never>[];
|
|
107
|
+
blackhole: <S extends string>(prefixSets: readonly S[]) => PolicyRule<never, S>[];
|
|
111
108
|
catalogue: Community[];
|
|
112
109
|
};
|
|
113
110
|
/** A member of an internet exchange: a network with a port on the fabric and an address on the peering LAN. */
|
|
@@ -145,4 +142,3 @@ export declare function internetExchange<const V extends string>(exchange: Inter
|
|
|
145
142
|
ports: (device: string) => Record<string, Port<V, string, string, string>>;
|
|
146
143
|
check: Check;
|
|
147
144
|
};
|
|
148
|
-
export {};
|
package/package.json
CHANGED
package/src/presets/index.ts
CHANGED
|
@@ -231,17 +231,15 @@ export type CommunityScheme<Class extends string = string> = {
|
|
|
231
231
|
/** Set on import: the AS a route was learned from, `asn:function:asn`. */
|
|
232
232
|
learned_from_as?: number;
|
|
233
233
|
/** A neighbor asks: do not announce the route to an AS, `asn:function:asn`, or to anyone, `asn:function:0`. */
|
|
234
|
-
do_not_announce?:
|
|
234
|
+
do_not_announce?: number;
|
|
235
235
|
/** A neighbor asks: prepend toward an AS once, twice or three times, `asn:function:asn`. */
|
|
236
|
-
prepend?:
|
|
237
|
-
/**
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
/** The classes allowed to ask for it, from `learned_from.classes`. From anyone else, the request is removed when the route comes in. */
|
|
244
|
-
trusted: readonly NoInfer<Class>[];
|
|
236
|
+
prepend?: { once?: number; twice?: number; three_times?: number };
|
|
237
|
+
/**
|
|
238
|
+
* A neighbor asks: drop all traffic to this route, `asn:function:0`, usually one address under attack. Your router drops it, and so does every upstream in `upstreams`.
|
|
239
|
+
*
|
|
240
|
+
* `upstreams` maps an upstream's AS to its own blackhole community, as its NOC gives it. The route is passed to that upstream with it, so the traffic stops before it reaches your links. An upstream not listed never receives the route.
|
|
241
|
+
*/
|
|
242
|
+
blackhole?: { function: number; upstreams?: Readonly<Record<number, string>> };
|
|
245
243
|
};
|
|
246
244
|
|
|
247
245
|
const PREPENDS = [
|
|
@@ -255,9 +253,9 @@ const article = (word: string) => (/^[aeiou]/i.test(word) ? `an ${word}` : `a ${
|
|
|
255
253
|
/**
|
|
256
254
|
* Policy rules and a catalogue from one community scheme, so the communities your routers set, the ones they act on, and the ones you publish never disagree.
|
|
257
255
|
*
|
|
258
|
-
* - `tag(neighborClass, neighborAs, { site })`: a rule for an import policy. It removes your communities a neighbor set, then adds where the route was learned. A neighbor keeps
|
|
256
|
+
* - `tag(neighborClass, neighborAs, { site, trusted })`: a rule for an import policy. It removes your communities a neighbor set, then adds where the route was learned. A `trusted` neighbor keeps its requests: do not announce, prepend, blackhole. `site` is needed when the scheme has `learned_at`.
|
|
259
257
|
* - `actions(neighborAs, { blackhole })`: rules for an export policy toward one neighbor. They act on a customer's action communities, then remove all of yours. Place them before the rules that accept. A blackholed route goes no further, unless `blackhole` names the neighbor's own blackhole community: then it is passed on with it, so the neighbor drops the traffic too.
|
|
260
|
-
* - `blackhole(
|
|
258
|
+
* - `blackhole(prefixSets)`: rules for the import policy of a neighbor you trust with blackholes, before anything that rejects long prefixes. They take a route the neighbor asked to blackhole, but only inside `prefixSets`, its own space, and drop traffic to it here. One rule per set, so one call covers both families.
|
|
261
259
|
* - `catalogue`: every community, for `communities` in `defineNetwork`.
|
|
262
260
|
*/
|
|
263
261
|
export function communityScheme<const Class extends string>(scheme: CommunityScheme<Class>) {
|
|
@@ -269,17 +267,12 @@ export function communityScheme<const Class extends string>(scheme: CommunitySch
|
|
|
269
267
|
(fn): fn is number => fn !== undefined
|
|
270
268
|
);
|
|
271
269
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const tag = (neighborClass: Class, neighborAs: number, options: { site?: number } = {}): PolicyRule<never, never> => {
|
|
280
|
-
const { site } = options;
|
|
281
|
-
const untrusted = requests.filter((request) => !request.trusted.includes(neighborClass)).flatMap((request) => request.functions);
|
|
282
|
-
const trustedForAny = requests.some((request) => request.functions.length && request.trusted.includes(neighborClass));
|
|
270
|
+
const tag = (
|
|
271
|
+
neighborClass: Class,
|
|
272
|
+
neighborAs: number,
|
|
273
|
+
options: { site?: number; trusted?: boolean } = {}
|
|
274
|
+
): PolicyRule<never, never> => {
|
|
275
|
+
const { site, trusted = false } = options;
|
|
283
276
|
if (scheme.learned_at && site === undefined)
|
|
284
277
|
throw new Error(`communityScheme: tag for AS${neighborAs} needs a site, for learned_at`);
|
|
285
278
|
|
|
@@ -287,8 +280,8 @@ export function communityScheme<const Class extends string>(scheme: CommunitySch
|
|
|
287
280
|
description: `Learned from AS${neighborAs}`,
|
|
288
281
|
set: {
|
|
289
282
|
remove_communities: ours.standard,
|
|
290
|
-
// A neighbor
|
|
291
|
-
remove_large_communities:
|
|
283
|
+
// A trusted neighbor keeps its requests and loses only the "where it came from" tags, which are ours to set. Anyone else loses every community of ours.
|
|
284
|
+
remove_large_communities: trusted ? information.map((fn) => community(fn, "*")) : ours.large,
|
|
292
285
|
add_large_communities: [
|
|
293
286
|
...(scheme.learned_from ? [community(scheme.learned_from.function, scheme.learned_from.classes[neighborClass])] : []),
|
|
294
287
|
...(scheme.learned_at ? [community(scheme.learned_at.function, site!)] : []),
|
|
@@ -298,74 +291,78 @@ export function communityScheme<const Class extends string>(scheme: CommunitySch
|
|
|
298
291
|
};
|
|
299
292
|
};
|
|
300
293
|
|
|
301
|
-
const blackhole = <S extends string>(
|
|
302
|
-
|
|
303
|
-
if (
|
|
304
|
-
throw new Error(`communityScheme: ${neighborClass} is not trusted to ask for a blackhole`);
|
|
294
|
+
const blackhole = <S extends string>(prefixSets: readonly S[]): PolicyRule<never, S>[] => {
|
|
295
|
+
const fn = scheme.blackhole?.function;
|
|
296
|
+
if (fn === undefined) throw new Error("communityScheme: blackhole needs a function number in the scheme");
|
|
305
297
|
|
|
306
|
-
return {
|
|
298
|
+
return prefixSets.map((prefixSet) => ({
|
|
307
299
|
description: "Blackhole, asked by the neighbor",
|
|
308
|
-
match: { large_community: community(
|
|
300
|
+
match: { large_community: community(fn, 0), prefix_set: prefixSet },
|
|
309
301
|
set: { blackhole: true },
|
|
310
302
|
action: "accept",
|
|
311
|
-
};
|
|
303
|
+
}));
|
|
312
304
|
};
|
|
313
305
|
|
|
314
|
-
const actions = (neighborAs: number
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
? [
|
|
326
|
-
{
|
|
327
|
-
description: "Asked not to be announced anywhere",
|
|
328
|
-
match: { large_community: community(scheme.do_not_announce.function, 0) },
|
|
329
|
-
action: "reject" as const,
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
description: `Asked not to be announced to AS${neighborAs}`,
|
|
333
|
-
match: { large_community: community(scheme.do_not_announce.function, neighborAs) },
|
|
334
|
-
action: "reject" as const,
|
|
335
|
-
},
|
|
336
|
-
]
|
|
337
|
-
: []),
|
|
338
|
-
...(scheme.blackhole !== undefined && options.blackhole
|
|
339
|
-
? [
|
|
340
|
-
{
|
|
341
|
-
description: `Blackhole passed on to AS${neighborAs}`,
|
|
342
|
-
match: { large_community: community(scheme.blackhole.function, 0) },
|
|
343
|
-
set: {
|
|
344
|
-
remove_communities: ours.standard,
|
|
345
|
-
remove_large_communities: ours.large,
|
|
346
|
-
add_communities: [options.blackhole],
|
|
306
|
+
const actions = (neighborAs: number): PolicyRule<never, never>[] => {
|
|
307
|
+
// The upstream's own blackhole community, when it takes blackholes from us.
|
|
308
|
+
const passOn = scheme.blackhole?.upstreams?.[neighborAs];
|
|
309
|
+
|
|
310
|
+
return [
|
|
311
|
+
...(scheme.blackhole !== undefined && !passOn
|
|
312
|
+
? [
|
|
313
|
+
{
|
|
314
|
+
description: "Blackholed here, never announced",
|
|
315
|
+
match: { large_community: community(scheme.blackhole.function, 0) },
|
|
316
|
+
action: "reject" as const,
|
|
347
317
|
},
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
318
|
+
]
|
|
319
|
+
: []),
|
|
320
|
+
...(scheme.do_not_announce !== undefined
|
|
321
|
+
? [
|
|
322
|
+
{
|
|
323
|
+
description: "Asked not to be announced anywhere",
|
|
324
|
+
match: { large_community: community(scheme.do_not_announce, 0) },
|
|
325
|
+
action: "reject" as const,
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
description: `Asked not to be announced to AS${neighborAs}`,
|
|
329
|
+
match: { large_community: community(scheme.do_not_announce, neighborAs) },
|
|
330
|
+
action: "reject" as const,
|
|
331
|
+
},
|
|
332
|
+
]
|
|
333
|
+
: []),
|
|
334
|
+
...(scheme.blackhole !== undefined && passOn
|
|
335
|
+
? [
|
|
336
|
+
{
|
|
337
|
+
description: `Blackhole passed on to AS${neighborAs}`,
|
|
338
|
+
match: { large_community: community(scheme.blackhole.function, 0) },
|
|
339
|
+
set: {
|
|
340
|
+
remove_communities: ours.standard,
|
|
341
|
+
remove_large_communities: ours.large,
|
|
342
|
+
add_communities: [passOn],
|
|
343
|
+
},
|
|
344
|
+
action: "accept" as const,
|
|
345
|
+
},
|
|
346
|
+
]
|
|
347
|
+
: []),
|
|
348
|
+
...PREPENDS.flatMap(([name, times]) => {
|
|
349
|
+
const fn = scheme.prepend?.[name];
|
|
350
|
+
if (fn === undefined) return [];
|
|
351
|
+
|
|
352
|
+
return [
|
|
353
|
+
{
|
|
354
|
+
description: `Asked to prepend ${name.replace("_", " ")} to AS${neighborAs}`,
|
|
355
|
+
match: { large_community: community(fn, neighborAs) },
|
|
356
|
+
set: { prepend: times },
|
|
357
|
+
},
|
|
358
|
+
];
|
|
359
|
+
}),
|
|
360
|
+
{
|
|
361
|
+
description: "Our communities stay inside our network",
|
|
362
|
+
set: { remove_communities: ours.standard, remove_large_communities: ours.large },
|
|
363
|
+
},
|
|
364
|
+
];
|
|
365
|
+
};
|
|
369
366
|
|
|
370
367
|
const catalogue: Community[] = [
|
|
371
368
|
...Object.entries<number>(scheme.learned_from?.classes ?? {}).map(([name, value]) => ({
|
|
@@ -386,8 +383,8 @@ export function communityScheme<const Class extends string>(scheme: CommunitySch
|
|
|
386
383
|
: []),
|
|
387
384
|
...(scheme.do_not_announce !== undefined
|
|
388
385
|
? [
|
|
389
|
-
{ community: community(scheme.do_not_announce
|
|
390
|
-
{ community: community(scheme.do_not_announce
|
|
386
|
+
{ community: community(scheme.do_not_announce, 0), description: "Do not announce to anyone" },
|
|
387
|
+
{ community: community(scheme.do_not_announce, "nnn"), description: "Do not announce to AS$0" },
|
|
391
388
|
]
|
|
392
389
|
: []),
|
|
393
390
|
...PREPENDS.flatMap(([name]) => {
|
|
@@ -395,7 +392,14 @@ export function communityScheme<const Class extends string>(scheme: CommunitySch
|
|
|
395
392
|
return fn === undefined ? [] : [{ community: community(fn, "nnn"), description: `Prepend ${name.replace("_", " ")} to AS$0` }];
|
|
396
393
|
}),
|
|
397
394
|
...(scheme.blackhole !== undefined
|
|
398
|
-
? [
|
|
395
|
+
? [
|
|
396
|
+
{
|
|
397
|
+
community: community(scheme.blackhole.function, 0),
|
|
398
|
+
description: Object.keys(scheme.blackhole.upstreams ?? {}).length
|
|
399
|
+
? `Blackhole: dropped in AS${asn} and by its upstreams that take it`
|
|
400
|
+
: `Blackhole: dropped in AS${asn}, not announced further`,
|
|
401
|
+
},
|
|
402
|
+
]
|
|
399
403
|
: []),
|
|
400
404
|
];
|
|
401
405
|
|