summaryrefslogtreecommitdiffstats
BranchCommit messageAuthorAge
masterhsa: http client honor configured timeoutFlorin Coras46 hours
stable/2410misc: VPP 24.10 Release NotesAndrew Yourtchenko7 weeks
stable/2406prom: test_prom fixMatus Fabian5 months
stable/2402build: update octeon-roc checksum to updated versionDave Wallace5 months
stable/2310sr: use correct reply to sr_policy_add_v2Vratko Polak8 months
stable/2306vpp-swan: fix configuration of policiesGabriel Oginski15 months
stable/2302vlib: reset stop_timer_handle on expired processesMatthew Smith15 months
stable/2210nat: fix nat44 vrf handlersDaniel Béreš21 months
stable/2206misc: VPP 22.06.1 Release NotesDave Wallace22 months
stable/2106ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne22 months
stable/2101ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne22 months
stable/2009ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne22 months
stable/2005ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne22 months
stable/2001ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne22 months
stable/1904ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne22 months
stable/1908ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne22 months
stable/2110ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne23 months
stable/2202ipsec: fix AES CBC IV generation (CVE-2022-46397)Benoît Ganne23 months
stable/1901vlib: address vlib_error_t scaling issueSteven Luong5 years
stable/1807Clean up multi-thread barrier-sync hold-down timerDave Barach6 years
stable/1810mp_safe SW_INTERFACE_DUMP, SW_INTERFACE_DETAILS, SW_INTERFACE_TAG_ADD_DEL,Steven Luong6 years
stable/1804fix packets redirect ineffective on af-packet interfacechenxiang6 years
stable/1801fix issue with missing sample_main in sample pluginDamjan Marion6 years
stable/1710l2-flood: fix restore vnet buffer's flags in the replication routineSteve Shin7 years
stable/1707Add replicate DPO header to export list for VPPSBNeale Ranns7 years
stable/1704VPP debug image with worker threads hit assert on adding IP route with traffi...Neale Ranns7 years
stable/1701Fix pretty-printing in "api trace custom-dump" (VPP-683)Andrew Yourtchenko8 years
stable/1609Vhost: Add thread sync while receiving vhost messagePierre Pfister8 years
stable/1606Fix generate-deb-changelog to handle YY.MM releaseEd Warnicke9 years
stable/testWhitespace probe for CIEd Warnicke9 years
 
TagDownloadAuthorAge
v24.10commit cfa0953251...Andrew Yourtchenko8 weeks
v24.10-rc2commit 466b350538...Andrew Yourtchenko2 months
v24.10-rc1commit b91e15387d...Andrew Yourtchenko3 months
v25.02-rc0commit 8f989630b0...Andrew Yourtchenko3 months
v24.06commit 6e8b350a01...Andrew Yourtchenko6 months
v24.06-rc2commit 55457075d9...Andrew Yourtchenko6 months
v24.06-rc1commit b3304b2b76...Andrew Yourtchenko7 months
v24.10-rc0commit 71e0902454...Andrew Yourtchenko7 months
v24.02commit 455960759b...Andrew Yourtchenko10 months
v24.02-rc2commit 8cbf84dce0...Andrew Yourtchenko10 months
v24.02-rc1commit 3a56e86a73...Andrew Yourtchenko11 months
v24.06-rc0commit 6fb2b3dc72...Andrew Yourtchenko11 months
v23.10commit 7c4027fa5e...Andrew Yourtchenko14 months
v23.10-rc2commit 015a6f7f17...Andrew Yourtchenko14 months
v23.10-rc1commit 14df6fc1ea...Andrew Yourtchenko15 months
v24.02-rc0commit 7419bede7a...Andrew Yourtchenko15 months
v23.06commit 493b8990d1...Andrew Yourtchenko18 months
v23.06-rc2commit 5e6bc730ef...Andrew Yourtchenko18 months
v23.06-rc1commit b60a6477eb...Andrew Yourtchenko19 months
v23.10-rc0commit a7dd04d73b...Andrew Yourtchenko19 months
v23.02commit 5516fc0f3b...Andrew Yourtchenko22 months
v22.10.1commit 57302fe52f...Dave Wallace22 months
v22.06.1commit 1513b381d8...Dave Wallace22 months
v23.02-rc2commit be1b844214...Andrew Yourtchenko22 months
v23.02-rc1commit 42b5a8767c...Andrew Yourtchenko23 months
v23.06-rc0commit 2ebb95228f...Andrew Yourtchenko23 months
v22.10commit 07e0c05e69...Andrew Yourtchenko2 years
v22.10-rc2commit 61bae8a54d...Andrew Yourtchenko2 years
v22.10-rc1commit f845abb5dd...Andrew Yourtchenko2 years
v23.02-rc0commit a2a7a4031b...Andrew Yourtchenko2 years
v22.06commit 0d352a97c5...Andrew Yourtchenko2 years
v22.06-rc2commit ea4bcec987...Andrew Yourtchenko3 years
v22.06-rc1commit 211fa4748c...Andrew Yourtchenko3 years
v22.10-rc0commit e0301eeb7b...Andrew Yourtchenko3 years
v22.02commit 7911f29c51...Andrew Yourtchenko3 years
v22.02-rc2commit 9d2db2eb2e...Andrew Yourtchenko3 years
v22.02-rc1commit 93e5bea2d3...Andrew Yourtchenko3 years
v22.06-rc0commit 017a676654...Andrew Yourtchenko3 years
v21.10.1commit 0385458a56...Andrew Yourtchenko3 years
v21.10commit 0e0384cde9...Andrew Yourtchenko3 years
v21.10-rc2commit c1931b2f09...Andrew Yourtchenko3 years
v21.10-rc1commit fd9d936b3c...Andrew Yourtchenko3 years
v22.02-rc0commit 192c55f2e7...Andrew Yourtchenko3 years
v21.01.1commit 54f8aff02a...Andrew Yourtchenko3 years
v21.06commit fc83f8cc67...Andrew Yourtchenko3 years
v21.06-rc2commit 8b297dbceb...Andrew Yourtchenko4 years
v21.06-rc1commit e82d59f381...Andrew Yourtchenko4 years
v21.10-rc0commit 91d6a94845...Andrew Yourtchenko4 years
v21.01commit 3d2d96e554...Andrew Yourtchenko4 years
v21.01-rc2commit 15db851d93...Andrew Yourtchenko4 years
v21.01-rc1commit 9dab7b9416...Andrew Yourtchenko4 years
v21.06-rc0commit 7742d5b355...Andrew Yourtchenko4 years
v20.09commit 072def4738...Andrew Yourtchenko4 years
v20.09-rc2commit a87deb77da...Andrew Yourtchenko4 years
v20.09-rc1commit fb6d768419...Andrew Yourtchenko4 years
v21.01-rc0commit 0b31630ce7...Andrew Yourtchenko4 years
v19.08.3commit 37e99c22df...Andrew Yourtchenko4 years
v20.05.1commit b1500e9fff...Andrew Yourtchenko4 years
v20.05commit ab572152d9...Andrew Yourtchenko5 years
v20.05-rc2commit 63f9e7cc0e...Andrew Yourtchenko5 years
v20.05-rc1commit b8e9009400...Andrew Yourtchenko5 years
v20.09-rc0commit b163bbb748...Andrew Yourtchenko5 years
v19.08.2commit ec9ce338f0...Andrew Yourtchenko5 years
v20.01commit fce396738f...Andrew Yourtchenko5 years
v20.01-rc2commit 29acfa2ad5...Andrew Yourtchenko5 years
v20.01-rc1commit c7fe31cfff...Andrew Yourtchenko5 years
v20.05-rc0commit 8ad070e102...Andrew Yourtchenko5 years
v19.04.4-rc0commit dfec10d137...Dave Wallace5 years
v19.04.3commit bdb89b9897...Dave Wallace5 years
v19.08.1commit f4dcae4164...Andrew Yourtchenko5 years
v19.08commit 1c586de48c...Andrew Yourtchenko5 years
v19.08-rc2commit 2f51729bb3...Dave Wallace6 years
v19.01.3-rc0commit 6af8243814...Dave Wallace6 years
v19.04.1commit 1662c9cd23...Dave Wallace6 years
v19.01.2commit fa63602fcb...Andrew Yourtchenko6 years
v19.01.2-rc0commit 67a3e2d130...Dave Wallace6 years
v19.04.1-rc0commit 873b9ed405...Dave Wallace6 years
v19.04commit 3d18a191aa...Dave Wallace6 years
v19.04-rc2commit 0d7332e43f...Dave Wallace6 years
v19.08-rc0commit 40fd1f3dfd...Dave Wallace6 years
v19.04-rc1commit e29b8228a2...Dave Wallace6 years
v19.01.1commit cbd68cb711...Dave Wallace6 years
v19.01commit 67d9475ae3...Andrew Yourtchenko6 years
v19.01-rc2commit 0cb68778ec...Andrew Yourtchenko6 years
v19.01-rc1commit 3e2bc759f4...Damjan Marion6 years
v19.04-rc0commit ef080e1f9b...Andrew Yourtchenko6 years
v18.10commit 3a9a6f72d1...Marco Varlese6 years
v18.10-rc2commit b3aff922ff...Marco Varlese6 years
v19.01-rc0commit 4f611176e9...Marco Varlese6 years
v18.10-rc1commit 90395743d3...Marco Varlese6 years
v18.07.1commit 55fbdb9941...Ed Warnicke6 years
v18.07commit db6d6b3058...Ed Warnicke6 years
v18.07-rc2commit c16a23c596...Ed Warnicke6 years
v18.10-rc0commit 0e6f4d6af4...Ed Warnicke6 years
v18.07-rc0commit 3e21eba4d2...Ed Warnicke6 years
v18.07-rc1commit e400a6d1a5...Ed Warnicke6 years
v18.01.2commit 540b31ac8f...Dave Wallace7 years
v18.04commit ac2b7363f4...Chris Luke7 years
v18.04-rc2commit 18744ee680...Chris Luke7 years
v18.04-rc1commit 7ace56b9d8...Chris Luke7 years
v18.01.1commit f13bac295d...Dave Wallace7 years
v18.01commit 9d21268d0a...Dave Wallace7 years
v18.01-rc2commit bbdfeaebf2...Dave Wallace7 years
v18.01-rc1commit 8c2bacde4f...Dave Wallace7 years
v18.04-rc0commit a3a6ec63d3...Dave Wallace7 years
v17.10commit 116af2170e...Florin Coras7 years
v17.10-rc2commit cf6c343710...Florin Coras7 years
v18.01-rc0commit 75a17ecddc...Florin Coras7 years
v17.10-rc1commit 7ea28045aa...Florin Coras7 years
v17.07.01commit 839fa732c1...Neale Ranns7 years
v17.07commit f4f635e7c0...Neale Ranns7 years
v17.07-rc2commit 01d2b4b13a...Neale Ranns7 years
v17.10-rc0commit cdc74273df...Neale Ranns8 years
v17.07-rc1commit ea89b8cf66...Neale Ranns8 years
v17.04.2commit fc69a97116...Ole Troan8 years
v17.04.1commit 7d68ec6134...Ole Troan8 years
v17.04commit 511ee63cbb...Ole Troan8 years
v17.04-rc2commit 92bcecfdcc...Ole Troan8 years
v17.07-rc0commit 87edd671d7...Ole Troan8 years
v17.04-rc1commit cb92fc6edc...Ole Troan8 years
v17.01.1commit 8099e90346...Damjan Marion8 years
v17.01commit cd111b2228...Damjan Marion8 years
v17.01-rc2commit 235c64f067...Damjan Marion8 years
v17.04-rc0commit 2e70d8b31d...Damjan Marion8 years
v17.01-rc1commit 436b319354...Damjan Marion8 years
v17.01-rc0commit 931be3aca2...Ed Warnicke8 years
v16.09commit 21bc8624f5...Keith Burns (alagalah)8 years
v16.09-rc2commit 08377f8ff7...Keith Burns (alagalah)8 years
v16.12-rc0commit 694265d4f1...Dave Barach8 years
v16.09-rc1commit dbc6e3f0bb...Dave Barach8 years
v16.06commit 693f4358de...Ed Warnicke9 years
v16.06-rc3commit cf6511560e...Dave Barach9 years
v16.06-rc2commit b98a3a87a9...Dave Barach9 years
v16.09-rc0commit 862623da6e...Ed Warnicke9 years
v16.06-rc1commit 826d4f7b1f...Ed Warnicke9 years
v1.0.0commit cb9cadad57...Ed Warnicke9 years
.mac2 = bytearray(16) p = (self.mk_tunnel_header(tx_itf, is_ip6) / p) return p def verify_header(self, p, is_ip6=False): if is_ip6 is False: self._test.assertEqual(p[IP].src, self.itf.src) self._test.assertEqual(p[IP].dst, self.endpoint) else: self._test.assertEqual(p[IPv6].src, self.itf.src) self._test.assertEqual(p[IPv6].dst, self.endpoint) self._test.assertEqual(p[UDP].sport, self.itf.port) self._test.assertEqual(p[UDP].dport, self.port) self._test.assert_packet_checksums_valid(p) def consume_init(self, p, tx_itf, is_ip6=False): self.noise.set_as_responder() self.noise_init(self.itf.public_key) self.verify_header(p, is_ip6) init = Wireguard(p[Raw]) self._test.assertEqual(init[Wireguard].message_type, 1) self._test.assertEqual(init[Wireguard].reserved_zero, 0) self.sender = init[WireguardInitiation].sender_index # validate the hash mac_key = blake2s(b'mac1----' + public_key_bytes(self.public_key)).digest() mac1 = blake2s(bytes(init)[0:-32], digest_size=16, key=mac_key).digest() self._test.assertEqual(init[WireguardInitiation].mac1, mac1) # this passes only unencrypted_ephemeral, encrypted_static, # encrypted_timestamp fields of the init payload = self.noise.read_message(bytes(init)[8:-32]) # build the response b = self.noise.write_message() mac_key = blake2s(b'mac1----' + public_key_bytes(self.itf.public_key)).digest() resp = (Wireguard(message_type=2, reserved_zero=0) / WireguardResponse(sender_index=self.receiver_index, receiver_index=self.sender, unencrypted_ephemeral=b[0:32], encrypted_nothing=b[32:])) mac1 = blake2s(bytes(resp)[:-32], digest_size=16, key=mac_key).digest() resp[WireguardResponse].mac1 = mac1 resp = (self.mk_tunnel_header(tx_itf, is_ip6) / resp) self._test.assertTrue(self.noise.handshake_finished) return resp def consume_response(self, p, is_ip6=False): self.verify_header(p, is_ip6) resp = Wireguard(p[Raw]) self._test.assertEqual(resp[Wireguard].message_type, 2) self._test.assertEqual(resp[Wireguard].reserved_zero, 0) self._test.assertEqual(resp[WireguardResponse].receiver_index, self.receiver_index) self.sender = resp[Wireguard].sender_index payload = self.noise.read_message(bytes(resp)[12:60]) self._test.assertEqual(payload, b'') self._test.assertTrue(self.noise.handshake_finished) def decrypt_transport(self, p, is_ip6=False): self.verify_header(p, is_ip6) p = Wireguard(p[Raw]) self._test.assertEqual(p[Wireguard].message_type, 4) self._test.assertEqual(p[Wireguard].reserved_zero, 0) self._test.assertEqual(p[WireguardTransport].receiver_index, self.receiver_index) d = self.noise.decrypt( p[WireguardTransport].encrypted_encapsulated_packet) return d def encrypt_transport(self, p): return self.noise.encrypt(bytes(p)) def validate_encapped(self, rxs, tx, is_ip6=False): for rx in rxs: if is_ip6 is False: rx = IP(self.decrypt_transport(rx)) # chech the oringial packet is present self._test.assertEqual(rx[IP].dst, tx[IP].dst) self._test.assertEqual(rx[IP].ttl, tx[IP].ttl-1) else: rx = IPv6(self.decrypt_transport(rx)) # chech the oringial packet is present self._test.assertEqual(rx[IPv6].dst, tx[IPv6].dst) self._test.assertEqual(rx[IPv6].ttl, tx[IPv6].ttl-1) def want_events(self): self._test.vapi.want_wireguard_peer_events( enable_disable=1, pid=os.getpid(), peer_index=self.index, sw_if_index=self.itf.sw_if_index) def wait_event(self, expect, timeout=5): rv = self._test.vapi.wait_for_event(timeout, "wireguard_peer_event") self._test.assertEqual(rv.flags, expect) self._test.assertEqual(rv.peer_index, self.index) class TestWg(VppTestCase): """ Wireguard Test Case """ error_str = compile(r"Error") wg4_output_node_name = '/err/wg4-output-tun/' wg4_input_node_name = '/err/wg4-input/' wg6_output_node_name = '/err/wg6-output-tun/' wg6_input_node_name = '/err/wg6-input/' kp4_error = wg4_output_node_name + "Keypair error" mac4_error = wg4_input_node_name + "Invalid MAC handshake" peer4_error = wg4_input_node_name + "Peer error" kp6_error = wg6_output_node_name + "Keypair error" mac6_error = wg6_input_node_name + "Invalid MAC handshake" peer6_error = wg6_input_node_name + "Peer error" @classmethod def setUpClass(cls): super(TestWg, cls).setUpClass() try: cls.create_pg_interfaces(range(3)) for i in cls.pg_interfaces: i.admin_up() i.config_ip4() i.config_ip6() i.resolve_arp() i.resolve_ndp() except Exception: super(TestWg, cls).tearDownClass() raise @classmethod def tearDownClass(cls): super(TestWg, cls).tearDownClass() def setUp(self): super(VppTestCase, self).setUp() self.base_kp4_err = self.statistics.get_err_counter(self.kp4_error) self.base_mac4_err = self.statistics.get_err_counter(self.mac4_error) self.base_peer4_err = self.statistics.get_err_counter(self.peer4_error) self.base_kp6_err = self.statistics.get_err_counter(self.kp6_error) self.base_mac6_err = self.statistics.get_err_counter(self.mac6_error) self.base_peer6_err = self.statistics.get_err_counter(self.peer6_error) def test_wg_interface(self): """ Simple interface creation """ port = 12312 # Create interface wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() self.logger.info(self.vapi.cli("sh int")) # delete interface wg0.remove_vpp_config() def test_handshake_hash(self): """ test hashing an init message """ # a init packet generated by linux given the key below h = "0100000098b9032b" \ "55cc4b39e73c3d24" \ "a2a1ab884b524a81" \ "1808bb86640fb70d" \ "e93154fec1879125" \ "ab012624a27f0b75" \ "c0a2582f438ddb5f" \ "8e768af40b4ab444" \ "02f9ff473e1b797e" \ "80d39d93c5480c82" \ "a3d4510f70396976" \ "586fb67300a5167b" \ "ae6ca3ff3dfd00eb" \ "59be198810f5aa03" \ "6abc243d2155ee4f" \ "2336483900aef801" \ "08752cd700000000" \ "0000000000000000" \ "00000000" b = bytearray.fromhex(h) tgt = Wireguard(b) pubb = base64.b64decode("aRuHFTTxICIQNefp05oKWlJv3zgKxb8+WW7JJMh0jyM=") pub = X25519PublicKey.from_public_bytes(pubb) self.assertEqual(pubb, public_key_bytes(pub)) # strip the macs and build a new packet init = b[0:-32] mac_key = blake2s(b'mac1----' + public_key_bytes(pub)).digest() init += blake2s(init, digest_size=16, key=mac_key).digest() init += b'\x00' * 16 act = Wireguard(init) self.assertEqual(tgt, act) def test_wg_peer_resp(self): """ Send handshake response """ port = 12323 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg0.admin_up() wg0.config_ip4() self.pg_enable_capture(self.pg_interfaces) self.pg_start() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip4, port+1, ["10.11.3.0/24"]).add_vpp_config() self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) r1 = VppIpRoute(self, "10.11.3.0", 24, [VppRoutePath("10.11.3.1", wg0.sw_if_index)]).add_vpp_config() # wait for the peer to send a handshake rx = self.pg1.get_capture(1, timeout=2) # consume the handshake in the noise protocol and # generate the response resp = peer_1.consume_init(rx[0], self.pg1) # send the response, get keepalive rxs = self.send_and_expect(self.pg1, [resp], self.pg1) for rx in rxs: b = peer_1.decrypt_transport(rx) self.assertEqual(0, len(b)) # send a packets that are routed into the tunnel p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, p * 255, self.pg1) peer_1.validate_encapped(rxs, p) # send packets into the tunnel, expect to receive them on # the other side p = [(peer_1.mk_tunnel_header(self.pg1) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) r1.remove_vpp_config() peer_1.remove_vpp_config() wg0.remove_vpp_config() def test_wg_peer_v4o4(self): """ Test v4o4""" port = 12333 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg0.admin_up() wg0.config_ip4() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip4, port+1, ["10.11.3.0/24"]).add_vpp_config() self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) r1 = VppIpRoute(self, "10.11.3.0", 24, [VppRoutePath("10.11.3.1", wg0.sw_if_index)]).add_vpp_config() # route a packet into the wg interface # use the allowed-ip prefix # this is dropped because the peer is not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp4_err + 1, self.statistics.get_err_counter(self.kp4_error)) # send a handsake from the peer with an invalid MAC p = peer_1.mk_handshake(self.pg1) p[WireguardInitiation].mac1 = b'foobar' self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_mac4_err + 1, self.statistics.get_err_counter(self.mac4_error)) # send a handsake from the peer but signed by the wrong key. p = peer_1.mk_handshake(self.pg1, False, X25519PrivateKey.generate().public_key()) self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_peer4_err + 1, self.statistics.get_err_counter(self.peer4_error)) # send a valid handsake init for which we expect a response p = peer_1.mk_handshake(self.pg1) rx = self.send_and_expect(self.pg1, [p], self.pg1) peer_1.consume_response(rx[0]) # route a packet into the wg interface # this is dropped because the peer is still not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp4_err + 2, self.statistics.get_err_counter(self.kp4_error)) # send a data packet from the peer through the tunnel # this completes the handshake p = (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw()) d = peer_1.encrypt_transport(p) p = (peer_1.mk_tunnel_header(self.pg1) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peer_1.sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, p * 255, self.pg1) for rx in rxs: rx = IP(peer_1.decrypt_transport(rx)) # chech the oringial packet is present self.assertEqual(rx[IP].dst, p[IP].dst) self.assertEqual(rx[IP].ttl, p[IP].ttl-1) # send packets into the tunnel, expect to receive them on # the other side p = [(peer_1.mk_tunnel_header(self.pg1) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii+1, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) r1.remove_vpp_config() peer_1.remove_vpp_config() wg0.remove_vpp_config() def test_wg_peer_v6o6(self): """ Test v6o6""" port = 12343 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip6, port).add_vpp_config() wg0.admin_up() wg0.config_ip6() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip6, port+1, ["1::3:0/112"]).add_vpp_config(True) self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) r1 = VppIpRoute(self, "1::3:0", 112, [VppRoutePath("1::3:1", wg0.sw_if_index)]).add_vpp_config() # route a packet into the wg interface # use the allowed-ip prefix # this is dropped because the peer is not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst="1::3:2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp6_err + 1, self.statistics.get_err_counter(self.kp6_error)) # send a handsake from the peer with an invalid MAC p = peer_1.mk_handshake(self.pg1, True) p[WireguardInitiation].mac1 = b'foobar' self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_mac6_err + 1, self.statistics.get_err_counter(self.mac6_error)) # send a handsake from the peer but signed by the wrong key. p = peer_1.mk_handshake(self.pg1, True, X25519PrivateKey.generate().public_key()) self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_peer6_err + 1, self.statistics.get_err_counter(self.peer6_error)) # send a valid handsake init for which we expect a response p = peer_1.mk_handshake(self.pg1, True) rx = self.send_and_expect(self.pg1, [p], self.pg1) peer_1.consume_response(rx[0], True) # route a packet into the wg interface # this is dropped because the peer is still not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst="1::3:2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp6_err + 2, self.statistics.get_err_counter(self.kp6_error)) # send a data packet from the peer through the tunnel # this completes the handshake p = (IPv6(src="1::3:1", dst=self.pg0.remote_ip6, hlim=20) / UDP(sport=222, dport=223) / Raw()) d = peer_1.encrypt_transport(p) p = (peer_1.mk_tunnel_header(self.pg1, True) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peer_1.sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0) for rx in rxs: self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(rx[IPv6].hlim, 19) # send a packets that are routed into the tunnel p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst="1::3:2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, p * 255, self.pg1) for rx in rxs: rx = IPv6(peer_1.decrypt_transport(rx, True)) # chech the oringial packet is present self.assertEqual(rx[IPv6].dst, p[IPv6].dst) self.assertEqual(rx[IPv6].hlim, p[IPv6].hlim-1) # send packets into the tunnel, expect to receive them on # the other side p = [(peer_1.mk_tunnel_header(self.pg1, True) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii+1, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IPv6(src="1::3:1", dst=self.pg0.remote_ip6, hlim=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0) for rx in rxs: self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(rx[IPv6].hlim, 19) r1.remove_vpp_config() peer_1.remove_vpp_config() wg0.remove_vpp_config() def test_wg_peer_v6o4(self): """ Test v6o4""" port = 12353 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg0.admin_up() wg0.config_ip6() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip4, port+1, ["1::3:0/112"]).add_vpp_config(True) self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) r1 = VppIpRoute(self, "1::3:0", 112, [VppRoutePath("1::3:1", wg0.sw_if_index)]).add_vpp_config() # route a packet into the wg interface # use the allowed-ip prefix # this is dropped because the peer is not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst="1::3:2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp6_err + 1, self.statistics.get_err_counter(self.kp6_error)) # send a handsake from the peer with an invalid MAC p = peer_1.mk_handshake(self.pg1) p[WireguardInitiation].mac1 = b'foobar' self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_mac4_err + 1, self.statistics.get_err_counter(self.mac4_error)) # send a handsake from the peer but signed by the wrong key. p = peer_1.mk_handshake(self.pg1, False, X25519PrivateKey.generate().public_key()) self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_peer4_err + 1, self.statistics.get_err_counter(self.peer4_error)) # send a valid handsake init for which we expect a response p = peer_1.mk_handshake(self.pg1) rx = self.send_and_expect(self.pg1, [p], self.pg1) peer_1.consume_response(rx[0]) # route a packet into the wg interface # this is dropped because the peer is still not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst="1::3:2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp6_err + 2, self.statistics.get_err_counter(self.kp6_error)) # send a data packet from the peer through the tunnel # this completes the handshake p = (IPv6(src="1::3:1", dst=self.pg0.remote_ip6, hlim=20) / UDP(sport=222, dport=223) / Raw()) d = peer_1.encrypt_transport(p) p = (peer_1.mk_tunnel_header(self.pg1) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peer_1.sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0) for rx in rxs: self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(rx[IPv6].hlim, 19) # send a packets that are routed into the tunnel p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst="1::3:2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, p * 255, self.pg1) for rx in rxs: rx = IPv6(peer_1.decrypt_transport(rx)) # chech the oringial packet is present self.assertEqual(rx[IPv6].dst, p[IPv6].dst) self.assertEqual(rx[IPv6].hlim, p[IPv6].hlim-1) # send packets into the tunnel, expect to receive them on # the other side p = [(peer_1.mk_tunnel_header(self.pg1) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii+1, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IPv6(src="1::3:1", dst=self.pg0.remote_ip6, hlim=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0) for rx in rxs: self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(rx[IPv6].hlim, 19) r1.remove_vpp_config() peer_1.remove_vpp_config() wg0.remove_vpp_config() def test_wg_peer_v4o6(self): """ Test v4o6""" port = 12363 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip6, port).add_vpp_config() wg0.admin_up() wg0.config_ip4() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip6, port+1, ["10.11.3.0/24"]).add_vpp_config() self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) r1 = VppIpRoute(self, "10.11.3.0", 24, [VppRoutePath("10.11.3.1", wg0.sw_if_index)]).add_vpp_config() # route a packet into the wg interface # use the allowed-ip prefix # this is dropped because the peer is not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp4_err + 1, self.statistics.get_err_counter(self.kp4_error)) # send a handsake from the peer with an invalid MAC p = peer_1.mk_handshake(self.pg1, True) p[WireguardInitiation].mac1 = b'foobar' self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_mac6_err + 1, self.statistics.get_err_counter(self.mac6_error)) # send a handsake from the peer but signed by the wrong key. p = peer_1.mk_handshake(self.pg1, True, X25519PrivateKey.generate().public_key()) self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual(self.base_peer6_err + 1, self.statistics.get_err_counter(self.peer6_error)) # send a valid handsake init for which we expect a response p = peer_1.mk_handshake(self.pg1, True) rx = self.send_and_expect(self.pg1, [p], self.pg1) peer_1.consume_response(rx[0], True) # route a packet into the wg interface # this is dropped because the peer is still not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(self.base_kp4_err + 2, self.statistics.get_err_counter(self.kp4_error)) # send a data packet from the peer through the tunnel # this completes the handshake p = (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw()) d = peer_1.encrypt_transport(p) p = (peer_1.mk_tunnel_header(self.pg1, True) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peer_1.sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, p * 255, self.pg1) for rx in rxs: rx = IP(peer_1.decrypt_transport(rx, True)) # chech the oringial packet is present self.assertEqual(rx[IP].dst, p[IP].dst) self.assertEqual(rx[IP].ttl, p[IP].ttl-1) # send packets into the tunnel, expect to receive them on # the other side p = [(peer_1.mk_tunnel_header(self.pg1, True) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii+1, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) r1.remove_vpp_config() peer_1.remove_vpp_config() wg0.remove_vpp_config() def test_wg_multi_peer(self): """ multiple peer setup """ port = 12373 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg1 = VppWgInterface(self, self.pg2.local_ip4, port+1).add_vpp_config() wg0.admin_up() wg1.admin_up() # Check peer counter self.assertEqual(len(self.vapi.wireguard_peers_dump()), 0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Create many peers on sencond interface NUM_PEERS = 16 self.pg2.generate_remote_hosts(NUM_PEERS) self.pg2.configure_ipv4_neighbors() self.pg1.generate_remote_hosts(NUM_PEERS) self.pg1.configure_ipv4_neighbors() peers_1 = [] peers_2 = [] routes_1 = [] routes_2 = [] for i in range(NUM_PEERS): peers_1.append(VppWgPeer(self, wg0, self.pg1.remote_hosts[i].ip4, port+1+i, ["10.0.%d.4/32" % i]).add_vpp_config()) routes_1.append(VppIpRoute(self, "10.0.%d.4" % i, 32, [VppRoutePath(self.pg1.remote_hosts[i].ip4, wg0.sw_if_index)]).add_vpp_config()) peers_2.append(VppWgPeer(self, wg1, self.pg2.remote_hosts[i].ip4, port+100+i, ["10.100.%d.4/32" % i]).add_vpp_config()) routes_2.append(VppIpRoute(self, "10.100.%d.4" % i, 32, [VppRoutePath(self.pg2.remote_hosts[i].ip4, wg1.sw_if_index)]).add_vpp_config()) self.assertEqual(len(self.vapi.wireguard_peers_dump()), NUM_PEERS*2) self.logger.info(self.vapi.cli("show wireguard peer")) self.logger.info(self.vapi.cli("show wireguard interface")) self.logger.info(self.vapi.cli("show adj 37")) self.logger.info(self.vapi.cli("sh ip fib 172.16.3.17")) self.logger.info(self.vapi.cli("sh ip fib 10.11.3.0")) # remove routes for r in routes_1: r.remove_vpp_config() for r in routes_2: r.remove_vpp_config() # remove peers for p in peers_1: self.assertTrue(p.query_vpp_config()) p.remove_vpp_config() for p in peers_2: self.assertTrue(p.query_vpp_config()) p.remove_vpp_config() wg0.remove_vpp_config() wg1.remove_vpp_config() def test_wg_multi_interface(self): """ Multi-tunnel on the same port """ port = 12500 # Create many wireguard interfaces NUM_IFS = 4 self.pg1.generate_remote_hosts(NUM_IFS) self.pg1.configure_ipv4_neighbors() self.pg0.generate_remote_hosts(NUM_IFS) self.pg0.configure_ipv4_neighbors() # Create interfaces with a peer on each peers = [] routes = [] wg_ifs = [] for i in range(NUM_IFS): # Use the same port for each interface wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg0.admin_up() wg0.config_ip4() wg_ifs.append(wg0) peers.append(VppWgPeer(self, wg0, self.pg1.remote_hosts[i].ip4, port+1+i, ["10.0.%d.0/24" % i]).add_vpp_config()) routes.append(VppIpRoute(self, "10.0.%d.0" % i, 24, [VppRoutePath("10.0.%d.4" % i, wg0.sw_if_index)]).add_vpp_config()) self.assertEqual(len(self.vapi.wireguard_peers_dump()), NUM_IFS) for i in range(NUM_IFS): # send a valid handsake init for which we expect a response p = peers[i].mk_handshake(self.pg1) rx = self.send_and_expect(self.pg1, [p], self.pg1) peers[i].consume_response(rx[0]) # send a data packet from the peer through the tunnel # this completes the handshake p = (IP(src="10.0.%d.4" % i, dst=self.pg0.remote_hosts[i].ip4, ttl=20) / UDP(sport=222, dport=223) / Raw()) d = peers[i].encrypt_transport(p) p = (peers[i].mk_tunnel_header(self.pg1) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peers[i].sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_hosts[i].ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel for i in range(NUM_IFS): p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_hosts[i].ip4, dst="10.0.%d.4" % i) / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, p * 64, self.pg1) for rx in rxs: rx = IP(peers[i].decrypt_transport(rx)) # check the oringial packet is present self.assertEqual(rx[IP].dst, p[IP].dst) self.assertEqual(rx[IP].ttl, p[IP].ttl-1) # send packets into the tunnel for i in range(NUM_IFS): p = [(peers[i].mk_tunnel_header(self.pg1) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peers[i].sender, counter=ii+1, encrypted_encapsulated_packet=peers[i].encrypt_transport( (IP(src="10.0.%d.4" % i, dst=self.pg0.remote_hosts[i].ip4, ttl=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(64)] rxs = self.send_and_expect(self.pg1, p, self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_hosts[i].ip4) self.assertEqual(rx[IP].ttl, 19) for r in routes: r.remove_vpp_config() for p in peers: p.remove_vpp_config() for i in wg_ifs: i.remove_vpp_config() def test_wg_event(self): """ Test events """ port = 12600 ESTABLISHED_FLAG = VppEnum.\ vl_api_wireguard_peer_flags_t.\ WIREGUARD_PEER_ESTABLISHED DEAD_FLAG = VppEnum.\ vl_api_wireguard_peer_flags_t.\ WIREGUARD_PEER_STATUS_DEAD # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg1 = VppWgInterface(self, self.pg2.local_ip4, port+1).add_vpp_config() wg0.admin_up() wg1.admin_up() # Check peer counter self.assertEqual(len(self.vapi.wireguard_peers_dump()), 0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Create peers NUM_PEERS = 2 self.pg2.generate_remote_hosts(NUM_PEERS) self.pg2.configure_ipv4_neighbors() self.pg1.generate_remote_hosts(NUM_PEERS) self.pg1.configure_ipv4_neighbors() peers_0 = [] peers_1 = [] routes_0 = [] routes_1 = [] for i in range(NUM_PEERS): peers_0.append(VppWgPeer(self, wg0, self.pg1.remote_hosts[i].ip4, port+1+i, ["10.0.%d.4/32" % i]).add_vpp_config()) routes_0.append(VppIpRoute(self, "10.0.%d.4" % i, 32, [VppRoutePath(self.pg1.remote_hosts[i].ip4, wg0.sw_if_index)]).add_vpp_config()) peers_1.append(VppWgPeer(self, wg1, self.pg2.remote_hosts[i].ip4, port+100+i, ["10.100.%d.4/32" % i]).add_vpp_config()) routes_1.append(VppIpRoute(self, "10.100.%d.4" % i, 32, [VppRoutePath(self.pg2.remote_hosts[i].ip4, wg1.sw_if_index)]).add_vpp_config()) self.assertEqual(len(self.vapi.wireguard_peers_dump()), NUM_PEERS*2) # Want events from the first perr of wg0 # and from all wg1 peers peers_0[0].want_events() wg1.want_events() for i in range(NUM_PEERS): # send a valid handsake init for which we expect a response p = peers_0[i].mk_handshake(self.pg1) rx = self.send_and_expect(self.pg1, [p], self.pg1) peers_0[i].consume_response(rx[0]) if (i == 0): peers_0[0].wait_event(ESTABLISHED_FLAG) p = peers_1[i].mk_handshake(self.pg2) rx = self.send_and_expect(self.pg2, [p], self.pg2) peers_1[i].consume_response(rx[0]) wg1.wait_events( ESTABLISHED_FLAG, [peers_1[0].index, peers_1[1].index]) # remove routes for r in routes_0: r.remove_vpp_config() for r in routes_1: r.remove_vpp_config() # remove peers for i in range(NUM_PEERS): self.assertTrue(peers_0[i].query_vpp_config()) peers_0[i].remove_vpp_config() if (i == 0): peers_0[i].wait_event(0) peers_0[i].wait_event(DEAD_FLAG) for p in peers_1: self.assertTrue(p.query_vpp_config()) p.remove_vpp_config() p.wait_event(0) p.wait_event(DEAD_FLAG) wg0.remove_vpp_config() wg1.remove_vpp_config() class WireguardHandoffTests(TestWg): """ Wireguard Tests in multi worker setup """ vpp_worker_count = 2 def test_wg_peer_init(self): """ Handoff """ port = 12383 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg0.admin_up() wg0.config_ip4() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip4, port+1, ["10.11.2.0/24", "10.11.3.0/24"]).add_vpp_config() self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) r1 = VppIpRoute(self, "10.11.3.0", 24, [VppRoutePath("10.11.3.1", wg0.sw_if_index)]).add_vpp_config() # send a valid handsake init for which we expect a response p = peer_1.mk_handshake(self.pg1) rx = self.send_and_expect(self.pg1, [p], self.pg1) peer_1.consume_response(rx[0]) # send a data packet from the peer through the tunnel # this completes the handshake and pins the peer to worker 0 p = (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw()) d = peer_1.encrypt_transport(p) p = (peer_1.mk_tunnel_header(self.pg1) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peer_1.sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0, worker=0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel # and pins the peer tp worker 1 pe = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, pe * 255, self.pg1, worker=1) peer_1.validate_encapped(rxs, pe) # send packets into the tunnel, from the other worker p = [(peer_1.mk_tunnel_header(self.pg1) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii+1, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0, worker=1) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel # from owrker 0 rxs = self.send_and_expect(self.pg0, pe * 255, self.pg1, worker=0) peer_1.validate_encapped(rxs, pe) r1.remove_vpp_config() peer_1.remove_vpp_config() wg0.remove_vpp_config() @unittest.skip("test disabled") def test_wg_multi_interface(self): """ Multi-tunnel on the same port """