mirror of
https://github.com/quantum5/bird-filter.git
synced 2025-04-24 09:01:57 -04:00
Compare commits
No commits in common. "52b52aa53623d535689d71c033eeafc6a18ece26" and "ed92df8fce96260a04a6786e635f547901544717" have entirely different histories.
52b52aa536
...
ed92df8fce
33
aspa/data.py
33
aspa/data.py
|
@ -1,33 +0,0 @@
|
|||
import json
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
reasn = re.compile(r"^AS(\d+)$")
|
||||
|
||||
|
||||
def parse_asn(text: str) -> Optional[int]:
|
||||
match = reasn.match(text)
|
||||
if match:
|
||||
return int(match.group(1))
|
||||
|
||||
|
||||
@dataclass
|
||||
class ASPA:
|
||||
customer: int
|
||||
providers: list[int]
|
||||
ta: str
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d):
|
||||
try:
|
||||
customer = parse_asn(d['customer'])
|
||||
providers = list(map(parse_asn, d['providers']))
|
||||
return cls(customer, providers, d['ta'])
|
||||
except (KeyError, TypeError):
|
||||
return None
|
||||
|
||||
|
||||
def parse_json(data: str) -> list[ASPA]:
|
||||
data = json.loads(data)
|
||||
return list(filter(None, map(ASPA.from_dict, data.get('aspas', []))))
|
|
@ -1,822 +0,0 @@
|
|||
{
|
||||
"metadata": {
|
||||
"generated": 1730172244,
|
||||
"generatedTime": "2024-10-29T03:24:04Z"
|
||||
},
|
||||
"aspas": [
|
||||
{
|
||||
"customer": "AS11358",
|
||||
"providers": [
|
||||
"AS835",
|
||||
"AS924",
|
||||
"AS6939",
|
||||
"AS20473",
|
||||
"AS34927"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS13852",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS20473",
|
||||
"AS34927",
|
||||
"AS41051",
|
||||
"AS52025"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS15562",
|
||||
"providers": [
|
||||
"AS2914",
|
||||
"AS8283",
|
||||
"AS51088",
|
||||
"AS206238"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS19330",
|
||||
"providers": [
|
||||
"AS393577"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS28584",
|
||||
"providers": [
|
||||
"AS28605"
|
||||
],
|
||||
"ta": "lacnic"
|
||||
},
|
||||
{
|
||||
"customer": "AS33733",
|
||||
"providers": [
|
||||
"AS174",
|
||||
"AS6939",
|
||||
"AS12186",
|
||||
"AS47787",
|
||||
"AS200454"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS40544",
|
||||
"providers": [
|
||||
"AS924",
|
||||
"AS6939",
|
||||
"AS12186",
|
||||
"AS52025"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS41720",
|
||||
"providers": [
|
||||
"AS174",
|
||||
"AS1299",
|
||||
"AS9002",
|
||||
"AS50877",
|
||||
"AS60068",
|
||||
"AS203446",
|
||||
"AS212508"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS44324",
|
||||
"providers": [
|
||||
"AS945",
|
||||
"AS955",
|
||||
"AS1299",
|
||||
"AS3204",
|
||||
"AS6939",
|
||||
"AS7720",
|
||||
"AS8772",
|
||||
"AS8849",
|
||||
"AS15353",
|
||||
"AS18041",
|
||||
"AS20473",
|
||||
"AS29632",
|
||||
"AS32595",
|
||||
"AS34465",
|
||||
"AS34927",
|
||||
"AS41051",
|
||||
"AS43426",
|
||||
"AS47272",
|
||||
"AS51087",
|
||||
"AS53667",
|
||||
"AS53808",
|
||||
"AS59538",
|
||||
"AS61112",
|
||||
"AS134823",
|
||||
"AS138997",
|
||||
"AS139317",
|
||||
"AS151364",
|
||||
"AS199545",
|
||||
"AS199765",
|
||||
"AS200105",
|
||||
"AS206499",
|
||||
"AS207656",
|
||||
"AS207841",
|
||||
"AS209554",
|
||||
"AS209735",
|
||||
"AS212483"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS47272",
|
||||
"providers": [
|
||||
"AS835",
|
||||
"AS924",
|
||||
"AS1299",
|
||||
"AS6830",
|
||||
"AS6939",
|
||||
"AS20473",
|
||||
"AS21738",
|
||||
"AS25759",
|
||||
"AS34927",
|
||||
"AS35133",
|
||||
"AS41051",
|
||||
"AS48605",
|
||||
"AS50391",
|
||||
"AS50917",
|
||||
"AS52025",
|
||||
"AS52210",
|
||||
"AS58057",
|
||||
"AS210667",
|
||||
"AS212514",
|
||||
"AS212895"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS47689",
|
||||
"providers": [
|
||||
"AS924",
|
||||
"AS1299",
|
||||
"AS6939",
|
||||
"AS21738",
|
||||
"AS34465",
|
||||
"AS34549",
|
||||
"AS34927",
|
||||
"AS395823"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS48070",
|
||||
"providers": [
|
||||
"AS174",
|
||||
"AS1299"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS48606",
|
||||
"providers": [
|
||||
"AS30893",
|
||||
"AS54681",
|
||||
"AS57974",
|
||||
"AS59678",
|
||||
"AS210691",
|
||||
"AS212276"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS50224",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS15353",
|
||||
"AS26930",
|
||||
"AS34465",
|
||||
"AS37988",
|
||||
"AS50104",
|
||||
"AS52025",
|
||||
"AS52210",
|
||||
"AS59920",
|
||||
"AS60841",
|
||||
"AS210475",
|
||||
"AS400304"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS50391",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS20473",
|
||||
"AS48070"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS51019",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS34549",
|
||||
"AS34927",
|
||||
"AS52025",
|
||||
"AS207841"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS51396",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS30823",
|
||||
"AS44066",
|
||||
"AS49581",
|
||||
"AS60223",
|
||||
"AS203446",
|
||||
"AS214995",
|
||||
"AS215436"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS52025",
|
||||
"providers": [
|
||||
"AS174",
|
||||
"AS835",
|
||||
"AS906",
|
||||
"AS917",
|
||||
"AS924",
|
||||
"AS1299",
|
||||
"AS3257",
|
||||
"AS6204",
|
||||
"AS6939",
|
||||
"AS7720",
|
||||
"AS8860",
|
||||
"AS12186",
|
||||
"AS18041",
|
||||
"AS20473",
|
||||
"AS21700",
|
||||
"AS21738",
|
||||
"AS25369",
|
||||
"AS29802",
|
||||
"AS32097",
|
||||
"AS34549",
|
||||
"AS34927",
|
||||
"AS35133",
|
||||
"AS35661",
|
||||
"AS36369",
|
||||
"AS37988",
|
||||
"AS39409",
|
||||
"AS47787",
|
||||
"AS48070",
|
||||
"AS48605",
|
||||
"AS50917",
|
||||
"AS51519",
|
||||
"AS52210",
|
||||
"AS56655",
|
||||
"AS57695",
|
||||
"AS61138",
|
||||
"AS197216",
|
||||
"AS199545",
|
||||
"AS209022",
|
||||
"AS209533",
|
||||
"AS394177",
|
||||
"AS396998",
|
||||
"AS397423",
|
||||
"AS400304",
|
||||
"AS400587"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS52210",
|
||||
"providers": [
|
||||
"AS174",
|
||||
"AS835",
|
||||
"AS6939",
|
||||
"AS52025",
|
||||
"AS62513",
|
||||
"AS210667"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS54148",
|
||||
"providers": [
|
||||
"AS835",
|
||||
"AS924",
|
||||
"AS6939",
|
||||
"AS20473",
|
||||
"AS21738",
|
||||
"AS34927",
|
||||
"AS37988",
|
||||
"AS47272",
|
||||
"AS50917",
|
||||
"AS53667"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS54218",
|
||||
"providers": [
|
||||
"AS917",
|
||||
"AS16509",
|
||||
"AS37988",
|
||||
"AS53667",
|
||||
"AS59678"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS56762",
|
||||
"providers": [
|
||||
"AS47689"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS57194",
|
||||
"providers": [
|
||||
"AS924",
|
||||
"AS52210"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS57984",
|
||||
"providers": [
|
||||
"AS8283",
|
||||
"AS48112",
|
||||
"AS206763"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS59678",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS34927",
|
||||
"AS54218",
|
||||
"AS55081"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS60223",
|
||||
"providers": [
|
||||
"AS945",
|
||||
"AS49581"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS60431",
|
||||
"providers": [
|
||||
"AS34927",
|
||||
"AS41495",
|
||||
"AS50917"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS60841",
|
||||
"providers": [
|
||||
"AS30456",
|
||||
"AS400304"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS149301",
|
||||
"providers": [
|
||||
"AS20473",
|
||||
"AS61138"
|
||||
],
|
||||
"ta": "apnic"
|
||||
},
|
||||
{
|
||||
"customer": "AS151642",
|
||||
"providers": [
|
||||
"AS20473",
|
||||
"AS61138"
|
||||
],
|
||||
"ta": "apnic"
|
||||
},
|
||||
{
|
||||
"customer": "AS198136",
|
||||
"providers": [
|
||||
"AS0"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS199376",
|
||||
"providers": [
|
||||
"AS47311",
|
||||
"AS61112",
|
||||
"AS150249",
|
||||
"AS151544",
|
||||
"AS199762",
|
||||
"AS209533",
|
||||
"AS215379"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS199762",
|
||||
"providers": [
|
||||
"AS945",
|
||||
"AS6939",
|
||||
"AS8849",
|
||||
"AS15353",
|
||||
"AS34927",
|
||||
"AS44817",
|
||||
"AS47311",
|
||||
"AS48605",
|
||||
"AS140731",
|
||||
"AS150249"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS200242",
|
||||
"providers": [
|
||||
"AS835",
|
||||
"AS6939",
|
||||
"AS21738",
|
||||
"AS34465",
|
||||
"AS34927",
|
||||
"AS52025",
|
||||
"AS59678",
|
||||
"AS60841",
|
||||
"AS210475"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS200351",
|
||||
"providers": [
|
||||
"AS34927",
|
||||
"AS47272",
|
||||
"AS209022",
|
||||
"AS210475"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS200454",
|
||||
"providers": [
|
||||
"AS174",
|
||||
"AS6424",
|
||||
"AS6939",
|
||||
"AS9186",
|
||||
"AS12186"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS202076",
|
||||
"providers": [
|
||||
"AS207960"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS202359",
|
||||
"providers": [
|
||||
"AS30740",
|
||||
"AS33920",
|
||||
"AS41495"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS202881",
|
||||
"providers": [
|
||||
"AS205329"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS203619",
|
||||
"providers": [
|
||||
"AS200454"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS203843",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS20473",
|
||||
"AS53667"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS204857",
|
||||
"providers": [
|
||||
"AS50224",
|
||||
"AS59920",
|
||||
"AS60841",
|
||||
"AS400304"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS204931",
|
||||
"providers": [
|
||||
"AS34927",
|
||||
"AS44103",
|
||||
"AS207656"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS205329",
|
||||
"providers": [
|
||||
"AS945",
|
||||
"AS983",
|
||||
"AS6939",
|
||||
"AS7720",
|
||||
"AS8894",
|
||||
"AS9409",
|
||||
"AS20473",
|
||||
"AS34927",
|
||||
"AS41051",
|
||||
"AS131657",
|
||||
"AS134823",
|
||||
"AS151364"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS205603",
|
||||
"providers": [
|
||||
"AS38074",
|
||||
"AS59105"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS205663",
|
||||
"providers": [
|
||||
"AS20473",
|
||||
"AS61138"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS205789",
|
||||
"providers": [
|
||||
"AS200242",
|
||||
"AS207960"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS205848",
|
||||
"providers": [
|
||||
"AS1299",
|
||||
"AS6939",
|
||||
"AS34549",
|
||||
"AS34927",
|
||||
"AS52025",
|
||||
"AS209022"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS207487",
|
||||
"providers": [
|
||||
"AS20473"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS207841",
|
||||
"providers": [
|
||||
"AS174",
|
||||
"AS6939",
|
||||
"AS137409"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS207960",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS20473",
|
||||
"AS34854",
|
||||
"AS34927",
|
||||
"AS136620",
|
||||
"AS202359",
|
||||
"AS207968"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS210561",
|
||||
"providers": [
|
||||
"AS207960"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS212068",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS13237",
|
||||
"AS62240",
|
||||
"AS207960"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS212245",
|
||||
"providers": [
|
||||
"AS917",
|
||||
"AS57695",
|
||||
"AS212068"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS212934",
|
||||
"providers": [
|
||||
"AS835",
|
||||
"AS6939",
|
||||
"AS34927",
|
||||
"AS52210",
|
||||
"AS53667",
|
||||
"AS61138",
|
||||
"AS62513",
|
||||
"AS209533",
|
||||
"AS210667"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215028",
|
||||
"providers": [
|
||||
"AS216107"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215131",
|
||||
"providers": [
|
||||
"AS8283",
|
||||
"AS34927"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215147",
|
||||
"providers": [
|
||||
"AS47263",
|
||||
"AS207252",
|
||||
"AS215828"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215436",
|
||||
"providers": [
|
||||
"AS6762",
|
||||
"AS6939",
|
||||
"AS51396",
|
||||
"AS60223"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215664",
|
||||
"providers": [
|
||||
"AS1299",
|
||||
"AS3204",
|
||||
"AS6939",
|
||||
"AS34549",
|
||||
"AS41720",
|
||||
"AS56382",
|
||||
"AS203446",
|
||||
"AS212508"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215778",
|
||||
"providers": [
|
||||
"AS34465",
|
||||
"AS39249",
|
||||
"AS41051",
|
||||
"AS207656",
|
||||
"AS209533",
|
||||
"AS393577"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215828",
|
||||
"providers": [
|
||||
"AS6204",
|
||||
"AS6939",
|
||||
"AS8772",
|
||||
"AS29390",
|
||||
"AS29632",
|
||||
"AS34465",
|
||||
"AS34927",
|
||||
"AS39249",
|
||||
"AS41051",
|
||||
"AS44592",
|
||||
"AS48752",
|
||||
"AS50917",
|
||||
"AS51019",
|
||||
"AS58057",
|
||||
"AS62403",
|
||||
"AS152726",
|
||||
"AS197071",
|
||||
"AS199524",
|
||||
"AS203686",
|
||||
"AS207656",
|
||||
"AS209533",
|
||||
"AS210464",
|
||||
"AS216324",
|
||||
"AS216360",
|
||||
"AS393577"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS215849",
|
||||
"providers": [
|
||||
"AS215828"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS216107",
|
||||
"providers": [
|
||||
"AS924",
|
||||
"AS6939",
|
||||
"AS16509",
|
||||
"AS20473",
|
||||
"AS21738",
|
||||
"AS34927",
|
||||
"AS63473",
|
||||
"AS209022",
|
||||
"AS211588"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS216311",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS13852",
|
||||
"AS20473",
|
||||
"AS34927",
|
||||
"AS52025"
|
||||
],
|
||||
"ta": "ripe"
|
||||
},
|
||||
{
|
||||
"customer": "AS267386",
|
||||
"providers": [
|
||||
"AS6939",
|
||||
"AS25933",
|
||||
"AS28220",
|
||||
"AS28649",
|
||||
"AS267613"
|
||||
],
|
||||
"ta": "lacnic"
|
||||
},
|
||||
{
|
||||
"customer": "AS270470",
|
||||
"providers": [
|
||||
"AS53062"
|
||||
],
|
||||
"ta": "lacnic"
|
||||
},
|
||||
{
|
||||
"customer": "AS393577",
|
||||
"providers": [
|
||||
"AS1299",
|
||||
"AS6939",
|
||||
"AS32097",
|
||||
"AS40676",
|
||||
"AS137409"
|
||||
],
|
||||
"ta": "arin"
|
||||
},
|
||||
{
|
||||
"customer": "AS401111",
|
||||
"providers": [
|
||||
"AS945",
|
||||
"AS6939",
|
||||
"AS17676"
|
||||
],
|
||||
"ta": "arin"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
from aspa.data import ASPA
|
||||
|
||||
|
||||
def generate_bird(aspas: list[ASPA]) -> str:
|
||||
lines = [
|
||||
'function is_aspa_invalid_pair(int upstream_asn; int downstream_asn) {',
|
||||
' case downstream_asn {'
|
||||
]
|
||||
|
||||
for aspa in aspas:
|
||||
if aspa.providers:
|
||||
asns = ', '.join(map(str, aspa.providers))
|
||||
lines.append(f' {aspa.customer}: if upstream_asn !~ [{asns}] then return true;')
|
||||
else:
|
||||
lines.append(f' {aspa.customer}: return true;')
|
||||
|
||||
lines += [
|
||||
' }',
|
||||
' return false;',
|
||||
'}'
|
||||
]
|
||||
|
||||
return '\n'.join(lines)
|
174
aspa/test.py
174
aspa/test.py
|
@ -1,174 +0,0 @@
|
|||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from aspa.data import ASPA, parse_json
|
||||
from aspa.validate import BirdValidator, Validator
|
||||
|
||||
|
||||
class ParserTest(unittest.TestCase):
|
||||
def test_parse(self):
|
||||
with open(Path(__file__).parent / 'example.json') as f:
|
||||
result = parse_json(f.read())
|
||||
|
||||
self.assertEqual(len(result), 69)
|
||||
|
||||
for aspa in result:
|
||||
if aspa.customer == 54148:
|
||||
self.assertEqual(aspa.providers, [835, 924, 6939, 20473, 21738, 34927, 37988, 47272, 50917, 53667])
|
||||
self.assertEqual(aspa.ta, 'arin')
|
||||
|
||||
|
||||
class CustomerTest(unittest.TestCase):
|
||||
validator_class = Validator
|
||||
|
||||
def setUp(self):
|
||||
self.validator = self.validator_class([
|
||||
ASPA(64500, [64501], 'test'),
|
||||
ASPA(64501, [64502], 'test'),
|
||||
ASPA(64502, [64503], 'test'),
|
||||
ASPA(64503, [64504], 'test'),
|
||||
])
|
||||
|
||||
def test_all_valid(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64501, [64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64502, [64501, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64503, [64502, 64501, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64504, [64503, 64502, 64501, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64504, [64503, 64502, 64501]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64504, [64503, 64502]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64504, [64503]))
|
||||
|
||||
def test_some_unknown(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64505, [64504, 64503, 64502, 64501]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64503, [64502, 64501, 64505]))
|
||||
|
||||
def test_all_unknown(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64506, [64507, 64508]))
|
||||
|
||||
def test_some_invalid(self):
|
||||
self.assertTrue(self.validator.is_aspa_invalid_customer(64505, [64504, 64503, 64501, 64501]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_customer(64504, [64503, 64502, 64506, 64500]))
|
||||
|
||||
|
||||
class PeerTest(unittest.TestCase):
|
||||
validator_class = Validator
|
||||
|
||||
def setUp(self):
|
||||
self.validator = self.validator_class([
|
||||
ASPA(64500, [64501], 'test'),
|
||||
ASPA(64501, [64502], 'test'),
|
||||
ASPA(64502, [64503], 'test'),
|
||||
ASPA(64503, [64504], 'test'),
|
||||
])
|
||||
|
||||
def test_all_valid(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64501, [64501, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64502, [64502, 64501, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64503, [64503, 64502, 64501, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64504, [64504, 64503, 64502, 64501]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64504, [64504, 64503, 64502]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64504, [64504, 64503]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64504, [64504]))
|
||||
|
||||
def test_prepend_valid(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64501, [64501, 64500, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64502, [64502, 64502, 64501, 64501, 64500]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64503, [64503, 64502, 64502, 64501, 64500, 64500]))
|
||||
|
||||
def test_some_unknown(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64505, [64505, 64504, 64503, 64502]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(64503, [64503, 64503, 64502, 64505]))
|
||||
|
||||
def test_all_unknown(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_customer(64506, [64506, 64507, 64508]))
|
||||
|
||||
def test_some_invalid(self):
|
||||
self.assertTrue(self.validator.is_aspa_invalid_peer(64505, [64505, 64505, 64503, 64503]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_peer(64504, [64504, 64503, 64506, 64500]))
|
||||
|
||||
def test_peer_originated(self):
|
||||
for i in [64500, 64501, 64502, 64503, 64504, 64505]:
|
||||
self.assertFalse(self.validator.is_aspa_invalid_peer(i, [i]))
|
||||
|
||||
|
||||
class UpstreamTest(unittest.TestCase):
|
||||
validator_class = Validator
|
||||
|
||||
def setUp(self):
|
||||
# 6451x are tier 1 ISPs
|
||||
# 6452x are tier 2 ISPs
|
||||
# 6453x are tier 3 ISPs
|
||||
self.validator = self.validator_class([
|
||||
ASPA(64510, [], 'test'),
|
||||
ASPA(64511, [], 'test'),
|
||||
ASPA(64512, [], 'test'),
|
||||
ASPA(64514, [], 'test'),
|
||||
ASPA(64520, [64510, 64511], 'test'),
|
||||
ASPA(64521, [64512, 64513], 'test'),
|
||||
ASPA(64522, [64511, 64512], 'test'),
|
||||
ASPA(64530, [64520], 'test'),
|
||||
ASPA(64531, [64521, 64523], 'test'),
|
||||
])
|
||||
|
||||
def test_all_valid(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64530, [64520, 64510, 64512, 64521, 64531]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64520, [64510, 64512, 64521, 64531]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64521, [64512, 64510, 64520, 64520, 64530]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64531, [64521, 64512, 64510, 64520, 64530]))
|
||||
|
||||
def test_valid_edge(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64530, [64520, 64510]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64530, [64520]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64520, [64510]))
|
||||
|
||||
def test_tier_1_tier_2_peer(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64530, [64520, 64512, 64521, 64531]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64521, [64510, 64510, 64520, 64520, 64530]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64531, [64521, 64510, 64520, 64530]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64531, [64521, 64510, 64510, 64520, 64520]))
|
||||
|
||||
def test_some_unknown(self):
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64530, [64520, 64510, 64513, 64521, 64531]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64520, [64510, 64513, 64521, 64531]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64521, [64510, 64510, 64520, 64520, 64530]))
|
||||
self.assertFalse(self.validator.is_aspa_invalid_upstream(64531, [64521, 64510, 64520, 64530]))
|
||||
|
||||
def test_invalid_downramp(self):
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64520, 64510, 64512, 64522, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64520, 64510, 64512, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64521, 64512, 64510, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64521, 64512, 64510, 64522, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64520, 64512, 64522, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64521, [64510, 64510, 64520, 64522, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64521, [64510, 64510, 64522, 64520, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64520, 64510, 64522, 64531]))
|
||||
|
||||
def test_invalid_upramp(self):
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64520, 64513, 64512, 64521, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64521, 64510, 64512, 64521, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64520, 64512, 64510, 64520, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64521, 64511, 64510, 64520, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64520, 64514, 64521, 64521, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64521, 64510, 64521, 64531, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64520, 64512, 64520, 64520, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64521, 64514, 64520, 64530, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64520, 64520, 64514, 64521, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64530, [64521, 64510, 64510, 64521, 64531]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64520, 64512, 64512, 64520, 64530]))
|
||||
self.assertTrue(self.validator.is_aspa_invalid_upstream(64531, [64521, 64521, 64514, 64520, 64530]))
|
||||
|
||||
|
||||
class BirdCustomerTest(CustomerTest):
|
||||
validator_class = BirdValidator
|
||||
|
||||
|
||||
class BirdPeerTest(PeerTest):
|
||||
validator_class = BirdValidator
|
||||
|
||||
|
||||
class BirdUpstreamTest(UpstreamTest):
|
||||
validator_class = BirdValidator
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -1,96 +0,0 @@
|
|||
from itertools import chain, dropwhile
|
||||
|
||||
from aspa.data import ASPA
|
||||
|
||||
|
||||
class Validator:
|
||||
def __init__(self, aspas: list[ASPA]):
|
||||
self.aspas = {aspa.customer: aspa for aspa in aspas}
|
||||
|
||||
def is_invalid_pair(self, upstream: int, downstream: int) -> bool:
|
||||
if downstream not in self.aspas:
|
||||
return False
|
||||
|
||||
return upstream not in self.aspas[downstream].providers
|
||||
|
||||
def is_aspa_invalid_customer(self, my_asn: int, bgp_path: list[int]) -> bool:
|
||||
for prev_asn, asn in zip(chain([my_asn], bgp_path), bgp_path):
|
||||
# Ignore AS-path prepends
|
||||
if prev_asn == asn:
|
||||
continue
|
||||
|
||||
if self.is_invalid_pair(prev_asn, asn):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def is_aspa_invalid_peer(self, peer_asn: int, bgp_path: list[int]) -> bool:
|
||||
remove_peer = list(dropwhile(lambda asn: asn != peer_asn, bgp_path))
|
||||
|
||||
for prev_asn, asn in zip(chain([peer_asn], remove_peer), remove_peer):
|
||||
if prev_asn == asn:
|
||||
continue
|
||||
|
||||
if self.is_invalid_pair(prev_asn, asn):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def is_aspa_invalid_upstream(self, my_asn: int, bgp_path: list[int]) -> bool:
|
||||
max_up_ramp = len(bgp_path)
|
||||
min_down_ramp = 0
|
||||
|
||||
for i, (prev_asn, asn) in enumerate(zip(chain([my_asn], bgp_path), bgp_path)):
|
||||
if prev_asn == asn:
|
||||
continue
|
||||
|
||||
if self.is_invalid_pair(asn, prev_asn):
|
||||
max_up_ramp = min(max_up_ramp, i)
|
||||
|
||||
if self.is_invalid_pair(prev_asn, asn):
|
||||
min_down_ramp = max(min_down_ramp, i)
|
||||
|
||||
return min_down_ramp > max_up_ramp
|
||||
|
||||
|
||||
class BirdValidator(Validator):
|
||||
"""Validator coded with only language features available in bird DSL."""
|
||||
|
||||
def is_aspa_invalid_customer(self, my_asn: int, bgp_path: list[int]) -> bool:
|
||||
prev_asn = my_asn
|
||||
|
||||
for asn in bgp_path:
|
||||
if prev_asn != asn and self.is_invalid_pair(prev_asn, asn):
|
||||
return True
|
||||
prev_asn = asn
|
||||
|
||||
return False
|
||||
|
||||
def is_aspa_invalid_peer(self, peer_asn: int, bgp_path: list[int]) -> bool:
|
||||
prev_asn = peer_asn
|
||||
|
||||
for asn in bgp_path:
|
||||
if asn != peer_asn and prev_asn != asn and self.is_invalid_pair(prev_asn, asn):
|
||||
return True
|
||||
prev_asn = asn
|
||||
|
||||
return False
|
||||
|
||||
def is_aspa_invalid_upstream(self, my_asn: int, bgp_path: list[int]) -> bool:
|
||||
prev_asn = my_asn
|
||||
max_up_ramp = len(bgp_path)
|
||||
min_down_ramp = 0
|
||||
i = 0
|
||||
|
||||
for asn in bgp_path:
|
||||
if prev_asn != asn:
|
||||
if self.is_invalid_pair(asn, prev_asn) and max_up_ramp > i:
|
||||
max_up_ramp = i
|
||||
|
||||
if self.is_invalid_pair(prev_asn, asn) and min_down_ramp < i:
|
||||
min_down_ramp = i
|
||||
|
||||
prev_asn = asn
|
||||
i += 1
|
||||
|
||||
return min_down_ramp > max_up_ramp
|
|
@ -1,46 +0,0 @@
|
|||
function is_aspa_invalid_customer() {
|
||||
int prev_asn = MY_ASN;
|
||||
|
||||
for int cur_asn in bgp_path do {
|
||||
if prev_asn != cur_asn && is_aspa_invalid_pair(prev_asn, cur_asn) then
|
||||
return true;
|
||||
prev_asn = cur_asn;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function is_aspa_invalid_peer(int peer_asn) {
|
||||
int prev_asn = peer_asn;
|
||||
|
||||
for int cur_asn in bgp_path do {
|
||||
if cur_asn != peer_asn && prev_asn != cur_asn &&
|
||||
is_aspa_invalid_pair(prev_asn, cur_asn) then
|
||||
return true;
|
||||
prev_asn = cur_asn;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function is_aspa_invalid_upstream() {
|
||||
int prev_asn = MY_ASN;
|
||||
int max_up_ramp = bgp_path.len;
|
||||
int min_down_ramp = 0;
|
||||
int i = 0;
|
||||
|
||||
for int cur_asn in bgp_path do {
|
||||
if prev_asn != cur_asn then {
|
||||
if is_aspa_invalid_pair(cur_asn, cur_asn) && max_up_ramp > i then
|
||||
max_up_ramp = i;
|
||||
|
||||
if is_aspa_invalid_pair(prev_asn, cur_asn) && min_down_ramp < i then
|
||||
min_down_ramp = i;
|
||||
}
|
||||
|
||||
prev_asn = cur_asn;
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
return min_down_ramp > max_up_ramp;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
|
||||
from aspa.data import parse_json
|
||||
from aspa.generate import generate_bird
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Generates is_aspa_invalid_pair function for bird')
|
||||
parser.add_argument('aspa_json', type=str, help='the JSON file with ASPA data')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.aspa_json) as f:
|
||||
aspas = parse_json(f.read())
|
||||
|
||||
print(generate_bird(aspas))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in a new issue