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.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<MACAddress, Direction>()
private var itemsHandledThisTick = 0
private var packetsHandledThisTick = 0
private var delayedPackets: Deque<Pair<PacketFrame, SwitchInterface>> = 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 {