Skip to content

Commit

Permalink
apps.rss.rss: Add VLAN match capability
Browse files Browse the repository at this point in the history
To overcome a limitation of the pf module, add a special syntax to the
filter string that implements VLAN matching against metadata. This can
also be combined with a regulat BPF filter.
  • Loading branch information
alexandergall committed May 5, 2020
1 parent 15ef82b commit afbe2bd
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
27 changes: 21 additions & 6 deletions src/apps/rss/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,27 @@ the following set of extensions.

The output links can be grouped into equivalence classes with respect
to matching conditions in terms of arbitrary pflang expressions as
provided by the `pf` module. Matching packets are only distributed to
the output links that belong to the equivalence class. By default, a
single equivalence class exists which matches all packets. It is
special in the sense that the matching condition cannot be expressed
in pflang. This default class is the only one that can receive non-IP
packets.
provided by the `pf` module. Because the current implementation of the
`pf` module does not implement the `vlan` primitive, an auxiliary
construct is needed to match on the VLAN tag if required. Apart from a
regular BPF expression, the `rss` module also accepts a string of the
form

```
VLAN <vid1> <vid2> ... [ BPF <string> ]
```

where `<vidn>` are numbers representig VLAN IDs. This expression
matches a packet that carries any of the given VLAN tags. If the
expression also contains the keyword `BPF` followed by a regular BPF
expression, the packet must also match that expression to be mapped to
this equivalence class.

Matching packets are only distributed to the output links that belong
to the equivalence class. By default, a single equivalence class
exists which matches all packets. It is special in the sense that the
matching condition cannot be expressed in pflang. This default class
is the only one that can receive non-IP packets.

Classes are specified in an explicit order when an instance of the
`rss` app is created. The default class is created implicitly as the
Expand Down
36 changes: 33 additions & 3 deletions src/apps/rss/rss.lua
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,38 @@ function rss:new (config)
assert(not classes[config.name],
"Duplicate filter class: "..config.name)
classes[config.name] = true
add_class(config.name, pf.compile_filter(config.filter),
config.continue)
local match_fn
local vlans = config.filter:match("^VLAN (.*)$")
if vlans then
local expr = ""
local pf_fn
for vlan in vlans:split("%s") do
if (vlan:match("^(%d+)$")) then
expr = expr.."md.vlan == "..vlan.." or "
elseif vlan == "BPF" then
local bpf = config.filter:match("BPF (.*)")
pf_fn = pf.compile_filter(bpf)
break
else
error(string.format("illegal VLAN ID in filter expression of "..
"class %s: %s", class, vlan))
end
end
expr = expr.."nil"
match_fn = loadstring("return function(md) return "..expr.." end")()
if pf_fn then
match_fn_aux = match_fn
match_fn = function(md)
return match_fn_aux(md) and pf_fn(md.filter_start, md.filter_length)
end
end
else
pf_fn = pf.compile_filter(config.filter)
match_fn = function(md)
return pf_fn(md.filter_start, md.filter_length)
end
end
add_class(config.name, match_fn, config.continue)
end
if config.default_class then
-- Catch-all default filter
Expand Down Expand Up @@ -354,7 +384,7 @@ function rss:push_with_vlan(link, vlan)
for _ = 1, nreadable(queue) do
local p = receive(queue)
local md = mdget(p)
if class.match_fn(md.filter_start, md.filter_length) then
if class.match_fn(md) then
md.ref = md.ref + 1
transmit(class.input, p)
if class.continue then
Expand Down

0 comments on commit afbe2bd

Please sign in to comment.