├── .github └── workflows │ └── lint.yml ├── .gitignore ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── build.rs ├── completions ├── README.md ├── bash │ └── criu-coordinator ├── fish │ └── criu-coordinator.fish └── zsh │ └── _criu-coordinator ├── example-config └── criu-coordinator.json ├── proto ├── criu │ ├── LICENSE │ ├── apparmor.proto │ ├── autofs.proto │ ├── binfmt-misc.proto │ ├── bpfmap-data.proto │ ├── bpfmap-file.proto │ ├── cgroup.proto │ ├── core-aarch64.proto │ ├── core-arm.proto │ ├── core-mips.proto │ ├── core-ppc64.proto │ ├── core-s390.proto │ ├── core-x86.proto │ ├── core.proto │ ├── cpuinfo.proto │ ├── creds.proto │ ├── eventfd.proto │ ├── eventpoll.proto │ ├── ext-file.proto │ ├── fdinfo.proto │ ├── fh.proto │ ├── fifo.proto │ ├── file-lock.proto │ ├── fown.proto │ ├── fs.proto │ ├── fsnotify.proto │ ├── ghost-file.proto │ ├── img-streamer.proto │ ├── inventory.proto │ ├── ipc-desc.proto │ ├── ipc-msg.proto │ ├── ipc-sem.proto │ ├── ipc-shm.proto │ ├── ipc-var.proto │ ├── macvlan.proto │ ├── memfd.proto │ ├── mm.proto │ ├── mnt.proto │ ├── netdev.proto │ ├── ns.proto │ ├── opts.proto │ ├── packet-sock.proto │ ├── pagemap.proto │ ├── pidns.proto │ ├── pipe-data.proto │ ├── pipe.proto │ ├── pstree.proto │ ├── regfile.proto │ ├── remap-file-path.proto │ ├── rlimit.proto │ ├── rpc.proto │ ├── sa.proto │ ├── seccomp.proto │ ├── siginfo.proto │ ├── signalfd.proto │ ├── sit.proto │ ├── sk-inet.proto │ ├── sk-netlink.proto │ ├── sk-opts.proto │ ├── sk-packet.proto │ ├── sk-unix.proto │ ├── stats.proto │ ├── sysctl.proto │ ├── tcp-stream.proto │ ├── time.proto │ ├── timens.proto │ ├── timer.proto │ ├── timerfd.proto │ ├── tty.proto │ ├── tun.proto │ ├── userns.proto │ ├── utsns.proto │ └── vma.proto └── image.proto ├── src ├── cli.rs ├── client.rs ├── constants.rs ├── lib.rs ├── logger.rs ├── main.rs ├── pipeline.rs ├── pipeline │ ├── criu.rs │ ├── monitor.rs │ ├── ord_by.rs │ ├── protobuf.rs │ ├── streamer.rs │ └── unix_pipe.rs ├── server.rs └── server │ └── client_status.rs └── tests ├── Makefile ├── c1 └── criu-coordinator.json ├── c2 └── criu-coordinator.json ├── c3 └── criu-coordinator.json ├── kubescr-add-dependencies.py └── loop.c /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | lint: 6 | runs-on: ubuntu-latest 7 | 8 | steps: 9 | - name: Checkout code 10 | uses: actions/checkout@v3 11 | 12 | - name: Install Dependencies 13 | run: | 14 | sudo apt-get update 15 | sudo apt-get install -qqy protobuf-compiler libprotobuf-dev 16 | 17 | - name: Setup Rust 18 | uses: actions-rs/toolchain@v1 19 | with: 20 | toolchain: stable 21 | override: true 22 | components: clippy 23 | 24 | - name: Run lint 25 | run: make lint 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | criu-coordinator 2 | 3 | # Generated by Cargo for compiled files and executables 4 | debug/ 5 | target/ 6 | 7 | # Remove Cargo.lock from gitignore when creating an executable 8 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 9 | Cargo.lock 10 | 11 | # Backup files generated by rustfmt 12 | **/*.rs.bk 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "criu-coordinator" 3 | version = "0.1.0" 4 | authors = ["Radostin Stoyanov "] 5 | description = "Coordinates checkpointing and restore among CRIU processes in distributed applications." 6 | edition = "2018" 7 | license = "Apache-2.0" 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | clap = { version = "4.1.11", features = ["derive"] } 13 | clap_complete = "4.1.5" 14 | log = { version = "0.4", features = ["std"] } 15 | json = "*" 16 | libc = "0.2" 17 | nix = "0.26.2" 18 | slab = "0.4.8" 19 | lazy_static = "1.4.0" 20 | serde = "1.0.159" 21 | bytes = "1.4.0" 22 | prost = "0.11.8" 23 | log-panics = { version = "2.1.0", features = ["with-backtrace"] } 24 | config = "0.13.1" 25 | 26 | [build-dependencies] 27 | prost-build = "0.11.8" 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 University of Oxford. 2 | # Copyright (c) 2023 Red Hat, Inc. 3 | # All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | NAME = criu-coordinator 18 | 19 | .PHONY: all 20 | all: $(NAME) ## Build criu-coordinator binary 21 | 22 | BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions 23 | ZSHINSTALLDIR=${PREFIX}/share/zsh/site-functions 24 | FISHINSTALLDIR=${PREFIX}/share/fish/vendor_completions.d 25 | 26 | PREFIX ?= $(DESTDIR)/usr/local 27 | BINDIR ?= $(PREFIX)/bin 28 | 29 | BUILD ?= release 30 | 31 | BUILD_FLAGS= 32 | 33 | ifeq ($(BUILD),release) 34 | BUILD_FLAGS+=--release 35 | endif 36 | 37 | DEPS = $(wildcard src/*.rs src/**/*.rs) Cargo.toml 38 | 39 | CARGO=$(HOME)/.cargo/bin/cargo 40 | ifeq (,$(wildcard $(CARGO))) 41 | CARGO=cargo 42 | endif 43 | 44 | target/$(BUILD)/$(NAME): $(DEPS) 45 | $(CARGO) build $(BUILD_FLAGS) 46 | 47 | $(NAME): target/$(BUILD)/$(NAME) 48 | cp -a $< $@ 49 | 50 | .PHONY: install 51 | install: target/$(BUILD)/$(NAME) install.completions ## Install binary and completions 52 | @echo " INSTALL " $< 53 | @mkdir -p $(DESTDIR)$(BINDIR) 54 | @install -m0755 $< $(BINDIR)/$(NAME) 55 | 56 | .PHONY: uninstall 57 | uninstall: uninstall.completions ## Uninstall binary and completions 58 | @echo " UNINSTALL" $(NAME) 59 | $(RM) $(addprefix $(DESTDIR)$(BINDIR)/,$(NAME)) 60 | 61 | .PHONY: lint 62 | lint: ## Run clippy lint checks 63 | $(CARGO) clippy --all-targets --all-features -- -D warnings 64 | 65 | .PHONY: lint-fix 66 | lint-fix: ## Automatically fix lint issues 67 | $(CARGO) clippy --fix --all-targets --all-features -- -D warnings 68 | 69 | .PHONY: test 70 | test: ## Run tests 71 | $(CARGO) test 72 | 73 | .PHONY: completions 74 | completions: $(NAME) ## Generate shell completions 75 | declare -A outfiles=([bash]=%s [zsh]=_%s [fish]=%s.fish);\ 76 | for shell in $${!outfiles[*]}; do \ 77 | outfile=$$(printf "completions/$$shell/$${outfiles[$$shell]}" $(NAME)); \ 78 | ./$(NAME) completions $$shell >| $$outfile; \ 79 | done 80 | 81 | .PHONY: validate.completions 82 | validate.completions: SHELL:=/usr/bin/env bash # Set shell to bash for this target 83 | validate.completions: ## Validate generated completions with their shells 84 | # Check if the files can be loaded by the shell 85 | . completions/bash/$(NAME) 86 | if [ -x /bin/zsh ]; then \ 87 | /bin/zsh -c 'autoload -Uz compinit; compinit; source completions/zsh/_$(NAME)'; \ 88 | fi 89 | if [ -x /bin/fish ]; then /bin/fish completions/fish/$(NAME).fish; fi 90 | 91 | .PHONY: install.completions 92 | install.completions: ## Install generated completions 93 | @install -d -m 755 ${DESTDIR}${BASHINSTALLDIR} 94 | @install -m 644 completions/bash/$(NAME) ${DESTDIR}${BASHINSTALLDIR} 95 | @install -d -m 755 ${DESTDIR}${ZSHINSTALLDIR} 96 | @install -m 644 completions/zsh/_$(NAME) ${DESTDIR}${ZSHINSTALLDIR} 97 | @install -d -m 755 ${DESTDIR}${FISHINSTALLDIR} 98 | @install -m 644 completions/fish/$(NAME).fish ${DESTDIR}${FISHINSTALLDIR} 99 | 100 | .PHONY: uninstall.completions 101 | uninstall.completions: ## Remove installed completions 102 | @$(RM) $(addprefix ${DESTDIR}${BASHINSTALLDIR}/,$(NAME)) 103 | @$(RM) $(addprefix ${DESTDIR}${ZSHINSTALLDIR}/,_$(NAME)) 104 | @$(RM) $(addprefix ${DESTDIR}${FISHINSTALLDIR}/,$(NAME).fish) 105 | 106 | .PHONY: clean 107 | clean: ## Clean build artifacts 108 | rm -rf target $(NAME) 109 | 110 | .PHONY: help 111 | help: ## Show this help message 112 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \n\nTargets:\n"} \ 113 | /^[a-zA-Z0-9_.-]+:.*##/ { printf " * \033[36m%s\033[0m -%s\n", $$1, $$2 }' $(MAKEFILE_LIST) 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CRIU Coordinator 2 | ==================== 3 | 4 | _criu-coordinator_ enables checkpoint coordination among multiple processes, containers, or Kubernetes Pods. 5 | 6 | Usage Example 7 | ------------- 8 | 9 | 1. Start coordinator server 10 | 11 | ```console 12 | criu-coordinator server --address 127.0.0.1 --port 8080 13 | ``` 14 | 15 | 2. Create directory for CRIU image files and copy `criu-coordinator.json` 16 | 17 | ```console 18 | mkdir /tmp/test 19 | cp example-config/criu-coordinator.json /tmp/test/ 20 | ``` 21 | 22 | 3. Configure CRIU to use criu-coordinator 23 | 24 | ```console 25 | mkdir -p /etc/criu/ 26 | echo action-script="$(which criu-coordinator)" | sudo tee /etc/criu/default.conf 27 | ``` 28 | 29 | License 30 | ------- 31 | 32 | criu-coordinator is licensed under the 33 | [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0). 34 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | use std::path::PathBuf; 21 | 22 | fn get_proto_files(dir: &str) -> Vec { 23 | std::fs::read_dir(dir).expect("read_dir failed") 24 | .map(|file| file.unwrap().path()) 25 | .filter(|path| path.extension() == Some(std::ffi::OsStr::new("proto"))) 26 | .collect() 27 | } 28 | 29 | fn main() { 30 | prost_build::compile_protos(&get_proto_files("proto/"), 31 | &[PathBuf::from("proto/")]) 32 | .expect("Failed to generate protobuf wrappers ./proto/*.proto"); 33 | 34 | prost_build::compile_protos(&get_proto_files("proto/criu"), 35 | &[PathBuf::from("proto/criu")]) 36 | .expect("Failed to generate protobuf wrappers for ./proto/criu/*.proto"); 37 | } 38 | -------------------------------------------------------------------------------- /completions/README.md: -------------------------------------------------------------------------------- 1 | # Shell completion scripts 2 | 3 | checkpointctl offers shell completion scripts for bash, zsh and fish. These completion scripts are generated by `make completions`; do not 4 | edit these files directly. To install them you can run `sudo make install.completions`.Add commentMore actions 5 | 6 | For information about these scripts see `criu-coordinator completions --help`. 7 | -------------------------------------------------------------------------------- /completions/bash/criu-coordinator: -------------------------------------------------------------------------------- 1 | _criu-coordinator() { 2 | local i cur prev opts cmd 3 | COMPREPLY=() 4 | if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then 5 | cur="$2" 6 | else 7 | cur="${COMP_WORDS[COMP_CWORD]}" 8 | fi 9 | prev="$3" 10 | cmd="" 11 | opts="" 12 | 13 | for i in "${COMP_WORDS[@]:0:COMP_CWORD}" 14 | do 15 | case "${cmd},${i}" in 16 | ",$1") 17 | cmd="criu__coordinator" 18 | ;; 19 | criu__coordinator,client) 20 | cmd="criu__coordinator__client" 21 | ;; 22 | criu__coordinator,completions) 23 | cmd="criu__coordinator__completions" 24 | ;; 25 | criu__coordinator,help) 26 | cmd="criu__coordinator__help" 27 | ;; 28 | criu__coordinator,server) 29 | cmd="criu__coordinator__server" 30 | ;; 31 | criu__coordinator__help,client) 32 | cmd="criu__coordinator__help__client" 33 | ;; 34 | criu__coordinator__help,completions) 35 | cmd="criu__coordinator__help__completions" 36 | ;; 37 | criu__coordinator__help,help) 38 | cmd="criu__coordinator__help__help" 39 | ;; 40 | criu__coordinator__help,server) 41 | cmd="criu__coordinator__help__server" 42 | ;; 43 | *) 44 | ;; 45 | esac 46 | done 47 | 48 | case "${cmd}" in 49 | criu__coordinator) 50 | opts="-h -V --help --version client server completions help" 51 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then 52 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 53 | return 0 54 | fi 55 | case "${prev}" in 56 | *) 57 | COMPREPLY=() 58 | ;; 59 | esac 60 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 61 | return 0 62 | ;; 63 | criu__coordinator__client) 64 | opts="-i -d -a -D -s -o -h --address --port --id --deps --action --images-dir --stream --log-file --help" 65 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then 66 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 67 | return 0 68 | fi 69 | case "${prev}" in 70 | --address) 71 | COMPREPLY=($(compgen -f "${cur}")) 72 | return 0 73 | ;; 74 | --port) 75 | COMPREPLY=($(compgen -f "${cur}")) 76 | return 0 77 | ;; 78 | --id) 79 | COMPREPLY=($(compgen -f "${cur}")) 80 | return 0 81 | ;; 82 | -i) 83 | COMPREPLY=($(compgen -f "${cur}")) 84 | return 0 85 | ;; 86 | --deps) 87 | COMPREPLY=($(compgen -f "${cur}")) 88 | return 0 89 | ;; 90 | -d) 91 | COMPREPLY=($(compgen -f "${cur}")) 92 | return 0 93 | ;; 94 | --action) 95 | COMPREPLY=($(compgen -f "${cur}")) 96 | return 0 97 | ;; 98 | -a) 99 | COMPREPLY=($(compgen -f "${cur}")) 100 | return 0 101 | ;; 102 | --images-dir) 103 | COMPREPLY=($(compgen -f "${cur}")) 104 | return 0 105 | ;; 106 | -D) 107 | COMPREPLY=($(compgen -f "${cur}")) 108 | return 0 109 | ;; 110 | --log-file) 111 | COMPREPLY=($(compgen -f "${cur}")) 112 | return 0 113 | ;; 114 | -o) 115 | COMPREPLY=($(compgen -f "${cur}")) 116 | return 0 117 | ;; 118 | *) 119 | COMPREPLY=() 120 | ;; 121 | esac 122 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 123 | return 0 124 | ;; 125 | criu__coordinator__completions) 126 | opts="-h --help " 127 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then 128 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 129 | return 0 130 | fi 131 | case "${prev}" in 132 | *) 133 | COMPREPLY=() 134 | ;; 135 | esac 136 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 137 | return 0 138 | ;; 139 | criu__coordinator__help) 140 | opts="client server completions help" 141 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then 142 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 143 | return 0 144 | fi 145 | case "${prev}" in 146 | *) 147 | COMPREPLY=() 148 | ;; 149 | esac 150 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 151 | return 0 152 | ;; 153 | criu__coordinator__help__client) 154 | opts="" 155 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then 156 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 157 | return 0 158 | fi 159 | case "${prev}" in 160 | *) 161 | COMPREPLY=() 162 | ;; 163 | esac 164 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 165 | return 0 166 | ;; 167 | criu__coordinator__help__completions) 168 | opts="" 169 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then 170 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 171 | return 0 172 | fi 173 | case "${prev}" in 174 | *) 175 | COMPREPLY=() 176 | ;; 177 | esac 178 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 179 | return 0 180 | ;; 181 | criu__coordinator__help__help) 182 | opts="" 183 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then 184 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 185 | return 0 186 | fi 187 | case "${prev}" in 188 | *) 189 | COMPREPLY=() 190 | ;; 191 | esac 192 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 193 | return 0 194 | ;; 195 | criu__coordinator__help__server) 196 | opts="" 197 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then 198 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 199 | return 0 200 | fi 201 | case "${prev}" in 202 | *) 203 | COMPREPLY=() 204 | ;; 205 | esac 206 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 207 | return 0 208 | ;; 209 | criu__coordinator__server) 210 | opts="-a -p -o -h --address --port --log-file --help" 211 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then 212 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 213 | return 0 214 | fi 215 | case "${prev}" in 216 | --address) 217 | COMPREPLY=($(compgen -f "${cur}")) 218 | return 0 219 | ;; 220 | -a) 221 | COMPREPLY=($(compgen -f "${cur}")) 222 | return 0 223 | ;; 224 | --port) 225 | COMPREPLY=($(compgen -f "${cur}")) 226 | return 0 227 | ;; 228 | -p) 229 | COMPREPLY=($(compgen -f "${cur}")) 230 | return 0 231 | ;; 232 | --log-file) 233 | COMPREPLY=($(compgen -f "${cur}")) 234 | return 0 235 | ;; 236 | -o) 237 | COMPREPLY=($(compgen -f "${cur}")) 238 | return 0 239 | ;; 240 | *) 241 | COMPREPLY=() 242 | ;; 243 | esac 244 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 245 | return 0 246 | ;; 247 | esac 248 | } 249 | 250 | if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then 251 | complete -F _criu-coordinator -o nosort -o bashdefault -o default criu-coordinator 252 | else 253 | complete -F _criu-coordinator -o bashdefault -o default criu-coordinator 254 | fi 255 | -------------------------------------------------------------------------------- /completions/fish/criu-coordinator.fish: -------------------------------------------------------------------------------- 1 | # Print an optspec for argparse to handle cmd's options that are independent of any subcommand. 2 | function __fish_criu_coordinator_global_optspecs 3 | string join \n h/help V/version 4 | end 5 | 6 | function __fish_criu_coordinator_needs_command 7 | # Figure out if the current invocation already has a command. 8 | set -l cmd (commandline -opc) 9 | set -e cmd[1] 10 | argparse -s (__fish_criu_coordinator_global_optspecs) -- $cmd 2>/dev/null 11 | or return 12 | if set -q argv[1] 13 | # Also print the command, so this can be used to figure out what it is. 14 | echo $argv[1] 15 | return 1 16 | end 17 | return 0 18 | end 19 | 20 | function __fish_criu_coordinator_using_subcommand 21 | set -l cmd (__fish_criu_coordinator_needs_command) 22 | test -z "$cmd" 23 | and return 1 24 | contains -- $cmd[1] $argv 25 | end 26 | 27 | complete -c criu-coordinator -n "__fish_criu_coordinator_needs_command" -s h -l help -d 'Print help' 28 | complete -c criu-coordinator -n "__fish_criu_coordinator_needs_command" -s V -l version -d 'Print version' 29 | complete -c criu-coordinator -n "__fish_criu_coordinator_needs_command" -f -a "client" -d 'Run as client' 30 | complete -c criu-coordinator -n "__fish_criu_coordinator_needs_command" -f -a "server" -d 'Run as server' 31 | complete -c criu-coordinator -n "__fish_criu_coordinator_needs_command" -f -a "completions" -d 'Generate shell completions' 32 | complete -c criu-coordinator -n "__fish_criu_coordinator_needs_command" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' 33 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -l address -d 'Address to connect the client to' -r 34 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -l port -d 'Port to connect the client to' -r 35 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -s i -l id -d 'Unique client ID' -r 36 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -s d -l deps -d 'A colon-separated list of dependency IDs' -r 37 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -s a -l action -d 'Action name indicating the stage of checkpoint/restore' -r 38 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -s D -l images-dir -d 'Images directory where the stream socket is created' -r 39 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -s o -l log-file -d 'Log file name' -r 40 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -s s -l stream -d 'Use checkpoint streaming' 41 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand client" -s h -l help -d 'Print help' 42 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand server" -s a -l address -d 'Address to bind the server to' -r 43 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand server" -s p -l port -d 'Port to bind the server to' -r 44 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand server" -s o -l log-file -d 'Log file name' -r 45 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand server" -s h -l help -d 'Print help' 46 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand completions" -s h -l help -d 'Print help' 47 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand help; and not __fish_seen_subcommand_from client server completions help" -f -a "client" -d 'Run as client' 48 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand help; and not __fish_seen_subcommand_from client server completions help" -f -a "server" -d 'Run as server' 49 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand help; and not __fish_seen_subcommand_from client server completions help" -f -a "completions" -d 'Generate shell completions' 50 | complete -c criu-coordinator -n "__fish_criu_coordinator_using_subcommand help; and not __fish_seen_subcommand_from client server completions help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' 51 | -------------------------------------------------------------------------------- /completions/zsh/_criu-coordinator: -------------------------------------------------------------------------------- 1 | #compdef criu-coordinator 2 | 3 | autoload -U is-at-least 4 | 5 | _criu-coordinator() { 6 | typeset -A opt_args 7 | typeset -a _arguments_options 8 | local ret=1 9 | 10 | if is-at-least 5.2; then 11 | _arguments_options=(-s -S -C) 12 | else 13 | _arguments_options=(-s -C) 14 | fi 15 | 16 | local context curcontext="$curcontext" state line 17 | _arguments "${_arguments_options[@]}" : \ 18 | '-h[Print help]' \ 19 | '--help[Print help]' \ 20 | '-V[Print version]' \ 21 | '--version[Print version]' \ 22 | ":: :_criu-coordinator_commands" \ 23 | "*::: :->criu-coordinator" \ 24 | && ret=0 25 | case $state in 26 | (criu-coordinator) 27 | words=($line[1] "${words[@]}") 28 | (( CURRENT += 1 )) 29 | curcontext="${curcontext%:*:*}:criu-coordinator-command-$line[1]:" 30 | case $line[1] in 31 | (client) 32 | _arguments "${_arguments_options[@]}" : \ 33 | '--address=[Address to connect the client to]:ADDRESS:_default' \ 34 | '--port=[Port to connect the client to]:PORT:_default' \ 35 | '-i+[Unique client ID]:ID:_default' \ 36 | '--id=[Unique client ID]:ID:_default' \ 37 | '-d+[A colon-separated list of dependency IDs]:DEPS:_default' \ 38 | '--deps=[A colon-separated list of dependency IDs]:DEPS:_default' \ 39 | '-a+[Action name indicating the stage of checkpoint/restore]:ACTION:_default' \ 40 | '--action=[Action name indicating the stage of checkpoint/restore]:ACTION:_default' \ 41 | '-D+[Images directory where the stream socket is created]:IMAGES_DIR:_default' \ 42 | '--images-dir=[Images directory where the stream socket is created]:IMAGES_DIR:_default' \ 43 | '-o+[Log file name]:LOG_FILE:_default' \ 44 | '--log-file=[Log file name]:LOG_FILE:_default' \ 45 | '-s[Use checkpoint streaming]' \ 46 | '--stream[Use checkpoint streaming]' \ 47 | '-h[Print help]' \ 48 | '--help[Print help]' \ 49 | && ret=0 50 | ;; 51 | (server) 52 | _arguments "${_arguments_options[@]}" : \ 53 | '-a+[Address to bind the server to]:ADDRESS:_default' \ 54 | '--address=[Address to bind the server to]:ADDRESS:_default' \ 55 | '-p+[Port to bind the server to]:PORT:_default' \ 56 | '--port=[Port to bind the server to]:PORT:_default' \ 57 | '-o+[Log file name]:LOG_FILE:_default' \ 58 | '--log-file=[Log file name]:LOG_FILE:_default' \ 59 | '-h[Print help]' \ 60 | '--help[Print help]' \ 61 | && ret=0 62 | ;; 63 | (completions) 64 | _arguments "${_arguments_options[@]}" : \ 65 | '-h[Print help]' \ 66 | '--help[Print help]' \ 67 | ':shell -- Shell type (e.g., bash, zsh, fish, powershell, elvish):_default' \ 68 | && ret=0 69 | ;; 70 | (help) 71 | _arguments "${_arguments_options[@]}" : \ 72 | ":: :_criu-coordinator__help_commands" \ 73 | "*::: :->help" \ 74 | && ret=0 75 | 76 | case $state in 77 | (help) 78 | words=($line[1] "${words[@]}") 79 | (( CURRENT += 1 )) 80 | curcontext="${curcontext%:*:*}:criu-coordinator-help-command-$line[1]:" 81 | case $line[1] in 82 | (client) 83 | _arguments "${_arguments_options[@]}" : \ 84 | && ret=0 85 | ;; 86 | (server) 87 | _arguments "${_arguments_options[@]}" : \ 88 | && ret=0 89 | ;; 90 | (completions) 91 | _arguments "${_arguments_options[@]}" : \ 92 | && ret=0 93 | ;; 94 | (help) 95 | _arguments "${_arguments_options[@]}" : \ 96 | && ret=0 97 | ;; 98 | esac 99 | ;; 100 | esac 101 | ;; 102 | esac 103 | ;; 104 | esac 105 | } 106 | 107 | (( $+functions[_criu-coordinator_commands] )) || 108 | _criu-coordinator_commands() { 109 | local commands; commands=( 110 | 'client:Run as client' \ 111 | 'server:Run as server' \ 112 | 'completions:Generate shell completions' \ 113 | 'help:Print this message or the help of the given subcommand(s)' \ 114 | ) 115 | _describe -t commands 'criu-coordinator commands' commands "$@" 116 | } 117 | (( $+functions[_criu-coordinator__client_commands] )) || 118 | _criu-coordinator__client_commands() { 119 | local commands; commands=() 120 | _describe -t commands 'criu-coordinator client commands' commands "$@" 121 | } 122 | (( $+functions[_criu-coordinator__completions_commands] )) || 123 | _criu-coordinator__completions_commands() { 124 | local commands; commands=() 125 | _describe -t commands 'criu-coordinator completions commands' commands "$@" 126 | } 127 | (( $+functions[_criu-coordinator__help_commands] )) || 128 | _criu-coordinator__help_commands() { 129 | local commands; commands=( 130 | 'client:Run as client' \ 131 | 'server:Run as server' \ 132 | 'completions:Generate shell completions' \ 133 | 'help:Print this message or the help of the given subcommand(s)' \ 134 | ) 135 | _describe -t commands 'criu-coordinator help commands' commands "$@" 136 | } 137 | (( $+functions[_criu-coordinator__help__client_commands] )) || 138 | _criu-coordinator__help__client_commands() { 139 | local commands; commands=() 140 | _describe -t commands 'criu-coordinator help client commands' commands "$@" 141 | } 142 | (( $+functions[_criu-coordinator__help__completions_commands] )) || 143 | _criu-coordinator__help__completions_commands() { 144 | local commands; commands=() 145 | _describe -t commands 'criu-coordinator help completions commands' commands "$@" 146 | } 147 | (( $+functions[_criu-coordinator__help__help_commands] )) || 148 | _criu-coordinator__help__help_commands() { 149 | local commands; commands=() 150 | _describe -t commands 'criu-coordinator help help commands' commands "$@" 151 | } 152 | (( $+functions[_criu-coordinator__help__server_commands] )) || 153 | _criu-coordinator__help__server_commands() { 154 | local commands; commands=() 155 | _describe -t commands 'criu-coordinator help server commands' commands "$@" 156 | } 157 | (( $+functions[_criu-coordinator__server_commands] )) || 158 | _criu-coordinator__server_commands() { 159 | local commands; commands=() 160 | _describe -t commands 'criu-coordinator server commands' commands "$@" 161 | } 162 | 163 | if [ "$funcstack[1]" = "_criu-coordinator" ]; then 164 | _criu-coordinator "$@" 165 | else 166 | compdef _criu-coordinator criu-coordinator 167 | fi 168 | -------------------------------------------------------------------------------- /example-config/criu-coordinator.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "test", 3 | "dependencies": "test", 4 | "address": "127.0.0.1", 5 | "port": "8080", 6 | "log-file": "coordinator.log" 7 | } 8 | -------------------------------------------------------------------------------- /proto/criu/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 The CRIU developers 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /proto/criu/apparmor.proto: -------------------------------------------------------------------------------- 1 | 2 | // File imported by sync_criu_proto_files.sh 3 | 4 | syntax = "proto2"; 5 | package criu; 6 | 7 | message aa_policy { 8 | required string name = 1; 9 | required bytes blob = 2; 10 | } 11 | 12 | message aa_namespace { 13 | required string name = 1; 14 | repeated aa_policy policies = 2; 15 | repeated aa_namespace namespaces = 3; 16 | } 17 | 18 | message apparmor_entry { 19 | repeated aa_namespace namespaces = 1; 20 | } 21 | -------------------------------------------------------------------------------- /proto/criu/autofs.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message autofs_entry { 10 | required int32 fd = 1; 11 | required int32 pgrp = 2; 12 | required int32 timeout = 3; 13 | required int32 minproto = 4; 14 | required int32 maxproto = 5; 15 | required int32 mode = 6; 16 | 17 | optional int32 uid = 7; 18 | optional int32 gid = 8; 19 | 20 | optional int32 read_fd = 9; 21 | } 22 | -------------------------------------------------------------------------------- /proto/criu/binfmt-misc.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message binfmt_misc_entry { 10 | required string name = 1; 11 | required bool enabled = 2; 12 | required string interpreter = 3; 13 | optional string flags = 4; 14 | optional string extension = 5; 15 | optional string magic = 6; 16 | optional string mask = 7; 17 | optional int32 offset = 8; 18 | } 19 | -------------------------------------------------------------------------------- /proto/criu/bpfmap-data.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message bpfmap_data_entry { 10 | required uint32 map_id = 1; 11 | required uint32 keys_bytes = 2; /* Bytes required to store keys */ 12 | required uint32 values_bytes = 3; /* Bytes required to store values */ 13 | required uint32 count = 4; /* Number of key-value pairs stored */ 14 | } 15 | -------------------------------------------------------------------------------- /proto/criu/bpfmap-file.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | 12 | message bpfmap_file_entry { 13 | required uint32 id = 1; 14 | required uint32 flags = 2 [(criu).flags = "rfile.flags"]; 15 | required uint64 pos = 3; 16 | required fown_entry fown = 4; 17 | required uint32 map_type = 5; 18 | required uint32 key_size = 6; 19 | required uint32 value_size = 7; 20 | required uint32 map_id = 8; 21 | required uint32 max_entries = 9; 22 | required uint32 map_flags = 10; 23 | required uint64 memlock = 11; 24 | required bool frozen = 12 [default = false]; 25 | required string map_name = 13; 26 | required uint32 ifindex = 14 [default = 0]; 27 | optional sint32 mnt_id = 15 [default = -1]; 28 | } 29 | -------------------------------------------------------------------------------- /proto/criu/cgroup.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message cgroup_perms { 10 | required uint32 mode = 1; 11 | required uint32 uid = 2; 12 | required uint32 gid = 3; 13 | } 14 | 15 | message cgroup_prop_entry { 16 | required string name = 1; 17 | required string value = 2; 18 | optional cgroup_perms perms = 3; 19 | } 20 | 21 | message cgroup_dir_entry { 22 | required string dir_name = 1; 23 | repeated cgroup_dir_entry children = 2; 24 | repeated cgroup_prop_entry properties = 3; 25 | optional cgroup_perms dir_perms = 4; 26 | } 27 | 28 | message cg_controller_entry { 29 | repeated string cnames = 1; 30 | repeated cgroup_dir_entry dirs = 2; 31 | } 32 | 33 | message cg_member_entry { 34 | required string name = 1; 35 | required string path = 2; 36 | optional uint32 cgns_prefix = 3; 37 | } 38 | 39 | message cg_set_entry { 40 | required uint32 id = 1; 41 | repeated cg_member_entry ctls = 2; 42 | } 43 | 44 | message cgroup_entry { 45 | repeated cg_set_entry sets = 1; 46 | repeated cg_controller_entry controllers = 2; 47 | } 48 | -------------------------------------------------------------------------------- /proto/criu/core-aarch64.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message user_aarch64_regs_entry { 12 | repeated uint64 regs = 1; 13 | required uint64 sp = 2; 14 | required uint64 pc = 3; 15 | required uint64 pstate = 4; 16 | } 17 | 18 | message user_aarch64_fpsimd_context_entry { 19 | repeated uint64 vregs = 1; 20 | required uint32 fpsr = 2; 21 | required uint32 fpcr = 3; 22 | } 23 | 24 | message thread_info_aarch64 { 25 | required uint64 clear_tid_addr = 1[(criu).hex = true]; 26 | required uint64 tls = 2; 27 | required user_aarch64_regs_entry gpregs = 3[(criu).hex = true]; 28 | required user_aarch64_fpsimd_context_entry fpsimd = 4; 29 | } 30 | -------------------------------------------------------------------------------- /proto/criu/core-arm.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message user_arm_regs_entry { 12 | required uint32 r0 = 1; 13 | required uint32 r1 = 2; 14 | required uint32 r2 = 3; 15 | required uint32 r3 = 4; 16 | required uint32 r4 = 5; 17 | required uint32 r5 = 6; 18 | required uint32 r6 = 7; 19 | required uint32 r7 = 8; 20 | required uint32 r8 = 9; 21 | required uint32 r9 = 10; 22 | required uint32 r10 = 11; 23 | required uint32 fp = 12; 24 | required uint32 ip = 13; 25 | required uint32 sp = 14; 26 | required uint32 lr = 15; 27 | required uint32 pc = 16; 28 | required uint32 cpsr = 17; 29 | required uint32 orig_r0 = 18; 30 | } 31 | 32 | message user_arm_vfpstate_entry { 33 | repeated uint64 vfp_regs = 1; 34 | required uint32 fpscr = 2; 35 | required uint32 fpexc = 3; 36 | required uint32 fpinst = 4; 37 | required uint32 fpinst2 = 5; 38 | } 39 | 40 | message thread_info_arm { 41 | required uint64 clear_tid_addr = 1[(criu).hex = true]; 42 | required uint32 tls = 2; 43 | required user_arm_regs_entry gpregs = 3[(criu).hex = true]; 44 | required user_arm_vfpstate_entry fpstate = 4; 45 | } 46 | -------------------------------------------------------------------------------- /proto/criu/core-mips.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message user_mips_regs_entry { 12 | required uint64 r0 = 1; 13 | required uint64 r1 = 2; 14 | required uint64 r2 = 3; 15 | required uint64 r3 = 4; 16 | required uint64 r4 = 5; 17 | required uint64 r5 = 6; 18 | required uint64 r6 = 7; 19 | required uint64 r7 = 8; 20 | required uint64 r8 = 9; 21 | required uint64 r9 = 10; 22 | required uint64 r10 = 11; 23 | required uint64 r11 = 12; 24 | required uint64 r12 = 13; 25 | required uint64 r13 = 14; 26 | required uint64 r14 = 15; 27 | required uint64 r15 = 16; 28 | required uint64 r16 = 17; 29 | required uint64 r17 = 18; 30 | required uint64 r18 = 19; 31 | required uint64 r19 = 20; 32 | required uint64 r20 = 21; 33 | required uint64 r21 = 22; 34 | required uint64 r22 = 23; 35 | required uint64 r23 = 24; 36 | required uint64 r24 = 25; 37 | required uint64 r25 = 26; 38 | required uint64 r26 = 27; 39 | required uint64 r27 = 28; 40 | required uint64 r28 = 29; 41 | required uint64 r29 = 30; 42 | required uint64 r30 = 31; 43 | required uint64 r31 = 32; 44 | required uint64 lo = 33; 45 | required uint64 hi = 34; 46 | required uint64 cp0_epc = 35; 47 | required uint64 cp0_badvaddr = 36; 48 | required uint64 cp0_status = 37; 49 | required uint64 cp0_cause = 38; 50 | } 51 | 52 | message user_mips_fpregs_entry { 53 | required uint64 r0 = 1; 54 | required uint64 r1 = 2; 55 | required uint64 r2 = 3; 56 | required uint64 r3 = 4; 57 | required uint64 r4 = 5; 58 | required uint64 r5 = 6; 59 | required uint64 r6 = 7; 60 | required uint64 r7 = 8; 61 | required uint64 r8 = 9; 62 | required uint64 r9 = 10; 63 | required uint64 r10 = 11; 64 | required uint64 r11 = 12; 65 | required uint64 r12 = 13; 66 | required uint64 r13 = 14; 67 | required uint64 r14 = 15; 68 | required uint64 r15 = 16; 69 | required uint64 r16 = 17; 70 | required uint64 r17 = 18; 71 | required uint64 r18 = 19; 72 | required uint64 r19 = 20; 73 | required uint64 r20 = 21; 74 | required uint64 r21 = 22; 75 | required uint64 r22 = 23; 76 | required uint64 r23 = 24; 77 | required uint64 r24 = 25; 78 | required uint64 r25 = 26; 79 | required uint64 r26 = 27; 80 | required uint64 r27 = 28; 81 | required uint64 r28 = 29; 82 | required uint64 r29 = 30; 83 | required uint64 r30 = 31; 84 | required uint64 r31 = 32; 85 | required uint64 lo = 33; 86 | required uint64 hi = 34; 87 | required uint32 fpu_fcr31 = 35; 88 | required uint32 fpu_id = 36; 89 | } 90 | 91 | message thread_info_mips { 92 | required uint64 clear_tid_addr = 1[(criu).hex = true]; 93 | required uint64 tls = 2; 94 | required user_mips_regs_entry gpregs = 3[(criu).hex = true]; 95 | required user_mips_fpregs_entry fpregs = 4[(criu).hex = true]; 96 | } 97 | -------------------------------------------------------------------------------- /proto/criu/core-ppc64.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message user_ppc64_regs_entry { 12 | /* Following is the list of regiters starting at r0. */ 13 | repeated uint64 gpr = 1; 14 | required uint64 nip = 2; 15 | required uint64 msr = 3; 16 | required uint64 orig_gpr3 = 4; 17 | required uint64 ctr = 5; 18 | required uint64 link = 6; 19 | required uint64 xer = 7; 20 | required uint64 ccr = 8; 21 | required uint64 trap = 9; 22 | /* For Transactional memory support since P8 */ 23 | optional uint64 texasr = 10; 24 | optional uint64 tfhar = 11; 25 | optional uint64 tfiar = 12; 26 | } 27 | 28 | message user_ppc64_fpstate_entry { 29 | /* Following is the list of regiters starting at fpr0 */ 30 | repeated uint64 fpregs = 1; 31 | } 32 | 33 | message user_ppc64_vrstate_entry { 34 | /* 35 | * Altivec registers 36 | * The vector registers are 128bit registers (VSR[32..63]). 37 | * The following vregs entry will store first the high part then the 38 | * low one: 39 | * VR0 = vrregs[0] << 64 | vrregs[1]; 40 | * VR1 = vrregs[2] << 64 | vrregs[3]; 41 | * .. 42 | * The last entry stores in a 128bit field the VSCR which is a 32bit 43 | * value returned by the kernel in a 128 field. 44 | */ 45 | repeated uint64 vrregs = 1; 46 | required uint32 vrsave = 2; 47 | } 48 | 49 | message user_ppc64_vsxstate_entry { 50 | /* 51 | * VSX registers 52 | * The vector-scale registers are 128bit registers (VSR[0..64]). 53 | * Since there is an overlapping over the VSX registers by the FPR and 54 | * the Altivec registers, only the lower part of the first 32 VSX 55 | * registers have to be saved. 56 | */ 57 | repeated uint64 vsxregs = 1; 58 | } 59 | 60 | /* 61 | * Transactional memory operation's state 62 | */ 63 | message user_ppc64_tm_regs_entry { 64 | required user_ppc64_regs_entry gpregs = 1; 65 | optional user_ppc64_fpstate_entry fpstate = 2; 66 | optional user_ppc64_vrstate_entry vrstate = 3; 67 | optional user_ppc64_vsxstate_entry vsxstate = 4; 68 | } 69 | 70 | message thread_info_ppc64 { 71 | required uint64 clear_tid_addr = 1[(criu).hex = true]; 72 | required user_ppc64_regs_entry gpregs = 2[(criu).hex = true]; 73 | optional user_ppc64_fpstate_entry fpstate = 3; 74 | optional user_ppc64_vrstate_entry vrstate = 4; 75 | optional user_ppc64_vsxstate_entry vsxstate = 5; 76 | optional user_ppc64_tm_regs_entry tmstate = 6; 77 | } 78 | -------------------------------------------------------------------------------- /proto/criu/core-s390.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message user_s390_regs_entry { 12 | required uint64 psw_mask = 1; 13 | required uint64 psw_addr = 2; 14 | repeated uint64 gprs = 3; 15 | repeated uint32 acrs = 4; 16 | required uint64 orig_gpr2 = 5; 17 | required uint32 system_call = 6; 18 | } 19 | 20 | message user_s390_vxrs_low_entry { 21 | repeated uint64 regs = 1; 22 | } 23 | 24 | /* 25 | * The vxrs_high registers have 128 bit: 26 | * 27 | * vxrs_high_0 = regs[0] << 64 | regs[1]; 28 | * vxrs_high_1 = regs[2] << 64 | regs[3]; 29 | */ 30 | message user_s390_vxrs_high_entry { 31 | repeated uint64 regs = 1; 32 | } 33 | 34 | message user_s390_fpregs_entry { 35 | required uint32 fpc = 1; 36 | repeated uint64 fprs = 2; 37 | } 38 | 39 | message user_s390_gs_cb_entry { 40 | repeated uint64 regs = 1; 41 | } 42 | 43 | message user_s390_ri_entry { 44 | required uint32 ri_on = 1; 45 | repeated uint64 regs = 2; 46 | } 47 | 48 | message thread_info_s390 { 49 | required uint64 clear_tid_addr = 1[(criu).hex = true]; 50 | required user_s390_regs_entry gpregs = 2[(criu).hex = true]; 51 | required user_s390_fpregs_entry fpregs = 3[(criu).hex = true]; 52 | optional user_s390_vxrs_low_entry vxrs_low = 4[(criu).hex = true]; 53 | optional user_s390_vxrs_high_entry vxrs_high = 5[(criu).hex = true]; 54 | optional user_s390_gs_cb_entry gs_cb = 6[(criu).hex = true]; 55 | optional user_s390_gs_cb_entry gs_bc = 7[(criu).hex = true]; 56 | optional user_s390_ri_entry ri_cb = 8[(criu).hex = true]; 57 | } 58 | -------------------------------------------------------------------------------- /proto/criu/core-x86.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | enum user_x86_regs_mode { 12 | NATIVE = 1; 13 | COMPAT = 2; 14 | } 15 | 16 | /* Reusing entry for both 64 and 32 bits register sets */ 17 | message user_x86_regs_entry { 18 | required uint64 r15 = 1; 19 | required uint64 r14 = 2; 20 | required uint64 r13 = 3; 21 | required uint64 r12 = 4; 22 | required uint64 bp = 5; 23 | required uint64 bx = 6; 24 | required uint64 r11 = 7; 25 | required uint64 r10 = 8; 26 | required uint64 r9 = 9; 27 | required uint64 r8 = 10; 28 | required uint64 ax = 11; 29 | required uint64 cx = 12; 30 | required uint64 dx = 13; 31 | required uint64 si = 14; 32 | required uint64 di = 15; 33 | required uint64 orig_ax = 16; 34 | required uint64 ip = 17; 35 | required uint64 cs = 18; 36 | required uint64 flags = 19; 37 | required uint64 sp = 20; 38 | required uint64 ss = 21; 39 | required uint64 fs_base = 22; 40 | required uint64 gs_base = 23; 41 | required uint64 ds = 24; 42 | required uint64 es = 25; 43 | required uint64 fs = 26; 44 | required uint64 gs = 27; 45 | optional user_x86_regs_mode mode = 28 [default = NATIVE]; 46 | } 47 | 48 | message user_x86_xsave_entry { 49 | /* standart xsave features */ 50 | required uint64 xstate_bv = 1; 51 | 52 | /* AVX components: 16x 256-bit ymm registers, hi 128 bits */ 53 | repeated uint32 ymmh_space = 2; 54 | 55 | /* MPX components */ 56 | repeated uint64 bndreg_state = 3; 57 | repeated uint64 bndcsr_state = 4; 58 | 59 | /* AVX512 components: k0-k7, ZMM_Hi256, Hi16_ZMM */ 60 | repeated uint64 opmask_reg = 5; 61 | repeated uint64 zmm_upper = 6; 62 | repeated uint64 hi16_zmm = 7; 63 | 64 | /* Protected keys */ 65 | repeated uint32 pkru = 8; 66 | 67 | /* 68 | * Processor trace (PT) and hardware duty cycling (HDC) 69 | * are supervisor state components and only managed by 70 | * xsaves/xrstors on cpl=0, so ignore them. 71 | */ 72 | } 73 | 74 | message user_x86_fpregs_entry { 75 | 76 | /* fxsave data */ 77 | required uint32 cwd = 1; 78 | required uint32 swd = 2; 79 | required uint32 twd = 3; 80 | required uint32 fop = 4; 81 | required uint64 rip = 5; 82 | required uint64 rdp = 6; 83 | required uint32 mxcsr = 7; 84 | required uint32 mxcsr_mask = 8; 85 | repeated uint32 st_space = 9; 86 | repeated uint32 xmm_space = 10; 87 | 88 | /* Unused, but present for backward compatibility */ 89 | repeated uint32 padding = 11; 90 | 91 | /* xsave extension */ 92 | optional user_x86_xsave_entry xsave = 13; 93 | } 94 | 95 | message user_desc_t { 96 | required uint32 entry_number = 1; 97 | /* this is for GDT, not for MSRs - 32-bit base */ 98 | required uint32 base_addr = 2; 99 | required uint32 limit = 3; 100 | required bool seg_32bit = 4; 101 | required bool contents_h = 5; 102 | required bool contents_l = 6; 103 | required bool read_exec_only = 7 [default = true]; 104 | required bool limit_in_pages = 8; 105 | required bool seg_not_present = 9 [default = true]; 106 | required bool useable = 10; 107 | } 108 | 109 | message thread_info_x86 { 110 | required uint64 clear_tid_addr = 1[(criu).hex = true]; 111 | required user_x86_regs_entry gpregs = 2[(criu).hex = true]; 112 | required user_x86_fpregs_entry fpregs = 3; 113 | repeated user_desc_t tls = 4; 114 | } 115 | -------------------------------------------------------------------------------- /proto/criu/core.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "core-x86.proto"; 10 | import "core-arm.proto"; 11 | import "core-aarch64.proto"; 12 | import "core-ppc64.proto"; 13 | import "core-s390.proto"; 14 | import "core-mips.proto"; 15 | 16 | import "rlimit.proto"; 17 | import "timer.proto"; 18 | import "creds.proto"; 19 | import "sa.proto"; 20 | import "siginfo.proto"; 21 | 22 | import "opts.proto"; 23 | 24 | /* 25 | * These match the SECCOMP_MODE_* flags from . 26 | */ 27 | enum seccomp_mode { 28 | disabled = 0; 29 | strict = 1; 30 | filter = 2; 31 | }; 32 | 33 | message task_core_entry { 34 | required uint32 task_state = 1 [(criu).dict = "gen"]; 35 | required uint32 exit_code = 2; 36 | 37 | required uint32 personality = 3; 38 | required uint32 flags = 4; 39 | required uint64 blk_sigset = 5[(criu).hex = true]; 40 | 41 | required string comm = 6; 42 | 43 | optional task_timers_entry timers = 7; 44 | optional task_rlimits_entry rlimits = 8; 45 | 46 | optional uint32 cg_set = 9; 47 | 48 | optional signal_queue_entry signals_s = 10; 49 | 50 | /* These two are deprecated, should be per-thread */ 51 | optional seccomp_mode old_seccomp_mode = 11; 52 | optional uint32 old_seccomp_filter = 12; 53 | 54 | optional uint32 loginuid = 13; 55 | 56 | optional int32 oom_score_adj = 14; 57 | repeated sa_entry sigactions = 15; 58 | // Reserved for tty inheritance 59 | //optional int32 tty_nr = 16; 60 | //optional int32 tty_pgrp = 17; 61 | 62 | optional bool child_subreaper = 18; 63 | // Reserved for container relative start time 64 | //optional uint64 start_time = 19; 65 | optional uint64 blk_sigset_extended = 20[(criu).hex = true]; 66 | } 67 | 68 | message task_kobj_ids_entry { 69 | required uint32 vm_id = 1; 70 | required uint32 files_id = 2; 71 | required uint32 fs_id = 3; 72 | required uint32 sighand_id = 4; 73 | 74 | optional uint32 pid_ns_id = 5; 75 | optional uint32 net_ns_id = 6; 76 | optional uint32 ipc_ns_id = 7; 77 | optional uint32 uts_ns_id = 8; 78 | optional uint32 mnt_ns_id = 9; 79 | optional uint32 user_ns_id = 10; 80 | optional uint32 cgroup_ns_id = 11; 81 | optional uint32 time_ns_id = 12; 82 | } 83 | 84 | message thread_sas_entry { 85 | required uint64 ss_sp = 1; 86 | required uint64 ss_size = 2; 87 | required uint32 ss_flags = 3; 88 | } 89 | 90 | message thread_core_entry { 91 | required uint64 futex_rla = 1; 92 | required uint32 futex_rla_len = 2; 93 | optional sint32 sched_nice = 3; 94 | optional uint32 sched_policy = 4; 95 | optional uint32 sched_prio = 5; 96 | optional uint64 blk_sigset = 6; 97 | optional thread_sas_entry sas = 7; 98 | optional uint32 pdeath_sig = 8; 99 | 100 | optional signal_queue_entry signals_p = 9; 101 | optional creds_entry creds = 10; 102 | 103 | optional seccomp_mode seccomp_mode = 11; 104 | optional uint32 seccomp_filter = 12; 105 | 106 | optional string comm = 13; 107 | optional uint64 blk_sigset_extended = 14; 108 | } 109 | 110 | message task_rlimits_entry { 111 | repeated rlimit_entry rlimits = 1; 112 | }; 113 | 114 | message core_entry { 115 | enum march { 116 | UNKNOWN = 0; 117 | X86_64 = 1; 118 | ARM = 2; 119 | AARCH64 = 3; 120 | PPC64 = 4; 121 | S390 = 5; 122 | MIPS = 6; 123 | } 124 | 125 | required march mtype = 1; 126 | optional thread_info_x86 thread_info = 2; 127 | optional thread_info_arm ti_arm = 6; 128 | optional thread_info_aarch64 ti_aarch64 = 8; 129 | optional thread_info_ppc64 ti_ppc64 = 9; 130 | optional thread_info_s390 ti_s390 = 10; 131 | optional thread_info_mips ti_mips = 11; 132 | 133 | optional task_core_entry tc = 3; 134 | optional task_kobj_ids_entry ids = 4; 135 | optional thread_core_entry thread_core = 5; 136 | } 137 | -------------------------------------------------------------------------------- /proto/criu/cpuinfo.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message cpuinfo_x86_entry { 10 | enum vendor { 11 | UNKNOWN = 0; 12 | INTEL = 1; 13 | AMD = 2; 14 | } 15 | 16 | required vendor vendor_id = 1; 17 | required uint32 cpu_family = 2; 18 | required uint32 model = 3; 19 | required uint32 stepping = 4; 20 | required uint32 capability_ver = 5; 21 | repeated uint32 capability = 6; 22 | 23 | optional string model_id = 7; 24 | 25 | optional uint64 xfeatures_mask = 8; 26 | optional uint32 xsave_size = 9; 27 | optional uint32 xsave_size_max = 10; 28 | } 29 | 30 | message cpuinfo_ppc64_entry { 31 | enum endianness { 32 | BIGENDIAN = 0; 33 | LITTLEENDIAN = 1; 34 | } 35 | 36 | required endianness endian = 1; 37 | repeated uint64 hwcap = 2; 38 | } 39 | 40 | message cpuinfo_s390_entry { 41 | repeated uint64 hwcap = 2; 42 | } 43 | 44 | message cpuinfo_entry { 45 | /* 46 | * Usually on SMP system there should be same CPUs 47 | * installed, but it might happen that system carries 48 | * various CPUs so @repeated used. 49 | */ 50 | repeated cpuinfo_x86_entry x86_entry = 1; 51 | repeated cpuinfo_ppc64_entry ppc64_entry = 2; 52 | repeated cpuinfo_s390_entry s390_entry = 3; 53 | } 54 | -------------------------------------------------------------------------------- /proto/criu/creds.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message creds_entry { 10 | required uint32 uid = 1; 11 | required uint32 gid = 2; 12 | required uint32 euid = 3; 13 | required uint32 egid = 4; 14 | required uint32 suid = 5; 15 | required uint32 sgid = 6; 16 | required uint32 fsuid = 7; 17 | required uint32 fsgid = 8; 18 | 19 | repeated uint32 cap_inh = 9; 20 | repeated uint32 cap_prm = 10; 21 | repeated uint32 cap_eff = 11; 22 | repeated uint32 cap_bnd = 12; 23 | 24 | required uint32 secbits = 13; 25 | 26 | repeated uint32 groups = 14; 27 | 28 | optional string lsm_profile = 15; 29 | optional string lsm_sockcreate = 16; 30 | optional bytes apparmor_data = 17; 31 | } 32 | -------------------------------------------------------------------------------- /proto/criu/eventfd.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "fown.proto"; 10 | 11 | message eventfd_file_entry { 12 | required uint32 id = 1; 13 | required uint32 flags = 2; 14 | required fown_entry fown = 3; 15 | required uint64 counter = 4; 16 | } 17 | -------------------------------------------------------------------------------- /proto/criu/eventpoll.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "fown.proto"; 10 | 11 | message eventpoll_tfd_entry { 12 | required uint32 id = 1; 13 | required uint32 tfd = 2; 14 | required uint32 events = 3; 15 | required uint64 data = 4; 16 | 17 | /* to find dup'ed target files */ 18 | optional uint32 dev = 5; 19 | optional uint64 inode = 6; 20 | optional uint64 pos = 7; 21 | } 22 | 23 | message eventpoll_file_entry { 24 | required uint32 id = 1; 25 | required uint32 flags = 2; 26 | required fown_entry fown = 3; 27 | repeated eventpoll_tfd_entry tfd = 4; 28 | } 29 | -------------------------------------------------------------------------------- /proto/criu/ext-file.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "fown.proto"; 10 | 11 | message ext_file_entry { 12 | required uint32 id = 1; 13 | required fown_entry fown = 5; 14 | } 15 | -------------------------------------------------------------------------------- /proto/criu/fdinfo.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "regfile.proto"; 10 | import "sk-inet.proto"; 11 | import "ns.proto"; 12 | import "packet-sock.proto"; 13 | import "sk-netlink.proto"; 14 | import "eventfd.proto"; 15 | import "eventpoll.proto"; 16 | import "signalfd.proto"; 17 | import "tun.proto"; 18 | import "timerfd.proto"; 19 | import "fsnotify.proto"; 20 | import "ext-file.proto"; 21 | import "sk-unix.proto"; 22 | import "fifo.proto"; 23 | import "pipe.proto"; 24 | import "tty.proto"; 25 | import "memfd.proto"; 26 | import "bpfmap-file.proto"; 27 | 28 | enum fd_types { 29 | UND = 0; 30 | REG = 1; 31 | PIPE = 2; 32 | FIFO = 3; 33 | INETSK = 4; 34 | UNIXSK = 5; 35 | EVENTFD = 6; 36 | EVENTPOLL = 7; 37 | INOTIFY = 8; 38 | SIGNALFD = 9; 39 | PACKETSK = 10; 40 | TTY = 11; 41 | FANOTIFY = 12; 42 | NETLINKSK = 13; 43 | NS = 14; 44 | TUNF = 15; 45 | EXT = 16; 46 | TIMERFD = 17; 47 | MEMFD = 18; 48 | BPFMAP = 19; 49 | 50 | /* Any number above the real used. Not stored to image */ 51 | CTL_TTY = 65534; 52 | AUTOFS_PIPE = 65535; 53 | } 54 | 55 | message fdinfo_entry { 56 | required uint32 id = 1; 57 | required uint32 flags = 2; 58 | required fd_types type = 3; 59 | required uint32 fd = 4; 60 | optional string xattr_security_selinux = 5; 61 | } 62 | 63 | message file_entry { 64 | required fd_types type = 1; 65 | required uint32 id = 2; 66 | optional reg_file_entry reg = 3; 67 | optional inet_sk_entry isk = 4; 68 | optional ns_file_entry nsf = 5; 69 | optional packet_sock_entry psk = 6; 70 | optional netlink_sk_entry nlsk = 7; 71 | optional eventfd_file_entry efd = 8; 72 | optional eventpoll_file_entry epfd = 9; 73 | optional signalfd_entry sgfd = 10; 74 | optional tunfile_entry tunf = 11; 75 | optional timerfd_entry tfd = 12; 76 | optional inotify_file_entry ify = 13; 77 | optional fanotify_file_entry ffy = 14; 78 | optional ext_file_entry ext = 15; 79 | optional unix_sk_entry usk = 16; 80 | optional fifo_entry fifo = 17; 81 | optional pipe_entry pipe = 18; 82 | optional tty_file_entry tty = 19; 83 | optional memfd_file_entry memfd = 20; 84 | optional bpfmap_file_entry bpf = 21; 85 | } 86 | -------------------------------------------------------------------------------- /proto/criu/fh.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | enum fh_entry_sizes { 12 | min_entries = 16; 13 | } 14 | 15 | message fh_entry { 16 | required uint32 bytes = 1; 17 | required uint32 type = 2; 18 | 19 | /* The minimum is fh_n_handle repetitions */ 20 | repeated uint64 handle = 3; 21 | optional string path = 4; 22 | optional uint32 mnt_id = 5; 23 | } 24 | 25 | message irmap_cache_entry { 26 | required uint32 dev = 1 [(criu).dev = true, (criu).odev = true]; 27 | required uint64 inode = 2; 28 | required string path = 3; 29 | } 30 | -------------------------------------------------------------------------------- /proto/criu/fifo.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message fifo_entry { 10 | required uint32 id = 1; 11 | required uint32 pipe_id = 2; 12 | optional uint32 regf_id = 3; 13 | } 14 | -------------------------------------------------------------------------------- /proto/criu/file-lock.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message file_lock_entry { 10 | required uint32 flag = 1; 11 | required uint32 type = 2; 12 | required int32 pid = 3; 13 | required int32 fd = 4; 14 | required int64 start = 5; 15 | required int64 len = 6; 16 | } 17 | -------------------------------------------------------------------------------- /proto/criu/fown.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message fown_entry { 10 | required uint32 uid = 1; 11 | required uint32 euid = 2; 12 | required uint32 signum = 3; 13 | required uint32 pid_type = 4; 14 | required uint32 pid = 5; 15 | } 16 | -------------------------------------------------------------------------------- /proto/criu/fs.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message fs_entry { 10 | required uint32 cwd_id = 1; 11 | required uint32 root_id = 2; 12 | optional uint32 umask = 3; 13 | } 14 | -------------------------------------------------------------------------------- /proto/criu/fsnotify.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fh.proto"; 11 | import "fown.proto"; 12 | 13 | message inotify_wd_entry { 14 | required uint32 id = 1; 15 | required uint64 i_ino = 2; 16 | required uint32 mask = 3 [(criu).hex = true]; 17 | required uint32 ignored_mask = 4 [(criu).hex = true]; 18 | required uint32 s_dev = 5 [(criu).dev = true]; 19 | required uint32 wd = 6; 20 | required fh_entry f_handle = 7; 21 | } 22 | 23 | message inotify_file_entry { 24 | required uint32 id = 1; 25 | required uint32 flags = 2 [(criu).hex = true]; 26 | required fown_entry fown = 4; 27 | repeated inotify_wd_entry wd = 5; 28 | } 29 | 30 | enum mark_type { 31 | INODE = 1; 32 | MOUNT = 2; 33 | } 34 | 35 | message fanotify_inode_mark_entry { 36 | required uint64 i_ino = 1; 37 | required fh_entry f_handle = 2; 38 | } 39 | 40 | message fanotify_mount_mark_entry { 41 | required uint32 mnt_id = 1; 42 | optional string path = 2; 43 | } 44 | 45 | message fanotify_mark_entry { 46 | required uint32 id = 1; 47 | required mark_type type = 2; 48 | 49 | required uint32 mflags = 3 [(criu).hex = true]; 50 | required uint32 mask = 4 [(criu).hex = true]; 51 | required uint32 ignored_mask = 5 [(criu).hex = true]; 52 | required uint32 s_dev = 6 [(criu).dev = true]; 53 | 54 | optional fanotify_inode_mark_entry ie = 7; 55 | optional fanotify_mount_mark_entry me = 8; 56 | } 57 | 58 | message fanotify_file_entry { 59 | required uint32 id = 1; 60 | required uint32 flags = 2 [(criu).hex = true]; 61 | required fown_entry fown = 3; 62 | 63 | required uint32 faflags = 4 [(criu).hex = true]; 64 | required uint32 evflags = 5 [(criu).hex = true]; 65 | repeated fanotify_mark_entry mark = 6; 66 | } 67 | -------------------------------------------------------------------------------- /proto/criu/ghost-file.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "time.proto"; 11 | 12 | message ghost_file_entry { 13 | required uint32 uid = 1; 14 | required uint32 gid = 2; 15 | required uint32 mode = 3; 16 | 17 | optional uint32 dev = 4 [(criu).dev = true]; 18 | optional uint64 ino = 5; 19 | optional uint32 rdev = 6 [(criu).dev = true, (criu).odev = true]; 20 | optional timeval atim = 7; 21 | optional timeval mtim = 8; 22 | optional bool chunks = 9; 23 | optional uint64 size = 10; 24 | /* this field makes sense only when S_ISLNK(mode) */ 25 | optional string symlnk_target = 11; 26 | } 27 | 28 | message ghost_chunk_entry { 29 | required uint64 len = 1; 30 | required uint64 off = 2; 31 | } 32 | -------------------------------------------------------------------------------- /proto/criu/img-streamer.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | // This message is sent from CRIU to the streamer. 10 | // * During dump, it communicates the name of the file that is about to be sent 11 | // to the streamer. 12 | // * During restore, CRIU requests image files from the streamer. The message is 13 | // used to communicate the name of the desired file. 14 | message img_streamer_request_entry { 15 | required string filename = 1; 16 | } 17 | 18 | // This message is sent from the streamer to CRIU. It is only used during 19 | // restore to report whether the requested file exists. 20 | message img_streamer_reply_entry { 21 | required bool exists = 1; 22 | } 23 | -------------------------------------------------------------------------------- /proto/criu/inventory.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "core.proto"; 10 | 11 | enum lsmtype { 12 | NO_LSM = 0; 13 | SELINUX = 1; 14 | APPARMOR = 2; 15 | } 16 | 17 | message inventory_entry { 18 | required uint32 img_version = 1; 19 | optional bool fdinfo_per_id = 2; 20 | optional task_kobj_ids_entry root_ids = 3; 21 | optional bool ns_per_id = 4; 22 | optional uint32 root_cg_set = 5; 23 | optional lsmtype lsmtype = 6; 24 | optional uint64 dump_uptime = 8; 25 | optional uint32 pre_dump_mode = 9; 26 | optional bool tcp_close = 10; 27 | optional uint32 network_lock_method = 11; 28 | } 29 | -------------------------------------------------------------------------------- /proto/criu/ipc-desc.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message ipc_desc_entry { 10 | required uint32 key = 1; 11 | required uint32 uid = 2; 12 | required uint32 gid = 3; 13 | required uint32 cuid = 4; 14 | required uint32 cgid = 5; 15 | required uint32 mode = 6; 16 | required uint32 id = 7; 17 | } 18 | -------------------------------------------------------------------------------- /proto/criu/ipc-msg.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "ipc-desc.proto"; 10 | 11 | message ipc_msg { 12 | required uint64 mtype = 1; 13 | required uint32 msize = 2; 14 | } 15 | 16 | message ipc_msg_entry { 17 | required ipc_desc_entry desc = 1; 18 | required uint32 qbytes = 2; 19 | required uint32 qnum = 3; 20 | } 21 | -------------------------------------------------------------------------------- /proto/criu/ipc-sem.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "ipc-desc.proto"; 10 | 11 | message ipc_sem_entry { 12 | required ipc_desc_entry desc = 1; 13 | required uint32 nsems = 2; 14 | } 15 | -------------------------------------------------------------------------------- /proto/criu/ipc-shm.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "ipc-desc.proto"; 10 | 11 | message ipc_shm_entry { 12 | required ipc_desc_entry desc = 1; 13 | required uint64 size = 2; 14 | optional bool in_pagemaps = 3; 15 | } 16 | -------------------------------------------------------------------------------- /proto/criu/ipc-var.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message ipc_var_entry { 10 | repeated uint32 sem_ctls = 1; 11 | required uint32 msg_ctlmax = 2; 12 | required uint32 msg_ctlmnb = 3; 13 | required uint32 msg_ctlmni = 4; 14 | required uint32 auto_msgmni = 5; 15 | required uint64 shm_ctlmax = 6; 16 | required uint64 shm_ctlall = 7; 17 | required uint32 shm_ctlmni = 8; 18 | required uint32 shm_rmid_forced = 9; 19 | required uint32 mq_queues_max = 10; 20 | required uint32 mq_msg_max = 11; 21 | required uint32 mq_msgsize_max = 12; 22 | optional uint32 mq_msg_default = 13; 23 | optional uint32 mq_msgsize_default = 14; 24 | optional uint32 msg_next_id = 15; 25 | optional uint32 sem_next_id = 16; 26 | optional uint32 shm_next_id = 17; 27 | } 28 | -------------------------------------------------------------------------------- /proto/criu/macvlan.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message macvlan_link_entry { 10 | required uint32 mode = 1; 11 | optional uint32 flags = 2; 12 | } 13 | -------------------------------------------------------------------------------- /proto/criu/memfd.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | 12 | message memfd_file_entry { 13 | required uint32 id = 1; 14 | required uint32 flags = 2 [(criu).flags = "rfile.flags"]; 15 | required uint64 pos = 3; 16 | required fown_entry fown = 4; 17 | required uint32 inode_id = 5; 18 | }; 19 | 20 | message memfd_inode_entry { 21 | required string name = 1; 22 | required uint32 uid = 2; 23 | required uint32 gid = 3; 24 | required uint64 size = 4; 25 | required uint32 shmid = 5; 26 | required uint32 seals = 6 [(criu).flags = "seals.flags"]; 27 | required uint64 inode_id = 7; 28 | }; 29 | -------------------------------------------------------------------------------- /proto/criu/mm.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "vma.proto"; 11 | 12 | message aio_ring_entry { 13 | required uint64 id = 1; 14 | required uint32 nr_req = 2; 15 | required uint32 ring_len = 3; 16 | } 17 | 18 | message mm_entry { 19 | required uint64 mm_start_code = 1 [(criu).hex = true]; 20 | required uint64 mm_end_code = 2 [(criu).hex = true]; 21 | required uint64 mm_start_data = 3 [(criu).hex = true]; 22 | required uint64 mm_end_data = 4 [(criu).hex = true]; 23 | required uint64 mm_start_stack = 5 [(criu).hex = true]; 24 | required uint64 mm_start_brk = 6 [(criu).hex = true]; 25 | required uint64 mm_brk = 7 [(criu).hex = true]; 26 | required uint64 mm_arg_start = 8 [(criu).hex = true]; 27 | required uint64 mm_arg_end = 9 [(criu).hex = true]; 28 | required uint64 mm_env_start = 10 [(criu).hex = true]; 29 | required uint64 mm_env_end = 11 [(criu).hex = true]; 30 | required uint32 exe_file_id = 12; 31 | 32 | repeated uint64 mm_saved_auxv = 13; 33 | 34 | repeated vma_entry vmas = 14; 35 | 36 | optional int32 dumpable = 15; 37 | repeated aio_ring_entry aios = 16; 38 | optional bool thp_disabled = 17; 39 | } 40 | -------------------------------------------------------------------------------- /proto/criu/mnt.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | enum fstype { 12 | UNSUPPORTED = 0; 13 | PROC = 1; 14 | SYSFS = 2; 15 | DEVTMPFS = 3; 16 | BINFMT_MISC = 4; 17 | TMPFS = 5; 18 | DEVPTS = 6; 19 | SIMFS = 7; 20 | PSTORE = 8; 21 | SECURITYFS = 9; 22 | FUSECTL = 10; 23 | DEBUGFS = 11; 24 | CGROUP = 12; 25 | AUFS = 13; 26 | MQUEUE = 14; 27 | FUSE = 15; 28 | AUTO = 16; 29 | OVERLAYFS = 17; 30 | AUTOFS = 18; 31 | TRACEFS = 19; 32 | 33 | /* These three are reserved for NFS support */ 34 | // RPC_PIPEFS = 20; 35 | // NFS = 21; 36 | // NFS4 = 22; 37 | 38 | CGROUP2 = 23; 39 | }; 40 | 41 | message mnt_entry { 42 | required uint32 fstype = 1; 43 | required uint32 mnt_id = 2; 44 | required uint32 root_dev = 3 [(criu).dev = true]; 45 | required uint32 parent_mnt_id = 4; 46 | required uint32 flags = 5 [(criu).hex = true]; 47 | 48 | required string root = 6; 49 | required string mountpoint = 7; 50 | required string source = 8; 51 | required string options = 9; 52 | 53 | optional uint32 shared_id = 10; 54 | optional uint32 master_id = 11; 55 | 56 | optional bool with_plugin = 12; 57 | optional bool ext_mount = 13; 58 | 59 | optional string fsname = 14; 60 | optional bool internal_sharing = 15; 61 | 62 | optional bool deleted = 16; 63 | optional uint32 sb_flags = 17 [(criu).hex = true]; 64 | /* user defined mapping for external mount */ 65 | optional string ext_key = 18; 66 | } 67 | -------------------------------------------------------------------------------- /proto/criu/netdev.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "macvlan.proto"; 10 | import "opts.proto"; 11 | import "tun.proto"; 12 | import "sysctl.proto"; 13 | import "sit.proto"; 14 | 15 | enum nd_type { 16 | LOOPBACK = 1; 17 | VETH = 2; 18 | TUN = 3; 19 | /* 20 | * External link -- for those CRIU only dumps and restores 21 | * link parameters such as flags, address, MTU, etc. The 22 | * existence of the link on restore should be provided 23 | * by the setup-namespaces script. 24 | */ 25 | EXTLINK = 4; 26 | VENET = 5; /* OpenVZ device */ 27 | BRIDGE = 6; 28 | MACVLAN = 7; 29 | SIT = 8; 30 | } 31 | 32 | message net_device_entry { 33 | required nd_type type = 1; 34 | required uint32 ifindex = 2; 35 | required uint32 mtu = 3; 36 | required uint32 flags = 4 [(criu).hex = true]; 37 | required string name = 5; 38 | 39 | optional tun_link_entry tun = 6; 40 | 41 | optional bytes address = 7; 42 | 43 | repeated int32 conf = 8; 44 | 45 | repeated sysctl_entry conf4 = 9; 46 | 47 | repeated sysctl_entry conf6 = 10; 48 | 49 | optional macvlan_link_entry macvlan = 11; 50 | 51 | optional uint32 peer_ifindex = 12; 52 | optional uint32 peer_nsid = 13; 53 | optional uint32 master = 14; 54 | optional sit_entry sit = 15; 55 | } 56 | 57 | message netns_id { 58 | /* This is CRIU's id which is allocated for each namespace */ 59 | required uint32 target_ns_id = 1; 60 | /* 61 | * This is an id which can be used to address this namespace 62 | * from another network namespace. Each network namespace has 63 | * one set of id-s for other namespaces. 64 | */ 65 | required int32 netnsid_value = 2; 66 | } 67 | 68 | message netns_entry { 69 | repeated int32 def_conf = 1; 70 | repeated int32 all_conf = 2; 71 | 72 | repeated sysctl_entry def_conf4 = 3; 73 | repeated sysctl_entry all_conf4 = 4; 74 | 75 | repeated sysctl_entry def_conf6 = 5; 76 | repeated sysctl_entry all_conf6 = 6; 77 | 78 | repeated netns_id nsids = 7; 79 | optional string ext_key = 8; 80 | repeated sysctl_entry unix_conf = 9; 81 | } 82 | -------------------------------------------------------------------------------- /proto/criu/ns.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message ns_file_entry { 10 | required uint32 id = 1; 11 | required uint32 ns_id = 2; 12 | required uint32 ns_cflag = 3; 13 | required uint32 flags = 4; 14 | } 15 | -------------------------------------------------------------------------------- /proto/criu/opts.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "google/protobuf/descriptor.proto"; 10 | 11 | message CRIU_Opts_pb { 12 | optional bool hex = 1; // Idicate that CRIT should treat this field as hex. 13 | optional bool ipadd = 2; // The field is IPv4/v6 address 14 | optional string flags = 3; 15 | optional bool dev = 4; // Device major:minor packed 16 | optional bool odev = 5; // ... in old format 17 | optional string dict = 6; 18 | optional string conv = 7; 19 | } 20 | 21 | extend google.protobuf.FieldOptions { 22 | // Registered unique number to use for all kinds of custom options. 23 | optional CRIU_Opts_pb criu = 1018; 24 | } 25 | -------------------------------------------------------------------------------- /proto/criu/packet-sock.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | import "sk-opts.proto"; 12 | 13 | message packet_mclist { 14 | required uint32 index = 1; 15 | required uint32 type = 2; 16 | required bytes addr = 3; 17 | } 18 | 19 | message packet_ring { 20 | required uint32 block_size = 1; 21 | required uint32 block_nr = 2; 22 | required uint32 frame_size = 3; 23 | required uint32 frame_nr = 4; 24 | 25 | required uint32 retire_tmo = 5; 26 | required uint32 sizeof_priv = 6; 27 | required uint32 features = 7; 28 | } 29 | 30 | message packet_sock_entry { 31 | required uint32 id = 1; 32 | required uint32 type = 2; 33 | required uint32 protocol = 3; 34 | required uint32 flags = 4 [(criu).hex = true]; 35 | required uint32 ifindex = 5; 36 | 37 | required fown_entry fown = 6; 38 | required sk_opts_entry opts = 7; 39 | 40 | required uint32 version = 8; 41 | required uint32 reserve = 9; 42 | required bool aux_data = 10; 43 | required bool orig_dev = 11; 44 | required bool vnet_hdr = 12; 45 | required bool loss = 13; 46 | required uint32 timestamp = 14; 47 | required uint32 copy_thresh = 15; 48 | repeated packet_mclist mclist = 16; 49 | optional uint32 fanout = 17 [ default = 0xffffffff ]; 50 | optional packet_ring rx_ring = 18; 51 | optional packet_ring tx_ring = 19; 52 | optional uint32 ns_id = 20; 53 | } 54 | -------------------------------------------------------------------------------- /proto/criu/pagemap.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message pagemap_head { 12 | required uint32 pages_id = 1; 13 | } 14 | 15 | message pagemap_entry { 16 | required uint64 vaddr = 1 [(criu).hex = true]; 17 | required uint32 nr_pages = 2; 18 | optional bool in_parent = 3; 19 | optional uint32 flags = 4 [(criu).flags = "pmap.flags" ]; 20 | } 21 | -------------------------------------------------------------------------------- /proto/criu/pidns.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message pidns_entry { 10 | optional string ext_key = 1; 11 | } 12 | -------------------------------------------------------------------------------- /proto/criu/pipe-data.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message pipe_data_entry { 10 | required uint32 pipe_id = 1; 11 | required uint32 bytes = 2; 12 | optional uint32 size = 3; 13 | } 14 | -------------------------------------------------------------------------------- /proto/criu/pipe.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | 12 | message pipe_entry { 13 | required uint32 id = 1; 14 | required uint32 pipe_id = 2; 15 | required uint32 flags = 3 [(criu).hex = true]; 16 | required fown_entry fown = 4; 17 | } 18 | -------------------------------------------------------------------------------- /proto/criu/pstree.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message pstree_entry { 10 | required uint32 pid = 1; 11 | required uint32 ppid = 2; 12 | required uint32 pgid = 3; 13 | required uint32 sid = 4; 14 | repeated uint32 threads = 5; 15 | } 16 | -------------------------------------------------------------------------------- /proto/criu/regfile.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | 12 | message reg_file_entry { 13 | required uint32 id = 1; 14 | required uint32 flags = 2 [(criu).flags = "rfile.flags"]; 15 | required uint64 pos = 3; 16 | required fown_entry fown = 5; 17 | required string name = 6; 18 | optional sint32 mnt_id = 7 [default = -1]; 19 | optional uint64 size = 8; 20 | optional bool ext = 9; 21 | optional uint32 mode = 10; 22 | 23 | /* This field stores the build-ID of the file if it could be obtained. */ 24 | repeated uint32 build_id = 11; 25 | 26 | /* This field stores the CRC32C checksum of the file if it could be obtained. */ 27 | optional uint32 checksum = 12; 28 | 29 | /* 30 | * This field stores the configuration of bytes which were used in the 31 | * calculation of the checksum, if it could be obtained. 32 | */ 33 | optional uint32 checksum_config = 13; 34 | 35 | /* 36 | * This field stores the checksum parameter if it was used in the calculation 37 | * of the checksum, if it could be obtained. 38 | */ 39 | optional uint32 checksum_parameter = 14; 40 | } -------------------------------------------------------------------------------- /proto/criu/remap-file-path.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | enum remap_type { 10 | LINKED = 0; 11 | GHOST = 1; 12 | PROCFS = 2; 13 | // Reserved for spfs manager 14 | // SPFS = 3; 15 | // SPFS_LINKED = 4; 16 | }; 17 | 18 | message remap_file_path_entry { 19 | required uint32 orig_id = 1; 20 | required uint32 remap_id = 2; 21 | optional remap_type remap_type = 3; 22 | } 23 | -------------------------------------------------------------------------------- /proto/criu/rlimit.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message rlimit_entry { 10 | required uint64 cur = 1; 11 | required uint64 max = 2; 12 | } 13 | -------------------------------------------------------------------------------- /proto/criu/rpc.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message criu_page_server_info { 10 | optional string address = 1; 11 | optional int32 port = 2; 12 | optional int32 pid = 3; 13 | optional int32 fd = 4; 14 | } 15 | 16 | message criu_veth_pair { 17 | required string if_in = 1; 18 | required string if_out = 2; 19 | }; 20 | 21 | message ext_mount_map { 22 | required string key = 1; 23 | required string val = 2; 24 | }; 25 | 26 | message join_namespace { 27 | required string ns = 1; 28 | required string ns_file = 2; 29 | optional string extra_opt = 3; 30 | } 31 | 32 | message inherit_fd { 33 | required string key = 1; 34 | required int32 fd = 2; 35 | }; 36 | 37 | message cgroup_root { 38 | optional string ctrl = 1; 39 | required string path = 2; 40 | }; 41 | 42 | message unix_sk { 43 | required uint32 inode = 1; 44 | }; 45 | 46 | enum criu_cg_mode { 47 | IGNORE = 0; 48 | CG_NONE = 1; 49 | PROPS = 2; 50 | SOFT = 3; 51 | FULL = 4; 52 | STRICT = 5; 53 | DEFAULT = 6; 54 | }; 55 | 56 | enum criu_network_lock_method { 57 | IPTABLES = 1; 58 | NFTABLES = 2; 59 | }; 60 | 61 | enum criu_pre_dump_mode { 62 | SPLICE = 1; 63 | VM_READ = 2; 64 | }; 65 | 66 | message criu_opts { 67 | required int32 images_dir_fd = 1; 68 | optional int32 pid = 2; /* if not set on dump, will dump requesting process */ 69 | 70 | optional bool leave_running = 3; 71 | optional bool ext_unix_sk = 4; 72 | optional bool tcp_established = 5; 73 | optional bool evasive_devices = 6; 74 | optional bool shell_job = 7; 75 | optional bool file_locks = 8; 76 | optional int32 log_level = 9 [default = 2]; 77 | optional string log_file = 10; /* No subdirs are allowed. Consider using work-dir */ 78 | 79 | optional criu_page_server_info ps = 11; 80 | 81 | optional bool notify_scripts = 12; 82 | 83 | optional string root = 13; 84 | optional string parent_img = 14; 85 | optional bool track_mem = 15; 86 | optional bool auto_dedup = 16; 87 | 88 | optional int32 work_dir_fd = 17; 89 | optional bool link_remap = 18; 90 | repeated criu_veth_pair veths = 19; /* DEPRECATED, use external instead */ 91 | 92 | optional uint32 cpu_cap = 20 [default = 0xffffffff]; 93 | optional bool force_irmap = 21; 94 | repeated string exec_cmd = 22; 95 | 96 | repeated ext_mount_map ext_mnt = 23; /* DEPRECATED, use external instead */ 97 | optional bool manage_cgroups = 24; /* backward compatibility */ 98 | repeated cgroup_root cg_root = 25; 99 | 100 | optional bool rst_sibling = 26; /* swrk only */ 101 | repeated inherit_fd inherit_fd = 27; /* swrk only */ 102 | 103 | optional bool auto_ext_mnt = 28; 104 | optional bool ext_sharing = 29; 105 | optional bool ext_masters = 30; 106 | 107 | repeated string skip_mnt = 31; 108 | repeated string enable_fs = 32; 109 | 110 | repeated unix_sk unix_sk_ino = 33; /* DEPRECATED, use external instead */ 111 | 112 | optional criu_cg_mode manage_cgroups_mode = 34; 113 | optional uint32 ghost_limit = 35 [default = 0x100000]; 114 | repeated string irmap_scan_paths = 36; 115 | repeated string external = 37; 116 | optional uint32 empty_ns = 38; 117 | repeated join_namespace join_ns = 39; 118 | 119 | optional string cgroup_props = 41; 120 | optional string cgroup_props_file = 42; 121 | repeated string cgroup_dump_controller = 43; 122 | 123 | optional string freeze_cgroup = 44; 124 | optional uint32 timeout = 45; 125 | optional bool tcp_skip_in_flight = 46; 126 | optional bool weak_sysctls = 47; 127 | optional bool lazy_pages = 48; 128 | optional int32 status_fd = 49; 129 | optional bool orphan_pts_master = 50; 130 | optional string config_file = 51; 131 | optional bool tcp_close = 52; 132 | optional string lsm_profile = 53; 133 | optional string tls_cacert = 54; 134 | optional string tls_cacrl = 55; 135 | optional string tls_cert = 56; 136 | optional string tls_key = 57; 137 | optional bool tls = 58; 138 | optional bool tls_no_cn_verify = 59; 139 | optional string cgroup_yard = 60; 140 | optional criu_pre_dump_mode pre_dump_mode = 61 [default = SPLICE]; 141 | optional int32 pidfd_store_sk = 62; 142 | optional string lsm_mount_context = 63; 143 | optional criu_network_lock_method network_lock = 64 [default = IPTABLES]; 144 | /* optional bool check_mounts = 128; */ 145 | } 146 | 147 | message criu_dump_resp { 148 | optional bool restored = 1; 149 | } 150 | 151 | message criu_restore_resp { 152 | required int32 pid = 1; 153 | } 154 | 155 | message criu_notify { 156 | optional string script = 1; 157 | optional int32 pid = 2; 158 | } 159 | 160 | enum criu_req_type { 161 | EMPTY = 0; 162 | DUMP = 1; 163 | RESTORE = 2; 164 | CHECK = 3; 165 | PRE_DUMP = 4; 166 | PAGE_SERVER = 5; 167 | 168 | NOTIFY = 6; 169 | 170 | CPUINFO_DUMP = 7; 171 | CPUINFO_CHECK = 8; 172 | 173 | FEATURE_CHECK = 9; 174 | 175 | VERSION = 10; 176 | 177 | WAIT_PID = 11; 178 | PAGE_SERVER_CHLD = 12; 179 | } 180 | 181 | /* 182 | * List of features which can queried via 183 | * CRIU_REQ_TYPE__FEATURE_CHECK 184 | */ 185 | message criu_features { 186 | optional bool mem_track = 1; 187 | optional bool lazy_pages = 2; 188 | optional bool pidfd_store = 3; 189 | } 190 | 191 | /* 192 | * Request -- each type corresponds to must-be-there 193 | * request arguments of respective type 194 | */ 195 | 196 | message criu_req { 197 | required criu_req_type type = 1; 198 | 199 | optional criu_opts opts = 2; 200 | optional bool notify_success = 3; 201 | 202 | /* 203 | * When set service won't close the connection but 204 | * will wait for more req-s to appear. Works not 205 | * for all request types. 206 | */ 207 | optional bool keep_open = 4; 208 | /* 209 | * 'features' can be used to query which features 210 | * are supported by the installed criu/kernel 211 | * via RPC. 212 | */ 213 | optional criu_features features = 5; 214 | 215 | /* 'pid' is used for WAIT_PID */ 216 | optional uint32 pid = 6; 217 | } 218 | 219 | /* 220 | * Response -- it states whether the request was served 221 | * and additional request-specific information 222 | */ 223 | 224 | message criu_resp { 225 | required criu_req_type type = 1; 226 | required bool success = 2; 227 | 228 | optional criu_dump_resp dump = 3; 229 | optional criu_restore_resp restore = 4; 230 | optional criu_notify notify = 5; 231 | optional criu_page_server_info ps = 6; 232 | 233 | optional int32 cr_errno = 7; 234 | optional criu_features features = 8; 235 | optional string cr_errmsg = 9; 236 | optional criu_version version = 10; 237 | 238 | optional int32 status = 11; 239 | } 240 | 241 | /* Answer for criu_req_type.VERSION requests */ 242 | message criu_version { 243 | required int32 major_number = 1; 244 | required int32 minor_number = 2; 245 | optional string gitid = 3; 246 | optional int32 sublevel = 4; 247 | optional int32 extra = 5; 248 | optional string name = 6; 249 | } 250 | -------------------------------------------------------------------------------- /proto/criu/sa.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message sa_entry { 12 | required uint64 sigaction = 1 [(criu).hex = true]; 13 | required uint64 flags = 2 [(criu).hex = true]; 14 | required uint64 restorer = 3 [(criu).hex = true]; 15 | required uint64 mask = 4 [(criu).hex = true]; 16 | optional bool compat_sigaction = 5; 17 | optional uint64 mask_extended = 6 [(criu).hex = true]; 18 | } 19 | -------------------------------------------------------------------------------- /proto/criu/seccomp.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message seccomp_filter { 10 | required bytes filter = 1; 11 | optional uint32 prev = 2; 12 | optional uint32 flags = 3; 13 | } 14 | 15 | message seccomp_entry { 16 | repeated seccomp_filter seccomp_filters = 1; 17 | } 18 | -------------------------------------------------------------------------------- /proto/criu/siginfo.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message siginfo_entry { 10 | required bytes siginfo = 1; 11 | } 12 | 13 | message signal_queue_entry { 14 | repeated siginfo_entry signals = 1; 15 | } 16 | -------------------------------------------------------------------------------- /proto/criu/signalfd.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | 12 | message signalfd_entry { 13 | required uint32 id = 1; 14 | required uint32 flags = 2 [(criu).hex = true]; 15 | required fown_entry fown = 3; 16 | required uint64 sigmask = 4 [(criu).hex = true]; 17 | }; 18 | -------------------------------------------------------------------------------- /proto/criu/sit.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message sit_entry { 12 | optional uint32 link = 1; 13 | repeated uint32 local = 2 [(criu).ipadd = true]; 14 | repeated uint32 remote = 3 [(criu).ipadd = true]; 15 | optional uint32 ttl = 4; 16 | optional uint32 tos = 5; 17 | optional bool pmtudisc = 6; 18 | optional uint32 proto = 7; 19 | optional uint32 flags = 8; 20 | optional uint32 encap_type = 9; 21 | optional uint32 encap_flags = 10; 22 | optional uint32 encap_sport = 11; 23 | optional uint32 encap_dport = 12; 24 | optional uint32 rd_prefixlen = 13; 25 | repeated uint32 rd_prefix = 14 [(criu).ipadd = true]; 26 | optional uint32 relay_prefixlen = 15; 27 | repeated uint32 relay_prefix = 16 [(criu).ipadd = true]; 28 | }; 29 | -------------------------------------------------------------------------------- /proto/criu/sk-inet.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | import "sk-opts.proto"; 12 | 13 | message ip_opts_raw_entry { 14 | optional bool hdrincl = 1; 15 | optional bool nodefrag = 2; 16 | optional bool checksum = 3; 17 | repeated uint32 icmpv_filter = 4; 18 | } 19 | 20 | message ip_opts_entry { 21 | optional bool freebind = 1; 22 | // Fields 2 and 3 are reserved for vz7 use 23 | optional ip_opts_raw_entry raw = 4; 24 | } 25 | 26 | message inet_sk_entry { 27 | /* 28 | * We have two IDs here -- id and ino. The first one 29 | * is used when restoring socket behind a file descriprot. 30 | * The fdinfo image's id is it. The second one is used 31 | * in sk-inet.c internally, in particular we identify 32 | * a TCP stream to restore into this socket using the 33 | * ino value. 34 | */ 35 | required uint32 id = 1; 36 | required uint32 ino = 2; 37 | required uint32 family = 3 [(criu).dict = "sk"]; 38 | required uint32 type = 4 [(criu).dict = "sk"]; 39 | required uint32 proto = 5 [(criu).dict = "sk"]; 40 | required uint32 state = 6 [(criu).dict = "sk"]; 41 | required uint32 src_port = 7; 42 | required uint32 dst_port = 8; 43 | required uint32 flags = 9 [(criu).hex = true]; 44 | required uint32 backlog = 10; 45 | 46 | repeated uint32 src_addr = 11 [(criu).ipadd = true]; 47 | repeated uint32 dst_addr = 12 [(criu).ipadd = true]; 48 | 49 | required fown_entry fown = 13; 50 | required sk_opts_entry opts = 14; 51 | optional bool v6only = 15; 52 | optional ip_opts_entry ip_opts = 16; 53 | 54 | /* for ipv6, we need to send the ifindex to bind(); we keep the ifname 55 | * here and convert it on restore */ 56 | optional string ifname = 17; 57 | optional uint32 ns_id = 18; 58 | optional sk_shutdown shutdown = 19; 59 | } 60 | -------------------------------------------------------------------------------- /proto/criu/sk-netlink.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | import "sk-opts.proto"; 12 | 13 | message netlink_sk_entry { 14 | required uint32 id = 1; 15 | required uint32 ino = 2; 16 | required uint32 protocol = 3; 17 | required uint32 state = 4; 18 | required uint32 flags = 6 [(criu).hex = true]; 19 | required uint32 portid = 7; 20 | repeated uint32 groups = 8; 21 | required uint32 dst_portid = 9; 22 | required uint32 dst_group = 10; 23 | required fown_entry fown = 11; 24 | required sk_opts_entry opts = 12; 25 | optional uint32 ns_id = 13; 26 | // For netlink queued messages 27 | // optional nl_sk_opts_entry nl_opts = 14; 28 | } 29 | -------------------------------------------------------------------------------- /proto/criu/sk-opts.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message sk_opts_entry { 10 | required uint32 so_sndbuf = 1; 11 | required uint32 so_rcvbuf = 2; 12 | 13 | required uint64 so_snd_tmo_sec = 3; 14 | required uint64 so_snd_tmo_usec = 4; 15 | required uint64 so_rcv_tmo_sec = 5; 16 | required uint64 so_rcv_tmo_usec = 6; 17 | optional bool reuseaddr = 7; 18 | 19 | optional uint32 so_priority = 8; 20 | optional uint32 so_rcvlowat = 9; 21 | optional uint32 so_mark = 10; 22 | optional bool so_passcred = 11; 23 | optional bool so_passsec = 12; 24 | optional bool so_dontroute = 13; 25 | optional bool so_no_check = 14; 26 | 27 | optional string so_bound_dev = 15; 28 | 29 | repeated fixed64 so_filter = 16; 30 | optional bool so_reuseport = 17; 31 | optional bool so_broadcast = 18; 32 | optional bool so_keepalive = 19; 33 | optional uint32 tcp_keepcnt = 20; 34 | optional uint32 tcp_keepidle = 21; 35 | optional uint32 tcp_keepintvl = 22; 36 | optional uint32 so_oobinline = 23; 37 | optional uint32 so_linger = 24; 38 | } 39 | 40 | enum sk_shutdown { 41 | NONE = 0; 42 | READ = 1; 43 | WRITE = 2; 44 | BOTH = 3; 45 | } 46 | -------------------------------------------------------------------------------- /proto/criu/sk-packet.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message scm_entry { 10 | required uint32 type = 1; 11 | repeated uint32 rights = 2; 12 | } 13 | 14 | message sk_packet_entry { 15 | required uint32 id_for = 1; 16 | required uint32 length = 2; 17 | // Reserved for message address 18 | // optional bytes addr = 3; 19 | repeated scm_entry scm = 4; 20 | // Reserved for ucred restore 21 | // optional sk_ucred_entry ucred = 128; 22 | } 23 | -------------------------------------------------------------------------------- /proto/criu/sk-unix.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | import "sk-opts.proto"; 12 | 13 | message file_perms_entry { 14 | required uint32 mode = 1; 15 | required uint32 uid = 2; 16 | required uint32 gid = 3; 17 | } 18 | 19 | message unix_sk_entry { 20 | /* 21 | * Few words about why we need both -- id and ino. 22 | * 23 | * The former one is used to link file descriptor from 24 | * fdinfo image with the unix_sk_entry that should be 25 | * opened under it. 26 | * 27 | * The latter one ties together unix peers -- the peer 28 | * member on this structure is the ino one of its peer 29 | * and simetimes vise-versa. 30 | */ 31 | required uint32 id = 1; 32 | required uint32 ino = 2; 33 | required uint32 type = 3 [(criu).dict = "sk"]; 34 | required uint32 state = 4 [(criu).dict = "sk"]; 35 | required uint32 flags = 5 [(criu).hex = true]; 36 | required uint32 uflags = 6 [(criu).hex = true]; 37 | required uint32 backlog = 7; 38 | required uint32 peer = 8; 39 | required fown_entry fown = 9; 40 | required sk_opts_entry opts = 10; 41 | 42 | /* 43 | * Abstract name may contain \0 at any point, 44 | * so we need to carry it as byte sequence... 45 | */ 46 | required bytes name = 11 [(criu).conv = "unix_name"]; 47 | 48 | optional sk_shutdown shutdown = 12; 49 | 50 | optional file_perms_entry file_perms = 13; 51 | 52 | /* 53 | * Relative socket name may have prefix. 54 | */ 55 | optional string name_dir = 14; 56 | optional bool deleted = 15; 57 | 58 | optional uint32 ns_id = 16; 59 | optional sint32 mnt_id = 17 [default = -1]; 60 | /* Please, don't use field with number 18. */ 61 | } 62 | -------------------------------------------------------------------------------- /proto/criu/stats.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | // This one contains statistics about dump/restore process 10 | message dump_stats_entry { 11 | required uint32 freezing_time = 1; 12 | required uint32 frozen_time = 2; 13 | required uint32 memdump_time = 3; 14 | required uint32 memwrite_time = 4; 15 | 16 | required uint64 pages_scanned = 5; 17 | required uint64 pages_skipped_parent = 6; 18 | required uint64 pages_written = 7; 19 | 20 | optional uint32 irmap_resolve = 8; 21 | 22 | required uint64 pages_lazy = 9; 23 | optional uint64 page_pipes = 10; 24 | optional uint64 page_pipe_bufs = 11; 25 | 26 | optional uint64 shpages_scanned = 12; 27 | optional uint64 shpages_skipped_parent = 13; 28 | optional uint64 shpages_written = 14; 29 | } 30 | 31 | message restore_stats_entry { 32 | required uint64 pages_compared = 1; 33 | required uint64 pages_skipped_cow = 2; 34 | 35 | required uint32 forking_time = 3; 36 | required uint32 restore_time = 4; 37 | 38 | optional uint64 pages_restored = 5; 39 | } 40 | 41 | message stats_entry { 42 | optional dump_stats_entry dump = 1; 43 | optional restore_stats_entry restore = 2; 44 | } 45 | -------------------------------------------------------------------------------- /proto/criu/sysctl.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | enum SysctlType { 10 | CTL_STR = 5; 11 | CTL_32 = 6; 12 | } 13 | 14 | message sysctl_entry { 15 | required SysctlType type = 1; 16 | 17 | optional int32 iarg = 2; 18 | optional string sarg = 3; 19 | } 20 | -------------------------------------------------------------------------------- /proto/criu/tcp-stream.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message tcp_stream_entry { 12 | required uint32 inq_len = 1; 13 | required uint32 inq_seq = 2; 14 | required uint32 outq_len = 3; /* unsent and sent data in the send queue*/ 15 | required uint32 outq_seq = 4; 16 | 17 | required uint32 opt_mask = 5 [(criu).hex = true]; /* TCPI_OPT_ bits */ 18 | required uint32 snd_wscale = 6; 19 | required uint32 mss_clamp = 7; 20 | optional uint32 rcv_wscale = 8; 21 | optional uint32 timestamp = 9; 22 | 23 | optional bool cork = 10; 24 | optional bool nodelay = 11; 25 | 26 | optional uint32 unsq_len = 12; /* unsent data in the send queue */ 27 | 28 | optional uint32 snd_wl1 = 13; 29 | optional uint32 snd_wnd = 14; 30 | optional uint32 max_window = 15; 31 | optional uint32 rcv_wnd = 16; 32 | optional uint32 rcv_wup = 17; 33 | } 34 | -------------------------------------------------------------------------------- /proto/criu/time.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message timeval { 10 | required uint64 tv_sec = 1; 11 | required uint64 tv_usec = 2; 12 | } 13 | -------------------------------------------------------------------------------- /proto/criu/timens.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message timespec { 10 | required uint64 tv_sec = 1; 11 | required uint64 tv_nsec = 2; 12 | } 13 | message timens_entry { 14 | required timespec monotonic = 1; 15 | required timespec boottime = 2; 16 | } 17 | -------------------------------------------------------------------------------- /proto/criu/timer.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message itimer_entry { 10 | required uint64 isec = 1; 11 | required uint64 iusec = 2; 12 | required uint64 vsec = 3; 13 | required uint64 vusec = 4; 14 | } 15 | 16 | message posix_timer_entry { 17 | required uint32 it_id = 1; 18 | required uint32 clock_id = 2; 19 | required uint32 si_signo = 3; 20 | required uint32 it_sigev_notify = 4; 21 | required uint64 sival_ptr = 5; 22 | required uint32 overrun = 6; 23 | 24 | required uint64 isec = 7; 25 | required uint64 insec = 8; 26 | required uint64 vsec = 9; 27 | required uint64 vnsec = 10; 28 | optional int32 notify_thread_id= 11; 29 | } 30 | 31 | message task_timers_entry { 32 | required itimer_entry real = 1; 33 | required itimer_entry virt = 2; 34 | required itimer_entry prof = 3; 35 | repeated posix_timer_entry posix = 4; 36 | } 37 | -------------------------------------------------------------------------------- /proto/criu/timerfd.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | 12 | message timerfd_entry { 13 | required uint32 id = 1; 14 | required uint32 flags = 2 [(criu).hex = true]; 15 | required fown_entry fown = 3; 16 | 17 | required uint32 clockid = 4; 18 | required uint64 ticks = 5; 19 | required uint32 settime_flags = 6 [(criu).hex = true]; 20 | 21 | required uint64 vsec = 7; 22 | required uint64 vnsec = 8; 23 | required uint64 isec = 9; 24 | required uint64 insec = 10; 25 | } 26 | -------------------------------------------------------------------------------- /proto/criu/tty.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | import "fown.proto"; 11 | 12 | message winsize_entry { 13 | required uint32 ws_row = 1; 14 | required uint32 ws_col = 2; 15 | required uint32 ws_xpixel = 3; 16 | required uint32 ws_ypixel = 4; 17 | }; 18 | 19 | message termios_entry { 20 | required uint32 c_iflag = 1; 21 | required uint32 c_oflag = 2; 22 | required uint32 c_cflag = 3; 23 | required uint32 c_lflag = 4; 24 | required uint32 c_line = 5; 25 | required uint32 c_ispeed = 6; 26 | required uint32 c_ospeed = 7; 27 | 28 | repeated uint32 c_cc = 8; 29 | } 30 | 31 | message tty_pty_entry { 32 | required uint32 index = 1; 33 | } 34 | 35 | enum TtyType { 36 | UNKNOWN = 0; 37 | PTY = 1; 38 | CONSOLE = 2; 39 | VT = 3; 40 | CTTY = 4; 41 | EXT_TTY = 5; 42 | SERIAL = 6; 43 | } 44 | 45 | message tty_data_entry { 46 | required uint32 tty_id = 1; 47 | required bytes data = 2; 48 | 49 | // optional sint32 mnt_id = 3 [default = 0]; 50 | } 51 | 52 | message tty_info_entry { 53 | required uint32 id = 1; 54 | 55 | required TtyType type = 2; 56 | 57 | required bool locked = 3; /* Unix98 PTY only */ 58 | required bool exclusive = 4; 59 | required bool packet_mode = 5; /* Unix98 PTY only */ 60 | 61 | required uint32 sid = 6; 62 | required uint32 pgrp = 7; 63 | 64 | /* 65 | * Convenient for printing errors and such, with this 66 | * device encoded we can figure out major and minor 67 | * numbers. 68 | */ 69 | required uint32 rdev = 8; 70 | 71 | optional termios_entry termios = 9; 72 | optional termios_entry termios_locked = 10; 73 | optional winsize_entry winsize = 11; 74 | 75 | /* 76 | * These are optional fields which presence depends on 77 | * TTY type. 78 | */ 79 | optional tty_pty_entry pty = 12; 80 | optional uint32 dev = 13; 81 | 82 | optional uint32 uid = 14; 83 | optional uint32 gid = 15; 84 | 85 | // optional sint32 mnt_id = 16 [default = 0]; 86 | }; 87 | 88 | message tty_file_entry { 89 | required uint32 id = 1; 90 | required uint32 tty_info_id = 2; 91 | 92 | required uint32 flags = 3 [(criu).hex = true]; 93 | required fown_entry fown = 4; 94 | // optional sint32 mnt_id = 5 [default = 0]; 95 | optional uint32 regf_id = 6; 96 | } 97 | -------------------------------------------------------------------------------- /proto/criu/tun.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message tunfile_entry { 12 | required uint32 id = 1; 13 | optional string netdev = 2; 14 | optional bool detached = 3; 15 | optional uint32 ns_id = 4; 16 | }; 17 | 18 | message tun_link_entry { 19 | required uint32 flags = 1 [(criu).hex = true]; 20 | required int32 owner = 2; 21 | required int32 group = 3; 22 | required uint32 vnethdr = 4; 23 | required uint32 sndbuf = 5; 24 | }; 25 | -------------------------------------------------------------------------------- /proto/criu/userns.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message uid_gid_extent { 10 | required uint32 first = 1; 11 | required uint32 lower_first = 2; 12 | required uint32 count = 3; 13 | } 14 | 15 | message userns_entry { 16 | repeated uid_gid_extent uid_map = 1; 17 | repeated uid_gid_extent gid_map = 2; 18 | } 19 | -------------------------------------------------------------------------------- /proto/criu/utsns.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | message utsns_entry { 10 | required string nodename = 1; 11 | required string domainname = 2; 12 | } 13 | -------------------------------------------------------------------------------- /proto/criu/vma.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | 4 | // File imported by sync_criu_proto_files.sh 5 | 6 | syntax = "proto2"; 7 | package criu; 8 | 9 | import "opts.proto"; 10 | 11 | message vma_entry { 12 | required uint64 start = 1 [(criu).hex = true]; 13 | required uint64 end = 2 [(criu).hex = true]; 14 | required uint64 pgoff = 3; 15 | required uint64 shmid = 4; 16 | required uint32 prot = 5 [(criu).flags = "mmap.prot" ]; 17 | required uint32 flags = 6 [(criu).flags = "mmap.flags" ]; 18 | required uint32 status = 7 [(criu).flags = "mmap.status" ]; 19 | /* 20 | * This fd thing is unused in the image, it was lost 21 | * while switching from execve restore model. It is 22 | * -1 by default. 23 | */ 24 | required sint64 fd = 8; 25 | 26 | /* madvise flags bitmap */ 27 | optional uint64 madv = 9 [(criu).hex = true]; 28 | 29 | /* file status flags */ 30 | optional uint32 fdflags = 10 [(criu).hex = true]; 31 | } 32 | -------------------------------------------------------------------------------- /proto/image.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package image; 4 | 5 | message marker { 6 | uint64 seq = 1; 7 | oneof body { 8 | string filename = 2; 9 | uint32 file_data = 3; 10 | bool file_eof = 4; 11 | bool image_eof = 5; 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | use clap::Parser; 21 | 22 | pub const DEFAULT_ADDRESS: &str = "127.0.0.1"; 23 | pub const DEFAULT_PORT: &str = "8080"; 24 | 25 | #[derive(Parser)] 26 | #[clap( 27 | version = env!("CARGO_PKG_VERSION"), 28 | author = env!("CARGO_PKG_AUTHORS"), 29 | about = env!("CARGO_PKG_DESCRIPTION") 30 | )] 31 | pub struct Opts { 32 | #[clap(subcommand)] 33 | pub mode: Mode, 34 | } 35 | 36 | #[derive(Parser)] 37 | pub enum Mode { 38 | #[clap(about = "Run as client", aliases = ["c"])] 39 | Client { 40 | #[clap(long, default_value = DEFAULT_ADDRESS, help = "Address to connect the client to")] 41 | address: String, 42 | 43 | #[clap(long, default_value = DEFAULT_PORT, help = "Port to connect the client to")] 44 | port: u16, 45 | 46 | #[clap(short, long, help = "Unique client ID")] 47 | id: String, 48 | 49 | #[clap(short, long, help = "A colon-separated list of dependency IDs")] 50 | deps: String, 51 | 52 | #[clap(short, long, default_value = "pre-dump", help = "Action name indicating the stage of checkpoint/restore")] 53 | action: String, 54 | 55 | #[clap(short = 'D', long, default_value = ".", help = "Images directory where the stream socket is created")] 56 | images_dir: String, 57 | 58 | #[clap(short = 's', long, help = "Use checkpoint streaming")] 59 | stream: bool, 60 | 61 | #[clap(short = 'o', long, default_value = "-", hide_default_value = true, help = "Log file name")] 62 | log_file: String, 63 | }, 64 | 65 | #[clap(about = "Run as server", aliases = ["s"])] 66 | Server { 67 | #[clap(short, long, default_value = DEFAULT_ADDRESS, help = "Address to bind the server to")] 68 | address: String, 69 | 70 | #[clap(short, long, default_value = DEFAULT_PORT, help = "Port to bind the server to")] 71 | port: u16, 72 | 73 | #[clap(short = 'o', long, default_value = "-", hide_default_value = true, help = "Log file name")] 74 | log_file: String, 75 | }, 76 | 77 | #[clap(about = "Generate shell completions")] 78 | Completions { 79 | #[clap(help = "Shell type (e.g., bash, zsh, fish, powershell, elvish)")] 80 | shell: String, 81 | }, 82 | } 83 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | use std::io::{Read, Write}; 21 | use std::net::{TcpStream, Shutdown}; 22 | use std::path::Path; 23 | use std::process::exit; 24 | use std::str; 25 | use json::object; 26 | use log::*; 27 | 28 | use crate::constants::MESSAGE_ACK; 29 | use crate::pipeline::streamer::streamer; 30 | 31 | const BUFFER_SIZE: usize = 32768 * 4; 32 | 33 | pub fn run_client(address: &str, port: u16, id: &str, deps: &str, action: &str, images_dir: &Path, enable_streaming: bool) { 34 | let server_address = format!("{}:{}", address, port); 35 | 36 | info!("Connecting to {} using action {}", server_address, action); 37 | match TcpStream::connect(&server_address) { 38 | Ok(mut tcp_stream) => { 39 | info!("Connected to server at {}", server_address); 40 | 41 | let cmd = object!{ 42 | id: id, 43 | action: action, 44 | dependencies: deps, 45 | }; 46 | 47 | if let Err(e) = tcp_stream.write_all(cmd.dump().as_bytes()) { 48 | error!("Failed to send ID: {}", e); 49 | return; 50 | } 51 | 52 | let mut buffer = [0; BUFFER_SIZE]; 53 | let response = match tcp_stream.read(&mut buffer) { 54 | Ok(size) => str::from_utf8(&buffer[..size]).map_err(|e| e.to_string()), 55 | Err(e) => Err(e.to_string()), 56 | }; 57 | 58 | match response { 59 | Ok(response_str) => { 60 | info!("Server responded with: {}", response_str); 61 | if response_str != MESSAGE_ACK { 62 | exit(1); 63 | } 64 | } 65 | Err(e) => { 66 | error!("Failed to receive response: {}", e); 67 | } 68 | } 69 | 70 | if enable_streaming { 71 | streamer(&mut tcp_stream, images_dir).expect("Failed to start streamer"); 72 | } 73 | 74 | if let Err(e) = tcp_stream.shutdown(Shutdown::Both) { 75 | error!("Failed to shutdown TCP connection: {}", e); 76 | } 77 | } 78 | Err(e) => { 79 | error!("Failed to connect to the server: {}", e); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/constants.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | pub const ACTION_PRE_DUMP: &str = "pre-dump"; 21 | pub const ACTION_POST_DUMP: &str = "post-dump"; 22 | pub const ACTION_PRE_RESTORE: &str = "pre-restore"; 23 | pub const ACTION_POST_RESTORE: &str = "post-restore"; 24 | pub const ACTION_PRE_STREAM: &str = "pre-stream"; 25 | pub const ACTION_POST_STREAM: &str = "post-stream"; 26 | pub const ACTION_ADD_DEPENDENCIES: &str = "add-dependencies"; 27 | 28 | /// ENV_ACTION specifies the CRIU hook that is currently being used. 29 | pub const ENV_ACTION: &str = "CRTOOLS_SCRIPT_ACTION"; 30 | /// ENV_IMAGE_DIR specifies path as used a base directory for CRIU images. 31 | pub const ENV_IMAGE_DIR: &str = "CRTOOLS_IMAGE_DIR"; 32 | 33 | /// Unix socket used for "criu dump". 34 | pub const IMG_STREAMER_CAPTURE_SOCKET_NAME: &str = "streamer-capture.sock"; 35 | 36 | /// CONFIG_FILE is used to load checkpoint/restore parameters. 37 | pub const CONFIG_FILE: &str = "criu-coordinator.json"; 38 | 39 | /// Acknowledgment message sent to clients when an operation is successful. 40 | pub const MESSAGE_ACK: &str = "ACK"; 41 | /// Synchronization message to indicate that a local checkpoint is ready. 42 | pub const MESSAGE_SYN: &str = "SYN"; 43 | /// Acknowledgment message for successful receipt of an image chunk. 44 | pub const MESSAGE_IMG_ACK: &str = "IMG_ACK"; 45 | /// Error message to signal a timed out during connection or readiness check. 46 | pub const MESSAGE_TIMEOUT: &str = "timeout"; 47 | /// Error message when a client dependency is not connected. 48 | pub const MESSAGE_NOT_CONNECTED: &str = "not connected"; 49 | /// Message indicating that a checkpoint is already created. 50 | pub const MESSAGE_CHECKPOINT_EXISTS: &str = "checkpoint is already created"; 51 | /// Message indicating that a client is already connected. 52 | pub const MESSAGE_ALREADY_CONNECTED: &str = "client already connected"; 53 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | #[allow(clippy::all)] 21 | pub mod criu { 22 | include!(concat!(env!("OUT_DIR"), "/criu.rs")); 23 | } 24 | 25 | #[allow(clippy::all)] 26 | pub mod image { 27 | include!(concat!(env!("OUT_DIR"), "/image.rs")); 28 | } 29 | -------------------------------------------------------------------------------- /src/logger.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | use std::fs::{File, self, OpenOptions}; 21 | use std::os::unix::fs::OpenOptionsExt; 22 | use std::io::Write; 23 | use std::path::Path; 24 | use log::{Level, Metadata, Record, LevelFilter}; 25 | 26 | pub struct Logger { 27 | log_file: Option, 28 | } 29 | 30 | impl Logger { 31 | pub fn new() -> Box { 32 | Box::new(Self { log_file: None }) 33 | } 34 | 35 | pub fn set_log_file(&mut self, filename: String) { 36 | if filename == "-" { 37 | self.log_file = None; 38 | } else { 39 | match OpenOptions::new().write(true).create(true).truncate(true).mode(0o600).open(filename) { 40 | Ok(file) => { 41 | self.log_file = Some(file); 42 | } 43 | Err(error) => panic!("Opening log file: {:?}", error) 44 | } 45 | } 46 | } 47 | } 48 | 49 | impl log::Log for Logger { 50 | fn enabled(&self, metadata: &Metadata) -> bool { 51 | metadata.level() <= Level::Info 52 | } 53 | 54 | fn log(&self, record: &Record) { 55 | if self.enabled(record.metadata()) { 56 | if self.log_file.is_some() { 57 | if let Err(error) = writeln!(self.log_file.as_ref().unwrap(), "{} - {}", record.level(), record.args()) { 58 | eprintln!("Error writing to log file: {}", error); 59 | } 60 | } else { 61 | println!("{} - {}", record.level(), record.args()); 62 | } 63 | } 64 | } 65 | fn flush(&self) {} 66 | } 67 | 68 | pub fn init_logger(images_dir: Option<&Path>, filename: String) { 69 | let mut main_logger = Logger::new(); 70 | log_panics::init(); 71 | 72 | match filename.as_str() { 73 | "-" => {} // Do nothing 74 | _ if images_dir.is_none() || filename.starts_with('/') => { 75 | main_logger.set_log_file(filename); 76 | } 77 | _ => { 78 | let images_dir = images_dir.unwrap(); 79 | fs::create_dir_all(images_dir).unwrap_or_else(|_| panic!("Can't create images directory")); 80 | let full_path = images_dir.join(filename); 81 | main_logger.set_log_file(full_path.into_os_string().into_string().unwrap()); 82 | } 83 | } 84 | 85 | log::set_boxed_logger(main_logger).unwrap(); 86 | log::set_max_level(LevelFilter::Info); 87 | } -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | mod cli; 21 | mod client; 22 | mod server; 23 | mod constants; 24 | mod pipeline; 25 | mod logger; 26 | 27 | use constants::*; 28 | use config::Config; 29 | use std::collections::HashMap; 30 | use std::{env, path::PathBuf, process::exit, fs, os::unix::prelude::FileTypeExt}; 31 | use std::path::Path; 32 | 33 | use clap::{CommandFactory, Parser}; 34 | use clap_complete::{generate, Shell}; 35 | use std::io; 36 | 37 | use cli::{Opts, Mode, DEFAULT_ADDRESS, DEFAULT_PORT}; 38 | use client::run_client; 39 | use server::run_server; 40 | use logger::init_logger; 41 | 42 | struct ClientConfig { 43 | log_file: String, 44 | address: String, 45 | port: String, 46 | id: String, 47 | dependencies: String, 48 | } 49 | 50 | const CONFIG_KEY_ID: &str = "id"; 51 | const CONFIG_KEY_DEPS: &str = "dependencies"; 52 | const CONFIG_KEY_ADDR: &str = "address"; 53 | const CONFIG_KEY_PORT: &str = "port"; 54 | const CONFIG_KEY_LOG: &str = "log-file"; 55 | 56 | fn load_config_file>(images_dir: P) -> ClientConfig { 57 | let images_dir = images_dir.as_ref(); 58 | let mut config_file = images_dir.join(Path::new(CONFIG_FILE)); 59 | if !config_file.is_file() { 60 | // The following allows us to load global config files from /etc/criu. 61 | // This is useful for example when we want to use the same config file 62 | // for multiple containers. 63 | let config_dir = PathBuf::from("/etc/criu"); 64 | config_file = config_dir.join(Path::new(CONFIG_FILE)); 65 | if !config_file.is_file() { 66 | panic!("config file does not exist") 67 | } 68 | } 69 | 70 | let settings = Config::builder().add_source(config::File::from(config_file)).build().unwrap(); 71 | let settings_map = settings.try_deserialize::>().unwrap(); 72 | 73 | if !settings_map.contains_key(CONFIG_KEY_ID) { 74 | panic!("id missing in config file") 75 | } 76 | let id = settings_map.get(CONFIG_KEY_ID).unwrap(); 77 | 78 | let mut dependencies = String::new(); 79 | if settings_map.contains_key(CONFIG_KEY_DEPS) { 80 | dependencies = settings_map.get(CONFIG_KEY_DEPS).unwrap().to_string(); 81 | } 82 | 83 | let mut address = DEFAULT_ADDRESS; 84 | if settings_map.contains_key(CONFIG_KEY_ADDR) { 85 | address = settings_map.get(CONFIG_KEY_ADDR).unwrap(); 86 | } 87 | 88 | let mut port = DEFAULT_PORT; 89 | if settings_map.contains_key(CONFIG_KEY_PORT) { 90 | port = settings_map.get(CONFIG_KEY_PORT).unwrap(); 91 | } 92 | 93 | let mut log_file = "-"; 94 | if settings_map.contains_key(CONFIG_KEY_LOG) { 95 | log_file = settings_map.get(CONFIG_KEY_LOG).unwrap(); 96 | } 97 | 98 | ClientConfig { 99 | log_file: log_file.to_string(), 100 | address: address.to_string(), 101 | port: port.to_string(), 102 | id: id.to_string(), 103 | dependencies, 104 | } 105 | } 106 | 107 | fn main() { 108 | if let Ok(action) = env::var(ENV_ACTION) { 109 | 110 | let images_dir = PathBuf::from(env::var(ENV_IMAGE_DIR) 111 | .unwrap_or_else(|_| panic!("Missing {} environment variable", ENV_IMAGE_DIR))); 112 | 113 | let client_config = load_config_file(&images_dir); 114 | 115 | // Ignore all action hooks other than "pre-stream", "pre-dump" and "pre-restore". 116 | let enable_streaming = match action.as_str() { 117 | ACTION_PRE_STREAM => true, 118 | ACTION_PRE_DUMP => { 119 | match fs::symlink_metadata(images_dir.join(IMG_STREAMER_CAPTURE_SOCKET_NAME)) { 120 | Ok(metadata) => { 121 | if !metadata.file_type().is_socket() { 122 | panic!("{} exists but is not a Unix socket", IMG_STREAMER_CAPTURE_SOCKET_NAME); 123 | } 124 | // If the stream socket exists, ignore CRIU's "pre-dump" action hook. 125 | exit(0); 126 | }, 127 | Err(_) => false 128 | } 129 | }, 130 | ACTION_POST_DUMP => false, 131 | ACTION_PRE_RESTORE => false, 132 | _ => exit(0) 133 | }; 134 | 135 | init_logger(Some(&images_dir), client_config.log_file); 136 | 137 | run_client( 138 | &client_config.address, 139 | client_config.port.parse().unwrap(), 140 | &client_config.id, 141 | &client_config.dependencies, 142 | &action, 143 | &images_dir, 144 | enable_streaming 145 | ); 146 | exit(0); 147 | } 148 | 149 | let opts = Opts::parse(); 150 | 151 | match opts.mode { 152 | Mode::Completions { shell } => { 153 | let shell: Shell = shell.parse().expect("Invalid shell type"); 154 | let mut cmd = Opts::command(); 155 | generate(shell, &mut cmd, "criu-coordinator", &mut io::stdout()); 156 | } 157 | 158 | Mode::Client { address, port, id, deps, action, images_dir, stream, log_file} => { 159 | init_logger(Some(&PathBuf::from(&images_dir)), log_file); 160 | run_client(&address, port, &id, &deps, &action, &PathBuf::from(images_dir), stream); 161 | }, 162 | Mode::Server { address, port , log_file} => { 163 | init_logger(None, log_file); 164 | run_server(&address, port); 165 | } 166 | }; 167 | } 168 | -------------------------------------------------------------------------------- /src/pipeline.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | pub mod protobuf; 21 | pub mod unix_pipe; 22 | pub mod streamer; 23 | pub mod monitor; 24 | pub mod criu; 25 | pub mod ord_by; -------------------------------------------------------------------------------- /src/pipeline/criu.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | //! This module is responsible for handling the communication between the 21 | //! criu-coordinator and CRIU over the a local (unix) socket. 22 | 23 | use criu_coordinator::criu::ImgStreamerRequestEntry; 24 | 25 | use log::*; 26 | use std::{ 27 | fs, 28 | io::{Result, IoSliceMut}, 29 | path::Path, 30 | os::fd::{RawFd, AsRawFd}, 31 | process::exit, 32 | os::unix::net::{UnixListener, UnixStream}, 33 | }; 34 | use nix::sys::socket::{ControlMessageOwned, MsgFlags, recvmsg, RecvMsg, UnixAddr}; 35 | use crate::constants::IMG_STREAMER_CAPTURE_SOCKET_NAME; 36 | 37 | use super::{ 38 | protobuf::pb_read_next, 39 | unix_pipe::{UnixFile, UnixPipe} 40 | }; 41 | 42 | pub struct StreamListener { 43 | listener: UnixListener, 44 | } 45 | 46 | impl StreamListener { 47 | fn bind(socket_path: &Path) -> Result { 48 | let _ = fs::remove_file(socket_path); 49 | let listener = UnixListener::bind(socket_path)?; 50 | Ok(Self { listener }) 51 | } 52 | 53 | pub fn bind_for_checkpoint(images_dir: &Path) -> Result { 54 | Self::bind(&images_dir.join(IMG_STREAMER_CAPTURE_SOCKET_NAME)) 55 | } 56 | 57 | pub fn accept(self) -> Result { 58 | let (socket, _) = self.listener.accept()?; 59 | Ok(StreamConnection { socket }) 60 | } 61 | } 62 | 63 | pub struct StreamConnection { 64 | socket: UnixStream, 65 | } 66 | 67 | impl StreamConnection { 68 | pub fn as_raw_fd(&self) -> RawFd { 69 | self.socket.as_raw_fd() 70 | } 71 | 72 | pub(crate) fn read_next_file_request(&mut self) -> Result> { 73 | Ok(pb_read_next(&mut self.socket)?.map(|(req, _): (ImgStreamerRequestEntry, _)| req.filename)) 74 | } 75 | 76 | pub fn recv_pipe(&mut self) -> Result { 77 | UnixPipe::new(recv_fd(&mut self.socket)?) 78 | } 79 | } 80 | 81 | pub fn recv_fd(socket: &mut UnixStream) -> Result { 82 | let mut cmsgspace = nix::cmsg_space!([RawFd; 1]); 83 | 84 | let mut binding = [0]; 85 | let mut binding = [IoSliceMut::new(&mut binding)]; 86 | let msg: RecvMsg = recvmsg( 87 | socket.as_raw_fd(), 88 | &mut binding, 89 | Some(&mut cmsgspace), 90 | MsgFlags::empty() 91 | )?; 92 | 93 | Ok(match msg.cmsgs().next() { 94 | Some(ControlMessageOwned::ScmRights(fds)) if fds.len() == 1 => fds[0], 95 | _ => { 96 | error!("No fd received"); 97 | exit(0); 98 | }, 99 | }) 100 | } 101 | -------------------------------------------------------------------------------- /src/pipeline/monitor.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | //! This module is responsible for I/O monitoring of the stream file descriptors. 21 | 22 | use std::{ 23 | os::fd::RawFd, 24 | io::Result, 25 | convert::TryFrom, 26 | rc::Rc, 27 | fs::File, 28 | }; 29 | use slab::Slab; 30 | use nix::{ 31 | sys::epoll::{epoll_create, epoll_ctl, EpollOp, EpollEvent, EpollFlags, epoll_wait}, 32 | unistd::close, errno::Errno, 33 | }; 34 | use crate::pipeline::protobuf::MB; 35 | use super::{criu::StreamConnection, unix_pipe::{UnixFile, UnixPipe}}; 36 | 37 | 38 | /// CRIU has difficulties if the pipe size is bigger than 4MB. 39 | /// Note that the following pipe buffers are not actually using memory. The content of the pipe is 40 | /// just a list of pointers to the application memory page, which is already allocated as CRIU does 41 | /// a vmsplice(..., SPLICE_F_GIFT) when providing data. 42 | const CRIU_PIPE_DESIRED_CAPACITY: i32 = 4*MB as i32; 43 | 44 | /// ImageFile represents a CRIU image file. 45 | pub struct ImageFile { 46 | /// Incoming pipe from CRIU 47 | pub pipe: UnixFile, 48 | /// Associated filename (e.g., "pages-3.img") 49 | pub filename: Rc, 50 | /// Output file 51 | pub output_file: File, 52 | } 53 | impl ImageFile { 54 | pub(crate) fn new(filename: String, mut pipe: UnixFile, output_file: File) -> Self { 55 | let _ = pipe.set_capacity(CRIU_PIPE_DESIRED_CAPACITY); 56 | let filename = Rc::from(filename); 57 | Self { pipe, filename, output_file } 58 | } 59 | } 60 | 61 | /// MonitorType represents ... 62 | pub enum MonitorType { 63 | Criu(StreamConnection), 64 | ImageFile(ImageFile), 65 | } 66 | 67 | /// Monitor is responsible for monitoring multiple file descriptors 68 | /// to see if I/O is possible on any of them. 69 | pub struct Monitor { 70 | epoll_fd: RawFd, 71 | slab: Slab<(RawFd, T)>, 72 | pending_events: Vec, 73 | } 74 | 75 | impl Monitor { 76 | pub fn new() -> Result { 77 | let epoll_fd = epoll_create()?; 78 | let slab = Slab::new(); 79 | let pending_events = Vec::new(); 80 | 81 | Ok(Self { epoll_fd, slab, pending_events }) 82 | } 83 | 84 | pub fn add(&mut self, fd: RawFd, obj: T, flags: EpollFlags) -> Result { 85 | let entry = self.slab.vacant_entry(); 86 | let key = entry.key(); 87 | let mut event = EpollEvent::new(flags, u64::try_from(key).unwrap()); 88 | epoll_ctl(self.epoll_fd, EpollOp::EpollCtlAdd, fd, &mut event)?; 89 | entry.insert((fd, obj)); 90 | Ok(key) 91 | } 92 | 93 | pub(crate) fn poll(&mut self, capacity: usize) -> Result> { 94 | if self.slab.is_empty() { 95 | return Ok(None); 96 | } 97 | 98 | if self.pending_events.is_empty() { 99 | self.pending_events.resize(capacity, EpollEvent::empty()); 100 | 101 | let timeout = -1; 102 | let num_ready_fds = epoll_wait_no_intr(self.epoll_fd, &mut self.pending_events, timeout)?; 103 | 104 | assert!(num_ready_fds > 0); 105 | 106 | self.pending_events.truncate(num_ready_fds); 107 | } 108 | 109 | let event = self.pending_events.pop().unwrap(); 110 | let key = event.data() as usize; 111 | let (_fd, obj) = &mut self.slab[key]; 112 | Ok(Some((key, obj))) 113 | } 114 | 115 | pub fn remove(&mut self, key: usize) -> Result { 116 | let (fd, obj) = self.slab.remove(key); 117 | epoll_ctl(self.epoll_fd, EpollOp::EpollCtlDel, fd, None)?; 118 | Ok(obj) 119 | } 120 | } 121 | 122 | impl Drop for Monitor { 123 | fn drop(&mut self) { 124 | close(self.epoll_fd).expect("Failed to close epoll"); 125 | } 126 | } 127 | 128 | pub fn epoll_wait_no_intr(epoll_fd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) 129 | -> nix::Result 130 | { 131 | loop { 132 | match epoll_wait(epoll_fd, events, timeout_ms) { 133 | Err(Errno::EINTR) => continue, 134 | other => return other, 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/pipeline/ord_by.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | /// `impl_ord_by!` provides ordering on a type given a closure. 21 | /// We use it for providing ordering to types that are used in a BinaryHeap. 22 | #[macro_export] 23 | macro_rules! impl_ord_by { 24 | ($type:ident$(<$($gen:tt),+>)?, $cmp_fn:expr) => { 25 | impl$(<$($gen),+>)? Ord for $type$(<$($gen),+>)? { 26 | fn cmp(&self, other: &Self) -> std::cmp::Ordering { 27 | $cmp_fn(self, other) 28 | } 29 | } 30 | 31 | impl$(<$($gen),+>)? PartialOrd for $type$(<$($gen),+>)? { 32 | fn partial_cmp(&self, other: &Self) -> Option { 33 | Some(self.cmp(other)) 34 | } 35 | } 36 | 37 | impl$(<$($gen),+>)? PartialEq for $type$(<$($gen),+>)? { 38 | fn eq(&self, other: &Self) -> bool { 39 | self.cmp(other) == std::cmp::Ordering::Equal 40 | } 41 | } 42 | 43 | impl$(<$($gen),+>)? Eq for $type$(<$($gen),+>)? {} 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /src/pipeline/protobuf.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | use log::*; 21 | use prost::Message; 22 | use std::{ 23 | mem::size_of, 24 | process::exit, 25 | io::{Read, Result}, 26 | }; 27 | use bytes::{BytesMut, Buf}; 28 | 29 | 30 | pub const KB: usize = 1024; 31 | pub const MB: usize = 1024*1024; 32 | 33 | pub fn read_bytes_next(src: &mut S, len: usize) -> Result> { 34 | let mut buf = Vec::with_capacity(len); 35 | src.take(len as u64).read_to_end(&mut buf)?; 36 | Ok(match buf.len() { 37 | 0 => None, 38 | l if l == len => Some(buf[..].into()), 39 | _ => { 40 | error!("EOF unexpectedly reached"); 41 | exit(-1); 42 | }, 43 | }) 44 | } 45 | 46 | pub fn pb_read_next(src: &mut S) -> Result> { 47 | Ok(match read_bytes_next(src, size_of::())? { 48 | None => None, 49 | Some(mut size_buf) => { 50 | let size = size_buf.get_u32_le() as usize; 51 | assert!(size < 10*KB, "Would read a protobuf of size >10KB. Something is wrong"); 52 | let buf = read_bytes_next(src, size)?; 53 | let bytes_read = size_of::() + size_buf.len() + buf.clone().unwrap().len(); 54 | Some((T::decode(buf.unwrap())?, bytes_read)) 55 | } 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /src/pipeline/streamer.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | //! This module is responsible for facilitating the transmission of CRIU images. 21 | 22 | use json::object; 23 | 24 | use log::*; 25 | use std::{ 26 | fs::{self, File}, 27 | io::{self, Read, Write}, 28 | io::Error, 29 | os::fd::AsRawFd, 30 | path::Path, 31 | process::exit, 32 | net::TcpStream, 33 | collections::HashMap, 34 | rc::Rc, 35 | }; 36 | use nix::{ 37 | sys::{epoll::EpollFlags, stat::Mode, sendfile::sendfile}, 38 | unistd::{lseek, Whence}, 39 | fcntl::{openat, OFlag} 40 | }; 41 | 42 | use super::{ 43 | criu::StreamListener, 44 | monitor::{Monitor, MonitorType, ImageFile}, 45 | }; 46 | use crate::pipeline::unix_pipe::UnixPipe; 47 | 48 | const BUFFER_SIZE: usize = 32768 * 4; 49 | 50 | /// Fork into a new process 51 | fn fork_process() -> io::Result<()> { 52 | match unsafe { libc::fork() } { 53 | // If fork returns an error 54 | -1 => { 55 | error!("Error forking process: {}", Error::last_os_error()); 56 | exit(1); 57 | } 58 | // If this is the child process, continue 59 | 0 => Ok(()), 60 | // If this is the parent process, exit 61 | _ => exit(0), 62 | } 63 | } 64 | 65 | /// Detach from the controlling terminal 66 | fn detach_terminal() -> io::Result<()> { 67 | if unsafe { libc::setsid() } == -1 { 68 | error!("Error creating new session: {}", Error::last_os_error()); 69 | exit(1); 70 | } 71 | Ok(()) 72 | } 73 | 74 | /// Change working directory to root 75 | fn change_working_dir() -> io::Result<()> { 76 | if let Err(err) = std::env::set_current_dir("/") { 77 | error!("Error changing working directory: {}", err); 78 | exit(1); 79 | } 80 | Ok(()) 81 | } 82 | 83 | /// Close standard file descriptors 84 | fn close_std_file_descriptors() -> io::Result<()> { 85 | let dev_null = fs::File::open(Path::new("/dev/null")).unwrap(); 86 | let dev_null_fd = dev_null.as_raw_fd(); 87 | if unsafe { libc::dup2(dev_null_fd, libc::STDIN_FILENO) } == -1 { 88 | error!("Error reopening stdin: {}", Error::last_os_error()); 89 | exit(1); 90 | } 91 | if unsafe { libc::dup2(dev_null_fd, libc::STDOUT_FILENO) } == -1 { 92 | error!("Error reopening stdout: {}", Error::last_os_error()); 93 | exit(1); 94 | } 95 | if unsafe { libc::dup2(dev_null_fd, libc::STDERR_FILENO) } == -1 { 96 | error!("Error reopening stderr: {}", Error::last_os_error()); 97 | exit(1); 98 | } 99 | Ok(()) 100 | } 101 | 102 | fn send_message(tcp_stream: &mut TcpStream, message: &str) { 103 | info!("Sending message: {message}"); 104 | if let Err(e) = tcp_stream.write_all(message.as_bytes()) { 105 | error!("Failed to send message: {}", e); 106 | } 107 | } 108 | 109 | fn receive_response(tcp_stream: &mut TcpStream, expected_message: &str) { 110 | let mut buffer = [0; BUFFER_SIZE]; 111 | let response = match tcp_stream.read(&mut buffer) { 112 | Ok(size) => { 113 | std::str::from_utf8(&buffer[..size]).map_err(|e| e.to_string()) 114 | }, 115 | Err(e) => Err(e.to_string()), 116 | }; 117 | 118 | match response { 119 | Ok(response_str) => { 120 | info!("Server responded with: {}", response_str); 121 | if response_str != expected_message { 122 | exit(1); 123 | } 124 | } 125 | Err(e) => { 126 | error!("Failed to receive response: {}", e); 127 | } 128 | } 129 | } 130 | 131 | /// Create a Unix socket that accepts a connection with CRIU 132 | /// and run a streamer loop to receive and serialize CRIU images. 133 | fn run_streamer(tcp_stream: &mut TcpStream, images_dir: &Path) -> io::Result<()> { 134 | info!("Starting streamer at {}", images_dir.to_str().unwrap()); 135 | fs::create_dir_all(images_dir)?; 136 | // Create Unix socket to communicate with CRIU 137 | let stream_listener = StreamListener::bind_for_checkpoint(images_dir)?; 138 | // Accept connection with CRIU. 139 | let criu_connection = stream_listener.accept()?; 140 | 141 | info!("Initialize monitor for CRIU images"); 142 | let mut monitor = Monitor::new()?; 143 | monitor.add( 144 | criu_connection.as_raw_fd(), 145 | MonitorType::Criu(criu_connection), 146 | EpollFlags::EPOLLIN 147 | )?; 148 | 149 | // If the path to images directory is symlink to a folder, 150 | // it is likely to be a path to a file descriptor open by 151 | // CRIU under /proc. However, this file descriptor is 152 | // available only while the CRIU process is running. 153 | // To be able to send the checkpoint images to the coordinator 154 | // server after CRIU exist, we open a new file descriptor that 155 | // will persist. 156 | let images_dir = fs::File::open(images_dir)?; 157 | 158 | let mut saved_images: HashMap, File> = HashMap::new(); 159 | let mut image_size: HashMap, i32> = HashMap::new(); 160 | 161 | let epoll_capacity = 8; 162 | while let Some((monitor_key, monitor_obj)) = monitor.poll(epoll_capacity)? { 163 | match monitor_obj { 164 | MonitorType::Criu(criu_connection) => { 165 | match criu_connection.read_next_file_request()? { 166 | Some(filename) => { 167 | 168 | let file_fd = openat(images_dir.as_raw_fd(), filename.as_bytes(), OFlag::O_RDWR | OFlag::O_CREAT, Mode::S_IRUSR | Mode::S_IWUSR)?; 169 | let output_file = fs::File::new(file_fd)?; 170 | info!("Request: {}", filename); 171 | 172 | let pipe = criu_connection.recv_pipe()?; 173 | let image_file = ImageFile::new(filename, pipe, output_file); 174 | monitor.add( 175 | image_file.pipe.as_raw_fd(), 176 | MonitorType::ImageFile(image_file), 177 | EpollFlags::EPOLLIN 178 | )?; 179 | } 180 | None => { 181 | monitor.remove(monitor_key)?; 182 | } 183 | } 184 | }, 185 | MonitorType::ImageFile(img_file) => { 186 | info!("Receiving: {}", img_file.filename); 187 | let (eof, file_size) = img_file.pipe.drain_img_file(&img_file.output_file)?; 188 | 189 | let image_size_entry = image_size.entry(Rc::clone(&img_file.filename)).or_insert_with(|| 0); 190 | *image_size_entry += file_size; 191 | 192 | if !eof { 193 | info!("Saved: {} with size {}", img_file.filename, image_size_entry); 194 | let output_file = img_file.output_file.try_clone()?; 195 | saved_images.insert(Rc::clone(&img_file.filename), output_file); 196 | monitor.remove(monitor_key)?; 197 | } 198 | } 199 | } 200 | } 201 | 202 | info!("Local checkpoint complete"); 203 | send_message(tcp_stream, "SYN"); 204 | 205 | // FIXME: Receive ACK message 206 | receive_response(tcp_stream, "ACK"); 207 | 208 | // FIXME: Transfer local checkpoint to server 209 | for (img_name, img_file) in saved_images.iter() { 210 | let img_metadata = object!{ 211 | img_name: img_name.to_string(), 212 | img_size: image_size[img_name], 213 | }; 214 | 215 | send_message(tcp_stream, &img_metadata.dump()); 216 | 217 | // Go to the beginning of the file. 218 | lseek(img_file.as_raw_fd(), 0, Whence::SeekSet)?; 219 | 220 | // Send file content 221 | let mut offset = 0; 222 | let mut to_write = image_size[img_name] as usize; 223 | while to_write > 0 { 224 | let bytes_sent = sendfile(tcp_stream.as_raw_fd(), img_file.as_raw_fd(), Some(&mut offset), to_write)?; 225 | info!("bytes_sent: {}", bytes_sent); 226 | to_write -= bytes_sent; 227 | } 228 | 229 | // Wait to receive ACK 230 | receive_response(tcp_stream, "IMG_ACK"); 231 | } 232 | 233 | // Send SYN message 234 | send_message(tcp_stream, "SYN"); 235 | 236 | // FIXME: Receive ACK message 237 | 238 | info!("Checkpoint transfer complete"); 239 | 240 | Ok(()) 241 | } 242 | 243 | pub fn streamer(tcp_stream: &mut TcpStream, images_dir: &Path) -> io::Result<()> { 244 | info!("Detaching from main thread"); 245 | fork_process()?; 246 | detach_terminal()?; 247 | change_working_dir()?; 248 | close_std_file_descriptors()?; 249 | 250 | run_streamer(tcp_stream, images_dir) 251 | } -------------------------------------------------------------------------------- /src/pipeline/unix_pipe.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | 21 | use std::{ 22 | fs::{self, File}, 23 | io::{IoSlice, Result}, 24 | os::unix::io::{RawFd, FromRawFd, AsRawFd}, 25 | }; 26 | use nix::{ 27 | fcntl::{fcntl, FcntlArg}, 28 | fcntl::{vmsplice, splice, SpliceFFlags}, 29 | unistd::{sysconf, SysconfVar}, 30 | errno::Errno, 31 | }; 32 | 33 | lazy_static::lazy_static! { 34 | pub(crate) static ref PAGE_SIZE: usize = sysconf(SysconfVar::PAGE_SIZE) 35 | .expect("Failed to determine PAGE_SIZE") 36 | .expect("Failed to determine PAGE_SIZE") as usize; 37 | } 38 | 39 | 40 | pub type UnixFile = fs::File; 41 | 42 | pub trait UnixPipe: Sized { 43 | fn new(fd: RawFd) -> Result; 44 | fn fionread(&self) -> Result; 45 | fn set_capacity(&mut self, capacity: i32) -> nix::Result<()>; 46 | #[allow(dead_code)] 47 | fn increase_capacity(pipes: &mut [Self], max_capacity: i32) -> Result; 48 | fn splice_all(&mut self, dst: i32, len: usize) -> Result<()>; 49 | #[allow(dead_code)] 50 | fn vmsplice_all(&mut self, data: &[u8]) -> Result<()>; 51 | fn drain_img_file(&mut self, output_file: &File) -> Result<(bool, i32)>; 52 | } 53 | 54 | impl UnixPipe for UnixFile { 55 | fn new(fd: RawFd) -> Result { 56 | unsafe { Ok(fs::File::from_raw_fd(fd)) } 57 | } 58 | 59 | fn fionread(&self) -> Result { 60 | nix::ioctl_read_bad!(_fionread, libc::FIONREAD, i32); 61 | 62 | let mut result = 0; 63 | unsafe { _fionread(self.as_raw_fd(), &mut result) }?; 64 | Ok(result) 65 | } 66 | 67 | fn set_capacity(&mut self, capacity: i32) -> nix::Result<()> { 68 | fcntl(self.as_raw_fd(), FcntlArg::F_SETPIPE_SZ(capacity)).map(|_| ()) 69 | } 70 | 71 | fn increase_capacity(pipes: &mut [Self], max_capacity: i32) -> Result { 72 | let mut capacity = max_capacity; 73 | loop { 74 | match pipes.iter_mut().try_for_each(|pipe| pipe.set_capacity(capacity)) { 75 | Err(Errno::EPERM) => { 76 | assert!(capacity > *PAGE_SIZE as i32); 77 | capacity /= 2; 78 | continue; 79 | } 80 | Err(e) => { 81 | return Err(e.into()) 82 | }, 83 | Ok(()) => return Ok(capacity), 84 | }; 85 | } 86 | } 87 | 88 | fn splice_all(&mut self, dst_fd: i32, len: usize) -> Result<()> { 89 | let mut to_write = len; 90 | 91 | while to_write > 0 { 92 | let written = splice(self.as_raw_fd(), None, dst_fd, None, 93 | to_write, SpliceFFlags::SPLICE_F_MORE)?; 94 | to_write -= written; 95 | } 96 | 97 | Ok(()) 98 | } 99 | 100 | fn vmsplice_all(&mut self, data: &[u8]) -> Result<()> { 101 | let mut to_write = data.len(); 102 | let mut offset = 0; 103 | 104 | while to_write > 0 { 105 | let in_iov = IoSlice::new(&data[offset..]); 106 | let written = vmsplice(self.as_raw_fd(), &[in_iov], SpliceFFlags::SPLICE_F_GIFT)?; 107 | assert!(written > 0, "vmsplice() returned 0"); 108 | 109 | to_write -= written; 110 | offset += written; 111 | } 112 | 113 | Ok(()) 114 | } 115 | 116 | fn drain_img_file(&mut self, output_file: &File) -> Result<(bool, i32)> { 117 | let output_fd = output_file.as_raw_fd(); 118 | if output_fd < 0 { 119 | return Ok((true, -1)) 120 | } 121 | 122 | let readable_len = self.fionread()?; 123 | let is_eof = readable_len == 0; 124 | 125 | if readable_len > 0 { 126 | self.splice_all(output_fd, readable_len as usize)?; 127 | } 128 | 129 | Ok((!is_eof, readable_len)) 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/server.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | use std::{ 21 | collections::HashMap, 22 | io::{Read, Write}, 23 | net::{SocketAddr, TcpListener, TcpStream}, 24 | sync::{Arc, Mutex}, 25 | thread, time, str::from_utf8, process::exit, path::Path, fs::{File, create_dir_all}, 26 | }; 27 | 28 | use log::*; 29 | use json::{Null, JsonValue}; 30 | 31 | mod client_status; 32 | use client_status::ClientStatus; 33 | 34 | use crate::constants::*; 35 | 36 | const BUFFER_SIZE: usize = 32768 * 4; 37 | 38 | #[derive(Clone)] 39 | pub struct Server { 40 | } 41 | 42 | /// Start CRIU coordinator server 43 | pub fn run_server(address: &str, port: u16) { 44 | let mut server = Server::new(); 45 | 46 | // Create a shared HashMap to indicate connected clients using an Arc and Mutex 47 | let clients = Arc::new(Mutex::new(HashMap::new())); 48 | let container_dependencies = Arc::new(Mutex::new(HashMap::new())); 49 | 50 | server.run(address, port, clients, container_dependencies); 51 | } 52 | 53 | impl Server { 54 | // Create a new instance of the Server struct. 55 | pub fn new() -> Self { 56 | Self { } 57 | } 58 | 59 | // Start the server and listen for incoming connections. 60 | pub fn run(&mut self, address: &str, port: u16, clients: Arc>>, container_dependencies: Arc>>>) { 61 | 62 | // Create the server socket and start listening for incoming connections. 63 | let server_address = format!("{}:{}", address, port); 64 | let listener_address: SocketAddr = server_address.parse().expect("Invalid server address"); 65 | let listener = TcpListener::bind(listener_address).expect("Failed to bind server to address"); 66 | 67 | info!("[==] Server listening on {}", server_address); 68 | 69 | // Start accepting incoming connections and spawn a new thread to handle each connection. 70 | for stream in listener.incoming() { 71 | match stream { 72 | Ok(stream) => { 73 | info!("[==] New client connected: {}", stream.peer_addr().unwrap()); 74 | 75 | let clients_clone = clients.clone(); 76 | let container_dependencies_clone = container_dependencies.clone(); 77 | let stream_clone = Arc::new(Mutex::new(stream)); 78 | 79 | // Spawn a new thread to handle the client connection. 80 | thread::spawn(move || { 81 | handle_client(stream_clone, &clients_clone, &container_dependencies_clone); 82 | }); 83 | } 84 | Err(e) => { 85 | error!("[!!] Failed to accept a connection: {}", e); 86 | } 87 | } 88 | } 89 | } 90 | } 91 | 92 | // Handle a client connection. 93 | fn handle_client(tcp_stream: Arc>, clients_set: &Arc>>, container_dependencies: &Arc>>>) { 94 | 95 | info!("[>>] Receive client ID, action and dependencies"); 96 | let mut buffer = [0; 32768 * 4]; 97 | let message_data = match tcp_stream.lock().unwrap().read(&mut buffer) { 98 | Ok(size) => json::parse(from_utf8(&buffer[..size]).unwrap().to_string().as_str()).unwrap(), 99 | _ => Null, 100 | }; 101 | 102 | let client_id = message_data["id"].to_string(); 103 | let client_action = &message_data["action"]; 104 | let client_deps = &message_data["dependencies"]; 105 | 106 | info!("[{client_id}] [>>] ID: {client_id}"); 107 | info!("[{client_id}] [>>] ACTION: {client_action}"); 108 | info!("[{client_id}] [>>] DEPENDENCIES: {client_deps}"); 109 | 110 | let mut response_message = MESSAGE_ACK; 111 | 112 | if client_id == "kubescr" && client_action == ACTION_ADD_DEPENDENCIES { 113 | let mut container_dependencies_lock = container_dependencies.lock().unwrap(); 114 | 115 | for (key, values) in client_deps.entries() { 116 | let mut dependencies_vector = Vec::new(); 117 | for dependency in values.members() { 118 | if dependency != key { 119 | dependencies_vector.push(dependency.to_string()); 120 | } 121 | } 122 | 123 | // Print debug information 124 | print!("key: {} => ", key); 125 | for dependency in dependencies_vector.iter() { 126 | print!("{}, ", dependency); 127 | } 128 | println!(); 129 | 130 | container_dependencies_lock.insert(key.to_string(), dependencies_vector); 131 | } 132 | 133 | // Respond with ACK to indicate that all local checkpoints have been successful. 134 | info!("[{client_id}] [<<] Sending {response_message}"); 135 | tcp_stream.lock().unwrap().write_all(response_message.as_bytes()).expect("Failed to send message"); 136 | client_close_connection(&client_id, client_action, tcp_stream, clients_set); 137 | return; 138 | } 139 | 140 | let binding = client_deps.to_string(); 141 | let container_dependencies_lock = container_dependencies.lock().unwrap(); 142 | 143 | let dependencies: Vec<&str> = if binding.is_empty() { 144 | let dependencies_lock = container_dependencies_lock.get(&client_id).unwrap(); 145 | dependencies_lock.iter().map(|x| x.as_str()).collect() 146 | } else { 147 | binding.split(':').collect() 148 | }; 149 | 150 | 151 | if client_action == ACTION_POST_DUMP { 152 | info!("[{client_id}] [==] Wait for all dependencies to create local checkpoint"); 153 | 154 | for dependency in dependencies.iter() { 155 | info!("[{client_id}] [==] Checking local checkpoint: {dependency}"); 156 | let mut clients_lock = clients_set.lock().unwrap(); 157 | 158 | // All dependencies must be present; otherwise we should abort the checkpoint. 159 | if !clients_lock.contains_key(*dependency) { 160 | error!("[!!] Dependency {dependency} is no longer connected"); 161 | response_message = MESSAGE_NOT_CONNECTED; 162 | break; 163 | } 164 | 165 | if let Some(x) = clients_lock.get_mut(*dependency) { 166 | if x.has_local_checkpoint() { 167 | response_message = MESSAGE_CHECKPOINT_EXISTS; 168 | break; 169 | } 170 | x.set_local_checkpoint(); 171 | } 172 | } 173 | 174 | // Respond with ACK to indicate that all local checkpoints have been successful. 175 | info!("[{client_id}] [<<] Sending {response_message}"); 176 | tcp_stream.lock().unwrap().write_all(response_message.as_bytes()).expect("Failed to send message"); 177 | 178 | client_close_connection(&client_id, client_action, tcp_stream, clients_set); 179 | return; 180 | } 181 | 182 | response_message = get_response_message(&client_id, clients_set); 183 | 184 | if response_message != MESSAGE_ACK { 185 | // Send response message in case of an error. 186 | info!("[{client_id}] [<<] Sending {response_message}"); 187 | tcp_stream.lock().unwrap().write_all(response_message.as_bytes()).expect("Failed to send message"); 188 | client_close_connection(&client_id, client_action, tcp_stream, clients_set); 189 | return; 190 | } 191 | 192 | info!("[{client_id}] [==] Wait for all dependencies to connect"); 193 | 194 | for dependency in dependencies.iter() { 195 | info!("[{client_id}] [==] Checking connection of: {dependency}"); 196 | 197 | let mut connected = false; 198 | let mut max_retries = 30; 199 | 200 | loop { 201 | if clients_set.lock().unwrap().contains_key(&dependency.to_string()) { 202 | if let Some(x) = clients_set.lock().unwrap().get_mut(*dependency) { 203 | connected = x.is_connected(); 204 | } 205 | break; 206 | } 207 | 208 | if max_retries > 0 { 209 | max_retries -= 1; 210 | thread::sleep(time::Duration::from_secs(1)); 211 | } else { 212 | error!("Timeout for connection of {dependency}"); 213 | break; 214 | } 215 | } 216 | 217 | if connected { 218 | info!("[{client_id}] [==] {dependency} connected"); 219 | } else { 220 | response_message = MESSAGE_TIMEOUT; 221 | info!("[{client_id}] [==] Timeout for dependency: {dependency}"); 222 | break; 223 | } 224 | } 225 | 226 | 227 | 228 | if response_message != MESSAGE_ACK { 229 | // Send response message in case of an error. 230 | info!("[{client_id}] [<<] Sending {response_message}"); 231 | tcp_stream.lock().unwrap().write_all(response_message.as_bytes()).expect("Failed to send message"); 232 | client_close_connection(&client_id, client_action, tcp_stream, clients_set); 233 | return; 234 | } 235 | 236 | if let Some(x) = clients_set.lock().unwrap().get_mut(&client_id) { 237 | info!("[{client_id}] [==] Client is ready"); 238 | x.set_ready(true); 239 | } 240 | 241 | info!("[{client_id}] [==] Wait for all dependencies to be ready"); 242 | for dependency in dependencies.iter() { 243 | if dependency.is_empty() { 244 | continue 245 | } 246 | info!("[{client_id}] [==] Checking readiness of: {dependency}"); 247 | 248 | let mut ready = false; 249 | let mut max_retries = 30; 250 | 251 | loop { 252 | if clients_set.lock().unwrap().contains_key(*dependency) { 253 | if let Some(x) = clients_set.lock().unwrap().get_mut(*dependency) { 254 | ready = x.is_ready(); 255 | } 256 | } 257 | 258 | if ready { 259 | break; 260 | } 261 | 262 | if max_retries > 0 { 263 | max_retries -= 1; 264 | thread::sleep(time::Duration::from_secs(1)); 265 | } else { 266 | error!("Timeout for readiness of {dependency}"); 267 | break; 268 | } 269 | } 270 | 271 | if ready { 272 | info!("[{client_id}] [==] Dependency {dependency} is ready"); 273 | } else { 274 | response_message = MESSAGE_TIMEOUT; 275 | info!("[{client_id}] [==] Timeout for dependency: {dependency}"); 276 | break; 277 | } 278 | } 279 | 280 | info!("[{client_id}] [<<] Sending {response_message}"); 281 | tcp_stream.lock().unwrap().write_all(response_message.as_bytes()).expect("Failed to send message"); 282 | 283 | if client_action == ACTION_PRE_STREAM { 284 | // 3. Wait to receive SYN indicating that a local checkpoint has been created. 285 | let mut buffer = [0; BUFFER_SIZE]; 286 | let response = match tcp_stream.lock().unwrap().read(&mut buffer) { 287 | Ok(size) => { 288 | std::str::from_utf8(&buffer[..size]).map_err(|e| e.to_string()) 289 | }, 290 | Err(e) => Err(e.to_string()), 291 | }; 292 | 293 | match response { 294 | Ok(response_str) => { 295 | info!("[{client_id}] [==] Client responded with: {}", response_str); 296 | if response_str != MESSAGE_SYN { 297 | exit(1); 298 | } 299 | if let Some(x) = clients_set.lock().unwrap().get_mut(&client_id) { 300 | x.set_local_checkpoint(); 301 | } 302 | } 303 | Err(e) => { 304 | error!("[{client_id}] [!!] Failed to receive response: {}", e); 305 | } 306 | } 307 | } 308 | 309 | if response_message == MESSAGE_ACK && client_action == ACTION_PRE_STREAM { 310 | let images_dir = "/tmp/server-images".to_string(); 311 | create_dir_all(&images_dir).unwrap(); 312 | 313 | // FIXME: Receive image files 314 | loop { 315 | // Receive image name and size. 316 | let mut buffer = [0; 1024]; 317 | let data_size = tcp_stream.lock().unwrap().read(&mut buffer).unwrap(); 318 | 319 | let message_data = match from_utf8(&buffer[..data_size]) { 320 | Ok(data) => data.to_string(), 321 | Err(err) => { 322 | error!("[{client_id}] [!!] Failed to parse message data: {err}"); 323 | break; 324 | }, 325 | }; 326 | 327 | if message_data == MESSAGE_SYN { 328 | break; 329 | } 330 | 331 | let message_data = json::parse(message_data.as_str()).unwrap(); 332 | 333 | if !message_data.has_key("img_name") || !message_data.has_key("img_size") { 334 | break; 335 | } 336 | 337 | let img_name = message_data["img_name"].to_string(); 338 | let img_size: usize = message_data["img_size"].to_string().trim().parse().expect("Image size is not u32"); 339 | 340 | let output_file_path = Path::new(&images_dir).join(img_name.clone()); 341 | let mut output_file = File::create(output_file_path.clone()).unwrap(); 342 | 343 | info!("[{client_id}] [==] Receiving {} with size {} to {:?}", img_name, img_size, output_file_path.to_str()); 344 | 345 | let response_message: &str = MESSAGE_IMG_ACK; 346 | 347 | let mut buffer = [0u8; 1024]; 348 | let mut bytes_read = 0; 349 | 350 | while bytes_read < img_size { 351 | let bytes_to_read = std::cmp::min(buffer.len(), img_size - bytes_read); 352 | let n = tcp_stream.lock().unwrap().read(&mut buffer[..bytes_to_read]).unwrap(); 353 | if n == 0 { 354 | break; 355 | } 356 | output_file.write_all(&buffer[..n]).unwrap(); 357 | bytes_read += n; 358 | } 359 | 360 | info!("[{client_id}] [<<] Sending {response_message}: {img_name}; size: {img_size}"); 361 | tcp_stream.lock().unwrap().write_all(response_message.as_bytes()).expect("Failed to send message"); 362 | } 363 | 364 | // FIXME: 7. Wait to receive the image files from all dependencies. 365 | // FIXME: 8. Send ACK to confirm that the image files from all checkpoints have been received. 366 | } 367 | 368 | // Close TCP connection with client 369 | client_close_connection(&client_id, client_action, tcp_stream, clients_set); 370 | } 371 | 372 | fn get_response_message(client_id: &str, clients_set: &Arc>>) -> &'static str { 373 | let mut clients_lock = clients_set.lock().unwrap(); 374 | 375 | if clients_lock.is_empty() || !clients_lock.contains_key(client_id) { 376 | info!("[{}] [==] Insert client ID", client_id); 377 | clients_lock.insert(client_id.to_string(), ClientStatus::new()); 378 | return MESSAGE_ACK; 379 | } 380 | 381 | MESSAGE_ALREADY_CONNECTED 382 | } 383 | 384 | 385 | fn client_close_connection(client_id: &String, client_action: &JsonValue, tcp_stream: Arc>, clients_set: &Arc>>) { 386 | if let Some(x) = clients_set.lock().unwrap().get_mut(client_id) { 387 | if x.is_connected() { 388 | tcp_stream.lock().unwrap() 389 | .shutdown(std::net::Shutdown::Both) 390 | .expect("Failed to shutdown TCP connection"); 391 | info!("[{client_id}] [==] Client disconnected"); 392 | } 393 | } 394 | 395 | if client_action == ACTION_POST_STREAM || client_action == ACTION_POST_RESTORE { 396 | clients_set.lock().unwrap().remove(client_id); 397 | info!("[{client_id}] [==] Client removed"); 398 | } 399 | } -------------------------------------------------------------------------------- /src/server/client_status.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 University of Oxford. 3 | * Copyright (c) 2023 Red Hat, Inc. 4 | * All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | 21 | pub struct ClientStatus { 22 | connected: bool, 23 | ready: bool, 24 | local_checkpoint: bool, 25 | } 26 | 27 | impl ClientStatus { 28 | pub fn new() -> Self { 29 | Self { 30 | connected: true, 31 | ready: false, 32 | local_checkpoint: false, 33 | } 34 | } 35 | 36 | pub fn is_connected(&self) -> bool { 37 | self.connected 38 | } 39 | 40 | pub fn is_ready(&self) -> bool { 41 | self.ready 42 | } 43 | 44 | pub fn set_ready(&mut self, value: bool) { 45 | self.ready = value; 46 | } 47 | 48 | pub fn set_local_checkpoint(&mut self) { 49 | self.local_checkpoint = true; 50 | } 51 | 52 | pub fn has_local_checkpoint(&self) -> bool { 53 | self.local_checkpoint 54 | } 55 | } -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | all: loop-1 loop-2 loop-3 2 | 3 | loop-1: 4 | gcc loop.c -o $@ 5 | loop-2: 6 | gcc loop.c -o $@ 7 | loop-3: 8 | gcc loop.c -o $@ 9 | 10 | clean: 11 | rm -f loop-1 loop-2 loop-3 12 | .PHONY: clean 13 | -------------------------------------------------------------------------------- /tests/c1/criu-coordinator.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c1", 3 | "address": "127.0.0.1", 4 | "port": "8080", 5 | "log-file": "coordinator.log" 6 | } 7 | -------------------------------------------------------------------------------- /tests/c2/criu-coordinator.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c2", 3 | "address": "127.0.0.1", 4 | "port": "8080", 5 | "log-file": "coordinator.log" 6 | } 7 | -------------------------------------------------------------------------------- /tests/c3/criu-coordinator.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c3", 3 | "address": "127.0.0.1", 4 | "port": "8080", 5 | "log-file": "coordinator.log" 6 | } 7 | -------------------------------------------------------------------------------- /tests/kubescr-add-dependencies.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | 4 | def test_add_dependencies(): 5 | host = "127.0.0.1" 6 | port = 8080 7 | 8 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9 | s.connect((host, port)) 10 | s.sendall(bytes('{' 11 | '"id": "kubescr", ' 12 | '"action": "add_dependencies", ' 13 | '"dependencies": {"c1": ["c2", "c3"], "c2": ["c1", "c3"], "c3": ["c1", "c2"]}' 14 | '}', "utf-8")) 15 | 16 | data = s.recv(1024) 17 | s.close() 18 | print('Received', repr(data)) 19 | 20 | 21 | if __name__ == '__main__': 22 | test_add_dependencies() 23 | -------------------------------------------------------------------------------- /tests/loop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int i = 0; 6 | 7 | while(1) { 8 | printf("%d\n", i++); 9 | sleep(1); 10 | } 11 | return 0; 12 | } 13 | --------------------------------------------------------------------------------