openvswitch基础
openvswitch基础
基础命令
# 1 创建网桥 [root@vm180 ~]# ovs-vsctl add-br br0 # 2.1 创建内部接口port1 [root@vm180 ~]# ovs-vsctl add-port br0 port1 -- set interface port1 type=internal # 2.2 创建成功后会在系统产生一个对应的网络接口port1 [root@vm180 ~]# ip link ... 16: port1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether ca:d0:b7:fc:64:d7 brd ff:ff:ff:ff:ff:ff # 3 将系统网络接口(eth1)加入到网桥中 [root@vm180 ~]# ovs-vsctl add-port br0 eth1 # 4.1 创建patch port(类似于veth pair),用于连接两个ovs网桥,在网桥br0上创建patch port [root@vm180 ~]# ovs-vsctl add-port br0 patch-eb4c163-a -- set interface patch-eb4c163-a type=patch options:peer=patch-eb4c163-b # 4.2 在网桥br1上创建patch port [root@vm180 ~]# ovs-vsctl add-port br1 patch-eb4c163-b -- set interface patch-eb4c163-b type=patch options:peer=patch-eb4c163-a # 4.3 查看patch port [root@vm180 ~]# ovs-vsctl show f22b449d-96ff-4a7c-ab99-bc488bfecb05 Bridge "br0" Port "tap0" interface "tap0" type: internal Port "br0" interface "br0" type: internal Port "patch-eb4c163-a" interface "patch-eb4c163-a" type: patch options: {peer="patch-eb4c163-b"} Bridge "br1" Port "tap1" interface "tap1" type: internal Port "patch-eb4c163-b" interface "patch-eb4c163-b" type: patch options: {peer="patch-eb4c163-a"} Port "br1" interface "br1" type: internal ovs_version: "2.5.6" # 5.1 在vm180上创建vxlan0接口,指定VNI为100 [root@vm180 ~]# ovs-vsctl add-port br0 vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=192.144.60.181 options:key=100 # 5.2 在vm181上创建vxlan0接口,指定VNI为100 [root@vm181 ~]# ovs-vsctl add-port br0 vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=192.144.60.180 options:key=100 # 6.1 设置端口的tag(vlan id) [root@vm180 ~]# ovs-vsctl set port <port> tag=<tag-id> # 6.2 清除端口的tag(vlan id) [root@vm180 ~]# ovs-vsctl clear port <port> tag
流表命令
# 查看网桥br0上的流表 [root@vm181 ~]# ovs-ofctl dump-flows br0 NXST_FLOW reply (xid=0x4): cookie=0x0, duration=49275.418s, table=0, n_packets=22400, n_bytes=5299127, idle_age=12, priority=0 actions=NORMAL # 查看port的ofport,常用于匹配项in_port,和动作output的参数 [root@vm181 ~]# ovs-vsctl list interface tap0 _uuid : 5ab1ac08-fba5-4c6c-a48e-0dec5e0bc808 admin_state : up bfd : {} bfd_status : {} cfm_fault : [] cfm_fault_status : [] cfm_flap_count : [] cfm_health : [] cfm_mpid : [] cfm_remote_mpids : [] cfm_remote_opstate : [] duplex : [] error : [] external_ids : {} ifindex : 6 ingress_policing_burst: 0 ingress_policing_rate: 0 lacp_current : [] link_resets : 1 link_speed : [] link_state : up lldp : {} mac : [] mac_in_use : "8e:10:e3:4b:ff:4f" mtu : 1500 name : "tap0" ofport : 2 ofport_request : [] options : {} other_config : {} statistics : {collisions=0, rx_bytes=206024, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=2580, tx_bytes=5086470, tx_dropped=0, tx_errors=0, tx_packets=19925} status : {driver_name=openvswitch} type : internal 或者 [root@vm181 ~]# ovs-ofctl show br0 OFPT_FEATURES_REPLY (xid=0x2): dpid:0000f6c9e8e36e4a n_tables:254, n_buffers:256 capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst 2(tap0): addr:8e:10:e3:4b:ff:4f config: 0 state: 0 speed: 0 Mbps now, 0 Mbps max 8(vxlan1): addr:fe:cd:6c:ac:d6:d5 config: 0 state: 0 speed: 0 Mbps now, 0 Mbps max 9(vxlan0): addr:c6:d0:85:7e:ca:63 config: 0 state: 0 speed: 0 Mbps now, 0 Mbps max LOCAL(br0): addr:f6:c9:e8:e3:6e:4a config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0 # 查看网桥的fdb表 [root@vm181 ~]# ovs-appctl fdb/show br0 port VLAN MAC Age 2 0 8e:10:e3:4b:ff:4f 0
OVS实战
vlan
# 创建三台主机 [root@vm181 ~]# ip netns add vm0 [root@vm181 ~]# ip netns add vm1 [root@vm181 ~]# ip netns add vm2 # 在br0上创建tap0并接入到vm0中 [root@vm181 ~]# ovs-vsctl add-port br0 tap0 -- set interface tap0 type=internal [root@vm181 ~]# ip link set tap0 netns vm0 # 进入vm0设置ip [root@vm181 ~]# netns=vm0; ip netns exec ${netns} bash --rcfile <(echo "PS1=\"${netns}$ \"") vm0$ ip addr add 172.16.0.100/24 dev tap0 vm0$ ip link set tap0 up vm0$ ip link set lo up vm0$ ip addr ... 14: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000 link/ether 42:cb:85:b8:bf:2a brd ff:ff:ff:ff:ff:ff inet 172.16.0.100/24 scope global tap0 valid_lft forever preferred_lft forever inet6 fe80::40cb:85ff:feb8:bf2a/64 scope link valid_lft forever preferred_lft forever vm0$ exit # 在br0上创建tap1并接入到vm1中 [root@vm181 ~]# ovs-vsctl add-port br0 tap1 -- set interface tap1 type=internal [root@vm181 ~]# ip link set tap1 netns vm1 # 进入vm1设置ip [root@vm181 ~]# netns=vm1; ip netns exec ${netns} bash --rcfile <(echo "PS1=\"${netns}$ \"") vm1$ ip addr add 172.16.0.101/24 dev tap1 vm1$ ip link set tap1 up vm1$ ip link set lo up vm1$ ip addr ... 15: tap1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000 link/ether 82:86:1f:c6:d3:8a brd ff:ff:ff:ff:ff:ff inet 172.16.0.101/24 scope global tap1 valid_lft forever preferred_lft forever inet6 fe80::8086:1fff:fec6:d38a/64 scope link valid_lft forever preferred_lft forever vm1$ exit # 在br0上创建tap2并接入到vm2中 [root@vm181 ~]# ovs-vsctl add-port br0 tap2 -- set interface tap2 type=internal [root@vm181 ~]# ip link set tap2 netns vm2 # 进入vm2设置ip [root@vm181 ~]# netns=vm2; ip netns exec ${netns} bash --rcfile <(echo "PS1=\"${netns}$ \"") vm2$ ip addr add 172.16.0.102/24 dev tap2 vm2$ ip link set tap2 up vm2$ ip link set lo up vm2$ ip addr ... 16: tap2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000 link/ether 56:0b:aa:c1:91:8d brd ff:ff:ff:ff:ff:ff inet 172.16.0.102/24 scope global tap2 valid_lft forever preferred_lft forever inet6 fe80::540b:aaff:fec1:918d/64 scope link valid_lft forever preferred_lft forever vm2$ exit # 将tap0、tap1和tap2加入到vlan100中 [root@vm181 ~]# ovs-vsctl set port tap0 vlan tag=100 [root@vm181 ~]# ovs-vsctl set port tap1 vlan tag=100 [root@vm181 ~]# ovs-vsctl set port tap2 vlan tag=100 [root@vm181 ~]# ovs-vsctl show a2341c69-656c-477f-bf5e-d922ceffc6b8 Bridge "br0" Port "tap0" tag: 100 Interface "tap0" type: internal Port "br0" Interface "br0" type: internal Port "tap2" tag: 100 Interface "tap2" type: internal Port "tap1" tag: 100 Interface "tap1" type: internal ovs_version: "2.5.6" # 连通性检查vm0 -> vm1和vm2 vm0$ ping 172.16.0.101 PING 172.16.0.101 (172.16.0.101) 56(84) bytes of data. 64 bytes from 172.16.0.101: icmp_seq=1 ttl=64 time=0.188 ms vm0$ ping 172.16.0.102 PING 172.16.0.102 (172.16.0.102) 56(84) bytes of data. 64 bytes from 172.16.0.102: icmp_seq=1 ttl=64 time=0.041 ms # 将tap3加入到vlan101中 [root@vm181 ~]# ovs-vsctl set port tap2 tag=101 [root@vm181 ~]# ovs-vsctl show a2341c69-656c-477f-bf5e-d922ceffc6b8 Bridge "br0" Port "tap0" tag: 100 Interface "tap0" type: internal Port "br0" Interface "br0" type: internal Port "tap2" tag: 101 Interface "tap2" type: internal Port "tap1" tag: 100 Interface "tap1" type: internal ovs_version: "2.5.6" # 连通性检查,vm0 -> vm1:通,vm0 -> vm2:不通 vm0$ ping 172.16.0.101 PING 172.16.0.101 (172.16.0.101) 56(84) bytes of data. 64 bytes from 172.16.0.101: icmp_seq=1 ttl=64 time=0.200 ms vm0$ ping 172.16.0.102 PING 172.16.0.102 (172.16.0.102) 56(84) bytes of data. From 172.16.0.100 icmp_seq=10 Destination Host Unreachable
防火墙
实验环境:vm0和vm1,在br0上配置防护策略。
防护策略:
默认丢弃所有包
开通vm0的tcp 22端口
# 在vm0上开启tcp服务,监听22端口 vm0$ nc -k -lp 22 # 清空br0上的流表 [root@vm181 ~]# ovs-ofctl del-flows br0 # 在vm1上连接vm0的22端口 vm1$ nc -v 172.16.0.100 22 Ncat: Version 6.40 ( http://nmap.org/ncat ) Ncat: Connection timed out. # 开启br0的arp功能 [root@vm181 ~]# ovs-ofctl add-flow br0 arp,actions=normal # 在br0上添加流表,开通vm0的tcp 22端口 [root@vm181 ~]# ovs-ofctl add-flow br0 nw_dst=172.16.0.100/24,tcp,tp_dst=22,actions=NORMAL [root@vm181 ~]# ovs-ofctl add-flow br0 nw_src=172.16.0.100/24,tcp,tp_src=22,actions=NORMAL # 查看流表 [root@vm181 ~]# ovs-ofctl dump-flows br0 NXST_FLOW reply (xid=0x4): cookie=0x0, duration=70.116s, table=0, n_packets=2, n_bytes=84, idle_age=12, arp actions=NORMAL cookie=0x0, duration=38.510s, table=0, n_packets=4, n_bytes=288, idle_age=14, tcp,nw_dst=172.16.0.0/24,tp_dst=22 actions=NORMAL cookie=0x0, duration=15.212s, table=0, n_packets=1, n_bytes=74, idle_age=14, tcp,nw_src=172.16.0.0/24,tp_src=22 actions=NORMAL # 连通性测试 vm1$ nc -v 172.16.0.100 22 Ncat: Version 6.40 ( http://nmap.org/ncat ) Ncat: Connected to 172.16.0.100:22.
NAT
# 重置br0上的流表 [root@vm181 ~]# ovs-ofctl del-flows br0 [root@vm181 ~]# ovs-ofctl add-flow br0 actions=NORMAL # 创建vm3 [root@vm181 ~]# ip netns add vm3 # 创建br-nat网桥 [root@vm181 ~]# ovs-vsctl add-br br-nat # 在br-nat上创建接口并连接到vm3上 [root@vm181 ~]# ovs-vsctl add-port br-nat tap3 -- set interface tap3 type=internal [root@vm181 ~]# ip link set tap3 netns vm3 # 进入vm3配置接口ip [root@vm181 ~]# netns=vm3; ip netns exec ${netns} bash --rcfile <(echo "PS1=\"${netns}$ \"") vm3$ vm3$ ip addr add 203.0.1.101/24 dev tap3 vm3$ ip link set tap3 up vm3$ ip link set lo up vm3$ ip addr ... 19: tap3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000 link/ether 4a:74:91:ef:00:a6 brd ff:ff:ff:ff:ff:ff inet 203.0.1.101/24 scope global tap3 valid_lft forever preferred_lft forever inet6 fe80::4874:91ff:feef:a6/64 scope link valid_lft forever preferred_lft forever # 连接br0和br-nat [root@vm181 ~]# ovs-vsctl add-port br0 patch-nat-a -- set interface patch-nat-a type=patch options:peer=patch-nat-b [root@vm181 ~]# ovs-vsctl add-port br-nat patch-nat-b -- set interface patch-nat-b type=patch options:peer=patch-nat-a [root@vm181 ~]# [root@vm181 ~]# ovs-vsctl show a2341c69-656c-477f-bf5e-d922ceffc6b8 Bridge br-nat Port br-nat Interface br-nat type: internal Port patch-nat-b Interface patch-nat-b type: patch options: {peer=patch-nat-a} ... Bridge "br0" Port "br0" Interface "br0" type: internal Port patch-nat-a Interface patch-nat-a type: patch options: {peer=patch-nat-b} ... ovs_version: "2.5.6"
vxlan
静态隧道
[root@vm180 ~]# ovs-vsctl add-port br-tun vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=192.144.60.181 options:key=1000 [root@vm180 ~]# ovs-vsctl show f22b449d-96ff-4a7c-ab99-bc488bfecb05 Bridge br-tun Port "p2" tag: 101 Interface "p2" type: internal Port "vxlan0" Interface "vxlan0" type: vxlan options: {key="1000", remote_ip="192.144.60.181"} Port "p1" tag: 100 Interface "p1" type: internal Port br-tun Interface br-tun type: internal ovs_version: "2.5.6" [root@vm181 ~]# ovs-vsctl add-port br-tun vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=192.144.60.180 options:key=1000 [root@vm181 ~]# ovs-vsctl show a2341c69-656c-477f-bf5e-d922ceffc6b8 Bridge br-tun Port "p2" tag: 101 Interface "p2" type: internal Port br-tun Interface br-tun type: internal Port "vxlan0" Interface "vxlan0" type: vxlan options: {key="1000", remote_ip="192.144.60.180"} Port "p1" tag: 100 Interface "p1" type: internal ovs_version: "2.5.6" [root@vm181 ~]# ping 10.0.0.101 PING 10.0.0.101 (10.0.0.101) 56(84) bytes of data. 64 bytes from 10.0.0.101: icmp_seq=1 ttl=64 time=0.504 ms 64 bytes from 10.0.0.101: icmp_seq=2 ttl=64 time=0.206 ms
动态隧道
# 设置vxlan端口 [root@vm180 ~]# ovs-vsctl add-port br-tun vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=flow options:key=flow [root@vm181 ~]# ovs-vsctl add-port br-tun vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=flow options:key=flow # 设置流表 [root@vm180 ~]# ovs-ofctl add-flow br-tun "dl_vlan=100,actions=set_tunnel:1000,set_field:192.144.60.181->tun_dst,NORMAL" [root@vm181 ~]# ovs-ofctl add-flow br-tun "in_port=2,actions=load:1000->NXM_NX_TUN_ID[],set_field:192.144.60.180->tun_dst,NORMAL" [root@vm181 ~]# ping 10.0.0.101 PING 10.0.0.101 (10.0.0.101) 56(84) bytes of data. 64 bytes from 10.0.0.101: icmp_seq=1 ttl=64 time=0.454 ms 64 bytes from 10.0.0.101: icmp_seq=2 ttl=64 time=0.113 ms
动态隧道的建立需要设置相应的流表,从数据包匹配的流表中提取目标vtep的地址。
Openvswitch Tunnel TLV
tunnel tlv(type、length和value)是一个网桥的元数据(key、value形式),可以用于标记/分类一个网桥,并用在流表匹配、action等中。流表中通过tun_metadatan对元数据进行读取,如下:
ovs-ofctl add-tlv-map br0 "{class=0xffff,type=0,len=4}->tun_metadata0" ovs-ofctl add-flow br0 tun_metadata0=1234,actions=controller
http://www.openvswitch.org/support/dist-docs-2.5/ovs-ofctl.8.html
分片模式
normal(默认):和为分片的报文段一样通过流表,TCP、UDP端口和ICMP类型、code字段总是被置0,即使是分片中的第一个报文段(offset等于0)。
nx-match:和为分片的报文段一样通过流表,对于分片中的第一个报文段(offset等于0)TCP、UDP端口和ICMP类型、code字段 可用的,但是其他分片(offset不等于0)的这些字段总是被置0。
流语法/匹配字段
dl_vlan_pcp : 3bit,Priority Code Point (PCP),指定帧的优先级0~7,数值越大优先级越高
dl_type:数据链路层协议(如Ethernet)中封装的协议类型,即以太类型。
arp_spa:source ip address
arp_tpa:target ip address
dl_*:data link layer
nw_*:network layer
ip:dl_type=0x0800
arp:dl_type=0806
nw_proto/ip_proto:网络层协议中封装的协议类型,即IP协议。
tun_id:vni
tun_src/tun_dst:隧道端点的IPv4地址
action
set_tunnel: id
move:src[start..end]−>dst[start..end] 拷贝,src和dst字段必须是NXM字段(nicira-ext.h)
set_field:00:11:22:33:44:55->eth_src 等效于 load:0x001122334455->OXM_OF_ETH_DST[]
ecmp
ovs-ofctl add-group br0 group_id=1,type=select,bucket=output:2,bucket=output:3 ovs-ofctl add-flow br0 dl_type=0x0800,nw_src=192.168.1.0/24,actions=group:1
用户态vxlan
ovs-vsctl set bridge br0 datapath_type=netdev datapath_type:
system表示内核数据通路。
netdev表示用户态数据通路
https://github.com/openvswitch/ovs/blob/master/Documentation/intro/install/userspace.rst
http://docs.openvswitch.org/en/latest/howto/userspace-tunneling/
- 点赞
- 收藏
- 关注作者
评论(0)