Delay packets after switching capacity is reached

This commit is contained in:
Shadowfacts 2021-03-06 14:09:56 -05:00
parent da8b600f31
commit 7cc96d78ad
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
1 changed files with 54 additions and 12 deletions

View File

@ -3,19 +3,24 @@ package net.shadowfacts.phycon.block.netswitch
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntity 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.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.util.Tickable import net.minecraft.util.Tickable
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.api.frame.EthernetFrame import net.shadowfacts.phycon.api.frame.EthernetFrame
import net.shadowfacts.phycon.api.frame.PacketFrame 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.api.util.MACAddress
import net.shadowfacts.phycon.frame.BasePacketFrame
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.util.NetworkUtil
import net.shadowfacts.phycon.packet.ItemStackPacket import net.shadowfacts.phycon.packet.ItemStackPacket
import net.shadowfacts.phycon.util.NetworkUtil
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.Deque
import java.util.LinkedList
/** /**
* @author shadowfacts * @author shadowfacts
@ -25,13 +30,14 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
Tickable { Tickable {
companion object { 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()) } val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) }
private val macTable = mutableMapOf<MACAddress, Direction>() private val macTable = mutableMapOf<MACAddress, Direction>()
private var itemsHandledThisTick = 0 private var packetsHandledThisTick = 0
private var delayedPackets: Deque<Pair<PacketFrame, SwitchInterface>> = LinkedList()
fun interfaceForSide(side: Direction): SwitchInterface { fun interfaceForSide(side: Direction): SwitchInterface {
return interfaces.find { it.side == side }!! return interfaces.find { it.side == side }!!
@ -40,18 +46,20 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
private fun handle(frame: EthernetFrame, fromItf: SwitchInterface) { private fun handle(frame: EthernetFrame, fromItf: SwitchInterface) {
macTable[frame.source] = fromItf.side macTable[frame.source] = fromItf.side
if (frame is PacketFrame && frame.packet is ItemStackPacket) { if (frame is PacketFrame) {
val packet = frame.packet as ItemStackPacket if (packetsHandledThisTick > SWITCHING_CAPACITY) {
if (itemsHandledThisTick + packet.stack.count > SWITCHING_CAPACITY) { PhysicalConnectivity.NETWORK_LOGGER.debug("{} reached capacity, delaying forwarding {}", this, frame)
// todo: calculate entity spawn point by finding non-obstructed location delayedPackets.addLast(frame to fromItf)
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack)
world!!.spawnEntity(entity)
return return
} else { } 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)) { if (frame.destination.type != MACAddress.Type.BROADCAST && macTable.containsKey(frame.destination)) {
val dir = macTable[frame.destination]!! val dir = macTable[frame.destination]!!
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) forwarding {} to side {}", this, fromItf.side, fromItf.macAddress, frame, dir) 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() { 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 { override fun toTag(tag: CompoundTag): CompoundTag {
tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address }) 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) return super.toTag(tag)
} }
@ -88,6 +115,21 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l -> tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l ->
interfaces[i].macAddress = MACAddress(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 { override fun toClientTag(tag: CompoundTag): CompoundTag {