最近在研究MAP這個東東,
這個東西主要是用來做什麼的呢?
眾所皆知, IPv4 address都已經發完了。
IPv6絕對是未來的方向。
可以想像的,
IPv4未來會成為IPv6網路的孤島。
可能會有總總因素,會讓使用者(client)或服務提供者(server)只能使用IPv4 network的情況,
而如何透過IPv6的網路來傳送IPv4的封包,
就是MAP要做的事情。
而要在IPv6的網路上傳輸,必需要有IPv6 address。
問題是如何把IPv4轉換成IPv6 address。
通常有兩個主要的方式,
stateful, stateless
什麼是stateful呢?
就是在每一個IPv4與IPv6轉換的設備上會有轉換的記錄,
例如:
292.11.45.1→2001:34:55:99:ac::2
292.45.11.3→2001:34:55:99:ac::3
也就是說每當要轉換時,必需由讀取這一個記錄,
才能了解要怎麼轉換。
而stateless則是會有一個演算法,
使得IPv4與IPv6可以直接透過這一個演算法來互相轉換。
一般來說都會比較推薦stateless的方式(原因是什麼我目前還不太清楚)。
而MAP主要分為
Mapping of Address and Port with Encapsulation (MAP-E)
與
Mapping of Address and Port with Translation (MAP-T).
這兩個主要的差別在於MAP-E是用封裝的方式,
直接在IPv4的封包外再加上IPv6的header,
這樣的好處是可以完整保存IPv4的封包。
但是,要傳送的封包是會比較大一點,因為額外加了IPv6的封包了嘛。
而MAP-T則是把IPv4的header轉換成IPv6的header,
缺點是額外做轉換的動作,
效能來說可能會比較慢一點。
先暫時寫到這裡,
最近一直在研究這個東西,
應該還會持續一段時間。
參考資料:
【自由谈】城域网IPv6过渡技术——MAP技术(1)
2014年9月10日 星期三
Mapping of Address and Port (MAP)
2014年9月1日 星期一
linux下停用IPv6
直接寫入1到
/proc/sys/net/ipv6/conf/all/disable_ipv6
就可以關掉整個IPv6的支援。
可以填到
/usr/etc/rcS裡面寫入
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6
其它方式可以參考
Linux 下關閉支援 IPv6 提升效能
2014年8月11日 星期一
顯示make編譯信息
現在在編code的時候,因為在確認一些細節,想了解實際的的編
但是,編譯的過程中,並沒有把make的實際細節顯示出來。
我知道可以透過@與-s或--silent把完整的訊息隱藏起來,
但我的Makefile並沒有這一些東西啊,為什麼還是會隱藏起來呢?
原來是在build kernel module的時候,會使用的linux kernel的makefile,而kernel的makefile有預設隱藏這一些訊息。
有兩個方式
1. 則要到kernel的makefile把這一些部分註解掉。
要俢改的檔案位置是在/usr/src/linux-2.6.38.8/Makefile
...
ifeq ($(KBUILD_VERBOSE),1)
# quiet =
# Q =
else
# quiet=quiet_
# Q = @
endif
# If the user is running make -s (silent mode), suppress echoing of
# commands
ifneq ($(findstring s,$(MAKEFLAGS)),)
# quiet=silent_
endif
#export quiet Q KBUILD_VERBOSE
...
如此一來,重新編譯的時候,就可以顯示完整的編譯過程了。
2. 使用make V=1就可以顯示完整的訊息了, 這個方式就超級方便的了。
參考資料:
顯示make編譯信息
Linux內核make命令選項
2014年6月4日 星期三
pipe的用法
使用 pipe() 可建立一組雙向的管線,
通常會使用一個陣列來建立pipe
例:
int pfd[2];
這是一條水管,
從 pfd[0] 進入的東西會從 pfd[1] 出來,
反之亦然,
除此之外,
它也是可以跨 Process,
達成兩個程式溝通的目的。
實做上必須注意以下幾個重點
1.有複製,就要有關閉,一個dup2搭一個close,保持file descriptor的單純性
(此為血淚經驗談,自己實做就知道…)
2.fork出去的程式,沒用到的file descriptor一定要記得關
舉例來說,本來shell主程式裡面有一個pipe,若是此時fork出子程序來exec指令,主程序下wait指令等待子程序執行完畢且主程序沒有關閉pipe,則主程序會卡住。因為當fork的時候,一個pipe實際上會變成兩個pipe,當指派子程序接收pipe資料的時候,如果還有其他pipe沒有關閉,則子程序會判定pipe資料流尚未結束,而繼續癡癡等待輸入,若是主程序有pipe沒關閉的話,結果就是主程序在等子程序結束,子程序又在等待主程序的pipe輸入資料,造成死結。
參考:
C/C++, Linux, Web 相關技術, 程式心得筆記, 系統研發手札
pipe @ Linux Kernel
[程設] Linux C 的file descriptor以及pipe操作相關筆記(上)
[程設] Linux C 的file descriptor以及pipe操作相關筆記(下)
2014年5月21日 星期三
Linux C - gcc 預先定義的巨集
在Linux下使用gcc編譯,
有幾個內建的變數可以非常好用,
在Debug的時候,
占非常重要的角色。
1. __BASE_FILE__
完整的原始檔案路徑
2. __cplusplus
表示該檔案由 g++ 所編譯,當成 C++ 的檔案
3. __DATE__
編譯的日期
4. __TIME__
編譯的時間
5. __FILE__
原始檔名
6. __LINE__
所在行數
7. __VERSION__
gcc 版本
8. __func__
替代 __FUNCTION__,__FUNCTION__ 已被 GNU 不推薦使用
參考資料:
LinuxC – gcc 預先定義的巨集
2014年5月9日 星期五
如何開啟windows 7的telnet與tftp
為了把image燒到測試的板子上面,
必需要用到tftp這一個指令。
而在windows 7預設是把telnet與tftp關掉。
如何把這兩個功能打開呢?
開啟控制台→程式集→開啟或關閉Windows功能

選擇「Telnet用戶端」與「TFTP用戶端」的選擇,
再按確定。

這樣就可以使用telnet與tftp了。
參考資料:
Win7 開啟 telnet and tftp
2014年5月5日 星期一
union
因為IPv6的address一共有128bit,
若要處理的話,
目前long int也只有4 bytes(32bit),
double只有8bytes(64bit)
沒有一個變數可以儲存到128bit,
這個時候就要用到union
直接寫下
/* IPv6 address */
struct in6_addr {
union {
uint8_t u6_addr8[16];
uint16_t u6_addr16[8];
uint32_t u6_addr32[4];
} in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};這個宣告方式,可以讓128bit,
各別的使用8bit在運算。
下面是我寫的一個sub function,
也因為有了這個,
要運算IPv6才會變的比較簡單。
/*
* Filter the IPv6 by prefix to Network ID or Interface ID
*
* @param IPv6_Addr_Src the source for filtering
* @param IPv6_Addr_Dst the result of the filtering process
* @param PrefixLen the prefix of the network
* @param MaskType if the value is NetworkPrefix, network prefix would be reserved
* if the value is InterfaceIdentifier, the interface identifier would be reserved
*/
static void
MaskIPv6 (
struct in6_addr IPv6_Addr_Src,
struct in6_addr *IPv6_Addr_Dst,
int PrefixLen,
enum MaskType Direction
)
{
char *AddrPtr, *IndexAddrPtr;
int FullByteNumber, BitNumber;
char Mask;
int Index;
int CurrentPosition;
//
// The bytes of network id part
//
FullByteNumber = PrefixLen / 8;
//
// The bits of network id part
//
BitNumber = PrefixLen % 8;
//
// filter the bytes of Network ID part
//
for (CurrentPosition = 0; CurrentPosition < FullByteNumber; CurrentPosition++) {
if (Direction == NetworkPrefix) {
IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0xFF;
} else {
IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0x00;
}
}
//
// filter the bits of Network ID part and the bits of Interface ID part
//
Mask = 0;
if (BitNumber != 0) {
for (Index = 0; Index < BitNumber; Index++) {
Mask = (Mask << 1) | 1;
}
for (Index = 0; Index < 8 - BitNumber; Index++) {
Mask = Mask << 1;
}
if (Direction == InterfaceIdentifier) {
Mask = ~Mask;
}
IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & Mask;
CurrentPosition++;
}
//
// filter the bytes of Interface ID part
//
for (; CurrentPosition < 16; CurrentPosition++) {
if (Direction == NetworkPrefix) {
IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0x00;
} else {
IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0xFF;
}
}
//
// Copy the modified IPv6_Addr_Src context for return
//
memcpy (IPv6_Addr_Dst, &IPv6_Addr_Src, sizeof (IPv6_Addr_Src));
}