From ba3efea6c5d2f4d2fbd2ecc9364817f541000839 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 21 Jun 2021 21:33:06 +0200 Subject: simulator: Add support for attaching network adapter to machine This change bridges the compute and network simulation module by adding support for network adapters in the compute module. With these network adapters, compute workloads can communicate over the network that the adapters are connected to. --- .../opendc-simulator-compute/build.gradle.kts | 1 + .../opendc/simulator/compute/SimAbstractMachine.kt | 42 ++++++++++++++++++ .../org/opendc/simulator/compute/SimMachine.kt | 6 +++ .../opendc/simulator/compute/SimMachineContext.kt | 5 +++ .../simulator/compute/SimNetworkInterface.kt | 51 ++++++++++++++++++++++ .../simulator/compute/device/SimNetworkAdapter.kt | 36 +++++++++++++++ .../simulator/compute/device/SimPeripheral.kt | 33 ++++++++++++++ .../opendc/simulator/compute/model/MachineModel.kt | 7 ++- .../simulator/compute/model/NetworkAdapter.kt | 36 +++++++++++++++ .../org/opendc/simulator/compute/SimMachineTest.kt | 37 +++++++++++++--- 10 files changed, 248 insertions(+), 6 deletions(-) create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimNetworkInterface.kt create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimNetworkAdapter.kt create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimPeripheral.kt create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/NetworkAdapter.kt (limited to 'opendc-simulator/opendc-simulator-compute') diff --git a/opendc-simulator/opendc-simulator-compute/build.gradle.kts b/opendc-simulator/opendc-simulator-compute/build.gradle.kts index 41cdd40c..74384480 100644 --- a/opendc-simulator/opendc-simulator-compute/build.gradle.kts +++ b/opendc-simulator/opendc-simulator-compute/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { api(platform(projects.opendcPlatform)) api(projects.opendcSimulator.opendcSimulatorResources) api(projects.opendcSimulator.opendcSimulatorPower) + api(projects.opendcSimulator.opendcSimulatorNetwork) implementation(projects.opendcSimulator.opendcSimulatorCore) implementation(projects.opendcUtils) implementation(libs.yaml) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt index ca508054..99f9397d 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt @@ -25,8 +25,11 @@ package org.opendc.simulator.compute import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import org.opendc.simulator.compute.device.SimNetworkAdapter +import org.opendc.simulator.compute.device.SimPeripheral import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.model.MemoryUnit +import org.opendc.simulator.compute.model.NetworkAdapter import org.opendc.simulator.compute.workload.SimWorkload import org.opendc.simulator.resources.* import kotlin.coroutines.Continuation @@ -68,6 +71,16 @@ public abstract class SimAbstractMachine( */ protected val memory: SimMemory = Memory(SimResourceSource(model.memory.sumOf { it.size }.toDouble(), interpreter), model.memory) + /** + * The network interfaces available to the machine. + */ + protected val net: List = model.net.mapIndexed { i, adapter -> NetworkAdapterImpl(adapter, i) } + + /** + * The peripherals of the machine. + */ + public override val peripherals: List = net.map { it as SimNetworkAdapter } + /** * A flag to indicate that the machine is terminated. */ @@ -166,6 +179,8 @@ public abstract class SimAbstractMachine( override val memory: SimMemory = this@SimAbstractMachine.memory + override val net: List = this@SimAbstractMachine.net + override fun close() = cancel() } @@ -175,4 +190,31 @@ public abstract class SimAbstractMachine( private class Memory(source: SimResourceSource, override val models: List) : SimMemory, SimResourceProvider by source { override fun toString(): String = "SimAbstractMachine.Memory" } + + /** + * The [SimNetworkAdapter] implementation for a machine. + */ + private class NetworkAdapterImpl( + model: NetworkAdapter, + index: Int + ) : SimNetworkAdapter(), SimNetworkInterface { + override val name: String = "eth$index" + + override val bandwidth: Double = model.bandwidth + + override val provider: SimResourceProvider + get() = _rx + + override fun createConsumer(): SimResourceConsumer = _tx + + override val tx: SimResourceProvider + get() = _tx + private val _tx = SimResourceForwarder() + + override val rx: SimResourceConsumer + get() = _rx + private val _rx = SimResourceForwarder() + + override fun toString(): String = "SimAbstractMachine.NetworkAdapterImpl[name=$name,bandwidth=$bandwidth]" + } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt index 4e7d191c..0f4674d5 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt @@ -23,6 +23,7 @@ package org.opendc.simulator.compute import kotlinx.coroutines.flow.StateFlow +import org.opendc.simulator.compute.device.SimPeripheral import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.workload.SimWorkload @@ -35,6 +36,11 @@ public interface SimMachine : AutoCloseable { */ public val model: MachineModel + /** + * The peripherals attached to the machine. + */ + public val peripherals: List + /** * A [StateFlow] representing the CPU usage of the simulated machine. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt index 391442ec..68a7fb63 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt @@ -50,6 +50,11 @@ public interface SimMachineContext : AutoCloseable { */ public val memory: SimMemory + /** + * The network interfaces available to the workload. + */ + public val net: List + /** * Stop the workload. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimNetworkInterface.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimNetworkInterface.kt new file mode 100644 index 00000000..1ac126ae --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimNetworkInterface.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute + +import org.opendc.simulator.resources.SimResourceConsumer +import org.opendc.simulator.resources.SimResourceProvider + +/** + * A firmware interface to a network adapter. + */ +public interface SimNetworkInterface { + /** + * The name of the network interface. + */ + public val name: String + + /** + * The unidirectional bandwidth of the network interface in Mbps. + */ + public val bandwidth: Double + + /** + * The resource provider for the transmit channel of the network interface. + */ + public val tx: SimResourceProvider + + /** + * The resource consumer for the receive channel of the network interface. + */ + public val rx: SimResourceConsumer +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimNetworkAdapter.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimNetworkAdapter.kt new file mode 100644 index 00000000..dfb4ecf3 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimNetworkAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.device + +import org.opendc.simulator.compute.SimMachine +import org.opendc.simulator.network.SimNetworkPort + +/** + * A simulated network interface card (NIC or network adapter) that can be attached to a [SimMachine]. + */ +public abstract class SimNetworkAdapter : SimNetworkPort(), SimPeripheral { + /** + * The unidirectional bandwidth of the network adapter in Mbps. + */ + public abstract val bandwidth: Double +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimPeripheral.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimPeripheral.kt new file mode 100644 index 00000000..268271be --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/device/SimPeripheral.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.device + +import org.opendc.simulator.compute.SimMachine + +/** + * A component that can be attached to a [SimMachine]. + * + * This interface represents the physical view of the peripheral and should be used to configure the physical properties + * of the peripheral. + */ +public interface SimPeripheral diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt index 4b6fd7bb..d40aff53 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt @@ -27,5 +27,10 @@ package org.opendc.simulator.compute.model * * @property cpus The list of processing units available to the image. * @property memory The list of memory units available to the image. + * @property net A list of network adapters available for the machine. */ -public data class MachineModel(public val cpus: List, public val memory: List) +public data class MachineModel( + public val cpus: List, + public val memory: List, + public val net: List = emptyList() +) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/NetworkAdapter.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/NetworkAdapter.kt new file mode 100644 index 00000000..46472144 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/NetworkAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.model + +/** + * A description of a network adapter that is + * + * @property vendor The vendor of the network adapter. + * @property modelName The model name of the network adapter. + * @property bandwidth The bandwidth of the network adapter in Mbps. + */ +public data class NetworkAdapter( + public val vendor: String, + public val modelName: String, + public val bandwidth: Double +) diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt index dcf509e2..47ae119c 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt @@ -30,10 +30,8 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows -import org.opendc.simulator.compute.model.MachineModel -import org.opendc.simulator.compute.model.MemoryUnit -import org.opendc.simulator.compute.model.ProcessingNode -import org.opendc.simulator.compute.model.ProcessingUnit +import org.opendc.simulator.compute.device.SimNetworkAdapter +import org.opendc.simulator.compute.model.* import org.opendc.simulator.compute.power.ConstantPowerModel import org.opendc.simulator.compute.power.LinearPowerModel import org.opendc.simulator.compute.power.SimplePowerDriver @@ -41,6 +39,7 @@ import org.opendc.simulator.compute.workload.SimFlopsWorkload import org.opendc.simulator.compute.workload.SimWorkload import org.opendc.simulator.compute.workload.SimWorkloadLifecycle import org.opendc.simulator.core.runBlockingSimulation +import org.opendc.simulator.network.SimNetworkSink import org.opendc.simulator.power.SimPowerSource import org.opendc.simulator.resources.SimResourceInterpreter import org.opendc.simulator.resources.consumer.SimWorkConsumer @@ -58,7 +57,8 @@ class SimMachineTest { machineModel = MachineModel( cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } + memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + net = listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)) ) } @@ -232,6 +232,33 @@ class SimMachineTest { } } + @Test + fun testNetUsage() = runBlockingSimulation { + val interpreter = SimResourceInterpreter(coroutineContext, clock) + val machine = SimBareMetalMachine( + interpreter, + machineModel, + SimplePowerDriver(ConstantPowerModel(0.0)) + ) + + val adapter = (machine.peripherals[0] as SimNetworkAdapter) + adapter.connect(SimNetworkSink(interpreter, adapter.bandwidth)) + + try { + machine.run(object : SimWorkload { + override fun onStart(ctx: SimMachineContext) { + val lifecycle = SimWorkloadLifecycle(ctx) + val iface = ctx.net[0] + iface.tx.startConsumer(lifecycle.waitFor(SimWorkConsumer(iface.bandwidth, utilization = 0.8))) + } + }) + + assertEquals(1250, clock.millis()) + } finally { + machine.close() + } + } + @Test fun testCancellation() = runBlockingSimulation { val machine = SimBareMetalMachine( -- cgit v1.2.3