Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrated collection of open PRs on master #424

Merged
merged 28 commits into from
Mar 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
346ac0b
Makefile: Streamline LuaJIT build options
lukego Mar 5, 2015
f76af58
cksum_avx2: Switch to AVX unaligned loads
lukego Mar 23, 2015
90fc011
Run in busy-loop (engine.Hz = false) by default
lukego Mar 23, 2015
8cf86ff
engine: Make link report prettier
lukego Mar 23, 2015
e942aa0
core.memory: Replace mlockall() with on-demand mlock()
lukego Mar 23, 2015
487873c
core.packet: Don't allocate packets at module-load time
lukego Mar 23, 2015
25f97c6
core.main: Don't insist on starting as root
lukego Mar 23, 2015
51519c5
memory/pci: Explicitly check for root access when needed
lukego Mar 23, 2015
6759f01
snabbnfv: Improve --help usage printouts
lukego Mar 23, 2015
122bfa7
new function checksum.verify_packet() takes an IP packet (not the who…
javierguerragiraldez Mar 18, 2015
c809291
if we can check the incoming packet, tell the VM not to bother checki…
javierguerragiraldez Mar 18, 2015
3dec599
optimization: move the ntohs() to the end of the sums
javierguerragiraldez Mar 20, 2015
482f89e
return a single value, not a structure
javierguerragiraldez Mar 20, 2015
48b1721
Merge PR #389 to integration branch
lukego Mar 24, 2015
fb867d8
Merge PR #414 to integration branch
lukego Mar 24, 2015
ae0ff06
Merge PR #415 to integration branch
lukego Mar 24, 2015
629e905
Merge PR #417 to integration branch
lukego Mar 24, 2015
fa2b1d1
Merge PR #416 to integration branch
lukego Mar 24, 2015
5ab5336
Merge PR #418 to integration branch
lukego Mar 24, 2015
bdc7be7
snabbnfv traffic: Fix command-line argument parsing
lukego Mar 24, 2015
c2c7732
snabbnfv traffic: Fix benchmark-mode startup
lukego Mar 24, 2015
7ceacca
snabbnfv traffic: Print profiler output after benchmark
lukego Mar 24, 2015
72da719
Merge PR #420 into integration branch
lukego Mar 24, 2015
54cdbcc
ugly hack: return pseudoheader initial swapped or not according to size
javierguerragiraldez Mar 24, 2015
fc1a2b4
Explicit difference between 'bad' and 'unknown' packets
javierguerragiraldez Mar 24, 2015
a0b6811
Add random initial value to selftest
javierguerragiraldez Mar 25, 2015
32ca44c
Initial values are in network order
javierguerragiraldez Mar 25, 2015
6a41f25
Merge PR #411 into integration branch.
lukego Mar 25, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ COBJ = $(CSRC:.c=.o)
LUAJIT_O := deps/luajit/src/libluajit.a
SYSCALL := src/syscall.lua

LUAJIT_CFLAGS := -DLUAJIT_USE_PERFTOOLS -DLUAJIT_USE_GDBJIT -DLUAJIT_NUMMODE=3 -include $(CURDIR)/gcc-preinclude.h
LUAJIT_CFLAGS := -include $(CURDIR)/gcc-preinclude.h

all: $(LUAJIT_O) $(SYSCALL)
@echo "Building snabbswitch"
Expand Down
15 changes: 10 additions & 5 deletions src/core/app.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ configuration = config.new()
-- Count of the number of breaths taken
breaths = 0
-- Ideal number of breaths per second
Hz = 10000
Hz = false

-- Return current monotonic time in seconds.
-- Can be used to drive timers in apps.
Expand Down Expand Up @@ -268,10 +268,15 @@ function report (options)
return tonumber(drop) * 100 / (tonumber(drop)+sent)
end
if not options or options.showlinks then
print("link report")
for name, l in pairs(link_table) do
print(("%s sent on %s (loss rate: %d%%))"):format(l.stats.txpackets,
name, loss_rate(l.stats.txdrop, l.stats.txpackets)))
print("link report:")
local names = {}
for name in pairs(link_table) do table.insert(names, name) end
table.sort(names)
for i, name in ipairs(names) do
l = link_table[name]
print(("%20s sent on %s (loss rate: %d%%)"):format(
lib.comma_value(l.stats.txpackets),
name, loss_rate(l.stats.txdrop, l.stats.txpackets)))
end
end
if options and options.showapps then
Expand Down
3 changes: 0 additions & 3 deletions src/core/clib.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,3 @@ uint16_t ntohs(uint16_t);
uint32_t htonl(uint32_t);
uint32_t ntohl(uint32_t);

// geteuid(2) - get effective user identity
int geteuid();

9 changes: 9 additions & 0 deletions src/core/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module(...,package.seeall)
local ffi = require("ffi")
local C = ffi.C
local getopt = require("lib.lua.alt_getopt")
local syscall = require("syscall")
require("core.clib_h")

-- Returns true if x and y are structurally similar (isomorphic).
Expand Down Expand Up @@ -419,6 +420,14 @@ function have_module (name)
end
end

-- Exit with an error if we are not running as root.
function root_check (message)
if syscall.geteuid() ~= 0 then
print(message or "error: must run as root")
main.exit(1)
end
end

function selftest ()
print("selftest: lib")
print("Testing equal")
Expand Down
4 changes: 0 additions & 4 deletions src/core/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ function initialize ()
require("core.lib")
require("core.clib_h")
require("core.lib_h")
if C.geteuid() ~= 0 then
print("error: snabb has to run as root.")
os.exit(1)
end
-- Global API
_G.config = require("core.config")
_G.engine = require("core.app")
Expand Down
8 changes: 2 additions & 6 deletions src/core/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,13 @@ void *allocate_huge_page(int size)
shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
tmpptr = shmat(shmid, NULL, 0);
if (tmpptr == MAP_FAILED) { goto fail; }
if (mlock(tmpptr, size) != 0) { goto fail; }
physical_address = virtual_to_physical(tmpptr);
if (physical_address == 0) { goto fail; }
virtual_address = physical_address | 0x500000000000ULL;
realptr = shmat(shmid, (void*)virtual_address, 0);
if (realptr == MAP_FAILED) { goto fail; }
if (mlock(realptr, size) != 0) { goto fail; }
memset(realptr, 0, size); // zero memory to avoid potential surprises
shmdt(tmpptr);
shmctl(shmid, IPC_RMID, 0);
Expand All @@ -102,9 +104,3 @@ void *allocate_huge_page(int size)
return NULL;
}

// Lock all current and future virtual memory in a stable physical location.
int lock_memory()
{
return mlockall(MCL_CURRENT | MCL_FUTURE);
}

10 changes: 1 addition & 9 deletions src/core/memory.lua
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function allocate_hugetlb_chunk ()
end

function reserve_new_page ()
lib.root_check("error: must run as root to allocate memory for DMA")
set_hugepages(get_hugepages() + 1)
end

Expand Down Expand Up @@ -116,12 +117,3 @@ function selftest (options)
print("HugeTLB page allocation OK.")
end

--- ### module init: `mlock()` at load time

--- This module requires a stable physical-virtual mapping so this is
--- enforced automatically at load-time.
function module_init ()
assert(C.lock_memory() == 0)
end

module_init()
4 changes: 0 additions & 4 deletions src/core/packet.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,3 @@ function preallocate_step()
packet_allocation_step = 2 * packet_allocation_step
end

--preallocate packets freelist
if freelist_nfree(packets_fl) == 0 then
preallocate_step()
end
67 changes: 56 additions & 11 deletions src/lib/checksum.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ uint16_t cksum_generic(const void *buf, size_t len, uint16_t initial)

//
// A unaligned version of the cksum,
// n is number of 16-bit values to sum over, n in it self is a
// n is number of 16-bit values to sum over, n in it self is a
// 16 bit number in order to avoid overflow in the loop
//
static inline uint32_t cksum_ua_loop(unsigned char *p, uint16_t n)
Expand Down Expand Up @@ -135,7 +135,7 @@ static inline uint32_t cksum_sse2_loop(unsigned char *p, size_t n)

uint16_t cksum_sse2(unsigned char *p, size_t n, uint32_t initial)
{
uint32_t sum = initial;
uint32_t sum = ntohs(initial);

if (n < 128) { return cksum_generic(p, n, initial); }
int unaligned = (unsigned long) p & 0xf;
Expand Down Expand Up @@ -183,7 +183,7 @@ static inline uint32_t cksum_avx2_loop(unsigned char *p, size_t n)
__m256i s1 = zero;
n -= k;
while (k) {
__m256i src = _mm256_load_si256((__m256i const*) p);
__m256i src = _mm256_loadu_si256((__m256i const*) p);
__m256i t;

t = _mm256_unpacklo_epi8(src, zero);
Expand Down Expand Up @@ -217,16 +217,9 @@ static inline uint32_t cksum_avx2_loop(unsigned char *p, size_t n)

uint16_t cksum_avx2(unsigned char *p, size_t n, uint32_t initial)
{
uint32_t sum = initial;
uint32_t sum = ntohs(initial);

if (n < 128) { return cksum_generic(p, n, initial); }
int unaligned = (unsigned long) p & 31;
if (unaligned) {
size_t k = (32 - unaligned) >> 1;
sum += cksum_ua_loop(p, k);
n -= (2*k);
p += (2*k);
}
if (n >= 64) {
size_t k = (n >> 5);
sum += cksum_avx2_loop(p, k);
Expand Down Expand Up @@ -294,3 +287,55 @@ uint32_t tcp_pseudo_checksum(uint16_t *sip, uint16_t *dip,
return result;
}

// calculates the initial checksum value resulting from
// the pseudo header.
// return values:
// 0x0000 - 0xFFFF : initial checksum (in network order).
// 0xFFFF0001 : unknown packet (non IPv4/6 or non TCP/UDP)
// 0xFFFF0002 : bad header
uint32_t pseudo_header_initial(const int8_t *buf, size_t len)
{
const uint16_t const *hwbuf = (const uint16_t *)buf;
int8_t ipv = (buf[0] & 0xF0) >> 4;
int8_t proto = 0;
int headersize = 0;

if (ipv == 4) { // IPv4
proto = buf[9];
headersize = (buf[0] & 0x0F) * 4;
} else if (ipv == 6) { // IPv6
proto = buf[6];
headersize = 40;
} else {
return 0xFFFF0001;
}

if (proto == 6 || proto == 17) { // TCP || UDP
uint32_t sum = 0;
len -= headersize;
if (ipv == 4) { // IPv4
if (cksum_generic_reduce(cksum_generic_loop(buf, headersize, 0)) != 0) {
return 0xFFFF0002;
}
sum = htons(len & 0x0000FFFF) + (proto << 8)
+ hwbuf[6]
+ hwbuf[7]
+ hwbuf[8]
+ hwbuf[9];

} else { // IPv6
sum = hwbuf[2] + (proto << 8);
int i;
for (i = 4; i < 20; i+=4) {
sum += hwbuf[i] +
hwbuf[i+1] +
hwbuf[i+2] +
hwbuf[i+3];
}
}
sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
return sum;
}
return 0xFFFF0001;
}
1 change: 1 addition & 0 deletions src/lib/checksum.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ void checksum_update_incremental_32(uint16_t* checksum_cell,
uint32_t tcp_pseudo_checksum(uint16_t *sip, uint16_t *dip,
int addr_halfwords, int len);

uint32_t pseudo_header_initial(const int8_t *buf, size_t len);
30 changes: 24 additions & 6 deletions src/lib/checksum.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require("lib.checksum_h")
local lib = require("core.lib")
local ffi = require("ffi")
local C = ffi.C
local band = bit.band

-- Select ipsum(pointer, len, initial) function based on hardware
-- capability.
Expand All @@ -27,6 +28,22 @@ function finish_packet (buf, len, offset)
ffi.cast('uint16_t *', buf+offset)[0] = lib.htons(ipsum(buf, len, 0))
end

function verify_packet (buf, len)
local initial = C.pseudo_header_initial(buf, len)
if initial == 0xFFFF0001 then return nil
elseif initial == 0xFFFF0002 then return false
end

local headersize = 0
local ipv = band(buf[0], 0xF0)
if ipv == 0x60 then
headersize = 40
elseif ipv == 0x40 then
headersize = band(buf[0], 0x0F) * 4;
end

return ipsum(buf+headersize, len-headersize, initial) == 0
end

-- See checksum.h for more utility functions that can be added.

Expand All @@ -38,14 +55,15 @@ function selftest ()
for i = 0, n-1 do array[i] = i end
local avx2ok, sse2ok = 0, 0
for i = 1, tests do
local ref = C.cksum_generic(array+i*2, i*10+i, 0)
if have_avx2 and C.cksum_avx2(array+i*2, i*10+i, 0) == ref then
avx2ok = avx2ok + 1
local initial = math.random(0, 0xFFFF)
local ref = C.cksum_generic(array+i*2, i*10+i, initial)
if have_avx2 and C.cksum_avx2(array+i*2, i*10+i, initial) == ref then
avx2ok = avx2ok + 1
end
if have_sse2 and C.cksum_sse2(array+i*2, i*10+i, 0) == ref then
sse2ok = sse2ok + 1
if have_sse2 and C.cksum_sse2(array+i*2, i*10+i, initial) == ref then
sse2ok = sse2ok + 1
end
assert(ipsum(array+i*2, i*10+i, 0) == ref, "API function check")
assert(ipsum(array+i*2, i*10+i, initial) == ref, "API function check")
end
if have_avx2 then print("avx2: "..avx2ok.."/"..tests) else print("no avx2") end
if have_sse2 then print("sse2: "..sse2ok.."/"..tests) else print("no sse2") end
Expand Down
7 changes: 7 additions & 0 deletions src/lib/hardware/pci.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ end
--- Force Linux to release the device with `pciaddress`.
--- The corresponding network interface (e.g. `eth0`) will disappear.
function unbind_device_from_linux (pciaddress)
root_check()
local p = path(pciaddress).."/driver/unbind"
if lib.can_write(p) then
lib.writefile(path(pciaddress).."/driver/unbind", pciaddress)
Expand All @@ -85,6 +86,7 @@ end
-- Pointer for memory-mapped access.
-- File descriptor for the open sysfs resource file.
function map_pci_memory (device, n)
root_check()
local filepath = path(device).."/resource"..n
local fd = C.open_pci_resource(filepath)
assert(fd >= 0)
Expand All @@ -101,6 +103,7 @@ end
--- Enable or disable PCI bus mastering. DMA only works when bus
--- mastering is enabled.
function set_bus_master (device, enable)
root_check()
local fd = C.open_pcie_config(path(device).."/config")
local value = ffi.new("uint16_t[1]")
assert(C.pread(fd, value, 2, 0x4) == 2)
Expand All @@ -113,6 +116,10 @@ function set_bus_master (device, enable)
C.close(fd)
end

function root_check ()
lib.root_check("error: must run as root to access PCI devices")
end

--- ### Selftest
---
--- PCI selftest scans for available devices and performs our driver's
Expand Down
33 changes: 18 additions & 15 deletions src/lib/virtio/net_device.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function VirtioNetDevice:new(owner)
kickfd = {},
virtq = {},
rx = {},
tx = {
tx = {
p = nil,
tx_mrg_hdr = ffi.new("struct virtio_net_hdr_mrg_rxbuf*[1]") ,
data_sent = nil,
Expand Down Expand Up @@ -196,6 +196,21 @@ function VirtioNetDevice:transmit_packets_to_vm ()
end
end

local function validflags(buf, len)
local valid = checksum.verify_packet(buf, len)

if valid == true then
return C.VIO_NET_HDR_F_DATA_VALID
elseif valid == false then
return 0
else
return C.VIO_NET_HDR_F_NEEDS_CSUM
end
end




function VirtioNetDevice:tx_packet_start(addr, len)
local l = self.owner.input.rx
if link.empty(l) then return nil, nil end
Expand All @@ -205,6 +220,7 @@ function VirtioNetDevice:tx_packet_start(addr, len)

-- TODO: copy the relevnat fields from the packet
ffi.fill(tx_hdr, virtio_net_hdr_size)
tx_hdr.flags = validflags(tx_p.data+14, tx_p.length-14)

return tx_p
end
Expand Down Expand Up @@ -236,20 +252,7 @@ function VirtioNetDevice:tx_packet_start_mrg_rxbuf(addr, len)
if link.empty(l) then return end
tx_p = link.receive(l)

-- XXX: We should validate the checksum and report the result to
-- the VM. -lukego
--
-- If checksum successful then set C.VIO_NET_HDR_F_DATA_VALID.
--
-- If checksum failed then set C.VIO_NET_HDR_F_NEEDS_CSUM and
-- let the guest do its own check to detect the error.
--
-- The call to ipsum here should be replaced with a real
-- IP/TCP/UDP checksum check. The current call exists only to
-- make the CPU do the checksumming work so that we can measure
-- preliminary performance.
checksum.ipsum(tx_p.data, tx_p.length, 0)
tx_mrg_hdr.hdr.flags = C.VIO_NET_HDR_F_DATA_VALID
tx_mrg_hdr.hdr.flags = validflags(tx_p.data+14, tx_p.length-14)

self.tx.tx_mrg_hdr[0] = tx_mrg_hdr
self.tx.data_sent = 0
Expand Down
2 changes: 2 additions & 0 deletions src/program/snabbnfv/README
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ Usage:
snabbnfv fuzz

Use --help for per-command usage.
Example:
snabbnfv traffic --help
Loading