1 ---------------------------------
3 --- @brief IPsec (ESP/AH) offloading.
4 --- @todo Documentation
5 ---------------------------------
9 local dpdkc = require
"dpdkc"
10 local dpdk = require
"dpdk"
11 local
ffi = require
"ffi"
13 -- Intel X540 registers
14 local SECTXCTRL = 0x00008800
15 local SECRXCTRL = 0x00008D00
16 local SECTXSTAT = 0x00008804
17 local SECRXSTAT = 0x00008D04
18 local SECTXMINIFG = 0x00008810
19 local SECTXBUFFAF = 0x00008808
21 local IPSTXIDX = 0x00008900
22 local IPSTXKEY_3 = 0x00008914 --MSB of key
23 local IPSTXKEY_2 = 0x00008910
24 local IPSTXKEY_1 = 0x0000890C
25 local IPSTXKEY_0 = 0x00008908 --LSB of key
26 local IPSTXSALT = 0x00008904
28 local IPSRXIDX = 0x00008E00
29 local IPSRXKEY_3 = 0x00008E28 --MSB of key
30 local IPSRXKEY_2 = 0x00008E24
31 local IPSRXKEY_1 = 0x00008E20
32 local IPSRXKEY_0 = 0x00008E1C --LSB ofkey
33 local IPSRXSALT = 0x00008E2C
34 local IPSRXMOD = 0x00008E30
36 --Note: Field is defined in Big Endian (LS byte is first on the wire).
37 local IPSRXIPADDR_3 = 0x00008E10 --LSB of IPv6 or IPv4
38 local IPSRXIPADDR_2 = 0x00008E0C
39 local IPSRXIPADDR_1 = 0x00008E08
40 local IPSRXIPADDR_0 = 0x00008E04 --MSB of IPv6 or 0
42 --Note: Field is defined in Big Endian (LS byte is first on the wire).
43 local IPSRXSPI = 0x00008E14
44 local IPSRXIPIDX = 0x00008E18
46 -- Helper
function to
return padded,
unsigned 32bit hex
string.
48 return bit.tohex(x, 8)
51 -- Helper function to clear a single bit
52 function clear_bit32(reg32, idx)
53 if idx < 0 or idx > 31 then
54 error("Idx must be in
range 0-31")
56 local mask = bit.
bnot(bit.lshift(0x1, idx))
57 return bit.
band(reg32, mask)
60 -- Helper function to
set a single bit
61 function set_bit32(reg32, idx)
62 if idx < 0 or idx > 31 then
63 error("Idx must be in
range 0-31")
65 return bit.
bor(reg32, bit.lshift(0x1, idx))
68 -- Helper function to clear the bits (MSB) from..to (LSB)
69 function clear_bits32(reg32, from, to)
72 tmp = clear_bit32(tmp, i)
77 -- Helper function to
set the bits (MSB) from..to (LSB)
78 function set_bits32(reg32, from, to, value)
79 local upper_limit = math.pow(2, ((from-to)+1))-1 --i.e. (2^num_bits)-1
80 if value < 0 or value > upper_limit then
81 error("Value must be in
range 0-"..upper_limit)
83 local tmp = clear_bits32(reg32, from, to)
84 return bit.
bor(tmp, bit.lshift(value, to))
87 function dump_regs(port)
88 --print("===== DUMP REGS =====")
89 --local reg = dpdkc.read_reg32(port, SECTXCTRL)
90 --print("SECTXCTRL: 0x"..uhex32(reg))
91 --local reg = dpdkc.read_reg32(port, SECRXCTRL)
92 --print("SECRXCTRL: 0x"..uhex32(reg))
93 --local reg = dpdkc.read_reg32(port, SECTXSTAT)
94 --print("SECTXSTAT: 0x"..uhex32(reg))
95 --local reg = dpdkc.read_reg32(port, SECRXSTAT)
96 --print("SECRXSTAT: 0x"..uhex32(reg))
97 --local reg = dpdkc.read_reg32(port, SECTXMINIFG)
98 --print("SECTXMINIFG: 0x"..uhex32(reg))
99 --local reg = dpdkc.read_reg32(port, SECTXBUFFAF)
100 --print("SECTXBUFFAF: 0x"..uhex32(reg))
103 --- Enable the Hardware Crypto Engine.
104 --- This function must be called before using any other IPSec functions
105 --- @param port The port/interface to use
107 --print("IPsec
enable, port: "..port)
110 -- Stop TX data path (
set TX_DIS bit)
111 local SECTXCTRL__VALUE = set_bit32(dpdkc.read_reg32(port, SECTXCTRL), 1) --
set TX_DIS
112 dpdkc.write_reg32(port, SECTXCTRL, SECTXCTRL__VALUE)
114 -- Stop RX data path (
set RX_DIS bit)
115 local SECRXCTRL__VALUE = set_bit32(dpdkc.read_reg32(port, SECRXCTRL), 1) --
set RX_DIS
116 dpdkc.write_reg32(port, SECRXCTRL, SECRXCTRL__VALUE)
118 -- Wait for the data paths to be emptied by hardware (check SECTX/RX_RDY bits).
120 --print("Waiting for registers to be asserted by hardware...")
122 local SECTXSTAT__SECTX_RDY = bit.
band(dpdkc.read_reg32(port, SECTXSTAT), 0x1)
123 local SECRXSTAT__SECRX_RDY = bit.
band(dpdkc.read_reg32(port, SECRXSTAT), 0x1)
124 --print("SECTX_RDY: "..SECTXSTAT__SECTX_RDY..", SECRX_RDY: "..SECRXSTAT__SECRX_RDY)
125 until SECTXSTAT__SECTX_RDY == 0x1 and SECRXSTAT__SECRX_RDY == 0x1
127 -- Set MINSECIFG to 0x3
128 local SECTXMINIFG__VALUE = set_bits32(dpdkc.read_reg32(port, SECTXMINIFG), 3, 0, 0x3) --
set MINSECIFG
129 dpdkc.write_reg32(port, SECTXMINIFG, SECTXMINIFG__VALUE)
131 -- Set FULLTHRESH to 0x15
132 local SECTXBUFFAF__VALUE = set_bits32(dpdkc.read_reg32(port, SECTXBUFFAF), 9, 0, 0x15) --
set FULLTHRESH
133 dpdkc.write_reg32(port, SECTXBUFFAF, SECTXBUFFAF__VALUE)
135 -- Enable TX crypto engine
136 local SECTXCTRL__VALUE = clear_bit32(dpdkc.read_reg32(port, SECTXCTRL), 0) --clear SECTX_DIS
137 SECTXCTRL__VALUE = set_bit32(SECTXCTRL__VALUE, 2) --
set STORE_FORWARD
138 dpdkc.write_reg32(port, SECTXCTRL, SECTXCTRL__VALUE)
140 -- Enable RX crypto engine
141 local SECRXCTRL__VALUE = clear_bit32(dpdkc.read_reg32(port, SECRXCTRL), 0) --clear SECRX_DIS
142 dpdkc.write_reg32(port, SECRXCTRL, SECRXCTRL__VALUE)
144 -- Enable IPsec TX SA
lookup
145 local IPSTXIDX__VALUE = set_bit32(dpdkc.read_reg32(port, IPSTXIDX), 0) --
set IPS_TX_EN
146 dpdkc.write_reg32(port, IPSTXIDX, IPSTXIDX__VALUE)
148 -- Enable IPsec RX SA
lookup
149 local IPSRXIDX__VALUE = set_bit32(dpdkc.read_reg32(port, IPSRXIDX), 0) --
set IPS_RX_EN
150 dpdkc.write_reg32(port, IPSRXIDX, IPSRXIDX__VALUE)
152 -- Restart TX data path (clear TX_DIS bit)
153 local SECTXCTRL__VALUE = clear_bit32(dpdkc.read_reg32(port, SECTXCTRL), 1) --clear TX_DIS
154 dpdkc.write_reg32(port, SECTXCTRL, SECTXCTRL__VALUE)
156 -- Restart RX data path (clear RX_DIS bit)
157 local SECRXCTRL__VALUE = clear_bit32(dpdkc.read_reg32(port, SECRXCTRL), 1) --clear RX_DIS
158 dpdkc.write_reg32(port, SECRXCTRL, SECRXCTRL__VALUE)
163 --- Disable the Hardware Crypto Engine.
164 --- This function should be called after using the other IPSec functions
165 --- @param port The port/interface to use
167 --print("IPsec
disable, port: "..port)
170 -- Stop TX data path (
set TX_DIS bit)
171 local SECTXCTRL__VALUE = set_bit32(dpdkc.read_reg32(port, SECTXCTRL), 1) --
set TX_DIS
172 dpdkc.write_reg32(port, SECTXCTRL, SECTXCTRL__VALUE)
174 -- Stop RX data path (
set RX_DIS bit)
175 local SECRXCTRL__VALUE = set_bit32(dpdkc.read_reg32(port, SECRXCTRL), 1) --
set RX_DIS
176 dpdkc.write_reg32(port, SECRXCTRL, SECRXCTRL__VALUE)
178 -- Wait for the data paths to be emptied by hardware (check SECTX/RX_RDY bits).
180 --print("Waiting for registers to be asserted by hardware...")
182 local SECTXSTAT__SECTX_RDY = bit.
band(dpdkc.read_reg32(port, SECTXSTAT), 0x1)
183 local SECRXSTAT__SECRX_RDY = bit.
band(dpdkc.read_reg32(port, SECRXSTAT), 0x1)
184 --print("SECTX_RDY: "..SECTXSTAT__SECTX_RDY..", SECRX_RDY: "..SECRXSTAT__SECRX_RDY)
185 until SECTXSTAT__SECTX_RDY == 0x1 and SECRXSTAT__SECRX_RDY == 0x1
187 -- Disable IPsec TX SA
lookup
188 local IPSTXIDX__VALUE = clear_bit32(dpdkc.read_reg32(port, IPSTXIDX), 0) --clear IPS_TX_EN
189 dpdkc.write_reg32(port, IPSTXIDX, IPSTXIDX__VALUE)
191 -- Disable IPsec RX SA
lookup
192 local IPSRXIDX__VALUE = clear_bit32(dpdkc.read_reg32(port, IPSRXIDX), 0) --clear IPS_RX_EN
193 dpdkc.write_reg32(port, IPSRXIDX, IPSRXIDX__VALUE)
195 --TODO: what about MINSECIFG?
197 -- Set FULLTHRESH to 0x250
198 local SECTXBUFFAF__VALUE = set_bits32(dpdkc.read_reg32(port, SECTXBUFFAF), 9, 0, 0x250) --
set FULLTHRESH
199 dpdkc.write_reg32(port, SECTXBUFFAF, SECTXBUFFAF__VALUE)
201 -- Disable TX crypto engine
202 local SECTXCTRL__VALUE = set_bit32(dpdkc.read_reg32(port, SECTXCTRL), 0) --
set SECTX_DIS
203 SECTXCTRL__VALUE = clear_bit32(SECTXCTRL__VALUE, 2) --clear STORE_FORWARD
204 dpdkc.write_reg32(port, SECTXCTRL, SECTXCTRL__VALUE)
206 -- Disable RX crypto engine
207 local SECRXCTRL__VALUE = set_bit32(dpdkc.read_reg32(port, SECRXCTRL), 0) --
set SECRX_DIS
208 dpdkc.write_reg32(port, SECRXCTRL, SECRXCTRL__VALUE)
210 -- Restart TX data path (clear TX_DIS bit)
211 local SECTXCTRL__VALUE = clear_bit32(dpdkc.read_reg32(port, SECTXCTRL), 1) --clear TX_DIS
212 dpdkc.write_reg32(port, SECTXCTRL, SECTXCTRL__VALUE)
214 -- Restart RX data path (clear RX_DIS bit)
215 local SECRXCTRL__VALUE = clear_bit32(dpdkc.read_reg32(port, SECRXCTRL), 1) --clear RX_DIS
216 dpdkc.write_reg32(port, SECRXCTRL, SECRXCTRL__VALUE)
221 --- Write AES 128 bit Key and Salt into the Hardware TX SA table
222 --- @param port The port/interface to use
223 --- @parma idx Index into TX SA table (0-1023)
224 --- @param key 128 bit AES key (as hex
string)
225 --- @param salt 32 bit AES salt (as hex
string)
227 if idx > 1023 or idx < 0 then
228 error("Idx must be in
range 0-1023")
230 if
string.len(key) ~= 32 then
231 error("Key must be 128 bit (hex
string).")
233 if
string.len(salt) ~= 8 then
234 error("Salt must be 32 bit (hex
string).")
237 local key_3 = tonumber(
string.sub(key, 1, 8), 16) --MSB
238 local key_2 = tonumber(
string.sub(key, 9, 16), 16)
239 local key_1 = tonumber(
string.sub(key, 17, 24), 16)
240 local key_0 = tonumber(
string.sub(key, 25, 32), 16) --LSB
241 local _salt = tonumber(salt, 16)
243 -- Prepare command to write key to SA_IDX
244 local value = set_bits32(dpdkc.read_reg32(port, IPSTXIDX), 12, 3, idx) --
set SA_IDX
245 value = clear_bit32(value, 30) --clear READ
246 value = set_bit32(value, 31) --
set WRITE
247 --print("IPSTXIDX: 0x"..uhex32(value))
250 dpdkc.write_reg32(port, IPSTXKEY_3, key_3)
251 dpdkc.write_reg32(port, IPSTXKEY_2, key_2)
252 dpdkc.write_reg32(port, IPSTXKEY_1, key_1)
253 dpdkc.write_reg32(port, IPSTXKEY_0, key_0)
254 dpdkc.write_reg32(port, IPSTXSALT, _salt)
256 dpdkc.write_reg32(port, IPSTXIDX, value)
257 --pass SA_IDX via 'TX context descriptor' to use this SA!
260 --- Read AES 128 bit Key and Salt from the Hardware TX SA table
261 --- @param port The port/interface to use
262 --- @param idx Index into the TX SA table (0-1023)
263 --- @return Key and Salt (as hex
string)
265 if idx > 1023 or idx < 0 then
266 error("Idx must be in
range 0-1023")
269 -- Prepare command to read key from SA_IDX
270 local value = set_bits32(dpdkc.read_reg32(port, IPSTXIDX), 12, 3, idx) --
set SA_IDX
271 value = set_bit32(value, 30) --
set READ
272 value = clear_bit32(value, 31) --clear WRITE
273 --print("IPSTXIDX: 0x"..uhex32(value))
276 dpdkc.write_reg32(port, IPSTXIDX, value)
279 local key_3 = dpdkc.read_reg32(port, IPSTXKEY_3)
280 local key_2 = dpdkc.read_reg32(port, IPSTXKEY_2)
281 local key_1 = dpdkc.read_reg32(port, IPSTXKEY_1)
282 local key_0 = dpdkc.read_reg32(port, IPSTXKEY_0)
283 local _salt = dpdkc.read_reg32(port, IPSTXSALT)
285 local key = uhex32(key_3)..uhex32(key_2)..uhex32(key_1)..uhex32(key_0)
287 return key, uhex32(_salt)
290 --- Write AES 128 bit Key and Salt into the Hardware RX SA table
291 --- @param port the port/interface to use
292 --- @param idx Index into SA RX table (0-1023)
293 --- @param key 128 bit AES key (as hex
string)
294 --- @param salt 32 bit AES salt (as hex
string)
295 --- @param ip_ver IP Version for which this SA is valid (4 or 6)
296 --- @param proto IPSec protocol type to use ("esp" or "ah")
297 --- @param decrypt ESP mode (1=ESP decrypt and authenticate, 0=ESP authenticate only)
298 function
mod.
rx_set_key(port, idx, key, salt, ip_ver, proto, decrypt)
299 if idx > 1023 or idx < 0 then
300 error("Idx must be in
range 0-1023")
302 if
string.len(key) ~= 32 then
303 error("Key must be 128 bit (hex
string).")
305 if
string.len(salt) ~= 8 then
306 error("Salt must be 32 bit (hex
string).")
312 elseif ip_ver == 6 then
315 error("IP version must be either 4 or 6")
319 if proto == "esp" then
321 elseif proto == "ah" then
324 error("Protocol must be either 'esp' or 'ah'")
327 local esp_mode = decrypt or 0
328 if esp_mode ~= 1 and esp_mode ~= 0 then
329 error("ESP Decrypt must be either 0 or 1")
332 local key_3 = tonumber(
string.sub(key, 1, 8), 16) --MSB
333 local key_2 = tonumber(
string.sub(key, 9, 16), 16)
334 local key_1 = tonumber(
string.sub(key, 17, 24), 16)
335 local key_0 = tonumber(
string.sub(key, 25, 32), 16) --LSB
336 local _salt = tonumber(salt, 16)
338 -- Prepare command to write KEY_TABLE at TB_IDX
339 local value = set_bits32(dpdkc.read_reg32(port, IPSRXIDX), 2, 1, 0x3) --
set TABLE to KEY(0x3)
340 value = set_bits32(value, 12, 3, idx) --
set TB_IDX
341 value = clear_bit32(value, 30) --clear READ
342 value = set_bit32(value, 31) --
set WRITE
343 --print("IPSRXIDX: 0x"..uhex32(value))
345 -- Prepare security mode register
346 local mode = set_bit32(dpdkc.read_reg32(port, IPSRXMOD), 0) --
set VALID, 1=valid, 0=invalid SA
347 mode = set_bits32(mode, 2, 2, esp) --
set PROTO, 1=ESP, 0=AH
348 mode = set_bits32(mode, 3, 3, esp_mode) --
set DECRYPT, 1=decrypt(ESP), 0=authenticate(ESP)
349 mode = set_bits32(mode, 4, 4, ipv6) --
set IPV6, 1=IPv6, 0=IPv4
352 dpdkc.write_reg32(port, IPSRXKEY_3, key_3)
353 dpdkc.write_reg32(port, IPSRXKEY_2, key_2)
354 dpdkc.write_reg32(port, IPSRXKEY_1, key_1)
355 dpdkc.write_reg32(port, IPSRXKEY_0, key_0)
356 dpdkc.write_reg32(port, IPSRXSALT, _salt)
357 dpdkc.write_reg32(port, IPSRXMOD, mode)
359 dpdkc.write_reg32(port, IPSRXIDX, value)
362 --- Read AES 128 bit Key and Salt from the Hardware RX SA table
363 --- @param port The port/interface to use
364 --- @param idx Index into the RX SA table (0-1023)
365 --- @return Key and Salt (as hex
string),
366 --- Valid Flag (1=SA is valid, 0=SA is invalid),
367 --- Proto Flag (1=ESP, 0=AH),
368 --- Decrypt Flag (1=ESP decrypt and authenticate, 0=ESP authenticate only),
369 --- IPv6 Flag (1=SA is valid for IPv6, 0=SA is valid for IPv4)
371 if idx > 1023 or idx < 0 then
372 error("Idx must be in
range 0-1023")
375 -- Prepare command to read from KEY_TABLE at TB_IDX
376 local value = set_bits32(dpdkc.read_reg32(port, IPSRXIDX), 2, 1, 0x3) --
set TABLE to KEY(0x3)
377 value = set_bits32(value, 12, 3, idx) --
set TB_IDX
378 value = set_bit32(value, 30) --
set READ
379 value = clear_bit32(value, 31), --clear WRITE
380 --print("IPSRXIDX: 0x"..uhex32(value))
383 dpdkc.write_reg32(port, IPSRXIDX, value)
386 local key_3 = dpdkc.read_reg32(port, IPSRXKEY_3)
387 local key_2 = dpdkc.read_reg32(port, IPSRXKEY_2)
388 local key_1 = dpdkc.read_reg32(port, IPSRXKEY_1)
389 local key_0 = dpdkc.read_reg32(port, IPSRXKEY_0)
390 local _salt = dpdkc.read_reg32(port, IPSRXSALT)
391 local _mode = dpdkc.read_reg32(port, IPSRXMOD)
393 local valid = bit.rshift(bit.
band(_mode, 0x01), 0)
394 local proto = bit.rshift(bit.
band(_mode, 0x04), 2)
395 local decrypt = bit.rshift(bit.
band(_mode, 0x08), 3)
396 local ipv6 = bit.rshift(bit.
band(_mode, 0x10), 4)
397 local key = uhex32(key_3)..uhex32(key_2)..uhex32(key_1)..uhex32(key_0)
399 return key, uhex32(_salt), valid, proto, decrypt, ipv6
402 --- Write IP-Address into the Hardware RX IP table
403 --- @param port The port/interface to use
404 --- @param idx Index into the RX IP table (0-127).
405 --- @param ip_addr IP(v4/v6)-Address to
set (as
string)
407 if idx > 127 or idx < 0 then
408 error("Idx must be in
range 0-127")
418 if is_ipv4 == true then
421 ip_3 = bswap(ip.uint32[0])
422 ip_2 = bswap(ip.uint32[1])
423 ip_1 = bswap(ip.uint32[2])
424 ip_0 = bswap(ip.uint32[3])
427 -- Prepare command to write to IP_TABLE at TB_IDX
428 local value = set_bits32(dpdkc.read_reg32(port, IPSRXIDX), 2, 1, 0x1) --
set TABLE to IP(0x1)
429 value = set_bits32(value, 12, 3, idx) --
set TB_IDX
430 value = clear_bit32(value, 30) --clear READ
431 value = set_bit32(value, 31) --
set WRITE
432 --print("IPSRXIDX: 0x"..uhex32(value))
435 dpdkc.write_reg32(port, IPSRXIPADDR_3, ip_3)
436 dpdkc.write_reg32(port, IPSRXIPADDR_2, ip_2)
437 dpdkc.write_reg32(port, IPSRXIPADDR_1, ip_1)
438 dpdkc.write_reg32(port, IPSRXIPADDR_0, ip_0)
440 dpdkc.write_reg32(port, IPSRXIDX, value)
443 --- Read IP-Address from the Hardware RX IP table
444 --- @param port The port/interface to use
445 --- @param idx Index into the RX IP table (0-127)
446 --- @param is_ipv4 IP Version expected (true/false)
447 --- @return The IP(v4/v6)-Address (as
string) and a IP Version Flag (true=IPv4, false=IPv6)
449 if idx > 127 or idx < 0 then
450 error("Idx must be in
range 0-127")
452 if is_ipv4 == nil then
456 -- Prepare command to read from IP_TABLE at TB_IDX
457 local value = set_bits32(dpdkc.read_reg32(port, IPSRXIDX), 2, 1, 0x1) --
set TABLE to IP(0x1)
458 value = set_bits32(value, 12, 3, idx) --
set TB_IDX
459 value = set_bit32(value, 30) --
set READ
460 value = clear_bit32(value, 31) --clear WRITE
461 --print("IPSRXIDX: 0x"..uhex32(value))
464 dpdkc.write_reg32(port, IPSRXIDX, value)
466 local ip_3 = dpdkc.read_reg32(port, IPSRXIPADDR_3)
467 local ip_2 = dpdkc.read_reg32(port, IPSRXIPADDR_2)
468 local ip_1 = dpdkc.read_reg32(port, IPSRXIPADDR_1)
469 local ip_0 = dpdkc.read_reg32(port, IPSRXIPADDR_0)
472 if is_ipv4 == true then
473 local ip4 =
ffi.
new("union ip4_address")
488 --- Write SPI into the Hardware RX SPI table
489 --- This table functions as 'glue' between the received packet (SPI), IP and KEY table.
490 --- @param port The port/interface to use
491 --- @param idx Index into the RX SPI table (0-1023). This must match the idx of the corresponding KEY table entry.
492 --- @param spi SPI to write (0-0xFFFFFFFF)
493 --- @param ip_idx Reference to the IP table. This must match the idx of the corresponding IP table entry.
495 if idx > 1023 or idx < 0 then
496 error("Idx must be in
range 0-1023")
498 if spi > 0xFFFFFFFF or spi < 0 then
499 error("Spi must be in
range 0x0-0xFFFFFFFF")
501 if ip_idx > 127 or ip_idx < 0 then
502 error("IP_Idx must be in
range 0-127")
505 -- Prepare command to write SPI_TABLE at TB_IDX
506 local value = set_bits32(dpdkc.read_reg32(port, IPSRXIDX), 2, 1, 0x2) --
set TABLE to SPI(0x2)
507 value = set_bits32(value, 12, 3, idx) --
set TB_IDX
508 value = clear_bit32(value, 30) --clear READ
509 value = set_bit32(value, 31) --
set WRITE
510 --print("IPSRXIDX: 0x"..uhex32(value))
512 -- Prepare ip_idx field
513 ip_idx = set_bits32(dpdkc.read_reg32(port, IPSRXIPIDX), 6, 0, ip_idx) --
set IP_IDX
516 dpdkc.write_reg32(port, IPSRXSPI, bswap(spi)) --network byte order!
517 dpdkc.write_reg32(port, IPSRXIPIDX, ip_idx)
519 dpdkc.write_reg32(port, IPSRXIDX, value)
522 --- Read SPI from the Hardware RX SPI table
523 --- @param port The port/interface to use
524 --- @param idx Index into the RX SPI table (0-1023)
525 --- @return The SPI and the corresponding Index into the IP table
527 if idx > 1023 or idx < 0 then
528 error("Idx must be in
range 0-1023")
531 -- Prepare command to read from SPI_TABLE at TB_IDX
532 local value = set_bits32(dpdkc.read_reg32(port, IPSRXIDX), 2, 1, 0x2) --
set TABLE to SPI(0x2)
533 value = set_bits32(value, 12, 3, idx) --
set TB_IDX
534 value = set_bit32(value, 30) --
set READ
535 value = clear_bit32(value, 31) --clear WRITE
536 --print("IPSRXIDX: 0x"..uhex32(value))
539 dpdkc.write_reg32(port, IPSRXIDX, value)
541 local spi = dpdkc.read_reg32(port, IPSRXSPI) --network byte order!
542 local ip_idx = bit.
band(dpdkc.read_reg32(port, IPSRXIPIDX), 0x7f) --IP_IDX in bits 6:0
544 return bswap(spi), ip_idx
547 --- Calculate the length of extra padding needed, in order to achive a 4 byte alignment.
548 --- @param payload_len The lenght of the original IP packet
549 --- @return The number of extra padding bytes needed
551 local idx = math.ceil(payload_len/4)
553 local extra_pad = idx8 - payload_len
557 --- Calculate the length of extra padding included in this packet for 4 byte alignment.
558 --- @param buf The rte_mbuf containing the hw-decrypted ESP packet
559 --- @return The number of extra padding bytes included in this packet
562 local payload_len =
pkt.ip4:
getLength()-20 --IP4 Length less 20 bytes IP4 Header
563 --ESP_ICV(16), ESP_next_hdr(1), array_offset(1)
564 local esp_padding_len =
pkt.payload.uint8[payload_len-16-1-1]
565 return esp_padding_len-2 --subtract default padding of 2 bytes, which is always there
568 --- Calculate a ESP Trailer and the corresponding Padding and append to the packet payload.
569 --- Only relevant for ESP/Ecryption mode
570 --- @param buf rte_mbuf to
add esp trailer to
571 --- @param payload_len real payload length in bytes
572 --- @param next_hdr type of encapsulated packet
574 local
pkt = buf:getEspPacket()
575 local idx = math.ceil(payload_len/4)
577 local extra_pad = idx8 - payload_len
578 local pad_len = 2 + extra_pad
579 local esp_trailer_len = 20 + extra_pad
581 pkt.payload.uint8[idx8+0] = 0x00
582 pkt.payload.uint8[idx8+1] = 0x00
583 pkt.payload.uint8[idx8+2] = pad_len
584 pkt.payload.uint8[idx8+3] = next_hdr
586 pkt.payload.uint32[idx+1] = 0x00 -- ICV
n-3
587 pkt.payload.uint32[idx+2] = 0x00 -- ICV
n-2
588 pkt.payload.uint32[idx+3] = 0x00 -- ICV
n-1
589 pkt.payload.uint32[idx+4] = 0x00 -- ICV
n-0
594 --- Decapsulate a hw-decrypted ESP packet
595 --- @param buf The rte_mbuf containing the hw-decrypted ESP packet
596 --- @param len Length of the hw-decrypted IP/ESP packet
597 --- @param eth_mem memoryPool to allocate
new ethernet packets from
598 --- @return A
new rte_mbuf containing the original (inner) IP packet
601 --
eth(14),
pkt(len), pad(extra_pad), outer_ip(20), esp_header(16), esp_trailer(20)
602 local new_len = 14+len-extra_pad-20-16-20
604 local mybuf = eth_mem:alloc(new_len)
607 local esp_pkt = buf:getEspPacket()
608 ffi.copy(new_pkt.payload, esp_pkt.payload, new_len-14)
613 --- Encapsulate an IP packet into a
new IP header and ESP header and trailer
614 --- @param buf The rte_mbuf containing the original IP packet
615 --- @param len Length of the original IP packet
616 --- @param esp_mem memoryPool to allocate
new esp packets from
617 --- @return A
new rte_mbuf containing the encapsulated IP/ESP packet
620 -- eth(14), ip4(20), esp(16),
pkt(len), pad(extra_pad), esp_trailer(20)
621 local new_len = 14+20+16+len+extra_pad+20
623 local mybuf = esp_mem:alloc(new_len)
624 local new_pkt = mybuf:getEspPacket()
628 --for i = 0, len-1 do
629 -- new_pkt.payload.uint8[i] = eth_pkt.payload.uint8[i]
631 ffi.copy(new_pkt.payload, eth_pkt.payload, len)
function mod sleepMillis(t)
Delay by t milliseconds.
function mod disable(port)
Disable the Hardware Crypto Engine.
local ffi
low-level dpdk wrapper
function parseIPAddress(ip)
Parse a string to an IP address.
function ahHeader setLength(int)
Set the Length.
function ipsecICV getString(doByteSwap)
Get the IPsec string.
function mod band(mask1, mask2, result)
Bitwise and.
function range(max, start,...)
Return all integerss in the range [start, max].
function ipsecICV set(icv)
Set the IPsec ICV.
function mod rx_get_key(port, idx)
Read AES 128 bit Key and Salt from the Hardware RX SA table.
function mod add_esp_trailer(buf, payload_len, next_hdr)
Calculate a ESP Trailer and the corresponding Padding and append to the packet payload.
function mod rx_set_key(port, idx, key, salt, ip_ver, proto, decrypt)
Write AES 128 bit Key and Salt into the Hardware RX SA table.
function mod bor(mask1, mask2, result)
Bitwise or.
function mod enable(port)
Enable the Hardware Crypto Engine.
function mod get_extra_pad(buf)
Calculate the length of extra padding included in this packet for 4 byte alignment.
function mod tx_set_key(port, idx, key, salt)
Write AES 128 bit Key and Salt into the Hardware TX SA table.
local mod
high-level dpdk wrapper
function mod calc_extra_pad(payload_len)
Calculate the length of extra padding needed, in order to achive a 4 byte alignment.
function mod esp_vpn_decapsulate(buf, len, eth_mem)
Decapsulate a hw-decrypted ESP packet.
pkt getEthPacket
Cast the packet to an ethernet packet (alias for pkt.getEthernetPacket)
function ip4Addr add(val)
Add a number to an IPv4 address in-place.
function mod rx_get_ip(port, idx, is_ipv4)
Read IP-Address from the Hardware RX IP table.
function pkt setESPTrailerLength(len)
Set the ESP trailer length.
local eth
Ethernet protocol constants.
local ip6
IP6 protocol constants.
local ip
IP4 protocol constants.
function mod esp_vpn_encapsulate(buf, len, esp_mem)
Encapsulate an IP packet into a new IP header and ESP header and trailer.
function mod tx_get_key(port, idx)
Read AES 128 bit Key and Salt from the Hardware TX SA table.
function arp lookup(ip)
Perform a lookup in the ARP table.
local pkt
Module for packets (rte_mbuf)
function mod bnot(mask, result)
Bitwise not.
n
Create a new array of memory buffers (initialized to nil).
function mod rx_set_spi(port, idx, spi, ip_idx)
Write SPI into the Hardware RX SPI table This table functions as 'glue' between the received packet (...
function mod rx_get_spi(port, idx)
Read SPI from the Hardware RX SPI table.
function ahHeader getLength()
Retrieve the Length.
pkt getIPPacket
Cast the packet to either an IP4 (nil/true) or IP6 (false) packet, depending on the passed boolean...
function mod rx_set_ip(port, idx, ip_addr)
Write IP-Address into the Hardware RX IP table.