MoonGen
 All Files Functions Variables Pages
ip6.lua
Go to the documentation of this file.
1 ------------------------------------------------------------------------
2 --- @file ip6.lua
3 --- @brief Internet protocol (v6) utility.
4 --- Utility functions for the ip6_address and ip6_header structs
5 --- defined in \ref headers.lua . \n
6 --- Includes:
7 --- - IP6 constants
8 --- - IP6 address utility
9 --- - IP6 header utility
10 --- - Definition of IP6 packets
11 ------------------------------------------------------------------------
12 
13 local ffi = require "ffi"
14 local pkt = require "packet"
15 
16 require "utils"
17 require "headers"
18 
19 local ntoh, hton = ntoh, hton
20 local ntoh16, hton16 = ntoh16, hton16
21 local bswap = bswap
22 local bswap16 = bswap16
23 local bor, band, bnot, rshift, lshift= bit.bor, bit.band, bit.bnot, bit.rshift, bit.lshift
24 local istype = ffi.istype
25 local format = string.format
26 
27 ------------------------------------------------------------------------------------
28 ---- IP6 constants
29 ------------------------------------------------------------------------------------
30 
31 --- IP6 protocol constants
32 local ip6 = {}
33 
34 --- NextHeader field value for Tcp
35 ip6.PROTO_TCP = 0x06
36 --- NextHeader field value for Udp
37 ip6.PROTO_UDP = 0x11
38 --- NextHeader field value for Icmp
39 ip6.PROTO_ICMP = 0x3a -- 58
40 ip6.PROTO_ESP = 0x32
41 ip6.PROTO_AH = 0x33
42 
43 
44 -------------------------------------------------------------------------------------
45 ---- IPv6 addresses
46 -------------------------------------------------------------------------------------
47 
48 --- Module for ip6_address struct (see \ref headers.lua).
49 local ip6Addr = {}
50 ip6Addr.__index = ip6Addr
51 local ip6AddrType = ffi.typeof("union ip6_address")
52 
53 --- Retrieve the IPv6 address.
54 --- @return Address in 'union ip6_address' format.
55 function ip6Addr:get()
56  local addr = ip6AddrType()
57  addr.uint32[0] = bswap(self.uint32[3])
58  addr.uint32[1] = bswap(self.uint32[2])
59  addr.uint32[2] = bswap(self.uint32[1])
60  addr.uint32[3] = bswap(self.uint32[0])
61  return addr
62 end
63 
64 --- Set the IPv6 address.
65 --- @param addr Address in 'union ip6_address' format.
66 function ip6Addr:set(addr)
67  self.uint32[0] = bswap(addr.uint32[3])
68  self.uint32[1] = bswap(addr.uint32[2])
69  self.uint32[2] = bswap(addr.uint32[1])
70  self.uint32[3] = bswap(addr.uint32[0])
71 end
72 
73 --- Set the IPv6 address.
74 --- @param ip Address in string format.
75 function ip6Addr:setString(ip)
76  self:set(parseIP6Address(ip))
77 end
78 
79 --- Test equality of two IPv6 addresses.
80 --- @param lhs Address in 'union ip6_address' format.
81 --- @param rhs Address in 'union ip6_address' format.
82 --- @return true if equal, false otherwise.
83 function ip6Addr.__eq(lhs, rhs)
84  return istype(ip6AddrType, lhs) and istype(ip6AddrType, rhs) and lhs.uint64[0] == rhs.uint64[0] and lhs.uint64[1] == rhs.uint64[1]
85 end
86 
87 --- Add a number to an IPv6 address.
88 --- Max. 64bit, commutative.
89 --- @param lhs Address in 'union ip6_address' format.
90 --- @param rhs Number to add (64 bit integer).
91 --- @return Resulting address in 'union ip6_address' format.
92 function ip6Addr.__add(lhs, rhs)
93  -- calc ip (self) + number (val)
94  local self, val
95  if istype(ip6AddrType, lhs) then
96  self = lhs
97  val = rhs
98  else
99  -- commutative for number + ip
100  self = rhs
101  val = lhs
102  end -- TODO: ip + ip?
103  local addr = ip6AddrType()
104  local low, high = self.uint64[0], self.uint64[1]
105  low = low + val
106  -- handle overflow
107  if low < val and val > 0 then
108  high = high + 1
109  -- handle underflow
110  elseif low > -val and val < 0 then
111  high = high - 1
112  end
113  addr.uint64[0] = low
114  addr.uint64[1] = high
115  return addr
116 end
117 
118 --- Add a number to an IPv6 address in-place.
119 --- Max 64 bit.
120 --- @param val Number to add (64 bit integer).
121 function ip6Addr:add(val)
122  -- calc ip (self) + number (val)
123  local low, high = bswap(self.uint64[1]), bswap(self.uint64[0])
124  low = low + val
125  -- handle overflow
126  if low < val and val > 0 then
127  high = high + 1
128  -- handle underflow
129  elseif low > -val and val < 0 then
130  high = high - 1
131  end
132  self.uint64[1] = bswap(low)
133  self.uint64[0] = bswap(high)
134 end
135 
136 --- Subtract a number from an IPv6 address.
137 --- Max. 64 bit.
138 --- @param val Number to substract (64 bit integer).
139 --- @return Resulting address in 'union ip6_address' format.
140 function ip6Addr:__sub(val)
141  return self + -val
142 end
143 
144 --- Retrieve the string representation of an IPv6 address.
145 --- Assumes 'union ip6_address' is in network byteorder.
146 --- @param doByteSwap Optional change the byteorder of the ip6 address before returning the string representation.
147 --- @return Address in string format.
148 function ip6Addr:getString(doByteSwap)
149  doByteSwap = doByteSwap or false
150  if doByteSwap then
151  self = self:get()
152  end
153 
154  return ("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"):format(
155  self.uint8[0], self.uint8[1], self.uint8[2], self.uint8[3],
156  self.uint8[4], self.uint8[5], self.uint8[6], self.uint8[7],
157  self.uint8[8], self.uint8[9], self.uint8[10], self.uint8[11],
158  self.uint8[12], self.uint8[13], self.uint8[14], self.uint8[15]
159  )
160 end
161 
162 
163 ------------------------------------------------------------------------------
164 ---- IPv6 header
165 ------------------------------------------------------------------------------
166 
167 --- Module for ip6_header struct (see \ref headers.lua).
168 local ip6Header = {}
169 ip6Header.__index = ip6Header
170 
171 --- Set the version.
172 --- @param int IP6 header version as 4 bit integer. Should always be '6'.
173 function ip6Header:setVersion(int)
174  int = int or 6
175  int = band(lshift(int, 28), 0xf0000000) -- fill to 32 bits
176 
177  old = bswap(self.vtf)
178  old = band(old, 0x0fffffff) -- remove old value
179 
180  self.vtf = bswap(bor(old, int))
181 end
182 
183 --- Retrieve the version.
184 --- @return Version as 4 bit integer.
185 function ip6Header:getVersion()
186  return band(rshift(bswap(self.vtf), 28), 0x0000000f)
187 end
188 
189 --- Retrieve the version.
190 --- @return Version as string.
191 function ip6Header:getVersionString()
192  return self:getVersion()
193 end
194 
195 --- Set the traffic class.
196 --- @param int Traffic class of the ip6 header as 8 bit integer.
197 function ip6Header:setTrafficClass(int)
198  int = int or 0
199  int = band(lshift(int, 20), 0x0ff00000)
200 
201  old = bswap(self.vtf)
202  old = band(old, 0xf00fffff)
203 
204  self.vtf = bswap(bor(old, int))
205 end
206 
207 --- Retrieve the traffic class.
208 --- @return Traffic class as 8 bit integer.
209 function ip6Header:getTrafficClass()
210  return band(rshift(bswap(self.vtf), 20), 0x000000ff)
211 end
212 
213 --- Retrieve the traffic class.
214 --- @return Traffic class as string.
216  return self:getTrafficClass()
217 end
218 
219 --- Set the flow label.
220 --- @param int Flow label of the ip6 header as 20 bit integer.
221 function ip6Header:setFlowLabel(int)
222  int = int or 0
223  int = band(int, 0x000fffff)
224 
225  old = bswap(self.vtf)
226  old = band(old, 0xfff00000)
227 
228  self.vtf = bswap(bor(old, int))
229 end
230 
231 --- Retrieve the flow label.
232 --- @return Flow label as 20 bit integer.
233 function ip6Header:getFlowLabel()
234  return band(bswap(self.vtf), 0x000fffff)
235 end
236 
237 --- Retrieve the flow label.
238 --- @return Flow label as string.
239 function ip6Header:getFlowLabelString()
240  return self:getFlowLabel()
241 end
242 
243 --- Set the payload length.
244 --- @param int Length of the ip6 header payload (hence, excluding l2 and l3 headers). 16 bit integer.
245 function ip6Header:setLength(int)
246  int = int or 8 -- with eth + UDP -> minimum 66
247  self.len = hton16(int)
248 end
249 
250 --- Retrieve the length.
251 --- @return Length as 16 bit integer.
252 function ip6Header:getLength()
253  return hton16(self.len)
254 end
255 
256 --- Retrieve the length.
257 --- @return Length as string.
258 function ip6Header:getLengthString()
259  return self:getLength()
260 end
261 
262 --- Set the next header.
263 --- @param int Next header of the ip6 header as 8 bit integer.
264 function ip6Header:setNextHeader(int)
265  int = int or ip6.PROTO_UDP
266  self.nextHeader = int
267 end
268 
269 --- Retrieve the next header.
270 --- @return Next header as 8 bit integer.
271 function ip6Header:getNextHeader()
272  return self.nextHeader
273 end
274 
275 --- Retrieve the next header.
276 --- @return Next header as string.
278  local proto = self:getNextHeader()
279  local cleartext = ""
280 
281  if proto == ip6.PROTO_ICMP then
282  cleartext = "(ICMP)"
283  elseif proto == ip6.PROTO_UDP then
284  cleartext = "(UDP)"
285  elseif proto == ip6.PROTO_TCP then
286  cleartext = "(TCP)"
287  elseif proto == ip6.PROTO_ESP then
288  cleartext = "(ESP)"
289  elseif proto == ip6.PROTO_AH then
290  cleartext = "(AH)"
291  else
292  cleartext = "(unknown)"
293  end
294 
295  return format("0x%02x %s", proto, cleartext)
296 end
297 
298 --- Set the time-to-live (TTL).
299 --- @param int TTL of the ip6 header as 8 bit integer.
300 function ip6Header:setTTL(int)
301  int = int or 64
302  self.ttl = int
303 end
304 
305 --- Retrieve the time-to-live.
306 --- @return TTL as 8 bit integer.
307 function ip6Header:getTTL()
308  return self.ttl
309 end
310 
311 --- Retrieve the time-to-live.
312 --- @return TTL as string.
313 function ip6Header:getTTLString()
314  return self:getTTL()
315 end
316 
317 --- Set the destination address.
318 --- @param addr Address in 'union ip6_address' format.
319 function ip6Header:setDst(addr)
320  self.dst:set(addr)
321 end
322 
323 --- Retrieve the IP6 destination address.
324 --- @return Address in 'union ip6_address' format.
325 function ip6Header:getDst()
326  return self.dst:get()
327 end
328 
329 --- Set the source address.
330 --- @param addr Address in 'union ip6_address' format.
331 function ip6Header:setSrc(addr)
332  self.src:set(addr)
333 end
334 
335 --- Retrieve the IP6 source address.
336 --- @return Address in 'union ip6_address' format.
337 function ip6Header:getSrc()
338  return self.src:get()
339 end
340 
341 --- Set the destination address.
342 --- @param str Address in string format.
343 function ip6Header:setDstString(str)
344  self:setDst(parseIP6Address(str))
345 end
346 
347 --- Retrieve the IP6 destination address.
348 --- @return Address in string format.
349 function ip6Header:getDstString()
350  return self.dst:getString()
351 end
352 
353 --- Set the source address.
354 --- @param str Address in string format.
355 function ip6Header:setSrcString(str)
356  self:setSrc(parseIP6Address(str))
357 end
358 
359 --- Retrieve the IP6 source address.
360 --- @return Address in source format.
361 function ip6Header:getSrcString()
362  return self.src:getString()
363 end
364 
365 --- Set all members of the ip6 header.
366 --- Per default, all members are set to default values specified in the respective set function.
367 --- Optional named arguments can be used to set a member to a user-provided value.
368 --- @param args Table of named arguments. Available arguments: ip6Version, ip6TrafficClass, ip6FlowLabel, ip6Length, ip6NextHeader, ip6TTL, ip6Src, ip6Dst
369 --- @param pre prefix for namedArgs. Default 'ip6'.
370 --- @code
371 --- fill() --- only default values
372 --- fill{ ip6Src="f880::ab", ip6TTL=101 } --- all members are set to default values with the exception of ip6Src and ip6TTL
373 --- @endcode
374 function ip6Header:fill(args, pre)
375  args = args or {}
376  pre = pre or "ip6"
377 
378  self:setVersion(args[pre .. "Version"])
379  self:setTrafficClass(args[pre .. "TrafficClass"])
380  self:setFlowLabel(args[pre .. "FlowLabel"])
381  self:setLength(args[pre .. "Length"])
382  self:setNextHeader(args[pre .. "NextHeader"])
383  self:setTTL(args[pre .. "TTL"])
384 
385  local src = pre .. "Src"
386  local dst = pre .. "Dst"
387  args[src] = args[src] or "fe80::1"
388  args[dst] = args[dst] or "fe80::2"
389 
390  -- if for some reason the address is in 'union ip6_address' format, cope with it
391  if type(args[src]) == "string" then
392  self:setSrcString(args[src])
393  else
394  self:setSrc(args[src])
395  end
396  if type(args[dst]) == "string" then
397  self:setDstString(args[dst])
398  else
399  self:setDst(args[dst])
400  end
401 end
402 
403 --- Retrieve the values of all members.
404 --- @param pre prefix for namedArgs. Default 'ip6'.
405 --- @return Table of named arguments. For a list of arguments see "See also".
406 --- @see ip6Header:fill
407 function ip6Header:get(pre)
408  pre = pre or "ip6"
409 
410  local args = {}
411  args[pre .. "Src"] = self:getSrcString()
412  args[pre .. "Dst"] = self:getDstString()
413  args[pre .. "Version"] = self:getVersion()
414  args[pre .. "TrafficClass"] = self:getTrafficClass()
415  args[pre .. "FlowLabel"] = self:getFlowLabel()
416  args[pre .. "Length"] = self:getLength()
417  args[pre .. "NextHeader"] = self:getNextHeader()
418  args[pre .. "TTL"] = self:getTTL()
419 
420  return args
421 end
422 
423 --- Retrieve the values of all members.
424 --- @return Values in string format.
425 function ip6Header:getString()
426  return "IP6 " .. self:getSrcString() .. " > " .. self:getDstString() .. " ver " .. self:getVersionString()
427  .. " tc " .. self:getTrafficClassString() .. " fl " .. self:getFlowLabelString() .. " len " .. self:getLengthString()
428  .. " next " .. self:getNextHeaderString() .. " ttl " .. self:getTTLString()
429 end
430 
431 -- Maps headers to respective nextHeader value.
432 -- This list should be extended whenever a new protocol is added to 'IPv6 constants'.
433 local mapNameProto = {
434  icmp = ip6.PROTO_ICMP,
435  udp = ip6.PROTO_UDP,
436  tcp = ip6.PROTO_TCP,
437  esp = ip6.PROTO_ESP,
438  ah = ip6.PROTO_AH,
439 }
440 
441 --- Resolve which header comes after this one (in a packet).
442 --- For instance: in tcp/udp based on the ports.
443 --- This function must exist and is only used when get/dump is executed on
444 --- an unknown (mbuf not yet casted to e.g. tcpv6 packet) packet (mbuf)
445 --- @return String next header (e.g. 'udp', 'icmp', nil)
446 function ip6Header:resolveNextHeader()
447  local proto = self:getNextHeader()
448  for name, _proto in pairs(mapNameProto) do
449  if proto == _proto then
450  return name
451  end
452  end
453  return nil
454 end
455 
456 --- Change the default values for namedArguments (for fill/get).
457 --- This can be used to for instance calculate a length value based on the total packet length.
458 --- See proto/ip4.setDefaultNamedArgs as an example.
459 --- This function must exist and is only used by packet.fill.
460 --- @param pre The prefix used for the namedArgs, e.g. 'ip6'
461 --- @param namedArgs Table of named arguments (see See Also)
462 --- @param nextHeader The header following after this header in a packet
463 --- @param accumulatedLength The so far accumulated length for previous headers in a packet
464 --- @return Table of namedArgs
465 --- @see ip6Header:fill
466 function ip6Header:setDefaultNamedArgs(pre, namedArgs, nextHeader, accumulatedLength)
467  -- set length
468  if not namedArgs[pre .. "Length"] and namedArgs["pktLength"] then
469  namedArgs[pre .. "Length"] = namedArgs["pktLength"] - (accumulatedLength + 40)
470  end
471 
472  -- set protocol
473  if not namedArgs[pre .. "NextHeader"] then
474  for name, type in pairs(mapNameProto) do
475  if nextHeader == name then
476  namedArgs[pre .. "NextHeader"] = type
477  break
478  end
479  end
480  end
481  return namedArgs
482 end
483 
484 ----------------------------------------------------------------------------------
485 ---- Packets
486 ----------------------------------------------------------------------------------
487 
488 --- Cast the packet to an IP6 packet
490 
491 
492 ------------------------------------------------------------------------
493 ---- Metatypes
494 ------------------------------------------------------------------------
495 
496 ffi.metatype("union ip6_address", ip6Addr)
497 ffi.metatype("struct ip6_header", ip6Header)
498 
499 return ip6
local ip6Addr
Module for ip6_address struct (see headers.lua).
Definition: ip6.lua:39
pkt getIP6Packet
Cast the packet to an IP6 packet.
Definition: ip6.lua:260
function ip6Header getFlowLabelString()
Retrieve the flow label.
local ffi
low-level dpdk wrapper
Definition: dpdkc.lua:6
function ip6Header getDstString()
Retrieve the IP6 destination address.
function ip6Addr getString(doByteSwap)
Retrieve the string representation of an IPv6 address.
function ip6Header setNextHeader(int)
Set the next header.
function ip6Header setFlowLabel(int)
Set the flow label.
function ip6Header getNextHeader()
Retrieve the next header.
function bswap16(n)
Byte swap for 16 bit integers.
function packetCreate(...)
Create struct and functions for a new packet.
function ip6Header setSrc(addr)
Set the source address.
ip6 PROTO_ICMP
NextHeader field value for Icmp.
Definition: ip6.lua:32
function mod band(mask1, mask2, result)
Bitwise and.
function ip6Header setSrcString(str)
Set the source address.
function pkt dump(bytes)
Dumps the packet data cast to the best fitting packet struct.
function ip6Header fill(args, pre)
Set all members of the ip6 header.
function ip6Addr get()
Retrieve the IPv6 address.
function ip6Header getSrcString()
Retrieve the IP6 source address.
function ip6Addr add(val)
Add a number to an IPv6 address in-place.
function mod new(n)
function ip6Addr __eq(lhs, rhs)
Test equality of two IPv6 addresses.
local udp
Udp protocol constants.
Definition: udp.lua:23
function mod bor(mask1, mask2, result)
Bitwise or.
function ip6Header getTTLString()
Retrieve the time-to-live.
ip6 PROTO_TCP
NextHeader field value for Tcp.
Definition: ip6.lua:28
function ip6Header getTrafficClass()
Retrieve the traffic class.
function ip6Header setLength(int)
Set the payload length.
function ip6Header getVersionString()
Retrieve the version.
function ip6Header setTTL(int)
Set the time-to-live (TTL).
function ip6Header setDst(addr)
Set the destination address.
function ip6Addr set(addr)
Set the IPv6 address.
function ip6Header getTTL()
Retrieve the time-to-live.
function parseIP6Address(ip)
Parse a string to an IPv6 address.
local eth
Ethernet protocol constants.
Definition: ethernet.lua:24
local ip6
IP6 protocol constants.
Definition: ip6.lua:25
function ip6Header getSrc()
Retrieve the IP6 source address.
local ip
IP4 protocol constants.
Definition: ip4.lua:25
local pkt
Module for packets (rte_mbuf)
Definition: packet.lua:20
function ip6Header getLengthString()
Retrieve the length.
function mod bnot(mask, result)
Bitwise not.
ip6 PROTO_UDP
NextHeader field value for Udp.
Definition: ip6.lua:30
function ip6Header getLength()
Retrieve the length.
n
Create a new array of memory buffers (initialized to nil).
Definition: memory.lua:76
function ip6Addr __sub(val)
Subtract a number from an IPv6 address.
function ip6Header resolveNextHeader()
Resolve which header comes after this one (in a packet).
function ip6Header getVersion()
Retrieve the version.
function ip6Header getTrafficClassString()
Retrieve the traffic class.
function ip6Header getDst()
Retrieve the IP6 destination address.
local ip6Header
Module for ip6_header struct (see headers.lua).
Definition: ip6.lua:89
function ip6Header setVersion(int)
Set the version.
function ip6Header setTrafficClass(int)
Set the traffic class.
function ip6Header setDefaultNamedArgs(pre, namedArgs, nextHeader, accumulatedLength)
Change the default values for namedArguments (for fill/get).
local icmp
Icmp4 protocol constants.
Definition: icmp.lua:25
function ip6Header getNextHeaderString()
Retrieve the next header.
function ip6Header getFlowLabel()
Retrieve the flow label.
function ip6Addr setString(ip)
Set the IPv6 address.
function ip6Addr __add(lhs, rhs)
Add a number to an IPv6 address.
function ip6Header setDstString(str)
Set the destination address.