linux虚拟网络基础

linux虚拟网络基础
Neutron在构建网络服务时,利用了很多Linux虚拟网络功能(Linux内核中的虚拟网络设备以及其他网络功能)。为了对Neutron有一个全面的理解,掌握一些Linux虚拟网络知识是必要的。以下对与Neutron密切相关的Linux虚拟网络功能进行简单介绍。
1.1 tap
Linux在谈到tap时,经常会与tun并列谈论。两者都是操作系统内核中的虚拟网络设备。tap位于二层,tun位于三层。需要说明的是,这里所说的设备(Device))是Linux的概念,不是我们平时生活中所说的设备。比如,生活中,我们常常把一台物理路由器称为一台设备,如图2-1所示。
在这里插入图片描述

而Linux所说的设备,其背后指的是一个类似于数据结构、内核模块或设备驱动这样的含义。像tun/tap这样的设备,它的数据结构如下:

  • struct tun_struct {char name[8]; //设备名
  • unsigned long flags;//区分tun和tap设备
  • struct fasync_struct * fasync; //文件异步通知结构
  • wait_queue_head_t read_wait;//等待队列
  • struct net_device dev;//Linux抽象网络设备结构
  • struct sk_buff_head txq;//网络缓冲区队列
  • struct net_device_stats stats;//网卡状态信息结构

我们看到,甚至连数据结构,tap与tun的定义都是同一个,两者仅仅是通过一个Flag来区分。不过从背后所承载的功能而言,两者还是有比较大的区别: tap位于网络OSI模型的二层(数据链路层),tun位于网络的三层。本节暂时只介绍tap, tun会在后面的章节专门介绍。
tap从功能定位上来讲,位于数据链路层,数据链路层的主要协议有:
1 )点对点协议( Point-to-PointProtocol) ;
2)以太网(Ethernet) ;
3)高级数据链路协议(High-Level DataLink Protocol) ;
4)帧中继(Frame Relay) ;
5)异步传输模式(Asynchronous TransferMode) 。

但是tap只是与其中一种协议以太网(Ethernet)协议对应。所以,tap有时也称为“虚拟以太设备”。

要想使用Linux命令行操作一个tap,首先Linux得有tun模块(Linux使用tun模块实现了tun/tap),检查方法如下:

modinfo tun

filename:       /lib/modules/3.10.0-862.el7.x86_64/kernel/drivers/net/tun.ko.xz
alias:          devname:net/tun
alias:          char-major-10-200
license:        GPL
author:         (C) 1999-2004 Max Krasnyansky <[email protected]>
description:    Universal TUN/TAP device driver
retpoline:      Y
rhelversion:    7.5
srcversion:     50878D5D5A0138445B25AA8
depends:        
intree:         Y
vermagic:       3.10.0-862.el7.x86_64 SMP mod_unload modversions 
signer:         CentOS Linux kernel signing key
sig_key:        3A:F3:CE:8A:74:69:6E:F1:BD:0F:37:E5:52:62:7B:71:09:E3:2B:96
sig_hashalgo:   sha256

查看是否已经加载

lsmod | grep tun

tun                    31665  1 
ip6_udp_tunnel         12755  1 vxlan
udp_tunnel             14423  1 vxlan

若没有tun出现则敲
modprobe tun

安装tunctl的步骤

(1)先配置对应的yum源

vim /etc/yum.repos.d/nux-misc.repo 

[nux-misc]
name=Nux Misc
baseurl=http://li.nux.ro/download/nux/misc/el7/x86_64/
enabled=0
gpgcheck=1
gpgkey=http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro

(2)安装

yum  --enablerepo=nux-misc install tunctl

(3)创建tap设备

tunctl help

Create: tunctl [-b] [-u owner] [-g group] [-t device-name] [-p|-n] [-f tun-clone-device]
Delete: tunctl -d device-name [-f tun-clone-device]

The default tun clone device is /dev/net/tun - some systems use
/dev/misc/net/tun instead

-b will result in brief output (just the device name)
-n will result in a point-to-point tun device,
-p in an ethernet tap device. Default is a tap,
   except the device contains "tun" in the name.

tunctl -t erfa
Set 'erfa' persistent and owned by uid 0

(4)查看

 ifconfig -a

(5)绑定IP地址并查看

ifconfig erfa 192.168.10.20/24

ip a

1.2 namespace
namespace是Linux虚拟网络的一个重要概念。传统的Linux的许多资源是全局的,比如进程ID资源。而namespace的目的首先就是将这些资源做资源隔离。Linux可以在一个Host内创建许多namespace,于是那些原本是Linux全局的资源,就变成了namespace范围内的“全局”资源,而且不同namespace的资源互相不可见、彼此透明。
Linux具体将哪些全局资源做了隔离呢?看Linux相应的代码最直接、最直观:
在这里插入图片描述
从资源隔离的角度,Linux namespace示意图如下图所示
在这里插入图片描述
上图表明,每个namespace里面将原本是全局资源的进行了隔离,彼此互相不可见。同时在Linux的Host或者VM中,当然也会有一套相关的资源。
单纯从网络的视角来看,一个namespace提供了一份独立的网络协议栈(网络设备接口、IPv4、IPv6、IP路由、防火墙规则、sockets等)。一个设备(Linux Device)只能位于一个namespace中,不同namespace中的设备可以利用veth pair进行桥接(veth pair会在后面进行介绍)。
Linux操作namespace的命令是ip netns。这个命令行的帮助如下:

ip netns help

Usage: ip netns list
       ip netns add NAME
       ip netns set NAME NETNSID
       ip [-all] netns delete [NAME]
       ip netns identify [PID]
       ip netns pids NAME
       ip [-all] netns exec [NAME] cmd ...
       ip netns monitor
       ip netns list-id

(1)创建namespace

ip netns add ns_erfa

[root@controller ~]# ip net list
ns_erfa

(2)把之前创建的虚拟设备erfa迁移到这个namespace里去

ip link set erfa netns ns_erfa

(3 )查看发现虚拟设备erfa消失(因为搬迁到namespace ns_erfa里面去了)

ifconfig a

(4)查看与操作namespace里面的设备

ip [-all] netns exec [NAME] cmd (cmd操作的命令)
ip netns exec ns_erfa ip link list

(5) 在ns_erfa里面执行i

ip netns exec ns_erfa ifconfig -a

(6)绑定ip地址与查看ip地址

ip netns exec ns_erfa ifconfig erfa 192.168.10.60/24 up
ip netns exec ns_erfa ifconfig -a

1.3 veth pair
veth pair 不是设备,而是一对设备,以连接两个虚拟以太端口.操作veth pair需要跟namespace一起配合,不然就没意义。

测试用例

(1)创建veth pair

ip link add tap3 type  veth peer name tap4

(2)创建namespace:ns1 ns2

ip netns add ns1
ip netns add ns2

[root@controller ~]# ip netns list
ns2 (id: 2)
ns1 (id: 1)

(3)把两个tap迁移到对应的namespace中

ip link set tap3 netns ns1
ip link set tap4 netns ns2

(4)给两个tap绑定IP地址

ip netns exec ns1 ifconfig tap3 192.168.10.2/24 up
ip netns exec ns2 ifconfig tap4 192.168.10.3/24 up
查看
ip netns  exec ns1 ifconfig -a
ip netns  exec ns2 ifconfig -a

(5)ping

ip netns exec ns2 ping 192.168.10.2

PING 192.168.10.2 (192.168.10.2) 56(84) bytes of data.
64 bytes from 192.168.10.2: icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from 192.168.10.2: icmp_seq=2 ttl=64 time=0.034 ms
^C
--- 192.168.10.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.034/0.053/0.072/0.019 ms

通过上面的测试用例,我们了解通过veth pair 连接连个namespace的方法,但是如果是3个namespace之间需要互通呢?或者多个namespace之间需要互通呢?veth pair只有一对tap,无法胜任,怎么办?这就需要用到Bridge/Switch
1.4 Bridge
在Linux的语境里,Bridge(网桥)与 Switch(交换机)是一个概念,所以本文也不对二者进行区分。

Linux实现Bridge功能的是brctl模块。

(1)安装 brctl模块

yum install bridge-utils -y

测试用例

(1)创建 veth pair

ip link add tap2 type veth peer name tap3_peer
ip link add tap3 type veth peer name tap2_peer
ip link add tap4 type veth peer name tap2_peer
ip link add tap5 type veth peer name tap2_peer

(2)创建namespace

ip netns add ns1
ip netns add ns2
ip netns add ns3
ip netns add ns4

(3)把tap迁移到namespace中

ip link set tap2 netns ns1
ip link set tap3 netns ns2
ip link set tap4 netns ns3
ip link set tap5 netns ns4

(4)创建Bridge

brctl addbr erfa1

(5)把相应tap添加到Bridge中

brctl addif erfa1 tap2_peer
brctl addif erfa1 tap3_peer
brctl addif erfa1 tap4_peer
brctl addif erfa1 tap5_peer

(6)配置相应tap的ip地址

ip netns exec ns1 ifconfig tap2 192.168.10.31/24 up
ip netns exec ns2 ifconfig tap3 192.168.10.32/24 up
ip netns exec ns3 ifconfig tap4 192.168.10.33/24 up
ip netns exec ns4 ifconfig tap5 192.168.10.34/24 up

(7)将Bridge及所有tap状态设置为up

ip link set erfa1 up
ip link set tap2_peer up
ip link set tap3_peer up
ip link set tap4_peer up
ip link set tap5_peer up

(8)ping

ip netns exec ns1 ping 192.168.10.32
PING 192.168.10.32 (192.168.10.32) 56(84) bytes of data.
64 bytes from 192.168.10.32: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 192.168.10.32: icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from 192.168.10.32: icmp_seq=3 ttl=64 time=0.053 ms
^C
--- 192.168.10.32 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.050/0.053/0.056/0.002 ms

Guess you like

Origin blog.csdn.net/weixin_51788903/article/details/121275411