Skip to content

Commit a60e847

Browse files
committed
add asn flap tool
1 parent bf099c2 commit a60e847

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

asn-stream.py

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/usr/bin/env python3
2+
""" Subscribe to the RIPE RIS-Live stream and process it """
3+
4+
## (c) 2019 Jared Mauch
5+
6+
import json
7+
import time
8+
import websocket
9+
import sys
10+
11+
## Uncomment and update this with a unique identifier for the RIPE team
12+
#url = "wss://ris-live.ripe.net/v1/ws/?client=username_at_example_com"
13+
14+
asn = '20940'
15+
16+
# store start time
17+
last_periodic = time.time()
18+
periodic_interval = 90 # 90 seconds
19+
20+
noisy_prefix = {}
21+
noisy_aspath = {}
22+
while True:
23+
ws = websocket.WebSocket()
24+
try:
25+
ws.connect(url)
26+
except websocket.WebSocketBadStatusException as e:
27+
print(e, "while calling connect()")
28+
time.sleep(30)
29+
continue
30+
31+
# subscribe to all BGP Updates
32+
ws.send(json.dumps({"type": "ris_subscribe", "data": {"type": "UPDATE", "path": asn}}))
33+
try:
34+
for data in ws:
35+
# get current time
36+
now = time.time()
37+
if now - last_periodic > periodic_interval:
38+
print("============ periodic ============")
39+
#
40+
count = 0
41+
for k ,v in sorted(noisy_prefix.items(), key=lambda kv:(kv[1], kv[0]), reverse=True):
42+
if count > 10:
43+
break
44+
if noisy_prefix[k] > 100:
45+
print(k, noisy_prefix[k])
46+
count = count + 1
47+
count = 0
48+
for k, v in sorted(noisy_aspath.items(), key=lambda kv:(kv[1], kv[0]), reverse=True):
49+
if count > 10:
50+
break
51+
if noisy_aspath[k] > 100:
52+
print(k, noisy_aspath[k])
53+
count = count + 1
54+
55+
noisy_prefix = {}
56+
noisy_aspath = {}
57+
last_periodic = now
58+
print("============ periodic ============")
59+
#
60+
61+
parsed = json.loads(data)
62+
if parsed.get('type', None) == 'ris_error':
63+
print(data)
64+
if parsed.get('type', None) == 'ris_message':
65+
# print(parsed["type"], parsed["data"])
66+
parsed_data = parsed.get("data", None)
67+
announcements = parsed_data.get('announcements', None)
68+
withdrawls = parsed_data.get('withdrawls', None)
69+
try:
70+
as_path = ' '.join(str(x) for x in parsed_data.get('path', None))
71+
except:
72+
as_path = ''
73+
if announcements is not None:
74+
for announcement in announcements:
75+
for prefix in announcement['prefixes']:
76+
# print("add|%s|%s" % (prefix, as_path))
77+
noisy_prefix[prefix] = noisy_prefix.get(prefix, 0) + 1
78+
noisy_aspath[as_path] = noisy_aspath.get(as_path, 0) + 1
79+
80+
if withdrawls is not None:
81+
for announcement in withdrawls:
82+
for prefix in announcement['prefixes']:
83+
# print("del|%s|%s" % (prefix, as_path))
84+
noisy_prefix[prefix] = noisy_prefix.get(prefix, 0) + 1
85+
noisy_aspath[as_path] = noisy_aspath.get(as_path, 0) + 1
86+
87+
except websocket.WebSocketConnectionClosedException as e:
88+
print("Disconnected, sleeping for a few then reconnect", e)
89+
time.sleep(30)
90+
except ConnectionResetError as e:
91+
print("Disconnected, sleeping for a few then reconnect", e)
92+
time.sleep(30)
93+
except BrokenPipeError as e:
94+
print("Disconnected, sleeping for a few then reconnect", e)
95+
time.sleep(30)
96+
except websocket.WebSocketBadStatusException as e:
97+
print("Disconnected, sleeping for a few then reconnect", e)
98+
time.sleep(30)
99+
except websocket.WebSocketTimeoutException as e:
100+
print("Disconnected, sleeping for a few then reconnect", e)
101+
time.sleep(30)
102+
except KeyboardInterrupt:
103+
print("User stop requested")
104+
sys.exit()
105+
except Exception as e:
106+
print("some other error?", e)
107+
time.sleep(30)
108+
109+
##
110+
## ris_message
111+
### {'timestamp': 1550258410.78,
112+
### 'peer': '217.29.66.88',
113+
### 'peer_asn': '20811',
114+
### 'id': '217.29.66.88-1550258410.78-59479614',
115+
### 'host': 'rrc10',
116+
### 'type': 'UPDATE',
117+
### 'path': [20811, 8529, 9155, 51914, 51914, 51914, 51914],
118+
### 'origin': 'igp',
119+
### 'announcements':
120+
### [{'next_hop': '217.29.67.63', 'prefixes': ['91.221.128.0/24']} ]
121+
### }
122+
## ris_message
123+
### {'timestamp': 1550258410.78,
124+
### 'peer': '217.29.66.88',
125+
### 'peer_asn': '20811',
126+
### 'id': '217.29.66.88-1550258410.78-59479616',
127+
### 'host': 'rrc10',
128+
### 'type': 'UPDATE',
129+
### 'path': [20811, 8529, 49666, 42440, 205647, 44400, 47843],
130+
### 'origin': 'igp',
131+
### 'announcements': [
132+
#### {'next_hop': '217.29.67.63',
133+
#### 'prefixes':
134+
##### ['87.248.144.0/24',
135+
##### '87.248.150.0/24',
136+
##### '87.248.139.0/24',
137+
##### '87.248.153.0/24',
138+
##### '87.248.149.0/24',
139+
##### '87.248.145.0/24',
140+
##### '87.248.152.0/24',
141+
##### '87.248.151.0/24',
142+
##### '87.248.138.0/24',
143+
##### '87.248.133.0/24',
144+
##### '87.248.147.0/24',
145+
##### '87.248.155.0/24',
146+
##### '87.248.131.0/24',
147+
##### '87.248.132.0/24',
148+
##### '87.248.136.0/24',
149+
##### '87.248.154.0/24',
150+
##### '87.248.156.0/24',
151+
##### '87.248.158.0/24',
152+
##### '87.248.134.0/24',
153+
##### '87.248.135.0/24',
154+
##### '87.248.129.0/24',
155+
##### '87.248.130.0/24',
156+
##### '87.248.146.0/24',
157+
##### '87.248.128.0/24',
158+
##### '87.248.137.0/24']
159+
#### }
160+
### ]
161+
### }

0 commit comments

Comments
 (0)