Skip to content

Commit

Permalink
dev-env-docker (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
capr committed Jan 20, 2016
1 parent 4505936 commit ba8d15f
Show file tree
Hide file tree
Showing 25 changed files with 438 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/program/lisper/dev-env-docker/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
perftest*.pcap
lisper*.conf
18 changes: 18 additions & 0 deletions src/program/lisper/dev-env-docker/install
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# copy-paste these commmands from github to install
# dev-env-docker in a fresh docker container.

apt-get update
apt-get install mc git uml-utilities yasm

git clone https://github.com/capr/snabbswitch
cd snabbswitch
git checkout lisper4
git submodule update --init --recursive

cd src
make clean
make

cd ../..

ln -sf /root/snabbswitch/src/program/lisper/dev-env-docker /root/dev-env
16 changes: 16 additions & 0 deletions src/program/lisper/dev-env-docker/l2tp.app
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
n=$APP_N
p=$LISP_N
[ "$n" ] || exit 1
[ "$p" ] || exit 1
run() {
ip netns exec node$n ./l2tp.lua t0 e0 \
00:00:00:00:01:$n \
00:00:00:00:00:$n \
fd80:00$n:0000:0000:0000:0000:0000:0002 \
fd80:00$p:0000:0000:0000:0000:0000:0002 \
000000$n 000000$n
}
start() { run >/dev/null & }
stop() { pgrep -f "l2tp.lua .\*\?01:$n " | xargs kill -9; }
restart() { stop; start; }
if [ "$1" ]; then $1; else stop; run; fi
1 change: 1 addition & 0 deletions src/program/lisper/dev-env-docker/l2tp.app01
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
APP_N=01 LISP_N=04 ./l2tp.app "$@"
2 changes: 2 additions & 0 deletions src/program/lisper/dev-env-docker/l2tp.app02
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
APP_N=02 LISP_N=04 ./l2tp.app "$@"

2 changes: 2 additions & 0 deletions src/program/lisper/dev-env-docker/l2tp.app05
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
APP_N=05 LISP_N=08 ./l2tp.app "$@"

1 change: 1 addition & 0 deletions src/program/lisper/dev-env-docker/l2tp.app06
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
APP_N=06 LISP_N=08 ./l2tp.app "$@"
252 changes: 252 additions & 0 deletions src/program/lisper/dev-env-docker/l2tp.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
#!snabb/src/snabb snsh
io.stdout:setvbuf'no'
io.stderr:setvbuf'no'

--L2TP IP-over-IPv6 tunnelling program for testing.

local function assert(v, ...)
if v then return v, ... end
error(tostring((...)), 2)
end

local ffi = require'ffi'
local S = require'syscall'
local C = ffi.C
local htons = require'syscall.helpers'.htons

local DEBUG = os.getenv'DEBUG'

local function hex(s)
return (s:gsub('(.)(.?)', function(c1, c2)
return c2 and #c2 == 1 and
string.format('%02x%02x ', c1:byte(), c2:byte()) or
string.format('%02x ', c1:byte())
end))
end

local digits = {}
for i=0,9 do digits[string.char(('0'):byte()+i)] = i end
for i=0,5 do digits[string.char(('a'):byte()+i)] = 10+i end
for i=0,5 do digits[string.char(('A'):byte()+i)] = 10+i end
local function parsehex(s)
return (s:gsub('[%s%:%.]*(%x)(%x)[%s%:%.]*', function(hi, lo)
local hi = digits[hi]
local lo = digits[lo]
return string.char(lo + hi * 16)
end))
end

local function open_tap(name)
local fd = assert(S.open('/dev/net/tun', 'rdwr, nonblock'))
local ifr = S.t.ifreq{flags = 'tap, no_pi', name = name}
assert(fd:ioctl('tunsetiff', ifr))
return fd
end

local function open_raw(name)
local fd = assert(S.socket('packet', 'raw, nonblock', htons(S.c.ETH_P.all)))
local ifr = S.t.ifreq{name = name}
assert(S.ioctl(fd, 'siocgifindex', ifr))
assert(S.bind(fd, S.t.sockaddr_ll{
ifindex = ifr.ivalue,
protocol = 'all'}))
return fd
end

local mtu = 1500
local rawbuf = ffi.new('uint8_t[?]', mtu)
local tapbuf = ffi.new('uint8_t[?]', mtu)
local function read_buf(buf, fd)
return buf, assert(S.read(fd, buf, mtu))
end

local function write(fd, s, len)
assert(S.write(fd, s, len))
end

local tapname, ethname, smac, dmac, sip, dip, sid, did = unpack(main.parameters)
if not (tapname and ethname and smac and dmac and sip and dip and sid and did) then
print('Usage: l2tp.lua TAP ETH SMAC DMAC SIP DIP SID DID')
print' TAP: the tunneled interface: will be created if not present.'
print' ETH: the tunneling interface: must have an IPv6 assigned.'
print' SMAC: the MAC address of ETH.'
print' DMAC: the MAC address of the gateway interface.'
print' SIP: the IPv6 of ETH (long form).'
print' DIP: the IPv6 of ETH at the other endpoint (long form).'
print' SID: session ID (hex)'
print' DID: peer session ID (hex)'
os.exit(1)
end
smac = parsehex(smac)
dmac = parsehex(dmac)
sip = parsehex(sip)
dip = parsehex(dip)
sid = parsehex(sid)
did = parsehex(did)

local tap = open_tap(tapname)
local raw = open_raw(ethname)

print('tap ', tapname)
print('raw ', ethname)
print('smac ', hex(smac))
print('dmac ', hex(dmac))
print('sip ', hex(sip))
print('dip ', hex(dip))
print('sid ', hex(sid))
print('did ', hex(did))

local l2tp_ct = ffi.typeof[[
struct {
// ethernet
char dmac[6];
char smac[6];
uint16_t ethertype;
// ipv6
uint32_t flow_id; // version, tc, flow_id
int8_t payload_length_hi;
int8_t payload_length_lo;
int8_t next_header;
uint8_t hop_limit;
char src_ip[16];
char dst_ip[16];
// l2tp
//uint32_t session_id;
char session_id[4];
char cookie[8];
} __attribute__((packed))
]]

local l2tp_ct_size = ffi.sizeof(l2tp_ct)
local l2tp_ctp = ffi.typeof('$*', l2tp_ct)

local function decap_l2tp_buf(buf, len)
if len < l2tp_ct_size then return nil, 'packet too small' end
local p = ffi.cast(l2tp_ctp, buf)
if p.ethertype ~= 0xdd86 then return nil, 'not ipv6' end
if p.next_header ~= 115 then return nil, 'not l2tp' end
local dmac = ffi.string(p.dmac, 6)
local smac = ffi.string(p.smac, 6)
local sip = ffi.string(p.src_ip, 16)
local dip = ffi.string(p.dst_ip, 16)
local sid = ffi.string(p.session_id, 4) --p.session_id
local payload_size = len - l2tp_ct_size
return smac, dmac, sip, dip, sid, l2tp_ct_size, payload_size
end

local function encap_l2tp_buf(smac, dmac, sip, dip, did, payload, payload_size, outbuf)
local p = ffi.cast(l2tp_ctp, outbuf)
ffi.copy(p.dmac, dmac)
ffi.copy(p.smac, smac)
p.ethertype = 0xdd86
p.flow_id = 0x60
local ipsz = payload_size + 12
p.payload_length_hi = bit.rshift(ipsz, 8)
p.payload_length_lo = bit.band(ipsz, 0xff)
p.next_header = 115
p.hop_limit = 64
ffi.copy(p.src_ip, sip)
ffi.copy(p.dst_ip, dip)
ffi.copy(p.session_id, did)
ffi.fill(p.cookie, 8)
ffi.copy(p + 1, payload, payload_size)
return outbuf, l2tp_ct_size + payload_size
end

--fast select ----------------------------------------------------------------
--select() is gruesome.

local band, bor, shl, shr = bit.band, bit.bor, bit.lshift, bit.rshift

local function getbit(b, bits)
return band(bits[shr(b, 3)], shl(1, band(b, 7))) ~= 0
end

local function setbit(b, bits)
bits[shr(b, 3)] = bor(bits[shr(b, 3)], shl(1, band(b, 7)))
end

ffi.cdef[[
typedef struct {
uint8_t bits[128]; // 1024 bits
} xfd_set;
int xselect(int, xfd_set*, xfd_set*, xfd_set*, void*) asm("select");
]]
local function FD_ISSET(d, set) return getbit(d, set.bits) end
local function FD_SET(d, set)
assert(d <= 1024)
setbit(d, set.bits)
end
local fds0 = ffi.new'xfd_set'
local fds = ffi.new'xfd_set'
local fds_size = ffi.sizeof(fds)
local rawfd = raw:getfd()
local tapfd = tap:getfd()
FD_SET(rawfd, fds0)
FD_SET(tapfd, fds0)
local maxfd = math.max(rawfd, tapfd) + 1
local EINTR = 4
local function can_read() --returns true if fd has data, false if timed out
ffi.copy(fds, fds0, fds_size)
::retry::
local ret = C.xselect(maxfd, fds, nil, nil, nil)
if ret == -1 then
if C.errno() == EINTR then goto retry end
error('select errno '..tostring(C.errno()))
end
return FD_ISSET(rawfd, fds), FD_ISSET(tapfd, fds)
end

------------------------------------------------------------------------------

while true do
local can_raw, can_tap = can_read()
if can_raw or can_tap then
if can_raw then
local buf, len = read_buf(rawbuf, raw)
local smac1, dmac1, sip1, dip1, did1, payload_offset, payload_size = decap_l2tp_buf(buf, len)
local accept = smac1
and smac1 == dmac
and dmac1 == smac
and dip1 == sip
and sip1 == dip
and did1 == sid
if DEBUG then
if accept or smac1 then
print('read', accept and 'accepted' or 'rejected')
print(' smac ', hex(smac1))
print(' dmac ', hex(dmac1))
print(' sip ', hex(sip1))
print(' dip ', hex(dip1))
print(' did ', hex(did1))
print(' # ', payload_size)
end
end
if accept then
write(tap, buf + payload_offset, payload_size)
end
end
if can_tap then
local payload, payload_size = read_buf(tapbuf, tap)
local frame, frame_size = encap_l2tp_buf(smac, dmac, sip, dip, did, payload, payload_size, rawbuf)
if DEBUG then
print('write')
print(' smac ', hex(smac))
print(' dmac ', hex(dmac))
print(' sip ', hex(sip))
print(' dip ', hex(dip))
print(' did ', hex(did))
print(' #in ', payload_size)
print(' #out ', frame_size)
end
write(raw, frame, frame_size)
end
end
end

tap:close()
raw:close()
6 changes: 6 additions & 0 deletions src/program/lisper/dev-env-docker/lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
run() { ./lisp.lua ${LISP_N}; }
start() { run >/dev/null & }
stop() { pgrep -f "lisp.lua ${LISP_N}" | xargs kill -9; }
restart() { stop; start; }
if [ "$1" ]; then $1; else stop; run; fi
56 changes: 56 additions & 0 deletions src/program/lisper/dev-env-docker/lisp.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!snabb/src/snabb snsh
io.stdout:setvbuf'no'
io.stderr:setvbuf'no'

--LISP controller mock-up program for testing.

local function assert(v, ...)
if v then return v, ... end
error(tostring((...)), 2)
end

local ffi = require("ffi")
local S = require("syscall")
local _ = string.format

local LISP_N = os.getenv("LISP_N") or ""
local CONTROL_SOCK = "/var/tmp/lisp-ipc-map-cache"..LISP_N
local PUNT_SOCK = "/var/tmp/lispers.net-itr"..LISP_N

S.signal('pipe', 'ign') --I 💔 Linux

local sock
::retry::
sock = sock or assert(S.socket("unix", "dgram, nonblock"))
local sa = S.t.sockaddr_un(CONTROL_SOCK)
local ok, err = sock:connect(sa)
if not ok then
if err.CONNREFUSED or err.AGAIN or err.NOENT then
S.sleep(1)
print'retrying...'
goto retry
end
assert(nil, err)
end
print'connected'

while true do
if assert(S.select({writefds = {sock}}, 0)).count == 1 then

local t = {}
for s in io.lines('lisp'..LISP_N..'.fib') do
table.insert(t, s)
end

print'sending...'
for i,s in ipairs(t) do
if not S.write(sock, s, #s) then
print'write error'
sock:close()
sock = nil
goto retry
end
end
end
S.sleep(1)
end
1 change: 1 addition & 0 deletions src/program/lisper/dev-env-docker/lisp04
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
LISP_N=04 ./lisp "$@"
7 changes: 7 additions & 0 deletions src/program/lisper/dev-env-docker/lisp04.fib
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{ "instance-id": 1, "eid-prefix": "000000-00aa05/48", "rlocs": [{ "rloc": "fd80:8::2", "priority": 1, "weight": 50 }] }

{ "instance-id": 1, "eid-prefix": "000000-00aa06/48", "rlocs": [{ "rloc": "fd80:8::2", "priority": 1, "weight": 50 }] }

{ "instance-id": 1, "eid-prefix": "000000-00aa07/48", "rlocs": [{ "rloc": "fd80:8::2", "priority": 1, "weight": 50 }] }

{ "instance-id": 1, "eid-prefix": "ffffff-ffffff/48", "rles": [{ "rle": "fd80:8::2" }] }
1 change: 1 addition & 0 deletions src/program/lisper/dev-env-docker/lisp08
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
LISP_N=08 ./lisp "$@"
7 changes: 7 additions & 0 deletions src/program/lisper/dev-env-docker/lisp08.fib
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{ "instance-id": 1, "eid-prefix": "000000-00aa01/48", "rlocs": [{ "rloc": "fd80:4::2", "priority": 1, "weight": 50 }] }

{ "instance-id": 1, "eid-prefix": "000000-00aa02/48", "rlocs": [{ "rloc": "fd80:4::2", "priority": 1, "weight": 50 }] }

{ "instance-id": 1, "eid-prefix": "000000-00aa03/48", "rlocs": [{ "rloc": "fd80:4::2", "priority": 1, "weight": 50 }] }

{ "instance-id": 1, "eid-prefix": "ffffff-ffffff/48", "rles": [{ "rle": "fd80:4::2" }] }
7 changes: 7 additions & 0 deletions src/program/lisper/dev-env-docker/lisper
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
cd "$(dirname "$0")" || exit 1
run() { snabb/src/snabb lisper -c lisper${LISP_N}.conf; }
start() { run >/dev/null & }
stop() { pgrep -f "snabb lisper -c lisper${LISP_N}" | xargs kill -9; }
restart() { stop; start; }
if [ "$1" ]; then $1; else stop; run; fi
1 change: 1 addition & 0 deletions src/program/lisper/dev-env-docker/lisper04
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
LISP_N=04 ./lisper "$@"
1 change: 1 addition & 0 deletions src/program/lisper/dev-env-docker/lisper08
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
LISP_N=08 ./lisper "$@"
1 change: 1 addition & 0 deletions src/program/lisper/dev-env-docker/mklisper
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cd snabb && make
Loading

0 comments on commit ba8d15f

Please sign in to comment.