ovs-vsctl 命令在 OpenvSwitch 中主要用来获取或者更改 ovs-vswitchd的配置信息(如网桥、接口等),此工具操作的时候会更新ovsdb-server中的数据库,本博客主要介绍如何使用 OpenvSwitch ovs-vsctl 命令
基础命令
Open vSwitch commands:
  init                        initialize database, if not yet initialized
  show                        print overview of database contents
  emer-reset                  reset configuration to clean state
Bridge commands
Bridge commands:
  add-br BRIDGE               create a new bridge named BRIDGE
  add-br BRIDGE PARENT VLAN   create new fake BRIDGE in PARENT on VLAN
  del-br BRIDGE               delete BRIDGE and all of its ports
  list-br                     print the names of all the bridges
  br-exists BRIDGE            exit 2 if BRIDGE does not exist
  br-to-vlan BRIDGE           print the VLAN which BRIDGE is on
  br-to-parent BRIDGE         print the parent of BRIDGE
  br-set-external-id BRIDGE KEY VALUE  set KEY on BRIDGE to VALUE
  br-set-external-id BRIDGE KEY  unset KEY on BRIDGE
  br-get-external-id BRIDGE KEY  print value of KEY on BRIDGE
  br-get-external-id BRIDGE  list key-value pairs on BRIDGE
add-br
创建新的网桥(或称为交换机,以下说的网桥均同此意):
$ ovs-vsctl show
9ec2a9f0-73cc-48ad-8395-719979a3f2a9
    ovs_version: "2.11.7"
# # 创建网桥,名称为 br-0,其中 --may-exist 如果网桥 br-0 存在,什么也不做
$ ovs-vsctl add-br br-0
$ ovs-vsctl --may-exist add-br br-0
# 查看网桥
$ ovs-vsctl show
9ec2a9f0-73cc-48ad-8395-719979a3f2a9
    Bridge br-0
        Port br-0
            Interface br-0
                type: internal
    ovs_version: "2.11.7"
# 使用ifconfig查看网桥
$ ifconfig br-0
br-0: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 12:3b:18:dc:85:41  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# 创建 br-0,并将 eth0 加入到 br-0
$ ovs-vsctl add-br br-0 -- add-port br-0 eth0
当创建了一个网桥后:
- 此时网络功能不受影响,但会产生一个虚拟网卡,名字就是网桥的名称(br-0),ovs通过类似的虚拟网卡实现接下来的网桥(交换机)功能
- 有了网桥以后,还需要为该网桥增加端口(port),端口相当于物理网卡,当网卡加入到这个网桥后,其工作方式就和普通交换机的一个端口的工作方式类似
del-br
# 删除网桥 br-0,其中 --if-exists 如果网桥 br-0 不存在,什么也不做
$ ovs-vsctl del-br br-0
$ ovs-vsctl --if-exists del-br br-0
STP (Spanning Tree Protocol)
# 开启 STP
$ ovs-vsctl set bridge br-0 stp_enable=true
# 关闭 STP
$ ovs-vsctl set bridge br-0 stp_enable=false
# 查询 STP 配置信息
$ ovs-vsctl get bridge br-0 stp_enable
# 设置 Priority
$ ovs−vsctl set bridge br-0 other_config:stp-priority=0x7800
$ ovs-vsctl get bridge br-0 other_config
{stp-priority="0x7800"}
# 设置 Cost
$ ovs−vsctl set port eth0 other_config:stp-path-cost=10
$ ovs-vsctl get port eth0 other_config
{stp-path-cost="10"}
# 清楚 STP 设置
$ ovs-vsctl clear bridge br-0 other_config
Openflow Version
# 支持 OpenFlow Version 1.3
$ ovs-vsctl set bridge br-0 protocols=OpenFlow13
$ ovs-vsctl get bridge br-0 protocols
["OpenFlow13"]
# 支持 OpenFlow Version 1.3 1.2
$ ovs-vsctl set bridge br-0 protocols=OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14
# 移除 OpenFlow 支持设置
$ ovs-vsctl clear bridge br-0 protocols
Port commands
Port commands (a bond is considered to be a single port):
  list-ports BRIDGE           print the names of all the ports on BRIDGE
  add-port BRIDGE PORT        add network device PORT to BRIDGE
  add-bond BRIDGE PORT IFACE...  add bonded port PORT in BRIDGE from IFACES
  del-port [BRIDGE] PORT      delete PORT (which may be bonded) from BRIDGE
  port-to-br PORT             print name of bridge that contains PORT
add-prot
$ ovs-vsctl add-port br-0 eth0
$ ovs-vsctl --may-exist add-port br-0 eth0
# 设置端口 p0 的 OpenFlow 端口编号为 100
$ ovs-vsctl add-port br-0 p0 -- set Interface p0 ofport_request=100
del-prot
$ ovs-vsctl del-port br-0 eth0
$ ovs-vsctl --if-exists del-port br-0 eth0
mirrors
# 创建veth
$ ip link add tap2-1 type veth peer name tap2-2
# 在 br-0 上 add-port {eth0,eth1} mirror 至 `tap2-1`
$ ovs-vsctl add-port br-0 eth0
$ ovs-vsctl add-port br-0 eth1
$ ovs-vsctl add-port br-0 tap2-1 \
    -- --id=@p get port tap2-1 \
    -- --id=@m create mirror name=m0 select-all=true output-port=@p \
    -- set bridge br-0 mirrors=@m
# 将 tap2-1/2 up
$ ip link set tap2-1 up
$ ip link set tap2-2 up
# 此时可以在 `tap2-2` 上抓到流量包
# 删除 mirrors
$ ovs-vsctl clear bridge br-0 mirrors
GRE Tunnel
# 设置 GRE Tunnel
$ ovs−vsctl add−port br-0 ovs-gre \
    -- set interface ovs-gre type=gre options:remote_ip=1.2.3.4
# 查询 GRE Tunnel
$ ovs-vsctl show
VLAN
# 设置 VLAN tag
$ ovs-svctl add-port br-0 eth1 tag=3
$ ovs-vsctl add-port br-0 vlan3 tag=3 -- set interface vlan3 type=internal
# 移除 VLAN
$ ovs-vsctl del-port br-0 vlan3
# 查询 VLAN
$ ovs-vsctl show
$ ifconfig vlan3
# 设置 Vlan trunk
$ ovs-vsctl add-port br-0 eth0 trunk=3,4,5,6
# 设置已 add 的 port 为 access port, vlan id 9
$ ovs-vsctl set port eth0 tag=9
# ovs-ofctl add-flow 设置 vlan 100
$ ovs-ofctl add-flow br-0 in_port=1,dl_vlan=0xffff,actions=mod_vlan_vid:100,output:3
$ ovs-ofctl add-flow br-0 in_port=1,dl_vlan=0xffff,actions=push_vlan:0x8100,set_field:100-\>vlan_vid,output:3
# ovs-ofctl add-flow 拿掉 vlan tag
$ ovs-ofctl add-flow br-0 in_port=3,dl_vlan=100,actions=strip_vlan,output:1
# ovs-ofctl add-flow pop-vlan
$ ovs-ofctl add-flow br-0 in_port=3,dl_vlan=0xffff,actions=pop_vlan,output:1
VXLAN
# key=100表示设置vni为100,不设置默认为0
ovs-vsctl add-port br-0 vxlan100 -- set interface vxlan100 type=vxlan options:remote_ip=10.1.1.2 options:key=100
# 不设key值,vni默认为0
ovs-vsctl add-port br-0 vxlan100 -- set interface vxlan100 type=vxlan options:remote_ip=10.1.1.2
# key=flow的话,表示该port的vni可以通过openflow的actions来进行设置,如:
#   actions=set_field:100->tun_id
#   actions=set_tunnel:100
ovs-vsctl add-port br-0 vxlan100 -- set interface vxlan100 type=vxlan options:remote_ip=10.1.1.2 options:key=flow
- 建立 VXLAN Network ID (VNI)和指定的 OpenFlow port number, eg:VNI=5566, OF_PORT=9
ovs-vsctl set interface vxlan type=vxlan option:remote_ip=x.x.x.x option:key=5566 ofport_request=9
ovs-vsctl set interface vxlan type=vxlan option:remote_ip=10.1.1.2 option:key=flow ofport_request=9
ovs-ofctl add-flow br-0 in_port=1,actions=set_field:5566->tun_id,output:2
ovs-ofctl add-flow s1 in_port=2,tun_id=5566,actions=output:1
port type
# 设置 port 设备类型为 internal
$ ovs-vsctl set Interface eth0 type=internal
OpenvSwitch 接口设备类型:
- dpdkvhostuserclient:dpdk vhostuser 类型
- internal:对于 internal类型的的网络接口,OVS会同时在Linux系统中创建一个可以用来收发数据的模拟网络设备
- internal port 可以配置 IP 地址、进行数据监听
 
- patch:OVS里的不同bridge之间可以通过patch port进行连接,类似于 linux 的 veth 接口(Linux Veth Pair 介绍),OpenStack Kilo 版本之前使用veth pair连接2个网桥,因性能考虑 Liberty 开始使用patch连接。优点:
- vm 之间的流表不会因 neutron-openvswitch-agent 重启期间改变
 
- tunnel:使用建立 overlay network 隧道,包括:geneve、gre、vxlan、lisp、stt
创建 patch port 连接两个 bridge:
ovs-vsctl set bridge br-0 datapath_type=netdev
ovs-vsctl add-port br-1 patch-1 -- set Interface patch-1 type=patch -- set Interface patch-1 options:peer=patch-2
ovs-vsctl add-port br-2 patch-2 -- set Interface patch-2 type=patch -- set Interface patch-2 options:peer=patch-1
在 br-0 上创建 port p0,并设置为 internel port,绑定 ip 地址
ovs-vsctl add-br br-0 p0 -- set interface p0 type=internal
ip addr add 10.1.1.10/24 dev p0
- 创建 VLAN=10 的 internal access port
ovs-vsctl add-br br-0 p0 tag=10 -- set interface p0 type=internal
ip addr add 10.1.1.20/24 dev p0
OpenFlow port id
将 eth0 的 OpenFlow 端口设置为 100
# 更改 ofport (openflow port number)为100
$ ovs-vsctl set interface eth0 ofport_request=100
$ ovs-vsctl add-port br-0 eth0 -- set Interface eth0 ofport_request=100
说明:
- openflow port number 在 OpenFlow flow entry 的 in_port和 actions 的output时会用到
Interface commands
Interface commands (a bond consists of multiple interfaces):
  list-ifaces BRIDGE          print the names of all interfaces on BRIDGE
  iface-to-br IFACE           print name of bridge that contains IFACE
list-ifaces
# 查看某个 br 的 interfaces
$ ovs-vsctl list-ifaces br-0
tap1-1
tap2-1
iface-to-br
# 根据 interface-name 查看所属的网桥
$ ovs-vsctl iface-to-br tap1-1
br-0
Controller commands
说明:SDN 控制器有很多本文以 ODL 为例,安装部署见:Linux 安装 OpenDayLight
Controller commands:
  get-controller BRIDGE      print the controllers for BRIDGE
  del-controller BRIDGE      delete the controllers for BRIDGE
  [--inactivity-probe=MSECS]
  set-controller BRIDGE TARGET...  set the controllers for BRIDGE
  get-fail-mode BRIDGE       print the fail-mode for BRIDGE
  del-fail-mode BRIDGE       delete the fail-mode for BRIDGE
  set-fail-mode BRIDGE MODE  set the fail-mode for BRIDGE to MODE
get/set/del-controller
  
      
          | Listener Type | 参数 | 示例 | 
  
  
      
          | Active:主动模式 | tcp | tcp:1.2.3.4:6633 | 
      
          | Passive:被动模式 | ptcp | ptcp:6633 | 
  
# 获取指定 bridge 的 controller
$ ovs-vsctl get-controller br-0
# 设置 Controller
$ ovs-vsctl set-controller br-0 tcp:127.0.0.1:6633
# 设置多个 controller
$ ovs-vsctl set-controller br-0 tcp:1.2.3.4:6633 tcp:1.2.3.4:6633
# 使用 unix socket
$ ovs-vsctl set-controller br-0 unix:/var/run/xx/xx.sock
# 如果有成功连到 controller 则提示 is_connected:true, 反之未连上:
$ ovs-vsctl show
16c611da-53e3-41a6-adcd-29479c8bf774
    Bridge "br-0"
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        Port "br-0"
            Interface "br-0"
                type: internal
    ovs_version: "2.12.3"
$ ovs-vsctl get-controller br-0
tcp:127.0.0.1:6633
# 删除 Controller
$ ovs-vsctl del-controller br-0
get/set/del-fail-mode
OpenvSwitch 有两中故障模式(fail modes):
- Standalone:在孤立模式(默认)下,ovs只是作为一个 learning switch
- Secure:安全模式的不同之处在于它依赖于 控制器来插入流规则
# 设置为 standalone mode
$ ovs-vsctl set-fail-mode br-0 standalone
$ ovs-vsctl show
16c611da-53e3-41a6-adcd-29479c8bf774
    Bridge "br-0"
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: standalone
...
# 设置为 secure mode
$ ovs-vsctl set-fail-mode br-0 secure
$ ovs-vsctl show
16c611da-53e3-41a6-adcd-29479c8bf774
    Bridge "br-0"
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
...
# 查询 fail mode
$ ovs-vsctl get-fail-mode br-0
secure
# 删除 fail mode
$ ovs-vsctl del-fail-mode br-0
Manager commands
说明:SDN 控制器有很多本文以 ODL 为例,安装部署见:Linux 安装 OpenDayLight
Manager commands:
  get-manager                print the managers
  del-manager                delete the managers
  [--inactivity-probe=MSECS]
  set-manager TARGET...      set the list of managers to TARGET...
get/set/del-manager
  
      
          | Listener Type | 参数 | 示例 | 
  
  
      
          | Active:主动模式 | tcp | tcp:1.2.3.4:6640 | 
      
          | Passive:被动模式 | ptcp | ptcp:6640 | 
  
# 设置 manager 主动模式
$ ovs-vsctl set-manager tcp:127.0.0.1:6640
$ ovs-vsctl show
16c611da-53e3-41a6-adcd-29479c8bf774
    Manager "tcp:127.0.0.1:6640"
        is_connected: true
    Bridge "br-0"
...
# 查看 manager
$ ovs-vsctl get-manager
tcp:127.0.0.1:6640
# 删除 manager
$ ovs-vsctl del-manager
# 被动模式
$ ovs-vsctl set-manager ptcp:6640
SSL commands
SSL commands:
  get-ssl                     print the SSL configuration
  del-ssl                     delete the SSL configuration
  set-ssl PRIV-KEY CERT CA-CERT  set the SSL configuration
get/set/del-ssl
# 设置
$ ovs-vsctl set-ssl privkey.pem cert.pem cacert.pem
# 查询
$ ovs-vsctl get-ssl
$ 刪除
ovs-vsctl del-ssl
Auto Attach commands
Auto Attach commands:
  add-aa-mapping BRIDGE I-SID VLAN   add Auto Attach mapping to BRIDGE
  del-aa-mapping BRIDGE I-SID VLAN   delete Auto Attach mapping VLAN from BRIDGE
  get-aa-mapping BRIDGE              get Auto Attach mappings from BRIDGE
Switch commands
Switch commands:
  emer-reset                  reset switch to known good state
Database commands
Database commands:
  list TBL [REC]              list RECord (or all records) in TBL
  find TBL CONDITION...       list records satisfying CONDITION in TBL
  get TBL REC COL[:KEY]       print values of COLumns in RECord in TBL
  set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL
  add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL
  remove TBL REC COL [KEY=]VALUE  remove (KEY=)VALUE from COLumn
  clear TBL REC COL           clear values from COLumn in RECord in TBL
  create TBL COL[:KEY]=VALUE  create and initialize new record
  destroy TBL REC             delete RECord from TBL
  wait-until TBL REC [COL[:KEY]=VALUE]  wait until condition is true
Potentially unsafe database commands require --force option.
Database commands may reference a row in each table in the following ways:
  AutoAttach:
    by UUID
    via "auto_attach" of Bridge with matching "name"
  Bridge:
    by UUID
    by "name"
  Controller:
    by UUID
    via "controller" of Bridge with matching "name"
  Flow_Sample_Collector_Set:
    by UUID
    by "id"
  Flow_Table:
    by UUID
    by "name"
  IPFIX:
    by UUID
    via "ipfix" of Bridge with matching "name"
  Interface:
    by UUID
    by "name"
  Manager:
    by UUID
    by "target"
  Mirror:
    by UUID
    by "name"
  NetFlow:
    by UUID
    via "netflow" of Bridge with matching "name"
  Open_vSwitch:
    by UUID
    as "."
  Port:
    by UUID
    by "name"
  QoS:
    by UUID
    via "qos" of Port with matching "name"
  Queue:
    by UUID
  SSL:
    by UUID
    as "."
  sFlow:
    by UUID
    via "sflow" of Bridge with matching "name"
list-Bridge/Port/Interface
通过 list 命令,可以查看到对应设备的详细配置信息
ovs-vsctl list Bridge/Port/Interface/...
# demo
ovs-vsctl list bridge
ovs-vsctl list bridge <bridge-name>
ovs-vsctl list port
ovs-vsctl list port <port-name>  # 若是 OpenStack 可以通过 other_config 查看到 net_uuid、network_type、physical_network、tag 等信息
ovs-vsctl list interface
ovs-vsctl list interface <interface-name>  # 若是 OpenStack 可以通过 external_ids:vm-uuid 查看到 vm 的 uuid
list-sFlow
# 查询
ovs-vsctl list sflow
# 新增
ovs-vsctl set sFlow xxx
# 刪除
ovs-vsctl -- clear Bridge br-0 sflow
list-NetFlow
# 查询
ovs-vsctl list netflow
# 新增
ovs-vsctl set NetFlow 缺
# 刪除
ovs-vsctl -- clear Bridge br-0 netflow
list-Open_vSwitch
$ ovs-vsctl list open_vswitch
_uuid               : 16c611da-53e3-41a6-adcd-29479c8bf774
bridges             : [8ec70a70-bdd2-43e9-bd61-bad61512ea2e]
cur_cfg             : 29
datapath_types      : [netdev, system]
db_version          : "8.0.0"
dpdk_initialized    : false
dpdk_version        : "DPDK 18.11.11"
external_ids        : {hostname=dpdk, rundir="/var/run/openvswitch", system-id="e616ea61-511b-47fd-bc9f-ec2ea6657ef7"}
iface_types         : [erspan, geneve, gre, internal, "ip6erspan", "ip6gre", lisp, patch, stt, system, tap, vxlan]
manager_options     : []
next_cfg            : 29
other_config        : {}  # dpdk 的配置会在 other_config 中
ovs_version         : "2.12.3"
ssl                 : []
statistics          : {}
system_type         : centos
system_version      : "7"
get/set
# 查询
ovs-vsctl get controller br-0 connection-mode
# set
ovs-vsctl set controller br-0 connection-mode=out-of-band
ovs-vsctl set controller br-0 connection-mode=in-band
# 删除 hidden flow
ovs-vsctl set bridge br-0 other-config:disable-in-band=true
# 设置数据路径
ovs-vsctl set bridge br-0 datapath_type=netdev
find
ovs-vsctl find interface external_ids:vm-uuid=<vm-uuid>
FAQ
ovs创建port报错
$ ovs-vsctl add-port br-0 eth0
ovs-vsctl: Error detected while setting up 'eth0': could not open network device eth0 (No such device).  See ovs-vswitchd log for details.
ovs-vsctl: The default log directory is "/var/log/openvswitch".
$ ovs-vsctl show
9ec2a9f0-73cc-48ad-8395-719979a3f2a9
    Bridge "br-0"
        Port "eth0"
            Interface "eth0"
                error: "could not open network device eth0 (No such device)"
        Port "ens33"
            Interface "ens33"
        Port "br-0"
            Interface "br-0"
                type: internal
    ovs_version: "2.11.7"
使用ip tuntap add mod tap eth0创建虚拟设备
$ ovs-vsctl del-port br-0 eth0
$ ip tuntap add mod tap eth0
ioctl(TUNSETIFF): Device or resource busy
$ ovs-vsctl add-port br-0 eth0
$ ovs-vsctl show
9ec2a9f0-73cc-48ad-8395-719979a3f2a9
    Bridge "br-0"
        Port "eth0"
            Interface "eth0"
        Port "ens33"
            Interface "ens33"
        Port "br-0"
            Interface "br-0"
                type: internal
    ovs_version: "2.11.7"