diff --git a/Makefile b/Makefile index 835b7d96..650b0046 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ endif ifeq ($(OS),Linux) LINUX_ARCH = $(ARCH) else -LINUX_ARCH = $(shell docker run --rm vproxyio/compile:latest uname -m) +LINUX_ARCH := $(shell docker run --rm vproxyio/compile:latest uname -m) endif # ifeq ($(LINUX_ARCH),arm64) @@ -86,7 +86,7 @@ _add_linux_so_to_zip: mkdir -p ./io/vproxy/ cp ./base/src/main/c/libvfdposix.so ./io/vproxy/libvfdposix-$(LINUX_ARCH).so cp ./submodules/vpxdp/libvpxdp.so ./io/vproxy/libvpxdp-$(LINUX_ARCH).so - cp ./submodules/xdp-tools/lib/libxdp/libxdp.1.4.0 ./io/vproxy/libxdp-$(LINUX_ARCH).so + cp ./submodules/vpxdp/submodules/xdp-tools/lib/libxdp/libxdp.so.1.4.0 ./io/vproxy/libxdp-$(LINUX_ARCH).so cp ./libmsquic.so ./io/vproxy/libmsquic-$(LINUX_ARCH).so cp ./base/src/main/c/libmsquic-java.so ./io/vproxy/libmsquic-java-$(LINUX_ARCH).so cp ./submodules/fubuki/target/release/libfubukil.so ./io/vproxy/libfubuki-$(LINUX_ARCH).so @@ -118,6 +118,8 @@ endif .PHONY: jar-with-lib ifeq ($(OS),Linux) jar-with-lib: clean jar native _add_linux_so_to_zip +.PHONY: jar-with-lib-skip-native +jar-with-lib-skip-native: clean-jar jar _add_linux_so_to_zip else jar-with-lib: clean jar native _add_linux_so_to_zip jar-with-lib-skip-native .PHONY: jar-with-lib-no-docker diff --git a/app/src/main/java/io/vproxy/app/app/cmd/Flag.java b/app/src/main/java/io/vproxy/app/app/cmd/Flag.java index 69368aac..29116443 100644 --- a/app/src/main/java/io/vproxy/app/app/cmd/Flag.java +++ b/app/src/main/java/io/vproxy/app/app/cmd/Flag.java @@ -16,7 +16,6 @@ public enum Flag { disable("disable"), rxgencsum("rx-gen-csum"), - offload("offload"), ; public final String fullname; diff --git a/app/src/main/java/io/vproxy/app/app/cmd/HelpCommand.java b/app/src/main/java/io/vproxy/app/app/cmd/HelpCommand.java index 03d89f28..61d695da 100644 --- a/app/src/main/java/io/vproxy/app/app/cmd/HelpCommand.java +++ b/app/src/main/java/io/vproxy/app/app/cmd/HelpCommand.java @@ -1,6 +1,7 @@ package io.vproxy.app.app.cmd; import io.vproxy.app.app.Application; +import io.vproxy.app.app.cmd.handle.param.OffloadHandle; import io.vproxy.app.app.cmd.handle.resource.SwitchHandle; import io.vproxy.base.Config; import io.vproxy.base.util.coll.Tuple; @@ -447,6 +448,7 @@ public enum ParamMan { framesize("frame-size", null, "size of a frame"), busypoll("busy-poll", null, "a number indicating whether to enable busy poll, " + "and may set the SO_BUSY_POLL_BUDGET as well"), + offload("offload", null, "specify offload operations"), ip("ip", null, "ip address or ip/mask"), iface("iface", null, "connected interface in switch"), ; @@ -470,7 +472,6 @@ public enum FlagMan { force("force", null, "forcibly to do something"), zerocopy("zerocopy", null, "indicate to perform zerocopy operations"), rxgencsum("rx-gen-csum", null, "generate checksum before receiving the packet into vswitch"), - offload("offload", null, "offload operations from java"), enable("enable", null, "enable the resource"), disable("disable", null, "disable the resource"), ; @@ -1372,15 +1373,17 @@ public enum ResMan { new ResActMan(ActMan.addto, "add xdp socket into the switch", Arrays.asList( new ResActParamMan(ParamMan.umem, "umem for the xdp socket to use. See `umem` for more info"), new ResActParamMan(ParamMan.queue, "the queue index to bind to"), - new ResActParamMan(ParamMan.rxringsize, "rx ring size", "" + SwitchUtils.RX_TX_CHUNKS), - new ResActParamMan(ParamMan.txringsize, "tx ring size", "" + SwitchUtils.RX_TX_CHUNKS), + new ResActParamMan(ParamMan.rxringsize, "rx ring size", "" + SwitchUtils.DEFAULT_RX_TX_CHUNKS), + new ResActParamMan(ParamMan.txringsize, "tx ring size", "" + SwitchUtils.DEFAULT_RX_TX_CHUNKS), new ResActParamMan(ParamMan.mode, "mode of the xsk, enum: {SKB, DRIVER}, see doc for more info", "" + BPFMode.SKB), new ResActParamMan(ParamMan.busypoll, "whether to enable busy poll, and set SO_BUSY_POLL_BUDGET. Set this option to 0 to disable busy poll", "0"), - new ResActParamMan(ParamMan.vrf, "vrf which the iface is assigned to") + new ResActParamMan(ParamMan.vrf, "vrf which the iface is assigned to"), + new ResActParamMan(ParamMan.offload, "support " + OffloadHandle.PACKET_SWITCHING + "," + OffloadHandle.CHECKSUM + ". " + + "Note that checksum offloading requires kernel version >= 6.8 and not all drivers support this feature", + "(none)") ), Arrays.asList( new ResActFlagMan(FlagMan.zerocopy, "allow kernel to use zerocopy machanism", false), - new ResActFlagMan(FlagMan.rxgencsum, "generate checksum in native code before receiving the packet in java", false), - new ResActFlagMan(FlagMan.offload, "offload mac switching to xdp program", false) + new ResActFlagMan(FlagMan.rxgencsum, "generate checksum in native code before receiving the packet in java", false) ), Arrays.asList( new Tuple<>( "add xdp xdptut-4667 to switch sw0 umem umem0 queue 0 rx-ring-size 2048 tx-ring-size 2048 mode SKB vrf 1 zerocopy", @@ -1487,9 +1490,9 @@ public enum ResMan { umem("umem", null, "umem for xdp sockets to use", Arrays.asList( new ResActMan(ActMan.addto, "add a umem to a switch", Arrays.asList( - new ResActParamMan(ParamMan.chunks, "how many chunks are there in this umem", "" + (SwitchUtils.RX_TX_CHUNKS * 2)), - new ResActParamMan(ParamMan.fillringsize, "size of the fill ring", "" + SwitchUtils.RX_TX_CHUNKS), - new ResActParamMan(ParamMan.compringsize, "size of the comp ring", "" + SwitchUtils.RX_TX_CHUNKS), + new ResActParamMan(ParamMan.chunks, "how many chunks are there in this umem", "" + (SwitchUtils.DEFAULT_UMEM_CHUNKS)), + new ResActParamMan(ParamMan.fillringsize, "size of the fill ring", "" + SwitchUtils.DEFAULT_RX_TX_CHUNKS), + new ResActParamMan(ParamMan.compringsize, "size of the comp ring", "" + SwitchUtils.DEFAULT_RX_TX_CHUNKS), new ResActParamMan(ParamMan.framesize, "size of the frame, must be 2048 or 4096", "" + SwitchUtils.TOTAL_RCV_BUF_LEN / 2) ), Arrays.asList( new Tuple<>( diff --git a/app/src/main/java/io/vproxy/app/app/cmd/ModuleCommands.kt b/app/src/main/java/io/vproxy/app/app/cmd/ModuleCommands.kt index a70363ce..ccbd35e5 100644 --- a/app/src/main/java/io/vproxy/app/app/cmd/ModuleCommands.kt +++ b/app/src/main/java/io/vproxy/app/app/cmd/ModuleCommands.kt @@ -919,11 +919,11 @@ class ModuleCommands private constructor() : Commands() { it + ResActParam(Param.mode) { BPFModeHandle.check(it) } it + ResActParam(Param.busypoll) { BusyPollHandle.check(it) } it + ResActParam(Param.vrf, required) { VrfParamHandle.check(it) } + it + ResActParam(Param.offload) { OffloadHandle.check(it) } }, flags = { it + ResActFlag(Flag.zerocopy) it + ResActFlag(Flag.rxgencsum) - it + ResActFlag(Flag.offload) }, exec = execUpdate { XDPHandle.add(it) } ) diff --git a/app/src/main/java/io/vproxy/app/app/cmd/Param.java b/app/src/main/java/io/vproxy/app/app/cmd/Param.java index 54ec4d1b..1850d2d0 100644 --- a/app/src/main/java/io/vproxy/app/app/cmd/Param.java +++ b/app/src/main/java/io/vproxy/app/app/cmd/Param.java @@ -60,6 +60,7 @@ public enum Param { compringsize("comp-ring-size"), framesize("frame-size"), busypoll("busy-poll"), + offload("offload"), url("url"), cls("class"), diff --git a/app/src/main/java/io/vproxy/app/app/cmd/handle/param/OffloadHandle.java b/app/src/main/java/io/vproxy/app/app/cmd/handle/param/OffloadHandle.java new file mode 100644 index 00000000..7a2327df --- /dev/null +++ b/app/src/main/java/io/vproxy/app/app/cmd/handle/param/OffloadHandle.java @@ -0,0 +1,53 @@ +package io.vproxy.app.app.cmd.handle.param; + +import io.vproxy.app.app.cmd.Command; +import io.vproxy.app.app.cmd.Param; + +import java.util.Arrays; + +public class OffloadHandle { + private OffloadHandle() { + } + + public static final String PACKET_SWITCHING = "pktsw"; + public static final String CHECKSUM = "csum"; + + public static boolean check(Command cmd, String... available) { + if (!cmd.args.containsKey(Param.offload)) { + return true; + } + var lsAvailable = Arrays.asList(available); + var offload = cmd.args.get(Param.offload); + var split = offload.split(","); + for (var s : split) { + s = s.trim(); + if (!lsAvailable.contains(s)) { + return false; + } + } + return true; + } + + public static boolean isPacketSwitchingOffloaded(Command cmd) { + return isOffloaded(cmd, PACKET_SWITCHING); + } + + public static boolean isChecksumOffloaded(Command cmd) { + return isOffloaded(cmd, CHECKSUM); + } + + private static boolean isOffloaded(Command cmd, String match) { + var offload = cmd.args.get(Param.offload); + if (offload == null) { + return false; + } + var split = offload.split(","); + for (var s : split) { + s = s.trim(); + if (s.equals(match)) { + return true; + } + } + return false; + } +} diff --git a/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/ArpHandle.java b/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/ArpHandle.java index 8182a58b..8bef1c8f 100644 --- a/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/ArpHandle.java +++ b/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/ArpHandle.java @@ -83,18 +83,18 @@ public static List list(Resource parent) throws Exception { macInArpEntries.add(a.mac); var macEntry = macEntriesMap.get(a.mac); if (macEntry == null) { - result.add(new ArpEntry(a.mac, a.ip, null, a.getTTL(), -1, false)); + result.add(new ArpEntry(a.mac, a.ip, null, a.getTTL(), -1, false, 0)); } else { var iface = macEntry.iface; var ttl = macEntry.getTTL(); - result.add(new ArpEntry(a.mac, a.ip, iface, a.getTTL(), ttl, macEntry.isOffloaded())); + result.add(new ArpEntry(a.mac, a.ip, iface, a.getTTL(), ttl, macEntry.isOffloaded(), macEntry.getOffloadedCount())); } } for (var m : macEntries) { if (macInArpEntries.contains(m.mac)) { continue; } - result.add(new ArpEntry(m.mac, null, m.iface, -1, m.getTTL(), m.isOffloaded())); + result.add(new ArpEntry(m.mac, null, m.iface, -1, m.getTTL(), m.isOffloaded(), m.getOffloadedCount())); } result.sort((a, b) -> { // sort by mac @@ -144,23 +144,9 @@ public static void remove(Command cmd) throws Exception { net.arpTable.remove(mac); } - public static class ArpEntry { - public final MacAddress mac; - public final IP ip; - public final Iface iface; - public final long arpTTL; - public final long macTTL; - public final boolean offloaded; - - public ArpEntry(MacAddress mac, IP ip, Iface iface, long arpTTL, long macTTL, boolean offloaded) { - this.mac = mac; - this.ip = ip; - this.iface = iface; - this.arpTTL = arpTTL; - this.macTTL = macTTL; - this.offloaded = offloaded; - } - + public record ArpEntry( + MacAddress mac, IP ip, Iface iface, long arpTTL, long macTTL, boolean offloaded, int offloadedCount + ) { private String strForIp(ArpEntry e) { if (e.ip == null) return ""; return e.ip.formatToIPString(); @@ -236,7 +222,7 @@ public String toString(List all) { String strMacTTL = strForMacTTL(this); sb.append(split).append("MAC-TTL:").append(strMacTTL); if (offloaded) { - sb.append("/offload"); + sb.append("/offload(").append(offloadedCount).append(")"); } return sb.toString(); } diff --git a/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/UMemHandle.java b/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/UMemHandle.java index 7c8c0de4..4152aa30 100644 --- a/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/UMemHandle.java +++ b/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/UMemHandle.java @@ -31,9 +31,9 @@ public static UMem get(String alias, String swAlias) throws NotFoundException { } public static void add(Command cmd) throws Exception { - int chunksSize = RingSizeHandle.get(cmd, Param.chunks, SwitchUtils.RX_TX_CHUNKS * 2); - int fillRingSize = RingSizeHandle.get(cmd, Param.fillringsize, SwitchUtils.RX_TX_CHUNKS); - int compRingSize = RingSizeHandle.get(cmd, Param.compringsize, SwitchUtils.RX_TX_CHUNKS); + int chunksSize = RingSizeHandle.get(cmd, Param.chunks, SwitchUtils.DEFAULT_UMEM_CHUNKS); + int fillRingSize = RingSizeHandle.get(cmd, Param.fillringsize, SwitchUtils.DEFAULT_RX_TX_CHUNKS); + int compRingSize = RingSizeHandle.get(cmd, Param.compringsize, SwitchUtils.DEFAULT_RX_TX_CHUNKS); int frameSize = FrameSizeHandle.get(cmd, SwitchUtils.TOTAL_RCV_BUF_LEN / 2); Switch sw = Application.get().switchHolder.get(cmd.prepositionResource.alias); diff --git a/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/XDPHandle.java b/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/XDPHandle.java index 8acf924f..5724e0b4 100644 --- a/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/XDPHandle.java +++ b/app/src/main/java/io/vproxy/app/app/cmd/handle/resource/XDPHandle.java @@ -21,8 +21,8 @@ public static void add(Command cmd) throws Exception { UMem umem = UMemHandle.get(cmd.args.get(Param.umem), sw.alias); int queueId = QueueHandle.get(cmd); - int rxRingSize = RingSizeHandle.get(cmd, Param.rxringsize, SwitchUtils.RX_TX_CHUNKS); - int txRingSize = RingSizeHandle.get(cmd, Param.txringsize, SwitchUtils.RX_TX_CHUNKS); + int rxRingSize = RingSizeHandle.get(cmd, Param.rxringsize, SwitchUtils.DEFAULT_RX_TX_CHUNKS); + int txRingSize = RingSizeHandle.get(cmd, Param.txringsize, SwitchUtils.DEFAULT_RX_TX_CHUNKS); boolean zeroCopy = cmd.flags.contains(Flag.zerocopy); int busyPollBudget = 0; if (cmd.args.containsKey(Param.busypoll)) { @@ -30,7 +30,8 @@ public static void add(Command cmd) throws Exception { } boolean rxGenChecksum = cmd.flags.contains(Flag.rxgencsum); int vrf = VrfParamHandle.get(cmd); - boolean offload = cmd.flags.contains(Flag.offload); + boolean pktswOffloaded = OffloadHandle.isPacketSwitchingOffloaded(cmd); + boolean csumOffloaded = OffloadHandle.isChecksumOffloaded(cmd); var nic = cmd.resource.alias; var mode = BPFModeHandle.get(cmd, BPFMode.SKB); @@ -41,12 +42,26 @@ public static void add(Command cmd) throws Exception { try { var xskMap = bpfobj.getMap(Prebuilt.DEFAULT_XSKS_MAP_NAME); - var macMap = createResult.map(); + var mac2portMap = createResult.mac2portMap(); + var port2devMap = createResult.port2devMap(); var srcmac2countMap = bpfobj.getMap(Prebuilt.DEFAULT_SRC_MAC_TO_COUNT_MAP_NAME); + var passmacMap = bpfobj.getMap(Prebuilt.DEFAULT_PASS_MAC_MAP_NAME); - sw.addXDP(nic, vrf, umem, new XDPIface.XDPParams( - queueId, rxRingSize, txRingSize, mode, zeroCopy, busyPollBudget, rxGenChecksum, offload, - new XDPIface.BPFInfo(bpfobj, xskMap, macMap, srcmac2countMap, createResult.groupName()))); + var bpfInfo = new XDPIface.BPFInfo(bpfobj, xskMap, mac2portMap, port2devMap, srcmac2countMap, passmacMap, createResult.groupName()); + + sw.addXDP(nic, vrf, umem, new XDPIface.XDPParamsBuilder() + .setQueueId(queueId) + .setBPFInfo(bpfInfo) + .setRxRingSize(rxRingSize) + .setTxRingSize(txRingSize) + .setMode(mode) + .setZeroCopy(zeroCopy) + .setBusyPollBudget(busyPollBudget) + .setRxGenChecksum(rxGenChecksum) + .setPktswOffloaded(pktswOffloaded) + .setCsumOffloaded(csumOffloaded) + .build() + ); } catch (Exception e) { Logger.error(LogType.SYS_ERROR, "failed to create xdp interface " + nic, e); createResult.release(true); diff --git a/app/src/main/java/io/vproxy/app/controller/DockerNetworkDriverImpl.java b/app/src/main/java/io/vproxy/app/controller/DockerNetworkDriverImpl.java index a6824a3c..6f2952f1 100644 --- a/app/src/main/java/io/vproxy/app/controller/DockerNetworkDriverImpl.java +++ b/app/src/main/java/io/vproxy/app/controller/DockerNetworkDriverImpl.java @@ -386,31 +386,41 @@ private XDPIface createXDPIface(Switch sw, UMem umem, VirtualNetwork net, String bpfobj = BPFObject.loadAndAttachToNic(nicname, BPFMode.SKB, true); } - BPFMap mac2portMap; + BPFMap mac2portMap = null; + BPFMap port2devMap = null; + BPFMap srcmac2countMap = null; try { - mac2portMap = bpfobj.getMap(Prebuilt.DEFAULT_MAC_TO_PORT_MAP_NAME); - } catch (Exception e) { - Logger.error(LogType.SYS_ERROR, "failed to retrieve mac2port map", e); if (isPodNic) { - reusedResult.release(true); - } else { - bpfobj.release(true); + mac2portMap = bpfobj.getMap(Prebuilt.DEFAULT_MAC_TO_PORT_MAP_NAME); + port2devMap = bpfobj.getMap(Prebuilt.DEFAULT_PORT_TO_DEV_MAP_NAME); + srcmac2countMap = bpfobj.getMap(Prebuilt.DEFAULT_SRC_MAC_TO_COUNT_MAP_NAME); } + } catch (Exception e) { + Logger.error(LogType.SYS_ERROR, "failed to retrieve mac2port map", e); + reusedResult.release(true); throw e; } + var bpfInfo = new XDPIface.BPFInfo( + bpfobj, + bpfobj.getMap(Prebuilt.DEFAULT_XSKS_MAP_NAME), + mac2portMap, + port2devMap, + srcmac2countMap, + null, + isPodNic ? SHARED_BPF_MAP_GROUP_NAME : null + ); + XDPIface iface; try { iface = sw.addXDP(nicname, net != null ? net.vrf : NETWORK_ENTRY_VRF, umem, - new XDPIface.XDPParams(0, 32, 32, BPFMode.SKB, - false, 0, false, isPodNic, - new XDPIface.BPFInfo( - bpfobj, - bpfobj.getMap(Prebuilt.DEFAULT_XSKS_MAP_NAME), - isPodNic ? mac2portMap : null, - isPodNic ? bpfobj.getMap(Prebuilt.DEFAULT_SRC_MAC_TO_COUNT_MAP_NAME) : null, - isPodNic ? SHARED_BPF_MAP_GROUP_NAME : null - ))); + new XDPIface.XDPParamsBuilder() + .setQueueId(0) + .setBPFInfo(bpfInfo) + .setRxGenChecksum(!NativeXDP.supportTxMetadata) + .setPktswOffloaded(isPodNic) + .setCsumOffloaded(true) + .build()); } catch (Exception e) { Logger.error(LogType.SYS_ERROR, "failed to create xdp interface: " + nicname, e); if (isPodNic) { diff --git a/app/src/main/java/io/vproxy/app/process/Shutdown.java b/app/src/main/java/io/vproxy/app/process/Shutdown.java index 83681dd8..de4d3a3d 100644 --- a/app/src/main/java/io/vproxy/app/process/Shutdown.java +++ b/app/src/main/java/io/vproxy/app/process/Shutdown.java @@ -1,6 +1,7 @@ package io.vproxy.app.process; import io.vproxy.app.app.*; +import io.vproxy.app.app.cmd.handle.param.OffloadHandle; import io.vproxy.app.app.util.SignalHook; import io.vproxy.app.controller.HttpController; import io.vproxy.app.controller.RESPController; @@ -758,8 +759,14 @@ public static String currentConfig() { + " mode " + xdp.params.mode().name() + " busy-poll " + xdp.params.busyPollBudget() + " vrf " + xdp.vrf; - if (xdp.params.offload()) { - cmd += " offload"; + if (xdp.params.pktswOffloaded() || xdp.params.csumOffloaded()) { + cmd += " offload "; + var ls = new ArrayList(); + if (xdp.params.pktswOffloaded()) + ls.add(OffloadHandle.PACKET_SWITCHING); + if (xdp.params.csumOffloaded()) + ls.add(OffloadHandle.CHECKSUM); + cmd += String.join(",", ls); } if (xdp.params.zeroCopy()) { cmd += " zerocopy"; diff --git a/base/src/main/java/io/vproxy/vfd/posix/AESelector.java b/base/src/main/java/io/vproxy/vfd/posix/AESelector.java index b6f9f6b6..62ad9a46 100644 --- a/base/src/main/java/io/vproxy/vfd/posix/AESelector.java +++ b/base/src/main/java/io/vproxy/vfd/posix/AESelector.java @@ -18,7 +18,7 @@ public class AESelector implements FDSelector { private final Posix posix; private final long ae; - private final int[] pipefd; // null, or pipefd[read][write], might be the same if using linux eventfd + private final int[] pipefd; // pipefd[read][write], might be the same if using linux eventfd private final Att[] attachments; private final DirectByteBuffer bufferForPipeFD; private boolean closed = false; @@ -62,19 +62,17 @@ private EventSet getJavaEvents(int events) { } private void clearPipeFD() { - if (pipefd != null) { - while (true) { - int x; - try { - x = posix.read(pipefd[0], bufferForPipeFD.realBuffer(), 0, 8); - } catch (IOException e) { - Logger.shouldNotHappen("reading from read end of pipefd failed", e); - break; - } - assert x == 0 || x == 8; - if (x == 0) { - break; - } + while (true) { + int x; + try { + x = posix.read(pipefd[0], bufferForPipeFD.realBuffer(), 0, 8); + } catch (IOException e) { + Logger.shouldNotHappen("reading from read end of pipefd failed", e); + break; + } + assert x == 0 || x == 8; + if (x == 0) { + break; } } } @@ -147,9 +145,6 @@ public Collection select(long millis) throws IOException { @Override public void wakeup() { - if (pipefd == null) { - throw new UnsupportedOperationException("does not support wakeup"); - } checkOpen(); bufferForPipeFD.getMemorySegment().set(ValueLayout.JAVA_LONG, 0, 1L); try { @@ -273,18 +268,16 @@ public void close() { if (bufferForPipeFD != null) { bufferForPipeFD.clean(); } - if (pipefd != null) { + try { + posix.close(pipefd[0]); + } catch (IOException e) { + Logger.shouldNotHappen("closing read end of the pipefd failed", e); + } + if (pipefd[1] != pipefd[0]) { try { - posix.close(pipefd[0]); + posix.close(pipefd[1]); } catch (IOException e) { - Logger.shouldNotHappen("closing read end of the pipefd failed", e); - } - if (pipefd[1] != pipefd[0]) { - try { - posix.close(pipefd[1]); - } catch (IOException e) { - Logger.shouldNotHappen("closing write end of the pipefd failed", e); - } + Logger.shouldNotHappen("closing write end of the pipefd failed", e); } } } diff --git a/base/src/main/java/io/vproxy/xdp/BPFMap.java b/base/src/main/java/io/vproxy/xdp/BPFMap.java index 55c6fa47..4c1876fc 100644 --- a/base/src/main/java/io/vproxy/xdp/BPFMap.java +++ b/base/src/main/java/io/vproxy/xdp/BPFMap.java @@ -31,7 +31,7 @@ public int getInt(MacAddress mac) throws IOException { if (err == -XDPConsts.ENOENT) { throw new FileNotFoundException(); } - throw new IOException("failed to retrieve value of key " + mac + " from " + this); + throw new IOException("failed to retrieve value of key " + mac + " from " + this + ", err = " + err); } return value.get(ValueLayout.JAVA_INT, 0); } @@ -42,47 +42,71 @@ private void setMacIntoMemSeg(MacAddress mac, MemorySegment seg) { } public void put(int key, XDPSocket xsk) throws IOException { - int res = map.addXsk(key, xsk.xsk); - if (res != 0) { - throw new IOException("failed to add xsk " + xsk.xsk + " to " + this); + int err = map.addXsk(key, xsk.xsk); + if (err != 0) { + throw new IOException("failed to add xsk " + xsk.xsk + " to " + this + ", err = " + err); } } public void putNetif(MacAddress mac, String ifname) throws IOException { - int res; + int err; try (var allocator = Allocator.ofConfined()) { var macRaw = allocator.allocate(6); setMacIntoMemSeg(mac, macRaw); - res = map.addMac2Port(macRaw, new PNIString(allocator, ifname)); + err = map.addMac2Port(macRaw, new PNIString(allocator, ifname)); } - if (res != 0) { - throw new IOException("failed to add mac " + mac + " to " + this); + if (err != 0) { + throw new IOException("failed to add mac2port " + mac + " -> " + ifname + " to " + this + ", err = " + err); + } + } + + public void putNetif(String ifname) throws IOException { + int err; + try (var allocator = Allocator.ofConfined()) { + err = map.addPort2Dev(new PNIString(allocator, ifname)); + } + if (err != 0) { + throw new IOException("failed to add port2dev " + ifname + " -> " + ifname + " to " + this + ", err = " + err); } } public void put(int key, byte value) throws IOException { - int res; + int err; try (var allocator = Allocator.ofConfined()) { var keyRaw = allocator.allocate(4); var valueRaw = allocator.allocate(1); keyRaw.set(ValueLayout.JAVA_INT, 0, key); valueRaw.set(ValueLayout.JAVA_BYTE, 0, value); - res = map.update(keyRaw, 4, valueRaw, 1, 0); + err = map.update(keyRaw, 4, valueRaw, 1, 0); + } + if (err != 0) { + throw new IOException("failed to add " + key + " => " + value + " to " + this + ", err = " + err); + } + } + + public void put(MacAddress mac, byte value) throws IOException { + int err; + try (var allocator = Allocator.ofConfined()) { + var keyRaw = allocator.allocate(6); + var valueRaw = allocator.allocate(1); + setMacIntoMemSeg(mac, keyRaw); + valueRaw.set(ValueLayout.JAVA_BYTE, 0, value); + err = map.update(keyRaw, 6, valueRaw, 1, 0); } - if (res != 0) { - throw new IOException("failed to add " + key + " => " + value + " to " + this); + if (err != 0) { + throw new IOException("failed to add " + mac + " => " + value + " to " + this + ", err = " + err); } } public void remove(MacAddress mac) throws IOException { - int res; + int err; try (var allocator = Allocator.ofConfined()) { var macRaw = allocator.allocate(6); setMacIntoMemSeg(mac, macRaw); - res = map.delete(macRaw, 6); + err = map.delete(macRaw, 6, 0); } - if (res != 0) { - throw new IOException("failed to remove mac " + mac + " from " + this); + if (err != 0) { + throw new IOException("failed to remove mac " + mac + " from " + this + ", err = " + err); } } } diff --git a/base/src/main/java/io/vproxy/xdp/BPFObject.java b/base/src/main/java/io/vproxy/xdp/BPFObject.java index c80cd507..a26add56 100644 --- a/base/src/main/java/io/vproxy/xdp/BPFObject.java +++ b/base/src/main/java/io/vproxy/xdp/BPFObject.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import static io.vproxy.xdp.Prebuilt.DEFAULT_PROG; @@ -82,6 +83,9 @@ public static BPFObject load(ByteArray bpfObjectBytes) throws IOException { var filename = generateBpfObjectFile(bpfObjectBytes); try (var allocator = Allocator.ofConfined()) { var o = XDP.get().loadBPFObject(new PNIString(allocator, filename), null); + if (o == null) { + throw new IOException("loading bpfobj failed"); + } obj = new BPFObject(o, null); } return obj; @@ -113,7 +117,13 @@ public BPFMap getMap(String name) throws IOException { } } + private final AtomicBoolean isReleased = new AtomicBoolean(false); + public void release(boolean detach) { + if (!isReleased.compareAndSet(false, true)) { + return; + } + bpfobj.release(); if (detach) { int res; diff --git a/base/src/main/java/io/vproxy/xdp/Prebuilt.java b/base/src/main/java/io/vproxy/xdp/Prebuilt.java index 2dd6b889..a39b2149 100644 --- a/base/src/main/java/io/vproxy/xdp/Prebuilt.java +++ b/base/src/main/java/io/vproxy/xdp/Prebuilt.java @@ -6,7 +6,9 @@ public class Prebuilt { public static final String DEFAULT_XDP_PROG_NAME = "xdp_sock"; public static final String DEFAULT_XSKS_MAP_NAME = "xsks_map"; public static final String DEFAULT_MAC_TO_PORT_MAP_NAME = "mac2port_map"; + public static final String DEFAULT_PORT_TO_DEV_MAP_NAME = "port2dev_map"; public static final String DEFAULT_SRC_MAC_TO_COUNT_MAP_NAME = "srcmac2count_map"; + public static final String DEFAULT_PASS_MAC_MAP_NAME = "pass_mac_map"; public static final String HANDLE_DST_PORT_MAP_NAME = "handled_ports"; @@ -18,283 +20,350 @@ private Prebuilt() { private static final ByteArray _DEFAULT_PROG = ByteArray.fromHexString( "7f454c46020101000000000000000000" + "0100f700010000000000000000000000" + - "00000000000000003822000000000000" + + "00000000000000000028000000000000" + "00000000400000000000400019000100" + - "bf160000000000006161040000000000" + - "6168000000000000bf82000000000000" + - "07020000060000002d122e0000000000" + + "bf16000000000000b700000001000000" + + "61610400000000006162000000000000" + + "bf230000000000000703000006000000" + + "2d134700000000001801000000000000" + + "00000000000000008500000001000000" + + "bf01000000000000b700000002000000" + + "55014100000000006161040000000000" + + "6167000000000000bf72000000000000" + + "070200000e0000002d12370000000000" + + "71710d000000000071720c0000000000" + + "67020000080000004f12000000000000" + + "15023200008100001801000000000000" + + "0000000000000000bf72000000000000" + + "8500000001000000bf08000000000000" + + "15082c00000000000707000006000000" + "18010000000000000000000000000000" + - "bf820000000000008500000001000000" + - "15002900000000006107000000000000" + - "61610c00000000001d71260000000000" + + "bf720000000000008500000001000000" + + "15002600000000006101000000000000" + + "61620c00000000005d12230000000000" + + "61870000000000001d71210000000000" + + "61610400000000006168000000000000" + + "bf82000000000000070200000c000000" + + "2d121300000000000708000006000000" + "18010000000000000000000000000000" + "bf820000000000008500000001000000" + - "bf01000000000000b700000002000000" + - "55012900000000006161040000000000" + - "6168000000000000bf82000000000000" + - "070200000c0000002d12130000000000" + - "07080000060000001801000000000000" + + "55000a0000000000b701000001000000" + + "631afcff00000000bfa3000000000000" + + "07030000fcffffff1801000000000000" + "0000000000000000bf82000000000000" + - "850000000100000055000a0000000000" + - "b701000001000000631afcff00000000" + - "bfa300000000000007030000fcffffff" + + "b7040000000000008500000002000000" + + "05000300000000006101000000000000" + + "07010000010000006310000000000000" + "18010000000000000000000000000000" + - "bf82000000000000b704000000000000" + - "85000000020000000500030000000000" + - "61010000000000000701000001000000" + - "6310000000000000bf71000000000000" + - "b7020000000000008500000017000000" + - "bf010000000000006701000020000000" + - "770100002000000025010a0001000000" + - "b7000000010000006161040000000000" + - "61620000000000000702000006000000" + - "2d120500000000006162100000000000" + + "bf72000000000000b703000001000000" + + "8500000033000000bf01000000000000" + + "67010000200000007701000020000000" + + "25010500010000006162100000000000" + "18010000000000000000000000000000" + "b7030000010000008500000033000000" + "95000000000000000000000000000000" + "00000000000000000000000000000000" + - "0000000000000000dd00000005000800" + - "0f0000003c000000480000004e000000" + - "5900000060000000670000006e000000" + - "76000000850000008d0000009c000000" + - "b5000000bd000000c5000000cd000000" + - "04000801510408f80301560004104001" + - "510004182801580428480152000418b8" + - "01015800045090010150000460a00301" + - "570004b001e80101510004b801c80101" + - "5804c801f00101520004b801d8010158" + - "0004f801c802015004d002e802015000" + - "04800290020311019f049002d002027a" + - "0404d802e002015100048003a0030150" + - "0004b003e00301510004b803d0030152" + - "0004b803c00301520001110125251305" + - "0325721710171b25111b120673178c01" + - "170000023400032549133a0b3b050000" + - "03260049130000040f00491300000515" + - "01491327190000060500491300000724" + - "0003253e0b0b0b0000080f0000000916" + - "00491303253a0b3b0b00000a34000325" + - "49133f193a0b3b0b021800000b13010b" + - "0b3a0b3b0b00000c0d00032549133a0b" + - "3b0b380b00000d0101491300000e2100" + - "4913370b00000f240003250b0b3e0b00" + - "00102100491337050000113400032549" + - "133a0b3b0b0000122600000013040149" + - "1303250b0b3a0b3b0500001428000325" + - "1c0f0000152e0103253a0b3b0b271949" + - "133f19202101000016050003253a0b3b" + - "0b4913000017340003253a0b3b0b4913" + - "000018130103250b0b3a0b3b05000019" + - "0d00032549133a0b3b05380b00001a2e" + - "0103253a0b3b0b27193f192021010000" + - "1b2e01111b120640187a1903253a0b3b" + - "0b271949133f1900001c050002220325" + - "3a0b3b0b491300001d3400022203253a" + - "0b3b0b491300001e1d013113111b1206" + - "580b590b570b00001f05000218311300" + - "00203400022231130000009803000005" + - "0001080000000001000c000108000000" + - "000000000204f8010000080000000c00" + - "0000020330000000022d050335000000" + - "043a000000054f000000065300000006" + - "54000000065400000000070405080809" + - "5c00000006011f070507080a076b0000" + - "00000902a1000b2000040c0894000000" + - "0005000c0bad0000000006080c0cbe00" + - "00000007100c0dbe0000000008180004" + - "990000000da50000000ea90000001100" + - "070905040f0a080704b20000000da500" + - "00000ea9000000800004a50000000a0e" + - "ce000000001102a1010b20000c0c08f7" + - "000000000d000c0b08010000000e080c" + - "0c1a010000000f100c0dbe0000000010" + - "180004fc0000000da50000000ea90000" + - "000900040d0100000da500000010a900" + - "0000001000041f0100000d2b0100000e" + - "a90000000600070f06010a103a010000" + - "001902a1020b2000140c08f700000000" + - "15000c0b080100000016080c0c1a0100" + - "000017100c0d6301000000181800042b" + - "0100000a1173010000002002a1030b20" + - "001b0c08f7000000001c000c0b080100" + - "00001d080c0c1a010000001e100c0dbe" + - "000000001f18001112a4010000023803" + - "a901000004ae01000005530000000653" + - "00000006be0100000004c30100001202" + - "13cd010000026d0203d201000004d701" + - "0000054f00000006e701000006540000" + - "000009ef01000015011b071407041116" + - "fb010000024e03000200000405020000" + - "054f000000065300000006be01000006" + - "be01000006540000000013ef0100001c" + - "04031919141700141801141902141a03" + - "141b0400043e020000071d0801151e00" + - "35a5000000161f00357b020000172100" + - "36390200001727003839020000172000" + - "37390200001728003dbe000000172900" + - "41a50000000004800200001826180324" + - "191920e7010000032519001921e70100" + - "00032619041922e70100000327190819" + - "23e70100000329190c1924e701000003" + - "2a19101925e7010000032c1914001a2a" + - "0022161f00227b020000172100233902" + - "00001727002539020000172000243902" + - "0000172b002abe000000172c002ba500" + - "0000001b04f8010000015a2d004da500" + - "00001c001f004d7b0200001d0b2e004f" + - "a50000001d0c210054390200001d0d27" + - "0056390200001d0e200055390200001e" + - "420200000590010000004f181f01564a" + - "02000020015202000020025a02000020" + - "036202000020046a0200002005720200" + - "001ec302000006c00000000049051f01" + - "56c70200002006cf0200002007d70200" + - "002008df0200002009e7020000200aef" + - "02000000000000c00000000500000000" + - "00000027000000310000004200000053" + - "000000580000006b000000710000007a" + - "0000007f0000008300000097000000a3" + - "000000a7000000ad000000ba000000bf" + - "000000cc000000dd000000f1000000fe" + - "0000000b010000110100002501000031" + - "0100003a010000430100004a01000057" + - "01000062010000700100008401000088" + - "0100008d01000096010000a0010000b0" + - "010000bf010000ce010000d5010000d9" + - "010000ea010000f70100000b02000013" + - "02000017020000200200005562756e74" + - "7520636c616e672076657273696f6e20" + - "31342e302e302d317562756e7475312e" + - "310064656661756c742e63002f767072" + - "6f78792f7072656275696c7400627066" + - "5f72656469726563745f6d6170006c6f" + - "6e6700756e7369676e6564206c6f6e67" + - "206c6f6e67005f5f7536340078736b73" + - "5f6d6170007479706500696e74005f5f" + - "41525241595f53495a455f545950455f" + - "5f006d61785f656e7472696573006b65" + - "790076616c7565006d616332706f7274" + - "5f6d6170006368617200706173735f6d" + - "61635f6d6170007372636d616332636f" + - "756e745f6d6170006270665f6d61705f" + - "6c6f6f6b75705f656c656d006270665f" + - "726564697265637400756e7369676e65" + - "6420696e74005f5f753332006270665f" + - "6d61705f7570646174655f656c656d00" + - "5844505f41424f52544544005844505f" + - "44524f50005844505f50415353005844" + - "505f5458005844505f52454449524543" + - "54007864705f616374696f6e00756e73" + - "69676e65642063686172007265646972" + - "6563745f706b745f62795f6d61630063" + - "7478006461746100646174615f656e64" + - "00646174615f6d65746100696e677265" + - "73735f6966696e6465780072785f7175" + - "6575655f696e64657800656772657373" + - "5f6966696e646578007864705f6d6400" + - "706f73006f75747075745f6966616365" + - "5f707472006f75747075745f69666163" + - "6500706b745f636f756e745f62795f73" + - "72636d616300636e745f70747200636e" + - "74007864705f736f636b007265646972" + - "6563745f726573003c00000005000800" + "00000000000000000000000000000000" + - "00000000000000000800000000000000" + - "a8000000000000009feb010018000000" + - "0000000004030000040300007a040000" + - "00000000000000020300000001000000" + - "00000001040000002000000100000000" + - "00000003000000000200000004000000" + - "11000000050000000000000104000000" + - "20000000000000000000000206000000" + - "00000000000000030000000002000000" + - "04000000800000000000000000000002" + - "02000000000000000400000420000000" + - "1900000001000000000000001e000000" + - "05000000400000002a00000007000000" + - "800000002e00000007000000c0000000" + - "340000000000000e0800000001000000" + - "00000000000000020b00000000000000" + - "00000003000000000200000004000000" + - "0900000000000000000000020d000000" + - "00000000000000030000000002000000" + - "04000000001000000000000000000002" + - "100000003d0000000000000101000000" + - "08000001000000000000000300000000" + - "0f000000040000000600000000000000" + - "0400000420000000190000000a000000" + - "000000001e0000000c00000040000000" + - "2a0000000e000000800000002e000000" + - "07000000c0000000420000000000000e" + - "11000000010000000000000000000002" + - "0f000000000000000400000420000000" + - "190000000a000000000000001e000000" + - "0c000000400000002a0000000e000000" + - "800000002e00000013000000c0000000" + - "4f0000000000000e1400000001000000" + - "00000000040000042000000019000000" + - "0a000000000000001e0000000c000000" + - "400000002a0000000e00000080000000" + - "2e00000007000000c00000005c000000" + - "0000000e160000000100000000000000" + - "00000002190000006d00000006000004" + - "18000000740000001a00000000000000" + - "790000001a0000002000000082000000" + - "1a000000400000008c0000001a000000" + - "600000009c0000001a00000080000000" + - "ab0000001a000000a0000000ba000000" + - "000000081b000000c000000000000001" + - "0400000020000000000000000100000d" + - "02000000cd00000018000000d1000000" + - "0100000c1c000000740400000400000f" + - "00000000090000000000000020000000" + - "12000000000000002000000015000000" + - "00000000200000001700000000000000" + - "2000000000696e74005f5f4152524159" + - "5f53495a455f545950455f5f00747970" + - "65006d61785f656e7472696573006b65" + - "790076616c75650078736b735f6d6170" + - "0063686172006d616332706f72745f6d" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000601000005000800" + + "1200000048000000540000005a000000" + + "650000006b0000007200000080000000" + + "870000008f000000970000009f000000" + + "a7000000af000000b7000000c6000000" + + "ce000000dd000000f600000004000801" + + "510408f8040156000418480151000420" + + "30015204305001530004205001520004" + + "709801015100047888010157048801a0" + + "010152000478f00101570004b001d001" + + "01520004e001d0020158000490029003" + + "01500004a002c80201510004b802c804" + + "01570004c802800301510004d002e002" + + "015804e002880301520004d002f00201" + + "5800049003e003015004e80380040150" + + "00049803a8030311019f04a803e80302" + + "7a0404f003f80301510004a804c80401" + + "5000011101252513050325721710171b" + + "25111b120673178c0117000002340003" + + "2549133a0b3b0b000003260049130000" + + "040f0049130000051501491327190000" + + "06050049130000070f00000008260000" + + "00093400032549133a0b3b0500000a24" + + "0003253e0b0b0b00000b160049130325" + + "3a0b3b0b00000c3400032549133f193a" + + "0b3b0b021800000d13010b0b3a0b3b0b" + + "00000e0d00032549133a0b3b0b380b00" + + "000f0101491300001021004913370b00" + + "0011240003250b0b3e0b000012210049" + + "13370600001321004913370500001404" + + "01491303250b0b3a0b3b050000152800" + + "03251c0f0000162e0103253a0b3b0b27" + + "1949133f19202101000017050003253a" + + "0b3b0b4913000018340003253a0b3b0b" + + "4913000019130103250b0b3a0b3b0500" + + "001a0d00032549133a0b3b05380b0000" + + "1b2e0103253a0b3b0b27193f19202101" + + "00001c2e01111b120640187a1903253a" + + "0b3b0b271949133f1900001d05000222" + + "03253a0b3b0b491300001e3400022203" + + "253a0b3b0b491300001f1d013113111b" + + "1206580b590b570b0000200500021831" + + "130000213400022231130000000f0400" + + "00050001080000000001000c00010800" + + "00000000000002057802000008000000" + + "0c00000002032f000000013803340000" + + "00043900000005490000000649000000" + + "064a0000000007044f00000008090459" + + "000000012d05035e0000000463000000" + + "05780000000649000000067c00000006" + + "7c000000000a0505080b840000000702" + + "1f0a0607080c0893000000000902a100" + + "0d2000040e09bc0000000005000e0cd5" + + "0000000006080e0de60000000007100e" + + "0ee60000000008180004c10000000fcd" + + "00000010d100000011000a0a0504110b" + + "080704da0000000fcd00000010d10000" + + "00800004cd0000000c0ff60000000011" + + "02a1010d20000c0e091f010000000d00" + + "0e0c30010000000e080e0d4401000000" + + "0f100e0e590100000010180004240100" + + "000fcd00000010d10000000900043501" + + "00000fcd00000012d100000000000100" + + "0004490100000f5501000010d1000000" + + "06000a100601045e0100000b66010000" + + "12021b0a1107040c1375010000001a02" + + "a1020d2000150e099e0100000016000e" + + "0caf0100000017080e0d590100000018" + + "100e0e590100000019180004a3010000" + + "0fcd00000010d1000000190004b40100" + + "000fcd00000013d10000000001000c14" + + "cc010000002102a1030d20001c0e091f" + + "010000001d000e0cf5010000001e080e" + + "0d44010000001f100e0e070200000020" + + "180004fa0100000fcd00000013d10000" + + "0000100004550100000c151702000000" + + "2802a1040d2000230e091f0100000024" + + "000e0c300100000025080e0d44010000" + + "0026100e0ee600000000271800021648" + + "020000014e034d020000045202000005" + + "780000000649000000064a000000064a" + + "000000067c0000000014660100001c04" + + "031919151700151801151902151a0315" + + "1b0400048b0200000a1d0801161e003d" + + "cd000000171f003de00200001821003e" + + "8602000018270040860200001820003f" + + "8602000018280047cd0000001829004d" + + "59010000182a005359010000182b0059" + + "5e010000182c005f5e0100000004e502" + + "00001926180324191a205e0100000325" + + "19001a215e010000032619041a225e01" + + "0000032719081a235e0100000329190c" + + "1a245e010000032a19101a255e010000" + + "032c1914001b2d002a171f002ae00200" + + "001821002b860200001827002d860200" + + "001820002c86020000182e0032e60000" + + "00182f0033cd000000001c0578020000" + + "015a300069cd0000001d001f0069e002" + + "00001e0121006b860200001e0227006d" + + "860200001e0320006c860200001e1131" + + "0077cd0000001f8f02000006d8010000" + + "0077182001569702000021049f020000" + + "2105a70200002106af0200002107b702" + + "00002108bf0200002109c7020000210a" + + "cf020000210bd70200001f2803000007" + + "c00000000065052001562c030000210c" + + "34030000210d3c030000210e44030000" + + "210f4c03000021105403000000000000" + + "cc000000050000000000000027000000" + + "31000000420000005600000067000000" + + "6c0000007f000000850000008e000000" + + "9300000097000000ab000000b7000000" + + "bb000000c1000000ce000000d3000000" + + "e0000000e6000000f300000000010000" + + "1101000025010000310100003a010000" + + "430100004a0100005701000062010000" + + "7001000084010000880100008d010000" + + "96010000a0010000b0010000bf010000" + + "ce010000d5010000d9010000e4010000" + + "f501000005020000110200001e020000" + + "320200003a0200003e02000047020000" + + "5562756e747520636c616e6720766572" + + "73696f6e2031342e302e302d31756275" + + "6e7475312e310064656661756c742e63" + + "002f7670726f78792f7072656275696c" + + "74006270665f6d61705f6c6f6f6b7570" + + "5f656c656d006270665f726564697265" + + "63745f6d6170006c6f6e6700756e7369" + + "676e6564206c6f6e67206c6f6e67005f" + + "5f7536340078736b735f6d6170007479" + + "706500696e74005f5f41525241595f53" + + "495a455f545950455f5f006d61785f65" + + "6e7472696573006b65790076616c7565" + + "006d616332706f72745f6d6170006368" + + "617200756e7369676e656420696e7400" + + "5f5f75333200706f7274326465765f6d" + "617000706173735f6d61635f6d617000" + "7372636d616332636f756e745f6d6170" + - "007864705f6d64006461746100646174" + + "006270665f6d61705f7570646174655f" + + "656c656d005844505f41424f52544544" + + "005844505f44524f50005844505f5041" + + "5353005844505f5458005844505f5245" + + "444952454354007864705f616374696f" + + "6e00756e7369676e6564206368617200" + + "72656469726563745f706b745f62795f" + + "6d616300637478006461746100646174" + "615f656e6400646174615f6d65746100" + "696e67726573735f6966696e64657800" + "72785f71756575655f696e6465780065" + - "67726573735f6966696e646578005f5f" + - "75333200756e7369676e656420696e74" + - "00637478007864705f736f636b007864" + - "70002f7670726f78792f707265627569" + - "6c742f64656661756c742e6300534543" + - "2822786470222920696e74207864705f" + - "736f636b28737472756374207864705f" + - "6d64202a637478290020202020756e73" + - "69676e656420636861722a2064617461" + - "5f656e64203d2028756e7369676e6564" + - "20636861722a292028286c6f6e672920" + - "6374782d3e646174615f656e64293b00" + - "20202020756e7369676e656420636861" + - "722a206461746120202020203d202875" + - "6e7369676e656420636861722a292028" + - "286c6f6e6729206374782d3e64617461" + - "293b0020202020706f73202b3d20363b" + - "002020202069662028706f73203e2064" + - "6174615f656e6429207b002020202069" + - "6e742a206f75747075745f6966616365" + - "5f707472203d206270665f6d61705f6c" + - "6f6f6b75705f656c656d28266d616332" + - "706f72745f6d61702c2064617461293b" + - "0020202020696620286f75747075745f" + - "69666163655f707472203d3d204e554c" + - "4c29207b0020202020696e74206f7574" + - "7075745f6966616365203d202a6f7574" + - "7075745f69666163655f7074723b0020" + - "202020696620286374782d3e696e6772" + - "6573735f6966696e646578203d3d206f" + - "75747075745f696661636529207b0020" + - "202020696620286270665f6d61705f6c" + - "6f6f6b75705f656c656d282670617373" + - "5f6d61635f6d61702c20646174612929" + + "67726573735f6966696e646578007864" + + "705f6d6400706f730065746865725f74" + + "797065006f75747075745f6966616365" + + "5f70747200696e7075745f6966616365" + + "5f70747200696e7075745f6966616365" + + "006f75747075745f696661636500706b" + + "745f636f756e745f62795f7372636d61" + + "6300636e745f70747200636e74007864" + + "705f736f636b0072656469726563745f" + + "72657300440000000500080000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000068000000" + + "0000000040010000000000009feb0100" + + "1800000000000000d4030000d4030000" + + "00060000000000000000000203000000" + + "01000000000000010400000020000001" + + "00000000000000030000000002000000" + + "04000000090000000500000000000001" + + "04000000200000000000000000000002" + + "06000000000000000000000300000000" + + "02000000040000000010000000000000" + + "00000002090000001900000000000001" + + "01000000080000010000000000000003" + + "00000000080000000400000006000000" + + "00000000000000020800000000000000" + + "04000004200000001e00000001000000" + + "00000000230000000500000040000000" + + "2f000000070000008000000033000000" + + "0a000000c0000000390000000000000e" + + "0b000000010000000000000000000002" + + "0e000000000000000000000300000000" + + "02000000040000001100000000000000" + + "00000002100000000000000000000003" + + "00000000020000000400000080000000" + + "00000000000000020200000000000000" + + "04000004200000001e0000000d000000" + + "00000000230000000f00000040000000" + + "2f000000110000008000000033000000" + + "11000000c0000000460000000000000e" + + "12000000010000000000000000000002" + + "15000000000000000000000300000000" + + "02000000040000000000010000000000" + + "00000002170000004f00000000000008" + + "18000000550000000000000104000000" + + "20000000000000000400000420000000" + + "1e000000010000000000000023000000" + + "14000000400000002f00000007000000" + + "800000003300000016000000c0000000" + + "620000000000000e1900000001000000" + + "00000000000000021c00000000000000" + + "00000003000000000200000004000000" + + "1900000000000000000000021e000000" + + "00000000000000030000000002000000" + + "04000000000100000000000004000004" + + "200000001e0000001b00000000000000" + + "230000001d000000400000002f000000" + + "16000000800000003300000016000000" + + "c00000006f0000000000000e1f000000" + + "01000000000000000400000420000000" + + "1e000000010000000000000023000000" + + "14000000400000002f00000007000000" + + "800000003300000011000000c0000000" + + "7c0000000000000e2100000001000000" + + "0000000000000002240000008d000000" + + "06000004180000009400000017000000" + + "00000000990000001700000020000000" + + "a20000001700000040000000ac000000" + + "1700000060000000bc00000017000000" + + "80000000cb00000017000000a0000000" + + "000000000100000d02000000da000000" + + "23000000de0000000100000c25000000" + + "fa0500000500000f000000000c000000" + + "00000000200000001300000000000000" + + "200000001a0000000000000020000000" + + "20000000000000002000000022000000" + + "000000002000000000696e74005f5f41" + + "525241595f53495a455f545950455f5f" + + "00636861720074797065006d61785f65" + + "6e7472696573006b65790076616c7565" + + "00706173735f6d61635f6d6170007873" + + "6b735f6d6170005f5f75333200756e73" + + "69676e656420696e74006d616332706f" + + "72745f6d617000706f7274326465765f" + + "6d6170007372636d616332636f756e74" + + "5f6d6170007864705f6d640064617461" + + "00646174615f656e6400646174615f6d" + + "65746100696e67726573735f6966696e" + + "6465780072785f71756575655f696e64" + + "6578006567726573735f6966696e6465" + + "7800637478007864705f736f636b0078" + + "6470002f7670726f78792f7072656275" + + "696c742f64656661756c742e63005345" + + "432822786470222920696e7420786470" + + "5f736f636b2873747275637420786470" + + "5f6d64202a637478290020202020756e" + + "7369676e656420636861722a20646174" + + "615f656e64203d2028756e7369676e65" + + "6420636861722a292028286c6f6e6729" + + "206374782d3e646174615f656e64293b" + + "0020202020756e7369676e6564206368" + + "61722a206461746120202020203d2028" + + "756e7369676e656420636861722a2920" + + "28286c6f6e6729206374782d3e646174" + + "61293b0020202020706f73202b3d2036" + + "3b002020202069662028706f73203e20" + + "646174615f656e6429207b0020202020" + + "696620286270665f6d61705f6c6f6f6b" + + "75705f656c656d2826706173735f6d61" + + "635f6d61702c20646174612929207b00" + + "20202020706f73202b3d2031343b202f" + + "2f206473745f6d6163202b207372635f" + + "6d6163202b2065746865725f74797065" + + "0020202020696e742065746865725f74" + + "797065203d202828646174615b31325d" + + "2026203078666629203c3c203829207c" + + "2028646174615b31335d202620307866" + + "66293b00202020206966202865746865" + + "725f74797065203d3d20307838313030" + + "29207b00202020205f5f7533322a206f" + + "75747075745f69666163655f70747220" + + "3d206270665f6d61705f6c6f6f6b7570" + + "5f656c656d28266d616332706f72745f" + + "6d61702c2064617461293b0020202020" + + "696620286f75747075745f6966616365" + + "5f707472203d3d204e554c4c29207b00" + + "202020205f5f7533322a20696e707574" + + "5f69666163655f707472203d20627066" + + "5f6d61705f6c6f6f6b75705f656c656d" + + "28266d616332706f72745f6d61702c20" + + "64617461202b2036293b002020202069" + + "662028696e7075745f69666163655f70" + + "7472203d3d204e554c4c29207b002020" + + "20205f5f75333220696e7075745f6966" + + "616365203d202a696e7075745f696661" + + "63655f7074723b002020202069662028" + + "6374782d3e696e67726573735f696669" + + "6e64657820213d20696e7075745f6966" + + "61636529207b00202020205f5f753332" + + "206f75747075745f6966616365203d20" + + "2a6f75747075745f69666163655f7074" + + "723b0020202020696620286374782d3e" + + "696e67726573735f6966696e64657820" + + "3d3d206f75747075745f696661636529" + "207b0020202020706f73202b3d203132" + "3b0020202020696e742a20636e745f70" + "7472203d206270665f6d61705f6c6f6f" + @@ -311,99 +380,112 @@ private Prebuilt() { "2a636e745f7074723b00202020202a63" + "6e745f707472203d20636e74202b2031" + "3b002020202072657475726e20627066" + - "5f7265646972656374286f7574707574" + - "5f69666163652c2030293b0020202020" + - "6966202872656469726563745f726573" + - "20213d205844505f44524f5020262620" + - "72656469726563745f72657320213d20" + - "5844505f41424f5254454429207b0020" + - "20202072657475726e206270665f7265" + - "6469726563745f6d6170282678736b73" + - "5f6d61702c206374782d3e72785f7175" + - "6575655f696e6465782c205844505f44" + - "524f50293b007d002e6d617073000000" + - "9feb0100200000000000000014000000" + - "140000002c0200004002000000000000" + - "08000000da0000000100000000000000" + - "1d00000010000000da00000022000000" + - "00000000de000000f900000000340100" + - "08000000de000000250100003dd80000" + - "10000000de0000006c0100003ddc0000" + - "18000000de000000af01000009e40000" + - "28000000de000000bd01000009e80000" + - "30000000de000000d70100001df40000" + - "50000000de0000001d02000009f80000" + - "58000000de0000004102000018040100" + - "60000000de0000006b0200000e080100" + - "68000000de0000006b02000009080100" + - "70000000de0000009b02000009140100" + - "a0000000de0000009b02000009140100" + - "a8000000de000000250100003d8c0000" + - "b0000000de0000006c0100003d900000" + - "b8000000de000000cf02000009980000" + - "c8000000de000000bd010000099c0000" + - "d0000000de000000de02000040a80000" + - "d8000000de000000de02000014a80000" + - "f8000000de0000002303000009b00000" + - "08010000de0000003e0300000db40000" + - "18010000de0000000000000000000000" + - "20010000de0000004f03000009b80000" + - "50010000de000000920300000bc40000" + - "58010000de000000a603000014c80000" + - "60010000de000000a60300000ec80000" + - "68010000de000000be0300000c280100" + - "98010000de000000e803000022400100" + - "a8010000de000000250100003d500100" + - "b0010000de0000006c0100003d540100" + - "b8010000de000000af010000095c0100" + - "c0010000de000000bd01000009600100" + - "c8010000de0000002b0400002d6c0100" + - "d0010000de0000002b0400000c6c0100" + - "f0010000de0000007204000001700100" + - "0c000000ffffffff04000800087c0b00" + - "14000000000000000000000000000000" + - "f8010000000000001f01000005000800" + - "82000000080101fb0e0d000101010100" + - "00000100000101011f04000000001100" + - "00002a0000006600000003011f020f05" + - "1e049c00000000fd1da420a38fa7edb1" + - "822d5ff10cf378a600000001b810f270" + - "733e106319b67ef512c6246eb1000000" + - "0265e4dc8e3121f91a5c2c9eb8563c56" + - "92c3000000034c85315b3b2730faad72" + - "401394cb73e504000009020000000000" + - "00000003cd0001053d0a036820210509" + - "222f051d2305094b051823050e210509" + - "062006230666053d06035e2021050922" + - "2f054023051406200509064c06035420" + - "050d06032d2006035320050906032e2e" + - "06035258050b06033120051421050e06" + - "20050c0603182005226c0603b07f2005" + - "3d0603d400202105092221052d23050c" + - "06200501064b02010001012f7670726f" + - "78792f7072656275696c74002f757372" + - "2f696e636c7564652f61736d2d67656e" + - "65726963002e2e2f7375626d6f64756c" + - "65732f7864702d746f6f6c732f6c6962" + - "2f6c69626270662f7372632f726f6f74" + - "2f7573722f696e636c7564652f627066" + - "002e2e2f7375626d6f64756c65732f78" + - "64702d746f6f6c732f6c69622f6c6962" + - "6270662f696e636c7564652f75617069" + - "2f6c696e75780064656661756c742e63" + - "00696e742d6c6c36342e68006270665f" + - "68656c7065725f646566732e68006270" + - "662e6800000000000000000000000000" + + "5f72656469726563745f6d6170282670" + + "6f7274326465765f6d61702c206f7574" + + "7075745f69666163652c205844505f44" + + "524f50293b0020202020696620287265" + + "6469726563745f72657320213d205844" + + "505f44524f5020262620726564697265" + + "63745f72657320213d205844505f4142" + + "4f5254454429207b0020202020726574" + + "75726e206270665f7265646972656374" + + "5f6d6170282678736b735f6d61702c20" + + "6374782d3e72785f71756575655f696e" + + "6465782c205844505f44524f50293b00" + + "7d002e6d617073009feb010020000000" + + "000000001400000014000000cc020000" + + "e00200000000000008000000e7000000" + + "01000000000000002600000010000000" + + "e70000002c00000000000000eb000000" + + "0601000000a4010010000000eb000000" + + "320100003dac010018000000eb000000" + + "790100003db0010020000000eb000000" + + "bc01000009b8010030000000eb000000" + + "ca01000009bc010038000000eb000000" + + "e401000009cc010060000000eb000000" + + "e401000009cc010068000000eb000000" + + "320100003df8000070000000eb000000" + + "790100003dfc000078000000eb000000" + + "180200000904010088000000eb000000" + + "ca0100000908010090000000eb000000" + + "49020000321c010098000000eb000000" + + "49020000181c0100a0000000eb000000" + + "49020000291c0100a8000000eb000000" + + "490200002f1c0100b0000000eb000000" + + "8c02000009200100b8000000eb000000" + + "ac0200001f340100e0000000eb000000" + + "f402000009380100e8000000eb000000" + + "18030000464c0100f0000000eb000000" + + "180300001e4c010010010000eb000000" + + "630300000950010018010000eb000000" + + "860300001964010020010000eb000000" + + "b00300000e68010028010000eb000000" + + "b00300000968010030010000eb000000" + + "df0300001a7c010038010000eb000000" + + "0b0400000980010040010000eb000000" + + "320100003dac000048010000eb000000" + + "790100003db0000050010000eb000000" + + "3b04000009b8000060010000eb000000" + + "ca01000009bc000068010000eb000000" + + "4a04000040c8000070010000eb000000" + + "4a04000014c8000090010000eb000000" + + "8f04000009d00000a0010000eb000000" + + "aa0400000dd40000b0010000eb000000" + + "0000000000000000b8010000eb000000" + + "bb04000009d80000e8010000eb000000" + + "fe0400000be40000f0010000eb000000" + + "1205000014e80000f8010000eb000000" + + "120500000ee8000000020000eb000000" + + "2a0500000c98010040020000eb000000" + + "6e05000022e0010048020000eb000000" + + "b10500002df0010050020000eb000000" + + "b10500000cf0010070020000eb000000" + + "f805000001f401000c000000ffffffff" + + "04000800087c0b001400000000000000" + + "00000000000000007802000000000000" + + "3a0100000500080082000000080101fb" + + "0e0d0001010101000000010000010101" + + "1f0400000000110000004d0000006600" + + "000003011f020f051e049c000000001d" + + "eeabbd89490a514ac511d461dea744a6" + + "0000000165e4dc8e3121f91a5c2c9eb8" + + "563c5692b800000002b810f270733e10" + + "6319b67ef512c6246ec3000000034c85" + + "315b3b2730faad72401394cb73e50400" + + "000902000000000000000003e9000105" + + "3d0a2f210509222f240658053d06034b" + + "20210509222f05322505180620052920" + + "052f2005090621051f25050959054625" + + "051e06200509064b051925050e210509" + + "0620051a0625050921053d034b202105" + + "09222f054023051406200509064c0603" + + "4c20050d0603352006034b2005090603" + + "362e06034a58050b0603392005142105" + + "0e0620050c06032c200522031282052d" + + "24050c06200501064b02010001012f76" + + "70726f78792f7072656275696c74002e" + + "2e2f7375626d6f64756c65732f786470" + + "2d746f6f6c732f6c69622f6c69626270" + + "662f7372632f726f6f742f7573722f69" + + "6e636c7564652f627066002f7573722f" + + "696e636c7564652f61736d2d67656e65" + + "726963002e2e2f7375626d6f64756c65" + + "732f7864702d746f6f6c732f6c69622f" + + "6c69626270662f696e636c7564652f75" + + "6170692f6c696e75780064656661756c" + + "742e63006270665f68656c7065725f64" + + "6566732e6800696e742d6c6c36342e68" + + "006270662e6800000000000000000000" + "00000000000000000000000000000000" + - "f00000000400f1ff0000000000000000" + + "fd0000000400f1ff0000000000000000" + "00000000000000000000000003000300" + "00000000000000000000000000000000" + - "1301000000000300a001000000000000" + + "20010000000003007002000000000000" + "00000000000000002801000000000300" + - "f0010000000000000000000000000000" + - "1a010000000003006801000000000000" + - "00000000000000002101000000000300" + - "50010000000000000000000000000000" + + "48020000000000000000000000000000" + + "30010000000003000002000000000000" + + "00000000000000003801000000000300" + + "e8010000000000000000000000000000" + "00000000030006000000000000000000" + "00000000000000000000000003000700" + "00000000000000000000000000000000" + @@ -416,245 +498,266 @@ private Prebuilt() { "00000000030015000000000000000000" + "00000000000000000000000003001700" + "00000000000000000000000000000000" + - "c6000000120003000000000000000000" + - "f8010000000000008200000011000500" + + "d3000000120003000000000000000000" + + "7802000000000000b600000011000500" + + "00000000000000002000000000000000" + + "8f000000110005004000000000000000" + + "20000000000000009c00000011000500" + + "80000000000000002000000000000000" + + "82000000110005006000000000000000" + + "2000000000000000ad00000011000500" + "20000000000000002000000000000000" + - "a9000000110005004000000000000000" + - "20000000000000008f00000011000500" + - "60000000000000002000000000000000" + - "a0000000110005000000000000000000" + - "20000000000000003000000000000000" + - "01000000100000007000000000000000" + - "0100000011000000d800000000000000" + - "01000000120000002001000000000000" + - "0100000012000000d001000000000000" + - "01000000130000000800000000000000" + - "03000000080000001100000000000000" + - "03000000090000001500000000000000" + - "030000000d0000001f00000000000000" + - "030000000b0000002300000000000000" + - "03000000070000000800000000000000" + - "030000000a0000000c00000000000000" + - "030000000a0000001000000000000000" + - "030000000a0000001400000000000000" + - "030000000a0000001800000000000000" + - "030000000a0000001c00000000000000" + - "030000000a0000002000000000000000" + - "030000000a0000002400000000000000" + - "030000000a0000002800000000000000" + - "030000000a0000002c00000000000000" + - "030000000a0000003000000000000000" + - "030000000a0000003400000000000000" + - "030000000a0000003800000000000000" + - "030000000a0000003c00000000000000" + - "030000000a0000004000000000000000" + - "030000000a0000004400000000000000" + - "030000000a0000004800000000000000" + - "030000000a0000004c00000000000000" + - "030000000a0000005000000000000000" + - "030000000a0000005400000000000000" + - "030000000a0000005800000000000000" + - "030000000a0000005c00000000000000" + - "030000000a0000006000000000000000" + - "030000000a0000006400000000000000" + - "030000000a0000006800000000000000" + - "030000000a0000006c00000000000000" + - "030000000a0000007000000000000000" + - "030000000a0000007400000000000000" + - "030000000a0000007800000000000000" + - "030000000a0000007c00000000000000" + - "030000000a0000008000000000000000" + - "030000000a0000008400000000000000" + - "030000000a0000008800000000000000" + - "030000000a0000008c00000000000000" + - "030000000a0000009000000000000000" + - "030000000a0000009400000000000000" + - "030000000a0000009800000000000000" + - "030000000a0000009c00000000000000" + - "030000000a000000a000000000000000" + - "030000000a000000a400000000000000" + - "030000000a000000a800000000000000" + - "030000000a000000ac00000000000000" + - "030000000a000000b000000000000000" + - "030000000a000000b400000000000000" + - "030000000a000000b800000000000000" + - "030000000a000000bc00000000000000" + - "030000000a000000c000000000000000" + - "030000000a0000000800000000000000" + - "02000000130000001000000000000000" + - "02000000100000001800000000000000" + - "02000000110000002000000000000000" + - "02000000120000002800000000000000" + - "02000000020000003000000000000000" + - "02000000020000003800000000000000" + - "0200000002000000f002000000000000" + - "0400000013000000fc02000000000000" + - "04000000100000000803000000000000" + - "04000000110000001403000000000000" + - "04000000120000002c00000000000000" + - "04000000020000004000000000000000" + - "04000000020000005000000000000000" + - "04000000020000006000000000000000" + - "04000000020000007000000000000000" + - "04000000020000008000000000000000" + - "04000000020000009000000000000000" + - "0400000002000000a000000000000000" + - "0400000002000000b000000000000000" + - "0400000002000000c000000000000000" + - "0400000002000000d000000000000000" + - "0400000002000000e000000000000000" + - "0400000002000000f000000000000000" + - "04000000020000000001000000000000" + - "04000000020000001001000000000000" + - "04000000020000002001000000000000" + - "04000000020000003001000000000000" + - "04000000020000004001000000000000" + - "04000000020000005001000000000000" + - "04000000020000006001000000000000" + - "04000000020000007001000000000000" + - "04000000020000008001000000000000" + - "04000000020000009001000000000000" + - "0400000002000000a001000000000000" + - "0400000002000000b001000000000000" + - "0400000002000000c001000000000000" + - "0400000002000000d001000000000000" + - "0400000002000000e001000000000000" + - "0400000002000000f001000000000000" + - "04000000020000000002000000000000" + - "04000000020000001002000000000000" + - "04000000020000002002000000000000" + - "04000000020000003002000000000000" + - "04000000020000004002000000000000" + - "04000000020000005002000000000000" + - "04000000020000001400000000000000" + - "030000000c0000001800000000000000" + - "02000000020000002200000000000000" + - "030000000e0000002600000000000000" + - "030000000e0000002a00000000000000" + - "030000000e0000002e00000000000000" + - "030000000e0000003a00000000000000" + - "030000000e0000004f00000000000000" + - "030000000e0000006400000000000000" + - "030000000e0000007900000000000000" + - "030000000e0000009300000000000000" + - "0200000002000000002e64656275675f" + - "616262726576002e74657874002e7265" + - "6c2e4254462e657874002e6465627567" + - "5f6c6f636c69737473002e72656c2e64" + - "656275675f7374725f6f666673657473" + - "002e6d617073002e64656275675f7374" + - "72002e64656275675f6c696e655f7374" + - "72002e72656c2e64656275675f616464" + - "72002e72656c786470006d616332706f" + - "72745f6d6170007372636d616332636f" + - "756e745f6d61700078736b735f6d6170" + - "00706173735f6d61635f6d6170002e72" + - "656c2e64656275675f696e666f007864" + - "705f736f636b002e72656c2e64656275" + - "675f6c696e65002e72656c2e64656275" + - "675f6672616d650064656661756c742e" + - "63002e737472746162002e73796d7461" + - "62002e72656c2e425446004c4242305f" + - "39004c4242305f38004c4242305f3700" + - "4c4242305f3131000000000000000000" + - "00000000000000000000000000000000" + - "0000000000000000fa00000003000000" + + "38000000000000000100000010000000" + + "b8000000000000000100000011000000" + + "f0000000000000000100000011000000" + + "70010000000000000100000012000000" + + "b8010000000000000100000012000000" + + "00020000000000000100000013000000" + + "50020000000000000100000014000000" + + "08000000000000000300000008000000" + + "11000000000000000300000009000000" + + "1500000000000000030000000d000000" + + "1f00000000000000030000000b000000" + + "23000000000000000300000007000000" + + "0800000000000000030000000a000000" + + "0c00000000000000030000000a000000" + + "1000000000000000030000000a000000" + + "1400000000000000030000000a000000" + + "1800000000000000030000000a000000" + + "1c00000000000000030000000a000000" + + "2000000000000000030000000a000000" + + "2400000000000000030000000a000000" + + "2800000000000000030000000a000000" + + "2c00000000000000030000000a000000" + + "3000000000000000030000000a000000" + + "3400000000000000030000000a000000" + + "3800000000000000030000000a000000" + + "3c00000000000000030000000a000000" + + "4000000000000000030000000a000000" + + "4400000000000000030000000a000000" + + "4800000000000000030000000a000000" + + "4c00000000000000030000000a000000" + + "5000000000000000030000000a000000" + + "5400000000000000030000000a000000" + + "5800000000000000030000000a000000" + + "5c00000000000000030000000a000000" + + "6000000000000000030000000a000000" + + "6400000000000000030000000a000000" + + "6800000000000000030000000a000000" + + "6c00000000000000030000000a000000" + + "7000000000000000030000000a000000" + + "7400000000000000030000000a000000" + + "7800000000000000030000000a000000" + + "7c00000000000000030000000a000000" + + "8000000000000000030000000a000000" + + "8400000000000000030000000a000000" + + "8800000000000000030000000a000000" + + "8c00000000000000030000000a000000" + + "9000000000000000030000000a000000" + + "9400000000000000030000000a000000" + + "9800000000000000030000000a000000" + + "9c00000000000000030000000a000000" + + "a000000000000000030000000a000000" + + "a400000000000000030000000a000000" + + "a800000000000000030000000a000000" + + "ac00000000000000030000000a000000" + + "b000000000000000030000000a000000" + + "b400000000000000030000000a000000" + + "b800000000000000030000000a000000" + + "bc00000000000000030000000a000000" + + "c000000000000000030000000a000000" + + "c400000000000000030000000a000000" + + "c800000000000000030000000a000000" + + "cc00000000000000030000000a000000" + + "08000000000000000200000014000000" + + "10000000000000000200000011000000" + + "18000000000000000200000013000000" + + "20000000000000000200000010000000" + + "28000000000000000200000012000000" + + "30000000000000000200000002000000" + + "38000000000000000200000002000000" + + "40000000000000000200000002000000" + + "b4030000000000000400000010000000" + + "c0030000000000000400000014000000" + + "cc030000000000000400000011000000" + + "d8030000000000000400000013000000" + + "e4030000000000000400000012000000" + + "2c000000000000000400000002000000" + + "40000000000000000400000002000000" + + "50000000000000000400000002000000" + + "60000000000000000400000002000000" + + "70000000000000000400000002000000" + + "80000000000000000400000002000000" + + "90000000000000000400000002000000" + + "a0000000000000000400000002000000" + + "b0000000000000000400000002000000" + + "c0000000000000000400000002000000" + + "d0000000000000000400000002000000" + + "e0000000000000000400000002000000" + + "f0000000000000000400000002000000" + + "00010000000000000400000002000000" + + "10010000000000000400000002000000" + + "20010000000000000400000002000000" + + "30010000000000000400000002000000" + + "40010000000000000400000002000000" + + "50010000000000000400000002000000" + + "60010000000000000400000002000000" + + "70010000000000000400000002000000" + + "80010000000000000400000002000000" + + "90010000000000000400000002000000" + + "a0010000000000000400000002000000" + + "b0010000000000000400000002000000" + + "c0010000000000000400000002000000" + + "d0010000000000000400000002000000" + + "e0010000000000000400000002000000" + + "f0010000000000000400000002000000" + + "00020000000000000400000002000000" + + "10020000000000000400000002000000" + + "20020000000000000400000002000000" + + "30020000000000000400000002000000" + + "40020000000000000400000002000000" + + "50020000000000000400000002000000" + + "60020000000000000400000002000000" + + "70020000000000000400000002000000" + + "80020000000000000400000002000000" + + "90020000000000000400000002000000" + + "a0020000000000000400000002000000" + + "b0020000000000000400000002000000" + + "c0020000000000000400000002000000" + + "d0020000000000000400000002000000" + + "e0020000000000000400000002000000" + + "f0020000000000000400000002000000" + + "1400000000000000030000000c000000" + + "18000000000000000200000002000000" + + "2200000000000000030000000e000000" + + "2600000000000000030000000e000000" + + "2a00000000000000030000000e000000" + + "2e00000000000000030000000e000000" + + "3a00000000000000030000000e000000" + + "4f00000000000000030000000e000000" + + "6400000000000000030000000e000000" + + "7900000000000000030000000e000000" + + "93000000000000000200000002000000" + + "002e64656275675f616262726576002e" + + "74657874002e72656c2e4254462e6578" + + "74002e64656275675f6c6f636c697374" + + "73002e72656c2e64656275675f737472" + + "5f6f666673657473002e6d617073002e" + + "64656275675f737472002e6465627567" + + "5f6c696e655f737472002e72656c2e64" + + "656275675f61646472002e72656c7864" + + "7000706f7274326465765f6d6170006d" + + "616332706f72745f6d6170007372636d" + + "616332636f756e745f6d61700078736b" + + "735f6d617000706173735f6d61635f6d" + + "6170002e72656c2e64656275675f696e" + + "666f007864705f736f636b002e72656c" + + "2e64656275675f6c696e65002e72656c" + + "2e64656275675f6672616d6500646566" + + "61756c742e63002e737472746162002e" + + "73796d746162002e72656c2e42544600" + + "4c4242305f3134004c4242305f313300" + + "4c4242305f3132004c4242305f313100" + "00000000000000000000000000000000" + - "08210000000000003001000000000000" + - "00000000000000000100000000000000" + - "00000000000000000f00000001000000" + - "06000000000000000000000000000000" + - "40000000000000000000000000000000" + - "00000000000000000400000000000000" + - "00000000000000007e00000001000000" + - "06000000000000000000000000000000" + - "4000000000000000f801000000000000" + - "00000000000000000800000000000000" + - "00000000000000007a00000009000000" + - "40000000000000000000000000000000" + - "e8190000000000005000000000000000" + - "18000000030000000800000000000000" + - "10000000000000004900000001000000" + - "03000000000000000000000000000000" + - "38020000000000008000000000000000" + - "00000000000000000800000000000000" + - "00000000000000002200000001000000" + "00000000000000000000000000000000" + - "b802000000000000e100000000000000" + - "00000000000000000100000000000000" + - "00000000000000000100000001000000" + "00000000000000000000000000000000" + - "99030000000000009201000000000000" + - "00000000000000000100000000000000" + - "0000000000000000ba00000001000000" + "00000000000000000000000000000000" + - "2b050000000000009c03000000000000" + - "00000000000000000100000000000000" + - "0000000000000000b600000009000000" + - "40000000000000000000000000000000" + - "381a0000000000005000000000000000" + - "18000000080000000800000000000000" + - "10000000000000003600000001000000" + + "07010000030000000000000000000000" + + "0000000000000000c026000000000000" + + "40010000000000000000000000000000" + + "01000000000000000000000000000000" + + "0f000000010000000600000000000000" + + "00000000000000004000000000000000" + "00000000000000000000000000000000" + - "c708000000000000c400000000000000" + - "00000000000000000100000000000000" + - "00000000000000003200000009000000" + - "40000000000000000000000000000000" + - "881a000000000000f002000000000000" + - "180000000a0000000800000000000000" + - "10000000000000004f00000001000000" + - "30000000000000000000000000000000" + - "8b090000000000002d02000000000000" + - "00000000000000000100000000000000" + - "01000000000000006e00000001000000" + - "00000000000000000000000000000000" + - "b80b0000000000004000000000000000" + - "00000000000000000100000000000000" + - "00000000000000006a00000009000000" + - "40000000000000000000000000000000" + - "781d0000000000007000000000000000" + - "180000000d0000000800000000000000" + - "10000000000000000e01000001000000" + - "00000000000000000000000000000000" + - "f80b0000000000009607000000000000" + - "00000000000000000400000000000000" + - "00000000000000000a01000009000000" + - "40000000000000000000000000000000" + - "e81d0000000000004000000000000000" + - "180000000f0000000800000000000000" + - "10000000000000001900000001000000" + - "00000000000000000000000000000000" + - "90130000000000006002000000000000" + - "00000000000000000400000000000000" + - "00000000000000001500000009000000" + - "40000000000000000000000000000000" + - "281e0000000000003002000000000000" + - "18000000110000000800000000000000" + - "1000000000000000e300000001000000" + - "00000000000000000000000000000000" + - "f0150000000000002800000000000000" + - "00000000000000000800000000000000" + - "0000000000000000df00000009000000" + - "40000000000000000000000000000000" + - "58200000000000002000000000000000" + - "18000000130000000800000000000000" + - "1000000000000000d300000001000000" + - "00000000000000000000000000000000" + - "18160000000000002301000000000000" + - "00000000000000000100000000000000" + - "0000000000000000cf00000009000000" + - "40000000000000000000000000000000" + - "78200000000000009000000000000000" + - "18000000150000000800000000000000" + - "10000000000000005a00000001000000" + - "30000000000000000000000000000000" + - "3b17000000000000c900000000000000" + - "00000000000000000100000000000000" + - "01000000000000000201000002000000" + - "00000000000000000000000000000000" + - "0818000000000000e001000000000000" + - "010000000f0000000800000000000000" + - "1800000000000000").persist(); + "04000000000000000000000000000000" + + "7e000000010000000600000000000000" + + "00000000000000004000000000000000" + + "78020000000000000000000000000000" + + "08000000000000000000000000000000" + + "7a000000090000004000000000000000" + + "0000000000000000901e000000000000" + + "70000000000000001800000003000000" + + "08000000000000001000000000000000" + + "49000000010000000300000000000000" + + "0000000000000000b802000000000000" + + "a0000000000000000000000000000000" + + "08000000000000000000000000000000" + + "22000000010000000000000000000000" + + "00000000000000005803000000000000" + + "0a010000000000000000000000000000" + + "01000000000000000000000000000000" + + "01000000010000000000000000000000" + + "00000000000000006204000000000000" + + "9b010000000000000000000000000000" + + "01000000000000000000000000000000" + + "c7000000010000000000000000000000" + + "0000000000000000fd05000000000000" + + "13040000000000000000000000000000" + + "01000000000000000000000000000000" + + "c3000000090000004000000000000000" + + "0000000000000000001f000000000000" + + "50000000000000001800000008000000" + + "08000000000000001000000000000000" + + "36000000010000000000000000000000" + + "0000000000000000100a000000000000" + + "d0000000000000000000000000000000" + + "01000000000000000000000000000000" + + "32000000090000004000000000000000" + + "0000000000000000501f000000000000" + + "2003000000000000180000000a000000" + + "08000000000000001000000000000000" + + "4f000000010000003000000000000000" + + "0000000000000000e00a000000000000" + + "54020000000000000000000000000000" + + "01000000000000000100000000000000" + + "6e000000010000000000000000000000" + + "0000000000000000340d000000000000" + + "48000000000000000000000000000000" + + "01000000000000000000000000000000" + + "6a000000090000004000000000000000" + + "00000000000000007022000000000000" + + "8000000000000000180000000d000000" + + "08000000000000001000000000000000" + + "1b010000010000000000000000000000" + + "00000000000000007c0d000000000000" + + "ec090000000000000000000000000000" + + "04000000000000000000000000000000" + + "17010000090000004000000000000000" + + "0000000000000000f022000000000000" + + "5000000000000000180000000f000000" + + "08000000000000001000000000000000" + + "19000000010000000000000000000000" + + "00000000000000006817000000000000" + + "00030000000000000000000000000000" + + "04000000000000000000000000000000" + + "15000000090000004000000000000000" + + "00000000000000004023000000000000" + + "d0020000000000001800000011000000" + + "08000000000000001000000000000000" + + "f0000000010000000000000000000000" + + "0000000000000000681a000000000000" + + "28000000000000000000000000000000" + + "08000000000000000000000000000000" + + "ec000000090000004000000000000000" + + "00000000000000001026000000000000" + + "20000000000000001800000013000000" + + "08000000000000001000000000000000" + + "e0000000010000000000000000000000" + + "0000000000000000901a000000000000" + + "3e010000000000000000000000000000" + + "01000000000000000000000000000000" + + "dc000000090000004000000000000000" + + "00000000000000003026000000000000" + + "90000000000000001800000015000000" + + "08000000000000001000000000000000" + + "5a000000010000003000000000000000" + + "0000000000000000ce1b000000000000" + + "c9000000000000000000000000000000" + + "01000000000000000100000000000000" + + "0f010000020000000000000000000000" + + "0000000000000000981c000000000000" + + "f801000000000000010000000f000000" + + "08000000000000001800000000000000").persist(); private static final ByteArray _HANDLE_DST_PORT_EBPF_OBJECT = ByteArray.from( "7f454c46020101000000000000000000" + @@ -697,6 +800,8 @@ private Prebuilt() { "bf06000000000000bf60000000000000" + "95000000000000000000000000000000" + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + "0000000000000000d700000005000800" + "0900000024000000300000003e000000" + "6500000073000000870000009b000000" + @@ -1173,6 +1278,8 @@ private Prebuilt() { "42305f3135004c4242305f3133004c42" + "42305f31300000000000000000000000" + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + "0000000000000000de00000003000000" + "00000000000000000000000000000000" + "281f0000000000001e01000000000000" + @@ -1273,7 +1380,7 @@ private Prebuilt() { /** * default.c - * md5sum(default.o): cae0a2a6adcba86a49aeeba164ecdcda + * md5sum(default.o): 8df266ca0ed22071d5cb8cacaa1d04ec */ public static final ByteArray DEFAULT_PROG = _DEFAULT_PROG; /** diff --git a/base/src/main/java/io/vproxy/xdp/SharedBPFMapHolder.java b/base/src/main/java/io/vproxy/xdp/SharedBPFMapHolder.java index ccad2f0d..4a63555a 100644 --- a/base/src/main/java/io/vproxy/xdp/SharedBPFMapHolder.java +++ b/base/src/main/java/io/vproxy/xdp/SharedBPFMapHolder.java @@ -1,7 +1,5 @@ package io.vproxy.xdp; -import io.vproxy.base.util.coll.Tuple; - import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -17,25 +15,29 @@ public static SharedBPFMapHolder getInstance() { private SharedBPFMapHolder() { } - private record Storage(BPFObject bpfObject, BPFMap bpfMap, AtomicInteger refCount) { + private record Storage(BPFObjectAndMapProviderResultTuple tup, AtomicInteger refCount) { + } + + public record BPFObjectAndMapProviderResultTuple(BPFObject object, BPFMap mac2portMap, BPFMap devMap) { } private final Map bpfMaps = new HashMap<>(); public interface BPFObjAndMapProvider { - Tuple get() throws IOException; + BPFObjectAndMapProviderResultTuple get() throws IOException; } - public synchronized BPFMap getOrCreate(String mapGroup, BPFObjAndMapProvider f) throws IOException { + public synchronized BPFObjectAndMapProviderResultTuple + getOrCreate(String mapGroup, BPFObjAndMapProvider f) throws IOException { if (bpfMaps.containsKey(mapGroup)) { var storage = bpfMaps.get(mapGroup); storage.refCount.incrementAndGet(); - return storage.bpfMap; + return storage.tup; } var tup = f.get(); - var storage = new Storage(tup._1, tup._2, new AtomicInteger(1)); + var storage = new Storage(tup, new AtomicInteger(1)); bpfMaps.put(mapGroup, storage); - return tup._2; + return tup; } public synchronized void release(String mapGroup) { @@ -45,7 +47,7 @@ public synchronized void release(String mapGroup) { } if (s.refCount.decrementAndGet() == 0) { bpfMaps.remove(mapGroup); - s.bpfObject.release(false); + s.tup.object.release(false); } } } diff --git a/build.gradle b/build.gradle index 66678215..4c67a018 100644 --- a/build.gradle +++ b/build.gradle @@ -551,6 +551,18 @@ project(':test') { "submodules/vpxdp/submodules/xdp-tools/lib/libxdp") systemProperty("vfd", "posix") main = "io.vproxy.poc.XDPPoc" + def ifname = System.getProperty("ifname") + def offload = System.getProperty("offload") + doLast { + if (ifname == null) { + throw new Exception("You must specify -Difname={...}") + } + var ls = [ifname] + if (offload != null) { + ls.add(offload) + } + args = ls + } } task QuicPoc(type: JavaExec) { diff --git a/core/src/main/java/io/vproxy/vswitch/MacTable.java b/core/src/main/java/io/vproxy/vswitch/MacTable.java index afa899b2..b7423a09 100644 --- a/core/src/main/java/io/vproxy/vswitch/MacTable.java +++ b/core/src/main/java/io/vproxy/vswitch/MacTable.java @@ -129,7 +129,7 @@ void record() { // the mac is already registered on another iface // remove that iface MacEntry entry = macMap.get(mac); - entry.cancel(); + entry.cancel(false); } entries.add(this); macMap.put(mac, this); @@ -148,12 +148,15 @@ void record() { } private void tryOffload() { - if (!(iface instanceof XDPIface xdpIface) || !xdpIface.params.offload()) { + if (!(iface instanceof XDPIface xdpIface) || !xdpIface.params.pktswOffloaded()) { return; } if (xdpIface.params.bpf().mac2port() == null) { return; } + if (xdpIface.params.bpf().port2dev() == null) { + return; + } if (xdpIface.params.bpf().srcmac2count() == null) { return; } @@ -168,10 +171,10 @@ private void tryOffload() { } var mac2portMap = xdpIface.params.bpf().mac2port(); - if (mac2portMap == null) { - return; - } + var port2devMap = xdpIface.params.bpf().port2dev(); try { + port2devMap.putNetif(xdpIface.nic); + // first add port2dev map, then add mac2port map, so that the dev would be valid mac2portMap.putNetif(mac, xdpIface.nic); Logger.trace(LogType.ALERT, "mac entry " + iface.name() + " -> " + mac + " recorded into xdp offload mac map"); } catch (IOException e) { @@ -183,9 +186,13 @@ private void tryOffload() { @Override public void cancel() { + cancel(true); + } + + public void cancel(boolean isTimeout) { super.cancel(); - if (offloaded) { + if (isTimeout && offloaded) { if (hasOffloadedPacketPassed()) { start(); return; @@ -208,13 +215,18 @@ public void cancel() { } private boolean hasOffloadedPacketPassed() { - assert iface instanceof XDPIface; - assert ((XDPIface) iface).params.bpf().srcmac2count() != null; + if (!(iface instanceof XDPIface xdpIface)) { + return false; + } + if (xdpIface.params.bpf().srcmac2count() == null) { + return false; + } try { - int n = ((XDPIface) iface).params.bpf().srcmac2count().getInt(mac); + int n = xdpIface.params.bpf().srcmac2count().getInt(mac); assert Logger.lowLevelDebug("fetched packet count from xdp offload map: " + n + ", last recorded: " + offloadedCount); if (n != offloadedCount) { + assert Logger.lowLevelDebug("mac entry " + iface.name() + " -> " + mac + " has packets passed, old: " + offloadedCount + ", new: " + n); offloadedCount = n; return true; } @@ -243,7 +255,7 @@ private void clearOffload() { mac2portMap.remove(mac); Logger.trace(LogType.ALERT, "mac entry removed from xdp offload mac map: " + iface.name() + " -> " + mac); } catch (IOException e) { - Logger.error(LogType.SYS_ERROR, "failed to removed mac from xdp offload mac map: " + iface.name() + " -> " + mac); + Logger.error(LogType.SYS_ERROR, "failed to removed mac from xdp offload mac map: " + iface.name() + " -> " + mac, e); } } @@ -252,6 +264,7 @@ public void resetTimer() { if (getTimeout() == -1) { return; } + hasOffloadedPacketPassed(); // will update offloadedCount field super.resetTimer(); } @@ -259,13 +272,17 @@ public boolean isOffloaded() { return offloaded; } + public int getOffloadedCount() { + return offloadedCount; + } + @Override public String toString() { return "MacEntry{" + - "mac=" + mac + - ", iface=" + iface.name() + - ", offloaded=" + offloaded + - '}'; + "mac=" + mac + + ", iface=" + iface.name() + + ", offloaded=" + offloaded + "(" + offloadedCount + ")" + + '}'; } } diff --git a/core/src/main/java/io/vproxy/vswitch/iface/XDPIface.java b/core/src/main/java/io/vproxy/vswitch/iface/XDPIface.java index 1be78f9e..bcbc152a 100644 --- a/core/src/main/java/io/vproxy/vswitch/iface/XDPIface.java +++ b/core/src/main/java/io/vproxy/vswitch/iface/XDPIface.java @@ -4,7 +4,6 @@ import io.vproxy.base.selector.HandlerContext; import io.vproxy.base.selector.SelectorEventLoop; import io.vproxy.base.util.ByteArray; -import io.vproxy.base.util.Consts; import io.vproxy.base.util.LogType; import io.vproxy.base.util.Logger; import io.vproxy.base.util.thread.VProxyThread; @@ -21,6 +20,7 @@ import java.io.IOException; import java.lang.foreign.MemorySegment; +import java.util.ArrayList; public class XDPIface extends Iface { public final String nic; @@ -35,22 +35,23 @@ public class XDPIface extends Iface { public record BPFInfo( BPFObject bpfObject, - BPFMap xsk, BPFMap mac2port, BPFMap srcmac2count, - String mac2portSharedMapGroup) { - + BPFMap xsk, BPFMap mac2port, BPFMap port2dev, BPFMap srcmac2count, BPFMap passmac, + String mac2portSharedMapGroup + ) { public BPFInfo(BPFObject bpfObject, BPFMap xsk) { - this(bpfObject, xsk, null, null, null); + this(bpfObject, xsk, null, null, null, null, null); } } public record XDPParams(int queueId, int rxRingSize, int txRingSize, BPFMode mode, - boolean zeroCopy, int busyPollBudget, boolean rxGenChecksum, boolean offload, + boolean zeroCopy, int busyPollBudget, boolean rxGenChecksum, + boolean pktswOffloaded, boolean csumOffloaded, BPFInfo bpf) { } public XDPIface(String nic, int vrf, UMem umem, XDPParams params) { // check offload - if (params.offload) { + if (params.pktswOffloaded) { if (params.bpf.mac2port == null || params.bpf.srcmac2count == null) { throw new IllegalArgumentException("offload is true, but macMap is not provided"); } @@ -113,7 +114,7 @@ public void sendPacket(PacketBuffer pkb) { assert Logger.lowLevelDebug("update pktaddr(" + pktaddr + ") and pktlen(" + pktlen + ")"); chunk.setPktAddr(pktaddr); chunk.setPktLen(pktlen); - chunk.setCsumFlags(SwitchUtils.checksumFlagsFor(pkb.pkt, umem.metaLen)); + chunk.setCsumFlags(SwitchUtils.checksumFlagsFor(pkb.pkt, umem.metaLen, params.csumOffloaded)); if (chunk.getCsumFlags() != 0) { statistics.incrCsumSkip(); } @@ -142,9 +143,9 @@ public void sendPacket(PacketBuffer pkb) { } ByteArray pktData = pkb.pkt.getRawPacket(AbstractPacket.FLAG_CHECKSUM_UNNECESSARY); - long pktaddr = chunk.getAddr() + Consts.XDP_HEADROOM_DRIVER_RESERVED; - long availableSpace = chunk.getEndAddr() - chunk.getAddr() - Consts.XDP_HEADROOM_DRIVER_RESERVED; - var csumFlags = SwitchUtils.checksumFlagsFor(pkb.pkt, umem.metaLen); + long pktaddr = chunk.getAddr() + umem.headroom; + long availableSpace = chunk.getEndAddr() - chunk.getAddr() - umem.headroom; + var csumFlags = SwitchUtils.checksumFlagsFor(pkb.pkt, umem.metaLen, params.csumOffloaded); if ((csumFlags & XDPConsts.VP_CSUM_XDP_OFFLOAD) != 0) { pktaddr += umem.metaLen; availableSpace -= umem.metaLen; @@ -248,7 +249,19 @@ public String name() { @Override protected String toStringExtra() { - return "#q=" + params.queueId + ",umem=" + umem.alias + ",vrf:" + vrf + (params.offload ? ",offload" : ""); + var off = ""; + if (params.pktswOffloaded || params.csumOffloaded) { + off = ",offload="; + var ls = new ArrayList(); + if (params.pktswOffloaded) { + ls.add("pktsw"); + } + if (params.csumOffloaded) { + ls.add("csum"); + } + off += String.join(",", ls); + } + return "#q=" + params.queueId + ",umem=" + umem.alias + ",vrf:" + vrf + off; } private class XDPHandler implements Handler { @@ -319,4 +332,83 @@ public void removed(HandlerContext ctx) { callback.alertDeviceDown(XDPIface.this); } } + + public static class XDPParamsBuilder { + public XDPParamsBuilder$1 setQueueId(int queueId) { + return new XDPParamsBuilder$1(queueId); + } + + public record XDPParamsBuilder$1(int queueId) { + public XDPParamsBuilder$2 setBPFInfo(BPFInfo bpf) { + return new XDPParamsBuilder$2(queueId, bpf); + } + } + } + + public static class XDPParamsBuilder$2 { + private final int queueId; + private final BPFInfo bpf; + + private int rxRingSize = SwitchUtils.DEFAULT_RX_TX_CHUNKS; + private int txRingSize = SwitchUtils.DEFAULT_RX_TX_CHUNKS; + private BPFMode mode = BPFMode.SKB; + private boolean zeroCopy = false; + private int busyPollBudget = 0; + private boolean rxGenChecksum = false; + private boolean pktswOffloaded = false; + private boolean csumOffloaded = false; + + public XDPParamsBuilder$2(int queueId, BPFInfo bpf) { + this.queueId = queueId; + this.bpf = bpf; + } + + public XDPParams build() { + return new XDPParams( + queueId, rxRingSize, txRingSize, mode, + zeroCopy, busyPollBudget, rxGenChecksum, + pktswOffloaded, csumOffloaded, + bpf); + } + + public XDPParamsBuilder$2 setRxRingSize(int rxRingSize) { + this.rxRingSize = rxRingSize; + return this; + } + + public XDPParamsBuilder$2 setTxRingSize(int txRingSize) { + this.txRingSize = txRingSize; + return this; + } + + public XDPParamsBuilder$2 setMode(BPFMode mode) { + this.mode = mode; + return this; + } + + public XDPParamsBuilder$2 setZeroCopy(boolean zeroCopy) { + this.zeroCopy = zeroCopy; + return this; + } + + public XDPParamsBuilder$2 setBusyPollBudget(int busyPollBudget) { + this.busyPollBudget = busyPollBudget; + return this; + } + + public XDPParamsBuilder$2 setRxGenChecksum(boolean rxGenChecksum) { + this.rxGenChecksum = rxGenChecksum; + return this; + } + + public XDPParamsBuilder$2 setPktswOffloaded(boolean pktswOffloaded) { + this.pktswOffloaded = pktswOffloaded; + return this; + } + + public XDPParamsBuilder$2 setCsumOffloaded(boolean csumOffloaded) { + this.csumOffloaded = csumOffloaded; + return this; + } + } } diff --git a/core/src/main/java/io/vproxy/vswitch/util/SwitchUtils.java b/core/src/main/java/io/vproxy/vswitch/util/SwitchUtils.java index 09744f60..88c0bc8d 100644 --- a/core/src/main/java/io/vproxy/vswitch/util/SwitchUtils.java +++ b/core/src/main/java/io/vproxy/vswitch/util/SwitchUtils.java @@ -4,7 +4,6 @@ import io.vproxy.base.util.Consts; import io.vproxy.base.util.Logger; import io.vproxy.base.util.Utils; -import io.vproxy.base.util.coll.Tuple; import io.vproxy.vfd.*; import io.vproxy.vpacket.*; import io.vproxy.vpacket.conntrack.tcp.TcpNat; @@ -26,7 +25,8 @@ public class SwitchUtils { public static final int TOTAL_RCV_BUF_LEN = 4096; public static final int RCV_HEAD_PRESERVE_LEN = 128; - public static final int RX_TX_CHUNKS = 2048; + public static final int DEFAULT_UMEM_CHUNKS = 4096; + public static final int DEFAULT_RX_TX_CHUNKS = 256; public static final MacAddress BROADCAST_MAC = new MacAddress("ff:ff:ff:ff:ff:ff"); public static final MacAddress ZERO_MAC = new MacAddress("00:00:00:00:00:00"); @@ -49,7 +49,7 @@ public static void checkAndUpdateMss(PacketBuffer pkb, Iface iface) { return; } int maxMss = iface.getParams().getBaseMTU() - iface.getOverhead() - 20 /* tcp common */ - - 20 /* possible options in normal tcp packets, and also ip headers/opts */; + - 20 /* possible options in normal tcp packets, and also ip headers/opts */; if (!(pkb.pkt.getPacket() instanceof AbstractIpPacket)) { return; // only tcp requires modification } @@ -294,8 +294,8 @@ public static FilterResult applyFilters(ArrayList filters, PacketF return FilterResult.PASS; } - public static int checksumFlagsFor(EthernetPacket pkt, int metaLen) { - assert Logger.lowLevelDebug("checksumFlagsFor(" + pkt + ", " + metaLen + ")"); + public static int checksumFlagsFor(EthernetPacket pkt, int metaLen, boolean offloadEnabled) { + assert Logger.lowLevelDebug("checksumFlagsFor(" + pkt + ", " + metaLen + ", " + offloadEnabled + ")"); if (!(pkt.getPacket() instanceof AbstractIpPacket)) { return 0; } @@ -305,7 +305,7 @@ public static int checksumFlagsFor(EthernetPacket pkt, int metaLen) { ret |= XDPConsts.VP_CSUM_IP; } if (ip.getPacket().isRequireUpdatingChecksum()) { - if (NativeXDP.supportTxMetadata && metaLen >= 16) { + if (offloadEnabled && NativeXDP.supportTxMetadata && metaLen >= 16) { ret |= XDPConsts.VP_CSUM_UP_PSEUDO | XDPConsts.VP_CSUM_XDP_OFFLOAD; } else { ret |= XDPConsts.VP_CSUM_UP; @@ -319,7 +319,7 @@ public static boolean executeTcpNat(PacketBuffer pkb, TcpNat nat) { assert Logger.lowLevelDebug("executeTcpNat(" + pkb + ", " + nat + ")"); var pkt = pkb.tcpPkt; boolean isBackhaul = pkb.ipPkt.getSrc().equals(nat._2.remote.getAddress()) && - pkb.tcpPkt.getSrcPort() == nat._2.remote.getPort(); + pkb.tcpPkt.getSrcPort() == nat._2.remote.getPort(); assert Logger.lowLevelDebug("isBackhaul = " + isBackhaul); if (pkt.isRst()) { @@ -358,7 +358,7 @@ public static boolean executeTcpNat(PacketBuffer pkb, TcpNat nat) { handled = true; } else { assert Logger.lowLevelDebug("received unexpected packet, " + - "the proxy protocol header is not sent yet, but received !syn + ack packet from the passive side"); + "the proxy protocol header is not sent yet, but received !syn + ack packet from the passive side"); return false; // drop } } @@ -504,7 +504,7 @@ public static void executeUdpNat(PacketBuffer pkb, UdpNat nat) { assert Logger.lowLevelDebug("executeUdpNat(" + pkb + ", " + nat + ")"); var pkt = pkb.udpPkt; boolean isBackhaul = pkb.ipPkt.getSrc().equals(nat._2.remote.getAddress()) && - pkb.udpPkt.getSrcPort() == nat._2.remote.getPort(); + pkb.udpPkt.getSrcPort() == nat._2.remote.getPort(); assert Logger.lowLevelDebug("isBackhaul = " + isBackhaul); nat.resetTimer(); @@ -618,7 +618,7 @@ public interface BPFObjectCreator { BPFObject get(Map reusedMaps) throws IOException; } - public record GetSharedMapGroupResult(BPFObject object, BPFMap map, String groupName) { + public record GetSharedMapGroupResult(BPFObject object, BPFMap mac2portMap, BPFMap port2devMap, String groupName) { public void release(boolean detach) { object.release(detach); SharedBPFMapHolder.getInstance().release(groupName); @@ -628,21 +628,24 @@ public void release(boolean detach) { public static GetSharedMapGroupResult createBPFObjectWithReusedMaps(Switch sw, int vrf, BPFObjectCreator fn) throws IOException { var mapGroupName = "mac2port:" + sw.alias + ":" + vrf; - var mapName = Prebuilt.DEFAULT_MAC_TO_PORT_MAP_NAME; + var mac2portName = Prebuilt.DEFAULT_MAC_TO_PORT_MAP_NAME; + var devMapName = Prebuilt.DEFAULT_PORT_TO_DEV_MAP_NAME; - var res = SharedBPFMapHolder.getInstance().getOrCreate(mapGroupName, () -> { + var tup = SharedBPFMapHolder.getInstance().getOrCreate(mapGroupName, () -> { var obj = BPFObject.load(Prebuilt.DEFAULT_PROG); - BPFMap map; + BPFMap mac2portMap; + BPFMap port2devMap; try { - map = obj.getMap(mapName); + mac2portMap = obj.getMap(mac2portName); + port2devMap = obj.getMap(devMapName); } catch (IOException e) { obj.release(true); throw e; } - return new Tuple<>(obj, map); + return new SharedBPFMapHolder.BPFObjectAndMapProviderResultTuple(obj, mac2portMap, port2devMap); }); - var reuseMap = Map.of(mapName, res); + var reuseMap = Map.of(mac2portName, tup.mac2portMap(), devMapName, tup.devMap()); BPFObject obj; try { @@ -651,14 +654,16 @@ public static GetSharedMapGroupResult createBPFObjectWithReusedMaps(Switch sw, i SharedBPFMapHolder.getInstance().release(mapGroupName); throw e; } - BPFMap map; + BPFMap mac2portMap; + BPFMap port2devMap; try { - map = obj.getMap(mapName); + mac2portMap = obj.getMap(mac2portName); + port2devMap = obj.getMap(devMapName); } catch (IOException e) { obj.release(true); SharedBPFMapHolder.getInstance().release(mapGroupName); throw e; } - return new GetSharedMapGroupResult(obj, map, mapGroupName); + return new GetSharedMapGroupResult(obj, mac2portMap, port2devMap, mapGroupName); } } diff --git a/extended/src/main/java/io/vproxy/vproxyx/websocks/uot/UdpOverTcpSetup.java b/extended/src/main/java/io/vproxy/vproxyx/websocks/uot/UdpOverTcpSetup.java index 31257535..dd82018d 100644 --- a/extended/src/main/java/io/vproxy/vproxyx/websocks/uot/UdpOverTcpSetup.java +++ b/extended/src/main/java/io/vproxy/vproxyx/websocks/uot/UdpOverTcpSetup.java @@ -91,9 +91,10 @@ public static FDs setup(boolean client, int port, String nicname, EventLoopGroup UMem umem = sw.addUMem("umem0", 256, 128, 128, 2048); XDPIface iface = sw.addXDP(nicname, 1, umem, - new XDPIface.XDPParams(0, 128, 128, BPFMode.SKB, - false, 0, false, false, - new XDPIface.BPFInfo(obj, xskMap))); + new XDPIface.XDPParamsBuilder() + .setQueueId(0) + .setBPFInfo(new XDPIface.BPFInfo(obj, xskMap)) + .build()); UdpOverTcpPacketFilter filter = new UdpOverTcpPacketFilter(client); iface.addIngressFilter(filter); diff --git a/submodules/vpxdp b/submodules/vpxdp index 4eb940f5..16da4da9 160000 --- a/submodules/vpxdp +++ b/submodules/vpxdp @@ -1 +1 @@ -Subproject commit 4eb940f5fd4c2836406b2f20def630460c8f1817 +Subproject commit 16da4da961f89e4d643c401ec09a0dfd5bccb183 diff --git a/test/src/test/java/io/vproxy/poc/XDPPoc.java b/test/src/test/java/io/vproxy/poc/XDPPoc.java index 238557e0..4218e2ec 100644 --- a/test/src/test/java/io/vproxy/poc/XDPPoc.java +++ b/test/src/test/java/io/vproxy/poc/XDPPoc.java @@ -21,6 +21,23 @@ public static void main(String[] args) throws Exception { return; } String ifname = args[0]; + boolean csumOffloaded = false; + for (var i = 1; i < args.length; i++) { + var arg = args[i]; + if (arg.startsWith("offload=")) { + var v = arg.substring("offload=".length()); + var split = v.split(","); + for (var s : split) { + s = s.trim(); + if (s.equals("csum")) { + csumOffloaded = true; + } else { + Logger.error(LogType.ALERT, "unexpected argument " + arg); + return; + } + } + } + } BPFObject bpfobj = BPFObject.loadAndAttachToNic( ifname, @@ -44,10 +61,10 @@ public static void main(String[] args) throws Exception { new Annotations()); UMem umem = sw.addUMem("poc-umem", 64, 32, 32, 4096); - sw.addXDP(ifname, 1, umem, new XDPIface.XDPParams( - 0, 32, 32, BPFMode.SKB, - false, 0, false, false, - new XDPIface.BPFInfo(bpfobj, xskMap) - )); + sw.addXDP(ifname, 1, umem, new XDPIface.XDPParamsBuilder() + .setQueueId(0) + .setBPFInfo(new XDPIface.BPFInfo(bpfobj, xskMap)) + .setCsumOffloaded(csumOffloaded) + .build()); } }