Skip to content

Commit 771b55c

Browse files
committed
Merge PR #1370 (v2018.09 release) into master
2 parents 732eae9 + a154efc commit 771b55c

File tree

80 files changed

+875
-278
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+875
-278
lines changed

.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2018.06
1+
2018.09

src/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ following keys are recognized:
258258
printed.
259259

260260

261+
— Function **engine.stop**
262+
263+
Stop all apps in the engine by loading an empty configuration.
264+
261265
— Function **engine.now**
262266

263267
Returns monotonic time in seconds as a floating point number. Suitable

src/apps/bridge/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ arriving on a free input port may be forwarded to all other output
99
ports. Packets arriving on an input port that belongs to a split-horizon
1010
group are never forwarded to any output port belonging to the same
1111
split-horizon group. There are two `bridge` implementations available:
12-
`apps.bridge.flooding` and apps.bridge.learning`.
12+
`apps.bridge.flooding` and `apps.bridge.learning`.
1313

1414
DIAGRAM: bridge
1515
+----------+

src/apps/example/asm.dasl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ local asm_status = ffi.new("uint32_t[1]")
1919
|.arch x64
2020
|.actionlist actions
2121
local Dst = dasm.new(actions)
22-
| mov dword [asm_status], 0xdeadbeef
22+
| mov64 rax, asm_status
23+
| mov dword [rax], 0xdeadbeef
2324
| ret
2425
code = Dst:build() -- assign to 'code' to avoid machine code being GC'd
2526
fptr = ffi.cast("void(*)()", code)

src/apps/ipfix/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ included). The exporter can produce output in either the standard RFC
1010

1111
DIAGRAM: IPFIX
1212
+-----------+
13+
| |
1314
input ---->* IPFIX *----> output
15+
| |
1416
+-----------+
1517

1618
See the `snabb ipfix probe` command-line interface for a program built

src/apps/vhost/vhost_user.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ enum {
2121
VHOST_USER_SET_VRING_KICK = 12,
2222
VHOST_USER_SET_VRING_CALL = 13,
2323
VHOST_USER_SET_VRING_ERR = 14,
24+
VHOST_USER_GET_PROTOCOL_FEATURES = 15,
25+
VHOST_USER_SET_PROTOCOL_FEATURES = 16,
26+
VHOST_USER_GET_QUEUE_NUM = 17,
27+
VHOST_USER_SET_VRING_ENABLE = 18,
2428
VHOST_USER_MAX
2529
};
2630

src/apps/vhost/vhost_user.lua

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,21 +111,25 @@ end
111111

112112
-- Table of request code -> name of handler method
113113
handler_names = {
114-
[C.VHOST_USER_NONE] = 'none',
115-
[C.VHOST_USER_GET_FEATURES] = 'get_features',
116-
[C.VHOST_USER_SET_FEATURES] = 'set_features',
117-
[C.VHOST_USER_SET_OWNER] = 'set_owner',
118-
[C.VHOST_USER_RESET_OWNER] = 'reset_owner',
119-
[C.VHOST_USER_SET_MEM_TABLE] = 'set_mem_table',
120-
[C.VHOST_USER_SET_LOG_BASE] = 'set_log_base',
121-
[C.VHOST_USER_SET_LOG_FD] = 'set_log_fd',
122-
[C.VHOST_USER_SET_VRING_NUM] = 'set_vring_num',
123-
[C.VHOST_USER_SET_VRING_ADDR] = 'set_vring_addr',
124-
[C.VHOST_USER_SET_VRING_BASE] = 'set_vring_base',
125-
[C.VHOST_USER_GET_VRING_BASE] = 'get_vring_base',
126-
[C.VHOST_USER_SET_VRING_KICK] = 'set_vring_kick',
127-
[C.VHOST_USER_SET_VRING_CALL] = 'set_vring_call',
128-
[C.VHOST_USER_SET_VRING_ERR] = 'set_vring_err'
114+
[C.VHOST_USER_NONE] = 'none',
115+
[C.VHOST_USER_GET_FEATURES] = 'get_features',
116+
[C.VHOST_USER_SET_FEATURES] = 'set_features',
117+
[C.VHOST_USER_SET_OWNER] = 'set_owner',
118+
[C.VHOST_USER_RESET_OWNER] = 'reset_owner',
119+
[C.VHOST_USER_SET_MEM_TABLE] = 'set_mem_table',
120+
[C.VHOST_USER_SET_LOG_BASE] = 'set_log_base',
121+
[C.VHOST_USER_SET_LOG_FD] = 'set_log_fd',
122+
[C.VHOST_USER_SET_VRING_NUM] = 'set_vring_num',
123+
[C.VHOST_USER_SET_VRING_ADDR] = 'set_vring_addr',
124+
[C.VHOST_USER_SET_VRING_BASE] = 'set_vring_base',
125+
[C.VHOST_USER_GET_VRING_BASE] = 'get_vring_base',
126+
[C.VHOST_USER_SET_VRING_KICK] = 'set_vring_kick',
127+
[C.VHOST_USER_SET_VRING_CALL] = 'set_vring_call',
128+
[C.VHOST_USER_SET_VRING_ERR] = 'set_vring_err',
129+
[C.VHOST_USER_GET_PROTOCOL_FEATURES] = 'get_protocol_features',
130+
[C.VHOST_USER_SET_PROTOCOL_FEATURES] = 'set_protocol_features',
131+
[C.VHOST_USER_GET_QUEUE_NUM] = 'get_queue_num',
132+
[C.VHOST_USER_SET_VRING_ENABLE] = 'set_vring_enable'
129133
}
130134

131135
-- Process all vhost_user requests from QEMU.
@@ -178,6 +182,26 @@ function VhostUser:set_features (msg)
178182
self.dev:set_features(features)
179183
end
180184

185+
function VhostUser:get_protocol_features (msg)
186+
msg.u64 = 0ULL -- no extensions supported for now
187+
msg.size = ffi.sizeof("uint64_t")
188+
self:reply(msg)
189+
end
190+
191+
function VhostUser:set_protocol_features (msg)
192+
-- ignore protocol features for now (FIXME)
193+
end
194+
195+
function VhostUser:get_queue_num (msg)
196+
-- ignore for now (FIXME)
197+
end
198+
199+
-- Handle VHOST_USER_SET_VRING_ENABLE, which explicitly enables/disables the
200+
-- ring (this msg is only used if VHOST_USER_F_PROTOCOL_FEATURES is used)
201+
function VhostUser:set_vring_enable (msg)
202+
self.vhost_ready = msg.u64 ~= 0
203+
end
204+
181205
-- Feature cache: A kludge to be compatible with a "QEMU reconnect" patch.
182206
--
183207
-- QEMU upstream (circa 2015) does not support the vhost-user device

src/core/app.lua

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ function configure (new_config)
137137
counter.add(configs)
138138
end
139139

140+
141+
-- Stop all apps by loading an empty configuration.
142+
function stop ()
143+
configure(config.new())
144+
end
145+
140146
-- Removes the claim on a name, freeing it for other programs.
141147
--
142148
-- This relinquish a claim on a name if one exists. if the name does not
@@ -724,6 +730,11 @@ function selftest ()
724730
main({duration = 4, report = {showapps = true}})
725731
assert(app_table.app3 ~= orig_app3) -- should be restarted
726732

733+
-- Check engine stop
734+
assert(not lib.equal(app_table, {}))
735+
engine.stop()
736+
assert(lib.equal(app_table, {}))
737+
727738
-- Check one can't unclaim a name if no name is claimed.
728739
assert(not pcall(unclaim_name))
729740

src/core/lib.lua

Lines changed: 2 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -457,84 +457,8 @@ function root_check (message)
457457
end
458458
end
459459

460-
-- Simple token bucket for rate-limiting of events. A token bucket is
461-
-- created through
462-
--
463-
-- local tb = token_bucket_new({ rate = <rate> })
464-
--
465-
-- where <rate> is the maximum allowed rate in Hz, which defaults to
466-
-- 10. Conceptually, <rate> tokens are added to the bucket each
467-
-- second and the bucket can hold no more than <rate> tokens but at
468-
-- least one.
469-
--
470-
471-
local token_bucket = {}
472-
token_bucket.mt = { __index = token_bucket }
473-
token_bucket.default = { rate = 10 }
474-
function token_bucket_new (config)
475-
local config = config or token_bucket.default
476-
local tb = setmetatable({}, token_bucket.mt)
477-
tb:rate(config.rate or token_bucket.default.rate)
478-
tb._tstamp = C.get_monotonic_time()
479-
return tb
480-
end
481-
482-
-- The rate can be set with the rate() method at any time, which fills
483-
-- the token bucket an also returns the previous value. If called
484-
-- with a nil argument, returns the currently configured rate.
485-
function token_bucket:rate (rate)
486-
if rate ~= nil then
487-
local old_rate = self._rate
488-
self._rate = rate
489-
self._max_tokens = math.max(rate, 1)
490-
self._tokens = self._max_tokens
491-
return old_rate
492-
end
493-
return self._rate
494-
end
495-
496-
function token_bucket:_update (tokens)
497-
local now = C.get_monotonic_time()
498-
local tokens = math.min(self._max_tokens, tokens + self._rate*(now-self._tstamp))
499-
self._tstamp = now
500-
return tokens
501-
end
502-
503-
-- The take() method tries to remove <n> tokens from the bucket. If
504-
-- enough tokens are available, they are subtracted from the bucket
505-
-- and a true value is returned. Otherwise, the bucket remains
506-
-- unchanged and a false value is returned. For efficiency, the
507-
-- tokens accumulated since the last call to take() or can_take() are
508-
-- only added if the request can not be fulfilled by the state of the
509-
-- bucket when the method is called.
510-
function token_bucket:take (n)
511-
local n = n or 1
512-
local result = false
513-
local tokens = self._tokens
514-
if n > tokens then
515-
tokens = self:_update(tokens)
516-
end
517-
if n <= tokens then
518-
tokens = tokens - n
519-
result = true
520-
end
521-
self._tokens = tokens
522-
return result
523-
end
524-
525-
-- The can_take() method returns a true value if the bucket contains
526-
-- at least <n> tokens, false otherwise. The bucket is updated in a
527-
-- layz fashion as described for the take() method.
528-
function token_bucket:can_take (n)
529-
local n = n or 1
530-
local tokens = self._tokens
531-
if n <= tokens then
532-
return true
533-
end
534-
tokens = self:_update(tokens)
535-
self._tokens = tokens
536-
return n <= tokens
537-
end
460+
-- Backward compatibility
461+
token_bucket_new = require("lib.token_bucket").new
538462

539463
-- Simple rate-limited logging facility. Usage:
540464
--

src/core/memory.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,12 @@ function allocate_huge_page (size, persistent)
146146
local fd = syscall.open(tmpfile, "creat, rdwr", "RWXU")
147147
assert(fd, "create hugetlb")
148148
assert(syscall.ftruncate(fd, size), "ftruncate")
149-
local tmpptr = syscall.mmap(nil, size, "read, write", "shared, hugetlb", fd, 0)
149+
local tmpptr = syscall.mmap(nil, size, "read, write", "shared", fd, 0)
150150
assert(tmpptr, "mmap hugetlb")
151151
assert(syscall.mlock(tmpptr, size))
152152
local phys = resolve_physical(tmpptr)
153153
local virt = bit.bor(phys, tag)
154-
local ptr = syscall.mmap(virt, size, "read, write", "shared, hugetlb, fixed", fd, 0)
154+
local ptr = syscall.mmap(virt, size, "read, write", "shared, fixed", fd, 0)
155155
local filename = ("/var/run/snabb/hugetlbfs/%012x.dma"):format(tonumber(phys))
156156
if persistent then
157157
assert(syscall.rename(tmpfile, filename))
@@ -160,6 +160,7 @@ function allocate_huge_page (size, persistent)
160160
else
161161
assert(syscall.unlink(tmpfile))
162162
end
163+
syscall.munmap(tmpptr, size)
163164
syscall.close(fd)
164165
return ptr, filename
165166
end

src/lib/README.ctable.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ Optional entries that may be present in the *parameters* table include:
5252
2. Defaults to 0.9, for a 90% maximum occupancy ratio.
5353
* `min_occupancy_rate`: Minimum ratio of `occupancy/size`. Removing an
5454
entry from an "empty" table will shrink the table.
55+
* `resize_callback`: An optional function that is called after the
56+
table has been resized. The function is called with two arguments:
57+
the ctable object and the old size. By default, no callback is used.
5558

5659
— Function **ctable.load** *stream* *parameters*
5760

src/lib/README.token_bucket.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
### Token Bucket (lib.token_bucket)
2+
3+
This module implements a [token
4+
bucket](https://en.wikipedia.org/wiki/Token_bucket) for rate-limiting
5+
of arbitrary events. The bucket is filled with tokens at a constant
6+
rate up to a given maximum called the *burst_size*. Tokens are added
7+
and removed in integer quantities. An event can only take place if at
8+
least one token is available. A burst of back-to-back events is
9+
allowed to happen by consuming all available tokens at a given point
10+
in time. The maximum size of such a burst is determined by the
11+
capacity of the bucket, hence the name *burst_size*.
12+
13+
The token bucket is updated in a lazy fashion, i.e. only when a
14+
request for tokens cannot be satisfied immediately.
15+
16+
By default, a token bucket uses the `rdtsc` time source via the
17+
[`tsc`](./README.tsc.md) module to minimise overhead. To override,
18+
the `default_source` parameter of the `tsc` module must be set
19+
to the desired value.
20+
21+
#### Functions
22+
23+
— Function **new** *config*
24+
25+
Creates an instance of a token bucket. The required *config* argument
26+
must be a table with the following keys.
27+
28+
— Key **rate**
29+
30+
*Required*. The rate in units of Hz at which tokens are placed in the
31+
bucket as an arbitrary floating point number larger than zero.
32+
33+
— Key **burst_size**
34+
35+
*Optional*. The maximum number of tokens that can be stored in the
36+
bucket. The default is **rate** tokens, i.e. the amount of tokens
37+
accumulated over one second rounded up to the next integer.
38+
39+
#### Methods
40+
41+
The object returned by the **new** function provides the following
42+
methods.
43+
44+
— Method **token_bucket:set** [*rate*], [*burst_size*]
45+
46+
Set the rate and burst size to the values *rate* and *burst_size*,
47+
respectively, and fill the bucket to capacity. If *rate* is `nil`,
48+
the rate remains unchanged. If *burst_size* is `nil`, the burst size
49+
is set to the number of tokens that will be accumulated over one
50+
second with the new rate (like in the **new** function).
51+
52+
— Method **token_bucket:get**
53+
54+
Returns the current rate and burst size.
55+
56+
— Method **token_bucket:can_take** [*n*]
57+
58+
Returns `true` if at least *n* tokens are available, `false`
59+
otherwise. If *n* is `nil`, the bucket is checked for a single token.
60+
61+
— Method **token_bucket:take** [*n*]
62+
63+
If at least *n* tokens are available, they are removed from the bucket
64+
and the method returns `true`. Otherwise, the bucket remains
65+
unchanged and `false` is returned. If *n* is `nil`, the bucket is
66+
checked for a single token.
67+
68+
— Method **token_bucket:take_burst**
69+
70+
Takes all available tokens from the bucket and returns that number.

0 commit comments

Comments
 (0)