Skip to content

Commit

Permalink
development environment scripts and helper programs using network nam…
Browse files Browse the repository at this point in the history
…espaces (WIP: l2tp.lua doesn't work anymore with namespaces, it was working with containers)
  • Loading branch information
capr committed Nov 14, 2015
1 parent d1d975e commit 508f931
Show file tree
Hide file tree
Showing 10 changed files with 296 additions and 59 deletions.
41 changes: 0 additions & 41 deletions src/program/lisp/lisp.lua

This file was deleted.

18 changes: 0 additions & 18 deletions src/program/lisper/README.inc

This file was deleted.

1 change: 1 addition & 0 deletions src/program/lisper/README.inc
6 changes: 6 additions & 0 deletions src/program/lisper/dev-env/l2tp.app1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ip netns exec app1 ./l2tp.lua t0 e0 \
aa:aa:aa:aa:aa:01 \
aa:aa:aa:aa:aa:02 \
fd80:0001:0000:0000:0000:0000:0000:0002 \
fd80:0002:0000:0000:0000:0000:0000:0002 \
00001234 00004321
6 changes: 6 additions & 0 deletions src/program/lisper/dev-env/l2tp.app2
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ip netns exec app2 ./l2tp.lua t0 e0 \
aa:aa:aa:aa:aa:02 \
aa:aa:aa:aa:aa:01 \
fd80:0002:0000:0000:0000:0000:0000:0002 \
fd80:0001:0000:0000:0000:0000:0000:0002 \
00004321 00001234
166 changes: 166 additions & 0 deletions src/program/lisper/dev-env/l2tp.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#!/usr/bin/env luajit

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

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

local DEBUG = true

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

local function hex(s)
return (s:gsub('(.)(.?)', function(c1, c2)
return c2 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 function can_read(...)
return assert(S.select({readfds = {...}}, 0)).count == 1
end

local function can_write(...)
return assert(S.select({writefds = {...}}, 0)).count == 1
end

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

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

local function close(fd)
S.close(fd)
end

local tapname, ethname, smac, dmac, sip, dip, sid, did = ...
if not (tapname and ethname and smac and dmac and sip and dip and sid and did) then
print('Usage: '..arg[0]..' TAP ETH SMAC DMAC SIP DIP SID DID')
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 function decap_l2tp(s)
local dmac = s:sub(1, 6)
local smac = s:sub(1+6, 1+6+6-1)
local sip = s:sub(23, 23+16-1)
local dip = s:sub(23+16, 23+16+16-1)
local sid = s:sub(55, 55+4-1)
local payload = s:sub(63)
return smac, dmac, sip, dip, sid, payload
end

local function encap_l2tp(smac, dmac, sip, dip, did, payload)
local l2tp = did..'\0\0\0\0'
local len = #payload + #l2tp
local len = string.char(bit.rshift(len, 8)) .. string.char(bit.band(len, 0xff))
local ipv6_proto = '\115' --l2tp
local maxhops = '\64'
local ipv6 = '\x60\0\0\0'..len..ipv6_proto..maxhops..sip..dip
local eth_proto = '\x86\xdd' --ipv6
local eth = dmac..smac..eth_proto
return eth..ipv6..l2tp..payload
end

while true do
if can_read(tap, raw) then
if can_read(raw) then
local s = read(raw)
local smac1, dmac1, sip1, dip1, did1, payload = decap_l2tp(s)
local accept =
smac1 == dmac
and dmac1 == smac
and dip1 == sip
and sip1 == dip
and did1 == sid
if DEBUG 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)
end
if accept then
write(tap, payload)
end
end
if can_read(tap) then
local payload = read(tap)
local s = encap_l2tp(smac, dmac, sip, dip, did, payload)
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(' # ', #payload)
print(hex(s))
end
write(raw, s)
end
end
end

tap:close()
raw:close()
35 changes: 35 additions & 0 deletions src/program/lisper/dev-env/lisp.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env luajit

--LISP controller mock-up program for testing.

local ffi = require("ffi")
local S = require("syscall")

CONTROL_SOCK = "/var/tmp/ctrl.socket"
CONTROL_DATA = [[
[5] 08:00:27:7f:05:37 fd80:1::1,fd80:1::2
[7] 4a:86:5c:50:33:5a fd80:2::1
[2] 00:16:3e:01:01:02 fd80:3::1
]]

local sock = assert(S.socket("unix", "stream, nonblock"))
local sa = S.t.sockaddr_un(CONTROL_SOCK)

::retry::
local ok, err = sock:connect(sa)
if not ok then
if err.CONNREFUSED or err.AGAIN then
S.sleep(1)
print'retrying...'
goto retry
end
assert(nil, err)
end
print'connected'

while assert(S.select({writefds = {sock}}, 0)).count == 1 do
print'sending...'
assert(S.write(sock, CONTROL_DATA, #CONTROL_DATA))
S.sleep(1)
end

79 changes: 79 additions & 0 deletions src/program/lisper/dev-env/net-bringup
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash

# This creates a virtual network of 3 machines in 3 different subnets
# connected to a router. Besides that, app1 and app2 machines create
# two static l2tp tunnels which connect _to the same endpoint_ in the
# lisp machine where lisper responds back.

bringup() {
ip netns add r2
ip netns add app1
ip netns add app2
ip netns add lisp

ip link add netns app1 e0 address aa:aa:aa:aa:aa:01 type veth peer name e1 netns r2
ip link add netns app2 e0 address aa:aa:aa:aa:aa:02 type veth peer name e2 netns r2
ip link add netns lisp e0 address aa:aa:aa:aa:aa:04 type veth peer name e4 netns r2

ip netns exec r2 ip addr add fd80:1::1/56 dev e1
ip netns exec r2 ip addr add fd80:2::1/56 dev e2
ip netns exec r2 ip addr add fd80:4::1/56 dev e4

ip netns exec app1 ip addr add fd80:1::2/56 dev e0
ip netns exec app2 ip addr add fd80:2::2/56 dev e0
ip netns exec lisp ip addr add fd80:4::2/56 dev e0

ip netns exec app1 ip -6 route add default via fd80:1::1
ip netns exec app2 ip -6 route add default via fd80:2::1
ip netns exec lisp ip -6 route add default via fd80:4::1

ip netns exec app1 ip link set e0 up
ip netns exec app2 ip link set e0 up
ip netns exec lisp ip link set e0 up

ip netns exec r2 sysctl -wq net.ipv6.conf.all.forwarding=1

ip netns exec r2 ip link set e1 up
ip netns exec r2 ip link set e2 up
ip netns exec r2 ip link set e4 up

if false; then
# NOTE: l2tp ip-over-ipv6 encapsulation doesn't work with namespaces.
# Hence we're using our own little Lua script which does the same thing in userspace.
modprobe l2tp_ip6
modprobe l2tp_eth
modprobe l2tp_core
modprobe l2tp_netlink
ip netns exec app1 ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 encap ip local fd80:1::2 remote fd80:4::2
ip netns exec app2 ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 encap ip local fd80:2::2 remote fd80:4::2
ip netns exec app1 ip l2tp add session name t0 tunnel_id 1 session_id 4660 peer_session_id 17185
ip netns exec app2 ip l2tp add session name t0 tunnel_id 1 session_id 4660 peer_session_id 17185
ip netns exec app1 ip link set t0 up
ip netns exec app2 ip link set t0 up
ip netns exec lisp ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 encap ip local fd80:4::2 remote fd80:1::2
ip netns exec lisp ip l2tp add session name t0 tunnel_id 1 session_id 17185 peer_session_id 4660
ip netns exec lisp ip link set t0 up
else
./l2tp.app1 &
echo $! > l2tp.app1.pid
./l2tp.app2 &
echo $! > l2tp.app2.pid
sleep 0.2
ip netns exec app1 ifconfig t0 10.0.0.1/24 up
ip netns exec app2 ifconfig t0 10.0.0.2/24 up
fi
}


teardown() {
kill -9 `cat l2tp.app1.pid`; rm l2tp.app1.pid
kill -9 `cat l2tp.app2.pid`; rm l2tp.app2.pid
ip netns del r2
ip netns del app1
ip netns del app2
ip netns del lisp
}


action=$1; [ "$action" ] || action=bringup
$action
1 change: 1 addition & 0 deletions src/program/lisper/dev-env/net-teardown
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./net-bringup teardown
1 change: 1 addition & 0 deletions src/program/lisper/dev-env/syscall
1 change: 1 addition & 0 deletions src/program/lisper/dev-env/syscall.lua

0 comments on commit 508f931

Please sign in to comment.