From 4c3ef28236835e04c1aebce7eb08914d90629316 Mon Sep 17 00:00:00 2001 From: gruetzkopf Date: Sun, 30 Jan 2022 21:10:14 +0100 Subject: [PATCH] This should work --- .../li/cil/oc2/common/block/VxlanBlock.java | 9 ++++ .../common/blockentity/VxlanBlockEntity.java | 48 ++++++++++++++--- .../cil/oc2/common/vxlan/TunnelManager.java | 53 +++++++++++-------- 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/src/main/java/li/cil/oc2/common/block/VxlanBlock.java b/src/main/java/li/cil/oc2/common/block/VxlanBlock.java index 6a8911f8..79f0cea6 100644 --- a/src/main/java/li/cil/oc2/common/block/VxlanBlock.java +++ b/src/main/java/li/cil/oc2/common/block/VxlanBlock.java @@ -2,6 +2,7 @@ package li.cil.oc2.common.block; import li.cil.oc2.common.blockentity.BlockEntities; import li.cil.oc2.common.blockentity.NetworkHubBlockEntity; +import li.cil.oc2.common.blockentity.TickableBlockEntity; import li.cil.oc2.common.blockentity.VxlanBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -12,6 +13,8 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.HorizontalDirectionalBlock; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.material.Material; @@ -52,6 +55,12 @@ public final class VxlanBlock extends HorizontalDirectionalBlock implements Enti return BlockEntities.VXLAN_HUB.get().create(pos, state); } + @Nullable + @Override + public BlockEntityTicker getTicker(final Level level, final BlockState state, final BlockEntityType type) { + return TickableBlockEntity.createServerTicker(level, type, BlockEntities.VXLAN_HUB.get()); + } + /////////////////////////////////////////////////////////////////// @Override diff --git a/src/main/java/li/cil/oc2/common/blockentity/VxlanBlockEntity.java b/src/main/java/li/cil/oc2/common/blockentity/VxlanBlockEntity.java index cbddbc1b..d43ffcaf 100644 --- a/src/main/java/li/cil/oc2/common/blockentity/VxlanBlockEntity.java +++ b/src/main/java/li/cil/oc2/common/blockentity/VxlanBlockEntity.java @@ -16,13 +16,19 @@ import net.minecraftforge.common.util.LazyOptional; import javax.annotation.Nullable; import java.util.Arrays; import java.util.Objects; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; import java.util.stream.Stream; -public final class VxlanBlockEntity extends ModBlockEntity implements NetworkInterface { +public final class VxlanBlockEntity extends ModBlockEntity implements NetworkInterface, TickableBlockEntity { private static final int TTL_COST = 1; - private int vti = ((int) (Math.random() * Integer.MAX_VALUE)) & 0x00ff_ffff; + //private int vti = ((int) (Math.random() * Integer.MAX_VALUE)) & 0x00ff_ffff; + private int vti = 4037973; private boolean initialized = false; + private BlockingQueue packetQueue = new ArrayBlockingQueue(32); + /////////////////////////////////////////////////////////////////// // Each face and the default TunnelInterface connecting to the outernet @@ -32,9 +38,10 @@ public final class VxlanBlockEntity extends ModBlockEntity implements NetworkInt /////////////////////////////////////////////////////////////////// public VxlanBlockEntity(final BlockPos pos, final BlockState state) { - super(BlockEntities.NETWORK_HUB.get(), pos, state); + super(BlockEntities.VXLAN_HUB.get(), pos, state); } + /////////////////////////////////////////////////////////////////// public void handleNeighborChanged() { @@ -55,24 +62,47 @@ public final class VxlanBlockEntity extends ModBlockEntity implements NetworkInt }); } + @Override + public void serverTick() { + if (level == null) { + return; + } + + if (adjacentBlockInterfaces[0] != null) { + packetQueue.forEach(packet -> { + writeEthernetFrame(adjacentBlockInterfaces[0], packet, 255); + }); + packetQueue.clear(); + } else { + System.out.printf("VXLAN block is unregistered upstream: VTI=%d\n", vti); + } + } + /////////////////////////////////////////////////////////////////// @Override public void load(CompoundTag tag) { super.load(tag); - vti = tag.getInt("vti"); + if (!level.isClientSide()) { + // vti = tag.getInt("vti"); + adjacentBlockInterfaces[0] = TunnelManager.instance().registerVti(vti, packetQueue); + } } @Override public void saveAdditional(CompoundTag tag) { super.saveAdditional(tag); - tag.putInt("vti", vti); + if (!level.isClientSide()) { + tag.putInt("vti", vti); + } } @Override protected void onUnload(final boolean isRemove) { - adjacentBlockInterfaces[0] = null; - TunnelManager.instance().unregisterVti(vti); + if (!level.isClientSide()) { + adjacentBlockInterfaces[0] = null; + TunnelManager.instance().unregisterVti(vti); + } super.onUnload(isRemove); } @@ -83,12 +113,14 @@ public final class VxlanBlockEntity extends ModBlockEntity implements NetworkInt if (!level.isClientSide()) { System.out.println("Tunnel VTI: " + vti); + adjacentBlockInterfaces[0] = TunnelManager.instance().registerVti(vti, this.packetQueue); } - adjacentBlockInterfaces[0] = TunnelManager.instance().registerVti(vti, this); } /////////////////////////////////////////////////////////////////// + + @Override protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) { collector.offer(Capabilities.NETWORK_INTERFACE, this); diff --git a/src/main/java/li/cil/oc2/common/vxlan/TunnelManager.java b/src/main/java/li/cil/oc2/common/vxlan/TunnelManager.java index e6f028be..e9d8939f 100644 --- a/src/main/java/li/cil/oc2/common/vxlan/TunnelManager.java +++ b/src/main/java/li/cil/oc2/common/vxlan/TunnelManager.java @@ -2,11 +2,11 @@ package li.cil.oc2.common.vxlan; import li.cil.oc2.api.capabilities.NetworkInterface; import li.cil.oc2.common.Config; -import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.net.*; import java.util.HashMap; +import java.util.concurrent.BlockingQueue; public class TunnelManager { @@ -28,8 +28,8 @@ public class TunnelManager { public static void initialize() { try { INSTANCE = new TunnelManager( - InetAddress.getByName("2001:16b8:4908:5700:d22e:ecd:e75b:f5a8"), (short) Config.bindPort, - InetAddress.getByName("2001:470:7398::a"), (short) Config.remotePort + InetAddress.getByName("2001:470:7398::a"), (short) Config.bindPort, + InetAddress.getByName("2001:470:7398::10"), (short) Config.remotePort ); } catch (SocketException | UnknownHostException e) { System.out.println("Failed to bind host: " + e.getMessage()); @@ -37,13 +37,15 @@ public class TunnelManager { } //if (Config.enable) { - new Thread(() -> { + Thread bgThread = new Thread(() -> { try { INSTANCE.listen(); } catch (IOException e) { e.printStackTrace(); } - }).start(); + }); + bgThread.setName("VXLAN Background Thread"); + bgThread.start(); //} } @@ -52,7 +54,7 @@ public class TunnelManager { //if (Config.enable) { socket = new DatagramSocket(bindPort/*, bindHost*/); - socket.connect(remoteHost, remotePort); + //socket.connect(remoteHost, remotePort); //} else { // socket = null; //} @@ -62,28 +64,33 @@ public class TunnelManager { while (true) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket.receive(packet); - System.out.println("Received message"); - if (packet.getData().length < 8) { + if (packet.getLength() < 8) { continue; } byte flags = packet.getData()[0]; - int vni = packet.getData()[6] - + packet.getData()[5] << 8 - + packet.getData()[4] << 16; + int vni = (packet.getData()[6] & 0xFF ) + | ( ( packet.getData()[5] & 0xFF ) << 8 ) + | ( ( packet.getData()[4] & 0xFF ) << 16 ); if ((flags & 0x08) != 0x08) { continue; } + System.out.println(vni); + TunnelInterface iface = tunnels.get(vni); if (iface != null) { - byte[] inner = new byte[packet.getData().length - 8]; - System.arraycopy(packet.getData(), 8, inner, 0, packet.getData().length - 8); + byte[] inner = new byte[packet.getLength() - 8]; + System.arraycopy(packet.getData(), 8, inner, 0, packet.getLength() - 8); - iface.target.writeEthernetFrame(iface, inner, 255); + try { + iface.packetQueue.add(inner); + } catch (IllegalStateException ignored) { + System.err.println("Queue full"); + } } } } @@ -92,8 +99,9 @@ public class TunnelManager { return INSTANCE; } - public void sendToVti(int vti, byte[] payload) { + public void sendToOuternet(int vti, byte[] payload) { if (socket != null) { + byte[] buffer = new byte[payload.length + 8]; System.arraycopy(payload, 0, buffer, 8, payload.length); @@ -110,11 +118,13 @@ public class TunnelManager { } catch (IOException e) { e.printStackTrace(); } + } else { + System.out.printf("No socket in TunnelManager\n"); } } - public NetworkInterface registerVti(int vti, NetworkInterface iface) { - TunnelInterface tuniface = new TunnelInterface(vti, iface); + public NetworkInterface registerVti(int vti, BlockingQueue packetQueue) { + TunnelInterface tuniface = new TunnelInterface(vti, packetQueue); tunnels.put(vti, tuniface); return tuniface; } @@ -124,14 +134,15 @@ public class TunnelManager { } public class TunnelInterface implements NetworkInterface { - final NetworkInterface target; + final BlockingQueue packetQueue; private final int vti; - public TunnelInterface(int vti, NetworkInterface iface) { + public TunnelInterface(int vti, BlockingQueue packetQueue) { this.vti = vti; - this.target = iface; + this.packetQueue = packetQueue; } + @Override public byte[] readEthernetFrame() { return new byte[0]; @@ -139,7 +150,7 @@ public class TunnelManager { @Override public void writeEthernetFrame(final NetworkInterface source, final byte[] frame, final int timeToLive) { - TunnelManager.this.sendToVti(vti, frame); + TunnelManager.this.sendToOuternet(vti, frame); } } }