testprotocols 0.1.0__py3-none-any.whl

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.
Files changed (119) hide show
  1. testprotocols/__init__.py +217 -0
  2. testprotocols/aftr_gateway.py +22 -0
  3. testprotocols/appliance_nat.py +52 -0
  4. testprotocols/appliance_uplinks.py +32 -0
  5. testprotocols/appliance_vlans.py +50 -0
  6. testprotocols/arp_client.py +26 -0
  7. testprotocols/bgp.py +55 -0
  8. testprotocols/conntrack.py +147 -0
  9. testprotocols/content_filtering.py +47 -0
  10. testprotocols/device_lifecycle.py +49 -0
  11. testprotocols/device_management.py +50 -0
  12. testprotocols/devices/__init__.py +46 -0
  13. testprotocols/devices/base.py +40 -0
  14. testprotocols/devices/client.py +133 -0
  15. testprotocols/devices/cpe.py +66 -0
  16. testprotocols/devices/infra.py +62 -0
  17. testprotocols/devices/sdwan.py +97 -0
  18. testprotocols/devices/switch.py +115 -0
  19. testprotocols/devices/traffic.py +53 -0
  20. testprotocols/devices/voice.py +69 -0
  21. testprotocols/devices/wan.py +60 -0
  22. testprotocols/dhcp_client.py +30 -0
  23. testprotocols/dhcp_server.py +23 -0
  24. testprotocols/discovery.py +20 -0
  25. testprotocols/dns_client.py +23 -0
  26. testprotocols/file_transfer.py +22 -0
  27. testprotocols/firewall.py +121 -0
  28. testprotocols/firewall_zones.py +133 -0
  29. testprotocols/first_hop_security.py +52 -0
  30. testprotocols/gateway_redundancy.py +29 -0
  31. testprotocols/http_client.py +36 -0
  32. testprotocols/http_server.py +22 -0
  33. testprotocols/hw_console.py +48 -0
  34. testprotocols/infra_controller.py +28 -0
  35. testprotocols/interface_dhcp.py +30 -0
  36. testprotocols/ip_interface.py +62 -0
  37. testprotocols/ip_routing.py +57 -0
  38. testprotocols/iperf_client.py +47 -0
  39. testprotocols/iperf_generator.py +42 -0
  40. testprotocols/iperf_server.py +41 -0
  41. testprotocols/l3_firewall.py +74 -0
  42. testprotocols/l7_firewall.py +32 -0
  43. testprotocols/link_aggregation.py +24 -0
  44. testprotocols/mac_table.py +20 -0
  45. testprotocols/models/__init__.py +304 -0
  46. testprotocols/models/dhcp.py +28 -0
  47. testprotocols/models/firewall.py +197 -0
  48. testprotocols/models/impairment.py +18 -0
  49. testprotocols/models/l2_common.py +53 -0
  50. testprotocols/models/multicast.py +22 -0
  51. testprotocols/models/networking.py +50 -0
  52. testprotocols/models/packets.py +21 -0
  53. testprotocols/models/qoe.py +31 -0
  54. testprotocols/models/radius.py +63 -0
  55. testprotocols/models/sdwan_appliance.py +637 -0
  56. testprotocols/models/switch.py +297 -0
  57. testprotocols/models/switch_routing.py +122 -0
  58. testprotocols/models/tr069.py +35 -0
  59. testprotocols/models/traffic.py +29 -0
  60. testprotocols/models/wan_edge.py +116 -0
  61. testprotocols/models/wifi.py +183 -0
  62. testprotocols/multicast_client.py +20 -0
  63. testprotocols/nat.py +87 -0
  64. testprotocols/netem_controller.py +42 -0
  65. testprotocols/network_endpoint.py +32 -0
  66. testprotocols/network_probe.py +27 -0
  67. testprotocols/nmap_scanner.py +27 -0
  68. testprotocols/ntp_client.py +26 -0
  69. testprotocols/ntp_config.py +25 -0
  70. testprotocols/ospf.py +24 -0
  71. testprotocols/packet_filter.py +144 -0
  72. testprotocols/pcap_capture.py +39 -0
  73. testprotocols/pdu_controller.py +26 -0
  74. testprotocols/port_poe.py +25 -0
  75. testprotocols/port_security.py +25 -0
  76. testprotocols/port_status.py +23 -0
  77. testprotocols/py.typed +0 -0
  78. testprotocols/qoe_browser.py +62 -0
  79. testprotocols/radius_client.py +78 -0
  80. testprotocols/radius_server.py +130 -0
  81. testprotocols/routed_interfaces.py +29 -0
  82. testprotocols/router.py +53 -0
  83. testprotocols/routing_read.py +22 -0
  84. testprotocols/sdwan_policy_manager.py +64 -0
  85. testprotocols/sip_phone.py +230 -0
  86. testprotocols/sip_server.py +205 -0
  87. testprotocols/site_to_site_vpn.py +61 -0
  88. testprotocols/snmp_client.py +17 -0
  89. testprotocols/spanning_tree.py +37 -0
  90. testprotocols/static_routes.py +47 -0
  91. testprotocols/storm_control.py +24 -0
  92. testprotocols/streaming_server.py +32 -0
  93. testprotocols/switch_acl.py +29 -0
  94. testprotocols/switch_ports.py +28 -0
  95. testprotocols/switch_qos.py +33 -0
  96. testprotocols/switch_vlans.py +34 -0
  97. testprotocols/syslog_config.py +31 -0
  98. testprotocols/tftp_server.py +22 -0
  99. testprotocols/threat_prevention.py +60 -0
  100. testprotocols/tr069_client.py +47 -0
  101. testprotocols/tr069_server.py +151 -0
  102. testprotocols/traffic_shaping.py +54 -0
  103. testprotocols/upnp_client.py +37 -0
  104. testprotocols/vlan_client.py +22 -0
  105. testprotocols/wan_link_admin.py +34 -0
  106. testprotocols/wifi_bss.py +197 -0
  107. testprotocols/wifi_client.py +72 -0
  108. testprotocols/wifi_mesh.py +259 -0
  109. testprotocols/wifi_onboarding.py +105 -0
  110. testprotocols/wifi_radio.py +153 -0
  111. testprotocols/wifi_rf.py +78 -0
  112. testprotocols/wifi_stations.py +59 -0
  113. testprotocols/wifi_transitions.py +112 -0
  114. testprotocols-0.1.0.dist-info/METADATA +29 -0
  115. testprotocols-0.1.0.dist-info/RECORD +119 -0
  116. testprotocols-0.1.0.dist-info/WHEEL +5 -0
  117. testprotocols-0.1.0.dist-info/licenses/LICENSE +201 -0
  118. testprotocols-0.1.0.dist-info/licenses/NOTICE +11 -0
  119. testprotocols-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,22 @@
1
+ """HTTP / Server template.
2
+
3
+ Defines the abstract contract for HTTP server operations including
4
+ starting and stopping an HTTP service.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Protocol, runtime_checkable
10
+
11
+
12
+ @runtime_checkable
13
+ class HttpServer(Protocol):
14
+ """Abstract contract for HTTP server operations."""
15
+
16
+ def start_http_service(self, port: str, ip_version: str) -> str:
17
+ """Start an HTTP service on *port* for *ip_version*."""
18
+ ...
19
+
20
+ def stop_http_service(self, port: str) -> None:
21
+ """Stop the HTTP service listening on *port*."""
22
+ ...
@@ -0,0 +1,48 @@
1
+ """Hardware console template.
2
+
3
+ Defines the abstract contract for managing physical hardware consoles,
4
+ power cycling, and bootloader-level flashing of a device under test.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, Protocol, runtime_checkable
10
+
11
+
12
+ @runtime_checkable
13
+ class HwConsole(Protocol):
14
+ """Abstract contract for hardware console and power management operations."""
15
+
16
+ def connect_to_consoles(self, device_name: str) -> None:
17
+ """Connect to all hardware consoles for the named device."""
18
+ ...
19
+
20
+ def disconnect_from_consoles(self) -> None:
21
+ """Disconnect from all hardware consoles."""
22
+ ...
23
+
24
+ def get_console(self, console_name: str) -> Any:
25
+ """Return the console object identified by *console_name*."""
26
+ ...
27
+
28
+ def get_interactive_consoles(self) -> dict[str, Any]:
29
+ """Return a mapping of console names to interactive console objects."""
30
+ ...
31
+
32
+ def power_cycle(self) -> None:
33
+ """Power cycle the device (power off, then power on)."""
34
+ ...
35
+
36
+ def wait_for_hw_boot(self) -> None:
37
+ """Block until the hardware has completed its boot sequence."""
38
+ ...
39
+
40
+ def flash_via_bootloader(
41
+ self,
42
+ image: str,
43
+ tftp_devices: dict[str, Any],
44
+ termination_sys: Any = None,
45
+ method: str | None = None,
46
+ ) -> None:
47
+ """Flash the given image to the device via the bootloader."""
48
+ ...
@@ -0,0 +1,28 @@
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
+ ...
@@ -0,0 +1,30 @@
1
+ """Per-SVI DHCP server/relay configuration (reuses appliance DHCP models)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Protocol, runtime_checkable
6
+
7
+ from testprotocols.models.sdwan_appliance import DhcpLease
8
+ from testprotocols.models.switch_routing import InterfaceDhcpConfig
9
+
10
+
11
+ @runtime_checkable
12
+ class InterfaceDhcp(Protocol):
13
+ """Abstract contract for per-interface DHCP server/relay.
14
+
15
+ Best-effort lease read: a product without a true lease table may approximate
16
+ or raise unsupported-capability on ``get_dhcp_leases``.
17
+ """
18
+
19
+ def set_interface_dhcp(self, config: InterfaceDhcpConfig) -> None:
20
+ """Create or replace the DHCP config for ``config.interface``."""
21
+ ...
22
+
23
+ def get_interface_dhcp(self, interface: str) -> InterfaceDhcpConfig:
24
+ """Return the DHCP config for *interface*."""
25
+ ...
26
+
27
+ def get_dhcp_leases(self, interface: str | None = None) -> list[DhcpLease]:
28
+ """Return current DHCP leases (best-effort; a product without a true
29
+ lease table may approximate or raise unsupported-capability)."""
30
+ ...
@@ -0,0 +1,62 @@
1
+ """IP / Interface template.
2
+
3
+ Defines the abstract contract for querying and configuring IP interface state.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from ipaddress import IPv4Address
9
+ from typing import Protocol, runtime_checkable
10
+
11
+
12
+ @runtime_checkable
13
+ class IpInterface(Protocol):
14
+ """Abstract contract for IP interface operations."""
15
+
16
+ def get_interface_ipv4addr(self, interface: str) -> str:
17
+ """Return the IPv4 address assigned to *interface*."""
18
+ ...
19
+
20
+ def get_interface_ipv6addr(self, interface: str) -> str:
21
+ """Return the global IPv6 address assigned to *interface*."""
22
+ ...
23
+
24
+ def get_interface_link_local_ipv6addr(self, interface: str) -> str:
25
+ """Return the link-local IPv6 address of *interface*."""
26
+ ...
27
+
28
+ def get_interface_macaddr(self, interface: str) -> str:
29
+ """Return the MAC address of *interface*."""
30
+ ...
31
+
32
+ def get_interface_mask(self, interface: str) -> str:
33
+ """Return the subnet mask of *interface*."""
34
+ ...
35
+
36
+ def get_interface_mtu_size(self, interface: str) -> int:
37
+ """Return the MTU size of *interface*."""
38
+ ...
39
+
40
+ def is_link_up(self, interface: str, pattern: str = "BROADCAST,MULTICAST,UP") -> bool:
41
+ """Return True if *interface* flags match *pattern*."""
42
+ ...
43
+
44
+ def set_link_state(self, interface: str, state: str) -> None:
45
+ """Bring *interface* up or down according to *state*."""
46
+ ...
47
+
48
+ def enable_ipv6(self) -> None:
49
+ """Enable IPv6 on the device."""
50
+ ...
51
+
52
+ def disable_ipv6(self) -> None:
53
+ """Disable IPv6 on the device."""
54
+ ...
55
+
56
+ def set_static_ip(self, interface: str, ip_address: IPv4Address, netmask: IPv4Address) -> None:
57
+ """Assign a static IP address and netmask to *interface*."""
58
+ ...
59
+
60
+ def remove_static_ip(self, interface: str) -> None:
61
+ """Remove any static IP address configuration from *interface*."""
62
+ ...
@@ -0,0 +1,57 @@
1
+ """IP / Routing template.
2
+
3
+ Defines the abstract contract for IP routing operations such as ping, traceroute,
4
+ and default gateway management.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from ipaddress import IPv4Address
10
+ from typing import Any, Protocol, runtime_checkable
11
+
12
+
13
+ @runtime_checkable
14
+ class IpRouting(Protocol):
15
+ """Abstract contract for IP routing operations."""
16
+
17
+ def ping(
18
+ self,
19
+ ping_ip: str,
20
+ ping_count: int = 4,
21
+ ping_interface: str | None = None,
22
+ options: str = "",
23
+ timeout: int = 50,
24
+ json_output: bool = False,
25
+ ) -> bool | dict[str, Any]:
26
+ """Send ICMP echo requests to *ping_ip* and return success or parsed output."""
27
+ ...
28
+
29
+ def traceroute(
30
+ self,
31
+ host_ip: str | IPv4Address,
32
+ version: str = "",
33
+ options: str = "",
34
+ timeout: int = 60,
35
+ ) -> str | None:
36
+ """Run a traceroute to *host_ip* and return the output."""
37
+ ...
38
+
39
+ def add_route(self, destination: str, gw_interface: str) -> None:
40
+ """Add a static route to *destination* via *gw_interface*."""
41
+ ...
42
+
43
+ def delete_route(self, destination: str) -> None:
44
+ """Delete the static route to *destination*."""
45
+ ...
46
+
47
+ def get_default_gateway(self) -> IPv4Address:
48
+ """Return the current default gateway address."""
49
+ ...
50
+
51
+ def del_default_route(self, interface: str | None = None) -> None:
52
+ """Delete the default route, optionally scoped to *interface*."""
53
+ ...
54
+
55
+ def set_default_gw(self, ip_address: IPv4Address, interface: str) -> None:
56
+ """Set the default gateway to *ip_address* via *interface*."""
57
+ ...
@@ -0,0 +1,47 @@
1
+ """Traffic / IperfClient template.
2
+
3
+ Defines the abstract contract for iperf client operations including
4
+ sending traffic and collecting logs.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Protocol, runtime_checkable
10
+
11
+
12
+ @runtime_checkable
13
+ class IperfClient(Protocol):
14
+ """Abstract contract for iperf client (traffic sender) operations."""
15
+
16
+ def start_traffic_sender(
17
+ self,
18
+ host: str,
19
+ traffic_port: int,
20
+ bandwidth: int | None = None,
21
+ bind_to_ip: str | None = None,
22
+ direction: str | None = None,
23
+ ip_version: int | None = None,
24
+ udp_protocol: bool = False,
25
+ time: int = 10,
26
+ client_port: int | None = None,
27
+ udp_only: bool | None = None,
28
+ ) -> tuple[int, str]:
29
+ """Start an iperf traffic sender towards *host* on *traffic_port*.
30
+
31
+ Returns a tuple of (pid, log_file_path).
32
+ """
33
+ ...
34
+
35
+ def stop_traffic(self, pid: int | None = None) -> bool:
36
+ """Stop a running iperf traffic sender.
37
+
38
+ Parameters
39
+ ----------
40
+ pid:
41
+ Process ID to stop. If *None*, stop the most recently started sender.
42
+ """
43
+ ...
44
+
45
+ def get_iperf_logs(self, log_file: str) -> str:
46
+ """Return the iperf log contents from *log_file*."""
47
+ ...
@@ -0,0 +1,42 @@
1
+ """Traffic / IperfGenerator template.
2
+
3
+ Defines the abstract contract for a higher-level iperf traffic generator
4
+ that manages flows and returns structured results.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Protocol, runtime_checkable
10
+
11
+ from testprotocols.models.traffic import TrafficResult, TrafficSpec
12
+
13
+
14
+ @runtime_checkable
15
+ class IperfGenerator(Protocol):
16
+ """Abstract contract for iperf-based traffic flow management."""
17
+
18
+ @property
19
+ def server_ip(self) -> str:
20
+ """IP address of the iperf server."""
21
+ ...
22
+
23
+ @property
24
+ def active_flows(self) -> list[str]:
25
+ """List of currently active traffic flow IDs."""
26
+ ...
27
+
28
+ def start_traffic(self, spec: TrafficSpec) -> str:
29
+ """Start a traffic flow defined by *spec* and return its flow ID."""
30
+ ...
31
+
32
+ def stop_traffic(self, flow_id: str) -> TrafficResult:
33
+ """Stop the traffic flow identified by *flow_id* and return its result."""
34
+ ...
35
+
36
+ def stop_all_traffic(self) -> dict[str, TrafficResult]:
37
+ """Stop all active traffic flows and return a mapping of flow_id to result."""
38
+ ...
39
+
40
+ def run_traffic(self, spec: TrafficSpec) -> TrafficResult:
41
+ """Run a traffic flow defined by *spec* to completion and return the result."""
42
+ ...
@@ -0,0 +1,41 @@
1
+ """Traffic / IperfServer template.
2
+
3
+ Defines the abstract contract for iperf server operations including
4
+ receiving traffic and collecting logs.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Protocol, runtime_checkable
10
+
11
+
12
+ @runtime_checkable
13
+ class IperfServer(Protocol):
14
+ """Abstract contract for iperf server (traffic receiver) operations."""
15
+
16
+ def start_traffic_receiver(
17
+ self,
18
+ traffic_port: int,
19
+ bind_to_ip: str | None = None,
20
+ ip_version: int | None = None,
21
+ udp_only: bool | None = None,
22
+ ) -> tuple[int, str]:
23
+ """Start an iperf traffic receiver on *traffic_port*.
24
+
25
+ Returns a tuple of (pid, log_file_path).
26
+ """
27
+ ...
28
+
29
+ def stop_traffic(self, pid: int | None = None) -> bool:
30
+ """Stop a running iperf traffic receiver.
31
+
32
+ Parameters
33
+ ----------
34
+ pid:
35
+ Process ID to stop. If *None*, stop the most recently started receiver.
36
+ """
37
+ ...
38
+
39
+ def get_iperf_logs(self, log_file: str) -> str:
40
+ """Return the iperf log contents from *log_file*."""
41
+ ...
@@ -0,0 +1,74 @@
1
+ """L3 firewall template — managed SD-WAN appliance edition.
2
+
3
+ Defines the abstract contract for a managed SD-WAN appliance's L3 firewall:
4
+ **ordered allow/deny policy lists** for outbound (LAN→WAN) and inbound (WAN→LAN)
5
+ traffic. A managed appliance exposes each direction as a single ordered list
6
+ that is read and replaced as a whole — distinct from
7
+ ``packet_filter.PacketFilter`` (netfilter INPUT/OUTPUT/FORWARD chains, add/remove
8
+ a rule by name), which models a Linux host's stateless filter.
9
+
10
+ In scope: read and replace the outbound, inbound, and site-to-site VPN
11
+ ordered rule lists.
12
+
13
+ Out of scope: L7 / application-aware rules (see ``l7_firewall``), URL / category
14
+ filtering (see ``content_filtering``), NAT and port-forwarding (see
15
+ ``appliance_nat``), and netfilter-chain filtering (see ``packet_filter``).
16
+
17
+ Rules are transport-agnostic ``L3Rule`` records; the driver translates them
18
+ into its product's API. Value vocabularies (``action``, ``protocol``) are the
19
+ normalized sets in ``models.sdwan_appliance``.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from typing import Protocol, runtime_checkable
25
+
26
+ from testprotocols.models.sdwan_appliance import L3Rule
27
+
28
+
29
+ @runtime_checkable
30
+ class L3Firewall(Protocol):
31
+ """Abstract contract for an appliance's ordered L3 firewall policy."""
32
+
33
+ def set_outbound_rules(self, rules: list[L3Rule]) -> None:
34
+ """Replace the ordered outbound (LAN→WAN) policy with *rules*.
35
+
36
+ The list is the complete policy in evaluation order; the driver
37
+ replaces the appliance's outbound ruleset wholesale.
38
+ """
39
+ ...
40
+
41
+ def get_outbound_rules(self) -> list[L3Rule]:
42
+ """Return the outbound (LAN→WAN) rules in evaluation order."""
43
+ ...
44
+
45
+ def set_inbound_rules(self, rules: list[L3Rule]) -> None:
46
+ """Replace the ordered inbound (WAN→LAN) policy with *rules*.
47
+
48
+ The list is the complete policy in evaluation order; the driver
49
+ replaces the appliance's inbound ruleset wholesale.
50
+
51
+ Conformance note: not every appliance family exposes a generic
52
+ inbound rule list — some offer only an implicit stateful deny plus
53
+ NAT-scoped inbound allowances. Such drivers raise
54
+ unsupported-capability here rather than approximating.
55
+ """
56
+ ...
57
+
58
+ def get_inbound_rules(self) -> list[L3Rule]:
59
+ """Return the inbound (WAN→LAN) rules in evaluation order."""
60
+ ...
61
+
62
+ def set_vpn_rules(self, rules: list[L3Rule]) -> None:
63
+ """Replace the ordered site-to-site VPN policy with *rules*.
64
+
65
+ The list is the complete policy, in evaluation order, governing
66
+ traffic traversing the site-to-site VPN overlay. On some products
67
+ this rule set is scoped wider than a single device (e.g.
68
+ fleet-wide); that is a driver/testbed concern, not a contract one.
69
+ """
70
+ ...
71
+
72
+ def get_vpn_rules(self) -> list[L3Rule]:
73
+ """Return the site-to-site VPN rules in evaluation order."""
74
+ ...
@@ -0,0 +1,32 @@
1
+ """L7 firewall template — application-aware allow/deny for a managed appliance.
2
+
3
+ Defines the abstract contract for an SD-WAN appliance's L7 (application-aware)
4
+ firewall: an ordered list of rules that match by application, application
5
+ category, host, port, or IP range and allow/deny accordingly. Like
6
+ ``l3_firewall.L3Firewall`` the policy is read and replaced as a whole list.
7
+
8
+ In scope: read and replace the ordered L7 rule list.
9
+
10
+ Out of scope: L3 5-tuple filtering (see ``l3_firewall``), URL / content-category
11
+ blocking (see ``content_filtering``), and traffic shaping (see
12
+ ``traffic_shaping``).
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import Protocol, runtime_checkable
18
+
19
+ from testprotocols.models.sdwan_appliance import L7Rule
20
+
21
+
22
+ @runtime_checkable
23
+ class L7Firewall(Protocol):
24
+ """Abstract contract for an appliance's ordered L7 firewall policy."""
25
+
26
+ def set_rules(self, rules: list[L7Rule]) -> None:
27
+ """Replace the ordered L7 policy with *rules* (complete, in order)."""
28
+ ...
29
+
30
+ def get_rules(self) -> list[L7Rule]:
31
+ """Return the L7 rules in evaluation order."""
32
+ ...
@@ -0,0 +1,24 @@
1
+ """Link-aggregation (LAG) configuration by member ports + mode."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Protocol, runtime_checkable
6
+
7
+ from testprotocols.models.switch import LinkAggregationGroup
8
+
9
+
10
+ @runtime_checkable
11
+ class LinkAggregation(Protocol):
12
+ """Abstract contract for LAG configuration."""
13
+
14
+ def list_groups(self) -> list[LinkAggregationGroup]:
15
+ """Return every aggregation group."""
16
+ ...
17
+
18
+ def set_group(self, group: LinkAggregationGroup) -> None:
19
+ """Create or replace the group ``group.name``."""
20
+ ...
21
+
22
+ def remove_group(self, name: str) -> None:
23
+ """Remove the group *name*."""
24
+ ...
@@ -0,0 +1,20 @@
1
+ """Read-only forwarding-database (FDB / MAC address-table) read."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Protocol, runtime_checkable
6
+
7
+ from testprotocols.models.l2_common import MacTableEntry
8
+
9
+
10
+ @runtime_checkable
11
+ class MacTable(Protocol):
12
+ """Abstract contract for the FDB read.
13
+
14
+ A product with no FDB API raises unsupported-capability. A raw-dump white-box
15
+ extension is a LEVELS.md candidate (``MacTableWhiteBox``).
16
+ """
17
+
18
+ def get_mac_table(self, vlan: int | None = None) -> list[MacTableEntry]:
19
+ """Return FDB entries, optionally filtered to one *vlan*."""
20
+ ...