Permalink
Browse files

Merge PR #1060 (v2016.11 release) into master

  • Loading branch information...
2 parents eb9d141 + c47074d commit bd4ec1c041b53a4fdfaa4b18142f88eeb77207ac @eugeneia eugeneia committed Nov 7, 2016
Showing 322 changed files with 11,970 additions and 3,031 deletions.
View
@@ -22,6 +22,11 @@ join the [snabb-devel mailing
list](https://groups.google.com/forum/#!forum/snabb-devel) and read
on.
+## Documentation
+
+- [API Reference](http://snabbco.github.io/)
+- [Contributor Hints](https://github.com/snabbco/snabb/blob/master/CONTRIBUTING.md#hints-for-contributors)
+
## How does it work?
Snabb is written using these main techniques:
@@ -119,4 +124,3 @@ Here are the ways you can get involved:
- Join the [snabb-devel mailing list](https://groups.google.com/forum/#!forum/snabb-devel).
- Send a mail to [introduce yourself](https://groups.google.com/forum/#!searchin/snabb-devel/introduce/snabb-devel/d8t6hGClnQY/flztyLiIGzoJ) to the community (don't be shy!).
- Create your very own application: [Getting Started](src/doc/getting-started.md).
-
@@ -347,6 +347,17 @@ function C.sched_setparam(pid, param)
return syscall(sys.sched_setparam, int(pid), void(param))
end
+function C.get_mempolicy(mode, mask, maxnode, addr, flags)
+ return syscall(sys.get_mempolicy, void(mode), void(mask), ulong(maxnode), ulong(addr), ulong(flags))
+end
+function C.set_mempolicy(mode, mask, maxnode)
+ return syscall(sys.set_mempolicy, int(mode), void(mask), ulong(maxnode))
+end
+
+function C.migrate_pages(pid, maxnode, from, to)
+ return syscall(sys.migrate_pages, int(pid), ulong(maxnode), void(from), void(to))
+end
+
-- in librt for glibc but use syscalls instead of loading another library
function C.clock_nanosleep(clk_id, flags, req, rem)
return syscall(sys.clock_nanosleep, int(clk_id), int(flags), void(req), void(rem))
@@ -684,7 +695,7 @@ C.gettimeofday = ffi.C.gettimeofday
--function C.gettimeofday(tv, tz) return syscall(sys.gettimeofday, void(tv), void(tz)) end
-- glibc does not provide getcpu; it is however VDSO
-function C.getcpu(cpu, node, tcache) return syscall(sys.getcpu, void(node), void(node), void(tcache)) end
+function C.getcpu(cpu, node, tcache) return syscall(sys.getcpu, void(cpu), void(node), void(tcache)) end
-- time is VDSO but not really performance critical; does not exist for some architectures
if sys.time then
function C.time(t) return syscall(sys.time, void(t)) end
@@ -3149,6 +3149,23 @@ c.IPT_SO_GET = strflag {
REVISION_TARGET = IPT_BASE_CTL + 3,
}
+c.MPOL_MODE = multiflags {
+ DEFAULT = 0,
+ PREFERRED = 1,
+ BIND = 2,
+ INTERLEAVE = 3,
+ LOCAL = 4,
+ -- TODO: Only the following two flags can be ORed.
+ STATIC_NODES = 0x80000000,
+ RELATIVE_NODES = 0x40000000,
+}
+
+c.MPOL_FLAG = multiflags {
+ NODE = 1,
+ ADDR = 2,
+ MEMS_ALLOWED = 4
+}
+
c.SCHED = multiflags {
NORMAL = 0,
OTHER = 0,
@@ -457,6 +457,25 @@ function S.sched_setaffinity(pid, mask, len) -- note len last as rarely used
return retbool(C.sched_setaffinity(pid or 0, len or s.cpu_set, mktype(t.cpu_set, mask)))
end
+function S.get_mempolicy(mode, mask, addr, flags)
+ mode = mode or t.int1()
+ mask = mktype(t.bitmask, mask)
+ local ret, err = C.get_mempolicy(mode, mask.mask, mask.size, addr or 0, c.MPOL_FLAG[flags])
+ if ret == -1 then return nil, t.error(err or errno()) end
+ return { mode=mode[0], mask=mask }
+end
+function S.set_mempolicy(mode, mask)
+ mask = mktype(t.bitmask, mask)
+ return retbool(C.set_mempolicy(c.MPOL_MODE[mode], mask.mask, mask.size))
+end
+
+function S.migrate_pages(pid, from, to)
+ from = mktype(t.bitmask, from)
+ to = mktype(t.bitmask, to)
+ assert(from.size == to.size, "incompatible nodemask sizes")
+ return retbool(C.migrate_pages(pid or 0, from.size, from.mask, to.mask))
+end
+
function S.sched_get_priority_max(policy) return retnum(C.sched_get_priority_max(c.SCHED[policy])) end
function S.sched_get_priority_min(policy) return retnum(C.sched_get_priority_min(c.SCHED[policy])) end
@@ -1002,6 +1002,74 @@ mt.cpu_set = {
addtype(types, "cpu_set", "struct cpu_set_t", mt.cpu_set)
+local ulong_bit_count = ffi.sizeof('unsigned long') * 8
+local function ulong_index_and_bit(n)
+ local i = math.floor(n / ulong_bit_count)
+ local b = bit.lshift(1ULL, n - i * ulong_bit_count)
+ return i, b
+end
+
+mt.bitmask = {
+ index = {
+ zero = function(mask) ffi.fill(mask, s.bitmask) end,
+ set = function(mask, node)
+ if type(node) == "table" then -- table is an array of node numbers eg {1, 2, 4}
+ for i = 1, #node do mask:set(node[i]) end
+ return mask
+ end
+ if node >= mask.size then error("numa node too large " .. node) end
+ local i, b = ulong_index_and_bit(node)
+ mask.mask[i] = bit.bor(mask.mask[i], b)
+ return mask
+ end,
+ clear = function(mask, node)
+ if type(node) == "table" then -- table is an array of node numbers eg {1, 2, 4}
+ for i = 1, #node do mask:clear(node[i]) end
+ return mask
+ end
+ if node < mask.size then
+ local i, b = ulong_index_and_bit(node)
+ mask.mask[i] = bit.band(mask.mask[i], bit.bnot(b))
+ end
+ return mask
+ end,
+ get = function(mask, node)
+ local i, b = ulong_index_and_bit(node)
+ if node >= mask.size then return false end
+ return bit.band(mask.mask[i], b) ~= 0
+ end,
+ },
+ __index = function(mask, k)
+ if mt.bitmask.index[k] then return mt.bitmask.index[k] end
+ if type(k) == "number" then return mask:get(k) end
+ error("invalid index " .. k)
+ end,
+ __newindex = function(mask, k, v)
+ if type(k) ~= "number" then error("invalid index " .. k) end
+ if v then mask:set(k) else mask:clear(k) end
+ end,
+ __new = function(tp, tab, size)
+ -- Round size to multiple of ulong bit count.
+ if size then
+ size = bit.band(size + ulong_bit_count - 1, bit.bnot(ulong_bit_count - 1))
+ else
+ size = ulong_bit_count
+ end
+ local mask = ffi.new(tp, size / ulong_bit_count, size)
+ if tab then mask:set(tab) end
+ return mask
+ end,
+ __tostring = function(mask)
+ local tab = {}
+ for i = 0, tonumber(mask.size - 1) do
+ if mask:get(i) then tab[#tab + 1] = i end
+ end
+ return "{" .. table.concat(tab, ",") .. "}"
+ end,
+}
+
+addtype_var(types, "bitmask", "struct {unsigned long size; unsigned long mask[?];}", mt.bitmask)
+
mt.mq_attr = {
index = {
flags = function(mqa) return tonumber(mqa.mq_flags) end,
View
@@ -355,8 +355,8 @@ packets are allocated and freed.
```
struct packet {
- uint8_t data[packet.max_payload];
uint16_t length;
+ uint8_t data[packet.max_payload];
};
```
@@ -393,18 +393,21 @@ error is raised if there is not enough space in *packet* to accomodate
— Function **packet.prepend** *packet*, *pointer*, *length*
Prepends *length* bytes starting at *pointer* to the front of
-*packet*. An error is raised if there is not enough space in *packet* to
+*packet*, taking ownership of the packet and returning a new packet.
+An error is raised if there is not enough space in *packet* to
accomodate *length* additional bytes.
— Function **packet.shiftleft** *packet*, *length*
-Truncates *packet* by *length* bytes from the front. *Length* must be less than
-or equal to `length` of *packet*.
+Take ownership of *packet*, truncate it by *length* bytes from the
+front, and return a new packet. *Length* must be less than or equal to
+`length` of *packet*.
— Function **packet.shiftright** *packet*, *length*
-Moves *packet* payload to the right by *length* bytes, growing *packet* by
-*length*. The sum of *length* and `length` of *packet* must be less than or
+Take ownership of *packet*, moves *packet* payload to the right by
+*length* bytes, growing *packet* by *length*. Returns a new packet.
+The sum of *length* and `length` of *packet* must be less than or
equal to `packet.max_payload`.
— Function **packet.from_pointer** *pointer*, *length*
@@ -41,18 +41,18 @@ names. The default is no split-horizon groups.
*Optional*. The configuration of the actual bridge implementation.
-# Flooding bridge (apps.bridge.flooding)
+## Flooding bridge (apps.bridge.flooding)
The flooding `bridge` app implements the simplest possible bridge, which
floods a packet arriving on an input port to all output ports within its
scope according to the split-horizon topology.
-## Configuration
+### Configuration
The flooding `bridge` app ignores the *config* key of its configuration.
-# Learning bridge (apps.bridge.learning)
+## Learning bridge (apps.bridge.learning)
The learning `bridge` app implements a *learning bridge* using a
custom hash table to store the set of MAC source addresses of packets
@@ -63,7 +63,7 @@ flooded to all output ports. Multicast MAC addresses are always
flooded to all output ports associated with the input port. The
scoping rules according to the split-horizon topology apply unchanged.
-## Configuration
+### Configuration
The learning `bridge` app accepts a table as the value of the *config*
key of its configuration. The following keys are defined:
@@ -2,17 +2,13 @@
## AES128gcm (apps.ipsec.esp)
-The `AES128gcm` implements an ESP transport tunnel using the AES-GCM-128
+The `AES128gcm` implements ESP in transport mode using the AES-GCM-128
cipher. It encrypts packets received on its `decapsulated` port and transmits
them on its `encapsulated` port, and vice-versa. Packets arriving on the
`decapsulated` port must have an IPv6 header, and packets arriving on the
`encapsulated` port must have an IPv6 header followed by an ESP header,
otherwise they will be discarded.
-References:
-
- - `lib.ipsec.esp`
-
DIAGRAM: AES128gcm
+-----------+
encapsulated | |
@@ -26,19 +22,60 @@ References:
<-------|---/ /------->
\-----/ decapsulated
+References:
+
+ - `lib.ipsec.esp`
+
### Configuration
The `AES128gcm` app accepts a table as its configuration argument. The
following keys are defined:
— Key **spi**
-*Required*. Security Parameter Index. A 32 bit integer.
+*Required*. A 32 bit integer denoting the “Security Parameters Index” as
+specified in RFC 4303.
+
+— Key **transmit_key**
+
+*Required*. Hexadecimal string of 32 digits (two digits for each byte) that
+denotes a 128-bit AES key as specified in RFC 4106 used for the encryption of
+outgoing packets.
+
+— Key **transmit_salt**
+
+*Required*. Hexadecimal string of eight digits (two digits for each byte) that
+denotes four bytes of salt as specified in RFC 4106 used for the encryption of
+outgoing packets.
+
+— Key **receive_key**
+
+*Required*. Hexadecimal string of 32 digits (two digits for each byte) that
+denotes a 128-bit AES key as specified in RFC 4106 used for the decryption of
+incoming packets.
+
+— Key **receive_salt**
+
+*Required*. Hexadecimal string of eight digits (two digits for each byte) that
+denotes four bytes of salt as specified in RFC 4106 used for the decryption of
+incoming packets.
+
+— Key **receive_window**
+
+*Optional*. Minimum width of the window in which out of order packets are
+accepted as specified in RFC 4303. The default is 128.
+
+— Key **resync_threshold**
+
+*Optional*. Number of consecutive packets allowed to fail decapsulation before
+attempting “Re-synchronization” as specified in RFC 4303. The default is 1024.
-— Key **key**
+— Key **resync_attempts**
-*Required*. 20 bytes in form of a hex encoded string.
+*Optional*. Number of attempts to re-synchronize a packet that triggered
+“Re-synchronization” as specified in RFC 4303. The default is 8.
-— Key **replay_window**
+— Key **auditing**
-*Optional*. Size of the “Anti-Replay Window”. Defaults to 128.
+*Optional.* A boolean value indicating whether to enable or disable “Auditing”
+as specified in RFC 4303. The default is `nil` (no auditing).
@@ -10,7 +10,15 @@ local C = require("ffi").C
AES128gcm = {
config = {
- spi = {required=true}, key = {required=true}, window_size = {}
+ spi = {required=true},
+ transmit_key = {required=true},
+ transmit_salt = {required=true},
+ receive_key = {required=true},
+ receive_salt = {required=true},
+ receive_window = {},
+ resync_threshold = {},
+ resync_attempts = {},
+ auditing = {}
},
shm = {
txerrors = {counter}, rxerrors = {counter}
@@ -19,17 +27,22 @@ AES128gcm = {
function AES128gcm:new (conf)
local self = {}
+ assert(conf.transmit_salt ~= conf.receive_salt,
+ "Refusing to operate with transmit_salt == receive_salt")
self.encrypt = esp.esp_v6_encrypt:new{
mode = "aes-128-gcm",
spi = conf.spi,
- keymat = conf.key:sub(1, 32),
- salt = conf.key:sub(33, 40)}
+ key = conf.transmit_key,
+ salt = conf.transmit_salt}
self.decrypt = esp.esp_v6_decrypt:new{
mode = "aes-128-gcm",
spi = conf.spi,
- keymat = conf.key:sub(1, 32),
- salt = conf.key:sub(33, 40),
- window_size = conf.replay_window}
+ key = conf.receive_key,
+ salt = conf.receive_salt,
+ window_size = conf.receive_window,
+ resync_threshold = conf.resync_threshold,
+ resync_attempts = conf.resync_attempts,
+ auditing = conf.auditing}
return setmetatable(self, {__index = AES128gcm})
end
@@ -123,7 +123,6 @@ function nd_light:new (conf)
-- Prepare packet for solicitation of next hop
local nh = { nsent = 0 }
local dgram = datagram:new()
- nh.packet = dgram:packet()
local sol_node_mcast = ipv6:solicited_node_mcast(conf.next_hop)
local ipv6 = ipv6:new({ next_header = 58, -- ICMP6
hop_limit = 255,
@@ -148,6 +147,7 @@ function nd_light:new (conf)
dgram:push(ethernet:new({ src = conf.local_mac,
dst = ethernet:ipv6_mcast(sol_node_mcast),
type = 0x86dd }))
+ nh.packet = dgram:packet()
dgram:free()
-- Timer for retransmits of neighbor solicitations
@@ -176,7 +176,6 @@ function nd_light:new (conf)
-- Prepare packet for solicited neighbor advertisement
local sna = {}
dgram = datagram:new()
- sna.packet = dgram:packet()
-- Leave dst address unspecified. It will be set to the source of
-- the incoming solicitation
ipv6 = ipv6:new({ next_header = 58, -- ICMP6
@@ -197,6 +196,8 @@ function nd_light:new (conf)
-- Leave dst address unspecified.
dgram:push(ethernet:new({ src = conf.local_mac,
type = 0x86dd }))
+ sna.packet = dgram:packet()
+
-- Parse the headers we want to modify later on from our template
-- packet.
dgram = dgram:new(sna.packet, ethernet)
Oops, something went wrong.

0 comments on commit bd4ec1c

Please sign in to comment.