Add an example to filter looping packets on (for instance) a bond
interface, by recording the egress MAC+VLAN and dropping any packets that
come in on other (related) interfaces with the same MAC+VLAN.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
When libxdp is linked against the submodule libbpf, the order of linker
arguments is important because libxdp.a needs symbols from libbpf.a. Fix up
configure so it ensures this.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Update the version of xdp-tools to pull in some configure changes that
makes interoperating between a libbpf submodule and an xdp-tools submodule
work better, and set the LIBBPF_UNBUILT variable in the top-level configure
to enables this support.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Introduce helper to make is easier to test two struct variations
with the same invalid btf_id struct location.
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
It is a bad habit to rely on process exit to free memory.
Add proper memory free operations.
Using checker command:
valgrind --leak-check=yes ./btf_unit_test
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
Since we now have libxdp as a submodule, we can switch pping over to using
libxdp for loading its XDP program. This requires switching the order of
attachment, because libxdp needs to be fed the BPF object in an unloaded
state (and will load it as part of attaching).
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Use the newly-added logging helpers from logging.h and add a -v option to
increase the effective log level.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Include logging.{h,c} from xdp-tools so utilities can use them for setting
libxdp and libbpf logging.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Pull the latest version of xdp-tools into the submodule. Change the
wildcard pattern for libxdp to not include the XDP programs to avoid
constantly recompiling it.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Instead of having the someone redundantly named 'lib/lib-install' folder,
let's rename it to just 'lib/install', and drop the 'usr/' prefix of the
files installed into that directory. Also, to simplify the configure
script, check in the directory to git so it's always present, and always
include it in the include and linker paths. On clean we just clear out the
contents.
Also, copy over libbpf.a to lib/install/lib alongside libxdp.a instead of
putting libbpf/src in the linker path.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
This adds libxdp as a submodule and link target alongside libbpf. This
should make it just as easy for examples to use libxdp as it currently is
for libbpf. Some hoops need to be jumped through to make libxdp link
against the same version of libbpf as the one we use in this repository.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
The header files included from pping_kern.c include definitions of AF_INET
and AF_INET6, leading to warnings like:
pping_kern.c:25:9: warning: 'AF_INET' macro redefined [-Wmacro-redefined]
^
/usr/include/bits/socket.h:97:9: note: previous definition is here
^
pping_kern.c:26:9: warning: 'AF_INET6' macro redefined [-Wmacro-redefined]
^
/usr/include/bits/socket.h:105:9: note: previous definition is here
^
2 warnings generated.
Fix this by guarding the definitions behind suitable ifdefs.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Now that lib side of xsk_btf__init_xdp_hint check for a valid
btf_id variable, then users of the call doesn't need to check
for the existance of a btf_id member.
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
The connection state had 3 boolean flags related to what state it was
in (is_empty, has_opened and has_closed). Only specific combinations
of these flags really made sense (has_opened/has_closed didn't really
mean anything if is_empty, and if has_closed one would expect is_empty
to be false and has_opened to be true etc.). Therefore, replace these
combinations of boolean values with a singular enum which is used to
check if the flow is empty, waiting to open (seen outgoing packet but
no response), is open or has closed.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Combine the flow state entries for both the "forward" and "reverse"
direction of the flow into a single dualflow state. Change the
flowstate map to use the dualflow state so that state for both
directions can be retrieved using a single map lookup.
As flow states are now kept in pairs, cannot directly create/delete
states from the BPF map each time a flow opens/closes in one
direction. Therefore, update all logic related to creating/deleting
flows. For example, use "empty" slot in dualflow state instead of
creating a new map entry, and only delete the dual flow state entry
once both directions of the flow have closed/timed out.
Some implementation details:
Have implemented a simple memcmp function as I could not get the
__builtin_memcmp function to work (got error "libbpf: failed to
find BTF for extern 'memcmp': -2").
To ensure that both directions of the flow always look up the same
entry, use the "sorted" flow tuple (the (ip, port) pair that is
smaller is always first) as key. This is what the memcmp is used for.
To avoid storing two copies of the flow tuple (src -> dst and dst ->
src) and doing additional memcmps, always store the flow state for the
"sorted" direction as the first direction and the reverse as the
second direction. Then simply check if a flow is sorted or not to
determine which direction in the dual flow state that matches. Have
attempted to at least partially abstract this detail away from most of
the code by adding some get_flowstate_from* helpers.
The dual flow state simply stores the two (single direction) flow
states as the struct members dir1 and dir2. Use these two (admittedly
poorly named) members instead of a single array of size 2 in order to
avoid some issues with the verifier being worried that the array index
might be out of bounds.
Have added some new boolean members to the flow state to keep track of
"connection state". In addition the the previous has_opened, I now
also have a member for if the flow is "empty" or if it has been
closed. These are needed to cope with having to keep individual flow
states for both directions of the flow around as long as one direction
of the flow is used. I plan to replace these boolean "connection
state" members with a single enum in a future commit.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Refactor functions for parsing protocol-specific packet
identifiers (parse_tcp_identifier, parse_icmp6_identifer and
parse_icmp_identifer) so they no longer directly fill in the
packet_info struct. Instead make the functions take additional
pointers as arguments and fill in a protocol_info struct.
The reason for this change is to decouple the
parse_<protocol>_identifier functions from the logic of how the
packet_info struct should be filled. The parse_packet_indentifier is
now solely responsible for filling in the members of packet_info
struct correctly instead of working in tandem with the
parse_<protocol>_identifier, filling in some members each.
This might result in a minimal performance degradation as some values
are now first filled in the protocol_info struct and later copied to
packet_info instead of being filled in directly in packet_info.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Format code using clang-format from the kernel tree. However, leave
code in orginal format in some instances where clang-format clearly
reduces readability of code (ex. do not remove alginment of comments
for struct members and long options).
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Add a counter of outstanding (unmatched) timestamped entires in the
flow state. Before a timestamp lookup is attempted, check that there
are any outstanding timestamps, otherwise avoid the unecessary hash
map lookup.
Use 32 bit counter for outstanding timestamps to allow atomic
increments/decrements using __synch_fetch_and_add. This operation is
not supported on smaller integers, which is why such a large counter
is used. The atomicity is needed because the counter may be
concurrently accessed by both the ingress/egress hook as well as the
periodical map cleanup.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Add conditions that allows removing old flow and timestamp entries
sooner.
For flow map, have added conditions that allow unopened flows and ICMP
flows to be removed earlier than open TCP flows (currently both set to
30 sec instead of 300 sec).
For timestamp entries, allow them to be removed if they're more than
TIMESTAMP_RTT_LIFETIME (currently 8) times higher than the flow's
sRTT.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Add some debug info to the periodical map cleanup process. Push debug
information through the events perf buffer by using newly added
map_clean_event.
The old user space map cleanup process had some simple debug
information that was lost when transitioning to using bpf_iter
instead. Therefore, add back similar (but more extensive) debug
information but now collected from the BPF-side. In addition to stats
on entries deleted by the cleanup process, also include stats on
entries deleted by ePPing itself due to matching (for timestamp
entries) or detecting FIN/RST (for flow entries)
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
To improve the performance of the map cleanup, switch from the
user-spaced loop to using BPF iterators. With BPF iterators, a BPF
program can be run on each element in the map, and can thus be done in
kernel-space. This should hopefully also avoid the issue the previous
userspace loop had with resetting in case an element was removed by
the BPF programs during the cleanup.
Due to removal of userspace logic for map cleanup, no longer provide
any debug information about how many entires there are in each map and
how many of them were removed by the garbage collection. This will be
added back in the next commit.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Explicitly stop the thread which performs periodical map cleanup on
shutdown, before attempting to free up any resources it might use.
For the cleanup order to make more sense, also setup the perf-buffer
before setting up the periodical map cleaning, so that the thread can
be stopped as the first part of the cleanup. This also matches better
with the next couple of commits where map cleaning debug information
will be pushed through the perf-buffer.
Finally, move the addition of the signalhandler earlier in the code to
eliminate a window where it was possible to terminate the program
without relevant cleanup code having a chance to run.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
Allocate the clean_args on the stack of the main function rather than
the stack of setup_periodical_map_cleaning. The clean_args is used by
periodical_map_cleanup from a different thread, so allocating them on
stack for setup_periodical_map_cleaning which goes out of scope
directly after the thread is created opens up for errors where later
function calls may overwrite the arguments, causing unpredictable
behavior.
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
If there were more transmit slots, then we umem free the
packet, but we continued sending it anyhow.
The places tx_pkt() is currently used this never happened.
Still fix the bug.
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>