靈修分享:亞略巴古的演講

亞略巴古的演說是使徒行傳一篇非常著名的講道。基督徒往往用這段經文來說明上帝的屬性,同時也會參考這段經文作為和外邦人互動的一個參考方式。最近因為團契查經查到這一段,重新思想後看到了以前沒有考慮過的面向,在這邊記錄一下。

徒17:16-34保羅在雅典等候他們的時候,看見滿城都是偶像,就心裏着急;於是在會堂裏與猶太人和虔敬的人,並每日在市上所遇見的人,辯論。還有伊壁鳩魯和斯多亞兩門的學士,與他爭論。有的說:「這胡言亂語的要說甚麼?」有的說:「他似乎是傳說外邦鬼神的。」這話是因保羅傳講耶穌與復活的道。他們就把他帶到亞略‧巴古,說:「你所講的這新道,我們也可以知道嗎?因為你有些奇怪的事傳到我們耳中,我們願意知道這些事是甚麼意思。」(雅典人和住在那裏的客人都不顧別的事,只將新聞說說聽聽。)
保羅站在亞略‧巴古當中,說:「眾位雅典人哪,我看你們凡事很敬畏鬼神。我遊行的時候,觀看你們所敬拜的,遇見一座壇,上面寫着『未識之神』。你們所不認識而敬拜的,我現在告訴你們。創造宇宙和其中萬物的神,既是天地的主,就不住人手所造的殿,也不用人手服事,好像缺少甚麼;自己倒將生命、氣息、萬物,賜給萬人。他從一本本:有古卷是血脈造出萬族的人,住在全地上,並且預先定準他們的年限和所住的疆界,要叫他們尋求神,或者可以揣摩而得,其實他離我們各人不遠;我們生活、動作、存留,都在乎他。就如你們作詩的,有人說:『我們也是他所生的。』我們既是神所生的,就不當以為神的神性像人用手藝、心思所雕刻的金、銀、石。世人蒙昧無知的時候,神並不監察,如今卻吩咐各處的人都要悔改。因為他已經定了日子,要藉着他所設立的人按公義審判天下,並且叫他從死裏復活,給萬人作可信的憑據。」
眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」於是保羅從他們當中出去了。 但有幾個人貼近他,信了主,其中有亞略‧巴古的官丟尼修,並一個婦人,名叫大馬哩,還有別人一同信從。

對基督徒來說,保羅這篇講道講的真好,不但講出了上帝的超越性(像是不住人手所造的殿、也不是金銀石的彫刻),也帶出了耶穌基督復活的大能。但最近我才注意到眾人的反應:「眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」」不曉得你看到這一段有什麼感想?可能我是玻璃心吧,如果我是保羅,我大概會非常非常的難過,看起來似乎沒有人理會這個福音、這篇講道。這篇被基督…

Netlink Performance 測試

這篇文章的由來在於客戶說的一句話:「Netlink 的效能似乎不太好」客戶口中的不太好指的是 Throughput 只有 10Mbps。本來嘛,我想之後才處理這件事情,但結果我的一個同事 York 抱著追根究底的精神進行了下面的實驗。首先,他用一支 user space 的程式來產生封包到 kernel space 的模組,模組收到以後就將封包打回 user space。簡單來講究是一個 echo 的行為。下面會列出這兩隻程式:

實驗平台:某平台
Kernel 版本:3.10

User Space:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define NETLINK_TEST 18
//#define MAX_PAYLOAD 1024
//#define MAX_PAYLOAD 2048
//#define MAX_PAYLOAD 4096
#define MAX_PAYLOAD 8192
#define MESSAGE_COUNT 1048576

struct sockaddr_nl src_addr, dest_addr;
struct msghdr msg;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;

void main()
{
    int _i = 0;

    time_t startTime = 0;
    time_t endTime = 0;

    sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);

    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.nl_family = AF_NETLINK;
    src_addr.nl_pid = getpid();
    src_addr.nl_groups = 0;

    bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));

    memset(&dest_addr, 0, sizeof(dest_addr));
    dest_addr.nl_family = AF_NETLINK;
    dest_addr.nl_pid = 0;    // send to kernel
    dest_addr.nl_groups = 0;

    startTime = time(NULL);
    printf("start time: %s\n", ctime(&startTime));
    for (_i = 0; _i < MESSAGE_COUNT; _i++)
    {
        nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
        memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));

        nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
        nlh->nlmsg_pid = getpid();
        nlh->nlmsg_flags = 0;

        iov.iov_base = (void *)nlh;
        iov.iov_len = nlh->nlmsg_len;
        msg.msg_name = (void *)&dest_addr;
        msg.msg_namelen = sizeof(dest_addr);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;


        strcpy(NLMSG_DATA(nlh), "Hello Kernel");
        sendmsg(sock_fd, &msg, 0);  // send message to kernel
        memset(nlh, 0, NLMSG_SPACE(strlen("Hello Kernel")));
        recvmsg(sock_fd, &msg, 0);

        free(nlh);
    }

    endTime = time(NULL);
    printf("end time: %s\n", ctime(&endTime));

    printf("Avg speed is %lf Byte/s\n", (double)((unsigned long long)MESSAGE_COUNT * (unsigned long long)MAX_PAYLOAD) / difftime(endTime, startTime));

    close(sock_fd);
}


Kernel Space:

/* 
* Dist/Platform Kernel Version:
*     Ubuntu 14.04(Linux Mint 17): 3.13
*     CentOS 7: 3.10
*     Cavium AC: 3.10
*     Ubuntu 12.04(Linux Mint 13): 3.2
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define NETLINK_TEST 18
//#define MAX_PAYLOAD 1024
//#define MAX_PAYLOAD 2048
//#define MAX_PAYLOAD 4096
#define MAX_PAYLOAD 8192

MODULE_LICENSE("GPL");

static struct sock *nl_sk = NULL;

int netlinkSayHello(int pid)
{
    struct sk_buff *skb;
    struct nlmsghdr *nlh;

    skb = nlmsg_new(MAX_PAYLOAD, GFP_ATOMIC);
    if (skb == NULL)
    {
        printk(KERN_ERR "Failed to alloc skb\n");
        return 0;
    }

    // put into skb
    nlh = nlmsg_put(skb, 0, 0, 0, MAX_PAYLOAD, 0);

    // below line is meaningless
    memcpy(NLMSG_DATA(nlh), "Hello Client", sizeof("Hello Client"));

    if (netlink_unicast(nl_sk, skb, pid, 0) < 0)
    {
        printk(KERN_ERR"Failed to unicast skb\n");
        return 0;
    }

    return 1;
}

static void nl_data_ready(struct sk_buff *skb)
{
    struct nlmsghdr *nlh = NULL;

    if (skb == NULL)
    {
        printk(KERN_INFO"skb is NULL\n");
        return;
    }

    nlh = (struct nlmsghdr *)skb->data;

    netlinkSayHello(nlh->nlmsg_pid);
}

static void netlink_test(void)
{
/* for Cavium AC/CentOS 7/Ubuntu 14.04/Linux Mint 17 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
    struct netlink_kernel_cfg cfg = {
        .input = nl_data_ready,
    };
    nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &cfg);

/* for Ubuntu 12.04/Linux Mint 13 */
//#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
#else
    nl_sk = netlink_kernel_create(&init_net,
                                  NETLINK_TEST,
                                  0,
                                  nl_data_ready,
                                  NULL,
                                  THIS_MODULE);
#endif

    if (nl_sk == NULL)
    {
        printk(KERN_ERR "Failed to create netlink socket\n");
    }
}

static int __init my_module_init(void)
{
    printk(KERN_INFO "Initializing Netlink Socket\n");
    netlink_test();

    return 0;
}

static void __exit my_module_exit(void)
{
    netlink_kernel_release(nl_sk);
    printk(KERN_INFO "Goodbye\n");
}

module_init(my_module_init);
module_exit(my_module_exit);

實驗的結果如下:

1KB * 1048576 (1G)
Avg speed is 67108864.000000 Byte/s = 67MBps
2KB * 1048576 (2G)
Avg speed is 89478485.333333 Byte/s = 89MBps
4KB * 1048576 (4G)
Avg speed is 226050910.315789 Byte/s = 226MBps
8KB * 1048576 (8G)
Avg speed is 268435456.000000 Byte/s = 268MBps

看起來比想像中好很多呢~

留言

這個網誌中的熱門文章

如何將Linux打造成OpenFlow Switch:Openvswitch

我弟家的新居感恩禮拜分享:善頌善禱

如何利用 Wireshark 來監聽 IEEE 802.11 的管理封包