faucetsdn / beka Goto Github PK
View Code? Open in Web Editor NEWA Python BGP Speaker
License: Apache License 2.0
A Python BGP Speaker
License: Apache License 2.0
Hello hello,
Parsing this message:
20:57:20.386957 IP6 (class 0xc0, flowlabel 0x5e6ef, hlim 1, next-header TCP (6) payload length: 136) 2404:138:134:120::1.58823 > 2404:138:134:120::2.179: Flags [P.], cksum 0x96aa (correct), seq 64:168, ack 63, win 17074, options [nop,nop,TS val 2962291451 ecr 242517267], length 104: BGP
Keepalive Message (4), length: 19
Update Message (2), length: 85
Origin (1), length: 1, Flags [T]: IGP
0x0000: 00
AS Path (2), length: 6, Flags [T]: 38022
0x0000: 0201 0000 9486
Community (8), length: 4, Flags [OT]: 38022:10700
0x0000: 9486 29cc
Multi-Protocol Reach NLRI (14), length: 38, Flags [OE]:
AFI: IPv6 (2), SAFI: Unicast (1)
nexthop: 2404:138:134:120::1, fe80::f21c:2dff:fe7f:a796, nh-length: 32, no SNPA
::/0
0x0000: 0002 0120 2404 0138 0134 0120 0000 0000
0x0010: 0000 0001 fe80 0000 0000 0000 f21c 2dff
0x0020: fe7f a796 0000
Which looks like this on the wire:
0000 90 0e 00 26 00 02 01 20 24 04 01 38 01 34 01 20 ...&... $..8.4.
0010 00 00 00 00 00 00 00 01 fe 80 00 00 00 00 00 00 ................
0020 f2 1c 2d ff fe 7f a7 96 00 00 ..-.......
Causes a crash on line 317 in bgp_message.py, because during
afi, safi, next_hop_length = struct.unpack("!HBB", stream.read(4))
The BytesIO object is being created from an empty string. Tracking it back a little bit I have found that in parse_path_attributes the packed_attribute being passed in is just '\x00', which seems wrong.
I ran out of time tonight, but I can have another poke at this later. v4 is working with Juniper OK, from what I can tell.
I noticed that some of the tests fail on Python 3.5.2, but all tests pass on Python 3.6. I think this is due to the way the tests are written, not to bugs in the code.
The BgpMessageTestCase.test_open_message_packs_capabilities
failure looks like a case of dict ordering changing between versions. Python 3.6 maintains the original order, while the dict ordering in Python 3.5.2 is non-deterministic.
==================================== test session starts =====================================
platform darwin -- Python 3.5.2, pytest-3.6.0, py-1.5.3, pluggy-0.6.0
rootdir: /Users/bfish/code/beka, inifile:
plugins: cov-2.5.1
collected 65 items
test/test_beka.py ... [ 4%]
test/test_bgp_message.py .....F................. [ 40%]
test/test_chopper.py ... [ 44%]
test/test_ip.py .. [ 47%]
test/test_peering.py .F [ 50%]
test/test_state_machine.py ...............F.............. [ 96%]
test/test_timer.py .. [100%]
========================================== FAILURES ==========================================
__________________ BgpMessageTestCase.test_open_message_packs_capabilities ___________________
self = <test_bgp_message.BgpMessageTestCase testMethod=test_open_message_packs_capabilities>
def test_open_message_packs_capabilities(self):
expected_serialised_message = build_byte_string("04fe0900b4c0a8000f160214010400010001010400020001020041040000fdeb")
capabilities = {
"multiprotocol": ["ipv4-unicast", "ipv6-unicast"],
"routerefresh": [True],
"fourbyteas": [65003]
}
message = BgpOpenMessage(4, 65033, 180, IP4Address.from_string("192.168.0.15"), capabilities)
serialised_message = BgpMessagePacker().pack(message)
> self.assertEqual(serialised_message[19:], expected_serialised_message)
E AssertionError: b'\x0[38 chars]2\x14A\x04\x00\x00\xfd\xeb\x02\x00\x01\x04\x00[32 chars]\x01' != b'\x0[38 chars]2\x14\x01\x04\x00\x01\x00\x01\x01\x04\x00\x02\[32 chars]\xeb'
test/test_bgp_message.py:77: AssertionError
__________________________ PeeringTestCase.test_run_starts_threads ___________________________
self = <test_peering.PeeringTestCase testMethod=test_run_starts_threads>
def test_run_starts_threads(self):
with patch("beka.peering.GreenPool") as GreenPool:
self.peering.run()
GreenPool().spawn.assert_has_calls([
call(self.peering.send_messages),
call(self.peering.print_route_updates),
call(self.peering.kick_timers),
call(self.peering.receive_messages),
])
> GreenPool().waitall.assert_called_once()
test/test_peering.py:66:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <MagicMock name='GreenPool().waitall' id='4391708992'>, name = 'assert_called_once'
def __getattr__(self, name):
if name in {'_mock_methods', '_mock_unsafe'}:
raise AttributeError(name)
elif self._mock_methods is not None:
if name not in self._mock_methods or name in _all_magics:
raise AttributeError("Mock object has no attribute %r" % name)
elif _is_magic(name):
raise AttributeError(name)
if not self._mock_unsafe:
if name.startswith(('assert', 'assret')):
> raise AttributeError(name)
E AttributeError: assert_called_once
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/mock.py:583: AttributeError
__________ StateMachineOpenConfirmTestCase.test_keepalive_message_sends_all_routes ___________
self = <test_state_machine.StateMachineOpenConfirmTestCase testMethod=test_keepalive_message_sends_all_routes>
def test_keepalive_message_sends_all_routes(self):
self.tick += 3600
self.state_machine.routes_to_advertise = [
RouteAddition(
IP4Prefix.from_string("10.0.0.0/8"),
IP4Address.from_string("192.168.1.33"),
"",
"IGP"
),
RouteAddition(
IP4Prefix.from_string("192.168.64.0/23"),
IP4Address.from_string("192.168.1.33"),
"",
"IGP"
),
RouteAddition(
IP4Prefix.from_string("192.168.128.0/23"),
IP4Address.from_string("192.168.1.34"),
"",
"IGP"
)
]
message = BgpKeepaliveMessage()
self.state_machine.event(EventMessageReceived(message), self.tick)
self.assertEqual(self.state_machine.state, "established")
self.assertTrue(self.state_machine.timers["hold"].running())
self.assertFalse(self.state_machine.timers["hold"].expired(self.tick))
self.assertEqual(self.state_machine.output_messages.qsize(), 2)
first_update = self.state_machine.output_messages.get()
second_update = self.state_machine.output_messages.get()
self.assertTrue(isinstance(first_update, BgpUpdateMessage))
self.assertTrue(isinstance(second_update, BgpUpdateMessage))
> self.assertEqual(first_update.path_attributes["next_hop"], IP4Address.from_string("192.168.1.33"))
E AssertionError: IP4Address.from_string("192.168.1.34") != IP4Address.from_string("192.168.1.33")
test/test_state_machine.py:238: AssertionError
---------- coverage: platform darwin, python 3.5.2-final-0 -----------
Coverage XML written to file coverage.xml
============================ 3 failed, 62 passed in 1.45 seconds =============================
These are stateless but 32-bit ASN support means the parser needs to hold some state (as_set encodes differently whether our peer is old or new). The cleanest way to do this is to have a parser/packer that holds this state and then picks the right packer/parser as needed. Currently this will just be the path attributes field in the update message.
The issue with eventlet + dnspython has been fixed in recent eventlet versions. The need to pin it introduced in #7b4eb28577ed76f5d10218b9e910d610fc36c29d can probably be removed.
I ran into this issue when running latest official Faucet + Beka before dnspython was pinned.
It'd be great to be able to compare Bekas, using (for example):
self.local_address = local_address
self.bgp_port = bgp_port
self.local_as = local_as
self.router_id = router_id
That way we can decide whether we need to start a new Beka or not by comparing it to an existing one.
Repackage beka with https://docs.openstack.org/pbr/
Currently we only handle passive, active will be useful
32b is the standard now and has been for at least 5 years
Step towards #1
We're really not doing this properly, let's make it actually a thing
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
.github/workflows/release-debian.yml
actions/checkout v3
faucetsdn/action-packagecloud-upload-debian-packages v1
.github/workflows/release-python.yml
actions/checkout v3
actions/setup-python v4
pypa/gh-action-pypi-publish v1.5.1
.github/workflows/tests-codecheck.yml
actions/checkout v3
actions/setup-python v4
actions/checkout v3
actions/setup-python v4
.github/workflows/tests-unit.yml
actions/checkout v3
actions/setup-python v4
codecov/codecov-action v3
.github/workflows/tests-yaml-lint.yml
actions/checkout v3
ibiqlik/action-yamllint v3
codecheck-requirements.txt
pylint ==2.15.4
pytype ==2022.10.13
requirements.txt
eventlet >=0.25.1,<=0.33.0
pbr >=1.9
test-requirements.txt
setup.py
pbr >=1.9
setuptools >=17.1
Currently we make the other peer send the first OPEN message, but in practice we need to either send an OPEN message when the connection starts, or start a timer that eventually initiates with an OPEN method. Both of these would then move to the OpenSent stage which hasn't yet been defined.
The current behaviour is as if we have an OpenDelayTimer set with a super high value which isn't necessarily wrong, but isn't the right intention (and makes it harder for us to build active peering)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.