MoonGen
 All Files Functions Variables Pages
lpm.lua
Go to the documentation of this file.
1 ---------------------------------
2 --- @file lpm.lua
3 --- @brief Longest Prefix Matching ...
4 --- @todo TODO docu
5 ---------------------------------
6 
7 local ffi = require "ffi"
8 
9 --require "utils"
10 local band, lshift, rshift = bit.band, bit.lshift, bit.rshift
11 local dpdkc = require "dpdkc"
12 local dpdk = require "dpdk"
13 local serpent = require "Serpent"
14 require "memory"
15 --local burst = require "burst"
16 
17 ffi.cdef [[
18 
19 struct rte_table_lpm_params {
20  uint32_t n_rules;
21  uint32_t entry_unique_size;
22  uint32_t offset;
23 };
24 void * mg_table_lpm_create(void *params, int socket_id, uint32_t entry_size);
25 int mg_table_lpm_free(void *table);
26 int mg_table_entry_add_simple(
27  void *table,
28  uint32_t ip,
29  uint8_t depth,
30  void *entry);
31 int mg_table_lpm_entry_add(
32  void *table,
33  uint32_t ip,
34  uint8_t depth,
35  void *entry,
36  int *key_found,
37  void **entry_ptr);
38 int mg_table_lpm_lookup(
39  void *table,
40  struct rte_mbuf **pkts,
41  uint64_t pkts_mask,
42  uint64_t *lookup_hit_mask,
43  void **entries);
44 int mg_table_lpm_lookup_big_burst(
45  void *table,
46  struct rte_mbuf **pkts,
47  struct mg_bitmask* pkts_mask,
48  struct mg_bitmask* lookup_hit_mask,
49  void **entries);
50 int mg_table_lpm_entry_delete(
51  void *table,
52  uint32_t ip,
53  uint8_t depth,
54  int *key_found,
55  void *entry);
56 void ** mg_lpm_table_allocate_entry_prts(uint16_t n_entries);
57 int printf(const char *fmt, ...);
58 
59 int mg_table_lpm_apply_route(
60  struct rte_mbuf **pkts,
61  struct mg_bitmask* pkts_mask,
62  void **entries,
63  uint16_t offset_entry,
64  uint16_t offset_pkt,
65  uint16_t size);
66 
67 ]]
68 
69 
70 local mod = {}
71 
72 local mg_lpm4Table = {}
73 mod.mg_lpm4Table = mg_lpm4Table
74 mg_lpm4Table.__index = mg_lpm4Table
75 
76 --- Create a new LPM lookup table.
77 --- @param socket optional (default = socket of the calling thread), CPU socket, where memory for the table should be allocated.
78 --- @return the table handler
79 function mod.createLpm4Table(socket, table, entry_ctype)
80  socket = socket or select(2, dpdk.getCore())
81  -- configure parameters for the LPM table
82  local params = ffi.new("struct rte_table_lpm_params")
83  params.n_rules = 1000
84  params.entry_unique_size = 5
85  --params.offset = 128 + 27+4
86  params.offset = 128+ 14 + 12+4
87  return setmetatable({
88  table = table or ffi.gc(ffi.C.mg_table_lpm_create(params, socket, ffi.sizeof(entry_ctype)), function(self)
89  -- FIXME: why is destructor never called?
90  print "lpm garbage"
91  ffi.C.mg_table_lpm_free(self)
92  end),
93  entry_ctype = entry_ctype
94  }, mg_lpm4Table)
95 end
96 
97 -- --- Free the LPM Table
98 -- --- @return 0 on success, error code otherwise
99 -- function mg_lpm4Table:destruct()
100 -- return ffi.C.mg_table_lpm_free(self.table)
101 -- end
102 
103 --- Add an entry to a Table
104 --- @param addr IPv4 network address of the destination network.
105 --- @param depth number of significant bits of the destination network address
106 --- @param entry routing table entry (will be copied)
107 --- @return true if entry was added without error
108 function mg_lpm4Table:addEntry(addr, depth, entry)
109  return 0 == ffi.C.mg_table_entry_add_simple(self.table, addr, depth, entry)
110 end
111 
112 --- Perform IPv4 route lookup for a burst of packets
113 --- This should not be used for single packet lookup, as ist brings
114 --- a significant penalty for bursts <<64
115 --- @param packets Array of mbufs (bufArray), for which the lookup will be performed
116 --- @param mask optional (default = all packets), bitmask, for which packets the lookup should be performed
117 --- @param hitMask Bitmask, where the routed packets are flagged
118 --- with one. This may be the same Bitmask as passed in the mask
119 --- parameter, in this case not routed packets will be cleared in
120 --- the bitmask.
121 --- @param entries Preallocated routing entry Pointers
122 function mg_lpm4Table:lookupBurst(packets, mask, hitMask, entries)
123  -- FIXME: I feel uneasy about this cast, should this cast not be
124  -- done implicitly?
125  return ffi.C.mg_table_lpm_lookup_big_burst(self.table, packets.array, mask.bitmask, hitMask.bitmask, ffi.cast("void **",entries.array))
126 end
127 
128 function mg_lpm4Table:__serialize()
129  return "require 'lpm'; return " .. serpent.addMt(serpent.dumpRaw(self), "require('lpm').mg_lpm4Table"), true
130 end
131 
132 --- Allocates an LPM table entry
133 --- @return The newly allocated entry
134 function mg_lpm4Table:allocateEntry()
135  return ffi.new(self.entry_ctype)
136 end
137 
138 local mg_lpm4EntryPtrs = {}
139 
140 --- Allocates an array of pointers to routing table entries
141 --- This is used during burst lookup, to store references to the
142 --- result entries.
143 --- @param n Number of entry pointers
144 --- @return Wrapper table around the allocated array
145 function mg_lpm4Table:allocateEntryPtrs(n)
146  -- return ffi.C.mg_lpm_table_allocate_entry_prts(n)
147  return setmetatable({
148  array = ffi.new(self.entry_ctype .. "*[?]", n)
149  }, mg_lpm4EntryPtrs)
150 end
151 
152 function mg_lpm4EntryPtrs:__index(k)
153  if type(k) == "number" then
154  return self.array[k - 1]
155  else
156  return mg_lpm4EntryPtrs[k]
157  end
158 end
159 
160 function mod.applyRoute(pkts, mask, entries, entryOffset)
161  entryOffset = entryOffset or 1
162  return ffi.C.mg_table_lpm_apply_route(pkts.array, mask.bitmask, ffi.cast("void **", entries.array), entryOffset, 128, 6)
163 end
164 
165 --- FIXME: this should not be in LPM module. but where?
166 --- Decrements the IP TTL field of all masked packets by one.
167 --- out_mask masks the successfully decremented packets (TTL did not reach zero).
168 function mod.decrementTTL(pkts, in_mask, out_mask, ipv4)
169  ipv4 = ipv4 == nil or ipv4
170  if ipv4 then
171  -- TODO: C implementation might be faster...
172  for i, pkt in ipairs(pkts) do
173  if in_mask[i] then
174  local ipkt = pkt:getIPPacket()
175  local ttl = ipkt.ip4:getTTL()
176  ttl = ttl - 1;
177  ipkt.ip4:setTTL(ttl)
178  if(ttl ~= 0)then
179  out_mask[i] = 1
180  else
181  out_mask[i] = 0
182  end
183  else
184  out_mask[i] = 0
185  end
186  end
187  else
188  errorf("TTL decrement for ipv6 not yet implemented")
189  end
190 end
191 
192 return mod
param n optional(default=2047)
Create a new memory pool.
local ffi
low-level dpdk wrapper
Definition: dpdkc.lua:6
function mg_lpm4Table addEntry(addr, depth, entry)
Add an entry to a Table.
function mod band(mask1, mask2, result)
Bitwise and.
function mod new(n)
function mg_lpm4Table allocateEntryPtrs(n)
Allocates an array of pointers to routing table entries This is used during burst lookup...
function mempool bufArray(n)
Create a new array of memory buffers (initialized to nil).
local mod
high-level dpdk wrapper
Definition: dpdk.lua:6
function printf(str,...)
Print a formatted string.
local ip
IP4 protocol constants.
Definition: ip4.lua:25
function arp lookup(ip)
Perform a lookup in the ARP table.
local pkt
Module for packets (rte_mbuf)
Definition: packet.lua:20
function mod decrementTTL(pkts, in_mask, out_mask, ipv4)
FIXME: this should not be in LPM module.
n
Create a new array of memory buffers (initialized to nil).
Definition: memory.lua:76
function ip4Header getTTL()
Retrieve the time-to-live.
function errorf(str,...)
Print a formatted error string.
function ip4Header setTTL(int)
Set the time-to-live (TTL).
function mg_lpm4Table allocateEntry()
Allocates an LPM table entry.
function mg_lpm4Table lookupBurst(packets, mask, hitMask, entries)
Perform IPv4 route lookup for a burst of packets This should not be used for single packet lookup...
pkt getIPPacket
Cast the packet to either an IP4 (nil/true) or IP6 (false) packet, depending on the passed boolean...
Definition: ip4.lua:321