From e4b6f266e8dd65c59e26455134b4a276a1fba028 Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Mon, 31 Jul 2023 20:05:36 +0100 Subject: [PATCH] #1715 - Added timestep int as a param to the apply_timestep function in core.py. Also added a reset_component_for_episode function. Updated docs with details of Link and NIC. --- .../node_nic_link_component_diagram.png | Bin 0 -> 25394 bytes docs/index.rst | 1 - docs/source/simulation.rst | 17 +- .../network/physical_layer.rst | 75 +++++++++ docs/source/simulation_structure.rst | 13 ++ src/primaite/simulator/core.py | 12 +- .../simulator/network/physical_layer.py | 156 +++++++++--------- 7 files changed, 192 insertions(+), 82 deletions(-) create mode 100644 docs/_static/node_nic_link_component_diagram.png create mode 100644 docs/source/simulation_components/network/physical_layer.rst create mode 100644 docs/source/simulation_structure.rst diff --git a/docs/_static/node_nic_link_component_diagram.png b/docs/_static/node_nic_link_component_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..00a3d93985101dde616ad36e3d5ab0f0ee54b036 GIT binary patch literal 25394 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 literal 0 HcmV?d00001 diff --git a/docs/index.rst b/docs/index.rst index c0e7a007..a75dd8e5 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -36,7 +36,6 @@ Head over to the :ref:`getting-started` page to install and setup PrimAITE! .. toctree:: :maxdepth: 8 :caption: Contents: - :hidden: source/getting_started source/about diff --git a/docs/source/simulation.rst b/docs/source/simulation.rst index 1620f6ba..0af6c89f 100644 --- a/docs/source/simulation.rst +++ b/docs/source/simulation.rst @@ -2,9 +2,18 @@ © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK -Simulation Strucutre -==================== -The simulation is made up of many smaller components which are related to each other in a tree-like structure. At the top level, there is an object called the ``SimulationController`` _(doesn't exist yet)_, which has a physical network and a software controller for managing software and users. +Simulation +========== -Each node of the simulation 'tree' has responsibility for creating, deleting, and updating its direct descendants. +.. TODO:: Add spiel here about what the simulation is. + + +Contents +######## + +.. toctree:: + :maxdepth: 8 + + simulation_structure + simulation_components/network/physical_layer diff --git a/docs/source/simulation_components/network/physical_layer.rst b/docs/source/simulation_components/network/physical_layer.rst new file mode 100644 index 00000000..2d942847 --- /dev/null +++ b/docs/source/simulation_components/network/physical_layer.rst @@ -0,0 +1,75 @@ +.. only:: comment + + © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + +Physical Layer +============== + +The physical layer components are mode of a ``NIC`` (Network Interface Card) and a ``Link``. These components allow +modelling of layer 1 (physical layer) in the OSI model. + +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``. + +NICs have the following attributes: + +- **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. + +**Basic Example** + +.. code-block:: python + + nic1 = NIC( + ip_address="192.168.1.100", + subnet_mask="255.255.255.0", + gateway="192.168.1.1" + ) + +Link +#### + +The ``Link`` class represents a physical link between two network endpoints. + +Links have the following attributes: + +- **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. + +**Basic Example** + +.. 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" + ) + + link = Link( + endpoint_a=nic1, + endpoint_b=nic2, + bandwidth=1000 + ) + +Link, NIC, Node Interface +######################### + +.. image:: ../../../_static/node_nic_link_component_diagram.png diff --git a/docs/source/simulation_structure.rst b/docs/source/simulation_structure.rst new file mode 100644 index 00000000..65373a72 --- /dev/null +++ b/docs/source/simulation_structure.rst @@ -0,0 +1,13 @@ +.. only:: comment + + © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK + + +Simulation Structure +==================== + +The simulation is made up of many smaller components which are related to each other in a tree-like structure. At the +top level, there is an object called the ``SimulationController`` _(doesn't exist yet)_, which has a physical network +and a software controller for managing software and users. + +Each node of the simulation 'tree' has responsibility for creating, deleting, and updating its direct descendants. diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 5b9bea1f..c3130116 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -37,7 +37,7 @@ class SimComponent(BaseModel): possible_actions = self._possible_actions() if action[0] in possible_actions: # take the first element off the action list and pass the remaining arguments to the corresponding action - # funciton + # function possible_actions[action.pop(0)](action) else: raise ValueError(f"{self.__class__.__name__} received invalid action {action}") @@ -45,7 +45,7 @@ class SimComponent(BaseModel): def _possible_actions(self) -> Dict[str, Callable[[List[str]], None]]: return {} - def apply_timestep(self) -> None: + def apply_timestep(self, timestep: int) -> None: """ Apply a timestep evolution to this component. @@ -53,3 +53,11 @@ class SimComponent(BaseModel): sending data. """ pass + + def reset_component_for_episode(self): + """ + Reset this component to its original state for a new episode. + + Override this method with anything that needs to happen within the component for it to be reset. + """ + pass diff --git a/src/primaite/simulator/network/physical_layer.py b/src/primaite/simulator/network/physical_layer.py index 6d268b59..2bc5c2b8 100644 --- a/src/primaite/simulator/network/physical_layer.py +++ b/src/primaite/simulator/network/physical_layer.py @@ -43,76 +43,6 @@ def generate_mac_address(oui: Optional[str] = None) -> str: return ":".join(f"{b:02x}" for b in mac) -class Link(SimComponent): - """ - Represents a network link between two network interface cards (NICs). - - :param endpoint_a: The first NIC connected to the Link. - :type endpoint_a: NIC - :param endpoint_b: The second NIC connected to the Link. - :type endpoint_b: NIC - :param bandwidth: The bandwidth of the Link in Mbps (default is 100 Mbps). - :type bandwidth: int - """ - - endpoint_a: NIC - endpoint_b: NIC - bandwidth: int = 100 - current_load: int = 0 - - def model_post_init(self, __context: Any) -> None: - """ - Ensure that endpoint_a and endpoint_b are not the same :class:`~primaite.simulator.network.physical_layer.NIC`. - - :raises ValueError: If endpoint_a and endpoint_b are the same NIC. - """ - if self.endpoint_a == self.endpoint_b: - msg = "endpoint_a and endpoint_b cannot be the same NIC" - _LOGGER.error(msg) - raise ValueError(msg) - self.endpoint_a.connect_link(self) - self.endpoint_b.connect_link(self) - - def send_frame(self, sender_nic: NIC, frame): - """ - Send a network frame from one NIC to another connected NIC. - - :param sender_nic: The NIC sending the frame. - :type sender_nic: NIC - :param frame: The network frame to be sent. - :type frame: Frame - """ - pass - - def receive_frame(self, sender_nic: NIC, frame): - """ - Receive a network frame from a connected NIC. - - :param sender_nic: The NIC sending the frame. - :type sender_nic: NIC - :param frame: The network frame being received. - :type frame: Frame - """ - pass - - def describe_state(self) -> Dict: - """ - Get the current state of the Libk as a dict. - - :return: A dict containing the current state of the Link. - """ - pass - - def apply_action(self, action: str): - """ - Apply an action to the Link. - - :param action: The action to be applied. - :type action: str - """ - pass - - class NIC(SimComponent): """ Models a Network Interface Card (NIC) in a computer or network device. @@ -121,13 +51,11 @@ class NIC(SimComponent): :param subnet_mask: The subnet mask assigned to the NIC. :param gateway: The default gateway IP address for forwarding network traffic to other networks. :param mac_address: The MAC address of the NIC. Defaults to a randomly set MAC address. - :param speed: The speed of the NIC in Mbps. + :param speed: The speed of the NIC in Mbps (default is 100 Mbps). :param mtu: The Maximum Transmission Unit (MTU) of the NIC in Bytes, representing the largest data packet size it - can handle without fragmentation. + can handle without fragmentation (default is 1500 B). :param wake_on_lan: Indicates if the NIC supports Wake-on-LAN functionality. :param dns_servers: List of IP addresses of DNS servers used for name resolution. - :param connected_link: The link to which the NIC is connected (default is None). - :param enabled: Indicates whether the NIC is enabled. """ ip_address: Union[str, IPv4Address] @@ -204,7 +132,11 @@ class NIC(SimComponent): def disconnect_link(self): """Disconnect the NIC from the connected :class:`~primaite.simulator.network.physical_layer.Link`.""" - pass + if self.connected_link.endpoint_a == self: + self.connected_link.endpoint_a = None + if self.connected_link.endpoint_b == self: + self.connected_link.endpoint_b = None + self.connected_link = None def add_dns_server(self, ip_address: IPv4Address): """ @@ -260,3 +192,77 @@ class NIC(SimComponent): :type action: str """ pass + + +class Link(SimComponent): + """ + Represents a network link between two network interface cards (NICs). + + :param endpoint_a: The first NIC connected to the Link. + :type endpoint_a: NIC + :param endpoint_b: The second NIC connected to the Link. + :type endpoint_b: NIC + :param bandwidth: The bandwidth of the Link in Mbps (default is 100 Mbps). + :type bandwidth: int + """ + + endpoint_a: NIC + "The first NIC connected to the Link." + endpoint_b: NIC + "The second NIC connected to the Link." + bandwidth: int = 100 + "The bandwidth of the Link in Mbps (default is 100 Mbps)." + current_load: int = 0 + "The current load on the link in Mbps." + + def model_post_init(self, __context: Any) -> None: + """ + Ensure that endpoint_a and endpoint_b are not the same :class:`~primaite.simulator.network.physical_layer.NIC`. + + :raises ValueError: If endpoint_a and endpoint_b are the same NIC. + """ + if self.endpoint_a == self.endpoint_b: + msg = "endpoint_a and endpoint_b cannot be the same NIC" + _LOGGER.error(msg) + raise ValueError(msg) + self.endpoint_a.connect_link(self) + self.endpoint_b.connect_link(self) + + def send_frame(self, sender_nic: NIC, frame): + """ + Send a network frame from one NIC to another connected NIC. + + :param sender_nic: The NIC sending the frame. + :type sender_nic: NIC + :param frame: The network frame to be sent. + :type frame: Frame + """ + pass + + def receive_frame(self, sender_nic: NIC, frame): + """ + Receive a network frame from a connected NIC. + + :param sender_nic: The NIC sending the frame. + :type sender_nic: NIC + :param frame: The network frame being received. + :type frame: Frame + """ + pass + + def describe_state(self) -> Dict: + """ + Get the current state of the Libk as a dict. + + :return: A dict containing the current state of the Link. + """ + pass + + def apply_action(self, action: str): + """ + Apply an action to the Link. + + :param action: The action to be applied. + :type action: str + """ + pass