Skip to content

Commit

Permalink
[xdp]refactor offload=pktsw,csum and optimize code
Browse files Browse the repository at this point in the history
  • Loading branch information
wkgcass committed Oct 6, 2024
1 parent 6056dc0 commit b05df03
Show file tree
Hide file tree
Showing 23 changed files with 1,108 additions and 752 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion app/src/main/java/io/vproxy/app/app/cmd/Flag.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public enum Flag {
disable("disable"),

rxgencsum("rx-gen-csum"),
offload("offload"),
;
public final String fullname;

Expand Down
21 changes: 12 additions & 9 deletions app/src/main/java/io/vproxy/app/app/cmd/HelpCommand.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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"),
;
Expand All @@ -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"),
;
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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<>(
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/io/vproxy/app/app/cmd/ModuleCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
)
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/io/vproxy/app/app/cmd/Param.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public enum Param {
compringsize("comp-ring-size"),
framesize("frame-size"),
busypoll("busy-poll"),
offload("offload"),

url("url"),
cls("class"),
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,18 @@ public static List<ArpEntry> 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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -236,7 +222,7 @@ public String toString(List<ArpEntry> 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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ 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)) {
busyPollBudget = BusyPollHandle.get(cmd);
}
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);
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
11 changes: 9 additions & 2 deletions app/src/main/java/io/vproxy/app/process/Shutdown.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<String>();
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";
Expand Down
Loading

0 comments on commit b05df03

Please sign in to comment.