Category Archives: Programming

Ampere Altra Mt. Jade OpenBMC build guide on ARM64 platform

Ampere announce Altra CPU, it’s a 80 cores ARM64v8 CPU for cloud native workloads. Altra Max CPU is 128 cores. Follow the CPU, Ampere also has a CRB (customer reference board) named Mt. Jade, and Ampere also open source OpenBMC and EDKII source code for Mt. Jade platform.

This article is personal note, all information can be found from internet. And open source project keeps going, it might be some minor differences when you find this article.

Read more »

Python 取得 PM2.5 和天氣資訊

最近終於將很久之前就說要架的室內 PM 2.5 偵測弄起來,上一版是用 Cacti 做的,但是有點過時了,這一版是用 Grafana + Prometheus 做的,看起來就漂亮多了

不過架上去之後的問題是,想比較數值,但是又不想再組一套系統出來,畢竟感測器也是成本,不如就用現成的氣象和環保局的數據吧,反正都只是參考用的,看個大概就好了

Read more »

PyCharm 內執行 QT Designer 和 ui 轉 py

看了幾篇文章都有些疏漏,並沒有辦法真正的做到直接在程式內直接呼叫 External tool 做到這兩件事

都會有一些錯誤訊息

Read more »

RSS Toeplitz Hash Calculation C Code

Toeplitz RSS(Receive Side Scaling) sample code 如下, 從 ODP Code 借來的

因為是測試用 code, 所以也不要太在乎語法什麼的
輸出可以正確的跑出 microsoft 網站的 sample

$ ./a.out
sip: 187.149.9.66   dip:80.100.142.161 sport:1766   dport:2794   hash: 51ccc178

目前的 code 會計算 4 個 IP
像是這樣

$ ./a.out
sip: 192.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: 8c2cb4f
sip: 193.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: ef1317e8
sip: 194.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: 5f061160
sip: 195.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: 2324d4ee

連檔名都叫 a.out 我真懶

#include <stdint.h>
#include <stdio.h>
#include <endian.h>
#include <string.h>
#include <arpa/inet.h>

/** rss data type */
typedef union {
uint8_t u8[40];
uint32_t u32[10];
} rss_key;

/** IPv4 tuple
*
*/
typedef struct thash_ipv4_tuple {
uint32_t src_addr;
uint32_t dst_addr;
union {
struct {
uint16_t sport;
uint16_t dport;
};
uint32_t sctp_tag;
};
} thash_ipv4_tuple_t;

/** Thash tuple union */
typedef union {
thash_ipv4_tuple_t v4;
//thash_ipv6_tuple_t v6;
} thash_tuple_t;
static const rss_key default_rss = {
.u8 = {
0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
}
};

static inline
uint32_t thash_softrss(uint32_t *tuple, uint8_t len,
const rss_key key)
{
uint32_t i, j, ret = 0;

for (j = 0; j < len; j++) {
for (i = 0; i < 32; i++) {
if (tuple[j] & (1 << (31 – i))) {
ret ^= htobe32(((const uint32_t *)
key.u32)[j]) << i | (uint32_t)((uint64_t) (htobe32(((const uint32_t *)key.u32) [j + 1])) >> (32 – i));
}
}
}

return ret;
}
int main(int argc,char *argv[]){
thash_tuple_t tuple;
uint32_t hash;
uint32_t tuple_len;
struct in_addr ip_addr_s,ip_addr_d;
char str_s[15], str_d[15];

#if 0
tuple.v4.src_addr = (uint32_t) inet_addr(“66.9.149.187”);
tuple.v4.dst_addr = (uint32_t) inet_addr(“161.142.100.80”);
ip_addr_s.s_addr = tuple.v4.src_addr;
ip_addr_d.s_addr = tuple.v4.dst_addr;
tuple_len += 2;
tuple.v4.sport = htobe16(2794);
tuple.v4.dport = htobe16(1766);
tuple_len += 1;
#endif

for(int i=0;i<4;i++){
tuple_len = 0;
hash = 0;

tuple.v4.src_addr = (uint32_t) inet_addr(“192.168.1.100”);
tuple.v4.src_addr = be32toh(tuple.v4.src_addr);
tuple.v4.src_addr=tuple.v4.src_addr+i*4;
tuple.v4.src_addr = htobe32(tuple.v4.src_addr);
tuple.v4.dst_addr = (uint32_t) inet_addr(“10.0.0.100”);
ip_addr_s.s_addr = tuple.v4.src_addr;
ip_addr_d.s_addr = tuple.v4.dst_addr;
tuple_len += 2;
tuple.v4.sport = htobe16(1000);
tuple.v4.dport = htobe16(1000);
tuple_len += 1;

if (tuple_len){
tuple.v4.src_addr = be32toh(tuple.v4.src_addr);
tuple.v4.dst_addr = be32toh(tuple.v4.dst_addr);
tuple.v4.sctp_tag = be32toh(tuple.v4.sctp_tag);
hash = thash_softrss((uint32_t *)&tuple,
tuple_len, default_rss);
}

ip_addr_s.s_addr = htobe32(tuple.v4.src_addr);
ip_addr_d.s_addr = htobe32(tuple.v4.dst_addr);
strcpy(str_s,inet_ntoa(ip_addr_s));
strcpy(str_d,inet_ntoa(ip_addr_d));
printf(“sip: %-14s dip:%-14s sport:%-6d dport:%-6d hash: %x \n”,
str_s,str_d,
tuple.v4.sport,
tuple.v4.dport, hash);

}

return hash;
}

附帶一提, 如果在 Linux 下要修改 hash key . 可以用 ethtool 這個指令, ex:

$ ethtool -X enp5s0f4 hkey 6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a

ref.
Verifying the RSS Hash Calculation : 可以比對計算出是不是正確
Symmetric RSS : 有趣的文章, 提到原來的功能沒有辦法有效的 hash , 將所有的 key 都改 0x6d5a 就可以
Scalable TCP Session Monitoring with Symmetric Receive-side Scaling
Scaling in the Linux Networking Stack
odp_classification.c

Ubuntu 16.04 error: undefined reference to `create_module’

Ubuntu 16.04 error: undefined reference to `create_module’

Building module-init-tools-3.2 in Ubuntu16.04 failed:
lsmod.o: In function `try_old_version':
./module-init-tools-3.2/backwards_compat.c:56: undefined reference to `create_module'

這一篇Ubuntu 16.04 error: undefined reference to `create_module’對我沒有用, 但是解法是對的, 這時就要用粗暴的方式, 直接改 backwards_compat.c
加上

#define CONFIG_NO_BACKWARDS_COMPAT

暫時解決問題

SIGALARM / timer_create 造成 CPU sys 100% 的問題

最近遇到一個怪問題, 某一隻程式跑起來的時候, 有一定的機率 sys 佔有率是 100%

Cpu0  :  0.0%us,100.0%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

Read more »

git subversion

git 真是很難操控的東西. 好像寫了很多次, 但是都忘記怎麼用..
Read more »

[GIT] 將現有的目錄改成 bare 並且修改 remote server

git 如果從另一個目錄 clone 出來, 兩邊都有 source code, 是不能直接 master push 到 master 的.
會出現錯誤訊息
[TEXT]
git push error ‘[remote rejected] master -> master (branch is currently checked out)’
[/TEXT]

這時可以產生另一個 bare 目錄, 然後到 git 目錄內下指令, 將該目錄變成 bare
[BASH]
# cp -a (path_to_source_dir) (path_to_bare_dir)
# cd (path_to_bare_dir)
# git config –bool core.bare true
# rm (all source code)
# mv .git/* .
# rmdir .git
[/BASH]

這樣就可以了.

原來的目錄可以修改 remote url 的方式指到新的目錄
[BASH]
# cd (path_to_source_dir)
# git remote set-url origin //(path_to_bare_dir)
[/BASH]

這時有 source code 的目錄還是用 git push/pull 更新 source code.
如果是 bare 的話就是 git push, git fetch/merge 更新 source code.

Ref web.
http://stackoverflow.com/questions/2816369/git-push-error-remote-rejected-master-master-branch-is-currently-checked
http://stackoverflow.com/questions/2432764/how-to-change-a-remote-repository-uri-using-git

KEIL uVersion Link Error

Compile 時最後碰到這個問題.

這是在 C 中去 Link C++ 的 Code 產生的.

[TEXT]
linking…
.\Obj\Memory.axf: Error: L6218E: Undefined symbol __aeabi_unwind_cpp_pr0 (referred from array_new.o).
.\Obj\Memory.axf: Error: L6218E: Undefined symbol __rt_new_handler_addr (referred from new.o).
.\Obj\Memory.axf: Error: L6218E: Undefined symbol abort (referred from arm_exceptions_terminate.o).
.\Obj\Memory.axf: Error: L6218E: Undefined symbol __rt_eh_globals_addr (referred from arm_exceptions_globs.o).
Target not created
[/TEXT]

解決方法就是 Option -> Target -> Use MicroLib 關掉.

如果要引入一些標準的 C Library, 也不能使用 MicroLib .
像是要初始化 Heap , _init_alloc 也是要關掉 MicroLib 的支援.

註:
當使用 malloc 時, 會去 heap 取得一塊 memory 給程式使用, 但是
Keil 本身並沒有 heap 的管理機制, 要指定一塊 memory 給 heap 用.
這時就要先 initial heap, 要使用 _init_alloc 這個 function 才可以 allocate .

Ref.
MicroLib

git 筆記: 如何將現有的 Tree 推到 remote

我本來在開發 AMP 的程式, 所以從 source code clone 了一個新的開發目錄, 稱 A, 再從 A clone 一個新的開發目錄, 稱 B.
這時在 B 的目錄下, 沒有辦法直接 push 回 A , 因為 A 內有 source code , 所以只好再開一個新的空 git, 往上推.

假設主要的 tracking branch name 是 major. (一般用 origin or master, btw, 我是從別的地方再 clone 過來的, 所以不用此名)
創立一個新的空 git 目錄.
[BASH]
$ cd /data/prj/AMP/core-data
$ git init –bare
[/BASH]

在 source code A 下, 建立一個新的 remote
[BASH]
$ git remote add test /data/prj/AMP/core-data
$ git push test major
[/BASH]

在 source code B 下, 加入一個新的 remote, 用 git reset –hard 是清除所有的改變, 以便 pull
[BASH]
$ git diff
$ git reset –hard
$ git remote add test /data/prj/AMP/core-data/bare/
$ git pull test major
[/BASH]

* 若是遇到這種情形, 可以檢查是不是這個檔在是 untracked, 可以用 $ git status 查看. 如果是 untracked, 可以刪除.
[BASH]
$ git pull test major
From /data/prj/AMP/core-data/bare
* branch major -> FETCH_HEAD
error: Untracked working tree file ‘kernels/linux-2.6.35.12/arch/arm/kernel/real-amp.c’ would be overwritten by merge. Aborting
[/BASH]

git 功能太多 :-/