Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Do a major refactoring of the flow exporter into two apps
This separates the metering code from the export code, which is a cleaner separation. Currently the flow expiry code is in the export app, but it's not clear that that's the right place. It may be more appropriate to put it in the metering app, with expired packets going in some kind of queue perhaps in the flow cache for the other app to read out of.
- Loading branch information
Showing
5 changed files
with
256 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
-- This module implements the FlowCache class, which is used to track | ||
-- flow keys & flow records for IPFIX flow metering and exporting. | ||
|
||
module(..., package.seeall) | ||
|
||
local ffi = require("ffi") | ||
local ctable = require("lib.ctable") | ||
|
||
-- Flow key & flow record FFI type definitions | ||
-- | ||
-- see https://www.iana.org/assignments/ipfix/ipfix.xhtml for | ||
-- information on the IEs for the flow key and record | ||
ffi.cdef[[ | ||
struct flow_key { | ||
uint32_t src_ipv4; /* sourceIPv4Address */ | ||
uint32_t dst_ipv4; /* destinationIPv4Address */ | ||
uint32_t src_ipv6_1; /* sourceIPv6Address */ | ||
uint32_t src_ipv6_2; | ||
uint32_t src_ipv6_3; | ||
uint32_t src_ipv6_4; | ||
uint32_t dst_ipv6_1; /* destinationIPv6Address */ | ||
uint32_t dst_ipv6_2; | ||
uint32_t dst_ipv6_3; | ||
uint32_t dst_ipv6_4; | ||
uint8_t is_ipv6; | ||
uint8_t protocol; /* protocolIdentifier */ | ||
uint16_t src_port; /* sourceTransportPort */ | ||
uint16_t dst_port; /* destinationTransportPort */ | ||
uint16_t __padding; | ||
} __attribute__((packed)); | ||
|
||
struct flow_record { | ||
uint64_t start_time; /* flowStartMilliseconds */ | ||
uint64_t end_time; /* flowEndMilliseconds */ | ||
uint64_t pkt_count; /* packetDeltaCount */ | ||
uint64_t octet_count; /* octetDeltaCount */ | ||
uint32_t ingress; /* ingressInterface */ | ||
uint32_t egress; /* egressInterface */ | ||
uint32_t src_peer_as; /* bgpPrevAdjacentAsNumber */ | ||
uint32_t dst_peer_as; /* bgpNextAdjacentAsNumber */ | ||
uint16_t tcp_control; /* tcpControlBits */ | ||
uint8_t tos; /* ipClassOfService */ | ||
uint8_t __padding; | ||
} __attribute__((packed)); | ||
]] | ||
|
||
FlowCache = {} | ||
|
||
function FlowCache:new(config) | ||
assert(config, "expected configuration table") | ||
|
||
local o = { -- TODO: compute the default cache value | ||
-- based on expected flow amounts? | ||
cache_size = config.cache_size or 20000 } | ||
|
||
local params = { | ||
key_type = ffi.typeof("struct flow_key"), | ||
value_type = ffi.typeof("struct flow_record"), | ||
max_occupancy_rate = 0.4, | ||
initial_size = math.ceil(o.cache_size / 0.4), | ||
} | ||
|
||
o.table = ctable.new(params) | ||
|
||
return setmetatable(o, { __index = self }) | ||
end | ||
|
||
function FlowCache:add(flow_key, flow_record) | ||
self.table:add(flow_key, flow_record) | ||
end | ||
|
||
function FlowCache:lookup(flow_key) | ||
return self.table:lookup_ptr(flow_key) | ||
end | ||
|
||
function FlowCache:iterate() | ||
return self.table:iterate() | ||
end | ||
|
||
function FlowCache:remove(flow_key) | ||
self.table:remove(flow_key) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.