2025/05/27

使用 netem 和 ifb 進行 ingress 的網路交通模擬

因為 qdisc 只能控制 egress 的流量, 所以將 enp0s25 的 ingress 導向到 ifb0, 再控制 ifb0 的 egress. 來達成 ingress 的網路模擬.

建立新的 ifb 介面

sudo modprobe ifb numifbs=1
    # numifbs=1 表示建立 1 個新的 ifb 介面. 
    # 在建立的前後使用 ifconfig -a 可以檢視新建立的 ifb 介面名稱. 
    # 如果還沒建立任何 ifb 介面, 則新建立的名稱會是 ifb0.

sudo ip link set dev ifb0 up
    # 喚醒 ifb0

將 enp025 的 ingress 流量導向 ifb0

sudo tc qdisc del dev enp0s25 ingress &> /dev/null
    # 清除 enp0s25 的所有 qdisc

sudo tc qdisc add dev enp0s25 handle ffff: ingress
    # 在 enp0s25 建立 ingress 的 qdisc

sudo tc filter add dev enp0s25 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0
    # 將 enp0s25 的所有 ingress 流量重新導向到 ifb0
# sudo tc filter add dev enp0s25 parent ffff: protocol ip u32 match ip protocol 17 0xff action mirred egress redirect dev ifb0
    ## 如果只想要處理 UDP 封包的話, 可以將 match 改成 ip protocol 17 0xff

透過 tc 設定流量控制

sudo tc qdisc del dev ifb0 root &> /dev/null
    # 清除 ifb0 的所有 qdisc

sudo tc qdisc add dev ifb0 root handle 1: netem delay 180ms 30ms loss 5% duplicate 3%
    # 模擬 180ms 延遲, 30ms 抖動, 5% 遺失和 3% 重複

2025/02/18

C Check that the pointer is in range of the memory.

It's hard to say. It's important to protect yourself.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Function to check if a pointer is within the process's mapped memory regions
int is_pointer_in_memory_range(void *ptr) {
    FILE *fp = fopen("/proc/self/maps", "r");
    if (!fp) {
        perror("fopen");
        return 0;
    }

    char line[256];
    uintptr_t addr = (uintptr_t)ptr;
    uintptr_t start, end;
    while (fgets(line, sizeof(line), fp)) {
        if (sscanf(line, "%lx-%lx", &start, &end) == 2) {
            if (addr >= start && addr < end) {
                fclose(fp);
                return 1; // Pointer is in a valid range
            }
        }
    }

    fclose(fp);
    return 0; // Pointer is not in the mapped memory range
}


2024/10/08

LINE Notify 的替代方案

 LINE Notify 割韭菜了.

只好拿稍微麻煩一點的 pushbullet 來用.

產生 token:

登入 pushbullet 主頁.


在帳號的設定頁面建立 token.



請牢記你的 token, 保管好並且不要洩漏.
然後點選你想接收訊息的裝置

URL 最後就是你的裝置 ID.
接下來就是透過 curl 傳遞我們想要傳送的訊息:
curl -X POST https://api.pushbullet.com/v2/pushes \
-H "Authorization: Bearer ${你的token}>" \
-H "Content-Type: application/json" \
-d "{\"type\": \"note\", \"title\": \"${訊息抬頭}\", \"body\": \"${訊息內容}\", \"device_iden\": \"${你的裝置ID}\"}"



2024/04/18

[C] chek cpu endian

1
2
3
4
5
6
7
8
#include <stdint.h>

static uint8_t is_little_endian(void)
{
    uint16_t value = 0x0001;
    uint8_t *byte_ptr = (uint8_t *)&value;
    return (*byte_ptr == 0x01); // If the system is little endian, the least significant byte is 0x01.
}


2024/04/09

[C] Create a folder even if the parent folder does not exist.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static int my_dirname(char *path) {
    char *p = strrchr(path, '/');
    if (p == NULL || p == path) {
        return -1;
    }
    *p = '\0';
    return 0;
}

static int my_mkdir(char *path) {
    struct  stat    st;
    char            p[128];
    char            l[128];

    mkdir(path, 0775);
    while ((stat(path, &st) != 0)) {
        memset(p, 0, 128);
        memcpy(p, path, strlen(path));
        if (0 != my_dirname(p)) {
            return (-1);
        }
        while ((stat(p, &st) != 0)) {
            memset(l, 0, 128);
            memcpy(l, p, strlen(p));  // save the last not exist parent path.
            if (0 != my_dirname(p)) {
                return (-1);
            }
        }
        mkdir(l, 0775);
        if (stat(l, &st) != 0) {
            return (-1);
        }
        mkdir(path, 0775);
    }
    return (0);
}