diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e877d20 --- /dev/null +++ b/.clang-format @@ -0,0 +1,23 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +ColumnLimit: 120 +AlignEscapedNewlines: Left +AlignAfterOpenBracket: AlwaysBreak +# +# Bind * to the type rather than the name. +PointerAlignment: Left +# +# Put function name on separate line from return type. +AlwaysBreakAfterReturnType: All +# +# Put arguments either all on same line or on separate lines. +BinPackArguments: false +# +# Put function parameters on separate lines. +BinPackParameters: false +# +# Open brace goes on new line only when starting a new struct, enum, or func. +BreakBeforeBraces: Mozilla +# +# Don't sort includes in alphabetical order because Windows headers are odd. +SortIncludes: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4754196 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +repos: +- repo: local + hooks: + - id: clang-format + name: clang-format + entry: ./git-hooks/clang-format-pre-commit.sh + language: system + files: \.(c|cpp|h|hpp)$ + stages: [commit] + - id: check-commit-message + name: Check Commit Message + entry: ./git-hooks/check-commit-message.sh + language: script + stages: [commit-msg] + - id: go-format + name: go-format + entry: ./git-hooks/go-format-pre-commit.sh + language: system + files: \.(go)$ + stages: [commit] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1c5535a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,92 @@ +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to +agree to a Contributor License Agreement (CLA) declaring that you have the right to, +and actually do, grant us the rights to use your contribution. For details, visit +https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need +to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the +instructions provided by the bot. You will only need to do this once across all repositories using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +# Contribution Guidelines + +We welcome contributions from everyone. The following guidelines will help you understand our expectations and streamline the review process. + +## Code Style + +We follow the LLVM coding style for all C/C++ code. Please ensure your code conforms to this style. To automate this process, we use `clang-format`: + +```sh +clang-format -i path/to/your/file.cpp +``` + +It is recommended to install the [Clang-Format extension](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) in Visual Studio Code to format your code automatically. + +For go code, we follow the standard Go formatting guidelines. You can format your code using the `gofmt` tool: + +```sh +gofmt -w path/to/your/file.go +``` + +## Commit Messages + +Please follow these guidelines for commit messages: + +- Use the present tense ("Add feature" not "Added feature"). +- Use the imperative mood ("Move cursor to..." not "Moves cursor to..."). +- Limit the first line to 72 characters or less. +- Reference issues and pull requests liberally. + +## Pre-commit Hooks + +We use pre-commit hooks to ensure code quality and consistency. These hooks will check your code for proper formatting before allowing a commit. + +### Setting up pre-commit hooks for the first time + +1. Install the pre-commit package, for example, in Ubuntu you can run: + ```sh + sudo apt install pre-commit + ``` + +2. Install the pre-commit hooks: + ```sh + pre-commit install --hook-type commit-msg + pre-commit install + ``` + +3. Manually run the hooks on all files (optional but recommended for first-time setup): + ```sh + pre-commit run --all-files + ``` + +4. Auto Format when you commit: + ```sh + export AUTO_FORMAT=1 + ``` + +## Submitting a Pull Request + +1. Ensure your code follows the style guide and passes all tests. +2. Commit your changes with a descriptive commit message. +3. Push your changes to your fork: + ```sh + git push origin your-branch + ``` +4. Create a pull request against the `main` branch of the upstream repository. + +In your pull request, please include: +- A descriptive title and detailed description of the changes. +- Reference any relevant issues or pull requests. + +## Additional Resources + +- [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html) +- [Clang-Format Documentation](https://clang.llvm.org/docs/ClangFormat.html) +- [GitHub Guides: Forking Projects](https://guides.github.com/activities/forking/) +- [Pre-commit Documentation](https://pre-commit.com/) +- [Go Formatting Guidelines](https://golang.org/doc/effective_go.html#formatting) diff --git a/examples/first_example_ipc/Makefile b/examples/first_example_ipc/Makefile index ccaa66e..92e65d1 100644 --- a/examples/first_example_ipc/Makefile +++ b/examples/first_example_ipc/Makefile @@ -6,6 +6,7 @@ else ifeq ($(BUILD_TYPE),AddressSanitizer) DEBUG_CFLAGS = -fsanitize=address endif +CLANG_FORMAT_BIN ?= clang-format AGENT_NAME := example_app PRIMARY_NAME := example_collect_control CODELET_NAME := example_codelet.o @@ -22,7 +23,15 @@ CODELET_CFLAGS := -O2 -target bpf -Wall -DJBPF_DEBUG_ENABLED -D__x86_64__ .PHONY: all clean -all: clean schema codelet agent primary +all: clang-format clean schema codelet agent primary + +clang-format: + @if command -v ${CLANG_FORMAT_BIN} > /dev/null; then \ + echo "Running clang-format check..."; \ + ${CLANG_FORMAT_BIN} --style=file --dry-run --Werror ${AGENT_FILE} ${PRIMARY_FILE} ${CODELET_FILE}; \ + else \ + echo "clang-format not found, skipping..."; \ + fi codelet: ${CODELET_FILE} ${CODELET_CC} ${CODELET_CFLAGS} ${INCLUDES} -c ${CODELET_FILE} -o ${CODELET_NAME} diff --git a/examples/first_example_ipc/example_app.cpp b/examples/first_example_ipc/example_app.cpp index a27db3c..1e6a41e 100644 --- a/examples/first_example_ipc/example_app.cpp +++ b/examples/first_example_ipc/example_app.cpp @@ -20,32 +20,33 @@ DECLARE_JBPF_HOOK( example, struct jbpf_generic_ctx ctx, ctx, - HOOK_PROTO(packet *p, int ctx_id), - HOOK_ASSIGN(ctx.ctx_id = ctx_id; ctx.data = (uint64_t)(void *)p; ctx.data_end = (uint64_t)(void *)(p + 1);)) + HOOK_PROTO(packet* p, int ctx_id), + HOOK_ASSIGN(ctx.ctx_id = ctx_id; ctx.data = (uint64_t)(void*)p; ctx.data_end = (uint64_t)(void*)(p + 1);)) DEFINE_JBPF_HOOK(example) bool done = false; -void sig_handler(int signo) +void +sig_handler(int signo) { done = true; } -int handle_signal() +int +handle_signal() { - if (signal(SIGINT, sig_handler) == SIG_ERR) - { + if (signal(SIGINT, sig_handler) == SIG_ERR) { return 0; } - if (signal(SIGTERM, sig_handler) == SIG_ERR) - { + if (signal(SIGTERM, sig_handler) == SIG_ERR) { return 0; } return -1; } -int main(int argc, char **argv) +int +main(int argc, char** argv) { struct jbpf_config jbpf_config = {0}; @@ -65,15 +66,13 @@ int main(int argc, char **argv) "%s", JBPF_DEFAULT_LCM_SOCKET); - if (!handle_signal()) - { + if (!handle_signal()) { std::cout << "Could not register signal handler" << std::endl; return -1; } // Initialize jbpf - if (jbpf_init(&jbpf_config) < 0) - { + if (jbpf_init(&jbpf_config) < 0) { return -1; } @@ -83,8 +82,7 @@ int main(int argc, char **argv) int i = 0; // Sample application code calling a hook every second - while (!done) - { + while (!done) { packet p; p.seq_no = i; p.value = -i; diff --git a/examples/first_example_ipc/example_codelet.c b/examples/first_example_ipc/example_codelet.c index c609fa2..32a990f 100644 --- a/examples/first_example_ipc/example_codelet.c +++ b/examples/first_example_ipc/example_codelet.c @@ -27,12 +27,12 @@ struct jbpf_load_map_def SEC("maps") counter = { SEC("jbpf_generic") uint64_t -jbpf_main(void *state) +jbpf_main(void* state) { - void *c; + void* c; int cnt; - struct jbpf_generic_ctx *ctx; + struct jbpf_generic_ctx* ctx; packet *p, *p_end; packet echo; manual_ctrl_event resp = {0}; @@ -44,12 +44,12 @@ jbpf_main(void *state) if (!c) return 1; - cnt = *(int *)c; + cnt = *(int*)c; cnt++; - *(uint32_t *)c = cnt; + *(uint32_t*)c = cnt; - p = (packet *)ctx->data; - p_end = (packet *)ctx->data_end; + p = (packet*)ctx->data; + p_end = (packet*)ctx->data_end; if (p + 1 > p_end) return 1; @@ -58,13 +58,11 @@ jbpf_main(void *state) // Copy the data that was passed to the codelet to the outmap ringbuffer // and send them out. - if (jbpf_ringbuf_output(&outmap, &echo, sizeof(echo)) < 0) - { + if (jbpf_ringbuf_output(&outmap, &echo, sizeof(echo)) < 0) { return 1; } - if (jbpf_control_input_receive(&inmap, &resp, sizeof(resp)) == 1) - { + if (jbpf_control_input_receive(&inmap, &resp, sizeof(resp)) == 1) { // Print a debug message. This helper function should NOT be used in production environments, due to // its performance overhead. The helper function will be ignored, if *jbpf* has been built with the // USE_JBPF_PRINTF_HELPER option set to OFF. diff --git a/examples/first_example_ipc/example_collect_control.cpp b/examples/first_example_ipc/example_collect_control.cpp index 06a8422..d087884 100644 --- a/examples/first_example_ipc/example_collect_control.cpp +++ b/examples/first_example_ipc/example_collect_control.cpp @@ -19,36 +19,36 @@ static volatile int done = 0; static void handle_channel_bufs( - struct jbpf_io_channel *io_channel, struct jbpf_io_stream_id *stream_id, void **bufs, int num_bufs, void *ctx) + struct jbpf_io_channel* io_channel, struct jbpf_io_stream_id* stream_id, void** bufs, int num_bufs, void* ctx) { - struct jbpf_io_ctx *io_ctx = static_cast(ctx); + struct jbpf_io_ctx* io_ctx = static_cast(ctx); char serialized[MAX_SERIALIZED_SIZE]; int serialized_size; - if (stream_id && num_bufs > 0) - { + if (stream_id && num_bufs > 0) { // Fetch the data and send to local decoder - for (auto i = 0; i < num_bufs; i++) - { + for (auto i = 0; i < num_bufs; i++) { serialized_size = jbpf_io_channel_pack_msg(io_ctx, bufs[i], serialized, sizeof(serialized)); - if (serialized_size > 0) - { - sendto(sockfd, serialized, serialized_size, - MSG_CONFIRM, (const struct sockaddr *)&servaddr, - sizeof(servaddr)); + if (serialized_size > 0) { + sendto( + sockfd, + serialized, + serialized_size, + MSG_CONFIRM, + (const struct sockaddr*)&servaddr, + sizeof(servaddr)); std::cout << "Message sent, size: " << serialized_size << std::endl; - } - else - { + } else { std::cerr << "Failed to serialize message. Got return code: " << serialized_size << std::endl; } } } } -void *fwd_socket_to_channel_in(void *arg) +void* +fwd_socket_to_channel_in(void* arg) { - struct jbpf_io_ctx *io_ctx = static_cast(arg); + struct jbpf_io_ctx* io_ctx = static_cast(arg); jbpf_io_register_thread(); @@ -58,12 +58,10 @@ void *fwd_socket_to_channel_in(void *arg) // socket create and verification sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == -1) - { + if (sockfd == -1) { printf("socket creation failed...\n"); exit(0); - } - else + } else printf("Socket successfully created..\n"); bzero(&servaddr, sizeof(servaddr)); @@ -71,82 +69,61 @@ void *fwd_socket_to_channel_in(void *arg) servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(20787); - if ((bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) != 0) - { + if ((bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) != 0) { printf("socket bind failed...\n"); exit(0); - } - else + } else printf("Socket successfully binded..\n"); - if ((listen(sockfd, 5)) != 0) - { + if ((listen(sockfd, 5)) != 0) { printf("Listen failed...\n"); exit(0); - } - else + } else printf("Server listening..\n"); len = sizeof(cli); - for (;;) - { - connfd = accept(sockfd, (struct sockaddr *)&cli, &len); - if (connfd < 0) - { + for (;;) { + connfd = accept(sockfd, (struct sockaddr*)&cli, &len); + if (connfd < 0) { printf("server accept failed...\n"); exit(0); - } - else + } else printf("server accept the client...\n"); char buff[MAX_SERIALIZED_SIZE]; int n; struct jbpf_io_stream_id stream_id = {0}; - for (;;) - { + for (;;) { auto n_diff = read(connfd, &buff[n], sizeof(buff) - n); n += n_diff; - if (n_diff == 0) - { + if (n_diff == 0) { printf("Client disconnected\n"); break; - } - else if (n >= 18) - { + } else if (n >= 18) { uint16_t payload_size = buff[1] * 256 + buff[0]; - if (n < payload_size + 2) - { + if (n < payload_size + 2) { continue; - } - else if (n > payload_size + 2) - { - std::cerr << "Unexpected number of bytes in buffer, expected: " << payload_size << ", got: " << n - 2 << std::endl; + } else if (n > payload_size + 2) { + std::cerr << "Unexpected number of bytes in buffer, expected: " << payload_size + << ", got: " << n - 2 << std::endl; break; } - jbpf_channel_buf_ptr deserialized = jbpf_io_channel_unpack_msg(io_ctx, &buff[2], payload_size, &stream_id); - if (deserialized == NULL) - { + jbpf_channel_buf_ptr deserialized = + jbpf_io_channel_unpack_msg(io_ctx, &buff[2], payload_size, &stream_id); + if (deserialized == NULL) { std::cerr << "Failed to deserialize message. Got NULL" << std::endl; - } - else - { + } else { auto io_channel = jbpf_io_find_channel(io_ctx, stream_id, false); - if (io_channel) - { + if (io_channel) { auto ret = jbpf_io_channel_submit_buf(io_channel); - if (ret != 0) - { + if (ret != 0) { std::cerr << "Failed to send message to channel. Got return code: " << ret << std::endl; - } - else - { + } else { std::cout << "Dispatched msg of size: " << payload_size << std::endl; } - } - else - { + } else { std::cerr << "Failed to find io channel. Got NULL" << std::endl; } } @@ -162,19 +139,20 @@ void *fwd_socket_to_channel_in(void *arg) pthread_exit(NULL); } -void handle_ctrl_c(int signum) +void +handle_ctrl_c(int signum) { printf("\nCaught Ctrl+C! Exiting gracefully...\n"); done = 1; } -int main(int argc, char **argv) +int +main(int argc, char** argv) { signal(SIGINT, handle_ctrl_c); // Creating socket file descriptor - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } @@ -187,7 +165,7 @@ int main(int argc, char **argv) servaddr.sin_addr.s_addr = INADDR_ANY; struct jbpf_io_config io_config = {0}; - struct jbpf_io_ctx *io_ctx; + struct jbpf_io_ctx* io_ctx; // Designate the data collection framework as a primary for the IPC io_config.type = JBPF_IO_IPC_PRIMARY; @@ -200,8 +178,7 @@ int main(int argc, char **argv) // Configure the jbpf agent to operate in shared memory mode io_ctx = jbpf_io_init(&io_config); - if (!io_ctx) - { + if (!io_ctx) { return -1; } @@ -211,8 +188,7 @@ int main(int argc, char **argv) // Every thread that sends or receives jbpf data needs to be registered using this call jbpf_io_register_thread(); - while (!done) - { + while (!done) { // Continuously poll IPC output buffers jbpf_io_channel_handle_out_bufs(io_ctx, handle_channel_bufs, io_ctx); sleep(1); diff --git a/examples/first_example_standalone/Makefile b/examples/first_example_standalone/Makefile index e54640b..c1587e1 100644 --- a/examples/first_example_standalone/Makefile +++ b/examples/first_example_standalone/Makefile @@ -6,6 +6,7 @@ else ifeq ($(BUILD_TYPE),AddressSanitizer) DEBUG_CFLAGS = -fsanitize=address endif +CLANG_FORMAT_BIN ?= clang-format AGENT_NAME := example_app CODELET_NAME := example_codelet.o INCLUDES := -I${JBPF_OUT_DIR}/inc -I${NANO_PB} -DJBPF_EXPERIMENTAL_FEATURES=on @@ -19,7 +20,15 @@ CODELET_CFLAGS := -O2 -target bpf -Wall -DJBPF_DEBUG_ENABLED -D__x86_64__ .PHONY: all clean -all: clean schema codelet agent +all: clang-format clean schema codelet agent + +clang-format: + @if command -v ${CLANG_FORMAT_BIN} > /dev/null; then \ + echo "Running clang-format check..."; \ + ${CLANG_FORMAT_BIN} --style=file --dry-run --Werror ${AGENT_FILE} ${CODELET_FILE}; \ + else \ + echo "clang-format not found, skipping..."; \ + fi codelet: ${CODELET_FILE} ${CODELET_CC} ${CODELET_CFLAGS} ${INCLUDES} -c ${CODELET_FILE} -o ${CODELET_NAME} diff --git a/examples/first_example_standalone/example_app.cpp b/examples/first_example_standalone/example_app.cpp index 3793044..3ba6efd 100644 --- a/examples/first_example_standalone/example_app.cpp +++ b/examples/first_example_standalone/example_app.cpp @@ -26,18 +26,17 @@ DECLARE_JBPF_HOOK( example, struct jbpf_generic_ctx ctx, ctx, - HOOK_PROTO(packet *p, int ctx_id), - HOOK_ASSIGN(ctx.ctx_id = ctx_id; ctx.data = (uint64_t)(void *)p; ctx.data_end = (uint64_t)(void *)(p + 1);)) + HOOK_PROTO(packet* p, int ctx_id), + HOOK_ASSIGN(ctx.ctx_id = ctx_id; ctx.data = (uint64_t)(void*)p; ctx.data_end = (uint64_t)(void*)(p + 1);)) DEFINE_JBPF_HOOK(example) // Handler function that is invoked every time that jbpf receives one or more buffers of data from a codelet static void -io_channel_forward_output(jbpf_io_stream_id_t *stream_id, void **bufs, int num_bufs, void *ctx) +io_channel_forward_output(jbpf_io_stream_id_t* stream_id, void** bufs, int num_bufs, void* ctx) { auto io_ctx = jbpf_get_io_ctx(); - if (io_ctx == NULL) - { + if (io_ctx == NULL) { std::cerr << "Failed to get IO context. Got NULL" << std::endl; return; } @@ -45,21 +44,20 @@ io_channel_forward_output(jbpf_io_stream_id_t *stream_id, void **bufs, int num_b char serialized[MAX_SERIALIZED_SIZE]; int serialized_size; - if (stream_id && num_bufs > 0) - { + if (stream_id && num_bufs > 0) { // Fetch the data and print in JSON format - for (auto i = 0; i < num_bufs; i++) - { + for (auto i = 0; i < num_bufs; i++) { serialized_size = jbpf_io_channel_pack_msg(io_ctx, bufs[i], serialized, sizeof(serialized)); - if (serialized_size > 0) - { - sendto(sockfd, serialized, serialized_size, - MSG_CONFIRM, (const struct sockaddr *)&servaddr, - sizeof(servaddr)); + if (serialized_size > 0) { + sendto( + sockfd, + serialized, + serialized_size, + MSG_CONFIRM, + (const struct sockaddr*)&servaddr, + sizeof(servaddr)); std::cout << "Message sent, size: " << serialized_size << std::endl; - } - else - { + } else { std::cerr << "Failed to serialize message. Got return code: " << serialized_size << std::endl; } } @@ -68,32 +66,32 @@ io_channel_forward_output(jbpf_io_stream_id_t *stream_id, void **bufs, int num_b bool done = false; -void sig_handler(int signo) +void +sig_handler(int signo) { done = true; } -int handle_signal() +int +handle_signal() { - if (signal(SIGINT, sig_handler) == SIG_ERR) - { + if (signal(SIGINT, sig_handler) == SIG_ERR) { return 0; } - if (signal(SIGTERM, sig_handler) == SIG_ERR) - { + if (signal(SIGTERM, sig_handler) == SIG_ERR) { return 0; } return -1; } -void *fwd_socket_to_channel_in(void *arg) +void* +fwd_socket_to_channel_in(void* arg) { jbpf_register_thread(); auto io_ctx = jbpf_get_io_ctx(); - if (io_ctx == NULL) - { + if (io_ctx == NULL) { std::cerr << "Failed to get IO context. Got NULL" << std::endl; exit(0); } @@ -103,89 +101,66 @@ void *fwd_socket_to_channel_in(void *arg) struct sockaddr_in servaddr, cli; // socket create and verification sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == -1) - { + if (sockfd == -1) { printf("socket creation failed...\n"); exit(0); - } - else + } else printf("Socket successfully created..\n"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(20787); - if ((bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) != 0) - { + if ((bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) != 0) { printf("socket bind failed...\n"); exit(0); - } - else + } else printf("Socket successfully binded..\n"); - if ((listen(sockfd, 5)) != 0) - { + if ((listen(sockfd, 5)) != 0) { printf("Listen failed...\n"); exit(0); - } - else + } else printf("Server listening..\n"); len = sizeof(cli); - for (;;) - { - connfd = accept(sockfd, (struct sockaddr *)&cli, &len); - if (connfd < 0) - { + for (;;) { + connfd = accept(sockfd, (struct sockaddr*)&cli, &len); + if (connfd < 0) { printf("server accept failed...\n"); exit(0); - } - else + } else printf("server accept the client...\n"); char buff[MAX_SERIALIZED_SIZE]; int n; struct jbpf_io_stream_id stream_id = {0}; - for (;;) - { + for (;;) { auto n_diff = read(connfd, &buff[n], sizeof(buff) - n); n += n_diff; - if (n_diff == 0) - { + if (n_diff == 0) { printf("Client disconnected\n"); break; - } - else if (n >= 18) - { + } else if (n >= 18) { uint16_t payload_size = buff[1] * 256 + buff[0]; - if (n < payload_size + 2) - { + if (n < payload_size + 2) { continue; - } - else if (n > payload_size + 2) - { - std::cerr << "Unexpected number of bytes in buffer, expected: " << payload_size << ", got: " << n - 2 << std::endl; + } else if (n > payload_size + 2) { + std::cerr << "Unexpected number of bytes in buffer, expected: " << payload_size + << ", got: " << n - 2 << std::endl; break; } - jbpf_channel_buf_ptr deserialized = jbpf_io_channel_unpack_msg(io_ctx, &buff[2], payload_size, &stream_id); - if (deserialized == NULL) - { + jbpf_channel_buf_ptr deserialized = + jbpf_io_channel_unpack_msg(io_ctx, &buff[2], payload_size, &stream_id); + if (deserialized == NULL) { std::cerr << "Failed to deserialize message. Got NULL" << std::endl; - } - else - { + } else { auto io_channel = jbpf_io_find_channel(io_ctx, stream_id, false); - if (io_channel) - { + if (io_channel) { auto ret = jbpf_io_channel_submit_buf(io_channel); - if (ret != 0) - { + if (ret != 0) { std::cerr << "Failed to send message to channel. Got return code: " << ret << std::endl; - } - else - { + } else { std::cout << "Dispatched msg of size: " << payload_size << std::endl; } - } - else - { + } else { std::cerr << "Failed to find io channel. Got NULL" << std::endl; } } @@ -199,11 +174,11 @@ void *fwd_socket_to_channel_in(void *arg) pthread_exit(NULL); } -int main(int argc, char **argv) +int +main(int argc, char** argv) { // Creating socket file descriptor - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } @@ -226,15 +201,13 @@ int main(int argc, char **argv) "%s", JBPF_DEFAULT_LCM_SOCKET); - if (!handle_signal()) - { + if (!handle_signal()) { std::cout << "Could not register signal handler" << std::endl; return -1; } // Initialize jbpf - if (jbpf_init(&jbpf_config) < 0) - { + if (jbpf_init(&jbpf_config) < 0) { return -1; } @@ -250,8 +223,7 @@ int main(int argc, char **argv) int i = 0; // Sample application code calling a hook every second - while (!done) - { + while (!done) { packet p; p.seq_no = i; p.value = -i; diff --git a/examples/first_example_standalone/example_codelet.c b/examples/first_example_standalone/example_codelet.c index cfb04f0..c963e10 100644 --- a/examples/first_example_standalone/example_codelet.c +++ b/examples/first_example_standalone/example_codelet.c @@ -27,12 +27,11 @@ struct jbpf_load_map_def SEC("maps") counter = { SEC("jbpf_generic") uint64_t -jbpf_main(void *state) +jbpf_main(void* state) { - - void *c; + void* c; int cnt; - struct jbpf_generic_ctx *ctx; + struct jbpf_generic_ctx* ctx; packet *p, *p_end; packet echo; manual_ctrl_event resp = {0}; @@ -44,12 +43,12 @@ jbpf_main(void *state) if (!c) return 1; - cnt = *(int *)c; + cnt = *(int*)c; cnt++; - *(uint32_t *)c = cnt; + *(uint32_t*)c = cnt; - p = (packet *)ctx->data; - p_end = (packet *)ctx->data_end; + p = (packet*)ctx->data; + p_end = (packet*)ctx->data_end; if (p + 1 > p_end) return 1; @@ -58,13 +57,11 @@ jbpf_main(void *state) // Copy the data that was passed to the codelet to the outmap ringbuffer // and send them out. - if (jbpf_ringbuf_output(&outmap, &echo, sizeof(echo)) < 0) - { + if (jbpf_ringbuf_output(&outmap, &echo, sizeof(echo)) < 0) { return 1; } - if (jbpf_control_input_receive(&inmap, &resp, sizeof(resp)) == 1) - { + if (jbpf_control_input_receive(&inmap, &resp, sizeof(resp)) == 1) { // Print a debug message. This helper function should NOT be used in production environemtns, due to // its performance overhead. The helper function will be ignored, if *jbpf* has been built with the // USE_JBPF_PRINTF_HELPER option set to OFF. diff --git a/git-hooks/check-commit-message.sh b/git-hooks/check-commit-message.sh new file mode 100755 index 0000000..0036c63 --- /dev/null +++ b/git-hooks/check-commit-message.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +echo "Running check-commit-message pre-commit hook..." +# Read the commit message from the argument +commit_message_file="$1" + +# Extract the first line of the commit message +first_line=$(head -n 1 "$commit_message_file") + +# Check the length of the first line +max_length=72 +if [ ${#first_line} -gt $max_length ]; then + echo "Error: The first line of the commit message is too long (more than $max_length characters)." + echo "Please limit the first line to $max_length characters or less." + exit 1 +fi + +# If the first line is within the limit, allow the commit +exit 0 diff --git a/git-hooks/clang-format-pre-commit.sh b/git-hooks/clang-format-pre-commit.sh new file mode 100755 index 0000000..3433ff8 --- /dev/null +++ b/git-hooks/clang-format-pre-commit.sh @@ -0,0 +1,48 @@ +#!/bin/bash +echo "Running clang-format pre-commit hook..." + +# Define the clang-format executable +CLANG_FORMAT_BIN=clang-format + +# Check if clang-format is installed +if ! command -v ${CLANG_FORMAT_BIN} > /dev/null; then + echo "Error: clang-format is not installed." + exit 0 +fi + +# Get a list of all staged files +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(c|cpp|h|hpp)$') + +# Exit if there are no files to format +if [ -z "$STAGED_FILES" ]; then + echo "No C/C++ files staged for commit." + exit 0 +fi + +# If the env AUTO_FORMAT is set to 1, format the files +if [ "$AUTO_FORMAT" = "1" ]; then + echo "Auto-formatting staged files..." + for FILE in ${STAGED_FILES}; do + ${CLANG_FORMAT_BIN} --style=file -i "${FILE}" + done + exit 0 +fi + +# Check the formatting of each staged file +FORMAT_ERRORS=0 +for FILE in ${STAGED_FILES}; do + echo "Checking formatting of: ${FILE} ..." + ${CLANG_FORMAT_BIN} --style=file --dry-run --Werror "${FILE}" + if [ $? -ne 0 ]; then + FORMAT_ERRORS=1 + fi +done + +# If there were formatting errors, fail the commit +if [ $FORMAT_ERRORS -ne 0 ]; then + echo "Error: Some files are not formatted correctly. Please run clang-format and stage the changes." + exit 1 +fi + +# Exit successfully +exit 0 diff --git a/git-hooks/go-format-pre-commit.sh b/git-hooks/go-format-pre-commit.sh new file mode 100755 index 0000000..ff27bcc --- /dev/null +++ b/git-hooks/go-format-pre-commit.sh @@ -0,0 +1,49 @@ +#!/bin/bash +echo "Running gofmt pre-commit hook..." + +# Define the gofmt executable +GOFMT_BIN=gofmt + +# Check if gofmt is installed +if ! command -v ${GOFMT_BIN} > /dev/null; then + echo "Error: gofmt is not installed." + exit 0 +fi + +# Get a list of all staged Go files +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.go$') + +# Exit if there are no files to format +if [ -z "$STAGED_FILES" ]; then + echo "No Go files staged for commit." + exit 0 +fi + +# If the env AUTO_FORMAT is set to 1, format the files +if [ "$AUTO_FORMAT" = "1" ]; then + echo "Auto-formatting staged files..." + for FILE in ${STAGED_FILES}; do + ${GOFMT_BIN} -w "${FILE}" + git add "${FILE}" # Re-add formatted files to staging + done + exit 0 +fi + +# Check the formatting of each staged file +FORMAT_ERRORS=0 +for FILE in ${STAGED_FILES}; do + echo "Checking formatting of: ${FILE} ..." + if ! ${GOFMT_BIN} -l "${FILE}"; then + echo "Error: ${FILE} is not formatted correctly." + FORMAT_ERRORS=1 + fi +done + +# If there were formatting errors, fail the commit +if [ $FORMAT_ERRORS -ne 0 ]; then + echo "Error: Some files are not formatted correctly. Please run gofmt -w and stage the changes." + exit 1 +fi + +# Exit successfully +exit 0 diff --git a/pkg/Makefile b/pkg/Makefile index c383f28..2fe0bd3 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -6,9 +6,9 @@ TEST_WORKDIR ?= $(shell dirname $(shell pwd))/testdata REGENERATE_SNAPSHOT ?= false OUT_DIR ?= . -.PHONY : mod clean lint test testclean +.PHONY : format mod clean lint test testclean -${BINARY_NAME}: clean mod +${BINARY_NAME}: format clean mod CGO_ENABLED=0 go build --trimpath -o ${OUT_DIR}/${BINARY_NAME} main.go mod: @@ -20,6 +20,14 @@ clean: lint: golangci-lint run +format: + @if command -v gofmt > /dev/null; then \ + echo "Running gofmt check..."; \ + gofmt -s -d .; \ + else \ + echo "gofmt not found, skipping..."; \ + fi + test: TEST_WORKDIR=${TEST_WORKDIR} \ NANO_PB=${NANO_PB} \