1 ------------------------------------------------------------------------
3 --- @brief Address resolution protocol (ARP) utility.
4 --- Utility functions for the arp_header struct
5 --- defined in \ref headers.lua . \
n
8 --- - Arp address utility
9 --- - Arp header utility
10 --- - Definition of Arp packets
11 --- - Arp handler task
12 ------------------------------------------------------------------------
15 local
pkt = require "packet"
18 local dpdkc = require "dpdkc"
19 local dpdk = require "dpdk"
20 local memory = require "memory"
21 local filter = require "filter"
22 local ns = require "namespaces"
24 local
eth = require "proto.ethernet"
26 local ntoh, hton = ntoh, hton
27 local ntoh16, hton16 = ntoh16, hton16
28 local
bor,
band,
bnot, rshift, lshift= bit.bor, bit.band, bit.bnot, bit.rshift, bit.lshift
29 local format =
string.format
30 local istype =
ffi.istype
33 --------------------------------------------------------------------------------------------------------
34 ---- ARP constants (c.f. http:
35 --------------------------------------------------------------------------------------------------------
37 --- Arp protocol constants
40 --- Hardware address type
for ethernet
41 arp.HARDWARE_ADDRESS_TYPE_ETHERNET = 1
43 --- Proto address type
for IP (
for ethernet based protocols uses etherType numbers \ref ethernet.lua)
44 arp.PROTO_ADDRESS_TYPE_IP = 0x0800
46 --- Operation: request
52 --------------------------------------------------------------------------------------------------------
54 --------------------------------------------------------------------------------------------------------
56 --- Module
for arp_header
struct (see \ref headers.lua).
60 --- Set the hardware address type.
61 --- @param
int Type as 16 bit integer.
64 self.hrd = hton16(
int)
67 --- Retrieve the hardware address type.
68 --- @return Type as 16 bit integer.
70 return hton16(self.hrd)
73 --- Retrieve the hardware address type.
74 --- @return Type in
string format.
80 return format("0x%04x", type)
84 --- Set the protocol address type.
85 --- @param
int Type as 16 bit integer.
88 self.pro = hton16(
int)
91 --- Retrieve the protocol address type.
92 --- @return Type as 16 bit integer.
94 return hton16(self.pro)
97 --- Retrieve the protocol address type.
98 --- @return Type in
string format.
101 if type ==
arp.PROTO_ADDR_TYPE_IP then
104 return format("0x%04x", type)
108 --- Set the hardware address length.
109 --- @param
int Length as 8 bit integer.
115 --- Retrieve the hardware address length.
116 --- @return Length as 8 bit integer.
121 --- Retrieve the hardware address length.
122 --- @return Length in
string format.
127 --- Set the protocol address length.
128 --- @param
int Length as 8 bit integer.
134 --- Retrieve the protocol address length.
135 --- @return Length as 8 bit integer.
140 --- Retrieve the protocol address length.
141 --- @return Length in
string format.
146 --- Set the operation.
147 --- @param
int Operation as 16 bit integer.
150 self.op = hton16(
int)
153 --- Retrieve the operation.
154 --- @return Operation as 16 bit integer.
156 return hton16(self.op)
159 --- Retrieve the operation.
160 --- @return Operation in
string format.
172 --- Set the hardware source address.
173 --- @param addr Address in 'struct mac_address' format.
178 --- Retrieve the hardware source address.
179 --- @return Address in 'struct mac_address' format.
181 return self.sha:
get()
184 --- Set the hardware source address.
185 --- @param addr Address in
string format.
190 --- Retrieve the hardware source address.
191 --- @return Address in
string format.
196 --- Set the hardware destination address.
197 --- @param addr Address in 'struct mac_address' format.
202 --- Retrieve the hardware destination address.
203 --- @return Address in 'struct mac_address' format.
205 return self.tha:
get()
208 --- Set the hardware destination address.
209 --- @param addr Address in
string format.
214 --- Retrieve the hardware destination address.
215 --- @return Address in
string format.
220 --- Set the protocol source address.
221 --- @param addr Address in 'struct ip4_address' format.
226 --- Retrieve the protocol source address.
227 --- @return Address in 'struct ip4_address' format.
229 return self.spa:
get()
232 --- Set the protocol source address.
233 --- @param addr Address in source format.
238 --- Retrieve the protocol source address.
239 --- @return Address in
string format.
244 --- Set the protocol destination address.
245 --- @param addr Address in 'struct ip4_address' format.
250 --- Retrieve the protocol destination address.
251 --- @return Address in 'struct ip4_address' format.
253 return self.tpa:
get()
256 --- Set the protocol destination address.
257 --- @param addr Address in
string format.
262 --- Retrieve the protocol destination address.
263 --- @return Address in
string format.
268 --- Set all members of the
ip header.
269 --- Per default, all members are
set to default values specified in the respective
set function.
270 --- Optional named arguments can be used to
set a member to a user-provided value.
271 --- @param args Table of named arguments. Available arguments: HardwareAddressType, ProtoAddressType, HardwareAddressLength, ProtoAddressLength, Operation, HardwareSrc, HardwareDst, ProtoSrc, ProtoDst
272 --- @param pre prefix for namedArgs. Default '
arp'.
274 ---
fill() --- only default values
275 ---
fill{ arpOperation=2, ipTTL=100 } --- all members are
set to
default values with the exception of arpOperation
287 local hwSrc = pre ..
"HardwareSrc"
288 local hwDst = pre ..
"HardwareDst"
289 local prSrc = pre ..
"ProtoSrc"
290 local prDst = pre ..
"ProtoDst"
291 args[hwSrc] = args[hwSrc] or
"01:02:03:04:05:06"
292 args[hwDst] = args[hwDst] or
"07:08:09:0a:0b:0c"
293 args[prSrc] = args[prSrc] or
"0.1.2.3"
294 args[prDst] = args[prDst] or
"4.5.6.7"
296 --
if for some reason the address is in
'struct mac_address'/
'union ipv4_address' format, cope with it
297 if type(args[hwSrc]) ==
"string" then
302 if type(args[hwDst]) ==
"string" then
308 if type(args[prSrc]) ==
"string" then
313 if type(args[prDst]) ==
"string" then
320 --- Retrieve the values of all members.
321 --- @param pre prefix
for namedArgs. Default
'arp'.
322 --- @
return Table of named arguments. For a list of arguments see
"See also".
341 --- Retrieve the values of all members.
342 --- @return Values in
string format.
373 --- Resolve which header comes after this one (in a packet).
374 --- For instance: in tcp/
udp based on the ports.
375 --- This function must exist and is only used when
get/
dump is executed on
376 --- an unknown (mbuf not yet casted to e.g. tcpv6 packet) packet (mbuf)
377 --- @return String next header (e.g. '
udp', '
icmp', nil)
382 --- Change the default values for namedArguments (for
fill/
get).
383 --- This can be used to for instance calculate a length value based on the total packet length.
385 --- This function must exist and is only used by packet.
fill.
386 --- @param pre The prefix used for the namedArgs, e.g. '
arp'
387 --- @param namedArgs Table of named arguments (see See Also)
388 --- @param nextHeader The header following after this header in a packet
389 --- @param accumulatedLength The so far accumulated length for previous headers in a packet
390 --- @return Table of namedArgs
396 ---------------------------------------------------------------------------------
398 ---------------------------------------------------------------------------------
400 --- Cast the packet to an Arp packet
404 ---------------------------------------------------------------------------------
405 ---- ARP Handler Task
406 ---------------------------------------------------------------------------------
408 --- Arp handler task, responds to ARP queries for given IPs and performs
arp lookups
409 --- @todo TODO implement garbage collection/refreshing entries \
n
410 --- the current implementation does not handle large tables efficiently \
n
411 --- @todo TODO multi-NIC support
422 -- two ways to call this: single nic or array of nics
423 if qs[1] == nil and qs.rxQueue then
428 -- loop over NICs/Queues
429 for _, nic in pairs(qs) do
430 if nic.txQueue.dev ~= nic.rxQueue.dev then
431 error("both queues must belong to the same device")
434 if type(nic.ips) == "
string" then
435 nic.ips = { nic.ips }
438 for _,
ip in pairs(nic.ips) do
441 nic.txQueue.dev:l2Filter(
eth.
TYPE_ARP, nic.rxQueue)
444 local rxBufs = memory.createBufArray(1)
447 arpOperation =
arp.OP_REPLY,
457 for _, nic in pairs(qs) do
465 local mac = ipToMac[
ip]
468 -- TODO: a single-packet API would be nice for things like this
477 nic.txQueue:send(txBufs)
480 -- learn from all
arp replies we see (
arp cache poisoning doesn't matter here)
490 -- send outstanding requests
492 -- TODO: refresh or GC old entries
493 if value ~= "pending" then
505 -- TODO: do not send requests on all devices, but only the relevant
506 for _, nic in pairs(qs) do
507 local mac = nic.txQueue.dev:getMac()
511 nic.txQueue:send(txBufs)
518 --- Perform a
lookup in the ARP table.
519 --- Lookup the MAC address for a given IP.
520 --- Blocks for up to 1 second if the
arp task is not yet
running
521 --- Caution: this function uses locks and namespaces, must not be used in the fast path
522 --- @param ip The ip address in
string or cdata format to look up.
524 if type(ip) == "
string" then
526 elseif type(ip) == "cdata" then
530 local waitForArpTask = 0
531 while not
arpTable.taskRunning and waitForArpTask < 10 do
535 error("ARP task is not
running")
539 if type(mac) == "table" then
540 return mac.mac, mac.timestamp
550 --- Perform a non-blocking
lookup in the ARP table.
551 --- @param ip The ip address in
string or cdata format to look up.
552 --- @param timeout TODO
553 --- @todo FIXME: this only sends a single request
555 local timeout = dpdk.
getTime() + timeout
562 until dpdk.
getTime() >= timeout
568 ---------------------------------------------------------------------------------
570 ---------------------------------------------------------------------------------
function mod sleepMillis(t)
Delay by t milliseconds.
function arpHeader getHardwareDstString()
Retrieve the hardware destination address.
local arpHeader
Module for arp_header struct (see headers.lua).
function etherHeader setDst(addr)
Set the destination MAC address.
function arpHeader setProtoDst(addr)
Set the protocol destination address.
local ffi
low-level dpdk wrapper
function arpHeader getString()
Retrieve the values of all members.
function arpHeader setHardwareSrcString(addr)
Set the hardware source address.
function parseIPAddress(ip)
Parse a string to an IP address.
function arpHeader get(pre)
Retrieve the values of all members.
function etherHeader setSrc(addr)
Set the source MAC address.
eth TYPE_ARP
EtherType for Arp.
function etherHeader getSrc(addr)
Retrieve the source MAC address.
function packetCreate(...)
Create struct and functions for a new packet.
function arpHeader getProtoAddressType()
Retrieve the protocol address type.
function macAddr setString(mac)
Set the MAC address.
function arpHeader setProtoSrcString(addr)
Set the protocol source address.
function arpHeader getOperationString()
Retrieve the operation.
function arpHeader getProtoDstString()
Retrieve the protocol destination address.
function arpHeader getHardwareAddressType()
Retrieve the hardware address type.
function mod band(mask1, mask2, result)
Bitwise and.
function pkt dump(bytes)
Dumps the packet data cast to the best fitting packet struct.
function arpHeader setProtoDstString(addr)
Set the protocol destination address.
function arpHeader setHardwareAddressType(int)
Set the hardware address type.
function arpHeader setProtoAddressLength(int)
Set the protocol address length.
function arpHeader setProtoSrc(addr)
Set the protocol source address.
function ipsecICV set(icv)
Set the IPsec ICV.
pkt getArpPacket
Cast the packet to an Arp packet.
function arpHeader resolveNextHeader()
Resolve which header comes after this one (in a packet).
function etherHeader setDstString(str)
Set the destination MAC address.
function arpHeader getHardwareAddressLengthString()
Retrieve the hardware address length.
arp OP_REQUEST
Operation: request.
local udp
Udp protocol constants.
function arpHeader getProtoAddressLength()
Retrieve the protocol address length.
function mod bor(mask1, mask2, result)
Bitwise or.
local arp
Arp protocol constants.
arp OP_REPLY
Operation: reply.
function arpHeader getHardwareSrcString()
Retrieve the hardware source address.
arp HARDWARE_ADDRESS_TYPE_ETHERNET
Hardware address type for ethernet.
function arpHeader getProtoAddressTypeString()
Retrieve the protocol address type.
function mempool bufArray(n)
Create a new array of memory buffers (initialized to nil).
function arpHeader setProtoAddressType(int)
Set the protocol address type.
function arpHeader setHardwareSrc(addr)
Set the hardware source address.
function arpHeader getOperation()
Retrieve the operation.
arp PROTO_ADDRESS_TYPE_IP
Proto address type for IP (for ethernet based protocols uses etherType numbers ethernet.lua)
function arpHeader getProtoDst()
Retrieve the protocol destination address.
function arpHeader setHardwareDst(addr)
Set the hardware destination address.
local arpTable
Arp table TODO docu.
function arpHeader getHardwareDst()
Retrieve the hardware destination address.
function etherHeader getType()
Retrieve the EtherType.
function arpHeader setOperation(int)
Set the operation.
local eth
Ethernet protocol constants.
function mod createMemPool(...)
function rxQueue tryRecvIdle(bufArray, maxWait)
Receive packets from a rx queue with a timeout.
function mod getTime()
gets the time in seconds
function arpHeader fill(args, pre)
Set all members of the ip header.
function arpHeader getHardwareSrc()
Retrieve the hardware source address.
local ip
IP4 protocol constants.
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.
eth BROADCAST
Ethernet broadcast address.
function bufArray freeAll()
Free all buffers in the array. Stops when it encounters the first one that is null.
function arpHeader getProtoSrcString()
Retrieve the protocol source address.
n
Create a new array of memory buffers (initialized to nil).
function arpHeader setDefaultNamedArgs(pre, namedArgs, nextHeader, accumulatedLength)
Change the default values for namedArguments (for fill/get).
function arpHeader getHardwareAddressLength()
Retrieve the hardware address length.
function mod sleepMillisIdle(t)
Sleep by t milliseconds by calling usleep().
function mod running(extraTime)
Returns false once the app receives SIGTERM or SIGINT, the time set via setRuntime expires...
namespace forEach(func)
Iterate over all keys/values in a namespace Note: namespaces do not offer a 'normal' iterator (e...
function arpHeader getProtoAddressLengthString()
Retrieve the protocol address length.
local icmp
Icmp4 protocol constants.
function arpHeader getProtoSrc()
Retrieve the protocol source address.
function arpHeader getHardwareAddressTypeString()
Retrieve the hardware address type.
function arp blockingLookup(ip, timeout)
Perform a non-blocking lookup in the ARP table.
arp arpTask
Arp handler task, responds to ARP queries for given IPs and performs arp lookups. ...
function arpHeader setHardwareDstString(addr)
Set the hardware destination address.
function arpHeader setHardwareAddressLength(int)
Set the hardware address length.