Linux上的物理网卡与虚拟网络设备

Tags: linux  network 

目录

物理网卡

物理网卡工作原理

通过ip link add可以创建多种类型的虚拟网络设备,在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在虚拟化支持领域对抗Cisco的VN-Tag的技术。

解决了虚拟机之间网络通信的问题,特别是位于同一个宿主机内的虚拟机之间的网络通信问题。

VN-Tag在标准的协议头中增加了一个全新的字段,VEPA则是通过修改网卡驱动和交换机,通过发夹弯技术回注报文。

vepa工作原理

TUN

TUN是Linux系统里的虚拟网络设备,它的原理和使用在Kernel DocWiki做了比较清楚的说明。

TUN设备模拟网络层设备(network layer),处理三层报文,IP报文等,用于将报文注入到网络协议栈。

TUN设备工作原理

应用程序(app)可以从物理网卡上读写报文,经过处理后通过TUN回送,或者从TUN读取报文处理后经物理网卡送出。

利用TUN实现VPN

TUN设备创建

创建:

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);
}

创建之后,使用ip addr就会看见一个名为”tun-default”的虚拟网卡

注意:如果程序退出,关闭了fd,虚拟网卡也会随之消失。

$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

可以对tun-default设置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等文件操作函数从fd中进行读取操作,就是在收取报文,向fd中写入数据,就是在发送报文。

TAP

TAP是Linux系统里的虚拟网络设备,它的原理和使用在Kernel DocWiki做了比较清楚的说明。

不同于TUN的是,TAP设备模拟链路层设备(link layer),处理二层报文,以太网帧等。

TAP设备创建

TAP设备的创建过程和TUN类似,在ioctl设置的时候,将类型设置为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设备
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设备与TUN设备的区别在于:

TAP虚拟的是一个二层设备,具有MAC地址,接收、发送的是二层包。
TUN虚拟的是一个三层设备,没有MAC地址,接收、发送的是三层包。

macvlan

有时我们可能需要一块物理网卡绑定多个 IP 以及多个 MAC 地址,虽然绑定多个 IP 很容易,但是这些 IP 会共享物理网卡的 MAC 地址,可能无法满足我们的设计需求,所以有了 MACVLAN 设备,其工作方式如下:

macvlan工作原理

MACVLAN 会根据收到包的目的 MAC 地址判断这个包需要交给哪个虚拟网卡。单独使用 MACVLAN 好像毫无意义,但是配合之前介绍的 network namespace 使用,我们可以构建这样的网络:

macvlan工作原理2

macvlan的工作原理3

采摘

macvlan使用

创建一个基于eth0的名为macv1的macvlan网卡:

ip link add link eth0 name macv1 type macvlan 

macvlan支持三种模式,bridge、vepa、private,在创建的时候设置“mode XXX”:

macvlan brige模式

bridge模式,macvlan网卡和物理网卡直接可以互通,类似于接入到同一个bridge。

macvlan vepa模式

vepa模式下,两个macvlan网卡直接不能直接通信,必须通过外部的支持“发夹弯”交换机才能通信。

macvlan vepa模式

private模式下,macvlan发出的广播包(arp等)被丢弃,即使接入了支持“发夹弯”的交换机也不能发现其它macvlan网卡,除非手动设置mac。

macvtap

MACVTAP 是对 MACVLAN的改进,把 MACVLAN 与 TAP 设备的特点综合一下,使用 MACVLAN 的方式收发数据包,但是收到的包不交给 network stack 处理,而是生成一个 /dev/tapX 文件,交给这个文件:

macvtap工作原理

由于 MACVLAN 是工作在 MAC 层的,所以 MACVTAP 也只能工作在 MAC 层,不会有 MACVTUN 这样的设备。

ipvlan

ipvlan和macvlan的区别在于它在ip层进行流量分离而不是基于mac地址,同属于一块宿主以太网卡的所有ipvlan虚拟网卡的mac地址都是一样的。

ipvlan工作原理

ip link add link <master-dev> <slave-dev> type ipvlan mode { l2 | L3 }

veth

veth工作原理

veth设备是成对创建的:

$ip link add vethA type veth peer name vethB

创建之后,执行ip link就可以看到新创建的veth设备:

58: [email protected]: <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: [email protected]: <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设备前面的ID,58:59:,一对veth设备的ID是相差1的,并且系统内全局唯一。可以通过ID找到一个veth设备的对端。

veth设备理解

ifb

Intermediate Functional Block device,连接ifb中做了很详细的介绍。

参考

  1. Kernel Doc tuntap.txt
  2. Wiki TUN/TAP
  3. Linux网络虚拟化
  4. TUN/TAP MACVLAN MACVTAP
  5. 图解几个与Linux网络虚拟化相关的虚拟网卡
  6. veth设备理解
  7. ifb

linux

  1. 重学 cgroups: 入门指引、基本概念和 cgroup v1 基础使用
  2. 在用户态观测 Linux 内核函数的调用情况(调用次数、传入参数、运行时长等)
  3. 系统性能分析方法论: 统计图谱工具
  4. Linux关闭swap失败,swapoff failed: cannot allocate memory
  5. Linux内核功能eBPF入门学习(二): BCC中的eBPF应用与bpftrace等
  6. Linux内核功能eBPF入门学习(一): BPF、eBPF、BCC等基本概念
  7. CentOS7/6内核升级的简单方法: 借助ELRepo,用yum命令更新内核
  8. cgroups: cgroup controller 汇总和参数(文件接口)
  9. cgroups: cgroup v1 和 cgroup v2 详细介绍
  10. Linux FUSE(用户态文件系统)的使用: 用libfuse创建FUSE文件系统
  11. 火焰图生成工具nginx-systemtap-toolkit使用时遇到的问题
  12. Linux内核参数用途记录
  13. Linux的nftables的使用
  14. Linux网络调试: iptables规则、连接跟踪表、报文跟踪
  15. 怎样获取Linux kernel相关的知识?Linux内核文档汇总
  16. linux中疑难问题的调查方法
  17. 服务器存在较多的FIN_WAIT1和TIME_WAIT状态的连接
  18. linux的tcp连接
  19. linux的traffic control
  20. DNS的benchmark工具
  21. cgroups: 基本概念&入门指引
  22. Linux的Network Tunnel技术
  23. Linux的网络namespace
  24. Linux上的物理网卡与虚拟网络设备
  25. 发包工具、改包工具
  26. 网络流量控制技术
  27. Linux内核调试、修改
  28. 常见网络报文的格式

network

  1. 怎样规划多DMZ区的安全企业网?
  2. Linux上的物理网卡与虚拟网络设备
  3. 怎样理解1.488Mpps?
  4. 这样子用零雀云翻墙
  5. 翻墙的原理与实践
  6. 匿名网络
  7. 网络虚拟化
  8. 常见网络报文的格式

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  李佶澳的博客  小鸟笔记  软件手册  编程手册  运营手册  网络课程  收藏文章  发现知识星球  百度搜索 谷歌搜索