From 7cc96d78ad70d94ff1e7ddc722fd28a3e30c94d7 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 6 Mar 2021 14:09:56 -0500 Subject: [PATCH] Delay packets after switching capacity is reached --- .../block/netswitch/SwitchBlockEntity.kt | 66 +++++++++++++++---- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt index 5f9f3f9..5e4f8d0 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt @@ -3,19 +3,24 @@ package net.shadowfacts.phycon.block.netswitch import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable import net.minecraft.block.BlockState import net.minecraft.block.entity.BlockEntity -import net.minecraft.entity.ItemEntity +import net.minecraft.item.ItemStack import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.ListTag import net.minecraft.util.Tickable import net.minecraft.util.math.Direction import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.frame.EthernetFrame import net.shadowfacts.phycon.api.frame.PacketFrame +import net.shadowfacts.phycon.api.util.IPAddress import net.shadowfacts.phycon.api.util.MACAddress +import net.shadowfacts.phycon.frame.BasePacketFrame import net.shadowfacts.phycon.init.PhyBlockEntities -import net.shadowfacts.phycon.util.NetworkUtil import net.shadowfacts.phycon.packet.ItemStackPacket +import net.shadowfacts.phycon.util.NetworkUtil import java.lang.ref.WeakReference +import java.util.Deque +import java.util.LinkedList /** * @author shadowfacts @@ -25,13 +30,14 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH), Tickable { companion object { - var SWITCHING_CAPACITY = 256 // 256 items/tick + var SWITCHING_CAPACITY = 256 // 256 packets/tick } val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) } private val macTable = mutableMapOf() - private var itemsHandledThisTick = 0 + private var packetsHandledThisTick = 0 + private var delayedPackets: Deque> = LinkedList() fun interfaceForSide(side: Direction): SwitchInterface { return interfaces.find { it.side == side }!! @@ -40,18 +46,20 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH), private fun handle(frame: EthernetFrame, fromItf: SwitchInterface) { macTable[frame.source] = fromItf.side - if (frame is PacketFrame && frame.packet is ItemStackPacket) { - val packet = frame.packet as ItemStackPacket - if (itemsHandledThisTick + packet.stack.count > SWITCHING_CAPACITY) { - // todo: calculate entity spawn point by finding non-obstructed location - val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack) - world!!.spawnEntity(entity) + if (frame is PacketFrame) { + if (packetsHandledThisTick > SWITCHING_CAPACITY) { + PhysicalConnectivity.NETWORK_LOGGER.debug("{} reached capacity, delaying forwarding {}", this, frame) + delayedPackets.addLast(frame to fromItf) return } else { - itemsHandledThisTick += packet.stack.count + packetsHandledThisTick++ } } + resend(frame, fromItf) + } + + private fun resend(frame: EthernetFrame, fromItf: SwitchInterface) { if (frame.destination.type != MACAddress.Type.BROADCAST && macTable.containsKey(frame.destination)) { val dir = macTable[frame.destination]!! PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) forwarding {} to side {}", this, fromItf.side, fromItf.macAddress, frame, dir) @@ -75,11 +83,30 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH), } override fun tick() { - itemsHandledThisTick = 0 + packetsHandledThisTick = 0 + + while (delayedPackets.isNotEmpty() && packetsHandledThisTick <= SWITCHING_CAPACITY) { + val (frame, fromItf) = delayedPackets.pop() + resend(frame, fromItf) + } } override fun toTag(tag: CompoundTag): CompoundTag { tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address }) + val list = ListTag() + for ((frame, fromItf) in delayedPackets) { + val packet = frame.packet + if (packet !is ItemStackPacket) continue + val compound = CompoundTag() + compound.putInt("FromItfSide", fromItf.side.ordinal) + compound.putInt("SourceIP", packet.source.address) + compound.putInt("DestinationIP", packet.destination.address) + compound.putLong("SourceMAC", frame.source.address) + compound.putLong("DestinationMAC", frame.destination.address) + compound.put("Stack", packet.stack.toTag(CompoundTag())) + list.add(compound) + } + tag.put("DelayedStackPackets", list) return super.toTag(tag) } @@ -88,6 +115,21 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH), tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l -> interfaces[i].macAddress = MACAddress(l) } + tag.getList("DelayedStackPackets", 10).forEach { it -> + val compound = it as CompoundTag + val fromItfSide = Direction.values()[compound.getInt("FromItfSide")] + val fromItf = interfaces.find { it.side == fromItfSide }!! + val sourceIP = IPAddress(compound.getInt("SourceIP")) + val destinationIP = IPAddress(compound.getInt("DestinationIP")) + val sourceMAC = MACAddress(compound.getLong("SourceMAC")) + val destinationMAC = MACAddress(compound.getLong("DestinationMAC")) + val stack = ItemStack.fromTag(compound.getCompound("Stack")) + if (!stack.isEmpty) { + val packet = ItemStackPacket(stack, sourceIP, destinationIP) + val frame = BasePacketFrame(packet, sourceMAC, destinationMAC) + delayedPackets.addLast(frame to fromItf) + } + } } override fun toClientTag(tag: CompoundTag): CompoundTag {