testprotocols 0.1.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {testprotocols-0.1.0/src/testprotocols.egg-info → testprotocols-0.3.0}/PKG-INFO +1 -1
- {testprotocols-0.1.0 → testprotocols-0.3.0}/pyproject.toml +1 -1
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/__init__.py +0 -2
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/appliance_vlans.py +15 -2
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/client.py +8 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/sdwan.py +7 -1
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/qoe.py +1 -0
- testprotocols-0.3.0/src/testprotocols/network_probe.py +49 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/qoe_browser.py +9 -1
- testprotocols-0.3.0/src/testprotocols/reachability_responder.py +55 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/sdwan_policy_manager.py +25 -3
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/spanning_tree.py +1 -1
- {testprotocols-0.1.0 → testprotocols-0.3.0/src/testprotocols.egg-info}/PKG-INFO +1 -1
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols.egg-info/SOURCES.txt +2 -1
- testprotocols-0.3.0/tests/test_appliance_vlans.py +33 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_device_types.py +5 -3
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_sdwan_appliance_models.py +12 -9
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_switch_models.py +1 -2
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_switch_routing_models.py +10 -2
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_wan_edge_templates.py +2 -0
- testprotocols-0.1.0/src/testprotocols/infra_controller.py +0 -28
- testprotocols-0.1.0/src/testprotocols/network_probe.py +0 -27
- {testprotocols-0.1.0 → testprotocols-0.3.0}/LICENSE +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/NOTICE +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/README.md +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/setup.cfg +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/aftr_gateway.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/appliance_nat.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/appliance_uplinks.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/arp_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/bgp.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/conntrack.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/content_filtering.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/device_lifecycle.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/device_management.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/__init__.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/base.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/cpe.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/infra.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/switch.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/traffic.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/voice.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/devices/wan.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/dhcp_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/dhcp_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/discovery.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/dns_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/file_transfer.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/firewall.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/firewall_zones.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/first_hop_security.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/gateway_redundancy.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/http_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/http_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/hw_console.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/interface_dhcp.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/ip_interface.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/ip_routing.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/iperf_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/iperf_generator.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/iperf_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/l3_firewall.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/l7_firewall.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/link_aggregation.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/mac_table.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/__init__.py +92 -92
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/dhcp.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/firewall.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/impairment.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/l2_common.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/multicast.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/networking.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/packets.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/radius.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/sdwan_appliance.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/switch.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/switch_routing.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/tr069.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/traffic.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/wan_edge.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/models/wifi.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/multicast_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/nat.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/netem_controller.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/network_endpoint.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/nmap_scanner.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/ntp_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/ntp_config.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/ospf.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/packet_filter.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/pcap_capture.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/pdu_controller.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/port_poe.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/port_security.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/port_status.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/py.typed +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/radius_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/radius_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/routed_interfaces.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/router.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/routing_read.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/sip_phone.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/sip_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/site_to_site_vpn.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/snmp_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/static_routes.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/storm_control.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/streaming_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/switch_acl.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/switch_ports.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/switch_qos.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/switch_vlans.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/syslog_config.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/tftp_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/threat_prevention.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/tr069_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/tr069_server.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/traffic_shaping.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/upnp_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/vlan_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wan_link_admin.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_bss.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_client.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_mesh.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_onboarding.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_radio.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_rf.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_stations.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols/wifi_transitions.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols.egg-info/dependency_links.txt +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/src/testprotocols.egg-info/top_level.txt +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_cpe_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_dhcp_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_firewall_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_infra_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_ip_interface.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_ip_routing.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_network_tool_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_package_imports.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_radius_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_sdwan_appliance_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_switch_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_traffic_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_voice_wifi_templates.py +0 -0
- {testprotocols-0.1.0 → testprotocols-0.3.0}/tests/test_wifi_templates.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testprotocols
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Common Test Resource Layer — capability and device protocols for telco testing.
|
|
5
5
|
Author-email: Alottabits <rjvisser@alottabits.com>
|
|
6
6
|
Maintainer-email: Alottabits <rjvisser@alottabits.com>
|
|
@@ -47,7 +47,6 @@ from testprotocols.gateway_redundancy import GatewayRedundancy
|
|
|
47
47
|
from testprotocols.http_client import HttpClient
|
|
48
48
|
from testprotocols.http_server import HttpServer
|
|
49
49
|
from testprotocols.hw_console import HwConsole
|
|
50
|
-
from testprotocols.infra_controller import InfraController
|
|
51
50
|
from testprotocols.interface_dhcp import InterfaceDhcp
|
|
52
51
|
from testprotocols.ip_interface import IpInterface
|
|
53
52
|
from testprotocols.ip_routing import IpRouting
|
|
@@ -136,7 +135,6 @@ __all__ = [
|
|
|
136
135
|
"HttpClient",
|
|
137
136
|
"HttpServer",
|
|
138
137
|
"HwConsole",
|
|
139
|
-
"InfraController",
|
|
140
138
|
"InterfaceDhcp",
|
|
141
139
|
"IpInterface",
|
|
142
140
|
"IpRouting",
|
|
@@ -5,8 +5,8 @@ subnet/addressing and DHCP configuration, plus observed DHCP leases. This is the
|
|
|
5
5
|
appliance counterpart to a Linux host's interface + DHCP-server surfaces — an
|
|
6
6
|
appliance configures DHCP per VLAN, not via a host daemon.
|
|
7
7
|
|
|
8
|
-
In scope: list/get/set VLAN configuration (incl. per-VLAN DHCP), and read
|
|
9
|
-
leases.
|
|
8
|
+
In scope: list/get/set/delete VLAN configuration (incl. per-VLAN DHCP), and read
|
|
9
|
+
DHCP leases.
|
|
10
10
|
|
|
11
11
|
Out of scope: WAN uplink status (see ``appliance_uplinks``), L3 firewall
|
|
12
12
|
(see ``l3_firewall``), and host-style per-interface config (see ``ip_interface``).
|
|
@@ -38,6 +38,19 @@ class ApplianceVlans(Protocol):
|
|
|
38
38
|
"""Create or replace the VLAN identified by ``config.vlan_id``."""
|
|
39
39
|
...
|
|
40
40
|
|
|
41
|
+
def delete_vlan(self, vlan_id: int) -> None:
|
|
42
|
+
"""Remove the LAN VLAN identified by *vlan_id*.
|
|
43
|
+
|
|
44
|
+
Per-object remove, completing the VLAN CRUD surface (mirrors
|
|
45
|
+
``StaticRoutes.remove_static_route``). On management planes that model the
|
|
46
|
+
LAN as one config blob, a driver implements this as read-modify-write of
|
|
47
|
+
that module. Deleting a missing VLAN may raise or succeed by plane;
|
|
48
|
+
callers needing idempotence should check first (``get_vlan`` raises
|
|
49
|
+
KeyError when absent). A plane that cannot remove a required / last LAN
|
|
50
|
+
VLAN raises unsupported-capability.
|
|
51
|
+
"""
|
|
52
|
+
...
|
|
53
|
+
|
|
41
54
|
def get_dhcp_leases(self, vlan_id: int | None = None) -> list[DhcpLease]:
|
|
42
55
|
"""Return current DHCP leases, optionally filtered to one *vlan_id*.
|
|
43
56
|
|
|
@@ -24,6 +24,7 @@ from testprotocols.ntp_client import NtpClient
|
|
|
24
24
|
from testprotocols.packet_filter import PacketFilter
|
|
25
25
|
from testprotocols.pcap_capture import PcapCapture
|
|
26
26
|
from testprotocols.qoe_browser import QoeBrowser
|
|
27
|
+
from testprotocols.reachability_responder import ReachabilityResponder
|
|
27
28
|
from testprotocols.syslog_config import SyslogConfig
|
|
28
29
|
from testprotocols.upnp_client import UpnpClient
|
|
29
30
|
from testprotocols.vlan_client import VlanClient
|
|
@@ -124,8 +125,15 @@ class QoeMeasurementClientDevice(QoeClientDevice, Protocol):
|
|
|
124
125
|
iperf_client: IperfClient
|
|
125
126
|
iperf_server: IperfServer
|
|
126
127
|
network_probe: NetworkProbe
|
|
128
|
+
responder: ReachabilityResponder
|
|
127
129
|
pcap: PcapCapture
|
|
128
130
|
|
|
131
|
+
test_ip: str
|
|
132
|
+
"""The client's test-plane address as a CIDR (e.g. ``"10.1.30.50/24"``), empty
|
|
133
|
+
if the client is not homed to a test segment. Vendor-neutral metadata the
|
|
134
|
+
driver resolves from its homing config — read it here rather than reaching into
|
|
135
|
+
a framework-specific config object."""
|
|
136
|
+
|
|
129
137
|
|
|
130
138
|
register_device_type("linux_lan_client", LanClientDevice)
|
|
131
139
|
register_device_type("linux_wlan_client", WlanClientDevice)
|
|
@@ -8,8 +8,8 @@ from testprotocols.appliance_nat import ApplianceNat
|
|
|
8
8
|
from testprotocols.appliance_uplinks import ApplianceUplinks
|
|
9
9
|
from testprotocols.appliance_vlans import ApplianceVlans
|
|
10
10
|
from testprotocols.bgp import Bgp
|
|
11
|
-
from testprotocols.content_filtering import ContentFiltering
|
|
12
11
|
from testprotocols.conntrack import Conntrack
|
|
12
|
+
from testprotocols.content_filtering import ContentFiltering
|
|
13
13
|
from testprotocols.devices import register_device_type
|
|
14
14
|
from testprotocols.devices.base import BaseDeviceProtocol
|
|
15
15
|
from testprotocols.ip_interface import IpInterface
|
|
@@ -93,5 +93,11 @@ class SdwanApplianceDevice(BaseDeviceProtocol, Protocol):
|
|
|
93
93
|
lan: ApplianceVlans
|
|
94
94
|
syslog: SyslogConfig
|
|
95
95
|
|
|
96
|
+
model: str
|
|
97
|
+
"""Hardware model identifier (e.g. ``"MX250"``) — vendor-neutral metadata the
|
|
98
|
+
driver resolves from its management API / inventory. The coverage axis for
|
|
99
|
+
model-parameterised tests; read it here rather than reaching into a
|
|
100
|
+
framework-specific config object."""
|
|
101
|
+
|
|
96
102
|
|
|
97
103
|
register_device_type("sdwan_appliance", SdwanApplianceDevice)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Network reachability probe template.
|
|
2
|
+
|
|
3
|
+
Defines the abstract contract for L3/L4 reachability checks initiated from
|
|
4
|
+
a host toward an external target. Distinct from ``HttpClient`` (which is
|
|
5
|
+
app-layer): a ``NetworkProbe`` verifies whether the SYN/ACK handshake
|
|
6
|
+
completes, not whether an HTTP responder is configured at the far end.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Protocol, runtime_checkable
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@runtime_checkable
|
|
15
|
+
class NetworkProbe(Protocol):
|
|
16
|
+
"""Abstract contract for L3/L4 reachability probes."""
|
|
17
|
+
|
|
18
|
+
def tcp_can_connect(self, host: str, port: int, timeout: int = 5) -> bool:
|
|
19
|
+
"""Attempt a TCP connection to *host*:*port* and return reachability.
|
|
20
|
+
|
|
21
|
+
Returns ``True`` if the three-way handshake completes within
|
|
22
|
+
*timeout* seconds, ``False`` otherwise (connection refused, no
|
|
23
|
+
route, filtered, timed out). The probe is read-only — no data is
|
|
24
|
+
sent on the connection — so it is safe to call against arbitrary
|
|
25
|
+
targets without side effects on the destination.
|
|
26
|
+
"""
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
def icmp_can_reach(self, host: str, count: int = 1, timeout: int = 5) -> bool:
|
|
30
|
+
"""Attempt an ICMP echo to *host* and return reachability.
|
|
31
|
+
|
|
32
|
+
Returns ``True`` if at least one of *count* echo requests is answered
|
|
33
|
+
within *timeout* seconds, ``False`` otherwise (no route, filtered,
|
|
34
|
+
timed out). Read-only — echo requests have no side effect on the
|
|
35
|
+
destination.
|
|
36
|
+
"""
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
def udp_can_reach(self, host: str, port: int, timeout: int = 5) -> bool:
|
|
40
|
+
"""Attempt a UDP exchange with *host*:*port* and return reachability.
|
|
41
|
+
|
|
42
|
+
UDP is connectionless and has no handshake, so a dropped datagram is
|
|
43
|
+
indistinguishable from a delivered one at the sender unless the far end
|
|
44
|
+
replies. This probe therefore reports reachability based on a **reply**
|
|
45
|
+
from a UDP responder at the target within *timeout* seconds — callers
|
|
46
|
+
that need a definitive verdict must ensure a responder is present. A
|
|
47
|
+
missing reply (no responder, no route, or filtered) is ``False``.
|
|
48
|
+
"""
|
|
49
|
+
...
|
|
@@ -27,8 +27,16 @@ class QoeBrowser(Protocol):
|
|
|
27
27
|
scenario: str = "page_load",
|
|
28
28
|
wait_until: str = "networkidle",
|
|
29
29
|
timeout_ms: int = 30000,
|
|
30
|
+
force_quic: bool = True,
|
|
30
31
|
) -> QoEResult:
|
|
31
|
-
"""Measure productivity-app QoE for *url* (e.g., page-load time).
|
|
32
|
+
"""Measure productivity-app QoE for *url* (e.g., page-load time).
|
|
33
|
+
|
|
34
|
+
``force_quic=True`` (default) forces HTTP/3/QUIC, as a QoE measurement
|
|
35
|
+
should. Set ``force_quic=False`` for a reachability/block probe: the
|
|
36
|
+
navigation runs over TCP/h2 (QUIC disabled), so a non-HTTP/3 site stays
|
|
37
|
+
reachable and a TCP/TLS-inspecting middlebox (e.g. content filtering)
|
|
38
|
+
actually sees the traffic.
|
|
39
|
+
"""
|
|
32
40
|
...
|
|
33
41
|
|
|
34
42
|
def measure_streaming(
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Reachability responder template — the answerer counterpart to ``NetworkProbe``.
|
|
2
|
+
|
|
3
|
+
``NetworkProbe`` *sends* reachability probes; a peer being probed must *answer*
|
|
4
|
+
them or a "blocked" verdict is indistinguishable from "no listener". This
|
|
5
|
+
capability stands up those answerers on the target's test interface:
|
|
6
|
+
|
|
7
|
+
* **TCP** — a listener that accepts connections (a ``tcp_can_connect`` connect
|
|
8
|
+
probe completes the handshake on accept).
|
|
9
|
+
* **UDP** — an echo responder (a content-based ``udp_can_reach`` probe sends a
|
|
10
|
+
token and is reachable iff it is echoed back).
|
|
11
|
+
|
|
12
|
+
ICMP needs no responder (the kernel answers echo requests). The pairing is
|
|
13
|
+
explicit and 1:1:
|
|
14
|
+
|
|
15
|
+
NetworkProbe.tcp_can_connect <-> ReachabilityResponder.start_tcp_responder
|
|
16
|
+
NetworkProbe.udp_can_reach <-> ReachabilityResponder.start_udp_responder
|
|
17
|
+
NetworkProbe.icmp_can_reach <-> (none — kernel)
|
|
18
|
+
|
|
19
|
+
Vendor-neutral contract; the listener mechanism (sockets / ``socat`` / a service)
|
|
20
|
+
lives entirely in the per-plugin impl, exactly as ``NetworkProbe`` impls do.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from typing import Protocol, runtime_checkable
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@runtime_checkable
|
|
29
|
+
class ReachabilityResponder(Protocol):
|
|
30
|
+
"""Abstract contract for standing up / tearing down reachability responders."""
|
|
31
|
+
|
|
32
|
+
def start_tcp_responder(self, port: int) -> None:
|
|
33
|
+
"""Start a TCP responder on *port* that accepts connections.
|
|
34
|
+
|
|
35
|
+
A connect-only ``NetworkProbe.tcp_can_connect`` probe completes its
|
|
36
|
+
handshake against this listener, so an open path reads as reachable.
|
|
37
|
+
"""
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
def start_udp_responder(self, port: int) -> None:
|
|
41
|
+
"""Start a UDP echo responder on *port*.
|
|
42
|
+
|
|
43
|
+
Reflects every datagram it receives back to the sender, so a peer's
|
|
44
|
+
content-based ``NetworkProbe.udp_can_reach`` probe gets its token echoed
|
|
45
|
+
when the path is open — making "blocked" distinguishable from
|
|
46
|
+
"no listener" on the connectionless protocol.
|
|
47
|
+
"""
|
|
48
|
+
...
|
|
49
|
+
|
|
50
|
+
def stop(self, port: int | None = None) -> None:
|
|
51
|
+
"""Stop the responders on *port* (both protocols); ``None`` stops all.
|
|
52
|
+
|
|
53
|
+
No-op if none is running.
|
|
54
|
+
"""
|
|
55
|
+
...
|
|
@@ -7,9 +7,12 @@ Firewall-rule administration is **not** here — it moved to the dedicated
|
|
|
7
7
|
``l3_firewall`` / ``l7_firewall`` capabilities (coherent-domain split; see
|
|
8
8
|
SPLITS.md). Typed path steering (``set_uplink_selection`` /
|
|
9
9
|
``get_uplink_selection`` over ordered ``UplinkSelectionRule``s; performance
|
|
10
|
-
classes reuse ``SLAPolicy`` by name) landed 2026-06-12;
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
classes reuse ``SLAPolicy`` by name) landed 2026-06-12; the default
|
|
11
|
+
(primary) uplink pair (``get_default_uplink`` / ``set_default_uplink``)
|
|
12
|
+
landed 2026-07-03 — the network-wide "which uplink carries default-routed
|
|
13
|
+
traffic" knob, distinct from per-flow steering. ``apply_policy`` remains
|
|
14
|
+
the generic escape hatch for vendor-shaped policies beyond that surface.
|
|
15
|
+
Application-match steering grows on evidence.
|
|
13
16
|
"""
|
|
14
17
|
|
|
15
18
|
from __future__ import annotations
|
|
@@ -48,6 +51,25 @@ class SdwanPolicyManager(Protocol):
|
|
|
48
51
|
"""Return application flows observed in the last *since_s* seconds."""
|
|
49
52
|
...
|
|
50
53
|
|
|
54
|
+
def get_default_uplink(self) -> str:
|
|
55
|
+
"""Return the name of the network's default (primary) uplink.
|
|
56
|
+
|
|
57
|
+
The default uplink carries all default-routed traffic that no
|
|
58
|
+
uplink-selection rule steers elsewhere — e.g. ``"wan1"``. Vendor
|
|
59
|
+
drivers map this to their primary-uplink notion.
|
|
60
|
+
"""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
def set_default_uplink(self, uplink: str) -> None:
|
|
64
|
+
"""Set the network's default (primary) uplink to *uplink*.
|
|
65
|
+
|
|
66
|
+
Changes only which uplink carries default-routed traffic; the
|
|
67
|
+
ordered uplink-selection rules (``set_uplink_selection``) are left
|
|
68
|
+
untouched. Drivers reject names the product cannot express (e.g.
|
|
69
|
+
an uplink the appliance does not have) rather than approximating.
|
|
70
|
+
"""
|
|
71
|
+
...
|
|
72
|
+
|
|
51
73
|
def set_uplink_selection(self, rules: list[UplinkSelectionRule]) -> None:
|
|
52
74
|
"""Replace the ordered uplink-selection rule list with *rules*.
|
|
53
75
|
|
|
@@ -21,7 +21,7 @@ class SpanningTree(Protocol):
|
|
|
21
21
|
...
|
|
22
22
|
|
|
23
23
|
def set_bridge_priority(self, priority: int) -> None:
|
|
24
|
-
"""Set the bridge priority (0
|
|
24
|
+
"""Set the bridge priority (0-61440, in steps of 4096 per IEEE 802.1D)."""
|
|
25
25
|
...
|
|
26
26
|
|
|
27
27
|
def set_port_config(self, config: StpPortConfig) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testprotocols
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Common Test Resource Layer — capability and device protocols for telco testing.
|
|
5
5
|
Author-email: Alottabits <rjvisser@alottabits.com>
|
|
6
6
|
Maintainer-email: Alottabits <rjvisser@alottabits.com>
|
|
@@ -25,7 +25,6 @@ src/testprotocols/gateway_redundancy.py
|
|
|
25
25
|
src/testprotocols/http_client.py
|
|
26
26
|
src/testprotocols/http_server.py
|
|
27
27
|
src/testprotocols/hw_console.py
|
|
28
|
-
src/testprotocols/infra_controller.py
|
|
29
28
|
src/testprotocols/interface_dhcp.py
|
|
30
29
|
src/testprotocols/ip_interface.py
|
|
31
30
|
src/testprotocols/ip_routing.py
|
|
@@ -55,6 +54,7 @@ src/testprotocols/py.typed
|
|
|
55
54
|
src/testprotocols/qoe_browser.py
|
|
56
55
|
src/testprotocols/radius_client.py
|
|
57
56
|
src/testprotocols/radius_server.py
|
|
57
|
+
src/testprotocols/reachability_responder.py
|
|
58
58
|
src/testprotocols/routed_interfaces.py
|
|
59
59
|
src/testprotocols/router.py
|
|
60
60
|
src/testprotocols/routing_read.py
|
|
@@ -119,6 +119,7 @@ src/testprotocols/models/tr069.py
|
|
|
119
119
|
src/testprotocols/models/traffic.py
|
|
120
120
|
src/testprotocols/models/wan_edge.py
|
|
121
121
|
src/testprotocols/models/wifi.py
|
|
122
|
+
tests/test_appliance_vlans.py
|
|
122
123
|
tests/test_cpe_templates.py
|
|
123
124
|
tests/test_device_types.py
|
|
124
125
|
tests/test_dhcp_templates.py
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Protocol-conformance tests for ApplianceVlans (runtime_checkable structural check)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from testprotocols.appliance_vlans import ApplianceVlans
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class _Complete:
|
|
9
|
+
"""Has every ApplianceVlans member, including delete_vlan."""
|
|
10
|
+
|
|
11
|
+
def list_vlans(self): ...
|
|
12
|
+
def get_vlan(self, vlan_id): ...
|
|
13
|
+
def set_vlan(self, config): ...
|
|
14
|
+
def delete_vlan(self, vlan_id): ...
|
|
15
|
+
def get_dhcp_leases(self, vlan_id=None): ...
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class _NoDelete:
|
|
19
|
+
"""Missing delete_vlan — must NOT satisfy the protocol once delete_vlan is declared."""
|
|
20
|
+
|
|
21
|
+
def list_vlans(self): ...
|
|
22
|
+
def get_vlan(self, vlan_id): ...
|
|
23
|
+
def set_vlan(self, config): ...
|
|
24
|
+
def get_dhcp_leases(self, vlan_id=None): ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_complete_impl_satisfies_protocol():
|
|
28
|
+
assert isinstance(_Complete(), ApplianceVlans)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_delete_vlan_is_required_by_protocol():
|
|
32
|
+
# runtime_checkable isinstance requires every declared member be present.
|
|
33
|
+
assert not isinstance(_NoDelete(), ApplianceVlans)
|
|
@@ -10,7 +10,6 @@ inventory-string -> Protocol binding and the per-archetype capability set
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
12
|
import pytest
|
|
13
|
-
|
|
14
13
|
from testprotocols.devices import DeviceTypeSpec, all_device_types, get_device_type
|
|
15
14
|
from testprotocols.devices.base import BaseDeviceProtocol
|
|
16
15
|
from testprotocols.devices.client import (
|
|
@@ -22,12 +21,12 @@ from testprotocols.devices.client import (
|
|
|
22
21
|
from testprotocols.devices.cpe import CpeDevice
|
|
23
22
|
from testprotocols.devices.infra import AcsDevice, ProvisionerDevice, TftpDevice
|
|
24
23
|
from testprotocols.devices.sdwan import SdwanApplianceDevice, SdwanRouterDevice
|
|
24
|
+
from testprotocols.devices.switch import L2Switch, L3Switch, L3SwitchRouted
|
|
25
25
|
from testprotocols.devices.traffic import (
|
|
26
26
|
IperfTrafficGeneratorDevice,
|
|
27
27
|
TrafficControllerDevice,
|
|
28
28
|
)
|
|
29
29
|
from testprotocols.devices.voice import SipPhoneDevice, SipServerDevice
|
|
30
|
-
from testprotocols.devices.switch import L2Switch, L3Switch, L3SwitchRouted
|
|
31
30
|
from testprotocols.devices.wan import WanServerDevice
|
|
32
31
|
|
|
33
32
|
_ALL_ARCHETYPES = (
|
|
@@ -320,6 +319,7 @@ def test_qoe_measurement_client_aggregates_expected_capabilities() -> None:
|
|
|
320
319
|
"iperf_client",
|
|
321
320
|
"iperf_server",
|
|
322
321
|
"network_probe",
|
|
322
|
+
"responder",
|
|
323
323
|
"pcap",
|
|
324
324
|
"syslog",
|
|
325
325
|
}
|
|
@@ -454,7 +454,9 @@ def test_cpe_full_firewall_surface() -> None:
|
|
|
454
454
|
|
|
455
455
|
def test_devices_without_firewall() -> None:
|
|
456
456
|
"""These archetypes must not pull in any of the firewall capabilities."""
|
|
457
|
-
firewall_attrs = (
|
|
457
|
+
firewall_attrs = (
|
|
458
|
+
"packet_filter", "firewall", "nat", "port_forwarding", "conntrack", "firewall_zones"
|
|
459
|
+
)
|
|
458
460
|
for archetype in (
|
|
459
461
|
TftpDevice,
|
|
460
462
|
WlanClientDevice,
|
|
@@ -10,7 +10,6 @@ from __future__ import annotations
|
|
|
10
10
|
from enum import StrEnum
|
|
11
11
|
|
|
12
12
|
import pytest
|
|
13
|
-
|
|
14
13
|
from testprotocols.models.sdwan_appliance import (
|
|
15
14
|
ApplicationCategory,
|
|
16
15
|
BgpConfig,
|
|
@@ -18,20 +17,20 @@ from testprotocols.models.sdwan_appliance import (
|
|
|
18
17
|
BgpPeerStatus,
|
|
19
18
|
BgpSessionState,
|
|
20
19
|
ContentCategory,
|
|
21
|
-
FlowMatch,
|
|
22
|
-
L3Rule,
|
|
23
|
-
L7MatchType,
|
|
24
|
-
L7Rule,
|
|
25
|
-
RuleAction,
|
|
26
|
-
RuleProtocol,
|
|
27
20
|
DhcpLease,
|
|
28
21
|
DhcpMode,
|
|
29
22
|
DhcpOption,
|
|
30
23
|
DhcpOptionType,
|
|
24
|
+
FlowMatch,
|
|
31
25
|
IntrusionConfig,
|
|
32
26
|
IntrusionMode,
|
|
33
27
|
IntrusionSensitivity,
|
|
28
|
+
L3Rule,
|
|
29
|
+
L7MatchType,
|
|
30
|
+
L7Rule,
|
|
34
31
|
MalwareMode,
|
|
32
|
+
RuleAction,
|
|
33
|
+
RuleProtocol,
|
|
35
34
|
SecurityAction,
|
|
36
35
|
SecurityEvent,
|
|
37
36
|
ShapingPriority,
|
|
@@ -126,7 +125,8 @@ def test_shaping_rule_uses_normalized_vocabulary() -> None:
|
|
|
126
125
|
priority=ShapingPriority.LOW,
|
|
127
126
|
)
|
|
128
127
|
assert rule.priority == "low"
|
|
129
|
-
|
|
128
|
+
default = ShapingRule(name="x", match_type=L7MatchType.HOST, value="1.2.3.4")
|
|
129
|
+
assert default.priority is ShapingPriority.NORMAL
|
|
130
130
|
|
|
131
131
|
|
|
132
132
|
def test_uplink_state_and_status() -> None:
|
|
@@ -144,7 +144,10 @@ def test_syslog_role_and_server() -> None:
|
|
|
144
144
|
|
|
145
145
|
|
|
146
146
|
def test_threat_prevention_vocabularies() -> None:
|
|
147
|
-
|
|
147
|
+
vocabularies = (
|
|
148
|
+
IntrusionMode, IntrusionSensitivity, MalwareMode, SecurityAction, ThreatCategory
|
|
149
|
+
)
|
|
150
|
+
for enum_cls in vocabularies:
|
|
148
151
|
assert issubclass(enum_cls, StrEnum)
|
|
149
152
|
assert {m.value for m in IntrusionMode} == {"disabled", "detection", "prevention"}
|
|
150
153
|
assert {s.value for s in IntrusionSensitivity} == {"low", "medium", "high"}
|
|
@@ -66,6 +66,7 @@ def test_switch_records() -> None:
|
|
|
66
66
|
AccessPolicy,
|
|
67
67
|
AccessPolicyType,
|
|
68
68
|
FhsBinding,
|
|
69
|
+
LinkAggregationGroup,
|
|
69
70
|
LinkState,
|
|
70
71
|
LldpNeighbor,
|
|
71
72
|
NtpServer,
|
|
@@ -74,12 +75,10 @@ def test_switch_records() -> None:
|
|
|
74
75
|
PortStatusEntry,
|
|
75
76
|
QosRule,
|
|
76
77
|
StormControlConfig,
|
|
77
|
-
StormControlType,
|
|
78
78
|
StpPortConfig,
|
|
79
79
|
SwitchAclRule,
|
|
80
80
|
SwitchPort,
|
|
81
81
|
VlanDef,
|
|
82
|
-
LinkAggregationGroup,
|
|
83
82
|
)
|
|
84
83
|
|
|
85
84
|
p = SwitchPort(name="1", mode="access") # type: ignore[arg-type]
|
|
@@ -43,7 +43,13 @@ def test_switch_routing_records() -> None:
|
|
|
43
43
|
RoutedInterface,
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
-
ri = RoutedInterface(
|
|
46
|
+
ri = RoutedInterface(
|
|
47
|
+
name="vlan10",
|
|
48
|
+
mode=InterfaceMode.SVI,
|
|
49
|
+
ip_address="10.0.10.1",
|
|
50
|
+
subnet="10.0.10.0/24",
|
|
51
|
+
vlan_id=10,
|
|
52
|
+
)
|
|
47
53
|
assert ri.vlan_id == 10
|
|
48
54
|
d = InterfaceDhcpConfig(interface="vlan10")
|
|
49
55
|
assert d.mode == "disabled" and d.relay_targets == []
|
|
@@ -51,5 +57,7 @@ def test_switch_routing_records() -> None:
|
|
|
51
57
|
assert o.version == "v2" and o.interfaces == []
|
|
52
58
|
oi = OspfInterfaceSettings(interface="vlan10", area="0.0.0.0")
|
|
53
59
|
assert oi.passive is False
|
|
54
|
-
g = RedundancyGroup(
|
|
60
|
+
g = RedundancyGroup(
|
|
61
|
+
group_id=1, virtual_ip="10.0.10.254", role=RedundancyRole.PRIMARY, interface="vlan10"
|
|
62
|
+
)
|
|
55
63
|
assert g.virtual_ip == "10.0.10.254"
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"""Infra-controller capability template.
|
|
2
|
-
|
|
3
|
-
Abstract contract for environment/fabric control delegated by the test
|
|
4
|
-
orchestrator to a hypervisor (vSphere). It reads and (for re-homing) moves a
|
|
5
|
-
VM NIC's port-group, and asserts a named port-group is present. It does NOT
|
|
6
|
-
create fabric — the lab carries the test VLANs already.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
from typing import Protocol, runtime_checkable
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@runtime_checkable
|
|
15
|
-
class InfraController(Protocol):
|
|
16
|
-
"""Read / presence-check / move a VM NIC's port-group."""
|
|
17
|
-
|
|
18
|
-
def get_nic_portgroup(self, vm_name: str, nic_index: int) -> str:
|
|
19
|
-
"""Return the portgroup name backing NIC *nic_index* on *vm_name*."""
|
|
20
|
-
...
|
|
21
|
-
|
|
22
|
-
def ensure_port_group(self, name: str) -> None:
|
|
23
|
-
"""Assert a portgroup named *name* exists (raise if absent). No create."""
|
|
24
|
-
...
|
|
25
|
-
|
|
26
|
-
def set_nic_portgroup(self, vm_name: str, nic_index: int, portgroup: str) -> None:
|
|
27
|
-
"""Repoint NIC *nic_index* on *vm_name* onto the named *portgroup*."""
|
|
28
|
-
...
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"""Network reachability probe template.
|
|
2
|
-
|
|
3
|
-
Defines the abstract contract for L3/L4 reachability checks initiated from
|
|
4
|
-
a host toward an external target. Distinct from ``HttpClient`` (which is
|
|
5
|
-
app-layer): a ``NetworkProbe`` verifies whether the SYN/ACK handshake
|
|
6
|
-
completes, not whether an HTTP responder is configured at the far end.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
from typing import Protocol, runtime_checkable
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@runtime_checkable
|
|
15
|
-
class NetworkProbe(Protocol):
|
|
16
|
-
"""Abstract contract for L3/L4 reachability probes."""
|
|
17
|
-
|
|
18
|
-
def tcp_can_connect(self, host: str, port: int, timeout: int = 5) -> bool:
|
|
19
|
-
"""Attempt a TCP connection to *host*:*port* and return reachability.
|
|
20
|
-
|
|
21
|
-
Returns ``True`` if the three-way handshake completes within
|
|
22
|
-
*timeout* seconds, ``False`` otherwise (connection refused, no
|
|
23
|
-
route, filtered, timed out). The probe is read-only — no data is
|
|
24
|
-
sent on the connection — so it is safe to call against arbitrary
|
|
25
|
-
targets without side effects on the destination.
|
|
26
|
-
"""
|
|
27
|
-
...
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|