物理網(wǎng)卡

link device type
通過ip link add可以創(chuàng)建多種類型的虛擬網(wǎng)絡(luò)設(shè)備,在man ip link中可以得知有以下類型的device:
bridge - Ethernet Bridge device
can - Controller Area Network interface
dummy - Dummy network interface
ifb - Intermediate Functional Block device
ipoib - IP over Infiniband device
macvlan - Virtual interface base on link layer address (MAC)
vcan - Virtual Local CAN interface
veth - Virtual ethernet interface
vlan - 802.1q tagged virtual LAN interface
vxlan - Virtual eXtended LAN
ip6tnl - Virtual tunnel interface IPv4|IPv6 over IPv6
ipip - Virtual tunnel interface IPv4 over IPv4
sit - Virtual tunnel interface IPv6 over IPv4
VEPA
Virtual Ethernet Port Aggregator。它是HP在虛擬化支持領(lǐng)域?qū)笴isco的VN-Tag的技術(shù)。
解決了虛擬機(jī)之間網(wǎng)絡(luò)通信的問題,特別是位于同一個(gè)宿主機(jī)內(nèi)的虛擬機(jī)之間的網(wǎng)絡(luò)通信問題。
VN-Tag在標(biāo)準(zhǔn)的協(xié)議頭中增加了一個(gè)全新的字段,VEPA則是通過修改網(wǎng)卡驅(qū)動(dòng)和交換機(jī),通過發(fā)夾彎技術(shù)回注報(bào)文。

TUN
TUN是Linux系統(tǒng)里的虛擬網(wǎng)絡(luò)設(shè)備,它的原理和使用在Kernel Doc和Wiki做了比較清楚的說明。
TUN設(shè)備模擬網(wǎng)絡(luò)層設(shè)備(network layer),處理三層報(bào)文,IP報(bào)文等,用于將報(bào)文注入到網(wǎng)絡(luò)協(xié)議棧。

應(yīng)用程序(app)可以從物理網(wǎng)卡上讀寫報(bào)文,經(jīng)過處理后通過TUN回送,或者從TUN讀取報(bào)文處理后經(jīng)物理網(wǎng)卡送出。

TUN設(shè)備創(chuàng)建
創(chuàng)建:
int tun_alloc(char *dev)
{
struct ifreq ifr;
int fd, err;
if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ){
printf("open /dev/net/tun fail\n");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN;
if( *dev )
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
return err;
}
strcpy(dev, ifr.ifr_name);
return fd;
}
int fd = tun_alloc("tun-default");
if (fd == -1) {
printf("create error: %d\n", fd);
return;
}
while(1){
sleep(1000);
}
創(chuàng)建之后,使用ip addr就會(huì)看見一個(gè)名為”tun-default”的虛擬網(wǎng)卡
注意:如果程序退出,關(guān)閉了fd,虛擬網(wǎng)卡也會(huì)隨之消失。
$ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 52:54:00:bd:97:1e brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic eth0
valid_lft 81917sec preferred_lft 81917sec
inet6 fe80::5054:ff:febd:971e/64 scope link
valid_lft forever preferred_lft forever
4: tun-default: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 500
link/none
可以對(duì)tun-default設(shè)置IP:
$sudo ip addr add 1.1.1.1 dev tun-default
$ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 52:54:00:bd:97:1e brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic eth0
valid_lft 81806sec preferred_lft 81806sec
inet6 fe80::5054:ff:febd:971e/64 scope link
valid_lft forever preferred_lft forever
4: tun-default: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 500
link/none
inet 1.1.1.1/32 scope global tun-default
valid_lft forever preferred_lft forever
使用open/write等文件操作函數(shù)從fd中進(jìn)行讀取操作,就是在收取報(bào)文,向fd中寫入數(shù)據(jù),就是在發(fā)送報(bào)文。
TAP
TAP是Linux系統(tǒng)里的虛擬網(wǎng)絡(luò)設(shè)備,它的原理和使用在Kernel Doc和Wiki做了比較清楚的說明。
不同于TUN的是,TAP設(shè)備模擬鏈路層設(shè)備(link layer),處理二層報(bào)文,以太網(wǎng)幀等。
TAP設(shè)備創(chuàng)建
TAP設(shè)備的創(chuàng)建過程和TUN類似,在ioctl設(shè)置的時(shí)候,將類型設(shè)置為IFF_TAP即可。
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TAP; //<--- TAP設(shè)備
if( *dev )
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
return err;
}
strcpy(dev, ifr.ifr_name);
return fd;
TAP設(shè)備與TUN設(shè)備的區(qū)別在于:
TAP虛擬的是一個(gè)二層設(shè)備,具有MAC地址,接收、發(fā)送的是二層包。
TUN虛擬的是一個(gè)三層設(shè)備,沒有MAC地址,接收、發(fā)送的是三層包。
macvlan
有時(shí)我們可能需要一塊物理網(wǎng)卡綁定多個(gè) IP 以及多個(gè) MAC 地址,雖然綁定多個(gè) IP 很容易,但是這些 IP 會(huì)共享物理網(wǎng)卡的 MAC 地址,可能無法滿足我們的設(shè)計(jì)需求,所以有了 MACVLAN 設(shè)備,其工作方式如下:

MACVLAN 會(huì)根據(jù)收到包的目的 MAC 地址判斷這個(gè)包需要交給哪個(gè)虛擬網(wǎng)卡。單獨(dú)使用 MACVLAN 好像毫無意義,但是配合之前介紹的 network namespace 使用,我們可以構(gòu)建這樣的網(wǎng)絡(luò):


macvlan使用
創(chuàng)建一個(gè)基于eth0的名為macv1的macvlan網(wǎng)卡:
ip link add link eth0 name macv1 type macvlan
macvlan支持三種模式,bridge、vepa、private,在創(chuàng)建的時(shí)候設(shè)置“mode XXX”:

bridge模式,macvlan網(wǎng)卡和物理網(wǎng)卡直接可以互通,類似于接入到同一個(gè)bridge。

vepa模式下,兩個(gè)macvlan網(wǎng)卡直接不能直接通信,必須通過外部的支持“發(fā)夾彎”交換機(jī)才能通信。

private模式下,macvlan發(fā)出的廣播包(arp等)被丟棄,即使接入了支持“發(fā)夾彎”的交換機(jī)也不能發(fā)現(xiàn)其它macvlan網(wǎng)卡,除非手動(dòng)設(shè)置mac。
macvtap
MACVTAP 是對(duì) MACVLAN的改進(jìn),把 MACVLAN 與 TAP 設(shè)備的特點(diǎn)綜合一下,使用 MACVLAN 的方式收發(fā)數(shù)據(jù)包,但是收到的包不交給 network stack 處理,而是生成一個(gè) /dev/tapX 文件,交給這個(gè)文件:

由于 MACVLAN 是工作在 MAC 層的,所以 MACVTAP 也只能工作在 MAC 層,不會(huì)有 MACVTUN 這樣的設(shè)備。
ipvlan
ipvlan和macvlan的區(qū)別在于它在ip層進(jìn)行流量分離而不是基于mac地址,同屬于一塊宿主以太網(wǎng)卡的所有ipvlan虛擬網(wǎng)卡的mac地址都是一樣的。
[圖片上傳失敗...(image-d98b6f-1597455459947)]
ip link add link <master-dev> <slave-dev> type ipvlan mode { l2 | L3 }
veth

veth設(shè)備是成對(duì)創(chuàng)建的:
$ip link add vethA type veth peer name vethB
創(chuàng)建之后,執(zhí)行ip link就可以看到新創(chuàng)建的veth設(shè)備:
58: vethB@vethA: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether ee:1b:b0:11:38:eb brd ff:ff:ff:ff:ff:ff
59: vethA@vethB: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether a6:f8:50:36:2d:1e brd ff:ff:ff:ff:ff:ff
注意veth設(shè)備前面的ID,58:和59:,一對(duì)veth設(shè)備的ID是相差1的,并且系統(tǒng)內(nèi)全局唯一。可以通過ID找到一個(gè)veth設(shè)備的對(duì)端。
ifb
Intermediate Functional Block device,連接ifb中做了很詳細(xì)的介紹。