# MVGAL Design Document: Multi-Vendor GPU Aggregation Layer

**Version:** 1.0  
**Date:** 2026-06-02  
**Status:** Implementation Phase

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [System Architecture](#2-system-architecture)
3. [Kernel Module Design](#3-kernel-module-design-mvgal-km)
4. [User-Space Architecture](#4-user-space-architecture)
5. [Device Discovery and Topology](#5-device-discovery-and-topology)
6. [Memory and Data Flow](#6-memory-and-data-flow)
7. [Workload Scheduling](#7-workload-scheduling)
8. [Synchronization](#8-synchronization)
9. [Power Management](#9-power-management)
10. [API Design](#10-api-design)
11. [Security Model](#11-security-model)
12. [Vendor Integration](#12-vendor-integration)
13. [Fallback Behavior](#13-fallback-behavior)
14. [Testing Strategy](#14-testing-strategy)
15. [Packaging and Distribution](#15-packaging-and-distribution)

---

## 1. Executive Summary

MVGAL (Multi-Vendor GPU Aggregation Layer) is a Linux system layer that enables multiple discrete GPUs from different vendors (AMD, NVIDIA, Intel, Moore Threads) to be used as a single logical compute/render resource.

### Design Philosophy

1. **Above-driver layer**: MVGAL does NOT replace vendor drivers; it coordinates them
2. **Standard interfaces**: Uses PCI, DRM, DMA-BUF, sysfs—avoiding vendor-private ABIs
3. **API-level aggregation**: Vulkan ICD, OpenCL ICD, CUDA shim provide explicit multi-GPU
4. **Graceful degradation**: Falls back to single-GPU when cross-vendor scaling unsafe

### Key Components

| Layer | Component | Language |
|-------|-----------|----------|
| 6 | CLI Tools (mvgal-info, mvgal-status, Qt dashboard) | C, Go |
| 5 | API Interception (Vulkan layer, OpenCL ICD, CUDA shim) | C, C++ |
| 4 | Execution Engine (frame sessions, migration plans) | C++ |
| 3 | Runtime Daemon (mvgald) | C++20, Rust |
| 2 | Rust Safety Crates (fence_manager, memory_safety) | Rust |
| 1 | Kernel Module (mvgal.ko) | C (GPL-2.0) |

---

## 2. System Architecture

### High-Level Architecture Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                        Applications                             │
│          (Games, Blender, PyTorch, OpenCL programs)             │
└────────────┬──────────────┬──────────────┬──────────────────────┘
             │ Vulkan        │ OpenCL        │ CUDA / OpenGL
             ▼              ▼              ▼
┌─────────────────────────────────────────────────────────────────┐
│                  Layer 5: API Interception                       │
│  VK_LAYER_MVGAL │ libmvgal_opencl.so │ libmvgal_cuda.so        │
│  libmvgal_gl.so (OpenGL LD_PRELOAD)                             │
└────────────────────────────┬────────────────────────────────────┘
                             │
┌────────────────────────────▼────────────────────────────────────┐
│                  Layer 4: Execution Engine                       │
│  Frame sessions · Migration plans · Steam/Proton profiles        │
└────────────────────────────┬────────────────────────────────────┘
                             │ IPC (Unix socket /run/mvgal/mvgal.sock)
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│               Layer 3: User-Space Runtime Daemon (mvgald)        │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │
│  │Scheduler │ │MemoryMgr │ │PowerMgr  │ │  MetricsCollector  │ │
│  └──────────┘ └──────────┘ └──────────┘ └────────────────────┘ │
└────────────────────────────┬────────────────────────────────────┘
                             │
┌────────────────────────────▼────────────────────────────────────┐
│               Layer 2: Rust Safety Subsystems (safe/)          │
│  fence_manager · memory_safety · capability_model               │
└────────────────────────────┬────────────────────────────────────┘
                             │ ioctl / sysfs
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│               Layer 1: Kernel Abstraction Driver                 │
│                         mvgal.ko (GPL-2.0)                       │
│              /dev/mvgal0  (character device)                     │
└──────┬──────────────┬──────────────┬──────────────┬─────────────┘
       │              │              │              │
       ▼              ▼              ▼              ▼
  amdgpu.ko     nvidia.ko       i915/xe.ko    mtgpu-drv.ko
  (AMD GPU)    (NVIDIA GPU)    (Intel GPU)   (MTT GPU)
```

---

## 3. Kernel Module Design (MVGAL-KM)

### 3.1 Overview

The kernel module (`mvgal.ko`) provides:
- PCI GPU discovery and topology enumeration
- Character device `/dev/mvgal0` for UAPI access
- Sysfs interface at `/sys/class/mvgal/mvgal0/`
- Per-vendor operation dispatch

### 3.2 Device Discovery Flow

```c
static void mvgal_rescan_locked(struct mvgal_main_device *mvdev)
{
    struct pci_dev *pdev = NULL;
    u32 index = 0;

    memset(mvdev->gpus, 0, sizeof(mvdev->gpus));

    while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
        if (!mvgal_is_display_controller(pdev))
            continue;

        if (index >= MVGAL_UAPI_MAX_GPUS)
            break;

        mvgal_fill_gpu_info(pdev, index, &mvdev->gpus[index].info);
        mvdev->gpus[index].present = true;
        mvdev->gpus[index].enabled = true;
        index++;
    }

    mvdev->gpu_count = index;
    mvdev->topology_generation++;
}
```

### 3.3 UAPI Interface

Defined in `include/mvgal/mvgal_uapi.h`:

```c
// Version query
#define MVGAL_IOC_QUERY_VERSION _IOR('M', 0x00, struct mvgal_uapi_version)

// Device enumeration
#define MVGAL_IOC_GET_GPU_COUNT _IOR('M', 0x01, struct mvgal_uapi_gpu_count)
#define MVGAL_IOC_GET_GPU_INFO _IOWR('M', 0x02, struct mvgal_uapi_gpu_query)

// Device control
#define MVGAL_IOC_ENABLE _IO('M', 0x03)
#define MVGAL_IOC_DISABLE _IO('M', 0x04)
#define MVGAL_IOC_RESCAN _IO('M', 0x07)

// Memory management
#define MVGAL_IOC_EXPORT_DMABUF _IOWR('M', 0x10, struct mvgal_uapi_dmabuf_request)
#define MVGAL_IOC_IMPORT_DMABUF _IOWR('M', 0x11, struct mvgal_uapi_dmabuf_request)
```

### 3.4 Kernel Module Parameters

```bash
# Enable verbose debug output
echo 1 > /sys/module/mvgal/parameters/enable_debug

# Check loaded state
ls /dev/mvgal0
ls /sys/class/mvgal/
```

---

## 4. User-Space Architecture

### 4.1 mvgald Daemon

**Main Loop:**

```cpp
int main(int argc, char *argv[])
{
    // Initialize logging
    mvgal_log_init();
    
    // Load configuration
    mvgal_config_load("/etc/mvgal/mvgal.conf");
    
    // Initialize kernel module connection
    mvgal_kernel_init("/dev/mvgal0");
    
    // Initialize subsystems
    mvgal_device_registry_init();
    mvgal_scheduler_init();
    mvgal_memory_manager_init();
    mvgal_power_manager_init();
    mvgal_metrics_collector_init();
    mvgal_ipc_server_init();
    
    // Main loop
    while (running) {
        mvgal_ipc_server_poll();
        mvgal_power_manager_update();
        mvgal_metrics_collector_update();
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}
```

### 4.2 libmvgallib API

**Header:** `include/mvgal/mvgal.h`

```c
#ifdef __cplusplus
extern "C" {
#endif

// Version
void mvgal_get_version_numbers(uint32_t *major, uint32_t *minor, uint32_t *patch);

// Initialization
mvgal_error_t mvgal_init(uint32_t flags);
void mvgal_shutdown(void);

// Device enumeration
mvgal_error_t mvgal_enumerate_gpus(mvgal_gpu_info_t **gpus, uint32_t *count);
mvgal_error_t mvgal_create_logical_device(const uint32_t *gpu_indices, 
                                          uint32_t count,
                                          mvgal_device_t *device);

// Memory management
mvgal_error_t mvgal_allocate_memory(size_t size, uint32_t flags, uint64_t *handle);
mvgal_error_t mvgal_free_memory(uint64_t handle);

// Command submission
mvgal_error_t mvgal_submit_workload(mvgal_device_t device,
                                    const void *commands,
                                    size_t size,
                                    uint64_t *fence);

// Synchronization
mvgal_error_t mvgal_wait_fence(uint64_t fence, uint32_t timeout_ms);

#ifdef __cplusplus
}
#endif
```

---

## 5. Device Discovery and Topology

### 5.1 GPU Information Structure

```c
struct mvgal_gpu_info {
    uint32_t index;
    uint32_t vendor_id;
    uint32_t device_id;
    uint32_t pci_domain;
    uint32_t pci_bus;
    uint32_t pci_slot;
    uint32_t pci_function;
    uint32_t numa_node;
    uint64_t vram_size;
    uint32_t compute_units;
    uint32_t api_flags;  // MVGAL_API_VULKAN | MVGAL_API_CUDA | ...
    char driver_name[32];
    char pci_bdf[16];
};
```

### 5.2 Topology Discovery

1. **PCI Scan**: Enumerate all display-class devices
2. **Driver Check**: Verify vendor driver is bound
3. **NUMA Detection**: Map to NUMA nodes for optimal placement
4. **P2P Detection**: Check PCIe topology for peer-to-peer capability

### 5.3 P2P Matrix Calculation

```c
static void mvgal_build_p2p_matrix(struct mvgal_main_device *mvdev)
{
    for (i = 0; i < mvdev->gpu_count; i++) {
        for (j = 0; j < mvdev->gpu_count; j++) {
            uint32_t idx = i * MVGAL_UAPI_MAX_GPUS + j;
            
            if (i == j) {
                caps->p2p_matrix[idx] = MVGAL_UAPI_P2P_P2P;
                continue;
            }
            
            // Same NUMA node often means P2P capable
            if (mvdev->gpus[i].info.numa_node == mvdev->gpus[j].info.numa_node) {
                caps->p2p_matrix[idx] = MVGAL_UAPI_P2P_P2P;
            } else {
                caps->p2p_matrix[idx] = MVGAL_UAPI_P2P_DMA;
            }
        }
    }
}
```

---

## 6. Memory and Data Flow

### 6.1 Three-Tier Transfer Strategy

```
1. DMA-BUF zero-copy   (preferred — kernel-supported, all vendors)
2. PCIe P2P transfer   (fallback — requires same root complex, kernel 5.10+)
3. Host-RAM staging    (last resort — always works, highest latency)
```

### 6.2 Memory Allocation Flags

```c
#define MVGAL_MEM_HOST_VALID     0x0001
#define MVGAL_MEM_GPU_VALID      0x0002
#define MVGAL_MEM_SHARED         0x0004
#define MVGAL_MEM_DMA_BUF        0x0008
#define MVGAL_MEM_P2P            0x0010
#define MVGAL_MEM_REPLICATED     0x0020
#define MVGAL_MEM_PERSISTENT     0x0040
#define MVGAL_MEM_LAZY_ALLOCATE  0x0080
```

### 6.3 Memory Manager Architecture

```cpp
class MemoryManager {
    struct Allocation {
        uint64_t handle;
        size_t size;
        uint32_t placement;
        std::vector<GPUID> gpu_bindings;
        std::vector<dma_buf*> dmabuf_exports;
    };
    
    std::unordered_map<uint64_t, Allocation> allocations_;
    std::mutex lock_;
    
public:
    uint64_t allocate(size_t size, uint32_t flags);
    int export_dmabuf(uint64_t handle, int gpu_index);
    int import_dmabuf(int dmabuf_fd, uint64_t *gpu_addr);
    int transfer(uint64_t handle, int src_gpu, int dst_gpu);
};
```

---

## 7. Workload Scheduling

### 7.1 Scheduling Strategies

| Strategy | Description | Use Case |
|----------|-------------|----------|
| `round_robin` | Even distribution across GPUs | General compute |
| `afr` | Alternate frame rendering | Gaming (odd/even frames) |
| `sfr` | Split frame rendering | Gaming (tile split) |
| `task` | Route by workload type | Mixed graphics/compute |
| `compute_offload` | Route compute to best GPU | AI/HPC |
| `hybrid` | Adaptive selection | General purpose |
| `single` | Primary GPU only | Fallback/compatibility |

### 7.2 Scheduler Algorithm

```cpp
struct GPUScore {
    uint32_t gpu_index;
    float compute_score;     // Based on FLOPS, VRAM, utilization
    float bandwidth_score;   // PCIe gen/width, P2P capability
    float thermal_score;     // Temperature, power limit
    float policy_score;      // User weights
};

GPUScore score_gpu(const GpuDevice &gpu, const Workload &wl) {
    GPUScore score;
    score.compute_score = gpu.compute_flops() * (1.0f - gpu.utilization()) * gpu.vram_free_ratio();
    score.bandwidth_score = gpu.pcie_bandwidth();
    score.thermal_score = 1.0f - (gpu.temperature() / 80.0f);
    return score;
}
```

### 7.3 Work Distribution

For compute workloads:
```cpp
void Scheduler::distribute_workload(const Workload &wl, 
                                    std::vector<GPUAssignment> &assignments) {
    uint32_t num_gpus = device_registry_->num_gpus();
    size_t chunk_size = wl.size() / num_gpus;
    
    for (uint32_t i = 0; i < num_gpus; i++) {
        assignments.push_back({
            .gpu_index = i,
            .offset = i * chunk_size,
            .size = (i == num_gpus - 1) ? wl.size() - (i * chunk_size) : chunk_size
        });
    }
}
```

---

## 8. Synchronization

### 8.1 Cross-Device Fence Design

```c
struct mvgal_fence {
    uint64_t handle;
    uint32_t gpu_index;
    enum fence_state state;  // PENDING, SUBMITTED, SIGNALED, RESET
    struct dma_fence *dma_fence;  // Underlying DMA fence if available
};
```

### 8.2 Fence Types

1. **CPU Timeline Fences**: Simple mutex+condvar based (fallback)
2. **DMA-BUF Fences**: `sync_file` for kernel-level synchronization
3. **Timeline Semaphores**: Vulkan-compatible timeline sync

### 8.3 Synchronization Flow

```
Application submits to GPU N
  ↓
mvgal_fence_create(gpu_n)
  ↓
mvgal_fence_submit(handle)
  ↓
[Work completes on GPU N]
  ↓
mvgal_fence_signal(handle)
  ↓
Application mvgal_fence_wait(handle)
```

---

## 9. Power Management

### 9.1 Power States

```c
enum mvgal_power_state {
    MVGAL_POWER_STATE_ACTIVE = 0,   // Normal operation
    MVGAL_POWER_STATE_SUSTAINED = 1, // High performance
    MVGAL_POWER_STATE_IDLE = 2,     // Reduced clocks
    MVGAL_POWER_STATE_PARK = 3,     // Low power
    MVGAL_POWER_STATE_OFF = 4,      // Off/switchable
};
```

### 9.2 Power Manager Design

```cpp
class PowerManager {
    struct GPUPowerState {
        enum mvgal_power_state state;
        uint64_t last_activity;
        uint32_t current_clock;
        float power_draw_watts;
    };
    
    void update_gpu_state(int gpu_index) {
        auto &state = gpu_states_[gpu_index];
        uint64_t now = get_timestamp_ms();
        
        if (now - state.last_activity > idle_timeout_ms_) {
            transition_to_state(gpu_index, MVGAL_POWER_STATE_IDLE);
        }
    }
    
    void transition_to_state(int gpu_index, enum mvgal_power_state new_state) {
        // Write to sysfs or vendor interface
        write_power_state(gpu_index, new_state);
    }
};
```

### 9.3 Vendor-Specific Power Interfaces

| Vendor | Interface | Path |
|--------|-----------|------|
| NVIDIA | NVML | `nvmlDeviceSetPowerState()` |
| AMD | DPM | `/sys/.../power_dpm_force_performance_level` |
| Intel | sysfs | `/sys/class/drm/cardN/device/..."` |
| MTT | MUSA | `musa_dev_power_control()` |

---

## 10. API Design

### 10.1 C API (libmvgal)

```c
// Device management
mvgal_error_t mvgal_enumerate_gpus(mvgal_gpu_info_t **info, uint32_t *count);
mvgal_error_t mvgal_create_aggregated_device(const uint32_t *indices, 
                                              uint32_t count,
                                              mvgal_device_t *device);

// Memory management
mvgal_error_t mvgal_alloc_surfaced(size_t size, uint32_t flags, uint64_t *ptr);
mvgal_error_t mvgal_free_surfaced(uint64_t ptr);

// Command submission
mvgal_error_t mvgal_submit_command_buffer(mvgal_device_t device,
                                          const void *data,
                                          size_t size,
                                          uint64_t *fence);

// Synchronization
mvgal_error_t mvgal_wait_fences(uint64_t *fences, uint32_t count, 
                                 uint32_t timeout_ms);
```

### 10.2 C++ API

```cpp
class MV GALLogicalDevice {
public:
    static std::unique_ptr<MV GALLogicalDevice> create(
        const std::vector<int> &gpu_indices);
    
    MV GALContext create_context();
    void submit(MVGALWorkload &workload);
    void wait_idle(uint32_t timeout_ms);
};
```

### 10.3 Python Bindings (via pybind11)

```python
import mvgal

gpus = mvgal.enumerate_gpus()
device = mvgal.create_aggregated_device([0, 1])

# Allocate shared memory
buffer = device.allocate(1024 * 1024, flags=mvgal.MEM_SHARED)
```

---

## 11. Security Model

### 11.1 Privilege Escalation

All privileged operations use `pkexec`:

```bash
# Starting daemon
pkexec systemctl start mvgald

# Loading kernel module  
pkexec insmod mvgal.ko

# Power state changes (via udev rules)
pkexec udevadm control --reload
```

### 11.2 Polkit Policy

File: `/usr/share/polkit-1/actions/org.freedesktop.mvgal.policy`

```xml
<?xml version="1.0" encoding="UTF-8"?>
<policyconfig>
  <action id="org.freedesktop.mvgal.load-module">
    <defaults>
      <allow_any>auth_admin</allow_any>
    </defaults>
  </action>
</policyconfig>
```

### 11.3 IPC Authentication

Unix socket uses `SCM_CREDENTIALS`:

```cpp
// Verify client credentials
struct ucred uartcred;
socklen_t len = sizeof(uartcred);
getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);

// Only allow video group members or root
if (ucred.pid != 0 && !gid_in_group(ucred.pid, "video")) {
    return -EACCES;
}
```

---

## 12. Vendor Integration

### 12.1 Per-Vendor Operations

Each vendor implements `struct mvgal_vendor_ops`:

```c
struct mvgal_vendor_ops {
    // Initialization
    int (*init)(struct mvgal_gpu_device *dev);
    void (*fini)(struct mvgal_gpu_device *dev);
    
    // Command submission
    int (*submit_cs)(struct mvgal_gpu_device *dev, struct mvgal_workload *wl);
    
    // Memory
    int (*alloc_vram)(struct mvgal_gpu_device *dev, size_t size, uint64_t *addr);
    void (*free_vram)(struct mvgal_gpu_device *dev, uint64_t addr);
    
    // Power management
    int (*set_power_state)(struct mvgal_gpu_device *dev, enum mvgal_power_state state);
    
    // DMA-BUF
    struct dma_buf *(*export_dmabuf)(struct mvgal_gpu_device *dev, uint64_t addr, size_t size);
    int (*import_dmabuf)(struct mvgal_gpu_device *dev, struct dma_buf *buf, uint64_t *addr);
    
    // Monitoring
    int (*query_utilization)(struct mvgal_gpu_device *dev, uint32_t *util_percent);
};
```

### 12.2 Vendor Detection Heuristic

```c
static const struct {
    uint16_t vendor_id;
    const char *name;
    const struct mvgal_vendor_ops *ops;
} vendor_table[] = {
    { 0x1002, "AMD", &mvgal_amd_ops },
    { 0x10DE, "NVIDIA", &mvgal_nvidia_ops },
    { 0x8086, "Intel", &mvgal_intel_ops },
    { 0x1ED5, "Moore Threads", &mvgal_mtt_ops },
};
```

---

## 13. Fallback Behavior

### 13.1 When Cross-Vendor Aggregation Fails

1. **API interception fails**: Fall back to single-GPU pass-through
2. **DMA-BUF transfer fails**: Use host staging fallback  
3. **P2P not available**: Route through system memory
4. **Vendor driver missing**: Skip GPU, log warning

### 13.2 Safe Defaults

```c
// Default configuration
struct mvgal_config {
    .default_strategy = MVGAL_STRATEGY_SINGLE_GPU,
    .enable_cross_vendor = false,  // Safety mode
    .power_state_fallback = MVGAL_POWER_STATE_ACTIVE,
    .dmabuf_timeout_ms = 5000,
};
```

---

## 14. Testing Strategy

### 14.1 Test Categories

| Category | Tests | Tools |
|----------|-------|-------|
| Unit | Fence manager, memory safety | `cargo test` |
| Integration | Device enumeration, DMA-BUF | `mvgal-info`, custom tests |
| Performance | Multi-GPU scaling | `mvgal-bench` |
| Compatibility | Single-GPU apps | Steam/Proton games |

### 14.2 CI Pipeline

```yaml
# .github/workflows/ci.yml
jobs:
  build:
    runs-on: [self-hosted, linux, x86_64]
    steps:
      - build kernel module
      - build runtime daemon
      - build userspace library
      - run unit tests
      
  test:
    needs: build
    runs-on: [self-hosted, gpu]
    steps:
      - install MVGAL
      - start mvgald
      - run mvgal-info
      - run cross-vendor compute test
      - report results
```

---

## 15. Packaging and Distribution

### 15.1 Build Dependencies

```bash
# Primary (CMake)
cmake >= 3.16
gcc >= 9 or clang >= 10
libdrm-devel
vulkan-headers
python3

# Optional
Rust >= 1.75 (for safe/ crates)
Go >= 1.20 (for REST server)
```

### 15.2 Package Structure

```
mvgal-0.3.x/
├── mvgal-kernel-0.3.x.deb      # kernel module
├── mvgal-runtime-0.3.x.deb     # mvgald daemon
├── mvgal-dev-0.3.x.deb         # headers, static libs
├── mvgal-0.3.x-1.x86_64.rpm    # RPM package
└── mvgal-0.3.x.tar.gz          # source tarball
```

### 15.3 DKMS Configuration

File: `/usr/src/mvgal-0.3.0/dkms.conf`

```
PACKAGE_NAME="mvgal"
PACKAGE_VERSION="0.3.0"
CLEAN="make -C kernel clean"
MAKE="/usr/bin/make -C kernel"
BUILT_MODULE_NAME[0]="mvgal"
DEST_MODULE_LOCATION[0]="/kernel/drivers/gpu/drm"
REMAKE_INITRD="yes"
AUTOINSTALL="yes"
```

---

## Appendix A: Initialization Sequence

```
1. User runs: pkexec systemctl start mvgald
2. mvgald opens /dev/mvgal0
3. Kernel module scans PCI GPUs
4. mvgald queries GPU info via ioctl
5. mvgald reads sysfs for additional details
6. mvgald initializes vendor-specific state
7. IPC socket created at /run/mvgal/mvgal.sock
8. Ready for client connections
```

## Appendix B: Error Handling

| Error Code | Meaning | Action |
|------------|---------|--------|
| `MVGAL_ERROR_NOT_INITIALIZED` | Library not initialized | Call mvgal_init() |
| `MVGAL_ERROR_INVALID_ARGUMENT` | Bad parameters | Fix caller |
| `MVGAL_ERROR_OUT_OF_MEMORY` | Allocation failed | Reduce workload |
| `MVGAL_ERROR_UNSUPPORTED` | Feature not available | Fall back |
| `MVGAL_ERROR_FENCE_TIMEOUT` | Sync timeout | Retry or fail |

---

## Appendix C: Configuration Reference

File: `/etc/mvgal/mvgal.conf`

```ini
[core]
enabled = true
default_strategy = round_robin
enable_dmabuf = true
enable_p2p = auto

[power]
idle_timeout_ms = 5000
sustained_timeout_ms = 30000
park_timeout_ms = 60000

[scheduler]
weights_gflops = 1.0
weights_bandwidth = 0.8
weights_temperature = 0.5

[logging]
level = info
file = /var/log/mvgal/mvgald.log
max_size_mb = 100
```