Skip to content

Commit

Permalink
Add Batching and Proxying peer testcase
Browse files Browse the repository at this point in the history
Proxying persistent keepalives are being done
by batcher when batching is used. Batcher uses
ICMP echo requests(pings) which is a different
mechanism from wireguard backend's keepalives.

To ensure those are being emitted the testcase uses
link detection and stops the peer. Given that there's
no other generated traffic it should trigger link detection
pretty soon and prove that batcher works correctly at least
to some degree.

Signed-off-by: Lukas Pukenis <[email protected]>
  • Loading branch information
LukasPukenis committed Dec 12, 2024
1 parent bc30a66 commit a339eb2
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 108 deletions.
80 changes: 78 additions & 2 deletions nat-lab/tests/test_batching.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,32 @@
import itertools
import pytest
from contextlib import AsyncExitStack
from helpers import SetupParameters, setup_environment
from helpers import (
SetupParameters,
setup_environment,
setup_mesh_nodes,
)
from itertools import zip_longest
from scapy.layers.inet import TCP, UDP, ICMP # type: ignore
from scapy.layers.l2 import ARP # type: ignore
from timeouts import TEST_BATCHING_TIMEOUT
from typing import List
from utils.asyncio_util import run_async_context
from utils.bindings import (
default_features,
features_with_endpoint_providers,
FeatureLinkDetection,
FeaturePersistentKeepalive,
FeatureBatching,
EndpointProvider,
RelayState,
LinkState,
NodeState,
PathType,
TelioAdapterType,
)
from utils.connection import DockerConnection
from utils.connection_util import DOCKER_GW_MAP, ConnectionTag, container_id
from utils.connection_util import ConnectionTag, DOCKER_GW_MAP, container_id
from utils.traffic import (
capture_traffic,
render_chart,
Expand Down Expand Up @@ -240,3 +246,73 @@ async def start_node_manually(client, node, sleep_s):

print("Delay chart below")
print(delay_chart)


def proxying_peer_parameters(clients: List[ConnectionTag]):
def features():
features = default_features(enable_direct=False, enable_nurse=False)
features.wireguard.persistent_keepalive.proxying = 5
features.link_detection = FeatureLinkDetection(
rtt_seconds=2, no_of_pings=0, use_for_downgrade=False
)

features.batching = FeatureBatching(
direct_connection_threshold=5,
trigger_cooldown_duration=60,
trigger_effective_duration=10,
)
return features

return [
SetupParameters(
connection_tag=conn_tag,
adapter_type_override=TelioAdapterType.NEP_TUN,
features=features(),
fingerprint=f"{conn_tag}",
)
for conn_tag in clients
]


@pytest.mark.asyncio
@pytest.mark.parametrize(
"setup_params",
[
proxying_peer_parameters(
[ConnectionTag.DOCKER_CONE_CLIENT_1, ConnectionTag.DOCKER_CONE_CLIENT_2]
)
],
)
@pytest.mark.timeout(60)
async def test_proxying_peers_reconnect(setup_params: List[SetupParameters]) -> None:
# Since batching keepalives are performed on application level instead of Wireguard
# backend we need to ensure that proxying peers are also handled. To test for this
# we can enable link detection that guarantees quick detection if there's no corresponding
# received traffic and expect traffic to be emitted behind the scenes. If that doesn't
# work then there will be no traffic to trigger link detection
async with AsyncExitStack() as exit_stack:
env = await setup_mesh_nodes(exit_stack, setup_params)

await asyncio.gather(*[
await exit_stack.enter_async_context(
run_async_context(
client.wait_for_state_peer(
node.public_key, [NodeState.CONNECTED], [PathType.RELAY]
)
)
)
for client, node in itertools.product(env.clients, env.nodes)
if not client.is_node(node)
])

alpha, beta = env.clients
await beta.stop_device()

_, beta_node = env.nodes

# 20 seconds should be enough since 10 seconds is for WireGuard's Passive-Keepalive
# RTT is configured to be just 2 seconds and no pings to validate.
await asyncio.sleep(20)

link_events = alpha.get_link_state_events(beta_node.public_key)
assert link_events[-1] == LinkState.DOWN
117 changes: 11 additions & 106 deletions nat-lab/tests/test_derp_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from copy import deepcopy
from helpers import SetupParameters, setup_mesh_nodes
from typing import List
from utils.bindings import RelayState, FeatureBatching, default_features
from utils.bindings import RelayState
from utils.connection_util import ConnectionTag
from utils.ping import ping

Expand All @@ -15,46 +15,13 @@
DERP3_IP = str(DERP_TERTIARY.ipv4)


def generate_features(batching: bool):
features = default_features()
features.wireguard.persistent_keepalive.proxying = 10
features.batching = (
FeatureBatching(
# It is used for direct, stun, proxy, vpn peers so the name can be confusing.
# TODO: rename to a better name
direct_connection_threshold=5,
trigger_cooldown_duration=60,
trigger_effective_duration=10,
)
if batching
else None
)
return features


@pytest.mark.asyncio
@pytest.mark.parametrize(
"setup_params",
[
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=False),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=False),
),
],
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=True),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=True),
),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2),
],
],
)
Expand Down Expand Up @@ -116,32 +83,9 @@ async def test_derp_reconnect_2clients(setup_params: List[SetupParameters]) -> N
"setup_params",
[
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=False),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=False),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_SYMMETRIC_CLIENT_1,
features=generate_features(batching=False),
),
],
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=True),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=True),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_SYMMETRIC_CLIENT_1,
features=generate_features(batching=True),
),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2),
SetupParameters(connection_tag=ConnectionTag.DOCKER_SYMMETRIC_CLIENT_1),
],
],
)
Expand Down Expand Up @@ -280,32 +224,9 @@ async def test_derp_reconnect_3clients(setup_params: List[SetupParameters]) -> N
"setup_params",
[
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=False),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=False),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_SYMMETRIC_CLIENT_1,
features=generate_features(batching=False),
),
],
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=True),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=True),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_SYMMETRIC_CLIENT_1,
features=generate_features(batching=True),
),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2),
SetupParameters(connection_tag=ConnectionTag.DOCKER_SYMMETRIC_CLIENT_1),
],
],
)
Expand Down Expand Up @@ -488,24 +409,8 @@ async def test_derp_restart(setup_params: List[SetupParameters]) -> None:
"setup_params",
[
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=False),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=False),
),
],
[
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1,
features=generate_features(batching=True),
),
SetupParameters(
connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2,
features=generate_features(batching=True),
),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_1),
SetupParameters(connection_tag=ConnectionTag.DOCKER_CONE_CLIENT_2),
],
],
)
Expand Down

0 comments on commit a339eb2

Please sign in to comment.