20170216_jeffrey - silenceuncrio/diary GitHub Wiki
0925
review
計畫永遠趕不上變化
昨天聽 ariel 說公司一月份虧了 一百多萬
M300 要能換錢回來
昨天來的印度客戶至少就是個相對實際的需求
先就下面這四個我來負責的項目 google 一下
- DMZ
- UPnP (IPv4v6)
- RIP
- OSPF
1330
ariel 表示 OSPF 不做了
要改用 BGP 來取代 OSPF
參考 動態路由協議全方位比較:RIPv2、EIGRP、OSPF、BGP 原文網址:https://read01.com/0jay5D.html
得知我原本要實作的 RIP
, OSPF
其實角色都是相當的
ariel 告知的只是 印度客戶 比較 prefer BGP
, 而不是 OSPF
google 到了 Quagga Routing Suite
Quagga is a routing software suite, providing implementations of OSPFv2, OSPFv3, RIP v1 and v2, RIPng and BGP-4 for Unix platforms, particularly FreeBSD, Linux, Solaris and NetBSD. Quagga is a fork of GNU Zebra which was developed by Kunihiro Ishiguro. The Quagga tree aims to build a more involved community around Quagga than the current centralised model of GNU Zebra.
一次解決 RIP
, BGP
YOCTO
裡也有 quagga
這個 recipe
1415
目前想到的工作節奏是這樣
先透過 Web server with HTTPS
來熟悉 M300 上的 icos 架構
然後可以先做 DMZ
和 UPNP
公司的其他案子有已經完工的 icos module 可以參考
例如 579X
RIP
和 BGP
雖然在 YOCTO
的 quagga
recipe 有提供
但這個工作項目相對複雜 - 需要新增相對應的 icos module
所以工作項目的實作順序是這樣
- Web server with HTTPS
- DMZ
- UPnP (IPv4v6)
- RIP
- BGP
1425
從 Web server with HTTPS
出發
好好地 trace webcfg.c
來打個底
先看一下 web
這個所謂的 icos module 長甚麼樣
sIcosModule webModule={
"web", // Name
InitWeb, // Init
ExitWeb, // Exit
ApplyWebSetting, // Apply
GetWebSetting, // GetSetting
SetWebSetting, // SetSetting
VerifyWebSetting, // VerifySetting
0, // GetStatus
0, // GetStatus
facotry_default_web_setting,
0,//period_ddns,
notify_web,
msgcb_web,
termcb_web,
};
我們需要參考 sIcosModule
這個型態的定義
typedef struct sIcosModule_t
{
char* szName; // module name
int (*Init) (char *pCfgStr); // module init
int (*Exit) (char *pCfgStr); // module exit
int (*Apply) (int flag, int index, void* pStruct, int structSize); // Apply Setting and Save setting to /ETC
int (*GetSetting) (int flag, int index, void* pStruct, int structSize); // Load Setting to pStruct
int (*SetSetting) (int flag, int index, void* pStruct, int structSize); // Save Setting to Memory only
int (*VerifySetting)(int flag, int index, void* pStruct, int structSize); // Verify Setting is correct or not ?
int (*GetStatus) (int flag, int index, void* pStruct, int structSize); // Get Status to pStruct
int (*Str2Value) (int attID, char *pAttValue, int *pValue); // String to value conversion
int (*Factory) (void); // Facotry To Default
int (*PeriodHandle) (void); // Ariel: only Called in icospromsg
int (*NotifyHandler)(PRO_EVENT *pevent); // Ariel: only Called in icospromsg
int (*proc_msg_cb) (char *msg, pid_t pid, int rc); // redirect process stdout into module call back
int (*proc_term_cb) (char *msg, pid_t pid); // process terminate callback
} sIcosModule;
1435
先來看 Init
這個 callback function 是怎麼被觸發的
這需要說到 icos 這東西是如何被啟動的
M300 開機時會執行 /etc/rc.local
這個 shell script
/etc/rc.local
裡會去執行 /usr/sbin/icosconfig bootinit
看到 icosconfig 這個可執行檔的 source code
/usr/sbin/icosconfig bootinit
所觸發的是 ICOS_Bootinit()
entry.c
#define icos_module_name_foreach(id, name) \
const char *name;\
int id; \
for (int keep = 1, count = 0; keep && count < dim(moduleInitAry); keep = !keep, count++) \
for (name = moduleInitAry[count].pString, \
id = moduleInitAry[count].value; keep; keep = !keep)
sAttStringSet moduleInitAry[] =
{
{ "MODULE_SYSTEM", MODULE_SYSTEM },
...
{ "MODULE_WEB", MODULE_WEB },
...
};
sIcosModule* GetIcosModule(int module)
{
switch (module)
{
...
case MODULE_WEB:
return &webModule;
...
}
eprintf(" module(id:%d) module mapping not exist!\n", module);
return 0;
}
int _icos_module_init_foreach(int bShowInfo)
{
...
icos_module_name_foreach(module_id, name)
{
pIcosModule=GetIcosModule(module_id);
if (pIcosModule==0) continue;
...
if (pIcosModule->Init)
{
res=pIcosModule->Init(szCfgStr);
if (res<0) printf(" Error: Module %s cfg init failure\n", pIcosModule->szName);
szCfgStr[module_id]='1';
}
}
return res;
}
int ICOS_Bootinit(void)
{
...
// =============================================================================
// | init modules
// =============================================================================
_icos_module_init_foreach(1);
...
}
icos_module.h
extern int ICOS_Bootinit(void);
icosmain.c
int main(int argc, char *argv[])
{
...
if (!strcmp(argv[1], "bootinit"))
{
res=ICOS_Bootinit();
}
...
}
從 source code 來看
ICOS_Bootinit() 便會把 webModule
的 InitWeb()
叫起來
1455
回到 sIcosModule
這個型態所定義的 Exit()
entry.c
int _icos_module_exit_foreach(int bShowInfo)
{
for (; i >= 0; i--)
{
int module_id = moduleInitAry[i].value;
pIcosModule=GetIcosModule(module_id);
if (pIcosModule->Exit)
{
res=pIcosModule->Exit(szCfgStr);
}
}
}
int ICOS_Shutdown(void)
{
...
_icos_module_exit_foreach(1);
...
}
int ICOS_WarmReboot(int bShowInfo)
{
...
// =============================================================================
// | exit modules
// =============================================================================
_icos_module_exit_foreach(1);
...
}
ICOS_Shutdown()
可由 /usr/sbin/icosconfig shutdown
這命令所觸發
ICOS_WarmReboot()
則是由 /usr/sbin/icosconfig warmreboot
這命令所觸發
這兩者最終都會導致 webModule
的 ExitWeb()
被叫起來
1505
來看 sIcosModule
型態定義的 Apply()
typedef struct sIcosModule_t
{
int (*Apply) (int flag, int index, void* pStruct, int structSize); // Apply Setting and Save setting to /ETC
} sIcosModule;
entry.c
int ICOS_Apply(int module, int flag, int index, void* pStruct, int structSize)
{
...
pIcosModule=GetIcosModule(module);
...
res=pIcosModule->Apply(flag, index, pStruct, structSize);
...
return res;
}
icos_module.h
extern int ICOS_Apply (int module, int flag, int index, void* pStruct, int structSize);
我們若把 icos 當作是個 library 的話
ICOS_Apply() 這個 API 帶入 MODULE_WEB
這個 module 參數
便會呼叫到 webModule
的 ApplyWebSetting()
1520
來看 sIcosModule
型態定義的 GetSetting()
typedef struct sIcosModule_t
{
int (*GetSetting) (int flag, int index, void* pStruct, int structSize); // Load Setting to pStruct
} sIcosModule;
entry.c
int ICOS_GetSetting(int module, int flag, int index, void* pStruct, int structSize)
{
sIcosModule *pIcosModule;
pIcosModule=GetIcosModule(module);
if (pIcosModule==0) return ICOS_FAILURE;
if (pIcosModule->GetSetting==0)
{
eprintf(" module(id:%d) func GetSetting not exist!\n", module);
return ICOS_FAILURE;
}
return pIcosModule->GetSetting(flag, index, pStruct, structSize);
}
icos_module.h
extern int ICOS_GetSetting (int module, int flag, int index, void* pStruct, int structSize);
我們若把 icos 當作是個 library 的話
ICOS_GetSetting() 這個 API 帶入 MODULE_WEB
這個 module 參數
便會呼叫到 webModule
的 GetWebSetting()
1550
來看 sIcosModule
型態定義的 SetSetting()
typedef struct sIcosModule_t
{
int (*SetSetting) (int flag, int index, void* pStruct, int structSize); // Save Setting to Memory only
} sIcosModule;
entry.c
int ICOS_SetSetting(int module, int flag, int index, void* pStruct, int structSize)
{
sIcosModule *pIcosModule;
pIcosModule=GetIcosModule(module);
if (pIcosModule==0) return ICOS_FAILURE;
if (CheckIgnoredModules(pIcosModule->szName)) return ICOS_FAILURE; //John20161215
if (pIcosModule->SetSetting==0)
{
eprintf(" module(id:%d) func SetSetting not exist!\n", module);
return ICOS_FAILURE;
}
return pIcosModule->SetSetting(flag, index, pStruct, structSize);
}
icos_module.h
extern int ICOS_SetSetting (int module, int flag, int index, void* pStruct, int structSize);
我們若把 icos 當作是個 library 的話
ICOS_SetSetting() 這個 API 帶入 MODULE_WEB
這個 module 參數
便會呼叫到 webModule
的 SetWebSetting()
1610
morris 進行 靜電 相關的測試後告知結果還算滿意
這表示我已經可以做 commit 的動作了
- uboot env verion - 1.2
- correct the GPIO setting for ethernet 1 and ethernet 2
- add some dummy uboot env to try to protect important uboot env
1620
繼續看 sIcosModule
型態定義的 VerifySetting()
typedef struct sIcosModule_t
{
int (*VerifySetting)(int flag, int index, void* pStruct, int structSize); // Verify Setting is correct or not ?
} sIcosModule;
entry.c
int ICOS_VerifySetting(int module, int flag, int index, void* pStruct, int structSize)
{
sIcosModule *pIcosModule;
pIcosModule=GetIcosModule(module);
if (pIcosModule==0) return ICOS_FAILURE;
if (pIcosModule->VerifySetting==0)
{
eprintf(" module(id:%d) func VerifySetting not exist!\n", module);
return ICOS_FAILURE;
}
return pIcosModule->VerifySetting(flag, index, pStruct, structSize);
}
icos_module.h
extern int ICOS_VerifySetting(int module, int flag, int index, void* pStruct, int structSize);
我們若把 icos 當作是個 library 的話
ICOS_VerifySetting() 這個 API 帶入 MODULE_WEB
這個 module 參數
便會呼叫到 webModule
的 VerifyWebSetting()
1625
繼續看 sIcosModule
型態定義的 GetStatus()
typedef struct sIcosModule_t
{
int (*GetStatus) (int flag, int index, void* pStruct, int structSize); // Get Status to pStruct
} sIcosModule;
entry.c
int ICOS_GetStatus(int module, int flag, int index, void* pStruct, int structSize)
{
sIcosModule *pIcosModule;
pIcosModule=GetIcosModule(module);
if (pIcosModule==0) return ICOS_FAILURE;
if (pIcosModule->GetStatus==0)
{
eprintf(" module(id:%d) func GetStatus not exist!\n", module);
return ICOS_FAILURE;
}
return pIcosModule->GetStatus(flag, index, pStruct, structSize);
}
icos_module.h
extern int ICOS_GetStatus (int module, int flag, int index, void* pStruct, int structSize);
ICOS_GetStatus() 這個 API 帶入 MODULE_WEB
這個 module 參數
並不會呼叫到 webModule
的任何 function
sIcosModule webModule={
"web", // Name
...
0, // GetStatus
...
};
1630
看 sIcosModule
型態定義的 Str2Value()
typedef struct sIcosModule_t
{
int (*Str2Value) (int attID, char *pAttValue, int *pValue); // String to value conversion
} sIcosModule;
entry.c
int ICOS_CheckStr2Value(int module, sIcosModule **pModule)
{
//LDBG(DBG_INFO, "\n");
*pModule = GetIcosModule(module);
if (*pModule==0) return ICOS_FAILURE;
// check if String to Value callback defined or not?
if ((*pModule)->Str2Value==0)
{
LDBG(DBG_INFO, " module(id:%d) func Str2Value() not defined!\n", module);
return ICOS_FAILURE;
}
return ICOS_SUCCESS;
}
icos_module.h
extern int ICOS_CheckStr2Value(int module, sIcosModule **pModule);
ICOS_GetStatus() 這個 API 帶入 MODULE_WEB
這個 module 參數
並不會呼叫到 webModule
的任何 function
sIcosModule webModule={
"web", // Name
...
0,
...
};
因為 webModule
並沒有準備相對應的 function 給 sIcosModule
型態裡的 Str2Value()
function poionter
1635
來看 sIcosModule
型態定義的 Factory()
typedef struct sIcosModule_t
{
int (*Factory) (void); // Facotry To Default
} sIcosModule;
目前沒有任何 export 出去的 API 會使用到
所以 webModule
的 facotry_default_web_setting
並不會有透過 API 被叫起來的 情況
1640
來看 sIcosModule
型態定義的 PeriodHandle()
typedef struct sIcosModule_t
{
int (*PeriodHandle) (void); // Ariel: only Called in icospromsg
} sIcosModule;
entry.c
int PeriodHandle(void)
{
int res;
sIcosModule *pIcosModule;
icos_module_name_foreach(module_id, name)
{
pIcosModule=GetIcosModule(module_id);
if (pIcosModule==0)
{
//CPRT("!!!No module(idx=%d)\n", module_id);
continue;
}
if (CheckIgnoredModules(pIcosModule->szName))
{
//CPRT("!!!IgnoredModule(Name=%s)\n", pIcosModule->szName);
continue;
}
if (pIcosModule->PeriodHandle)
{
CPRT("Process Module %s PeriodHandle()\n", pIcosModule->szName);
res=pIcosModule->PeriodHandle();
if (res<0) CPRT(" Error: Module %s PeriodHandle\n", pIcosModule->szName);
}
}
return ICOS_SUCCESS;
}
雖然 webModule
並沒有準備相對應的 function 給 sIcosModule
型態裡的 PeriodHandle()
function poionter
不過我們還是來追看看誰會呼叫 entry.c
的 PeriodHandle()
答案是 /usr/sbin/icospromsg
1650
來看 /usr/sbin/icospromsg
的 source code
icospromsg.c
int main(int argc, char **argv)
{
while (!G_loop_exit)
{
timeout.tv_sec = 1;
timeout.tv_usec = 0;
...
sel_ret=0;
sel_ret=select(maxfd+1, &rdset, 0, 0, &timeout);
if(G_loop_exit)
break;
if (sel_ret > 0)
{
...
}
else if (sel_ret == 0) //Timeout
{
//PRO_PRT("Call PeriodHandle()\n");
PeriodHandle();
TimerTS=time(0);
}
//PRO_PRT("Call PS_watchdog()\n");
PS_watchdog();
}//End_while
...
}
簡單來說就是一旦 /usr/sbin/icospromsg
被執行便會在
icospromsg.c
的 main()
的 while
作 loop
然後每一秒會呼叫一次 PeriodHandle()
1700
來看 sIcosModule
型態定義的 NotifyHandler()
typedef struct sIcosModule_t
{
int (*NotifyHandler)(PRO_EVENT *pevent); // Ariel: only Called in icospromsg
} sIcosModule;
entry.c
int BroadcastHandle(PRO_EVENT *pmsg)
{
int res=0;
icos_module_foreach(pIcosModule)
{
if (pIcosModule==0) continue;
if (CheckIgnoredModules(pIcosModule->szName))
{
continue;
}
if (pIcosModule->NotifyHandler)
{
CPRT("Process Module %s BroadcastHandle()\n", pIcosModule->szName);
res=pIcosModule->NotifyHandler(pmsg);
}
}
return res;
}
除了 icos 的 library 之外還要看到 可執行檔 /usr/sbin/icospromsg
的 source code
int main(int argc, char **argv)
{
...
while (!G_loop_exit)
{
timeout.tv_sec = 1;
timeout.tv_usec = 0;
...
sel_ret=0;
sel_ret=select(maxfd+1, &rdset, 0, 0, &timeout);
if (sel_ret > 0)
{
// Check Events
if (FD_ISSET(usfd, &rdset))
{
PRO_EVENT *pmsg=NULL;
unsigned char *sp=msg_buffer;
read_bytes = recv(usfd, sp, sizeof(PRO_EVENT),MSG_DONTWAIT | MSG_NOSIGNAL);
pmsg = (PRO_EVENT*)sp;
...
if (pmsg->dst_id == 0) // 0: means broadcast
{
BroadcastHandle(pmsg);
}
else
{
NotifyHandle(pmsg);
}
}
ProcMsgHandler(&rdset);
}
...
}//End_while
...
}
一旦 /usr/sbin/icospromsg
被執行便會在
icospromsg.c
的 main()
的 while
作 loop
一旦收到 PRO_EVENT
message 的話
便依據 dst_id
來決定是呼叫 BroadcastHandle()
還是 NotifyHandle()
試情況 webModule
的 notify_web()
便會被呼叫了
注意到不管是 BroadcastHandle()
還是 NotifyHandle()
都需要再呼叫 ProcMsgHandler()
先不追 ProcMsgHandler()
1720
來看 sIcosModule
型態定義的 proc_msg_cb()
typedef struct sIcosModule_t
{
int (*proc_msg_cb) (char *msg, pid_t pid, int rc); // redirect process stdout into module call back
} sIcosModule;
icos_process.c
int ProcMsg(int module_id, char *msg, pid_t pid, int rc)
{
...
pIcosModule=GetIcosModule(module_id);
if (pIcosModule->proc_msg_cb)
{
res=pIcosModule->proc_msg_cb(msg, pid, rc);
}
return res;
}
void ProcMsgHandler(fd_set *readfds)
{
...
while (ps_ctx)
{
if (ps_ctx->ptyfd > 0 && FD_ISSET(ps_ctx->ptyfd, readfds) )
{
rc=read(ps_ctx->ptyfd, buf, MSG_LEN-1);
if (rc>0)
{
buf[rc]='\0';
ProcMsg(ps_ctx->module_id, buf, ps_ctx->pid, rc);
}
}
ps_ctx = ps_ctx->next;
}
}
這邊的 ProcMsgHandler() 便和前頭的 BroadcastHandle()
和 NotifyHandle()
串起來了
也就是試情況 webModule
的 notify_web()
被呼叫後 就換 msgcb_web()
被叫起來做事
1730
來看 sIcosModule
型態定義的 proc_term_cb()
typedef struct sIcosModule_t
{
int (*proc_term_cb) (char *msg, pid_t pid); // process terminate callback
} sIcosModule;
icos_process.c
int ProcTerminate(int module_id, char *msg, pid_t pid)
{
sIcosModule *pIcosModule;
pIcosModule=GetIcosModule(module_id);
int res=0;
if (pIcosModule==0) return ICOS_FAILURE;
if (CheckIgnoredModules(pIcosModule->szName)) return ICOS_FAILURE;
if (pIcosModule->proc_term_cb)
{
PRO_PRT("Process Module %s ProcTerminate()\n", pIcosModule->szName);
res=pIcosModule->proc_term_cb(msg, pid);
}
return res;
}
void PS_watchdog(void)
{
struct proc_ctx *ps_ctx=NULL;
...
ps_ctx = phead_proc;
while (ps_ctx)
{
...
if (ps_ctx->state == PS_STATE_EXITED)
{
pIcosModule=GetIcosModule(ps_ctx->module_id);
if (pIcosModule->proc_term_cb)
{
pIcosModule->proc_term_cb(buf, ps_ctx->pid);
}
continue;
}
ps_ctx = ps_ctx->next;
}
}
目前並沒有看到誰在使用 ProcTerminate()
所以只有 PS_watchdog()
有可能會去呼叫 webModule
的 termcb_web()
至於 PS_watchdog()
在什麼狀況下會去呼叫 webModule
的 termcb_web()
呢?
這就需要再去追了
但不是現在需要去追的事