Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add-skeleton-kernel-module #50

Merged
merged 10 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Kernel Module Development",
"dockerFile": "Dockerfile.devcontainer",
"workspaceFolder": "/workspace",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.makefile-tools",
"ms-azuretools.vscode-docker",
"ms-vscode.cmake-tools"
]
}
},
"remoteUser": "root"
}

153 changes: 153 additions & 0 deletions .github/workflows/test-kernel-module.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: Test Kernel Module
on: workflow_dispatch # Manual trigger for testing

permissions:
id-token: write # Required for requesting the JWT

jobs:
start-runner:
name: Start EC2 runner
runs-on: ubuntu-latest
outputs:
label: ${{ steps.start-ec2-runner.outputs.label }}
ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }}
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ secrets.AWS_REGION }}
role-session-name: github-runner-session

- name: Start EC2 runner
id: start-ec2-runner
uses: machulav/[email protected]
with:
mode: start
github-token: ${{ secrets.REPO_ADMIN_TOKEN }}
ec2-image-id: ami-0884d2865dbe9de4b # Ubuntu 22.04 LTS in us-east-2
ec2-instance-type: t3.large
market-type: spot
subnet-id: ${{ secrets.AWS_SUBNET_ID }}
security-group-id: ${{ secrets.AWS_SECURITY_GROUP_ID }}
aws-resource-tags: >
[
{"Key": "Name", "Value": "github-runner"},
{"Key": "Repository", "Value": "${{ github.repository }}"},
{"Key": "Workflow", "Value": "${{ github.workflow }}"},
{"Key": "RunId", "Value": "${{ github.run_id }}"},
{"Key": "RunNumber", "Value": "${{ github.run_number }}"},
{"Key": "SHA", "Value": "${{ github.sha }}"},
{"Key": "Branch", "Value": "${{ github.ref_name }}"},
{"Key": "Actor", "Value": "${{ github.actor }}"}
]

test-module:
needs: start-runner
runs-on: ${{ needs.start-runner.outputs.label }}
timeout-minutes: 10 # Add timeout in case system hangs
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Disable IPv6
run: |
# Disable IPv6 via sysctl
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1

# Force apt to use IPv4
echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4

- name: Configure apt to use HTTPS
run: |
# Update all archive URLs to use HTTPS
sudo sed -i 's/http:/https:/g' /etc/apt/sources.list

# Install apt-transport-https (might fail initially, hence the || true)
sudo apt-get update || true
sudo apt-get install -y apt-transport-https ca-certificates

# Update again with HTTPS now configured
sudo apt-get update

- name: Install build dependencies
run: |
# Install base dependencies
sudo apt-get install -y build-essential linux-headers-$(uname -r)

- name: Build kernel module
working-directory: module
run: |
# Try to compile and capture the warning message
make 2>&1 | tee compile_output.txt || true

# Extract gcc version from the warning message
KERNEL_GCC_VERSION=$(grep "The kernel was built by:" compile_output.txt | grep -oP 'gcc-\K\d+' || echo "")
echo "Detected kernel compiler version: ${KERNEL_GCC_VERSION}"

# Install specific gcc version if detected
if [ ! -z "$KERNEL_GCC_VERSION" ]; then
echo "Installing gcc-${KERNEL_GCC_VERSION}"
sudo apt-get install -y gcc-${KERNEL_GCC_VERSION}

# Configure as default gcc
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${KERNEL_GCC_VERSION} 100
sudo update-alternatives --set gcc /usr/bin/gcc-${KERNEL_GCC_VERSION}
else
echo "Warning: Could not detect kernel compiler version"
fi

# Verify gcc version
gcc --version

# Now try the actual build
make

ls -l build/memory_collector.ko

- name: Load and test module
working-directory: module
run: |
# Load module
sudo insmod build/memory_collector.ko

# Verify module is loaded
lsmod | grep memory_collector

# Check kernel logs for module initialization
dmesg | grep "Memory Collector" || true

# Unload module
sudo rmmod memory_collector

# Verify module unloaded successfully
if lsmod | grep -q memory_collector; then
echo "Error: Module still loaded"
exit 1
fi

# Check kernel logs for cleanup message
dmesg | grep "Memory Collector" || true

stop-runner:
name: Stop EC2 runner
needs: [start-runner, test-module]
runs-on: ubuntu-latest
if: always() # Run even if previous jobs fail
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ secrets.AWS_REGION }}
role-session-name: github-runner-session

- name: Stop EC2 runner
uses: machulav/[email protected]
with:
mode: stop
github-token: ${{ secrets.REPO_ADMIN_TOKEN }}
label: ${{ needs.start-runner.outputs.label }}
ec2-instance-id: ${{ needs.start-runner.outputs.ec2-instance-id }}
21 changes: 21 additions & 0 deletions Dockerfile.devcontainer
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM ubuntu:latest

# Avoid prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive

# Update and install essential build tools and kernel headers
RUN apt-get update && apt-get install -y \
build-essential \
linux-headers-6.8.0-52-generic \
linux-image-6.8.0-52-generic \
git \
vim \
curl \
kmod \
&& rm -rf /var/lib/apt/lists/*

# Set the working directory
WORKDIR /workspace

# Keep container running
CMD ["sleep", "infinity"]
33 changes: 33 additions & 0 deletions module/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
obj-m += memory_collector.o

# Check if KVERSION is provided on command line
ifdef KVERSION
# Use provided version
KERNEL_VERSION := $(KVERSION)
else
# Check if we're in the dev container by looking for a specific file
# that would only exist in the container (like our Dockerfile)
ifneq (,$(wildcard /.dockerenv))
# In container - use the version we installed
KERNEL_VERSION := 6.8.0-52-generic
else
# Not in container - use current kernel
KERNEL_VERSION := $(shell uname -r)
endif
endif

KDIR := /lib/modules/$(KERNEL_VERSION)/build
BUILD_DIR := $(PWD)/build

all: | $(BUILD_DIR)
@echo "Building for kernel version: $(KERNEL_VERSION)"
$(MAKE) -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) modules

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

clean:
$(MAKE) -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) clean
rm -rf $(BUILD_DIR)

.PHONY: all clean
78 changes: 78 additions & 0 deletions module/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Memory Collector Kernel Module

This kernel module provides low-level memory subsystem monitoring capabilities for the Memory Collector project.

## Building the Module

### Prerequisites

- Linux kernel headers for your running kernel
- Build tools (gcc, make)

On Ubuntu/Debian:
```bash
sudo apt-get install linux-headers-$(uname -r) build-essential
```

On RHEL/Fedora:
```bash
sudo dnf install kernel-devel kernel-headers gcc make
```

### Manual Build

To build the module directly:

```bash
make
```

This will create `memory_collector.ko` which can be loaded with:

```bash
sudo insmod memory_collector.ko
```

To unload:
```bash
sudo rmmod memory_collector
```

### DKMS Installation

For automatic rebuilding when the kernel updates:

1. Install DKMS:
```bash
# Ubuntu/Debian
sudo apt-get install dkms

# RHEL/Fedora
sudo dnf install dkms
```

2. Install the module through DKMS:
```bash
sudo dkms add .
sudo dkms install memory-collector/1.0
```

The module will now automatically rebuild when your kernel is updated.

To uninstall:
```bash
sudo dkms remove memory-collector/1.0 --all
```

## Verification

After loading the module, verify it's running:

```bash
lsmod | grep memory_collector
```

Check kernel logs for module status:
```bash
dmesg | tail
```
7 changes: 7 additions & 0 deletions module/dkms.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
PACKAGE_NAME="memory-collector"
PACKAGE_VERSION="1.0"
BUILT_MODULE_NAME[0]="memory_collector"
DEST_MODULE_LOCATION[0]="/kernel/drivers/misc"
AUTOINSTALL="yes"
MAKE[0]="make"
CLEAN="make clean"
22 changes: 22 additions & 0 deletions module/memory_collector.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Memory Collector Project");
MODULE_DESCRIPTION("Memory subsystem monitoring for Kubernetes");
MODULE_VERSION("1.0");

static int __init memory_collector_init(void)
{
printk(KERN_INFO "Memory Collector: module loaded\n");
return 0;
}

static void __exit memory_collector_exit(void)
{
printk(KERN_INFO "Memory Collector: module unloaded\n");
}

module_init(memory_collector_init);
module_exit(memory_collector_exit);
Loading