1 ---------------------------------
5 ---------------------------------
9 local dpdkc = require
"dpdkc"
10 local device = require
"device"
11 local
ffi = require
"ffi"
12 local dpdk = require
"dpdk"
13 local mbitmask = require
"bitmask"
14 local err = require
"error"
19 local dev = device.__devicePrototype
21 local deviceDependent = {}
22 deviceDependent[device.PCI_ID_X540] = require
"filter_ixgbe"
23 deviceDependent[device.PCI_ID_X520] = require
"filter_ixgbe"
24 deviceDependent[device.PCI_ID_82599] = require
"filter_ixgbe"
25 deviceDependent[device.PCI_ID_XL710] = require
"filter_i40e"
28 function dev:l2Filter(etype, queue)
29 if type(queue) == "table" then
30 if queue.dev.
id ~= self.
id then
31 error("Queue must belong to the device being configured")
35 local fun = deviceDependent[self:getPciId()].l2Filter
37 return fun(self, etype, queue)
39 errorf("l2Filter not supported, or not yet implemented for this device")
43 --- Installs a 5tuple filter on the device.
44 --- Matching packets will be redirected into the specified rx queue
45 --- NOTE: this is currently only tested for X540 NICs, and will probably also
46 --- work for 82599 and other ixgbe NICs. Use on other NICs might result in
47 --- undefined behavior.
48 --- @param filter A table describing the filter. Possible fields are
49 --- src_ip : Sourche IPv4 Address
50 --- dst_ip : Destination IPv4 Address
51 --- src_port : Source L4 port
52 --- dst_port : Destination L4 port
53 --- l4protocol: L4 Protocol type
55 --- If a non supported type is given, the filter will only match on
56 --- protocols, which are not supported.
58 --- If a field is not present, or nil, the filter will ignore this field when
59 --- checking for a match.
60 --- @param queue RX Queue, where packets, matching this filter will be redirected
61 --- @param priority
optional (default = 1) The priority of this filter rule.
62 --- 7 is the highest priority and 1 the lowest priority.
66 return fun(self, filter, queue, priority)
72 --- Filter PTP time stamp packets by inspecting the PTP version and type field.
73 --- Packets with PTP version 2 are matched with this filter.
75 --- @param offset the offset of the PTP version field
76 --- @param ntype the PTP type to look for, default = 0
77 --- @param ver the PTP version to look for, default = 2
79 -- TODO: dpdk only allows to change this at
init time
80 -- however, I think changing the flex-byte offset field in the FDIRCTRL register can be changed at run time here
81 -- (as the fdir table needs to be cleared anyways which is the only precondition for changing this)
82 if type(queue) == "table" then
87 error("other offsets are not yet supported")
91 local value = value or bit.lshift(ver, 8) + mtype
92 local filter =
ffi.
new("struct rte_fdir_filter")
93 filter.flex_bytes = value
94 filter.l4type = dpdkc.RTE_FDIR_L4TYPE_UDP
95 local mask =
ffi.
new("struct rte_fdir_masks")
97 dpdkc.rte_eth_dev_fdir_set_masks(self.
id, mask)
98 dpdkc.rte_eth_dev_fdir_add_perfect_filter(self.
id, filter, 1, queue, 0)
102 -- FIXME:
add protp mask!!
104 struct mg_5tuple_rule {
107 uint8_t ip_src_prefix;
109 uint8_t ip_dst_prefix;
111 uint16_t port_src_range;
113 uint16_t port_dst_range;
117 struct rte_acl_ctx * mg_5tuple_create_filter(
int socket_id, uint32_t num_rules);
118 void mg_5tuple_destruct_filter(
struct rte_acl_ctx * acl);
119 int mg_5tuple_add_rule(
struct rte_acl_ctx * acx,
struct mg_5tuple_rule * mgrule, int32_t priority, uint32_t category_mask, uint32_t value);
120 int mg_5tuple_build_filter(
struct rte_acl_ctx * acx, uint32_t num_categories);
121 int mg_5tuple_classify_burst(
122 struct rte_acl_ctx * acx,
123 struct rte_mbuf **pkts,
124 struct mg_bitmask* pkts_mask,
125 uint32_t num_categories,
126 uint32_t num_real_categories,
127 struct mg_bitmask** result_masks,
128 uint32_t ** result_entries
130 uint32_t mg_5tuple_get_results_multiplier();
133 local mg_filter_5tuple = {}
134 mod.mg_filter_5tuple = mg_filter_5tuple
135 mg_filter_5tuple.__index = mg_filter_5tuple
137 --- Creates a
new 5tuple filter / packet classifier
138 --- @param socket
optional (
default: socket of calling thread), CPU socket, where memory
for the filter should be allocated.
139 --- @param acx experimental use only. should be nil.
140 --- @param numCategories number of categories,
this filter should support
141 --- @param maxNRules
optional (
default = 10), maximum number of rules.
142 --- @
return a wrapper table
for the created filter
143 function mod.create5TupleFilter(socket, acx, numCategories, maxNRules)
144 socket = socket or select(2, dpdk.getCore())
145 maxNRules = maxNRules or 10
147 local category_multiplier =
ffi.C.mg_5tuple_get_results_multiplier()
149 local rest = numCategories % category_multiplier
151 local numBlownCategories = numCategories
153 numBlownCategories = numCategories + category_multiplier - rest
156 local result = setmetatable({
157 acx = acx or
ffi.gc(
ffi.C.mg_5tuple_create_filter(socket, maxNRules),
function(
self)
158 -- FIXME: why is destructor never called?
159 print
"5tuple garbage"
160 ffi.C.mg_5tuple_destruct_filter(
self)
164 numCategories = numBlownCategories,
165 numRealCategories = numCategories,
166 out_masks =
ffi.new(
"struct mg_bitmask*[?]", numCategories),
167 out_values =
ffi.new(
"uint32_t*[?]", numCategories)
170 for i = 1,numCategories
do
171 result.out_masks[i-1] = nil
177 --- Bind an array of result values to a filter category.
178 --- One array of values can be boun to multiple categories. After classification
179 --- it will contain mixed values of all categories it was bound to.
180 --- @param values Array of values to be bound to a category. May also be a number. In
this case
181 --- a
new Array will be allocated and bound to the specified category.
182 --- @param category
optional (
default = bind the specified array to all not yet bound categories),
183 --- The category the array should be bound to
184 --- @
return the array, which was bound
186 if type(values) == "number" then
187 values =
ffi.
new("uint32_t[?]", values)
190 -- bind bitmask to all categories, which do not yet have an associated bitmask
191 for i = 1,self.numRealCategories do
192 if (self.out_values[i-1] == nil) then
193 print("assigned default at category " .. tostring(i))
194 self.out_values[i-1] = values
198 print("assigned bitmask to category " .. tostring(category))
199 self.out_values[category-1] = values
204 --- Bind a BitMask to a filter category.
205 --- On Classification the corresponding bits in the bitmask are
set, when a rule
206 --- matches a packet, for the corresponding category.
207 --- One Bitmask can be bound to multiple categories. The result will be a bitwise OR
208 --- of the Bitmasks, which would be filled for each category.
209 --- @param bitmask Bitmask to be bound to a category. May also be a number. In this case
210 --- a
new BitMask will be allocated and bound to the specified category.
211 --- @param category
optional (default = bind the specified bitmask to all not yet bound categories),
212 --- The category the bitmask should be bound to
213 --- @return the bitmask, which was bound
215 if type(bitmask) == "number" then
219 -- bind bitmask to all categories, which do not yet have an associated bitmask
220 for i = 1,self.numRealCategories do
221 if (self.out_masks[i-1] == nil) then
222 print("assigned default at category " .. tostring(i))
223 self.out_masks[i-1] = bitmask.bitmask
227 print("assigned bitmask to category " .. tostring(category))
228 self.out_masks[category-1] = bitmask.bitmask
234 --- Allocates memory for one 5 tuple rule
235 --- @return ctype
object "struct mg_5tuple_rule"
237 return
ffi.
new("struct mg_5tuple_rule")
240 --- Adds a rule to the filter
241 --- @param rule the rule to be added (ctype "struct mg_5tuple_rule")
242 --- @priority priority of the rule. Higher number -> higher priority
243 --- @category_mask bitmask for the categories, this rule should apply
244 --- @value 32bit integer value associated with this rule. Value is not allowed to be 0
245 function mg_filter_5tuple:
addRule(rule, priority, category_mask, value)
247 error("ERROR: Adding a rule with a 0 value is not allowed")
250 return
ffi.C.mg_5tuple_add_rule(self.acx, rule, priority, category_mask, value)
253 --- Builds the filter with the currently added rules. Should be executed after adding rules
254 --- @param
optional (default = number of Categories, set at 5tuple filter creation time) numCategories maximum number of categories, which are in use.
255 function mg_filter_5tuple:
build(numCategories)
256 numCategories = numCategories or self.numRealCategories
258 --self.numCategories = numCategories
259 return
ffi.C.mg_5tuple_build_filter(self.acx, numCategories)
262 --- Perform packet classification for a burst of packets
263 --- Will do memory violation, when Masks or Values are not correctly bound to categories.
264 --- @param pkts Array of mbufs. Mbufs should contain valid IPv4 packets with a
265 --- normal ethernet header (no VLAN tags). A L4 Protocol header has to be
266 --- present, to avoid reading at invalid memory address. -- FIXME: check if this is true
267 --- @param inMask bitMask, specifying on which packets the filter should be applied
268 --- @return 0 on successfull completion.
270 if not self.built then
271 print("Warning: New rules have been added without building the filter!")
273 --numCategories = numCategories or self.numCategories
274 return
ffi.C.mg_5tuple_classify_burst(self.acx, pkts.array, inMask.bitmask, self.numCategories, self.numRealCategories, self.out_masks, self.out_values)
param n optional(default=2047)
Create a new memory pool.
local ffi
low-level dpdk wrapper
function mg_filter_5tuple bindBitmaskToCategory(bitmask, category)
Bind a BitMask to a filter category.
function dev addHW5tupleFilter(filter, queue, priority)
Installs a 5tuple filter on the device.
function mg_filter_5tuple build(numCategories)
Builds the filter with the currently added rules.
function ipsecICV set(icv)
Set the IPsec ICV.
function mg_filter_5tuple classifyBurst(pkts, inMask)
Perform packet classification for a burst of packets Will do memory violation, when Masks or Values a...
ip PROTO_ICMP
Protocol field value for Icmp.
ip PROTO_TCP
Protocol field value for Tcp.
local mod
high-level dpdk wrapper
function dev filterTimestamps(queue, offset, ntype, ver)
Filter PTP time stamp packets by inspecting the PTP version and type field.
function mod init()
Inits DPDK. Called by MoonGen on startup.
function ip4Addr add(val)
Add a number to an IPv4 address in-place.
function mg_filter_5tuple addRule(rule, priority, category_mask, value)
Adds a rule to the filter.
function mod createBitMask(size)
Create a Bitmask The mask is internally built from blocks of 64bit integers.
function mg_filter_5tuple bindValuesToCategory(values, category)
Bind an array of result values to a filter category.
ip PROTO_UDP
Protocol field value for Udp.
local ip
IP4 protocol constants.
function errorf(str,...)
Print a formatted error string.
function mg_filter_5tuple allocateRule()
Allocates memory for one 5 tuple rule.