#1706 - Finished up the Node and Switch MVP. Added full extensive documentation on what's happening at each step.
This commit is contained in:
@@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Network Hardware - Added base hardware module with NIC, SwitchPort, Node, Switch, and Link. Nodes and Switches have
|
||||
fundamental services like ARP, ICMP, and PCAP running them by default.
|
||||
- Network Transmission - Modelled OSI Model layers 1 through to 5 with various classes for creating network frames and
|
||||
transmitting them from a Service/Application, down through the layers, over the wire, and back up through the layers to
|
||||
a Service/Application another machine.
|
||||
- system - Added the core structure of Application, Services, and Components. Also added a SoftwareManager and
|
||||
SessionManager.
|
||||
- File System - ability to emulate a node's file system during a simulation
|
||||
|
||||
## [2.0.0] - 2023-07-26
|
||||
|
||||
BIN
docs/_static/four_node_two_switch_network.png
vendored
Normal file
BIN
docs/_static/four_node_two_switch_network.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
@@ -6,7 +6,7 @@
|
||||
Simulation
|
||||
==========
|
||||
|
||||
.. TODO:: Add spiel here about what the simulation is.
|
||||
|
||||
|
||||
|
||||
Contents
|
||||
|
||||
@@ -5,71 +5,622 @@
|
||||
Base Hardware
|
||||
=============
|
||||
|
||||
The physical layer components are models of a ``NIC`` (Network Interface Card) and a ``Link``. These components allow
|
||||
modelling of layer 1 (physical layer) in the OSI model.
|
||||
The physical layer components are models of a NIC (Network Interface Card), SwitchPort, Node, Switch, and a Link.
|
||||
These components allow modelling of layer 1 (physical layer) in the OSI model and the nodes that connect to and
|
||||
transmit across layer 1.
|
||||
|
||||
NIC
|
||||
###
|
||||
The ``NIC`` class is a realistic model of a Network Interface Card. The ``NIC`` acts as the interface between the
|
||||
``Node`` and the ``Link``.
|
||||
The NIC class provides a realistic model of a Network Interface Card. The NIC acts as the interface between a Node and
|
||||
a Link, handling IP and MAC addressing, status, and sending/receiving frames.
|
||||
|
||||
NICs have the following attributes:
|
||||
Addressing
|
||||
**********
|
||||
|
||||
- **ip_address:** The IPv4 address assigned to the NIC.
|
||||
- **subnet_mask:** The subnet mask assigned to the NIC.
|
||||
- **gateway:** The default gateway IP address for forwarding network traffic to other networks.
|
||||
- **mac_address:** The MAC address of the NIC. Defaults to a randomly set MAC address.
|
||||
- **speed:** The speed of the NIC in Mbps (default is 100 Mbps).
|
||||
- **mtu:** The Maximum Transmission Unit (MTU) of the NIC in Bytes, representing the largest data packet size it can handle without fragmentation (default is 1500 B).
|
||||
- **wake_on_lan:** Indicates if the NIC supports Wake-on-LAN functionality.
|
||||
- **dns_servers:** List of IP addresses of DNS servers used for name resolution.
|
||||
- **connected_link:** The link to which the NIC is connected.
|
||||
- **enabled:** Indicates whether the NIC is enabled.
|
||||
A NIC has both an IPv4 address and MAC address assigned:
|
||||
|
||||
**Basic Example**
|
||||
- **ip_address** - The IPv4 address assigned to the NIC for communication on an IP network.
|
||||
- **subnet_mask** - The subnet mask that defines the network subnet.
|
||||
- **gateway** - The default gateway IP address for routing traffic beyond the local network.
|
||||
- **mac_address** - A unique MAC address assigned to the NIC by the manufacturer.
|
||||
|
||||
Status
|
||||
******
|
||||
|
||||
The status of the NIC is represented by:
|
||||
|
||||
- **enabled** - Indicates if the NIC is active/enabled or disabled/down. It must be enabled to send/receive frames.
|
||||
- **connected_node** - The Node instance the NIC is attached to.
|
||||
- **connected_link** - The Link instance the NIC is wired to.
|
||||
|
||||
Packet Capture
|
||||
**************
|
||||
|
||||
- **pcap** - A PacketCapture instance attached to the NIC for capturing all frames sent and received. This allows packet
|
||||
capture and analysis.
|
||||
|
||||
Sending/Receiving Frames
|
||||
************************
|
||||
|
||||
The NIC can send and receive Frames to/from the connected Link:
|
||||
|
||||
- **send_frame()** - Sends a Frame through the NIC onto the attached Link.
|
||||
- **receive_frame()** - Receives a Frame from the attached Link and processes it.
|
||||
|
||||
This allows a NIC to handle sending, receiving, and forwarding of network traffic at layer 2 of the OSI model.
|
||||
The Frames contain network data encapsulated with various protocol headers.
|
||||
|
||||
Basic Usage
|
||||
***********
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
nic1 = NIC(
|
||||
ip_address="192.168.1.100",
|
||||
ip_address="192.168.0.100",
|
||||
subnet_mask="255.255.255.0",
|
||||
gateway="192.168.1.1"
|
||||
gateway="192.168.0.1"
|
||||
)
|
||||
nic1.enable()
|
||||
frame = Frame(...)
|
||||
nic1.send_frame(frame)
|
||||
|
||||
SwitchPort
|
||||
##########
|
||||
|
||||
The SwitchPort models a port on a network switch. It has similar attributes and methods to NIC for addressing, status,
|
||||
packet capture, sending/receiving frames, etc.
|
||||
|
||||
Key attributes:
|
||||
|
||||
- **port_num**: The port number on the switch.
|
||||
- **connected_switch**: The switch to which this port belongs.
|
||||
|
||||
Node
|
||||
####
|
||||
|
||||
The Node class represents a base node that communicates on the Network.
|
||||
|
||||
Network Interfaces
|
||||
******************
|
||||
|
||||
A Node will typically have one or more NICs attached to it for network connectivity:
|
||||
|
||||
- **nics** - A dictionary containing the NIC instances attached to the Node. NICs can be added/removed.
|
||||
|
||||
Configuration
|
||||
*************
|
||||
|
||||
- **hostname** - Configured hostname of the Node.
|
||||
- **operating_state** - Current operating state like ON or OFF. The NICs will be enabled/disabled based on this.
|
||||
|
||||
Network Services
|
||||
****************
|
||||
|
||||
A Node runs various network services and components for handling traffic:
|
||||
|
||||
- **session_manager** - Handles establishing sessions to/from the Node.
|
||||
- **software_manager** - Manages software and applications on the Node.
|
||||
- **arp** - ARP cache for resolving IP addresses to MAC addresses.
|
||||
- **icmp** - ICMP service for responding to pings and echo requests.
|
||||
- **sys_log** - System log service for logging internal events and messages.
|
||||
|
||||
The SysLog provides a logging mechanism for the Node:
|
||||
|
||||
The SysLog records informational, warning, and error events that occur on the Node during simulation. This allows
|
||||
debugging and tracing program execution and network activity for each simulated Node. Other Node services like ARP and
|
||||
ICMP, along with custom Applications, services, and Processes will log to the SysLog.
|
||||
|
||||
Sending/Receiving
|
||||
*****************
|
||||
|
||||
The Node handles sending and receiving Frames via its attached NICs:
|
||||
|
||||
- **send_frame()** - Sends a Frame to the network through one of the Node's NICs.
|
||||
- **receive_frame()** - Receives a Frame from the network through a NIC. The Node then processes it appropriately based
|
||||
on the protocols and payload.
|
||||
|
||||
Basic Usage
|
||||
***********
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
node1 = Node(hostname='server1')
|
||||
node1.operating_state = NodeOperatingState.ON
|
||||
|
||||
nic1 = NIC()
|
||||
node1.connect_nic(nic1)
|
||||
|
||||
Send a frame
|
||||
frame = Frame(...)
|
||||
node1.send_frame(frame)
|
||||
|
||||
The Node class brings together the NICs, configuration, and services to model a full network node that can send,
|
||||
receive, process, and forward traffic on a simulated network.
|
||||
|
||||
|
||||
Switch
|
||||
######
|
||||
|
||||
The Switch subclass models a network switch. It inherits from Node and acts at layer 2 of the OSI model to forward
|
||||
frames based on MAC addresses.
|
||||
|
||||
Inherits Node Capabilities
|
||||
**************************
|
||||
|
||||
Since Switch subclasses Node, it inherits all capabilities from Node like:
|
||||
|
||||
- **Managing NICs**
|
||||
- **Running network services like ARP, ICMP**
|
||||
- **Sending and receiving frames**
|
||||
- **Maintaining system logs**
|
||||
|
||||
Ports
|
||||
*****
|
||||
|
||||
A Switch has multiple ports implemented using SwitchPort instances:
|
||||
|
||||
- **switch_ports** - A dictionary mapping port numbers to SwitchPort instances.
|
||||
- **num_ports** - The number of ports the Switch has.
|
||||
|
||||
Forwarding
|
||||
**********
|
||||
|
||||
A Switch forwards frames between ports based on the destination MAC:
|
||||
|
||||
- **dst_mac_table** - MAC address table that maps MACs to SwitchPorts.
|
||||
- **forward_frame()** - Forwards a frame out the port associated with the destination MAC.
|
||||
|
||||
When a frame is received on a SwitchPort:
|
||||
|
||||
1. The source MAC address is extracted from the frame.
|
||||
2. An entry is added to dst_mac_table that maps this source MAC to the SwitchPort it was received on.
|
||||
3. When a frame with that destination MAC is received in the future, it will be forwarded out this SwitchPort.
|
||||
|
||||
This allows the Switch to dynamically build up a mapping table between MAC addresses and SwitchPorts based on traffic
|
||||
received. If no entry exists for a destination MAC, it floods the frame out all ports.
|
||||
|
||||
Link
|
||||
####
|
||||
|
||||
The ``Link`` class represents a physical link between two network endpoints.
|
||||
The Link class represents a physical link or connection between two network endpoints like NICs or SwitchPorts.
|
||||
|
||||
Links have the following attributes:
|
||||
Endpoints
|
||||
*********
|
||||
|
||||
- **endpoint_a:** The first NIC connected to the Link.
|
||||
- **endpoint_b:** The second NIC connected to the Link.
|
||||
- **bandwidth:** The bandwidth of the Link in Mbps (default is 100 Mbps).
|
||||
- **current_load:** The current load on the link in Mbps.
|
||||
A Link connects two endpoints:
|
||||
|
||||
**Basic Example**
|
||||
- **endpoint_a** - The first endpoint, a NIC or SwitchPort.
|
||||
- **endpoint_b** - The second endpoint, a NIC or SwitchPort.
|
||||
|
||||
Transmission
|
||||
************
|
||||
|
||||
Links transmit Frames between the endpoints:
|
||||
|
||||
- **transmit_frame()** - Sends a Frame from one endpoint to the other.
|
||||
|
||||
Uses bandwidth/load properties to determine if transmission is possible.
|
||||
|
||||
Bandwidth & Load
|
||||
****************
|
||||
|
||||
- **bandwidth** - The total capacity of the Link in Mbps.
|
||||
- **current_load** - The current bandwidth utilization of the Link in Mbps.
|
||||
|
||||
As Frames are sent over the Link, the load increases. The Link tracks if there is enough unused capacity to transmit a
|
||||
Frame based on its size and the current load.
|
||||
|
||||
Status
|
||||
******
|
||||
|
||||
- **up** - Boolean indicating if the Link is currently up/active based on the endpoint status.
|
||||
- **endpoint_up()/down()** - Notifies the Link when an endpoint goes up or down.
|
||||
|
||||
This allows the Link to realistically model the connection and transmission characteristics between two endpoints.
|
||||
|
||||
Putting it all Together
|
||||
#######################
|
||||
|
||||
We'll now demonstrate how the nodes, NICs, switches, and links connect in a network, including full code examples and
|
||||
syslog extracts to illustrate the step-by-step process.
|
||||
|
||||
To demonstrate successful network communication between nodes and switches, we'll model a standard network with four
|
||||
PC's and two switches.
|
||||
|
||||
|
||||
.. image:: ../../../_static/four_node_two_switch_network.png
|
||||
|
||||
Create Nodes & NICs
|
||||
*******************
|
||||
|
||||
First, we'll create the four nodes, each with a single NIC.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
nic1 = NIC(
|
||||
ip_address="192.168.1.100",
|
||||
subnet_mask="255.255.255.0",
|
||||
gateway="192.168.1.1"
|
||||
)
|
||||
nic1 = NIC(
|
||||
ip_address="192.168.1.101",
|
||||
subnet_mask="255.255.255.0",
|
||||
gateway="192.168.1.1"
|
||||
pc_a = Node(hostname="pc_a")
|
||||
nic_a = NIC(ip_address="192.168.0.10", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
pc_a.connect_nic(nic_a)
|
||||
pc_a.power_on()
|
||||
|
||||
pc_b = Node(hostname="pc_b")
|
||||
nic_b = NIC(ip_address="192.168.0.11", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
pc_b.connect_nic(nic_b)
|
||||
pc_b.power_on()
|
||||
|
||||
pc_c = Node(hostname="pc_c")
|
||||
nic_c = NIC(ip_address="192.168.0.12", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
pc_c.connect_nic(nic_c)
|
||||
pc_c.power_on()
|
||||
|
||||
pc_d = Node(hostname="pc_d")
|
||||
nic_d = NIC(ip_address="192.168.0.13", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
pc_d.connect_nic(nic_d)
|
||||
pc_d.power_on()
|
||||
|
||||
|
||||
This produces:
|
||||
|
||||
**node_a NIC table**
|
||||
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+==========+
|
||||
| 80:af:f2:f6:58:b7 | 102.169.0.10 | 255.255.255.0 | 192.168.0.1 | 100 | Disabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
|
||||
**node_a sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,355 INFO: Connected NIC 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,355 INFO: Turned on
|
||||
|
||||
**node_b NIC table**
|
||||
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+==========+
|
||||
| 98:ad:eb:7c:dc:cb | 102.169.0.11 | 255.255.255.0 | 192.168.0.1 | 100 | Disabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
|
||||
**node_b sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,357 INFO: Connected NIC 98:ad:eb:7c:dc:cb/192.168.0.11
|
||||
2023-08-08 15:50:08,357 INFO: Turned on
|
||||
|
||||
**node_c NIC table**
|
||||
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+==========+
|
||||
| bc:72:82:5d:82:a4 | 102.169.0.12 | 255.255.255.0 | 192.168.0.1 | 100 | Disabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
|
||||
**node_c sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,358 INFO: Connected NIC bc:72:82:5d:82:a4/192.168.0.12
|
||||
2023-08-08 15:50:08,358 INFO: Turned on
|
||||
|
||||
**node_d NIC table**
|
||||
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+==========+
|
||||
| 84:20:7c:ec:a5:c6 | 102.169.0.13 | 255.255.255.0 | 192.168.0.1 | 100 | Disabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+----------+
|
||||
|
||||
**node_d sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,359 INFO: Connected NIC 84:20:7c:ec:a5:c6/192.168.0.13
|
||||
2023-08-08 15:50:08,360 INFO: Turned on
|
||||
|
||||
|
||||
Create Switches
|
||||
***************
|
||||
|
||||
Next, we'll create four six-port switches:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
switch_1 = Switch(hostname="switch_1", num_ports=6)
|
||||
switch_1.power_on()
|
||||
|
||||
switch_2 = Switch(hostname="switch_2", num_ports=6)
|
||||
switch_2.power_on()
|
||||
|
||||
This produces:
|
||||
|
||||
**switch_1 MAC table**
|
||||
|
||||
+------+-------------------+--------------+----------+
|
||||
| Port | MAC Address | Speed (Mbps) | Status |
|
||||
+======+===================+==============+==========+
|
||||
| 1 | 9d:ac:59:a0:05:13 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 2 | 45:f5:8e:b6:f5:d3 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 3 | ef:f5:b9:28:cb:ae | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 4 | 88:76:0a:72:fc:14 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 5 | 79:de:da:bd:e2:ba | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 6 | 91:d5:83:a0:02:f2 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
|
||||
**switch_1 sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,373 INFO: Turned on
|
||||
|
||||
**switch_2 MAC table**
|
||||
|
||||
+------+-------------------+--------------+----------+
|
||||
| Port | MAC Address | Speed (Mbps) | Status |
|
||||
+======+===================+==============+==========+
|
||||
| 1 | aa:58:fa:66:d7:be | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 2 | 72:d2:1e:88:e9:45 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 3 | 8a:fc:2a:56:d5:c5 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 4 | fb:b5:9a:04:4a:49 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 5 | 88:aa:48:d0:21:9e | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 6 | 96:77:39:d1:de:44 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
|
||||
**switch_2 sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,374 INFO: Turned on
|
||||
|
||||
Create Links
|
||||
************
|
||||
|
||||
Finally, we'll create the five links that connect the nodes and the switches:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
link_nic_a_switch_1 = Link(endpoint_a=nic_a, endpoint_b=switch_1.switch_ports[1])
|
||||
link_nic_b_switch_1 = Link(endpoint_a=nic_b, endpoint_b=switch_1.switch_ports[2])
|
||||
link_nic_c_switch_2 = Link(endpoint_a=nic_c, endpoint_b=switch_2.switch_ports[1])
|
||||
link_nic_d_switch_2 = Link(endpoint_a=nic_d, endpoint_b=switch_2.switch_ports[2])
|
||||
link_switch_1_switch_2 = Link(
|
||||
endpoint_a=switch_1.switch_ports[6], endpoint_b=switch_2.switch_ports[6]
|
||||
)
|
||||
|
||||
link = Link(
|
||||
endpoint_a=nic1,
|
||||
endpoint_b=nic2,
|
||||
bandwidth=1000
|
||||
)
|
||||
This produces:
|
||||
|
||||
Link, NIC, Node Interface
|
||||
#########################
|
||||
**node_a NIC table**
|
||||
|
||||
.. image:: ../../../_static/node_nic_link_component_diagram.png
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+=========+
|
||||
| 80:af:f2:f6:58:b7 | 102.169.0.10 | 255.255.255.0 | 192.168.0.1 | 100 | Enabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
|
||||
**node_a sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,355 INFO: Connected NIC 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,355 INFO: Turned on
|
||||
2023-08-08 15:50:08,355 INFO: NIC 80:af:f2:f6:58:b7/192.168.0.10 enabled
|
||||
|
||||
**node_b NIC table**
|
||||
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+=========+
|
||||
| 98:ad:eb:7c:dc:cb | 102.169.0.11 | 255.255.255.0 | 192.168.0.1 | 100 | Enabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
|
||||
**node_b sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,357 INFO: Connected NIC 98:ad:eb:7c:dc:cb/192.168.0.11
|
||||
2023-08-08 15:50:08,357 INFO: Turned on
|
||||
2023-08-08 15:50:08,357 INFO: NIC 98:ad:eb:7c:dc:cb/192.168.0.11 enabled
|
||||
|
||||
**node_c NIC table**
|
||||
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+=========+
|
||||
| bc:72:82:5d:82:a4 | 102.169.0.12 | 255.255.255.0 | 192.168.0.1 | 100 | Enabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
|
||||
**node_c sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,358 INFO: Connected NIC bc:72:82:5d:82:a4/192.168.0.12
|
||||
2023-08-08 15:50:08,358 INFO: Turned on
|
||||
2023-08-08 15:50:08,358 INFO: NIC bc:72:82:5d:82:a4/192.168.0.12 enabled
|
||||
|
||||
**node_d NIC table**
|
||||
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
| MAC Address | IP Address | Subnet Mask | Default Gateway | Speed (Mbps) | Status |
|
||||
+===================+==============+===============+=================+==============+=========+
|
||||
| 84:20:7c:ec:a5:c6 | 102.169.0.13 | 255.255.255.0 | 192.168.0.1 | 100 | Enabled |
|
||||
+-------------------+--------------+---------------+-----------------+--------------+---------+
|
||||
|
||||
**node_d sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,359 INFO: Connected NIC 84:20:7c:ec:a5:c6/192.168.0.13
|
||||
2023-08-08 15:50:08,360 INFO: Turned on
|
||||
2023-08-08 15:50:08,360 INFO: NIC 84:20:7c:ec:a5:c6/192.168.0.13 enabled
|
||||
|
||||
**switch_1 MAC table**
|
||||
|
||||
+------+-------------------+--------------+----------+
|
||||
| Port | MAC Address | Speed (Mbps) | Status |
|
||||
+======+===================+==============+==========+
|
||||
| 1 | 9d:ac:59:a0:05:13 | 100 | Enabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 2 | 45:f5:8e:b6:f5:d3 | 100 | Enabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 3 | ef:f5:b9:28:cb:ae | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 4 | 88:76:0a:72:fc:14 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 5 | 79:de:da:bd:e2:ba | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 6 | 91:d5:83:a0:02:f2 | 100 | Enabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
|
||||
|
||||
**switch_1 sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,373 INFO: Turned on
|
||||
2023-08-08 15:50:08,378 INFO: SwitchPort 9d:ac:59:a0:05:13 enabled
|
||||
2023-08-08 15:50:08,380 INFO: SwitchPort 45:f5:8e:b6:f5:d3 enabled
|
||||
2023-08-08 15:50:08,384 INFO: SwitchPort 91:d5:83:a0:02:f2 enabled
|
||||
|
||||
|
||||
**switch_2 MAC table**
|
||||
|
||||
+------+-------------------+--------------+----------+
|
||||
| Port | MAC Address | Speed (Mbps) | Status |
|
||||
+======+===================+==============+==========+
|
||||
| 1 | aa:58:fa:66:d7:be | 100 | Enabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 2 | 72:d2:1e:88:e9:45 | 100 | Enabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 3 | 8a:fc:2a:56:d5:c5 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 4 | fb:b5:9a:04:4a:49 | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 5 | 88:aa:48:d0:21:9e | 100 | Disabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
| 6 | 96:77:39:d1:de:44 | 100 | Enabled |
|
||||
+------+-------------------+--------------+----------+
|
||||
|
||||
|
||||
**switch_2 sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,374 INFO: Turned on
|
||||
2023-08-08 15:50:08,381 INFO: SwitchPort aa:58:fa:66:d7:be enabled
|
||||
2023-08-08 15:50:08,383 INFO: SwitchPort 72:d2:1e:88:e9:45 enabled
|
||||
2023-08-08 15:50:08,384 INFO: SwitchPort 96:77:39:d1:de:44 enabled
|
||||
|
||||
|
||||
Perform Ping
|
||||
************
|
||||
|
||||
Now with the network setup and operational, we can perform a ping to confirm that communication between nodes over a
|
||||
switched network is possible. In the below example, we ping 192.168.0.13 (node_d) from node_a:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pc_a.ping("192.168.0.13")
|
||||
|
||||
|
||||
This produces:
|
||||
|
||||
**node_a sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,355 INFO: Connected NIC 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,355 INFO: Turned on
|
||||
2023-08-08 15:50:08,355 INFO: NIC 80:af:f2:f6:58:b7/192.168.0.10 enabled
|
||||
2023-08-08 15:50:08,406 INFO: Attempting to ping 192.168.0.13
|
||||
2023-08-08 15:50:08,406 INFO: No entry in ARP cache for 192.168.0.13
|
||||
2023-08-08 15:50:08,406 INFO: Sending ARP request from NIC 80:af:f2:f6:58:b7/192.168.0.10 for ip 192.168.0.13
|
||||
2023-08-08 15:50:08,413 INFO: Received ARP response for 192.168.0.13 from 84:20:7c:ec:a5:c6 via NIC 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,413 INFO: Adding ARP cache entry for 84:20:7c:ec:a5:c6/192.168.0.13 via NIC 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,415 INFO: Sending echo request to 192.168.0.13
|
||||
2023-08-08 15:50:08,417 INFO: Received echo reply from 192.168.0.13
|
||||
2023-08-08 15:50:08,419 INFO: Sending echo request to 192.168.0.13
|
||||
2023-08-08 15:50:08,421 INFO: Received echo reply from 192.168.0.13
|
||||
2023-08-08 15:50:08,422 INFO: Sending echo request to 192.168.0.13
|
||||
2023-08-08 15:50:08,424 INFO: Received echo reply from 192.168.0.13
|
||||
2023-08-08 15:50:08,425 INFO: Sending echo request to 192.168.0.13
|
||||
2023-08-08 15:50:08,427 INFO: Received echo reply from 192.168.0.13
|
||||
|
||||
|
||||
**node_b sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,357 INFO: Connected NIC 98:ad:eb:7c:dc:cb/192.168.0.11
|
||||
2023-08-08 15:50:08,357 INFO: Turned on
|
||||
2023-08-08 15:50:08,357 INFO: NIC 98:ad:eb:7c:dc:cb/192.168.0.11 enabled
|
||||
2023-08-08 15:50:08,410 INFO: Received ARP request for 192.168.0.13 from 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,410 INFO: Ignoring ARP request for 192.168.0.13
|
||||
|
||||
|
||||
**node_c sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,358 INFO: Connected NIC bc:72:82:5d:82:a4/192.168.0.12
|
||||
2023-08-08 15:50:08,358 INFO: Turned on
|
||||
2023-08-08 15:50:08,358 INFO: NIC bc:72:82:5d:82:a4/192.168.0.12 enabled
|
||||
2023-08-08 15:50:08,411 INFO: Received ARP request for 192.168.0.13 from 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,411 INFO: Ignoring ARP request for 192.168.0.13
|
||||
|
||||
|
||||
**node_d sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,359 INFO: Connected NIC 84:20:7c:ec:a5:c6/192.168.0.13
|
||||
2023-08-08 15:50:08,360 INFO: Turned on
|
||||
2023-08-08 15:50:08,360 INFO: NIC 84:20:7c:ec:a5:c6/192.168.0.13 enabled
|
||||
2023-08-08 15:50:08,412 INFO: Received ARP request for 192.168.0.13 from 80:af:f2:f6:58:b7/192.168.0.10
|
||||
2023-08-08 15:50:08,412 INFO: Adding ARP cache entry for 80:af:f2:f6:58:b7/192.168.0.10 via NIC 84:20:7c:ec:a5:c6/192.168.0.13
|
||||
2023-08-08 15:50:08,412 INFO: Sending ARP reply from 84:20:7c:ec:a5:c6/192.168.0.13 to 192.168.0.10/80:af:f2:f6:58:b7
|
||||
2023-08-08 15:50:08,416 INFO: Received echo request from 192.168.0.10
|
||||
2023-08-08 15:50:08,417 INFO: Sending echo reply to 192.168.0.10
|
||||
2023-08-08 15:50:08,420 INFO: Received echo request from 192.168.0.10
|
||||
2023-08-08 15:50:08,420 INFO: Sending echo reply to 192.168.0.10
|
||||
2023-08-08 15:50:08,423 INFO: Received echo request from 192.168.0.10
|
||||
2023-08-08 15:50:08,423 INFO: Sending echo reply to 192.168.0.10
|
||||
2023-08-08 15:50:08,426 INFO: Received echo request from 192.168.0.10
|
||||
2023-08-08 15:50:08,426 INFO: Sending echo reply to 192.168.0.10
|
||||
|
||||
|
||||
|
||||
**switch_1 sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,373 INFO: Turned on
|
||||
2023-08-08 15:50:08,378 INFO: SwitchPort 9d:ac:59:a0:05:13 enabled
|
||||
2023-08-08 15:50:08,380 INFO: SwitchPort 45:f5:8e:b6:f5:d3 enabled
|
||||
2023-08-08 15:50:08,384 INFO: SwitchPort 91:d5:83:a0:02:f2 enabled
|
||||
2023-08-08 15:50:08,409 INFO: Added MAC table entry: Port 1 -> 80:af:f2:f6:58:b7
|
||||
2023-08-08 15:50:08,413 INFO: Added MAC table entry: Port 6 -> 84:20:7c:ec:a5:c6
|
||||
|
||||
|
||||
|
||||
**switch_2 sys log**
|
||||
|
||||
.. code-block::
|
||||
|
||||
2023-08-08 15:50:08,374 INFO: Turned on
|
||||
2023-08-08 15:50:08,381 INFO: SwitchPort aa:58:fa:66:d7:be enabled
|
||||
2023-08-08 15:50:08,383 INFO: SwitchPort 72:d2:1e:88:e9:45 enabled
|
||||
2023-08-08 15:50:08,384 INFO: SwitchPort 96:77:39:d1:de:44 enabled
|
||||
2023-08-08 15:50:08,411 INFO: Added MAC table entry: Port 6 -> 80:af:f2:f6:58:b7
|
||||
2023-08-08 15:50:08,412 INFO: Added MAC table entry: Port 2 -> 84:20:7c:ec:a5:c6
|
||||
|
||||
@@ -55,6 +55,19 @@ PrimAITE-specific metadata required for reinforcement learning (RL) purposes.
|
||||
Data Link Layer (Layer 2)
|
||||
#########################
|
||||
|
||||
**ARPEntry:** Represents an entry in the ARP cache. It consists of the following fields:
|
||||
|
||||
- **mac_address:** The MAC address associated with the IP address.
|
||||
- **nic_uuid:** The NIC (Network Interface Card) UUID through which the NIC with the IP address is reachable.
|
||||
|
||||
**ARPPacket:** Represents the ARP layer of a network frame, and it includes the following fields:
|
||||
|
||||
- **request:** ARP operation. Set to True for a request and False for a reply.
|
||||
- **sender_mac_addr:** Sender's MAC address.
|
||||
- **sender_ip:** Sender's IP address (IPv4 format).
|
||||
- **target_mac_addr:** Target's MAC address.
|
||||
- **target_ip:** Target's IP address (IPv4 format).
|
||||
|
||||
**EthernetHeader:** Represents the Ethernet layer of a network frame. It includes source and destination MAC addresses.
|
||||
This header is used to identify the physical hardware addresses of devices on a local network.
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ from enum import Enum
|
||||
from ipaddress import IPv4Address, IPv4Network
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from prettytable import PrettyTable
|
||||
|
||||
from primaite import getLogger
|
||||
from primaite.exceptions import NetworkError
|
||||
from primaite.simulator.core import SimComponent
|
||||
@@ -136,22 +138,23 @@ class NIC(SimComponent):
|
||||
if self.connected_node:
|
||||
if self.connected_node.operating_state == NodeOperatingState.ON:
|
||||
self.enabled = True
|
||||
_LOGGER.info(f"NIC {self} enabled")
|
||||
self.connected_node.sys_log.info(f"NIC {self} enabled")
|
||||
self.pcap = PacketCapture(hostname=self.connected_node.hostname, ip_address=self.ip_address)
|
||||
if self.connected_link:
|
||||
self.connected_link.endpoint_up()
|
||||
else:
|
||||
_LOGGER.info(f"NIC {self} cannot be enabled as the endpoint is not turned on")
|
||||
self.connected_node.sys_log.error(f"NIC {self} cannot be enabled as the endpoint is not turned on")
|
||||
else:
|
||||
msg = f"NIC {self} cannot be enabled as it is not connected to a Node"
|
||||
_LOGGER.error(msg)
|
||||
raise NetworkError(msg)
|
||||
_LOGGER.error(f"NIC {self} cannot be enabled as it is not connected to a Node")
|
||||
|
||||
def disable(self):
|
||||
"""Disable the NIC."""
|
||||
if self.enabled:
|
||||
self.enabled = False
|
||||
_LOGGER.info(f"NIC {self} disabled")
|
||||
if self.connected_node:
|
||||
self.connected_node.sys_log.info(f"NIC {self} disabled")
|
||||
else:
|
||||
_LOGGER.info(f"NIC {self} disabled")
|
||||
if self.connected_link:
|
||||
self.connected_link.endpoint_down()
|
||||
|
||||
@@ -161,7 +164,6 @@ class NIC(SimComponent):
|
||||
|
||||
:param link: The link to which the NIC is connected.
|
||||
:type link: :class:`~primaite.simulator.network.transmission.physical_layer.Link`
|
||||
:raise NetworkError: When an attempt to connect a Link is made while the NIC has a connected Link.
|
||||
"""
|
||||
if not self.connected_link:
|
||||
if self.connected_link != link:
|
||||
@@ -169,11 +171,9 @@ class NIC(SimComponent):
|
||||
self.connected_link = link
|
||||
_LOGGER.info(f"NIC {self} connected to Link {link}")
|
||||
else:
|
||||
_LOGGER.warning(f"Cannot connect link to NIC ({self.mac_address}) as it is already connected")
|
||||
_LOGGER.error(f"Cannot connect Link to NIC ({self.mac_address}) as it is already connected")
|
||||
else:
|
||||
msg = f"Cannot connect link to NIC ({self.mac_address}) as it already has a connection"
|
||||
_LOGGER.error(msg)
|
||||
raise NetworkError(msg)
|
||||
_LOGGER.error(f"Cannot connect Link to NIC ({self.mac_address}) as it already has a connection")
|
||||
|
||||
def disconnect_link(self):
|
||||
"""Disconnect the NIC from the connected Link."""
|
||||
@@ -293,12 +293,14 @@ class SwitchPort(SimComponent):
|
||||
if self.connected_node:
|
||||
if self.connected_node.operating_state == NodeOperatingState.ON:
|
||||
self.enabled = True
|
||||
_LOGGER.info(f"SwitchPort {self} enabled")
|
||||
self.connected_node.sys_log.info(f"SwitchPort {self} enabled")
|
||||
self.pcap = PacketCapture(hostname=self.connected_node.hostname)
|
||||
if self.connected_link:
|
||||
self.connected_link.endpoint_up()
|
||||
else:
|
||||
_LOGGER.info(f"SwitchPort {self} cannot be enabled as the endpoint is not turned on")
|
||||
self.connected_node.sys_log.info(
|
||||
f"SwitchPort {self} cannot be enabled as the endpoint is not turned on"
|
||||
)
|
||||
else:
|
||||
msg = f"SwitchPort {self} cannot be enabled as it is not connected to a Node"
|
||||
_LOGGER.error(msg)
|
||||
@@ -308,7 +310,10 @@ class SwitchPort(SimComponent):
|
||||
"""Disable the SwitchPort."""
|
||||
if self.enabled:
|
||||
self.enabled = False
|
||||
_LOGGER.info(f"SwitchPort {self} disabled")
|
||||
if self.connected_node:
|
||||
self.connected_node.sys_log.info(f"SwitchPort {self} disabled")
|
||||
else:
|
||||
_LOGGER.info(f"SwitchPort {self} disabled")
|
||||
if self.connected_link:
|
||||
self.connected_link.endpoint_down()
|
||||
|
||||
@@ -317,7 +322,6 @@ class SwitchPort(SimComponent):
|
||||
Connect the SwitchPort to a link.
|
||||
|
||||
:param link: The link to which the SwitchPort is connected.
|
||||
:raise NetworkError: When an attempt to connect a Link is made while the SwitchPort has a connected Link.
|
||||
"""
|
||||
if not self.connected_link:
|
||||
if self.connected_link != link:
|
||||
@@ -326,11 +330,9 @@ class SwitchPort(SimComponent):
|
||||
_LOGGER.info(f"SwitchPort {self} connected to Link {link}")
|
||||
self.enable()
|
||||
else:
|
||||
_LOGGER.warning(f"Cannot connect link to SwitchPort ({self.mac_address}) as it is already connected")
|
||||
_LOGGER.error(f"Cannot connect Link to SwitchPort {self.mac_address} as it is already connected")
|
||||
else:
|
||||
msg = f"Cannot connect link to SwitchPort ({self.mac_address}) as it already has a connection"
|
||||
_LOGGER.error(msg)
|
||||
raise NetworkError(msg)
|
||||
_LOGGER.error(f"Cannot connect link to SwitchPort {self.mac_address} as it already has a connection")
|
||||
|
||||
def disconnect_link(self):
|
||||
"""Disconnect the SwitchPort from the connected Link."""
|
||||
@@ -815,16 +817,34 @@ class Node(SimComponent):
|
||||
super().__init__(**kwargs)
|
||||
self.arp.nics = self.nics
|
||||
|
||||
def turn_on(self):
|
||||
"""Turn on the Node, enabling its NICs if it is in the OFF state."""
|
||||
def show(self):
|
||||
"""Prints a table of the NICs on the Node.."""
|
||||
from prettytable import PrettyTable
|
||||
|
||||
table = PrettyTable(["MAC Address", "Address", "Default Gateway", "Speed", "Status"])
|
||||
|
||||
for nic in self.nics.values():
|
||||
table.add_row(
|
||||
[
|
||||
nic.mac_address,
|
||||
f"{nic.ip_address}/{nic.ip_network.prefixlen}",
|
||||
nic.gateway,
|
||||
nic.speed,
|
||||
"Enabled" if nic.enabled else "Disabled",
|
||||
]
|
||||
)
|
||||
print(table)
|
||||
|
||||
def power_on(self):
|
||||
"""Power on the Node, enabling its NICs if it is in the OFF state."""
|
||||
if self.operating_state == NodeOperatingState.OFF:
|
||||
self.operating_state = NodeOperatingState.ON
|
||||
self.sys_log.info("Turned on")
|
||||
for nic in self.nics.values():
|
||||
nic.enable()
|
||||
|
||||
def turn_off(self):
|
||||
"""Turn off the Node, disabling its NICs if it is in the ON state."""
|
||||
def power_off(self):
|
||||
"""Power off the Node, disabling its NICs if it is in the ON state."""
|
||||
if self.operating_state == NodeOperatingState.ON:
|
||||
for nic in self.nics.values():
|
||||
nic.disable()
|
||||
@@ -934,6 +954,14 @@ class Switch(Node):
|
||||
dst_mac_table: Dict[str, SwitchPort] = {}
|
||||
"A MAC address table mapping destination MAC addresses to corresponding SwitchPorts."
|
||||
|
||||
def show(self):
|
||||
"""Prints a table of the SwitchPorts on the Switch."""
|
||||
table = PrettyTable(["Port", "MAC Address", "Speed", "Status"])
|
||||
|
||||
for port_num, port in self.switch_ports.items():
|
||||
table.add_row([port_num, port.mac_address, port.speed, "Enabled" if port.enabled else "Disabled"])
|
||||
print(table)
|
||||
|
||||
def describe_state(self) -> Dict:
|
||||
"""TODO."""
|
||||
pass
|
||||
|
||||
@@ -2,15 +2,17 @@ from primaite.simulator.network.hardware.base import Link, NIC, Node, Switch
|
||||
|
||||
|
||||
def test_node_to_node_ping():
|
||||
"""Tests two Nodes are able to ping each other."""
|
||||
# TODO Add actual checks. Manual check performed for now.
|
||||
node_a = Node(hostname="node_a")
|
||||
nic_a = NIC(ip_address="192.168.0.10", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_a.connect_nic(nic_a)
|
||||
node_a.turn_on()
|
||||
node_a.power_on()
|
||||
|
||||
node_b = Node(hostname="node_b")
|
||||
nic_b = NIC(ip_address="192.168.0.11", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_b.connect_nic(nic_b)
|
||||
node_b.turn_on()
|
||||
node_b.power_on()
|
||||
|
||||
Link(endpoint_a=nic_a, endpoint_b=nic_b)
|
||||
|
||||
@@ -18,22 +20,24 @@ def test_node_to_node_ping():
|
||||
|
||||
|
||||
def test_multi_nic():
|
||||
"""Tests that Nodes with multiple NICs can ping each other and the data go across the correct links."""
|
||||
# TODO Add actual checks. Manual check performed for now.
|
||||
node_a = Node(hostname="node_a")
|
||||
nic_a = NIC(ip_address="192.168.0.10", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_a.connect_nic(nic_a)
|
||||
node_a.turn_on()
|
||||
node_a.power_on()
|
||||
|
||||
node_b = Node(hostname="node_b")
|
||||
nic_b1 = NIC(ip_address="192.168.0.11", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
nic_b2 = NIC(ip_address="10.0.0.12", subnet_mask="255.0.0.0", gateway="10.0.0.1")
|
||||
node_b.connect_nic(nic_b1)
|
||||
node_b.connect_nic(nic_b2)
|
||||
node_b.turn_on()
|
||||
node_b.power_on()
|
||||
|
||||
node_c = Node(hostname="node_c")
|
||||
nic_c = NIC(ip_address="10.0.0.13", subnet_mask="255.0.0.0", gateway="10.0.0.1")
|
||||
node_c.connect_nic(nic_c)
|
||||
node_c.turn_on()
|
||||
node_c.power_on()
|
||||
|
||||
Link(endpoint_a=nic_a, endpoint_b=nic_b1)
|
||||
|
||||
@@ -45,30 +49,38 @@ def test_multi_nic():
|
||||
|
||||
|
||||
def test_switched_network():
|
||||
node_a = Node(hostname="node_a")
|
||||
"""Tests a larges network of Nodes and Switches with one node pinging another."""
|
||||
# TODO Add actual checks. Manual check performed for now.
|
||||
pc_a = Node(hostname="pc_a")
|
||||
nic_a = NIC(ip_address="192.168.0.10", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_a.connect_nic(nic_a)
|
||||
node_a.turn_on()
|
||||
pc_a.connect_nic(nic_a)
|
||||
pc_a.power_on()
|
||||
|
||||
node_b = Node(hostname="node_b")
|
||||
pc_b = Node(hostname="pc_b")
|
||||
nic_b = NIC(ip_address="192.168.0.11", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_b.connect_nic(nic_b)
|
||||
node_b.turn_on()
|
||||
pc_b.connect_nic(nic_b)
|
||||
pc_b.power_on()
|
||||
|
||||
node_c = Node(hostname="node_c")
|
||||
pc_c = Node(hostname="pc_c")
|
||||
nic_c = NIC(ip_address="192.168.0.12", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_c.connect_nic(nic_c)
|
||||
node_c.turn_on()
|
||||
pc_c.connect_nic(nic_c)
|
||||
pc_c.power_on()
|
||||
|
||||
switch_1 = Switch(hostname="switch_1")
|
||||
switch_1.turn_on()
|
||||
pc_d = Node(hostname="pc_d")
|
||||
nic_d = NIC(ip_address="192.168.0.13", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
pc_d.connect_nic(nic_d)
|
||||
pc_d.power_on()
|
||||
|
||||
switch_2 = Switch(hostname="switch_2")
|
||||
switch_2.turn_on()
|
||||
switch_1 = Switch(hostname="switch_1", num_ports=6)
|
||||
switch_1.power_on()
|
||||
|
||||
Link(endpoint_a=nic_a, endpoint_b=switch_1.switch_ports[1])
|
||||
Link(endpoint_a=nic_b, endpoint_b=switch_1.switch_ports[2])
|
||||
Link(endpoint_a=switch_1.switch_ports[24], endpoint_b=switch_2.switch_ports[24])
|
||||
Link(endpoint_a=nic_c, endpoint_b=switch_2.switch_ports[1])
|
||||
switch_2 = Switch(hostname="switch_2", num_ports=6)
|
||||
switch_2.power_on()
|
||||
|
||||
node_a.ping("192.168.0.12")
|
||||
link_nic_a_switch_1 = Link(endpoint_a=nic_a, endpoint_b=switch_1.switch_ports[1])
|
||||
link_nic_b_switch_1 = Link(endpoint_a=nic_b, endpoint_b=switch_1.switch_ports[2])
|
||||
link_nic_c_switch_2 = Link(endpoint_a=nic_c, endpoint_b=switch_2.switch_ports[1])
|
||||
link_nic_d_switch_2 = Link(endpoint_a=nic_d, endpoint_b=switch_2.switch_ports[2])
|
||||
link_switch_1_switch_2 = Link(endpoint_a=switch_1.switch_ports[6], endpoint_b=switch_2.switch_ports[6])
|
||||
|
||||
pc_a.ping("192.168.0.13")
|
||||
|
||||
@@ -6,13 +6,13 @@ def test_link_up():
|
||||
node_a = Node(hostname="node_a")
|
||||
nic_a = NIC(ip_address="192.168.0.10", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_a.connect_nic(nic_a)
|
||||
node_a.turn_on()
|
||||
node_a.power_on()
|
||||
assert nic_a.enabled
|
||||
|
||||
node_b = Node(hostname="node_b")
|
||||
nic_b = NIC(ip_address="192.168.0.11", subnet_mask="255.255.255.0", gateway="192.168.0.1")
|
||||
node_b.connect_nic(nic_b)
|
||||
node_b.turn_on()
|
||||
node_b.power_on()
|
||||
|
||||
assert nic_b.enabled
|
||||
|
||||
|
||||
Reference in New Issue
Block a user