Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dumping BPF map files (Issue #777) #1044

Merged
merged 12 commits into from
Aug 26, 2020

Conversation

abhishekvijeev
Copy link
Member

Hi,

I have implemented functionality to dump information about BPF map files and also created a template ZDTM static test file for BPF maps. The test currently fails because restore functionality has not yet been implemented. I am currently working on this.

My first goal is to get checkpoint and restore fully working for simple BPF map files, after which I will enhance CRIU to deal with other kinds of BPF files. Kindly let me know whether you would prefer me to prioritize something else.

I await your kind feedback.

Thank you.

@Snorch
Copy link
Member

Snorch commented Apr 29, 2020

Hi @abhishekvijeev!

Let's start with small nits on how you do a pr to criu:

  1. Please add a Siged-off-by line in each commit. (upd: please see https://criu.org/How_to_submit_patches#Sign_your_work)
  2. Each commit should have commit message formated as:
component1[/component2/...]: short commit summary

longer commit description which describes what, why and how exectly you do

Signed-off-by: Name Surname <e-mail>
  1. We want to have pr's containing commits with clean code only, you need to squash all fixup commit to their base and force push the pr. (I mean "Code formatting" commit is a bad practice)

  2. Another thing all related travis tests should pass, it looks like you have some of them failing:

===================== Run zdtm/static/bpf_create_map in h ======================
Start test
./bpf_create_map --pidfile=bpf_create_map.pid --outfile=bpf_create_map.out
Run criu dump
=[log]=> dump/zdtm/static/bpf_create_map/47/1/dump.log
------------------------ grep Error ------------------------
(00.003791) 47 fdinfo 2: pos:              0xe flags:           102001/0
(00.003812) 47 fdinfo 3: pos:                0 flags:           100000/0
(00.003822) Dumping path for 3 fd via self 18 [/home/travis/build/checkpoint-restore/criu/test/zdtm/static]
(00.003841) 47 fdinfo 4: pos:                0 flags:                2/0x1
(00.003868) Error (criu/proc_parse.c:1749): No data left in proc file while parsing bpfmap
(00.003879) Error (criu/proc_parse.c:2114): parse_fdinfo_pid_s: error parsing [map_type:	3] for 19: Success
(00.003887) ----------------------------------------
(00.003898) Error (criu/cr-dump.c:1349): Dump files (pid: 47) failed with -1
(00.004127) 47 was stopped
(00.004215) Unlock network
(00.004220) Unfreezing tasks into 1
(00.004223) 	Unseizing 47 into 1
(00.004235) Error (criu/cr-dump.c:1775): Dumping FAILED.
------------------------ ERROR OVER ------------------------
############## Test zdtm/static/bpf_create_map FAIL at CRIU dump ###############
Send the 9 signal to  47
Wait for zdtm/static/bpf_create_map(47) to die for 0.100000

@abhishekvijeev abhishekvijeev force-pushed the bpf_map branch 5 times, most recently from e5703e6 to f41a705 Compare April 30, 2020 15:48
@abhishekvijeev
Copy link
Member Author

Hi @Snorch ,

Thank you very much for the feedback.

I have made the necessary changes to the commits (will keep this in mind henceforth). Kindly let me know if I can explain any of the commit messages more clearly.

Also, the reason that majority of tests were failing was because I had implemented incomplete boiler-plate code for testing c/r of BPF maps. I have removed the test from the PR for now, and will add it once it is complete (I have described below my thoughts on creating tests for BPF maps).
Therefore, these tests pass successfully now. However, 3 of the tests (#4568.13, #4568.14 and 4568.20) for the ARM platform fail with the following error:

criu/proc_parse.c: In function 'parse_bpfmap':
criu/proc_parse.c:1724:32: error: format '%lu' expects argument of type 'long unsigned int *', but argument 3 has type 'uint64_t *' {aka 'long long unsigned int *'} [-Werror=format=]
if (sscanf(str, "map_flags: %lu", &bpf->map_flags) != 1)
~~^ ~~~~~~~~~~~~~~~
%llu
criu/proc_parse.c:1730:30: error: format '%lu' expects argument of type 'long unsigned int *', but argument 3 has type 'uint64_t *' {aka 'long long unsigned int *'} [-Werror=format=]
if (sscanf(str, "memlock: %lu", &bpf->memlock) != 1)
~~^ ~~~~~~~~~~~~~
%llu

I tried changing the format specifier to %llu, but the code didn't compile on my PC (x86_64). Does this test fail because compilers view the data type 'uint64_t' differently for ARM64 and x86_64? If this is the case, how should I resolve this issue?

Currently, this PR accomplishes 2 tasks:
a) Checkpoint - read information about BPF maps from the proc filesystem and dump this into image files
b) Restore - read information back from the image files and create new BPF map files with the same parameters preserved during checkpointing

However, a significant part of the problem remains unsolved. BPF map files typically contain data in the form of key value pairs. CRIU must therefore checkpoint and restore this data as well. According to my current understanding, the data contained within BPF maps is not made available via the proc
filesystem. Therefore, the way I'm thinking of accomplishing this is by iterating through all the key-value pairs stored in a map when it is about to be checkpointed, and saving them in a new image (similar to what is currently done for pipes' data). Kindly let me know your thoughts on this.

Also, BPF maps can be persisted on /sys/fs/bpf/ using the BPF_PIN_FD command argument. In this case, during restoration, instead of creating a new map with the same parameters (the way this PR currently works), CRIU must be able to open the map on the sys filesystem. This is another problem I will solve.

Once I have accomplished this, I will create 2 ZDTM tests that accomplish the following:

a) - Checkpoint a process that has a BPF map with data
- Restore the BPF map and its data
- Check whether the restored map's parameters and data are the same as before checkpointing

b) - Checkpoint a process that has a BPF map persisted on sysfs
- Restore the BPF map and its data
- Check whether the map is the same as the one persisted on sysfs

Thank you,
Abhishek

@Snorch
Copy link
Member

Snorch commented May 1, 2020

how should I resolve this issue?

PRIu64 should help to print unit64_t https://en.cppreference.com/w/c/types/integer

iterating through all the key-value pairs stored in a map when it is about to be checkpointed, and saving them in a new image

You may also consider protobuf repeated key-value pair entry.

Thanks,
Pavel.

@abhishekvijeev
Copy link
Member Author

Thanks!

@avagin
Copy link
Member

avagin commented May 8, 2020

Could you rebase this PR?

@abhishekvijeev
Copy link
Member Author

Sure @avagin , it's done.

@abhishekvijeev
Copy link
Member Author

I see that the following RPC test is failing:
https://travis-ci.org/github/checkpoint-restore/criu/jobs/684654477#L17709

I tried reproducing the error on my PC by executing the following command:
"make -C test/others/rpc/ run"

'test-c' fails with the following output (obtained from test/others/rpc/build/output_c):

"build/imgs_c
Fail
build/imgs_c
Fail
Cant connect to socket: Connection refused
build/imgs_c
build/imgs_c
Fail
build/imgs_c
Fail
build/imgs_c
Fail
build/imgs_c
Fail
build/imgs_c
Fail
build/imgs_c
Success
build/imgs_c
Success
Restored"

The socket connection was failing. I therefore re-ran the test as the root user, and it passed. Am I correct in assuming that instructing Travis to execute the test as root user is the correct solution to this problem? If so, how can I ensure that Travis passes it?

Thank you.

@avagin
Copy link
Member

avagin commented May 13, 2020

Could you push the test too? It will help to review these changes.

@abhishekvijeev
Copy link
Member Author

The template test I had created earlier for BPF maps?

@abhishekvijeev
Copy link
Member Author

Hi @Snorch @avagin ,

I don't think it's possible to checkpoint a BPF map file's data, as Linux's BPF system call API doesn't provide a means to duplicate BPF map data (like 'tee' for pipes). I have explained the problem in this email:
https://lists.openvz.org/pipermail/criu/2020-May/044995.html

It's meaningless to continue work on BPF map files (#777) unless Linux's BPF API evolves to support dumping map data. I mean, I don't see the point in only reading info from the proc filesystem and restoring an identical map without its data. Do let me know if you think otherwise (i.e if you think there is value in only dumping and restoring a map without its data). Else, I shall close this PR.

Thank you.

@abhishekvijeev
Copy link
Member Author

Hi @Snorch @avagin ,

Could you kindly let me know whether I am correct in assuming that I've hit a dead end and if so, can I close this PR?

Thank you.

@avagin
Copy link
Member

avagin commented Jun 8, 2020

@abhishekvijeev This is not a dead end, you hit a new challenge of extending linux API-s. While we were developing CRIU, we met similar problems a few time. Now, you need to discuss a new API for dumping BPF files with the kernel community and implement it.

@avagin avagin reopened this Jun 8, 2020
@abhishekvijeev
Copy link
Member Author

Thank you for the response @avagin
Sure, I'll get to work on this.

@abhishekvijeev abhishekvijeev force-pushed the bpf_map branch 2 times, most recently from fca68f1 to b94b87e Compare June 13, 2020 17:47
@abhishekvijeev abhishekvijeev force-pushed the bpf_map branch 2 times, most recently from ea4eed6 to bc0db39 Compare June 19, 2020 11:33
@abhishekvijeev abhishekvijeev force-pushed the bpf_map branch 7 times, most recently from 527d926 to b615e71 Compare August 17, 2020 16:47
@abhishekvijeev
Copy link
Member Author

Hi,

Travis tests pass now. The Fedora rawhide tests fail, but I see that this has been occurring across CRIU builds over that past couple of days - I therefore assume that this is a temporary problem independent of this PR.

I have not added a CentOS 8 test or upgraded the docker base images because there was no need to. I will be glad to do these if necessary.

Please let me know if I can improve this PR in any way before it's merged.

Thank you.

This commit adds protobuf definitions needed to checkpoint and
restore BPF map files along with the data they contain

Source files added:

* bpfmap-file.proto - Stores the meta-data about BPF maps

* bpfmap-data.proto - Stores the data (key-value pairs) contained
in BPF maps

Source files modified:

* fdinfo.proto - Added BPF map as a new kind of file descriptor.
'message file_entry' can now hold information about BPF map file
descriptors

* Makefile - Now generates build artifacts for bpfmap-file.proto
and bpfmap-data.proto

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit defines constants and includes necessary headers to c/r
BPF maps

Source files modified:

* magic.h - Defining BPFMAP_FILE_MAGIC and BPFMAP_DATA_MAGIC

* image-desc.h - Defining CR_FD_BPFMAP_FILE and CR_FD_BPFMAP_DATA

* image-desc.c - Create new entries for bpfmap-file and bpfmap-data
in CRIU's file descriptor set

* protobuf-desc.h - Defining PB_BPFMAP_FILE and PB_BPFMAP_DATA

* protobuf-desc.c - Including headers for BPF map protobuf images

Signed-off-by: Abhishek Vijeev <[email protected]>
Source files modified:

* Makefile.config - Checks whether libbpf is installed on the system.
If so, we add -lbpf to LIBS_FEATURES, -DCONFIG_HAS_LIBBPF to
FEATURE_DEFINES and set CONFIG_HAS_LIBBPF. This allows us to check for
the presence of libbpf before compiling or executing BPF c/r code and
ZDTM tests.

* Makefile - Set CONFIG_HAS_LIBBPF to clean all files.

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit enables CRIU to:
(a) identify an anonymous inode as being a BPF map
(b) parse information about BPF maps from procfs

Source files modified:

* files.c - Checks anonymous inodes to see whether they are BPF maps.
If so, sets struct fdtype_ops *ops to a structure that knows how to
dump BPF maps

* proc_parse.c - Function parse_fdinfo_pid_s() now checks whether the
current file being processed is a BPF map. If so, it calls a newly
defined function parse_bpfmap() which knows how to parse information
about BPF maps from procfs

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit enables CRIU to dump meta-data about BPF maps files by
prividing the structures and functions needed by other parts of the
code-base.

Source files added:

* bpfmap.c - defines new structures and functions:

    (a) struct fdtype_ops bpfmap_dump_ops:
            sets up the function handler to dump BPF maps

    (b) is_bpfmap_link():
            checks whether an anonymous inode is a BPF map file

    (c) dump_one_bpfmap():
            parses information for a BPF map file from procfs and
			dumps it

* include/bpfmap.h - structure and function declarations

Source files modified:

* Makefile.crtools - generates build artifacts for bpfmap.c

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit enables CRIU to dump data(key-value) pairs stored in BPF
maps

Source files modified:

* bpfmap.c

    - Function dump_one_bpfmap_data() reads the map's keys and
    values into two buffers using bpf_map_lookup_batch() and then
    writes them out to a protobuf image along with the number of
    key-value pairs read

    - Function dump_one_bpfmap() now dumps the data as well before
    returning

* include/bpfmap.h - Includes headers and declares functions needed to
dump BPF map data

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit enables CRIT to decode the contents of a protobuf image
that stores information related to BPF map

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit enables CRIU to restore a process' BPF map file
descriptors.

Source files modified:

* bpfmap.c - Structure and function definitions needed to:
    (a) collect a BPF map's information from its protobuf image
    (b) create and open a BPF map with the same parameters as when
    it was dumped
    (c) add the newly opened BPF map to the process' file descriptor
    list

* include/bpfmap.h - Structure declarations for restoring BPF maps

* files.c - Collects a BPF map's file entry during the restoration
phase

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit restores the data of BPF maps. A hash table (indexed by
the map's id) is used to store data objects for multiple BPF map
files that a process may have opened. Collisions are resolved with
chaining using a linked list.

Source files modified:

* bpfmap.c - Structure and function definitions needed to:
    (a) collect the protobuf image containing BPF map data
    (b) read the BPF map's data from the image and store it in the
    hash table
    (c) restore the map's data using bpf_map_update_batch()

* include/bpfmap.h
    - Defines the size of the hash table and maks to be used while
	indexing into it
	- Structure and function declarations that are used while restoring
	BPF map data

* cr-restore.c - Collects the protobuf image containing BPF map data
during the restoration phase

Signed-off-by: Abhishek Vijeev <[email protected]>
This commit adds ZDTM tests for c/r of processes with BPF maps as open
files

Source files added:

* zdtm/static/bpf_hash.c - Tests for c/r of the data and meta-data of
BPF map type BPF_MAP_TYPE_HASH

* zdtm/static/bpf_array.c - Tests for c/r of the data and meta-data
of BPF map type BPF_MAP_TYPE_ARRAY

Source files modified:

* zdtm/static/Makefile - Generating build artifacts for BPF tests

Signed-off-by: Abhishek Vijeev <[email protected]>
Source files modified:

* travis/vagrant.sh - Adding libbpf-devel

Signed-off-by: Abhishek Vijeev <[email protected]>
This change fixes the error:
error: 'security_context_t' is deprecated
[-Werror=deprecated-declarations]

Source files modified:

* lsm.c
* net.c

Please refer to:
SELinuxProject/selinux@9eb9c9327

Signed-off-by: Abhishek Vijeev <[email protected]>
Copy link
Member

@rst0git rst0git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done!

@abhishekvijeev
Copy link
Member Author

Thank you!

@avagin avagin merged commit 7a576bf into checkpoint-restore:criu-dev Aug 26, 2020
@avagin
Copy link
Member

avagin commented Aug 26, 2020

Applied. Thanks a lot!

@abhishekvijeev
Copy link
Member Author

That's great!

Thanks so much to the community for helping me work towards getting this PR merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants