mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 13:06:51 +00:00
Merge pull request #15448 from louis-6wind/bmp-labels
bgpd: export labels into BMP
This commit is contained in:
commit
9feb1aab76
@ -910,7 +910,8 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags,
|
|||||||
|
|
||||||
static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
|
static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
|
||||||
struct peer *peer, struct attr *attr,
|
struct peer *peer, struct attr *attr,
|
||||||
afi_t afi, safi_t safi)
|
afi_t afi, safi_t safi, mpls_label_t *label,
|
||||||
|
uint32_t num_labels)
|
||||||
{
|
{
|
||||||
struct bpacket_attr_vec_arr vecarr;
|
struct bpacket_attr_vec_arr vecarr;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
@ -946,8 +947,8 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
|
|||||||
|
|
||||||
mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
|
mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
|
||||||
&vecarr, attr);
|
&vecarr, attr);
|
||||||
bgp_packet_mpattr_prefix(s, afi, safi, p, prd, NULL, 0, 0, 0,
|
bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
|
||||||
attr);
|
num_labels, 0, 0, attr);
|
||||||
bgp_packet_mpattr_end(s, mpattrlen_pos);
|
bgp_packet_mpattr_end(s, mpattrlen_pos);
|
||||||
total_attr_len += stream_get_endp(s) - p1;
|
total_attr_len += stream_get_endp(s) - p1;
|
||||||
}
|
}
|
||||||
@ -1002,7 +1003,8 @@ static struct stream *bmp_withdraw(const struct prefix *p,
|
|||||||
static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
|
static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
|
||||||
uint8_t peer_type_flag, const struct prefix *p,
|
uint8_t peer_type_flag, const struct prefix *p,
|
||||||
struct prefix_rd *prd, struct attr *attr, afi_t afi,
|
struct prefix_rd *prd, struct attr *attr, afi_t afi,
|
||||||
safi_t safi, time_t uptime)
|
safi_t safi, time_t uptime, mpls_label_t *label,
|
||||||
|
uint32_t num_labels)
|
||||||
{
|
{
|
||||||
struct stream *hdr, *msg;
|
struct stream *hdr, *msg;
|
||||||
struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
|
struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
|
||||||
@ -1019,7 +1021,8 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
|
|||||||
|
|
||||||
monotime_to_realtime(&tv, &uptime_real);
|
monotime_to_realtime(&tv, &uptime_real);
|
||||||
if (attr)
|
if (attr)
|
||||||
msg = bmp_update(p, prd, peer, attr, afi, safi);
|
msg = bmp_update(p, prd, peer, attr, afi, safi, label,
|
||||||
|
num_labels);
|
||||||
else
|
else
|
||||||
msg = bmp_withdraw(p, prd, afi, safi);
|
msg = bmp_withdraw(p, prd, afi, safi);
|
||||||
|
|
||||||
@ -1219,18 +1222,24 @@ afibreak:
|
|||||||
bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE,
|
bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE,
|
||||||
bn_p, prd, bpi->attr, afi, safi,
|
bn_p, prd, bpi->attr, afi, safi,
|
||||||
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
|
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
|
||||||
: (time_t)(-1L));
|
: (time_t)(-1L),
|
||||||
|
bpi->extra ? bpi->extra->label : NULL,
|
||||||
|
bpi->extra ? bpi->extra->num_labels : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_VALID) &&
|
if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_VALID) &&
|
||||||
CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY))
|
CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY))
|
||||||
bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L,
|
bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L,
|
||||||
BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, bpi->attr,
|
BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, bpi->attr,
|
||||||
afi, safi, bpi->uptime);
|
afi, safi, bpi->uptime,
|
||||||
|
bpi->extra ? bpi->extra->label : NULL,
|
||||||
|
bpi->extra ? bpi->extra->num_labels : 0);
|
||||||
|
|
||||||
if (adjin)
|
if (adjin)
|
||||||
|
/* TODO: set label here when adjin supports labels */
|
||||||
bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
|
bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
|
||||||
bn_p, prd, adjin->attr, afi, safi, adjin->uptime);
|
bn_p, prd, adjin->attr, afi, safi, adjin->uptime,
|
||||||
|
NULL, 0);
|
||||||
|
|
||||||
if (bn)
|
if (bn)
|
||||||
bgp_dest_unlock_node(bn);
|
bgp_dest_unlock_node(bn);
|
||||||
@ -1343,7 +1352,9 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr)
|
|||||||
bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd,
|
bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd,
|
||||||
bpi ? bpi->attr : NULL, afi, safi,
|
bpi ? bpi->attr : NULL, afi, safi,
|
||||||
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
|
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
|
||||||
: (time_t)(-1L));
|
: (time_t)(-1L),
|
||||||
|
(bpi && bpi->extra) ? bpi->extra->label : NULL,
|
||||||
|
(bpi && bpi->extra) ? bpi->extra->num_labels : 0);
|
||||||
written = true;
|
written = true;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -1416,7 +1427,9 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
|
|||||||
bmp_monitor(bmp, peer, BMP_PEER_FLAG_L,
|
bmp_monitor(bmp, peer, BMP_PEER_FLAG_L,
|
||||||
BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd,
|
BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd,
|
||||||
bpi ? bpi->attr : NULL, afi, safi,
|
bpi ? bpi->attr : NULL, afi, safi,
|
||||||
bpi ? bpi->uptime : monotime(NULL));
|
bpi ? bpi->uptime : monotime(NULL),
|
||||||
|
(bpi && bpi->extra) ? bpi->extra->label : NULL,
|
||||||
|
(bpi && bpi->extra) ? bpi->extra->num_labels : 0);
|
||||||
written = true;
|
written = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1428,9 +1441,10 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
|
|||||||
if (adjin->peer == peer)
|
if (adjin->peer == peer)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* TODO: set label here when adjin supports labels */
|
||||||
bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
|
bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
|
||||||
&bqe->p, prd, adjin ? adjin->attr : NULL, afi, safi,
|
&bqe->p, prd, adjin ? adjin->attr : NULL, afi, safi,
|
||||||
adjin ? adjin->uptime : monotime(NULL));
|
adjin ? adjin->uptime : monotime(NULL), NULL, 0);
|
||||||
written = true;
|
written = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,17 @@ router bgp 65501
|
|||||||
neighbor 192:168::2 remote-as 65502
|
neighbor 192:168::2 remote-as 65502
|
||||||
!
|
!
|
||||||
bmp targets bmp1
|
bmp targets bmp1
|
||||||
bmp connect 192.0.178.10 port 1789 min-retry 100 max-retry 10000
|
bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000
|
||||||
exit
|
exit
|
||||||
!
|
!
|
||||||
|
address-family ipv4 vpn
|
||||||
|
neighbor 192.168.0.2 activate
|
||||||
|
neighbor 192.168.0.2 soft-reconfiguration inbound
|
||||||
|
exit-address-family
|
||||||
|
address-family ipv6 vpn
|
||||||
|
neighbor 192:168::2 activate
|
||||||
|
neighbor 192:168::2 soft-reconfiguration inbound
|
||||||
|
exit-address-family
|
||||||
address-family ipv4 unicast
|
address-family ipv4 unicast
|
||||||
neighbor 192.168.0.2 activate
|
neighbor 192.168.0.2 activate
|
||||||
neighbor 192.168.0.2 soft-reconfiguration inbound
|
neighbor 192.168.0.2 soft-reconfiguration inbound
|
||||||
@ -20,3 +28,21 @@ router bgp 65501
|
|||||||
neighbor 192:168::2 soft-reconfiguration inbound
|
neighbor 192:168::2 soft-reconfiguration inbound
|
||||||
exit-address-family
|
exit-address-family
|
||||||
!
|
!
|
||||||
|
router bgp 65502 vrf vrf1
|
||||||
|
bgp router_id 192.168.0.1
|
||||||
|
bgp log-neighbor-changes
|
||||||
|
address-family ipv4 unicast
|
||||||
|
label vpn export 101
|
||||||
|
rd vpn export 444:1
|
||||||
|
rt vpn both 52:100
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
address-family ipv6 unicast
|
||||||
|
label vpn export 103
|
||||||
|
rd vpn export 555:1
|
||||||
|
rt vpn both 54:200
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
exit
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
interface r1-eth0
|
interface r1-eth0
|
||||||
ip address 192.0.178.1/24
|
ip address 192.0.2.1/24
|
||||||
!
|
!
|
||||||
interface r1-eth1
|
interface r1-eth1
|
||||||
ip address 192.168.0.1/24
|
ip address 192.168.0.1/24
|
||||||
|
@ -11,9 +11,36 @@ router bgp 65502
|
|||||||
no neighbor 192:168::1 activate
|
no neighbor 192:168::1 activate
|
||||||
redistribute connected
|
redistribute connected
|
||||||
exit-address-family
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv4 vpn
|
||||||
|
neighbor 192.168.0.1 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv6 vpn
|
||||||
|
neighbor 192:168::1 activate
|
||||||
|
exit-address-family
|
||||||
!
|
!
|
||||||
address-family ipv6 unicast
|
address-family ipv6 unicast
|
||||||
neighbor 192:168::1 activate
|
neighbor 192:168::1 activate
|
||||||
redistribute connected
|
redistribute connected
|
||||||
exit-address-family
|
exit-address-family
|
||||||
!
|
!
|
||||||
|
router bgp 65502 vrf vrf1
|
||||||
|
bgp router-id 192.168.0.2
|
||||||
|
bgp log-neighbor-changes
|
||||||
|
no bgp network import-check
|
||||||
|
address-family ipv4 unicast
|
||||||
|
label vpn export 102
|
||||||
|
rd vpn export 444:2
|
||||||
|
rt vpn both 52:100
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
address-family ipv6 unicast
|
||||||
|
label vpn export 105
|
||||||
|
rd vpn export 555:2
|
||||||
|
rt vpn both 54:200
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
exit
|
||||||
|
@ -55,7 +55,7 @@ LOC_RIB = "loc-rib"
|
|||||||
def build_topo(tgen):
|
def build_topo(tgen):
|
||||||
tgen.add_router("r1")
|
tgen.add_router("r1")
|
||||||
tgen.add_router("r2")
|
tgen.add_router("r2")
|
||||||
tgen.add_bmp_server("bmp1", ip="192.0.178.10", defaultRoute="via 192.0.178.1")
|
tgen.add_bmp_server("bmp1", ip="192.0.2.10", defaultRoute="via 192.0.2.1")
|
||||||
|
|
||||||
switch = tgen.add_switch("s1")
|
switch = tgen.add_switch("s1")
|
||||||
switch.add_link(tgen.gears["r1"])
|
switch.add_link(tgen.gears["r1"])
|
||||||
@ -81,8 +81,8 @@ def setup_module(mod):
|
|||||||
tgen.start_router()
|
tgen.start_router()
|
||||||
|
|
||||||
logger.info("starting BMP servers")
|
logger.info("starting BMP servers")
|
||||||
for _, server in tgen.get_bmp_servers().items():
|
for bmp_name, server in tgen.get_bmp_servers().items():
|
||||||
server.start()
|
server.start(log_file=os.path.join(tgen.logdir, bmp_name, "bmp.log"))
|
||||||
|
|
||||||
|
|
||||||
def teardown_module(_mod):
|
def teardown_module(_mod):
|
||||||
@ -105,7 +105,9 @@ def get_bmp_messages():
|
|||||||
"""
|
"""
|
||||||
messages = []
|
messages = []
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
text_output = tgen.gears["bmp1"].run("cat /var/log/bmp.log")
|
text_output = tgen.gears["bmp1"].run(
|
||||||
|
"cat {}".format(os.path.join(tgen.logdir, "bmp1", "bmp.log"))
|
||||||
|
)
|
||||||
|
|
||||||
for m in text_output.splitlines():
|
for m in text_output.splitlines():
|
||||||
# some output in the bash can break the message decoding
|
# some output in the bash can break the message decoding
|
||||||
@ -121,7 +123,7 @@ def get_bmp_messages():
|
|||||||
return messages
|
return messages
|
||||||
|
|
||||||
|
|
||||||
def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
|
def check_for_prefixes(expected_prefixes, bmp_log_type, policy, labels=None):
|
||||||
"""
|
"""
|
||||||
Check for the presence of the given prefixes in the BMP server logs with
|
Check for the presence of the given prefixes in the BMP server logs with
|
||||||
the given message type and the set policy.
|
the given message type and the set policy.
|
||||||
@ -140,6 +142,12 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
|
|||||||
and "bmp_log_type" in m.keys()
|
and "bmp_log_type" in m.keys()
|
||||||
and m["bmp_log_type"] == bmp_log_type
|
and m["bmp_log_type"] == bmp_log_type
|
||||||
and m["policy"] == policy
|
and m["policy"] == policy
|
||||||
|
and (
|
||||||
|
labels is None
|
||||||
|
or (
|
||||||
|
m["ip_prefix"] in labels.keys() and m["label"] == labels[m["ip_prefix"]]
|
||||||
|
)
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# check for prefixes
|
# check for prefixes
|
||||||
@ -174,7 +182,7 @@ def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True):
|
|||||||
Configure the bgp prefixes.
|
Configure the bgp prefixes.
|
||||||
"""
|
"""
|
||||||
withdraw = "no " if not update else ""
|
withdraw = "no " if not update else ""
|
||||||
vrf = " vrf {}" if vrf else ""
|
vrf = " vrf {}".format(vrf) if vrf else ""
|
||||||
for p in prefixes:
|
for p in prefixes:
|
||||||
ip = ip_network(p)
|
ip = ip_network(p)
|
||||||
cmd = [
|
cmd = [
|
||||||
@ -216,6 +224,45 @@ def unicast_prefixes(policy):
|
|||||||
assert success, "Checking the withdrawed prefixes has been failed !."
|
assert success, "Checking the withdrawed prefixes has been failed !."
|
||||||
|
|
||||||
|
|
||||||
|
def vpn_prefixes(policy):
|
||||||
|
"""
|
||||||
|
Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes.
|
||||||
|
Check if the previous actions are logged in the BMP server with the right
|
||||||
|
message type and the right policy.
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
set_bmp_policy(tgen, "r1", 65501, "bmp1", "vpn", policy)
|
||||||
|
|
||||||
|
prefixes = ["172.31.10.1/32", "2001::2222/128"]
|
||||||
|
|
||||||
|
if policy == PRE_POLICY:
|
||||||
|
# labels are not yet supported in adj-RIB-in. Do not test for the moment
|
||||||
|
labels = None
|
||||||
|
else:
|
||||||
|
# "label vpn export" value in r2/bgpd.conf
|
||||||
|
labels = {
|
||||||
|
"172.31.10.1/32": 102,
|
||||||
|
"2001::2222/128": 105,
|
||||||
|
}
|
||||||
|
|
||||||
|
# add prefixes
|
||||||
|
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, vrf="vrf1")
|
||||||
|
|
||||||
|
logger.info("checking for updated prefixes")
|
||||||
|
# check
|
||||||
|
test_func = partial(check_for_prefixes, prefixes, "update", policy, labels=labels)
|
||||||
|
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||||
|
assert success, "Checking the updated prefixes has been failed !."
|
||||||
|
|
||||||
|
# withdraw prefixes
|
||||||
|
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, vrf="vrf1", update=False)
|
||||||
|
logger.info("checking for withdrawed prefixes")
|
||||||
|
# check
|
||||||
|
test_func = partial(check_for_prefixes, prefixes, "withdraw", policy)
|
||||||
|
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||||
|
assert success, "Checking the withdrawed prefixes has been failed !."
|
||||||
|
|
||||||
|
|
||||||
def test_bmp_server_logging():
|
def test_bmp_server_logging():
|
||||||
"""
|
"""
|
||||||
Assert the logging of the bmp server.
|
Assert the logging of the bmp server.
|
||||||
@ -223,7 +270,9 @@ def test_bmp_server_logging():
|
|||||||
|
|
||||||
def check_for_log_file():
|
def check_for_log_file():
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
output = tgen.gears["bmp1"].run("ls /var/log/")
|
output = tgen.gears["bmp1"].run(
|
||||||
|
"ls {}".format(os.path.join(tgen.logdir, "bmp1"))
|
||||||
|
)
|
||||||
if "bmp.log" not in output:
|
if "bmp.log" not in output:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@ -244,6 +293,16 @@ def test_bmp_bgp_unicast():
|
|||||||
unicast_prefixes(LOC_RIB)
|
unicast_prefixes(LOC_RIB)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bmp_bgp_vpn():
|
||||||
|
# check for the prefixes in the BMP server logging file
|
||||||
|
logger.info("***** VPN prefixes pre-policy logging *****")
|
||||||
|
vpn_prefixes(PRE_POLICY)
|
||||||
|
logger.info("***** VPN prefixes post-policy logging *****")
|
||||||
|
vpn_prefixes(POST_POLICY)
|
||||||
|
logger.info("***** VPN prefixes loc-rib logging *****")
|
||||||
|
vpn_prefixes(LOC_RIB)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = ["-s"] + sys.argv[1:]
|
args = ["-s"] + sys.argv[1:]
|
||||||
sys.exit(pytest.main(args))
|
sys.exit(pytest.main(args))
|
||||||
|
@ -33,24 +33,27 @@ IS_FILTERED = 1 << 7
|
|||||||
if not os.path.exists(LOG_DIR):
|
if not os.path.exists(LOG_DIR):
|
||||||
os.makedirs(LOG_DIR)
|
os.makedirs(LOG_DIR)
|
||||||
|
|
||||||
|
|
||||||
def bin2str_ipaddress(ip_bytes, is_ipv6=False):
|
def bin2str_ipaddress(ip_bytes, is_ipv6=False):
|
||||||
if is_ipv6:
|
if is_ipv6:
|
||||||
return str(ipaddress.IPv6Address(ip_bytes))
|
return str(ipaddress.IPv6Address(ip_bytes))
|
||||||
return str(ipaddress.IPv4Address(ip_bytes[-4:]))
|
return str(ipaddress.IPv4Address(ip_bytes[-4:]))
|
||||||
|
|
||||||
def log2file(logs):
|
|
||||||
|
def log2file(logs, log_file):
|
||||||
"""
|
"""
|
||||||
XXX: extract the useful information and save it in a flat dictionnary
|
XXX: extract the useful information and save it in a flat dictionnary
|
||||||
"""
|
"""
|
||||||
with open(LOG_FILE, 'a') as f:
|
with open(log_file, "a") as f:
|
||||||
f.write(json.dumps(logs) + "\n")
|
f.write(json.dumps(logs) + "\n")
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPCodes:
|
class BMPCodes:
|
||||||
"""
|
"""
|
||||||
XXX: complete the list, provide RFCs.
|
XXX: complete the list, provide RFCs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = 0x3
|
VERSION = 0x3
|
||||||
|
|
||||||
BMP_MSG_TYPE_ROUTE_MONITORING = 0x00
|
BMP_MSG_TYPE_ROUTE_MONITORING = 0x00
|
||||||
@ -107,15 +110,15 @@ class BMPCodes:
|
|||||||
|
|
||||||
# peer down reason code
|
# peer down reason code
|
||||||
BMP_PEER_DOWN_LOCAL_NOTIFY = 0x01
|
BMP_PEER_DOWN_LOCAL_NOTIFY = 0x01
|
||||||
BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0X02
|
BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0x02
|
||||||
BMP_PEER_DOWN_REMOTE_NOTIFY = 0X03
|
BMP_PEER_DOWN_REMOTE_NOTIFY = 0x03
|
||||||
BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0X04
|
BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0x04
|
||||||
BMP_PEER_DOWN_INFO_NO_LONGER = 0x05
|
BMP_PEER_DOWN_INFO_NO_LONGER = 0x05
|
||||||
BMP_PEER_DOWN_SYSTEM_CLOSED = 0X06
|
BMP_PEER_DOWN_SYSTEM_CLOSED = 0x06
|
||||||
|
|
||||||
# termincation message types
|
# termincation message types
|
||||||
BMP_TERM_TYPE_STRING = 0x00
|
BMP_TERM_TYPE_STRING = 0x00
|
||||||
BMP_TERM_TYPE_REASON = 0X01
|
BMP_TERM_TYPE_REASON = 0x01
|
||||||
|
|
||||||
# termination reason code
|
# termination reason code
|
||||||
BMP_TERM_REASON_ADMIN_CLOSE = 0x00
|
BMP_TERM_REASON_ADMIN_CLOSE = 0x00
|
||||||
@ -126,31 +129,32 @@ class BMPCodes:
|
|||||||
|
|
||||||
# policy route tlv
|
# policy route tlv
|
||||||
BMP_ROUTE_POLICY_TLV_VRF = 0x00
|
BMP_ROUTE_POLICY_TLV_VRF = 0x00
|
||||||
BMP_ROUTE_POLICY_TLV_POLICY= 0x01
|
BMP_ROUTE_POLICY_TLV_POLICY = 0x01
|
||||||
BMP_ROUTE_POLICY_TLV_PRE_POLICY = 0x02
|
BMP_ROUTE_POLICY_TLV_PRE_POLICY = 0x02
|
||||||
BMP_ROUTE_POLICY_TLV_POST_POLICY = 0x03
|
BMP_ROUTE_POLICY_TLV_POST_POLICY = 0x03
|
||||||
BMP_ROUTE_POLICY_TLV_STRING = 0x04
|
BMP_ROUTE_POLICY_TLV_STRING = 0x04
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPMsg:
|
class BMPMsg:
|
||||||
"""
|
"""
|
||||||
XXX: should we move register_msg_type and look_msg_type
|
XXX: should we move register_msg_type and look_msg_type
|
||||||
to generic Type class.
|
to generic Type class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
TYPES = {}
|
TYPES = {}
|
||||||
UNKNOWN_TYPE = None
|
UNKNOWN_TYPE = None
|
||||||
HDR_STR = '!BIB'
|
HDR_STR = "!BIB"
|
||||||
MIN_LEN = struct.calcsize(HDR_STR)
|
MIN_LEN = struct.calcsize(HDR_STR)
|
||||||
TYPES_STR = {
|
TYPES_STR = {
|
||||||
BMPCodes.BMP_MSG_TYPE_INITIATION: 'initiation',
|
BMPCodes.BMP_MSG_TYPE_INITIATION: "initiation",
|
||||||
BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: 'peer down notification',
|
BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: "peer down notification",
|
||||||
BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: 'peer up notification',
|
BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: "peer up notification",
|
||||||
BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: 'route monitoring',
|
BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: "route monitoring",
|
||||||
BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: 'statistics report',
|
BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: "statistics report",
|
||||||
BMPCodes.BMP_MSG_TYPE_TERMINATION: 'termination',
|
BMPCodes.BMP_MSG_TYPE_TERMINATION: "termination",
|
||||||
BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: 'route mirroring',
|
BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: "route mirroring",
|
||||||
BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: 'route policy',
|
BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: "route policy",
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -158,6 +162,7 @@ class BMPMsg:
|
|||||||
def _register_type(subcls):
|
def _register_type(subcls):
|
||||||
cls.TYPES[msgtype] = subcls
|
cls.TYPES[msgtype] = subcls
|
||||||
return subcls
|
return subcls
|
||||||
|
|
||||||
return _register_type
|
return _register_type
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -179,15 +184,15 @@ class BMPMsg:
|
|||||||
if len(data) < cls.MIN_LEN:
|
if len(data) < cls.MIN_LEN:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
_version, _len, _type = struct.unpack(cls.HDR_STR, data[0:cls.MIN_LEN])
|
_version, _len, _type = struct.unpack(cls.HDR_STR, data[0 : cls.MIN_LEN])
|
||||||
return _version, _len, _type
|
return _version, _len, _type
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def dissect(cls, data):
|
def dissect(cls, data, log_file=None):
|
||||||
global SEQ
|
global SEQ
|
||||||
version, msglen, msgtype = cls.dissect_header(data)
|
version, msglen, msgtype = cls.dissect_header(data)
|
||||||
|
|
||||||
msg_data = data[cls.MIN_LEN:msglen]
|
msg_data = data[cls.MIN_LEN : msglen]
|
||||||
data = data[msglen:]
|
data = data[msglen:]
|
||||||
|
|
||||||
if version != BMPCodes.VERSION:
|
if version != BMPCodes.VERSION:
|
||||||
@ -202,13 +207,13 @@ class BMPMsg:
|
|||||||
msg_cls.MSG_LEN = msglen - cls.MIN_LEN
|
msg_cls.MSG_LEN = msglen - cls.MIN_LEN
|
||||||
logs = msg_cls.dissect(msg_data)
|
logs = msg_cls.dissect(msg_data)
|
||||||
logs["seq"] = SEQ
|
logs["seq"] = SEQ
|
||||||
log2file(logs)
|
log2file(logs, log_file if log_file else LOG_FILE)
|
||||||
SEQ += 1
|
SEQ += 1
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPPerPeerMessage:
|
class BMPPerPeerMessage:
|
||||||
"""
|
"""
|
||||||
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
||||||
@ -229,30 +234,33 @@ class BMPPerPeerMessage:
|
|||||||
| Timestamp (microseconds) |
|
| Timestamp (microseconds) |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
"""
|
"""
|
||||||
PEER_UNPACK_STR = '!BB8s16sI4sII'
|
|
||||||
|
PEER_UNPACK_STR = "!BB8s16sI4sII"
|
||||||
PEER_TYPE_STR = {
|
PEER_TYPE_STR = {
|
||||||
BMPCodes.BMP_PEER_GLOBAL_INSTANCE: 'global instance',
|
BMPCodes.BMP_PEER_GLOBAL_INSTANCE: "global instance",
|
||||||
BMPCodes.BMP_PEER_RD_INSTANCE: 'route distinguisher instance',
|
BMPCodes.BMP_PEER_RD_INSTANCE: "route distinguisher instance",
|
||||||
BMPCodes.BMP_PEER_LOCAL_INSTANCE: 'local instance',
|
BMPCodes.BMP_PEER_LOCAL_INSTANCE: "local instance",
|
||||||
BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: 'loc-rib instance',
|
BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: "loc-rib instance",
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def dissect(cls, data):
|
def dissect(cls, data):
|
||||||
(peer_type,
|
(
|
||||||
|
peer_type,
|
||||||
peer_flags,
|
peer_flags,
|
||||||
peer_distinguisher,
|
peer_distinguisher,
|
||||||
peer_address,
|
peer_address,
|
||||||
peer_asn,
|
peer_asn,
|
||||||
peer_bgp_id,
|
peer_bgp_id,
|
||||||
timestamp_secs,
|
timestamp_secs,
|
||||||
timestamp_microsecs) = struct.unpack_from(cls.PEER_UNPACK_STR, data)
|
timestamp_microsecs,
|
||||||
|
) = struct.unpack_from(cls.PEER_UNPACK_STR, data)
|
||||||
|
|
||||||
msg = {'peer_type': cls.PEER_TYPE_STR[peer_type]}
|
msg = {"peer_type": cls.PEER_TYPE_STR[peer_type]}
|
||||||
|
|
||||||
if peer_type == 0x03:
|
if peer_type == 0x03:
|
||||||
msg['is_filtered'] = bool(peer_flags & IS_FILTERED)
|
msg["is_filtered"] = bool(peer_flags & IS_FILTERED)
|
||||||
msg['policy'] = 'loc-rib'
|
msg["policy"] = "loc-rib"
|
||||||
else:
|
else:
|
||||||
# peer_flags = 0x0000 0000
|
# peer_flags = 0x0000 0000
|
||||||
# ipv6, post-policy, as-path, adj-rib-out, reserverdx4
|
# ipv6, post-policy, as-path, adj-rib-out, reserverdx4
|
||||||
@ -260,29 +268,29 @@ class BMPPerPeerMessage:
|
|||||||
is_as_path = bool(peer_flags & IS_AS_PATH)
|
is_as_path = bool(peer_flags & IS_AS_PATH)
|
||||||
is_post_policy = bool(peer_flags & IS_POST_POLICY)
|
is_post_policy = bool(peer_flags & IS_POST_POLICY)
|
||||||
is_ipv6 = bool(peer_flags & IS_IPV6)
|
is_ipv6 = bool(peer_flags & IS_IPV6)
|
||||||
msg['policy'] = 'post-policy' if is_post_policy else 'pre-policy'
|
msg["policy"] = "post-policy" if is_post_policy else "pre-policy"
|
||||||
msg['ipv6'] = is_ipv6
|
msg["ipv6"] = is_ipv6
|
||||||
msg['peer_ip'] = bin2str_ipaddress(peer_address, is_ipv6)
|
msg["peer_ip"] = bin2str_ipaddress(peer_address, is_ipv6)
|
||||||
|
|
||||||
|
|
||||||
peer_bgp_id = bin2str_ipaddress(peer_bgp_id)
|
peer_bgp_id = bin2str_ipaddress(peer_bgp_id)
|
||||||
timestamp = float(timestamp_secs) + timestamp_microsecs * (10 ** -6)
|
timestamp = float(timestamp_secs) + timestamp_microsecs * (10**-6)
|
||||||
|
|
||||||
data = data[struct.calcsize(cls.PEER_UNPACK_STR):]
|
data = data[struct.calcsize(cls.PEER_UNPACK_STR) :]
|
||||||
msg.update({
|
msg.update(
|
||||||
'peer_distinguisher': str(RouteDistinguisher(peer_distinguisher)),
|
{
|
||||||
'peer_asn': peer_asn,
|
"peer_distinguisher": str(RouteDistinguisher(peer_distinguisher)),
|
||||||
'peer_bgp_id': peer_bgp_id,
|
"peer_asn": peer_asn,
|
||||||
'timestamp': str(datetime.datetime.fromtimestamp(timestamp)),
|
"peer_bgp_id": peer_bgp_id,
|
||||||
})
|
"timestamp": str(datetime.datetime.fromtimestamp(timestamp)),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return data, msg
|
return data, msg
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING)
|
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING)
|
||||||
class BMPRouteMonitoring(BMPPerPeerMessage):
|
class BMPRouteMonitoring(BMPPerPeerMessage):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def dissect(cls, data):
|
def dissect(cls, data):
|
||||||
data, peer_msg = super().dissect(data)
|
data, peer_msg = super().dissect(data)
|
||||||
@ -290,7 +298,7 @@ class BMPRouteMonitoring(BMPPerPeerMessage):
|
|||||||
return {**peer_msg, **update_msg}
|
return {**peer_msg, **update_msg}
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPStatisticsReport:
|
class BMPStatisticsReport:
|
||||||
"""
|
"""
|
||||||
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
||||||
@ -303,10 +311,11 @@ class BMPStatisticsReport:
|
|||||||
~ ~
|
~ ~
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPPeerDownNotification:
|
class BMPPeerDownNotification:
|
||||||
"""
|
"""
|
||||||
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
||||||
@ -316,10 +325,11 @@ class BMPPeerDownNotification:
|
|||||||
| Data (present if Reason = 1, 2 or 3) |
|
| Data (present if Reason = 1, 2 or 3) |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION)
|
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION)
|
||||||
class BMPPeerUpNotification(BMPPerPeerMessage):
|
class BMPPeerUpNotification(BMPPerPeerMessage):
|
||||||
"""
|
"""
|
||||||
@ -336,7 +346,8 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
|
|||||||
~ ~
|
~ ~
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
"""
|
"""
|
||||||
UNPACK_STR = '!16sHH'
|
|
||||||
|
UNPACK_STR = "!16sHH"
|
||||||
MIN_LEN = struct.calcsize(UNPACK_STR)
|
MIN_LEN = struct.calcsize(UNPACK_STR)
|
||||||
MSG_LEN = None
|
MSG_LEN = None
|
||||||
|
|
||||||
@ -344,16 +355,14 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
|
|||||||
def dissect(cls, data):
|
def dissect(cls, data):
|
||||||
data, peer_msg = super().dissect(data)
|
data, peer_msg = super().dissect(data)
|
||||||
|
|
||||||
(local_addr,
|
(local_addr, local_port, remote_port) = struct.unpack_from(cls.UNPACK_STR, data)
|
||||||
local_port,
|
|
||||||
remote_port) = struct.unpack_from(cls.UNPACK_STR, data)
|
|
||||||
|
|
||||||
msg = {
|
msg = {
|
||||||
**peer_msg,
|
**peer_msg,
|
||||||
**{
|
**{
|
||||||
'local_ip': bin2str_ipaddress(local_addr, peer_msg.get('ipv6')),
|
"local_ip": bin2str_ipaddress(local_addr, peer_msg.get("ipv6")),
|
||||||
'local_port': int(local_port),
|
"local_port": int(local_port),
|
||||||
'remote_port': int(remote_port),
|
"remote_port": int(remote_port),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +371,7 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
|
|||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_INITIATION)
|
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_INITIATION)
|
||||||
class BMPInitiation:
|
class BMPInitiation:
|
||||||
"""
|
"""
|
||||||
@ -374,30 +383,31 @@ class BMPInitiation:
|
|||||||
~ ~
|
~ ~
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
"""
|
"""
|
||||||
TLV_STR = '!HH'
|
|
||||||
|
TLV_STR = "!HH"
|
||||||
MIN_LEN = struct.calcsize(TLV_STR)
|
MIN_LEN = struct.calcsize(TLV_STR)
|
||||||
FIELD_TO_STR = {
|
FIELD_TO_STR = {
|
||||||
BMPCodes.BMP_INIT_INFO_STRING: 'information',
|
BMPCodes.BMP_INIT_INFO_STRING: "information",
|
||||||
BMPCodes.BMP_INIT_ADMIN_LABEL: 'admin_label',
|
BMPCodes.BMP_INIT_ADMIN_LABEL: "admin_label",
|
||||||
BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: 'system_description',
|
BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: "system_description",
|
||||||
BMPCodes.BMP_INIT_SYSTEM_NAME: 'system_name',
|
BMPCodes.BMP_INIT_SYSTEM_NAME: "system_name",
|
||||||
BMPCodes.BMP_INIT_VRF_TABLE_NAME: 'vrf_table_name',
|
BMPCodes.BMP_INIT_VRF_TABLE_NAME: "vrf_table_name",
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def dissect(cls, data):
|
def dissect(cls, data):
|
||||||
msg = {}
|
msg = {}
|
||||||
while len(data) > cls.MIN_LEN:
|
while len(data) > cls.MIN_LEN:
|
||||||
_type, _len = struct.unpack_from(cls.TLV_STR, data[0:cls.MIN_LEN])
|
_type, _len = struct.unpack_from(cls.TLV_STR, data[0 : cls.MIN_LEN])
|
||||||
_value = data[cls.MIN_LEN: cls.MIN_LEN + _len].decode()
|
_value = data[cls.MIN_LEN : cls.MIN_LEN + _len].decode()
|
||||||
|
|
||||||
msg[cls.FIELD_TO_STR[_type]] = _value
|
msg[cls.FIELD_TO_STR[_type]] = _value
|
||||||
data = data[cls.MIN_LEN + _len:]
|
data = data[cls.MIN_LEN + _len :]
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPTermination:
|
class BMPTermination:
|
||||||
"""
|
"""
|
||||||
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
|
||||||
@ -408,14 +418,15 @@ class BMPTermination:
|
|||||||
~ ~
|
~ ~
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPRouteMirroring:
|
class BMPRouteMirroring:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BMPRoutePolicy:
|
class BMPRoutePolicy:
|
||||||
pass
|
pass
|
||||||
|
@ -16,10 +16,12 @@ BGP_MAX_SIZE = 4096
|
|||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
|
parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
|
||||||
parser.add_argument("-p", "--port", type=int, default=1789)
|
parser.add_argument("-p", "--port", type=int, default=1789)
|
||||||
|
parser.add_argument("-l", "--logfile", type=str, default="/var/log/bmp.log")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
ADDRESS, PORT = args.address, args.port
|
ADDRESS, PORT = args.address, args.port
|
||||||
|
LOG_FILE = args.logfile
|
||||||
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
@ -31,7 +33,7 @@ def main():
|
|||||||
while True:
|
while True:
|
||||||
data = connection.recv(BGP_MAX_SIZE)
|
data = connection.recv(BGP_MAX_SIZE)
|
||||||
while len(data) > BMPMsg.MIN_LEN:
|
while len(data) > BMPMsg.MIN_LEN:
|
||||||
data = BMPMsg.dissect(data)
|
data = BMPMsg.dissect(data, log_file=LOG_FILE)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# XXX: do something
|
# XXX: do something
|
||||||
pass
|
pass
|
||||||
|
@ -94,7 +94,9 @@ def get_exabgp_cmd(commander=None):
|
|||||||
return False
|
return False
|
||||||
version = m.group(1)
|
version = m.group(1)
|
||||||
if topotest.version_cmp(version, "4.2.11") < 0:
|
if topotest.version_cmp(version, "4.2.11") < 0:
|
||||||
logging.debug("found exabgp version < 4.2.11 in %s will keep looking", exacmd)
|
logging.debug(
|
||||||
|
"found exabgp version < 4.2.11 in %s will keep looking", exacmd
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
logger.info("Using ExaBGP version %s in %s", version, exacmd)
|
logger.info("Using ExaBGP version %s in %s", version, exacmd)
|
||||||
return True
|
return True
|
||||||
@ -1253,9 +1255,12 @@ class TopoBMPCollector(TopoHost):
|
|||||||
gear += " TopoBMPCollector<>".format()
|
gear += " TopoBMPCollector<>".format()
|
||||||
return gear
|
return gear
|
||||||
|
|
||||||
def start(self):
|
def start(self, log_file=None):
|
||||||
|
log_arg = "-l {}".format(log_file) if log_file else ""
|
||||||
self.run(
|
self.run(
|
||||||
"{}/bmp_collector/bmpserver -a {} -p {}&".format(CWD, self.ip, self.port),
|
"{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
|
||||||
|
CWD, self.ip, self.port, log_arg
|
||||||
|
),
|
||||||
stdout=None,
|
stdout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user