OpenvSwitch

 ovs概述

Open vSwitch 概述;OVS支持的功能;ovs的模块介绍(ovs-vswitchd、ovsdb-server等等)
===========================================================================================================
Open vSwitch 概述
Open vSwitch(下面简称为 OVS)是由 Nicira Networks 主导的,运行在虚拟化平台(例如 KVM,Xen)上的虚拟交换机。在虚拟化平台上,OVS 可以为动态变化的端点提供 2 层交换功能,很好的控制虚拟网络中的访问策略、网络隔离、流量监控等等。
OVS 遵循 Apache 2.0 许可证, 能同时支持多种标准的管理接口和协议。OVS 也提供了对 OpenFlow 协议的支持,用户可以使用任何支持 OpenFlow 协议的控制器对 OVS 进行远程管理控制。

----------------------------------------------------------------------------------------------------------
OVS支持的功能
    支持NetFlow、sFlow(R)、IPFIX、SPAN、RSPAN和GRE隧道镜像等多种流量监控协议
    支持LACP (IEEE 802.1AX-2008)
    支持标准802.1Q VLAN协议,允许端口配置trunk模式
    支持组播
    支持BFD和802.1ag链路监控
    支持STP(IEEE 802.1D-1998)和RSTP(IEEE 802.1D-2004)
    支持细粒度的QoS(服务质量)配置
    支持HFSC qdisc
    支持接管每一个虚拟机的流量
    支持基于源MAC的负载均衡、主备模式和L4哈希的端口绑带
    支持OpenFlow协议(包含了很多对虚拟化的扩展)
    支持IPv6
    支持多种隧道协议(GRE、VXLAN、STT、Geneve和IPsec)
    支持C和Python的远程配置协议
    支持内核和用户空间的转发引擎选项
    具有流缓存引擎的多表转发管道
    转发层抽象以简化向新软件和硬件平台的移植

----------------------------------------------------------------------------------------------------------
ovs的模块介绍
当前最新代码包主要包括以下模块和特性:
    ovs-vswitchd        主要模块,实现switch的daemon,包括一个支持流交换的Linux内核模块;
    ovsdb-server        轻量级数据库服务器,提供ovs-vswitchd获取配置信息;
    ovs-brcompatd       让ovs-vswitch替换Linux bridge,包括获取bridge ioctls的Linux内核模块;
    ovs-dpctl           用来配置switch内核模块;
    一些Scripts and specs 辅助OVS安装在Citrix XenServer上,作为默认switch;
    ovs-vsctl           查询和更新ovs-vswitchd的配置;
    ovs-appctl          发送命令消息,运行相关daemon;
    ovsdbmonitor        GUI工具,可以远程获取OVS数据库和OpenFlow的流表。
此外,OVS也提供了支持OpenFlow的特性实现,包括
    ovs-openflowd:     一个简单的OpenFlow交换机;
    ovs-controller:    一个简单的OpenFlow控制器;
    ovs-ofctl           查询和控制OpenFlow交换机和控制器;
    ovs-pki :          OpenFlow交换机创建和管理公钥框架;
    ovs-tcpundump:     tcpdump的补丁,解析OpenFlow的消息;


OpenvSwitch 包含很多的模块,在用户态有两个重要的进程,也有两个重要的命令行工具。
    第一个进程是 OVSDB 进程。ovs-vsctl 命令行会和这个进程通信,去创建虚拟交换机,创建端口,将端口添加到虚拟交换机上,OVSDB 会将这些拓扑信息保存在一个本地的文件中。
    第二个进程是 vswitchd 进程。ovs-ofctl 命令行会和这个进程通信,去下发流表规则,规则里面会规定如何对网络包进行处理,vswitchd 会将流表放在用户态 Flow Table 中。
Open vSwitch 概述;OVS支持的功能;ovs的模块介绍(ovs-vswitchd、ovsdb-server等等)

 

OVS的术语解释:Bridge、Port(Normal、Internal、Patch、Tunnel)、Interface、Controller、Flow、datapath
====================================================================================================================
Bridge
    中文名称网桥,一个Bridge代表一个以太网交换机(Switch),一台主机中可以创建一个或多个Bridge,Bridge可以根据一定的规则,把某一个端口接收到的数据报文转发到另一个或多个端口上,也可以修改或者丢弃数据报文。

--------------------------------------------------------------
Port
    中文名称端口,需要注意的是它和TCP里面的端口不是同样的概念,它更像是物理交换机上面的插口,可以接水晶头的那种。Port隶属于Bridge,必须先添加了Bridge才能在Bridge上添加Port。Port有以下几种类型:
    Normal
        用户可以把操作系统中已有的网卡添加到Open vSwicth上,Open vSwitct会自动生成一个同名的Port开处理这张网卡进和出的数据报文。
            不过需要注意的是这种方式添加的Port不支持分配IP地址,如果之前网卡上配置的有IP,挂载到OVS上面之后将不可访问。此类型的Port常用于VLAN模式的多台物理主机相连的那个口,交换机一端属于Trunk模式。
    Internal
        当Port的类型是Internal时,OVS会自动创建一个虚拟网卡(Interface),此端口收到的数据报文都会转发给这块网卡,从这块网卡发出的数据报文也会通过Port交给OVS处理。当OVS创建一个新的网桥时,会自动创建一个与网桥同名的Internal Port,同时也会创建一个与网桥同名的Interface,因此可以通过ip命令在操作系统中查看到这张虚拟网卡,但是状态是down的。
    Patch
        Patch Port和veth pair功能相同,总是成双成对的出现,在其中一端收到的数据报文会被转发到另一个Patch Port上,就像是一根网线一样。Patch Port常用于连接两个Bridge,这样两个网桥就和一个网桥一样了。
    Tunnel
        OVS 支持 GRE、VXLAN、STT、Geneve和IPsec隧道协议,这些隧道协议就是overlay网络的基础协议,通过对物理网络做的一层封装和扩展,解决了二层网络数量不足的问题,最大限度的减少对底层物理网络拓扑的依赖性,同时也最大限度的增加了对网络的控制。

--------------------------------------------------------------
Interface
    (iface/接口)接口是OVS与操作系统交换数据报文的组件,一个接口即是操作系统上的一块网卡,这个网卡可能是OVS生成的虚拟网卡,也有可能是挂载在OVS上的物理网卡,操作系统上的虚拟网卡(TUN/TAP)也可以被挂载在OVS上。
        连接到 Port 的网络接口设备。在通常情况下,Port 和 Interface 是一对一的关系, 只有在配置 Port 为 bond 模式后,Port 和 Interface 是一对多的关系。
        
--------------------------------------------------------------
Controller
    OpenFlow控制器,OVS可以接收一个或者多个OpenFlow控制器的管理,功能主要是下发流表,控制转发规则。

--------------------------------------------------------------
Flow
    流表是OVS进行数据转发的核心功能,定义了端口之间转发数据报文的规则,一条流表规则主要分为匹配和动作两部分,匹配部分决定哪些数据报文需要被处理,动作决定了匹配到的数据报文该如何处理。
    每个 datapath 都和一个“flow table”关联,当 datapath 接收到数据之后, OVS 会在 flow table 中查找可以匹配的 flow,执行对应的操作, 例如转发数据到另外的端口。
--------------------------------------------------------------
datapath
    在 OVS 中,datapath 负责执行数据交换,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。
OVS的术语解释:Bridge、Port(Normal、Internal、Patch、Tunnel)、Interface、Controller、Flow、datapath

 

安装OpenvSwitch
====================================================================================================================
方式一
https://blog.csdn.net/qq_21127151/article/details/124262331
设置系统环境
    sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
    setenforce 0
    systemctl stop firewalld.service
    systemctl disable firewalld.service

安装环境依赖
    yum install -y python-six selinux-policy-devel gcc make python-devel openssl-devel kernel-devel graphviz kernel-debug-devel autoconf automake rpm-build redhat-rpm-config libtool wget net-tools

安装OpenvSwitch
    wget http://openvswitch.org/releases/openvswitch-2.5.4.tar.gz
    mkdir -p /root/rpmbuild/SOURCES
    cp openvswitch-2.5.4.tar.gz /root/rpmbuild/SOURCES/;cd /root/rpmbuild/SOURCES/
    tar -zxvf openvswitch-2.5.4.tar.gz
    ls /lib/modules/$(uname -r) -ln
    
    rpmbuild -bb --without check openvswitch-2.5.4/rhel/openvswitch.spec
    
    cd ../RPMS/x86_64/
    yum localinstall -y openvswitch-2.5.4-1.x86_64.rpm
    systemctl enable openvswitch.service
    systemctl start openvswitch.service

---------------------------------------------------------------------------------------------
方式二
    yum install openvswitch
    systemctl enable openvswitch
    systemctl start openvswitch

    如果当前软件源中没有openvswitch,可以通过阿里云官方镜像站(https://developer.aliyun.com/packageSearch?word=openvswitch)下载和操作系统版本对应的rpm包到本地再安装。 示例命令: yum localinstall openvswitch-2.9.0-3.el7.x86_64.rpm
安装OpenvSwitch

 

 ovs常用操作

access port 和 trunk port
--------------------------------------------------
在 OpenvSwitch 中端口 port 分两种,分别叫做 access port 和 trunk port。
第一类是 access port:
    这个端口可以配置一个 tag,其实就是一个 VLAN ID,从这个端口进来的包都会被打上这个 tag;
    如果网络包本身带有某个 VLAN ID 并且等于这个 tag,则这个包就会从这个 port 发出去;
    从 access port 发出的包就会把 VLAN ID 去掉。
第二类是 trunk port:
    这个 port 是不配置任何 tag 的,配置叫 trunks 的参数;
    如果 trunks 为空,则所有的 VLAN 都 trunk,也就意味着对于所有的 VLAN 的包,无论本身带什么 VLAN ID,我还是让他携带着这个 VLAN ID,如果没有设置 VLAN,就属于 VLAN 0,全部允许通过;
    如果 trunks 不为空,则仅仅允许带着这些 VLAN ID 的包通过。
access port 和 trunk port
ovs-vsctl命令(按操作对象分类):Bridge 操作、Port 操作、其他基本操作
=========================================================================================================================================
Bridge 操作
    ovs-vsctl add-br br-int         #添加网桥
    ovs-vsctl list-br               #查询网桥列表
    ovs-vsctl del-br br-int         #删除网桥
    ovs-vsctl show              #查看 OVS 交换机的信息
    
Port 操作
    Normal Port
        ovs-vsctl add-port br-int eth0      # 将物理网卡eth0添加到网桥br-int上
        ovs-vsctl del-port br-int eth0      # 移除网桥br-int上的Port

    Internal Port
        ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal        # 添加Internal Port 
        ip link set vnet0 up                            # 把网卡vnet0启动并配置IP
        ip addr add 192.168.0.1/24 dev vnet0
        ovs-vsctl set Port vnet0 tag=100                # 设置VLAN tag
        ovs-vsctl remove Port vnet0 tag 100             # 移除vnet0上面的VLAN tag配置
        ovs-vsctl set Port vnet0 trunks=100,200         # 设置vnet0允许通过的VLAN tag
        ovs-vsctl remove Port vnet0 trunks 100,200      # 移除vnet0允许通过的的VLAN tag配置

    Patch Port
        ovs-vsctl add-br br0
        ovs-vsctl add-br br1
        ovs-vsctl -- add-port br0 patch0 -- set interface patch0 type=patch options:peer=patch1 -- add-port br1 patch1 -- set interface patch1 type=patch options:peer=patch0

    Tunnel Port
        #主机10.1.7.21上
        ovs-vsctl add-br br-tun
        ovs-vsctl add-port br-tun vxlan-vx01 -- set Interface vxlan-vx01 type=vxlan options:remote_ip=10.1.7.22 options:key=flow
        ovs-vsctl add-port br-tun vxlan-vx02 -- set Interface vxlan-vx02 type=vxlan options:remote_ip=10.1.7.23 options:key=flow

        #主机10.1.7.22上
        ovs-vsctl add-br br-tun
        ovs-vsctl add-port br-tun vxlan-vx01 -- set Interface vxlan-vx01 type=vxlan options:remote_ip=10.1.7.21 options:key=flow
        ovs-vsctl add-port br-tun vxlan-vx02 -- set Interface vxlan-vx02 type=vxlan options:remote_ip=10.1.7.23 options:key=flow

        #主机10.1.7.23上
        ovs-vsctl add-br br-tun
        ovs-vsctl add-port br-tun vxlan-vx01 -- set Interface vxlan-vx01 type=vxlan options:remote_ip=10.1.7.21 options:key=flow
        ovs-vsctl add-port br-tun vxlan-vx02 -- set Interface vxlan-vx02 type=vxlan options:remote_ip=10.1.7.22 options:key=flow

    #ovs bond接口
        ovs-vsctl add-bond br0 bond0 first_br second_br     #默认情况下 bond_mode 是 active-backup 模式
        ovs-vsctl set Port bond0 lacp=active
        ovs-vsctl set Port bond0 bond_mode=balance-slb
        在 OpenvSwitch 里面,有个 bond_mode,可以设置为以下三个值:
            active-backup:一个连接是 active,其他的是 backup,只有当 active 失效的时候,backup 才顶上;
            balance-slb:流量按照源 MAC 和 output VLAN 进行负载均衡;
            balance-tcp:必须在支持 LACP 协议的情况下才可以,可根据 L2、L3、L4 进行负载均衡(L2、L3、L4 指的是网络协议 2、3、4 层)
    -------------------------------------------------------
    ovs-vsctl add-br ovs-switch         #创建一个新的 OVS 交换机
    ovs-vsctl add-port ovs-switch p0 -- set Interface p0 ofport_request=100     #创建一个端口 p0,设置端口 p0 的 OpenFlow 端口编号为 100(如果在创建端口的时候没有指定 OpenFlow 端口编号,OVS 会自动生成一个)。
    ovs-vsctl set Interface p0 type=internal                    #设置网络接口设备的类型为“internal”。对于 internal 类型的的网络接口,OVS 会同时在 Linux 系统中创建一个可以用来收发数据的模拟网络设备。我们可以为这个网络设备配置 IP 地址、进行数据监听等等。
    ethtool -i p0                       #如果p0是ovs创建的,此处可以看到“driver: openvswitch”

    ip netns add ns0                        #为了避免网络接口上的地址和本机已有网络地址冲突,我们可以创建一个虚拟网络空间 ns0,把 p0 接口移入网络空间 ns0,并配置 IP 地址为 192.168.1.100
    ip link set p0 netns ns0
    ip netns exec ns0 ip addr add 192.168.1.100/24 dev p0
    ip netns exec ns0 ifconfig p0 promisc up
    
    ovs-vsctl get Interface p0 ofport       #如果想获得网络接口的 OpenFlow 编号,也可以在 OVS 的数据库中查询
        
其他基本操作
    ovs-vsctl set port <port name> VLAN_mode=trunk|access|native-tagged|native-untagged     # 设置VLAN mode
    ovs-vsctl set port <port name> tag=<1-4095>                                             # 设置VLAN tag
    ovs-vsctl set port <port name> trunk=100,200                                            # 设置VLAN trunk
    ovs-vsctl remove port <port name> <property name> <property value>                      # 移除Port的属性
    ovs-vsctl list interface <port name>                                                    # 查看Port的属性
ovs-vsctl命令(按操作对象分类):Bridge 操作、Port 操作、其他基本操作
ovs-vsctl命令(按'是否ovsdb数据库操作'分类);配置QoS,端口映射
====================================================================================================
非ovsdb数据库操作
    ovs-vsctl add-br br0        #添加名为br0的网桥
    ovs-vsctl list-br           #列出所有网桥
    ovs-vsctl br-exists br0     #判断网桥br0是否存在;echo $? //0表示存在,否则不存在
    ovs-vsctl add-port br0 eth0 #将网络接口eth0挂接到网桥br0上
    ovs-vsctl add-port br0 eth1 tag=1   #将网络接口eth1挂接到网桥br0上,同时设置vlan tag=1
    ovs-vsctl set Port eth1 tag=103     #修改port tag为103
    ovs-vsctl set bridge br0 flood-vlans=101,102,103            #配置禁止 MAC 地址学习
    ovs-vsctl list-ports br0    #列出挂接到网桥br0上的所有网络接口
    ovs-vsctl port-to-br eth0   #列出已挂接eth0网络接口的网桥
    ovs-vsctl show              #查看 OVS 交换机的信息
    ovs-vsctl del-port br0 eth0 #删除网桥br0上挂接的eth0网络接口
    ovs-vsctl del-br br0        #删除名为br0的网桥
    ovs-vsctl add-bond br0 bond0 eth0 eth1

-------------------------------------------------------------------------------------------------
ovsdb数据库操作
    ovsdb是一个非常轻量级的数据库,与其说它是一个数据库,不如说它是一个提供增删查改等功能的临时配置缓存,之所以这么说,是因为ovsdb数据库的根本就未使用多少数据库技术,
    如SQL语言查询、存储过程等等。ovsdb 数据库通过模式文件“openvswitch-1.1.0pre2/vswitchd/vswitch.ovsschema”,如要定制ovsdb数据库,可通过更改 vswitch.ovsschema 文件实现。

    ovs-vsctl list/set/get/add/remove/clear/destroy table record column [value] #数据库操作的一般格式
    默认情况下ovsdb中有以下数据表:bridge, controller,interface,mirror,netflow,open_vswitch,port,qos,queue,ssl,sflow

    ovs-vsctl list bridge                               #查看bridge数据表中的所有记录
    ovs-vsctl get bridge br0 _uuid                      #获取bridge 的_uuid字段值
    ovs-vsctl set bridge br0 datapath_type="system"     #设置bridge数据表datapath_type字段的值
    ovs-vsctl clear bridge br0 flood_vlans              #清除bridge数据表flood_vlans字段的值
    ovs-vsctl remove bridge br0 flow_tables 23            
    ovs-vsctl destroy qos 69ee0c09-9e52-4236-8af6-037a98ca704d  #删除uuid为69ee0c09-9e52-4236-8af6-037a98ca704d的qos记录

-------------------------------------------------------------------------------------------------
QoS设置
    ovs-vsctl set interface eth4 ingress_policing_rate=1000     #设置网络接口eth4的带宽为1000±100kbps
    ovs-vsctl set interface eth4 ingress_policing_burst=100     #注:ingress_policing_rate:最大发送速率(单位均为kbps);ingress_policing_burst:超过ingress_policing_rate的最大浮动值

    ovs-vsctl -- set port vif0.0 qos=@newqos -- --id=@newqos create qos type=linux-htb other-config: \
    max-rate=100000000 queues=0=@q0,1=@q1 -- --id=@q0 create queue other-config:min-rate=100000000 \
    other-config:max-rate=100000000 -- --id=@q1 create queue other-config:min-rate=500000000
        #创建在vif0.0端口上的linux-htb QoS,linux-htb QoS可以针对具有指定特征的数据包流设置最大最小带宽,且在最大带宽范围内,某一特征的数据包流可以借用其他特征数据包流未用完的带宽。

-------------------------------------------------------------------------------------------------
端口映射
    ovs-vsctl --set bridge br0 mirrors=@m-- --id=@m create mirror name=mymirror \
    select-dst-port=a27e5ec3-5d78-437e-8e36-d6f81679132a select-src-port=be52eece-1f03-4ccf-a4c6-b0b68cb25f8a output-port=bc38e1c3-60a1-468e-89d7-e4b45585b533
        #将发往eth0端口和从eth1端口发出的数据包全部定向到eth2端口
        #用ovs-vsctl list port命令查看eth0、eth1、eth2端口的uuid
ovs-vsctl命令(按'是否ovsdb数据库操作'分类);配置QoS,端口映射

 

ovs-vsctl配置镜像端口

端口镜像类型
    端口镜像分为镜像源和镜像目的两部分。

镜像源
    select_all:布尔类型(true,false)。设置为 true 时,表示此网桥上的所有流量。
    select_dst_port:字符串(端口名称)。表示此端口接收的所有流量。
    select_src_port:字符串(端口名称)。表示此端口发送的所有流量。
    select_vlan:整形(1-4096)。表示携带此VLAN标签的流量。
镜像目的
    output_port:字符串(端口名称)。接收流量报文的观察端口。
    output_vlan:整形(1-4096)。表示只修改VLAN标签,原VLAN标签会被剥离。


基础操作命令
新增端口镜像
    ovs-vsctl -- set Bridge <bridge_name> mirrors=@m \
     -- --id=@<port0> get Port <port0> \
     -- --id=@<port1> get Port <port1> \
     -- --id=@m create Mirror name=<mirror_name> select-dst-port=@<port0> select-src-port=@<port0> output-port=@<port1>
        #这行命令会输出一个镜像ID

删除端口镜像
    ovs-vsctl remove Bridge <bridge-name> mirrors <mirror-id>

在原端口镜像的基础上增加一个镜像源
    ovs-vsctl get port <port_name> _uuid        # 获取端口的ID
    ovs-vsctl add Mirror <mirror-name> select_src_port <port-id>        # 在原端口镜像的基础上增加镜像源
    ovs-vsctl add Mirror <mirror-name> select_dst_port <port-id>

在原端口镜像的基础上删除一个镜像源
    ovs-vsctl get port <port_name> _uuid        # 获取端口的ID    
    ovs-vsctl remove Mirror <mirror-name> select_src_port <port-id>
    ovs-vsctl remove Mirror <mirror-name> select_dst_port <port-id>
    
清空端口镜像
    ovs-vsctl clear Mirror 
    
查看端口镜像
    ovs-vsctl list Mirror 

关闭端口的MAC地址学习
    ovs-ofctl mod-port <bridge-name> <port-name> NO-FLOOD
ovs-vsctl配置镜像端口

 

测试工具ovs-appctl ofproto/trace;一些其他命令:ovs-dpctl
====================================================================================
测试工具ovs-appctl ofproto/trace
OVS 提供的 ovs-appctl ofproto/trace 工具可以测试 OVS 对数据包的转发状况。ovs-appctl ofproto/trace 可以用来生成测试用的模拟数据包,并一步步的展示 OVS 对数据包的流处理过程。

ovs-vsctl set Port p1 tag=101           #修改端口 p1 的 VLAN tag 为 101,使端口 p1 成为一个隶属于 VLAN 101 的端口
ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8 -generate 
    #现在由于端口 p0 和 p1 属于不同的 VLAN,它们之间无法进行数据交换。我们使用 ovs-appctl ofproto/trace 生成一个从端口 p0 发送到端口 p1 的数据包,这个数据包不包含任何 VLAN tag,并观察 OVS 的处理过程

ovs-ofctl add-flow ovs-switch "priority=3,in_port=100,dl_vlan=0xffff,actions=mod_vlan_vid:101,normal"       #创建一条新的 Flow:对于从端口 p0 进入交换机的数据包,如果它不包含任何 VLAN tag,则自动为它添加 VLAN tag 101
ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8 –generate
    #再次尝试从端口 p0 发送一个不包含任何 VLAN tag 的数据包,发现数据包进入端口 p0 之后, 会被加上 VLAN tag101, 同时转发到端口 p1 上

ovs-appctl ofproto/trace ovs-switch in_port=101,dl_dst=66:4e:cc:ae:4d:20,dl_src=46:54:8a:95:dd:f8 -generate
    #反过来从端口 p1 发送数据包,由于 p1 现在是带有 VLAN tag 101 的 Access 类型的端口,所以数据包进入端口 p1 之后,会被 OVS 添加 VLAN tag 101 并发送到端口 p0

------------------------------------------------------------------------------------
ovs-appctl --version        #查看 OVS 的版本信息
ovs-ofctl --version         #查看 OVS 支持的 OpenFlow 协议的版本
ovs-dpctl show          #查看 datapath 的信息
测试工具ovs-appctl ofproto/trace;一些其他命令:ovs-dpctl

 OpenvSwitch flow table 流表

OpenvSwitch flow table 流表;ovs-ofctl工具
==============================================================================================================================
OpenFlow 是 SDN 控制器和网络设备之间互通的南向接口协议,OpenvSwitch 用于创建软件的虚拟交换机。OpenvSwitch 是支持 OpenFlow 协议的,当然也有一些硬件交换机也支持 OpenFlow 协议。它们都可以被统一的 SDN 控制器管理,从而实现物理机和虚拟机的网络连通。
OpenFlow 是用于管理交换机流表的协议,ovs-ofctl 则是 OVS 提供的命令行工具。在没有配置 OpenFlow 控制器的模式下,用户可以使用 ovs-ofctl 命令通过 OpenFlow 协议去连接 OVS,创建、修改或删除 OVS 中的流表项,并对 OVS 的运行状况进行动态监控。
OpenvSwitch flow table 流表
    OpenFlow(OF)被认为是第一个软件定义网络(SDN)标准之一。它最初在SDN环境中定义了通信协议,使SDN控制器能够与物理和虚拟的交换机和路由器等网络设备的转发平面直接进行交互,从而更好地适应不断变化的业务需求。
    如果把OpenFlow控制器比作“大脑”,OVS流表就像是“大腿”一样接受来自“大脑”的指令,决定要向哪个方向前进。但OVS流表功能更加强大,在没有OpenFlow控制器时,也可以自主工作,它本身也供一些命令让我们可以直接管理流表。

在 OpenvSwitch 里面,有一个流表规则,任何通过这个交换机的包,都会经过这些规则进行处理,从而接收、转发、放弃。
流表就是一个个表格,每个表格好多行,每行都是一条规则。每条规则都有优先级,先看高优先级的规则,再看低优先级的规则。
每条流规则由一系列字段组成,分为基本字段、条件字段和动作字段三部分。
    基本字段包括生效时间duration_sec、所属表项table_id、优先级priority、处理的数据包数n_packets,空闲超时时间idle_timeout等,
        空闲超时时间idle_timeout以秒为单位,超过设置的空闲超时时间后该流规则将被自动删除,空闲超时时间设置为0表示该流规则永不过期,idle_timeout将不包含于ovs-ofctl dump-flows brname的输出中。
    条件字段包括输入端口号in_port、源目的mac地址dl_src/dl_dst、源目的ip地址nw_src/nw_dst、数据包类型dl_type、网络层协议类型nw_proto等,
        可以为这些字段的任意组合,但在网络分层结构中底层的字段未给出确定值时上层的字段不允许给确定值,
        即一条流规则中允许底层协议字段指定为确定值,高层协议字段指定为通配符(不指定即为匹配任何值),
        而不允许高层协议字段指定为确定值,而底层协议字段却为通配符(不指定即为匹配任何值),
        否则,ovs-vswitchd 中的流规则将全部丢失,网络无法连接。
    动作字段包括正常转发normal、定向到某交换机端口output:port、丢弃drop、更改源目的mac地址mod_dl_src/mod_dl_dst等,一条流规则可有多个动作,动作执行按指定的先后顺序依次完成。

-------------------------------------------------------------------------------------------------------------------------------
操作命令
    查看流表规则
        ovs-ofctl dump-tables ovs-switch        #查看交换机中的所有 Table
        ovs−ofctl dump−flows ovs-switch         #查看交换机中的所有流表项
        ovs-ofctl dump-ports br0                #查看br0上各交换机端口的状态;注:输出的结果中包含了各网络接口上收到的数据包数,字节数,丢包数,错误数据包数等信息
        ovs-ofctl show ovs-switch               #查看 Open vSwitch 中的端口信息。从输出结果中,可以获得交换机对应的 datapath ID (dpid),以及每个端口的 OpenFlow 端口编号,端口名称,当前状态等等。


    添加或修改流表规则
        ovs-ofctl add-flow/add-flows/mod-flows “流表,匹配条件,actions=[动作1][,动作2…]”
        ovs-ofctl [options] command [switch] [args...]
        
    删除流表规则
        ovs-ofctl del-flows br-tun          # 删除br-tun上的全部流表规则
        ovs-ofctl del-flows br-tun xx       # 删除br-tun上匹配xx的全部流表规则
        ovs-ofctl del-flows ovs-switch "in_port=100"        #删除编号为 100 的端口上的所有流表项

    ovs-ofctl示例:
        ovs-ofctl add-flow br0 idle_timeout=120,in_port=2,actions=drop                                          #添加一条流规则:丢弃从2号端口发来的所有数据包
        ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"       #屏蔽所有进入 OVS 的以太网广播数据包
        ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"       #屏蔽 STP 协议的广播数据包

        ovs-ofctl add-flow ovs-switch "priority=1 idle_timeout=0,in_port=100,actions=mod_nw_src:9.181.137.1,normal"         #添加新的 OpenFlow 条目,修改从端口 p0(port编号100) 收到的数据包的源地址为 9.181.137.1
        ip netns exec ns0 ping 192.168.1.101            #从端口 p0(192.168.1.100)发送测试数据到端口 p1(192.168.1.101)
        ip netns exec ns1 tcpdump -i p1 icmp            #在接收端口 p1 监控数据,发现接收到的数据包的来源已经被修改为 9.181.137.1

        ovs-ofctl add-flow ovs-switch idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:102       #添加新的 OpenFlow 条目,重定向所有的 ICMP 数据包到端口 p2
        ip netns exec ns0 ping 192.168.1.101            #从端口 p0 (192.168.1.100)发送数据到端口 p1(192.168.1.101)
        ip netns exec ns3 tcpdump -i p2 icmp            #在端口 p2 上监控数据,发现数据包已被转发到端口 p2



        网站屏蔽
            ovs-ofctl add-flow br0 idle_timeout=0,dl_type=0x0800,nw_src=119.75.213.50,actions=drop
                #屏蔽由Open vSwitch管理的任何主机对主机119.75.213.50的访问,但只屏蔽ip数据包(由dl_type=0x0800指定),即所有主机将无法访问该主机上所有基于IP协议的服务,如万维网服务、FTP访问等

        数据包重定向
            ovs-ofctl add-flow br0 idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:4
                #将交换机中所有的icmp协议包(由dl_type=0x0800,nw_proto=1指定)全部转发到4号端口,包括4号端口自己发出的icmp包,该流规则将导致由Open vSwitch管理的主机间以及与外部网络间都将访问ping通,但可以使用万维网、FTP等服务。

        去除VLAN tag
            ovs-ofctl add-flow br0 idle_timeout=0,in_port=3,actions=strip_vlan,normal   #去除从3号端口发来的所有VLAN数据包中的tag,然后转发
        更改数据包源IP地址后转发
            ovs-ofctl add-flow br0 idle_timeout=0,in_port=3,actions=mod_nw_src:192.168.28.225,normal    #将从3号端口收到的所有IP包的源IP字段更改为192.168.28.225
OpenvSwitch flow table 流表;ovs-ofctl工具
流表匹配条件
=======================================================================================================
    table=number                #规则保存的流表编号,范围是 0-254,默认值:0。
    reg<idx>=value[/mask]       #交换机中的寄存器的值。当一个数据包进入交换机时,所有的寄存器都被清零,用户可以通过 Action 的指令修改寄存器中的值
    
----------------------------------------------------------------------------------------------
OSI模型第一层【物理层】
    in_port=port                #流量进入的端口编号或者名称,示例 in_port=br-int

---------------------------------------------------------------------------------------------
OSI模型第二层【数据链路层】
    #dl 即是 data link 的缩写。
    dl_type=ethertype           #匹配以太网协议类型以太类型,以10到65535之间的整数(包括0和65535)指定,以十进制或以0x前缀的十六进制数表示,示例如下。
        dl_type=0x0800 匹配IPv4数据包,等同于dl_type=ip 。
        dl_type=0x086dd 匹配IPv6数据包,等同于dl_type=ipv6 。
        dl_type=0x0806 匹配ARP数据包,等同于dl_type=arp 。
        dl_type=0x8035 匹配RARP数据包,等同于 dl_type=rarp。

    dl_vlan=vlan                #数据包的 VLAN Tag 值,范围是 0-4095,0xffff 代表不包含 VLAN Tag 的数据包
    dl_vlan_pcp=priority        #VLAN 优先级,取值区间为[0-7]。数字越大,表示优先级越高。

    dl_src=xx:xx:xx:xx:xx:xx    #源或目的的 MAC地址
    dl_dst=xx:xx:xx:xx:xx:xx    #源或目的的 MAC地址
        地址01:00:00:00:00:00/01:00:00:00:00:00 代表广播
        地址00:00:00:00:00:00/01:00:00:00:00:00 代表单播
        地址fe:ff:ff:ff:ff:ff 匹配除多播位以外的所有位,基本上不会用到。
        地址ff:ff:ff:ff:ff:ff 完全匹配(等同于省略子网掩码)。
        地址00:00:00:00:00:00 匹配全部位(等同于 dl_dst=*)。

---------------------------------------------------------------------------------------------
OSI模型第三层【网络层】
    nw_src=ip[/netmask]
    nw_dst=ip[/netmask]
    如果dl_type为0x0800(可能是通过简写形式,例如ip或tcp),则匹配IPv4源(或目标)地址ip,可以将其指定为IP地址或主机名(例如192.168.1.1或www.example.com)。
    可选的网络掩码允许将匹配限制为IPv4地址前缀。网络掩码可以指定为点分四边形(例如192.168.1.0/255.255.255.0)或CIDR块(例如192.168.1.0/24)。 
        #Open vSwitch 1.8和更高版本支持任意点状四元掩码;早期版本仅支持CIDR掩码,即等效于某些CIDR块的虚线四边形。
        当指定dl_type为0x0800 或者ip时,匹配源或者目标的 IPv4 地址,可以将其指定为IP地址或主机名,例如192.168.1.1或www.typesafe.cn。同时也可以写作192.168.1.0/255.255.255.0或者192.168.1.0/24的形式。
        当指定dl_type为0x0806 或arp时,分别与IPv4和Ethernet的ARP数据包中的ar_spa或ar_tpa字段匹配。
        当指定dl_type为0x8035 或rarp时,分别与IPv4和Ethernet的RARP数据包中的ar_spa或ar_tpa字段匹配。
        当指定dl_type为0x0800、0x0806或0x8035之外的其他值时,将忽略nw_src和nw_dst的值。

    nw_proto=proto
    ipproto=proto
        如果指定ip或dl_type=0x0800,则匹配IP协议类型proto,该协议类型被指定为0到255之间的十进制数(包括1和0,用于包含ICMP数据包或6以匹配TCP数据包)。
        如果指定了ipv6或dl_type=0x86dd,则匹配IPv6标头类型原型,该形式指定为0到255之间的十进制数字(例如,包括58以匹配ICMPv6数据包或6以匹配TCP)。标头类型是设计文档中描述的终端标头。
        当指定arp或dl_type=0x0806时,与ARP操作码的低8位匹配。大于255的ARP操作码被视为0。
        指定rarp或dl_type=0x8035时,与ARP操作码的低8位匹配。大于255的ARP操作码被视为0。
        当通配符dl_type或将其设置为0x0800、0x0806、0x8035或0x86dd之外的其他值时,将忽略nw_proto的值(请参见上面的流语法)。

    nw_tos=tos
        匹配IP ToS / DSCP或IPv6流量类别字段tos,该字段tos指定为0到255之间的十进制数字(包括0和255)。请注意,出于匹配目的,将忽略两个较低的保留位。
        当通配符dl_type或将其设置为0x0800或0x86dd之外的其他值时,将忽略nw_tos的值。

    ip_dscp=dscp
        匹配IP ToS / DSCP或IPv6流量类字段dscp,该字段指定为介于0和63之间(含0和63)的十进制数。
        当通配符dl_type或将其设置为0x0800或0x86dd之外的其他值时,将忽略ip_dscp的值(请参见上面的流语法)。

    nw_ecn=ecn
    ip_ecn=ecn
        匹配IP ToS或IPv6流量类别字段中的ecn位,该ecn位指定为0到3(含0和3)之间的十进制数。当通配符dl_type或将其设置为0x0800或0x86dd之外的其他值时,将忽略nw_ecn的值(请参见上面的流语法)。

    nw_ttl=ttl
        匹配IP TTL或IPv6跃点限制值ttl,该值指定为0到255之间的十进制数字(包括0和255)。
        当通配符dl_type或将其设置为0x0800或0x86dd之外的其他值时,将忽略nw_ttl的值(请参见上面的流语法)。

---------------------------------------------------------------------------------------------
OSI模型第四层【传输层】
    tcp_src=port
    tcp_dst=port
    udp_src=port
    udp_dst=port
    sctp_src=port
    sctp_dst=port
        匹配TCP,UDP或SCTP源端口或目标端口,端口号指定为0到65535(含0和65535)之间的十进制数。
        当通配符dl_type和nw_proto或将其设置为不表示适当协议的值时,这些设置的值将被忽略(请参见上面的流语法)。

    tcp_src=port/mask           #一次性匹配多个端口,较少使用
    tcp_dst=port/mask
    udp_src=port/mask
    udp_dst=port/mask
    sctp_src=port/mask
    sctp_dst=port/mask
        TCP(或UDP或SCTP)源或目标端口上的按位匹配。端口和掩码是16位数字,以十进制或十六进制写为0x。掩码中的每个1位要求端口中的相应位必须匹配。掩码中的每个0位都会导致忽略相应的位。
            #规则与反掩码相反,反掩码0严格匹配,1随机匹配
        传输端口上的按位匹配很少在隔离中有用,但是可以使用一组匹配项来减少在一系列传输端口上进行匹配所需的流数。
        例如,假设目标是将TCP源端口1000匹配到1999(含)。
            一种方法是插入1000个流,每个流在单个源端口上匹配。
            另一种方法是查看1000和1999的二进制表示形式,如下所示:
                01111101000
                11111001111
        然后将其转换为一系列按位匹配,以实现相同的结果:
            01111101xxx
            0111111xxxx
            10xxxxxxxxx
            110xxxxxxxx
            1110xxxxxxx
            11110xxxxxx
            1111100xxxx
        使用ovs-ofctl所需的语法编写时,这些内容如下:
            tcp,tcp_src=0x03e8/0xfff8   #通过这2条语句,完成端口1000-1999的匹配
            tcp,tcp_src=0x03f0/0xfff0
            tcp,tcp_src=0x0400/0xfe00
            tcp,tcp_src=0x0600/0xff00
            tcp,tcp_src=0x0700/0xff80
            tcp,tcp_src=0x0780/0xffc0
            tcp,tcp_src=0x07c0/0xfff0
        #仅Open vSwitch 1.6和更高版本支持传输端口上的按位匹配。
        #与上述完全匹配形式一样,按位匹配形式仅在dl_type和nw_proto指定TCP或UDP或SCTP时适用。

    tp_src=port
    tp_dst=port
        这些是L4端口匹配项已弃用的通用形式。在新代码中,请使用上述特定于TCP,UDP或SCTP的形式。

    tcp_flags=flags/mask
    tcp_flags=[+flag...][-flag...]
        TCP标志按位匹配。标志和掩码是16位数字,以十进制或以0x为前缀的十六进制表示。掩码中的每个1位要求标志中的相应位必须匹配。掩码中的每个0位都会导致忽略相应的位。
        或者,可以通过标志的符号名(在下面列出)来指定标志,每个标志名的前面都带有+,表示必须设置的标志,或者-表示必须取消设置的标志,且标志之间没有其他定界符。未提及的标志是通配符。
        例如,tcp,tcp_flags = + syn-ack匹配不是ACK的TCP SYN。 TCP协议当前定义9个标志位,并保留另外3个位(必须作为零发送),请参阅RFC 793、3168和3540。这些标志位的编号从最低有效位开始:
            0:fin 查找不再有来自发送方的数据。
            1:syn 同步同步序列号。
            2:rst 重置连接。
            3:psh 推送功能。
            4:ack 确认字段有效。
            5:urg 紧急指针字段有效。
            6:ece ECN回显。
            7:cer 减少拥塞窗口。
            8:ns 现时总和
            9-11:保留。
            12-15:不处理,必须为零。

    icmp_type=type
    icmp_code=code
        当dl_type和nw_proto指定ICMP或ICMPv6时,type匹配ICMP类型,而代码匹配ICMP代码。每个参数都指定为介于0和255之间(含两端)的十进制数。
        当dl_type和nw_proto采用其他值时,这些设置的值将被忽略(请参见上面的流语法)。

    metadata=value[/mask]
        在元数据字段中完全匹配值或使用可选掩码匹配值。 
        value和mask是64位整数,默认情况下为十进制(使用0x前缀指定十六进制)。
        允许使用任意掩码值:掩码中的1位表示值中的对应位必须完全匹配,而该位则使用0位通配符。在Open vSwitch 1.8中添加了对元数据的匹配。
        ip        #等同于dl_type=0x0800
        ipv6      #等同于dl_type=0x86dd
        icmp      #等同于dl_type=0x0800,nw_proto=1
        icmp6     #等同于dl_type=0x86dd,nw_proto=58
        tcp       #等同于dl_type=0x0800,nw_proto=6
        tcp6      #等同于dl_type=0x86dd,nw_proto=6
        udp       #等同于dl_type=0x0800,nw_proto=17
        udp6      #等同于dl_type=0x86dd,nw_proto=17
        sctp      #等同于dl_type=0x0800,nw_proto=132
        sctp6     #等同于dl_type=0x86dd,nw_proto=132
        arp       #等同于dl_type=0x0806
        rarp      #等同于dl_type=0x8035
        mpls      #等同于dl_type=0x8847
        mplsm     #等同于dl_type=0x8848

    vlan_tci=tci[/mask]
        匹配修改后的VLAN TCI tci。
        如果省略mask,则tci是要匹配的确切VLAN TCI;
        如果指定了mask,则mask中的1位表示tci中的对应位必须完全匹配,而0位通配符表示该位。 
        tci和mask均为16位值,默认情况下为十进制。使用0x前缀以十六进制指定它们。
        对于没有802.1Q标头的数据包,vlan_tci与之匹配的值为0。否则,它是802.1Q标头中的TCI值,其中CFI位(值为0x1000)被强制为1。
        vlan_tci=0                  #仅匹配没有802.1Q标头的数据包。
        vlan_tci=0xf123             #匹配VLAN 0x123中标记为优先级7的数据包。
        vlan_tci=0x1123/0x1fff      #匹配标记有VLAN 0x123(和任何优先级)的数据包。
        vlan_tci=0x5000/0xf000      #匹配标记为优先级2的数据包(在任何VLAN中)。
        vlan_tci=0/0xfff            #匹配没有802.1Q标头或带有VLAN 0(和任何优先级)标记的数据包。
        vlan_tci=0x5000/0xe000      #匹配没有802.1Q标头或带有优先级2标记的数据包(在任何VLAN中)。
        vlan_tci=0/0xefff           #匹配没有802.1Q标头或带有VLAN 0和优先级0标记的数据包。
        使用dl_vlan和dl_vlan_pcp也可以实现某些匹配可能性。

    ip_frag=frag_type
        当dl_type指定IP或IPv6时,frag_type指定要匹配的IP片段或非片段类型。支持以下frag_type值:
        no          #仅匹配非分段数据包。
        yes         #匹配所有片段。
        first       #仅匹配偏移量为0的片段。
        later       #仅匹配非零偏移量的片段。
        not_later   #匹配零碎的非碎片数据包和碎片。

    arp_spa=ip[/netmask]
    arp_tpa=ip[/netmask]
        当dl_type指定ARP或RARP时,arp_spa和arp_tpa分别与源和目标IPv4地址匹配。
        可以将地址指定为IP地址或主机名(例如192.168.1.1或www.example.com)。
        可选的网络掩码允许将匹配限制为IPv4地址前缀。
        网络掩码可以指定为点分四边形(例如192.168.1.0/255.255.255.0)或CIDR块(例如192.168.1.0/24)。

    arp_sha=xx:xx:xx:xx:xx:xx
    arp_tha=xx:xx:xx:xx:xx:xx
        当dl_type指定ARP或RARP时,arp_sha和arp_tha分别匹配源和目标硬件地址。地址指定为以冒号分隔的6对十六进制数字(例如00:0A:E4:25:6B:B0)。

    arp_sha=xx:xx:xx:xx:xx:xx/xx:xx:xx:xx:xx:xx
    arp_tha=xx:xx:xx:xx:xx:xx/xx:xx:xx:xx:xx:xx
        当dl_type指定ARP或RARP时,arp_sha和arp_tha分别匹配源和目标硬件地址。地址指定为以冒号分隔的6对十六进制数字(例如00:0A:E4:25:6B:B0),并在斜杠后加上通配符掩码。

    arp_op=opcode
        当dl_type指定ARP或RARP时,arp_op与ARP操作码匹配。只能指定1到255之间的ARP操作码进行匹配。

    ipv6_src=ipv6[/netmask]
    ipv6_dst=ipv6[/netmask]
        当dl_type为0x86dd时(可能通过简写形式,例如ipv6或tcp6),匹配IPv6源(或目标)地址ipv6,该地址可以按RFC 2373中的规定指定。
        首选格式为x:x:x:x:x:x:x:x,其中x是地址的八个16位块的十六进制值。 ::的单个实例可用于指示16位零的多个组。
        可选的网络掩码允许将匹配限制为IPv6地址前缀。网络掩码被指定为IPv6地址(例如2001:db8:3c4d:1::/ffff:ffff:ffff:ffff::)或CIDR块(例如2001:db8:3c4d:1::/64)。
        打开vSwitch 1.8及更高版本,支持仲裁掩码;早期版本仅支持CIDR掩码,即CIDR块和等同于CIDR块的IPv6地址。

    ipv6_label=label
        当dl_type为0x86dd时(可能通过简写形式,例如ipv6或tcp6),匹配IPv6流标签label。

    tun_id=tunnel-id[/mask]
    tunnel_id=tunnel-id[/mask]
        匹配隧道标识符tunnel-id。只有通过带有密钥的隧道到达的数据包(例如具有RFC 2890密钥扩展名和非零密钥值的GRE)才会具有非零的隧道ID。
        如果省略mask,则tunnel-id是要匹配的确切隧道ID;如果指定了mask,则mask中的1位表示tunnel-id中的相应位必须完全匹配,而0位通配符则将该位匹配。

    tun_flags=flags
        匹配标志,指示隧道封装的各个方面。当前,仅定义一个标志:
            oma     #隧道协议指示这是一个OAM控制数据包。
        可以在标志前面加上+或-来分别指示该标志应匹配为存在或不存在。另外,可以指定没有前缀的标志,并用|分隔。表示完全匹配。
        请注意,较新版本的Open vSwitch可能会引入具有不同含义的其他标志。因此,不建议在此字段上使用完全匹配,因为这些新标志的行为是未知的,应忽略。
        对于非隧道数据包,该值为0。
        此字段是在Open vSwitch 2.5中引入的。

    tun_src=ip[/netmask]
    tun_dst=ip[/netmask]
        匹配隧道IPv4源(或目标)地址ip。仅通过隧道到达的数据包将具有非零的隧道地址。
        该地址可以指定为IP地址或主机名(例如192.168.1.1或www.example.com)。
        可选的网络掩码允许将匹配限制为被掩码的IPv4地址。
        子网掩码可以指定为点分四边形(例如192.168.1.0/255.255.255.0)或CIDR块(例如192.168.1.0/24)。
        ipv6        #等同于dl_type=0x86dd
        tcp6        #等同于dl_type=0x86dd,nw_proto=6
        udp6        #等同于dl_type=0x86dd,nw_proto=17
        sctp6       #等同于dl_type=0x86dd,nw_proto=132
        icmp6       #等同于dl_type=0x86dd,nw_proto=58
流表匹配条件
流表动作:满足匹配条件之后将会执行的动作。
    output:port                         *****#将数据包输出到OpenFlow端口号port。如果port是数据包的输入端口,则不输出数据包。
    group:group_id                      #将数据包输出到OpenFlow组group_id。仅OpenFlow 1.1+支持组表。有关更多详细信息,请参见组语法。
    normal                              #使数据包经过设备的常规L2 / L3处理。 (并非所有OpenFlow交换机都执行此操作。)
    flood                               #在所有交换机物理端口上输出数据包,而不是在接收数据包的端口以及任何禁用洪泛的端口上进行输出(通常,这些端口是IEEE 802.1D生成树协议禁用的端口)。
    all                                 #在所有交换机物理端口上输出数据包,而不是在接收数据包的端口上。
    local                               #在与本地网桥名称相同的网络设备对应的``本地端口''上输出数据包。
    in_port                             #在接收数据包的端口上输出数据包。
    enqueue(port,queue)                 #将数据包放入端口port中的指定队列中,该队列必须是OpenFlow端口号或关键字(例如LOCAL)。支持的队列数取决于交换机;具体取决于交换机。一些OpenFlow实现根本不支持排队。
    drop                                #丢弃数据包,因此不会进行进一步的处理或转发。如果使用丢弃动作,则不能指定其他动作。

    mod_vlan_vid:vlan_vid               *****#修改报文的VLAN ID。根据需要添加或修改VLAN标记以匹配指定的值。如果添加了VLAN标记,则使用零优先级(请参阅mod_vlan_pcp操作来设置此优先级)。
    mod_vlan_pcp:vlan_pcp               #修改报文的VLAN优先级。根据需要添加或修改VLAN标记以匹配指定的值。有效值介于0(最低)和7(最高)之间。如果添加了VLAN标记,则使用的vid为零(请参阅mod_vlan_vid操作进行设置)。
    strip_vlan                          *****#从数据包中剥离VLAN标记(如果存在)。
    push_vlan:ethertype                 #将新的VLAN标签推入数据包。以太网类型用作标签的以太网类型。仅应使用ethertype 0x8100。 (目前尚不支持规范允许的0x88a8。)新标签使用优先级为零且标签为零。

    mod_dl_src:mac                      *****#将源以太网地址设置为mac。
    mod_dl_dst:mac                      *****#将目标以太网地址设置为mac。

    mod_nw_src:ip                       *****#将IPv4源地址设置为ip。
    mod_nw_dst:ip                       *****#将IPv4目标地址设置为ip。

    mod_tp_src:port                     #将TCP或UDP或SCTP源端口设置为port。
    mod_tp_dst:port                     #将TCP或UDP或SCTP目标端口设置为port。

    mod_nw_tos:tos                      #将IPv4 ToS / DSCP或IPv6流量类字段中的DSCP位设置为tos,该值必须为0到255之间的4的倍数。此操作不会修改ToS字段的两个最低有效位(ECN位)。
    mod_nw_ecn:ecn                      #将IPv4 ToS或IPv6流量类别字段中的ECN比特设置为ecn,该值必须介于0和3之间(包括0和3)。此操作不会修改该字段的六个最高有效位(DSCP位)。
                                            #需要OpenFlow 1.1或更高版本。
    mod_nw_ttl:ttl                      #将IPv4 TTL或IPv6跳数限制字段设置为ttl,指定为0到255之间的十进制数(包括0和255)。但是,没有很好地指定将ttl设置为零时的开关行为。
                                            #需要OpenFlow 1.1或更高版本。

    resubmit:port                       *****
    resubmit([port],[table])            *****#重新搜索此OpenFlow流表(或由表指定其编号的表),用in_port字段替换为端口(如果指定了port),并执行找到的操作(如果有),以及此流条目中的任何其他操作。

    set_tunnel:id
    set_tunnel64:id                     #如果输出到将数据包封装在隧道中并支持标识符(例如GRE)的端口,则将标识符设置为id。
                                            #如果使用set_tunnel形式,并且id可以容纳32位,则此操作将使用Open vSwitch 1.0和更高版本支持的操作扩展。
                                            #否则,如果id是64位值,则需要Open vSwitch 1.1或更高版本。

    set_queue:queue                     #设置输出数据包时应用于排队的队列。支持的队列数取决于交换机;具体取决于交换机。一些OpenFlow实现根本不支持排队。

    pop_queue                           #将队列恢复为应用任何set_queue操作之前的值。

    move:src[start..end]->dst[start..end]   #将已命名的位从字段src复制到字段dst。 src和dst必须是nicira-ext.h中定义的NXM字段名称,例如NXM_OF_UDP_SRC或NXM_NX_REG0。
                                            #每个开始和结束对(包括首尾对)必须指定相同的位数,并且必须适合其各自的字段。
                                            #存在[start..end]的简写形式:使用[bit]指定单个位,或使用[]指定整个字段。

    set_field:value[/mask]->dst
    load:value−>dst[start..end]         *****写数据到指定的字段 #将文字值加载到字段或字段的一部分中。对于set_field,在字段dst的惯用语法中给出了值和可选掩码,表示为字段名。
                                        #例如,set_field:00:11:22:33:44:55-> eth_src将以太网源地址设置为00:11:22:33:44:55。加载时,值必须是整数值(十进制或以0x开头的十六进制前缀),而dst是该字段的NXM或OXM名称。
                                        #例如,load:0x001122334455-> OXM_OF_ETH_DST []与前面的set_field示例具有相同的效果。
                                        #出于历史原因,存在这两种形式。 Open vSwitch 1.1引入了NXAST_REG_LOAD作为OpenFlow 1.0的Nicira扩展,并使用load来表达它。
                                        #后来,Open-Flow 1.2引入了一个标准的OFPAT_SET_FIELD操作,该操作仅限于加载整个字段,因此Open vSwitch添加了具有此限制的表单set_field。 
                                        #OpenFlow 1.5将OFPAT_SET_FIELD扩展到了它成为NXAST_REG_LOAD的超集的地步。
                                        #Open vSwitch会根据所使用的OpenFlow版本转换两种语法:
                                            #OpenFlow 1.0和1.1中的NXAST_REG_LOAD;
                                            #在OpenFlow 1.2、1.3和1.4中,NXAST_REG_LOAD用于加载或加载子字段,否则为OFPAT_SET_FIELD; 
                                            #OpenFlow 1.5及更高版本,OFPAT_SET_FIELD。

    push:src[start..end]                #在堆栈顶部的字段中,压入开始(包括结束)位。
                                            #示例:push:NXM_NX_REG2 [0..5]将存储在寄存器2位0到5(含0和5)中的值压入内部堆栈。

    pop:dst[start..end]                 #从堆栈的顶部弹出,从弹出的值中检索包含开始到结束的位,并将它们存储在dst中的相应位中。
                                            #示例:pop:NXM_NX_REG2 [0..5]从堆栈顶部弹出该值。根据刚刚弹出的值的0至5位,将寄存器2的0至5位(包括0和5)设置为1。

    multipath(fields,basis,algorithm,n_links,arg,dst[start..end])
                                        #使用base作为通用哈希参数对字段进行哈希处理,然后应用多路径链接选择算法(带有参数arg)从0到n_links减去1来选择n_links输出链接之一,并将链接存储到dst [start..end]中,它必须是如上所述的NXM字段。

    其他的请参考官方操作手册
        https://www.openvswitch.org/support/dist-docs-2.5/ovs-ofctl.8.txt
        man ovs-ofctl
流表动作
我对于flow table的理解
------------------------------------
我的理解:flow table其实相当于策略路由了,匹配中的数据包,想怎么样就怎么样,
    1.可以修改数据包的内容,比如mac,vlan,ip等等
    2.可以将该数据包从直接接口扔出去
    3.可以将数据包转入下一个table继续处理
    4.可以转发交换机,根据交换机的自身逻辑继续转发
我对于flow table的理解

ovs实验

实验一:单机无隔离网络;实验二: 单机隔离网络(vlan隔离)
============================================================================================================================
实验一:单机无隔离网络
使用ovs构建无隔离网络非常简单,只需要添加一个网桥,然后在这个网桥上再增加几个内部端口,最后把端口移动到netns中即可。

# 添加网桥
    ovs-vsctl add-br br-int
# 添加三个内部端口
    ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal            #当Port的类型是Internal时,OVS会自动创建一个虚拟网卡(Interface);
    ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal
    ovs-vsctl add-port br-int vnet2 -- set Interface vnet2 type=internal
    ip link add vnet3 type veth peer name vnet4                #增加一条veth类型的link,指定两端的名字
    ovs-vsctl add-port br-int vnet3                            #默认port类型为Normal,当网卡vnet3存在时,才能添加;否则会报错;同时normal port是不能配置IP的,一般用于trunk
# 添加三个netns
    ip netns add ns0
    ip netns add ns1
    ip netns add ns2
    ip netns add ns3
# 将内部端口分别移动到netns中
    ip link set vnet0 netns ns0
    ip link set vnet1 netns ns1
    ip link set vnet2 netns ns2
    ip link set vnet4 netns ns3

# 启动端口并配置IP
    ip netns exec ns0 ip link set lo up
    ip netns exec ns0 ip link set vnet0 up
    ip netns exec ns0 ip addr add 10.0.0.1/24 dev vnet0

    ip netns exec ns1 ip link set lo up
    ip netns exec ns1 ip link set vnet1 up
    ip netns exec ns1 ip addr add 10.0.0.2/24 dev vnet1

    ip netns exec ns2 ip link set lo up
    ip netns exec ns2 ip link set vnet2 up
    ip netns exec ns2 ip addr add 10.0.0.3/24 dev vnet2

    ip netns exec ns3 ip link set lo up
    ip netns exec ns3 ip link set vnet4 up
    ip netns exec ns3 ip addr add 10.0.0.4/24 dev vnet4
    ip link set vnet3 up

#测试通信情况
    ip netns exec ns0 ping 10.0.0.2 -c1
    ip netns exec ns0 ping 10.0.0.3 -c1
    ip netns exec ns1 ping 10.0.0.1 -c1
    ip netns exec ns1 ping 10.0.0.3 -c1
    ip netns exec ns2 ping 10.0.0.1 -c1
    ip netns exec ns2 ping 10.0.0.2 -c1
    ip netns exec ns3 ping 10.0.0.1 -c1         #默认不通,需要将veth pair 对端设备vnet3 设置为up;ip link set vnet3 up
    ip netns exec ns3 ping 10.0.0.2 -c1         #默认不通,需要将veth pair 对端设备vnet3 设置为up;ip link set vnet3 up
    ip netns exec ns3 ping 10.0.0.3 -c1         #默认不通,需要将veth pair 对端设备vnet3 设置为up;ip link set vnet3 up



[root@yefeng ~]# ovs-vsctl list-br
br-int
[root@yefeng ~]# ovs-vsctl show
130f1e2f-edaf-40d2-b55b-d45f850ccf2d
    Bridge br-int
        Port "vnet2"
            Interface "vnet2"
                type: internal
        Port "vnet1"
            Interface "vnet1"
                type: internal
        Port "vnet0"
            Interface "vnet0"
                type: internal
        Port br-int
            Interface br-int
                type: internal
        Port "vnet3"
            Interface "vnet3"       #add port时,默认类型为normal
    ovs_version: "2.5.4"


[root@yefeng ~]# ip a s br-int
7: br-int: <BROADCAST,MULTICAST> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 9a:81:4f:de:da:4f brd ff:ff:ff:ff:ff:ff
[root@yefeng ~]# ip link set br-int up
[root@yefeng ~]# tcpdump -i br-int icmp         #即使手工up,也抓不到包!


----------------------------------------------------------------------------------------------------------------------------
实验二: 单机隔离网络
使用ovs构建隔离网络也很简单,只需要给相应的端口设置上VLAN标签,就能实现网络的隔离。


ovs-vsctl set Port vnet0 tag=100        # 设置vnet0的VLAN tag为100

ovs-vsctl set Port vnet1 tag=200        # 设置vnet1和vnet2的VLAN tag为200
ovs-vsctl set Port vnet2 tag=200        # 设置vnet1和vnet2的VLAN tag为200


[root@yefeng ~]# ovs-vsctl show
130f1e2f-edaf-40d2-b55b-d45f850ccf2d
    Bridge br-int
        Port "vnet2"
            tag: 200                    # 设置vnet1和vnet2的VLAN tag为200
            Interface "vnet2"
                type: internal
        Port "vnet1"
            tag: 200                    # 设置vnet1和vnet2的VLAN tag为200
            Interface "vnet1"
                type: internal
        Port "vnet0"
            tag: 100                    # 设置vnet0的VLAN tag为100
            Interface "vnet0"
                type: internal
        Port br-int
            Interface br-int
                type: internal
        Port "vnet3"
            Interface "vnet3"
    ovs_version: "2.5.4"



ip netns exec ns0 ping 10.0.0.2 -c1     #因为vlan隔离,所以不通
ip netns exec ns0 ping 10.0.0.3 -c1     #因为vlan隔离,所以不通

ip netns exec ns1 ping 10.0.0.3 -c1     #处于相同vlan,互通没问题
ip netns exec ns2 ping 10.0.0.2 -c1     #处于相同vlan,互通没问题


ip netns exec ns0 ping 10.0.0.4
ip netns exec ns1 ping 10.0.0.4

[root@yefeng ~]# tcpdump -nnei vnet3
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vnet3, link-type EN10MB (Ethernet), capture size 262144 bytes
#可以抓到10.0.0.1的免费ARP查询报文,携带vlan id 100;
09:32:06.152103 da:9a:f1:97:8e:a1 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 28
09:32:07.176163 da:9a:f1:97:8e:a1 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 28
09:32:08.200905 da:9a:f1:97:8e:a1 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 28
#可以抓到10.0.0.1的免费ARP查询报文,携带vlan id 200;
09:34:11.976409 72:4b:4b:20:ca:26 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 200, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.2, length 28
09:34:13.000879 72:4b:4b:20:ca:26 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 200, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.2, length 28
09:34:14.024094 72:4b:4b:20:ca:26 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 200, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.2, length 28

---------------------------------------------------------------
清理实验环境
ovs-vsctl del-br br-int
ip netns del ns0
ip netns del ns1
ip netns del ns2
ip netns del ns3
实验一:单机无隔离网络;实验二: 单机隔离网络(vlan隔离)

 

实验1:分布式无隔离网络;实验2:分布式隔离网络(vlan隔离);实验3:分布式隔离网络(vlan隔离)的强制通信(ovs流表修改vlan)
==============================================================================================================================
实验1:分布式无隔离网络
网络拓扑如下图所示,我们每一台节点都有两张网卡,一张用于管理,一张用于业务。之所以使用两张网卡有两个原因:
    1.管理网卡用于日常的维护登录,业务网卡用于传输虚拟节点的数据报文,避免相互之间影响。
    2.我们要将业务网卡绑定到OVS网桥上,也就是Normal类型的Port。这种方式添加的Port不支持分配IP地址,如果之前网卡上配置的有IP,挂载到OVS上面之后将不可访问。

    需要注意的是,如果是使用物理环境搭建网络拓扑,需要把业务网卡对应的交换机端口配置为trunk模式。如果是使用VmWare搭建网络拓扑,业务网卡需要配置网络类型为仅主机模式。


配置环境 主机A
    ovs-vsctl add-br br-int
    ovs-vsctl add-port br-int ens36          # 请修改ens36为当前实验环境的业务网卡名称

    ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal        # 添加两个内部端口
    ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal

    ip netns add ns0                # 添加两个netns
    ip netns add ns1
    ip link set vnet0 netns ns0     # 将内部端口分别移动到netns中
    ip link set vnet1 netns ns1

    ip netns exec ns0 ip link set lo up             # 启动端口并配置IP
    ip netns exec ns0 ip link set vnet0 up
    ip netns exec ns0 ip addr add 10.0.0.1/24 dev vnet0

    ip netns exec ns1 ip link set lo up             # 启动端口并配置IP
    ip netns exec ns1 ip link set vnet1 up
    ip netns exec ns1 ip addr add 10.0.0.2/24 dev vnet1

配置环境 主机B
    ovs-vsctl add-br br-int
    ovs-vsctl add-port br-int ens36              # 请修改ens36为当前实验环境的业务网卡名称

    ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal        # 添加两个内部端口
    ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal

    ip netns add ns0                            # 添加两个netns
    ip netns add ns1

    ip link set vnet0 netns ns0                 # 将内部端口分别移动到netns中
    ip link set vnet1 netns ns1

    ip netns exec ns0 ip link set lo up         # 启动端口并配置IP
    ip netns exec ns0 ip link set vnet0 up
    ip netns exec ns0 ip addr add 10.0.0.3/24 dev vnet0

    ip netns exec ns1 ip link set lo up         # 启动端口并配置IP
    ip netns exec ns1 ip link set vnet1 up
    ip netns exec ns1 ip addr add 10.0.0.4/24 dev vnet1

测试
    
测试 主机A
    ip netns exec ns0 ping 10.0.0.2 -c1         #
    ip netns exec ns0 ping 10.0.0.3 -c1         #
    ip netns exec ns0 ping 10.0.0.4 -c1         #
    ip netns exec ns1 ping 10.0.0.1 -c1         #
    ip netns exec ns1 ping 10.0.0.3 -c1         #
    ip netns exec ns1 ping 10.0.0.4 -c1         #
测试 主机B
    ip netns exec ns0 ping 10.0.0.1 -c1         #
    ip netns exec ns0 ping 10.0.0.2 -c1         #
    ip netns exec ns0 ping 10.0.0.4 -c1         #
    ip netns exec ns1 ping 10.0.0.1 -c1         #
    ip netns exec ns1 ping 10.0.0.2 -c1         #
    ip netns exec ns1 ping 10.0.0.3 -c1         #


[root@yefeng ~]# tcpdump -nnei ens36 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens36, link-type EN10MB (Ethernet), capture size 262144 bytes
10:25:23.853594 4a:c2:27:6b:2a:9c > a2:c6:fa:8b:de:6c, ethertype IPv4 (0x0800), length 98: 10.0.0.2 > 10.0.0.4: ICMP echo request, id 2429, seq 1, length 64
10:25:23.853819 a2:c6:fa:8b:de:6c > 4a:c2:27:6b:2a:9c, ethertype IPv4 (0x0800), length 98: 10.0.0.4 > 10.0.0.2: ICMP echo reply, id 2429, seq 1, length 64

------------------------------------------------------------------------------------------------------------------
实验2:分布式隔离网络
在实验1的基础上,对ovs接口进行vlan划分,实现跨物理设备的隔离与通信
配置环境 主机A
    ovs-vsctl set Port vnet0 tag=100
    ovs-vsctl set Port vnet1 tag=200
配置环境 主机B
    ovs-vsctl set Port vnet0 tag=100
    ovs-vsctl set Port vnet1 tag=200

vlan 100:10.0.0.1、10.0.0.3
vlan 200:10.0.0.2、10.0.0.4
测试 主机A
    ip netns exec ns0 ping 10.0.0.2 -c1         #不通
    ip netns exec ns0 ping 10.0.0.3 -c1         #
    ip netns exec ns0 ping 10.0.0.4 -c1         #不通
    ip netns exec ns1 ping 10.0.0.1 -c1         #不通
    ip netns exec ns1 ping 10.0.0.3 -c1         #不通
    ip netns exec ns1 ping 10.0.0.4 -c1         #
测试 主机B
    ip netns exec ns0 ping 10.0.0.1 -c1         #
    ip netns exec ns0 ping 10.0.0.2 -c1         #不通
    ip netns exec ns0 ping 10.0.0.4 -c1         #不通
    ip netns exec ns1 ping 10.0.0.1 -c1         #不通
    ip netns exec ns1 ping 10.0.0.2 -c1         #
    ip netns exec ns1 ping 10.0.0.3 -c1         #不通

[root@yefeng ~]# tcpdump -nnei ens36 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens36, link-type EN10MB (Ethernet), capture size 262144 bytes
10:37:03.878421 12:94:2f:95:b0:c9 > 26:ac:db:49:c9:dd, ethertype 802.1Q (0x8100), length 102: vlan 100, p 0, ethertype IPv4, 10.0.0.1 > 10.0.0.3: ICMP echo request, id 2585, seq 8, length 64
10:37:03.878476 26:ac:db:49:c9:dd > 12:94:2f:95:b0:c9, ethertype 802.1Q (0x8100), length 102: vlan 100, p 0, ethertype IPv4, 10.0.0.3 > 10.0.0.1: ICMP echo reply, id 2585, seq 8, length 64

[root@yefeng ~]# tcpdump -nnei ens36
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens36, link-type EN10MB (Ethernet), capture size 262144 bytes
#10.0.0.4划分在vlan200,所以不响应icmp request包
10:37:58.749230 12:94:2f:95:b0:c9 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
10:37:59.773014 12:94:2f:95:b0:c9 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
10:38:00.796742 12:94:2f:95:b0:c9 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46



------------------------------------------------------------------------------------------------------------------
实验3:分布式隔离网络(vlan隔离)的强制通信(ovs流表修改vlan)【我的实验】


#配置流表前,在host2物理网卡抓包,可以发现只有icmp request包,因为10.0.0.1为vlan100,而10.0.0.4为vlan200,ovs不会将icmp request报文发给10.0.0.4,因此不会有回包
[root@yefeng ~]# tcpdump -nnei ens36 arp            
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens36, link-type EN10MB (Ethernet), capture size 262144 bytes
13:32:21.516658 f6:7f:2d:8e:fe:74 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
13:32:22.556467 f6:7f:2d:8e:fe:74 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
13:32:23.580723 f6:7f:2d:8e:fe:74 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
13:32:35.450333 f6:7f:2d:8e:fe:74 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
13:32:36.508780 f6:7f:2d:8e:fe:74 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46

#方式1:需要设置为NORMAL,否则ovs仅修改数据包tag,并不会进行转发
    ovs-ofctl add-flow br-int "dl_src=f6:7f:2d:8e:fe:74 actions=mod_vlan_vid:200,NORMAL"  
#方式2:剥离vlan,并从port3发出      
    #ovs-ofctl del-flows br-int "dl_src=f6:7f:2d:8e:fe:74"
    #ovs-ofctl show br-int              #查看ovs port的编号
    #ovs-vsctl show                     #查看port对应的vlan
    #ovs-ofctl add-flow br-int "dl_src=f6:7f:2d:8e:fe:74 actions=strip_vlan,output:3"           
    #####ovs-ofctl add-flow br-int "dl_src=f6:7f:2d:8e:fe:74 actions=mod_vlan_vid:200,output:3"     #错误示例,这样从port3发出的数据包是携带vlan200的!!!!
    
[root@yefeng ~]# ovs-ofctl dump-flows br-int        #查看指定ovs的流表
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=108.071s, table=0, n_packets=106, n_bytes=6784, idle_age=0, hard_age=5, dl_src=f6:7f:2d:8e:fe:74 actions=mod_vlan_vid:200,NORMAL      #新增的流表
 cookie=0x0, duration=1037.332s, table=0, n_packets=1009, n_bytes=87449, idle_age=0, priority=0 actions=NORMAL
 
#新增流表后,可以看到10.0.0.4回应了icmp reply,因为ovs将10.0.0.1的vlan修改为200
[root@yefeng ~]# tcpdump -nnei ens36 arp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens36, link-type EN10MB (Ethernet), capture size 262144 bytes
13:48:27.804649 f6:7f:2d:8e:fe:74 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
13:48:27.804684 36:f0:35:f8:a4:fa > f6:7f:2d:8e:fe:74, ethertype 802.1Q (0x8100), length 46: vlan 200, p 0, ethertype ARP, Reply 10.0.0.4 is-at 36:f0:35:f8:a4:fa, length 28
13:48:28.829738 f6:7f:2d:8e:fe:74 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
13:48:28.829885 36:f0:35:f8:a4:fa > f6:7f:2d:8e:fe:74, ethertype 802.1Q (0x8100), length 46: vlan 200, p 0, ethertype ARP, Reply 10.0.0.4 is-at 36:f0:35:f8:a4:fa, length 28

主机A添加流表
ovs-ofctl add-flow br-int "dl_src=36:f0:35:f8:a4:fa actions=mod_vlan_vid:100,NORMAL" 


[root@yefeng ~]# ip netns exec ns0 ping 10.0.0.4 -c1        #ping包测试通了
PING 10.0.0.4 (10.0.0.4) 56(84) bytes of data.
64 bytes from 10.0.0.4: icmp_seq=1 ttl=64 time=1.40 ms

--- 10.0.0.4 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.409/1.409/1.409/0.000 ms

#在主机B的物理网卡ens36抓包,可以发现10.0.0.1、10.0.0.4所属的vlan id不同,但是ping包是正常的,因为在主机AB的ovs内部进行了流表的修改
[root@yefeng ~]# tcpdump -nnei ens36 icmp                   
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens36, link-type EN10MB (Ethernet), capture size 262144 bytes
14:12:45.660765 f6:7f:2d:8e:fe:74 > 36:f0:35:f8:a4:fa, ethertype 802.1Q (0x8100), length 102: vlan 100, p 0, ethertype IPv4, 10.0.0.1 > 10.0.0.4: ICMP echo request, id 5619, seq 14, length 64
14:12:45.660828 36:f0:35:f8:a4:fa > f6:7f:2d:8e:fe:74, ethertype 802.1Q (0x8100), length 102: vlan 200, p 0, ethertype IPv4, 10.0.0.4 > 10.0.0.1: ICMP echo reply, id 5619, seq 14, length 64


---------------------------------------------------------------------------------------------------------------
清理实验环境
主机AB清理的命令相同
ovs-vsctl del-br br-int
ip netns del ns0
ip netns del ns1
实验1:分布式无隔离网络;实验2:分布式隔离网络(vlan隔离);实验3:分布式隔离网络(vlan隔离)的强制通信(ovs流表修改vlan)

 

镜像端口实验
实验拓扑分为一个网桥,三个虚拟网络设备
    # 添加网桥
        ovs-vsctl add-br br-int
    # 添加三个内部端口
        ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal
        ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal
        ovs-vsctl add-port br-int vnet2 -- set Interface vnet2 type=internal
    # 添加三个netns
        ip netns add ns0
        ip netns add ns1
        ip netns add ns2
    # 将内部端口分别移动到netns中
        ip link set vnet0 netns ns0
        ip link set vnet1 netns ns1
        ip link set vnet2 netns ns2

    # 启动端口并配置IP
        ip netns exec ns0 ip link set lo up
        ip netns exec ns0 ip link set vnet0 up
        ip netns exec ns0 ip addr add 10.0.0.1/24 dev vnet0

        ip netns exec ns1 ip link set lo up
        ip netns exec ns1 ip link set vnet1 up
        ip netns exec ns1 ip addr add 10.0.0.2/24 dev vnet1
    # 注意这里只启动了网卡,但没有配置IP
        ip netns exec ns2 ip link set lo up
        ip netns exec ns2 ip link set vnet2 up

        ovs-vsctl -- set Bridge br-int mirrors=@m \
         -- --id=@vnet1 get Port vnet1 \
         -- --id=@vnet2 get Port vnet2 \
         -- --id=@m create Mirror name=mirror_test select-dst-port=@vnet1 select-src-port=@vnet1 output-port=@vnet2
 
测试
    执行以下命令产生流量
        ip netns exec ns0 ping 10.0.0.2

    重新打开一个终端执行以下命令抓包
        ip netns exec ns2 tcpdump -i vnet2

清理实验环境
    ip netns del ns0
    ip netns del ns1
    ip netns del ns2
    ovs-vsctl del-br br-int
镜像端口实验
vxlan实验;令牌桶实验
----------------------------------------------------------------------------------------
https://time.geekbang.org/column/article/11324
第28讲 | 云中网络的隔离GRE、VXLAN:虽然住一个小区,也要保护隐私
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=1 actions=resubmit(,1)"        从 port 1 进来的,都是发出去的流量,全部由 Table 1 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=2 actions=resubmit(,3)"        从 port 2、3 进来的,都是进入物理机的流量,全部由 Table 3 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=3 actions=resubmit(,3)"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 actions=drop"

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)"      对于单播,由 Table 20 处理。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)"      对于多播,由 Table 21 处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=2 actions=drop"              Table 2 是紧接着 Table1 的,如果既不是单播,也不是多播,就默认丢弃。


Table 3 用于处理所有进来的网络包,需要将隧道 Tunnel ID 转换为 VLAN ID。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=3 actions=drop"          如果匹配不上 Tunnel ID,就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x1 actions=mod_vlan_vid:1,resubmit(,10)"       如果匹配上了 Tunnel ID,就转换为相应的 VLAN ID,然后跳到 Table 10。
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x2 actions=mod_vlan_vid:2,resubmit(,10)"       如果匹配上了 Tunnel ID,就转换为相应的 VLAN ID,然后跳到 Table 10。



ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=10  actions=learn(table=20,priority=1,hard_timeout=300,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1"


---------------------------------------------------------------------------------------------
在云中网络 Openvswitch 中,主要使用的是分层令牌桶规则(HTB),将总的带宽在一棵树上按照配置的比例进行分配,并且在一个分支不用的时候,可以借给另外的分支,从而增强带宽利用率。
ovs-vsctl set port first_br qos=@newqos -- --id=@newqos create qos type=linux-htb other-config:max-rate=10000000 queues=0=@q0,1=@q1,2=@q2 -- --id=@q0 create queue other-config:min-rate=3000000 other-config:max-rate=10000000 -- --id=@q1 create queue other-config:min-rate=1000000 other-config:max-rate=10000000 -- --id=@q2 create queue other-config:min-rate=6000000 other-config:max-rate=10000000

ovs-ofctl add-flow br0 "in_port=6 nw_src=192.168.100.100 actions=enqueue:5:0"
ovs-ofctl add-flow br0 "in_port=7 nw_src=192.168.100.101 actions=enqueue:5:1"
ovs-ofctl add-flow br0 "in_port=8 nw_src=192.168.100.102 actions=enqueue:5:2"
vxlan实验;令牌桶实验
 ovs flow table实验:使用ovs flow规则,创建一个支持VLAN、支持MAC-Learning的ovs
实验场景;实验环境准备
===============================================================================================================
https://www.cnblogs.com/popsuper1982/p/3800535.html
实验:使用ovs flow规则,创建一个支持VLAN、支持MAC-Learning的ovs


实验场景:创建一个Virtual Switch,支持VLAN,支持MAC-Learning

包含下面四个Port:
    P1, truck port
    P2, VLAN 20
    P3, P4 VLAN 30
包含五个flow table:
    Table 0: Admission control.
    Table 1: VLAN input processing.
    Table 2: Learn source MAC and VLAN for ingress port.
    Table 3: Look up learned port for destination MAC and VLAN.
    Table 4: Output processing

-----------------------------------------------------------------------------------------------------------------------
实验环境准备
    ovs-vsctl add-br ovs1 -- set bridge ovs1 fail-mode=secure       #创建ovs
        #如果设为fail-secure mode,则初始情况下flow table是空的,否则会有normal

    ovs-vsctl show                          #查看ovs
    ovs-ofctl show ovs1                     #查看ovs的接口状态
    ovs-ofctl dump-flows ovs1               #查看ovs的flow


    ovs-vsctl add-br ovs2            #创建ovs2
    ovs-ofctl show ovs2
    ovs-ofctl dump-flows ovs2

    创建四个veth pair
    ip link add first_br type veth peer name first_if
    ip link add second_br type veth peer name second_if   
    ip link add third_br type veth peer name third_if      
    ip link add forth_br type veth peer name forth_if

    添加四个端口port
    ovs-vsctl add-port ovs1 first_br -- set interface first_br ofport_request=100       #ofport_request是指定端口号
    ovs-vsctl add-port ovs1 second_br -- set interface second_br ofport_request=200
    ovs-vsctl add-port ovs1 third_br -- set interface third_br ofport_request=300
    ovs-vsctl add-port ovs1 forth_br -- set interface forth_br ofport_request=400


    ip addr                         #新添加的port都是出于DOWN的状态
    ovs-ofctl show ovs1       #接口都是down状态;同时可以看到接口编号
        OFPT_FEATURES_REPLY (xid=0x2): dpid:00002ad5009a6f41
        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
         100(first_br): addr:0a:5b:b5:b6:91:3c  #可以看到接口编号是指定的100
             config:     PORT_DOWN
             state:      LINK_DOWN
             current:    10GB-FD COPPER
             speed: 10000 Mbps now, 0 Mbps max
        …………………………
         LOCAL(ovs1): addr:2a:d5:00:9a:6f:41
             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


    把它们设为UP
        ip link set first_if up
        ip link set first_br up
        ip link set second_br up    
        ip link set second_if up
        ip link set third_if up     
        ip link set third_br up    
        ip link set forth_br up        
        ip link set forth_if up

    也可以用下面的命令
        ovs-ofctl mod-port ovs1 first_br up

    ip addr         #再次查看,确认端口up
    ovs-ofctl show ovs1           #接口状态切换为数字,说明接口up了
        OFPT_FEATURES_REPLY (xid=0x2): dpid:00002ad5009a6f41
        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
         100(first_br): addr:0a:5b:b5:b6:91:3c
             config:     0
             state:      0
             current:    10GB-FD COPPER
             speed: 10000 Mbps now, 0 Mbps max
        ………………………………………………………………
         LOCAL(ovs1): addr:2a:d5:00:9a:6f:41
             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
实验场景;实验环境准备
实现第一个Table 0,Admission control
-----------------------------------------------------------------------------------------------------------------------
实现第一个Table 0,Admission control
    table0规则:丢弃指定的数据包---source address是multicast,STP相关的数据包,都丢弃
                其他数据包则转入table 1继续处理
    包进入vswitch的时候首先进入Table 0,我们在这里可以设定规则,控制那些包可以进入,那些包不可以进入。

    ovs-ofctl add-flow ovs1 "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"       #source address是multicast的就不允许进入。
    ovs-ofctl add-flow ovs1 "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"       #STP的也不接受
    ovs-ofctl add-flow ovs1 "table=0, priority=0, actions=resubmit(,1)"                               #添加最后一个flow,这个flow的priority低于default,如果上面两个不匹配,则我们进入table 1

    ovs-ofctl dump-flows ovs1         #查看一下所有的flow
        NXST_FLOW reply (xid=0x4):
         cookie=0x0, duration=4.214s, table=0, n_packets=0, n_bytes=0, idle_age=4, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=drop
         cookie=0x0, duration=4.209s, table=0, n_packets=0, n_bytes=0, idle_age=4, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=drop
         cookie=0x0, duration=3.356s, table=0, n_packets=0, n_bytes=0, idle_age=3, priority=0 actions=resubmit(,1)


    测试Table 0:
    ovs-appctl ofproto/trace ovs1 in_port=1,dl_dst=01:80:c2:00:00:05              
        Bridge: ovs1
        Flow: in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:80:c2:00:00:05,dl_type=0x0000    #打印flow的各种数据

        Rule: table=0 cookie=0 dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0                                   #匹配的规则
        OpenFlow actions=drop                                                                               #相应的action
                                                                                                            #该工具的测试输出分为2部分:上半部分为匹配过程,逐表匹配,直到结束;此处示例直接匹配了结果为drop,所以只显示了一层
        Final flow: unchanged                                                                               #下半部分为匹配结果。
        Megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop

    ovs-appctl ofproto/trace ovs1 in_port=1,dl_dst=01:80:c2:00:00:10
        Bridge: ovs1
        Flow: in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:80:c2:00:00:10,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)                   #满足条件RESUBMIT,进入table 1继续处理

                Resubmitted flow: in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:80:c2:00:00:10,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=01:80:c2:00:00:10/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=254 cookie=0 priority=0,reg0=0x2        #因为此时未配置table1,所以实际进入table254,匹配的动作drop?
                OpenFlow actions=drop                   

        Final flow: unchanged
        Megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=01:80:c2:00:00:10/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop

            -----------------------------------
            ovs-ofctl mod-flows ovs1 "table=0, priority=0, actions=mod_dl_dst:01:80:c2:ff:ff:10,resubmit(,1)"       #我的测试,为了看到Final flow确实显示了改变
            ovs-ofctl mod-flows ovs1 "table=0, priority=0, actions=resubmit(,1)"                                    #测试结束后,立即回滚了
实现第一个Table 0,Admission control
实现第二个Table 1:VLAN Input Processing
-----------------------------------------------------------------------------------------------------------------------
实现第二个Table 1:VLAN Input Processing
    priority "man ovs-ofctl":取值范围0-65535,默认32768;准确的匹配规则优于包含通配符的规则,其隐式优先级为65535
    table0规则:丢弃指定的数据包---source address是multicast,STP相关的数据包,都丢弃
                其他数据包则转入table 1继续处理
    table1规则:从port2/3/4进入,且vlan_tci=0的数据包,先修改vlan id,再转入table2继续处理
                从port1进入,则直接转入table2进行处理(设计port1为trunk口)
                其他数据包drop

    ovs-ofctl add-flow ovs1 "table=1, priority=0, actions=drop"                           #首先添加一个最低优先级的DROP的规则
    ovs-ofctl add-flow ovs1 "table=1, priority=99, in_port=1, actions=resubmit(,2)"       #对于port 1,是trunk口,无论有没有VLAN Header都接受。

    #对于port 2, 3, 4, 我们希望没有VLAN Tag,然后我们给打上VLAN Tag
    ovs-ofctl add-flows ovs1 -  <<EOF
    table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)      #从port2进入的,vlan_tci=0的数据包
    table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)      #从port3进入的,vlan_tci=0的数据包
    table=1, priority=32768, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)   #从port4进入的,vlan_tci=0的数据包
    EOF     #注意此处EOF前不能有空格,所以不能直接复制

    ovs-ofctl dump-flows ovs1     #查看流表配置
        NXST_FLOW reply (xid=0x4):
         cookie=0x0, duration=2193.703s, table=0, n_packets=0, n_bytes=0, idle_age=2193, hard_age=1385, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,1)
         cookie=0x0, duration=2193.698s, table=0, n_packets=0, n_bytes=0, idle_age=2193, hard_age=1385, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=resubmit(,1)
         cookie=0x0, duration=2192.845s, table=0, n_packets=12, n_bytes=840, idle_age=290, hard_age=1385, priority=0 actions=resubmit(,1)
         cookie=0x0, duration=6.521s, table=1, n_packets=0, n_bytes=0, idle_age=6, priority=99,in_port=2,vlan_tci=0x0000 actions=mod_vlan_vid:20,resubmit(,2)
         cookie=0x0, duration=6.520s, table=1, n_packets=0, n_bytes=0, idle_age=6, priority=99,in_port=3,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=6.520s, table=1, n_packets=0, n_bytes=0, idle_age=6, in_port=4,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)       #指定priority=32768,因为默认priority=32768,所以此处没有显示
         cookie=0x0, duration=308.907s, table=1, n_packets=0, n_bytes=0, idle_age=308, priority=99,in_port=1 actions=resubmit(,2)
         cookie=0x0, duration=310.374s, table=1, n_packets=1, n_bytes=70, idle_age=290, priority=0 actions=drop
    
    #测试一:从port 1进入,tag为5的数据包
    ovs-appctl ofproto/trace ovs1 in_port=1,vlan_tci=5   
        Bridge: ovs1
        Flow: in_port=1,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0           #匹配了table0该条规则
        OpenFlow actions=resubmit(,1)               #转入table1继续处理

                Resubmitted flow: in_port=1,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=1        #匹配了table1该条规则
                OpenFlow actions=resubmit(,2)                       #转入table2继续处理

                        Resubmitted flow: unchanged
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=254 cookie=0 priority=0,reg0=0x2    #因为此时未配置table2,所以实际进入table254,匹配的动作drop?
                        OpenFlow actions=drop

        Final flow: unchanged
        Megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop
    
    #测试二:从port 2进入,没有打Tag的
    ovs-appctl ofproto/trace ovs1 in_port=2       
        Bridge: ovs1
        Flow: in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0           #匹配了table0该条规则
        OpenFlow actions=resubmit(,1)               #转入table1继续处理

                Resubmitted flow: in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000        #匹配了table1该条规则
                OpenFlow actions=mod_vlan_vid:20,resubmit(,2)                       #先修改vlan id,再转入table2继续处理

                        Resubmitted flow: in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=254 cookie=0 priority=0,reg0=0x2                #因为此时未配置table2,所以实际进入table254,匹配的动作drop?
                        OpenFlow actions=drop

        Final flow: in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
        Megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop
    
    #测试三:从port进入,带Tag 5的
    ovs-appctl ofproto/trace ovs1 in_port=2,vlan_tci=5
        Bridge: ovs1
        Flow: in_port=2,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0       #匹配了table0该条规则    
        OpenFlow actions=resubmit(,1)           #转入table1继续处理

                Resubmitted flow: in_port=2,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0001/0x0001,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=0       #匹配了table1 最低优先级的那条规则,数据包被drop
                OpenFlow actions=drop

        Final flow: unchanged
        Megaflow: recirc_id=0,in_port=2,vlan_tci=0x0001/0x1001,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop
    
实现第二个Table 1:VLAN Input Processing
实现第三个Table 2: MAC, VLAN learning for ingress port
-----------------------------------------------------------------------------------------------------------------------
实现第三个Table 2: MAC, VLAN learning for ingress port
    对于普通的switch,都会有这个学习的过程,当一个包到来的时候,由于包里面有MAC,VLAN Tag,以及从哪个口进来的这个信息。于是switch学习后,维护了一个表格port –> MAC –> VLAN Tag。
    这样以后如果有需要发给这个MAC的包,不用ARP,switch自然之道应该发给哪个port,应该打什么VLAN Tag。
    OVS也要学习这个,并维护三个之间的mapping关系。
    
    在我们的例子中,无论是从port进来的本身就带Tag的,还是从port 2, 3, 4进来的后来被打上Tag的,都需要学习。
    ovs-ofctl add-flow ovs1 "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), resubmit(,3)"
        learn表示这是一个学习的action
        table 10,这是一个MAC learning table,学习的结果会放在这个table中。
        NXM_OF_VLAN_TCI这个是VLAN Tag,在MAC Learning table中,每一个entry都是仅仅对某一个VLAN来说的,不同VLAN的learning table是分开的。在学习的结果的entry中,会标出这个entry是对于哪个VLAN的。
        NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]这个的意思是当前包里面的MAC Source Address会被放在学习结果的entry里面的dl_dst里面。
            这是因为每个switch都是通过Ingress包来学习,某个MAC从某个port进来,switch就应该记住以后发往这个MAC的包要从这个port出去,因而MAC source address就被放在了Mac destination address里面,因为这是为发送用的。
        NXM_OF_IN_PORT[]->NXM_NX_REG0将portf放入register.
        一般对于学习的entry还需要有hard_timeout,这是的每个学习结果都会expire,需要重新学习。

    ***********************插入一个学习***********************
        我们再来分析一个实践中,openstack中使用openvswitch的情况,这是br-tun上的规则。
        cookie=0x0, duration=802188.071s, table=10, n_packets=4885, n_bytes=347789, idle_age=730, hard_age=65534, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1
        cookie=0x0, duration=802187.786s, table=20, n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534, priority=0 actions=resubmit(,21)
        cookie=0x0, duration=802038.514s, table=20, n_packets=1239, n_bytes=83620, idle_age=735, hard_age=65534, priority=2,dl_vlan=1,dl_dst=fa:16:3e:7e:ab:cc actions=strip_vlan,set_tunnel:0x3e9,output:2
        cookie=0x0, duration=802187.653s, table=21, n_packets=17, n_bytes=1426, idle_age=65534, hard_age=65534, priority=0 actions=drop
        cookie=0x0, duration=802055.878s, table=21, n_packets=40, n_bytes=1736, idle_age=65534, hard_age=65534, dl_vlan=1 actions=strip_vlan,set_tunnel:0x3e9,output:2
            这里table 10 是用来学习的。table 20是learning table。如果table 20是空的,也即还没有学到什么,则会通过priority=0的规则resubmit到table 21.
            table 21是发送规则,将br-int上的vlan tag消除,然后打上gre tunnel的id。
            上面的情况中,table 20不是空的,也即发送给dl_dst=fa:16:3e:7e:ab:cc的包不用走默认规则,直接通过table 20就发送出去了。
            table 20的规则是通过table 10学习得到的,table 10是一个接受规则。最终output 1,发送给了br-int

            NXM_OF_VLAN_TCI[0..11]是记录vlan tag,所以学习结果中有dl_vlan=1
            NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]是将mac source address记录,所以结果中有dl_dst=fa:16:3e:7e:ab:cc
            load:0->NXM_OF_VLAN_TCI[]意思是发送出去的时候,vlan tag设为0,所以结果中有actions=strip_vlan
            load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[]意思是发出去的时候,设置tunnul id,所以结果中有set_tunnel:0x3e9
            output:NXM_OF_IN_PORT[]意思是发送给哪个port,由于是从port2进来的,因而结果中有output:2
    ***********************插入学习结束***********************
    
    table0规则:丢弃指定的数据包---source address是multicast,STP相关的数据包,都丢弃
                其他数据包则转入table 1继续处理
    table1规则:从port2/3/4进入,且vlan_tci=0的数据包,先修改vlan id,再转入table2继续处理
                从port1进入,则直接转入table2进行处理(设计port1为trunk口)
                其他数据包drop
    table2规则:仅有1条规则,无匹配项,只有actions,该actions为learn;所以数据包只要进入到table2,就会触发学习,动态生成table10规则;然后数据包转入到table3继续处理
        
    [root@yefeng ~]# ovs-ofctl dump-flows ovs1
        NXST_FLOW reply (xid=0x4):
         cookie=0x0, duration=4166.643s, table=0, n_packets=0, n_bytes=0, idle_age=4166, hard_age=3358, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,1)
         cookie=0x0, duration=4166.638s, table=0, n_packets=0, n_bytes=0, idle_age=4166, hard_age=3358, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=resubmit(,1)
         cookie=0x0, duration=4165.785s, table=0, n_packets=15, n_bytes=1050, idle_age=559, hard_age=3358, priority=0 actions=resubmit(,1)
         cookie=0x0, duration=1979.461s, table=1, n_packets=0, n_bytes=0, idle_age=1979, priority=99,in_port=2,vlan_tci=0x0000 actions=mod_vlan_vid:20,resubmit(,2)
         cookie=0x0, duration=1979.460s, table=1, n_packets=0, n_bytes=0, idle_age=1979, priority=99,in_port=3,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=1979.460s, table=1, n_packets=0, n_bytes=0, idle_age=1979, in_port=4,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=2281.847s, table=1, n_packets=0, n_bytes=0, idle_age=2281, priority=99,in_port=1 actions=resubmit(,2)
         cookie=0x0, duration=2283.314s, table=1, n_packets=4, n_bytes=280, idle_age=559, priority=0 actions=drop
         cookie=0x0, duration=16.012s, table=2, n_packets=0, n_bytes=0, idle_age=16, actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

    #测试一:从port 1来一个vlan为20的mac为50:00:00:00:00:01的包
    ovs-appctl ofproto/trace ovs1 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate          #携带'-generate'参数时,测试命令也能触发learn,自动生成table10
        Bridge: ovs1
        Flow: in_port=1,vlan_tci=0x0014,dl_src=50:00:00:00:00:01,dl_dst=00:00:00:00:00:00,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0               #匹配了table0该条规则,转入table1继续处理
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=1,vlan_tci=0x0014,dl_src=50:00:00:00:00:01,dl_dst=00:00:00:00:00:00,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=1        #匹配了table1该条规则,转入table2继续处理
                OpenFlow actions=resubmit(,2)

                        Resubmitted flow: unchanged
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0                      #table2没有规则,即全部匹配,触发了learn动作,转入table3继续处理
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x0fff,dl_src=50:00:00:00:00:01,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=254 cookie=0 priority=0,reg0=0x2        #table3未配置,所以实际进入table254,匹配的动作drop?
                                OpenFlow actions=drop

        Final flow: unchanged
        Megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x1fff,dl_src=50:00:00:00:00:01,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop

    [root@yefeng ~]# ovs-ofctl dump-flows ovs1      #自动生成table10规则
    NXST_FLOW reply (xid=0x4):
     cookie=0x0, duration=4785.734s, table=0, n_packets=0, n_bytes=0, idle_age=4785, hard_age=3977, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,1)
     cookie=0x0, duration=4785.729s, table=0, n_packets=0, n_bytes=0, idle_age=4785, hard_age=3977, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=resubmit(,1)
     cookie=0x0, duration=4784.876s, table=0, n_packets=16, n_bytes=1120, idle_age=293, hard_age=3977, priority=0 actions=resubmit(,1)
     cookie=0x0, duration=2598.552s, table=1, n_packets=0, n_bytes=0, idle_age=2598, priority=99,in_port=2,vlan_tci=0x0000 actions=mod_vlan_vid:20,resubmit(,2)
     cookie=0x0, duration=2598.551s, table=1, n_packets=0, n_bytes=0, idle_age=2598, priority=99,in_port=3,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
     cookie=0x0, duration=2598.551s, table=1, n_packets=0, n_bytes=0, idle_age=2598, in_port=4,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
     cookie=0x0, duration=2900.938s, table=1, n_packets=0, n_bytes=0, idle_age=2900, priority=99,in_port=1 actions=resubmit(,2)
     cookie=0x0, duration=2902.405s, table=1, n_packets=5, n_bytes=350, idle_age=293, priority=0 actions=drop
     cookie=0x0, duration=635.103s, table=2, n_packets=0, n_bytes=0, idle_age=635, actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)
     cookie=0x0, duration=2.098s, table=10, n_packets=0, n_bytes=0, idle_age=2, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]

    ovs-ofctl dump-flows ovs1
        table 10多了一条,vlan为20,dl_dst为50:00:00:00:00:01,发送的时候从port 1出去。???????
        所以可以配置被动的学习规则?????如果有匹配,则会创建相应的规则????
    
    #测试二:从port 2进来,被打上了vlan 20,mac为50:00:00:00:00:02
    ovs-appctl ofproto/trace ovs1 in_port=2,dl_src=50:00:00:00:00:02 -generate                
        Bridge: ovs1
        Flow: in_port=2,vlan_tci=0x0000,dl_src=50:00:00:00:00:02,dl_dst=00:00:00:00:00:00,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0           #匹配了table0该条规则,转入table1继续处理
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=2,vlan_tci=0x0000,dl_src=50:00:00:00:00:02,dl_dst=00:00:00:00:00:00,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000        #匹配了table1该条规则,先修改vlan id为20,再转入table2继续处理
                OpenFlow actions=mod_vlan_vid:20,resubmit(,2)

                        Resubmitted flow: in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=50:00:00:00:00:02,dl_dst=00:00:00:00:00:00,dl_type=0x0000
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0                                      #table2没有规则,即全部匹配,触发了learn动作,转入table3继续处理
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=50:00:00:00:00:02,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=254 cookie=0 priority=0,reg0=0x2        #table3未配置,所以实际进入table254,匹配的动作drop?
                                OpenFlow actions=drop

        Final flow: in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=50:00:00:00:00:02,dl_dst=00:00:00:00:00:00,dl_type=0x0000     #显示了修改:dl_vlan=20
        Megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=50:00:00:00:00:02,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop


    [root@yefeng ~]# ovs-ofctl dump-flows ovs1      #自动生成一条新的table10规则
    NXST_FLOW reply (xid=0x4):
     cookie=0x0, duration=5130.351s, table=0, n_packets=0, n_bytes=0, idle_age=5130, hard_age=4321, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,1)
     cookie=0x0, duration=5130.346s, table=0, n_packets=0, n_bytes=0, idle_age=5130, hard_age=4321, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=resubmit(,1)
     cookie=0x0, duration=5129.493s, table=0, n_packets=16, n_bytes=1120, idle_age=638, hard_age=4321, priority=0 actions=resubmit(,1)
     cookie=0x0, duration=2943.169s, table=1, n_packets=0, n_bytes=0, idle_age=2943, priority=99,in_port=2,vlan_tci=0x0000 actions=mod_vlan_vid:20,resubmit(,2)
     cookie=0x0, duration=2943.168s, table=1, n_packets=0, n_bytes=0, idle_age=2943, priority=99,in_port=3,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
     cookie=0x0, duration=2943.168s, table=1, n_packets=0, n_bytes=0, idle_age=2943, in_port=4,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
     cookie=0x0, duration=3245.555s, table=1, n_packets=0, n_bytes=0, idle_age=3245, priority=99,in_port=1 actions=resubmit(,2)
     cookie=0x0, duration=3247.022s, table=1, n_packets=5, n_bytes=350, idle_age=638, priority=0 actions=drop
     cookie=0x0, duration=979.720s, table=2, n_packets=0, n_bytes=0, idle_age=979, actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)
     cookie=0x0, duration=346.715s, table=10, n_packets=0, n_bytes=0, idle_age=346, hard_age=128, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
     cookie=0x0, duration=3.763s, table=10, n_packets=0, n_bytes=0, idle_age=3, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:02 actions=load:0x2->NXM_NX_REG0[0..15]
实现第三个Table 2: MAC, VLAN learning for ingress port
实现第四个table 3: Look Up Destination Port
-----------------------------------------------------------------------------------------------------------------------
实现第四个table 3: Look Up Destination Port
    ***看起来table2+table3就是为了模拟实现交换机自动学习mac的功能嘛,自动生成相应的table10表项,然后回包时可以根据table10规则找到相应的port发出去,而不用每次都flood
        在table 2中,vswtich通过进入的包,学习了vlanid –> mac –> port的映射后,对于要发送的包,可以根据学习到的table 10里面的内容,根据destination mac和vlan,来找到相应的port发送出去,而不用每次都flood
        
    table0规则:丢弃指定的数据包---source address是multicast,STP相关的数据包,都丢弃
                其他数据包则转入table 1继续处理
    table1规则:从port2/3/4进入,且vlan_tci=0的数据包,先修改vlan id,再转入table2继续处理
                从port1进入,则直接转入table2进行处理(设计port1为trunk口)
                其他数据包drop
    table2规则:仅有1条规则,无匹配项,只有actions,该actions为learn;所以数据包只要进入到table2,就会触发学习,动态生成table10规则;然后数据包转入到table3继续处理
    table3规则:1.如果是广播包,则转入table4继续处理
                2.其他数据包则先到table10处理;若table10无匹配,则到table4继续处理
                
                
    ovs-ofctl add-flow ovs1 "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"                               #首先到table 10中查找learn table entry,如果找不到则到table 4;
    ovs-ofctl add-flow ovs1 "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,4)"   #如果包本身就是multicast的或者broadcast的,则不用去table 10里面取查找。

    #测试1,自动生成table10规则
    ovs-appctl ofproto/trace ovs1 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate 
        Bridge: ovs1
        Flow: in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0               #匹配了table0该条规则,转入table1继续处理
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=90:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=1    #匹配了table1该条规则,转入table2继续处理
                OpenFlow actions=resubmit(,2)

                        Resubmitted flow: unchanged
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=90:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0                  #table2自动生成table10规则,然后转入table3继续处理
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x0fff,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=50          #table3先将数据包转入table10处理,若table10无匹配,则到table4继续处理
                                OpenFlow actions=resubmit(,10),resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x0fff,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=254 cookie=0 priority=0,reg0=0x2        #table10匹配无结果
                                        OpenFlow actions=drop

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x0fff,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=254 cookie=0 priority=0,reg0=0x2        #table4匹配无结果
                                        OpenFlow actions=drop

        Final flow: unchanged
        Megaflow: recirc_id=0,in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
        Datapath actions: drop

        ***测试流的源mac为f0:00:00:00:00:01,所以table2自动生成了一条table10规则,目标mac为f0:00:00:00:00:01,这样回包时,可以通过这条table10规则直接处理
        
    ovs-ofctl dump-flows ovs1
        NXST_FLOW reply (xid=0x4):
         cookie=0x0, duration=6400.806s, table=0, n_packets=0, n_bytes=0, idle_age=6400, hard_age=5592, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,1)
         cookie=0x0, duration=6400.801s, table=0, n_packets=0, n_bytes=0, idle_age=6400, hard_age=5592, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=resubmit(,1)
         cookie=0x0, duration=6399.948s, table=0, n_packets=16, n_bytes=1120, idle_age=1908, hard_age=5592, priority=0 actions=resubmit(,1)
         cookie=0x0, duration=4213.624s, table=1, n_packets=0, n_bytes=0, idle_age=4213, priority=99,in_port=2,vlan_tci=0x0000 actions=mod_vlan_vid:20,resubmit(,2)
         cookie=0x0, duration=4213.623s, table=1, n_packets=0, n_bytes=0, idle_age=4213, priority=99,in_port=3,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=4213.623s, table=1, n_packets=0, n_bytes=0, idle_age=4213, in_port=4,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=4516.010s, table=1, n_packets=0, n_bytes=0, idle_age=4516, priority=99,in_port=1 actions=resubmit(,2)
         cookie=0x0, duration=4517.477s, table=1, n_packets=5, n_bytes=350, idle_age=1908, priority=0 actions=drop
         cookie=0x0, duration=2250.175s, table=2, n_packets=0, n_bytes=0, idle_age=2250, actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)
         cookie=0x0, duration=532.343s, table=3, n_packets=0, n_bytes=0, idle_age=532, priority=99,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,4)
         cookie=0x0, duration=555.660s, table=3, n_packets=0, n_bytes=0, idle_age=555, priority=50 actions=resubmit(,10),resubmit(,4)
         cookie=0x0, duration=1617.170s, table=10, n_packets=0, n_bytes=0, idle_age=1617, hard_age=1398, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
         cookie=0x0, duration=1274.218s, table=10, n_packets=0, n_bytes=0, idle_age=1274, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:02 actions=load:0x2->NXM_NX_REG0[0..15]
         cookie=0x0, duration=349.222s, table=10, n_packets=0, n_bytes=0, idle_age=349, hard_age=176, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
    
    #测试2:自动生成另一条table10规则,同时数据包匹配了测试1自动生成的规则
    ovs-appctl ofproto/trace ovs1 in_port=2,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01 -generate   
        Bridge: ovs1
        Flow: in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=f0:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000
                OpenFlow actions=mod_vlan_vid:20,resubmit(,2)

                        Resubmitted flow: in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=f0:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=50
                                OpenFlow actions=resubmit(,10),resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01     #匹配了测试1自动生成的规则
                                        OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]

                                        Resubmitted flow: reg0=0x1,in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
                                        Resubmitted regs: reg0=0x1 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,reg0=0/0xffff,in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=254 cookie=0 priority=0,reg0=0x2                #看起来无论是否匹配了table10,都会进入table4继续匹配嘛。。。 
                                        OpenFlow actions=drop

        Final flow: reg0=0x1,in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
        Megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
        Datapath actions: drop


    #测试3:再次发送测试1的数据包,这一次匹配了测试2自动生成的规则
    ovs-appctl ofproto/trace ovs1 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate   #我们再发送第一次的包
        Bridge: ovs1
        Flow: in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=90:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=1
                OpenFlow actions=resubmit(,2)

                        Resubmitted flow: unchanged
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=90:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x0fff,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=50
                                OpenFlow actions=resubmit(,10),resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x0fff,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01     #匹配了测试2自动生成的规则
                                        OpenFlow actions=load:0x2->NXM_NX_REG0[0..15]

                                        Resubmitted flow: reg0=0x2,in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
                                        Resubmitted regs: reg0=0x2 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,reg0=0/0xffff,in_port=1,vlan_tci=0x0014/0x0fff,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=254 cookie=0 priority=0,reg0=0x2                #看起来无论是否匹配了table10,都会进入table4继续匹配嘛。。。                        
                                        OpenFlow actions=drop

        Final flow: reg0=0x2,in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
        Megaflow: recirc_id=0,in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
        Datapath actions: drop

    [root@yefeng ~]# ovs-ofctl dump-flows ovs1
        NXST_FLOW reply (xid=0x4):
         cookie=0x0, duration=7236.807s, table=0, n_packets=0, n_bytes=0, idle_age=7236, hard_age=6428, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,1)
         cookie=0x0, duration=7236.802s, table=0, n_packets=0, n_bytes=0, idle_age=7236, hard_age=6428, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=resubmit(,1)
         cookie=0x0, duration=7235.949s, table=0, n_packets=17, n_bytes=1190, idle_age=123, hard_age=6428, priority=0 actions=resubmit(,1)
         cookie=0x0, duration=5049.625s, table=1, n_packets=0, n_bytes=0, idle_age=5049, priority=99,in_port=2,vlan_tci=0x0000 actions=mod_vlan_vid:20,resubmit(,2)
         cookie=0x0, duration=5049.624s, table=1, n_packets=0, n_bytes=0, idle_age=5049, priority=99,in_port=3,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=5049.624s, table=1, n_packets=0, n_bytes=0, idle_age=5049, in_port=4,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=5352.011s, table=1, n_packets=0, n_bytes=0, idle_age=5352, priority=99,in_port=1 actions=resubmit(,2)
         cookie=0x0, duration=5353.478s, table=1, n_packets=6, n_bytes=420, idle_age=123, priority=0 actions=drop
         cookie=0x0, duration=3086.176s, table=2, n_packets=0, n_bytes=0, idle_age=3086, actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)
         cookie=0x0, duration=1368.344s, table=3, n_packets=0, n_bytes=0, idle_age=1368, priority=99,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,4)
         cookie=0x0, duration=1391.661s, table=3, n_packets=0, n_bytes=0, idle_age=1391, priority=50 actions=resubmit(,10),resubmit(,4)
         cookie=0x0, duration=2453.171s, table=10, n_packets=0, n_bytes=0, idle_age=2453, hard_age=2234, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
         cookie=0x0, duration=2110.219s, table=10, n_packets=0, n_bytes=0, idle_age=2110, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:02 actions=load:0x2->NXM_NX_REG0[0..15]
         cookie=0x0, duration=1185.223s, table=10, n_packets=0, n_bytes=0, idle_age=1185, hard_age=281, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
         cookie=0x0, duration=351.423s, table=10, n_packets=0, n_bytes=0, idle_age=351, vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
实现第四个table 3: Look Up Destination Port
实现第五个table 4: Output Processing
------------------------------------------------------------------------------------------------------------------------------------------------------
实现第五个table 4: Output Processing
    table0规则:丢弃指定的数据包---source address是multicast,STP相关的数据包,都丢弃
                其他数据包则转入table 1继续处理
    table1规则:从port2/3/4进入,且vlan_tci=0的数据包,先修改vlan id,再转入table2继续处理
                从port1进入,则直接转入table2进行处理(设计port1为trunk口)
                其他数据包drop
    table2规则:仅有1条规则,无匹配项,只有actions,该actions为learn;所以数据包只要进入到table2,就会触发学习,动态生成table10规则;然后数据包转入到table3继续处理
    table3规则:1.如果是广播包,则转入table4继续处理
                2.其他数据包则先到table10处理;若table10无匹配,则到table4继续处理
    table4规则:1.reg0=1 actions=1     reg01=1,即port1?因为port1是trunk port,所以不进行处理,从port1发出去
                2.reg0=2、3、4         则剥离vlan tag,然后从相应的port发出去


    -------------------------------
    ovs-ofctl add-flow ovs1 "table=4 reg0=1 actions=1"      #对于port 1来讲,是trunk port,所以携带的vlan tag就让他带着,从port 1出去。
    -------------------------------
    #对于port 2来讲,是vlan 20的,然而出去的时候,vlan tag会被抹掉,从port 2发出去
    #对于port 3, 4来讲,是vlan 30的,然而出去的时候,vlan tag会被抹掉,从port 3, 4出去
    ovs-ofctl add-flows ovs1 - <<'EOF'         
        table=4 reg0=2 actions=strip_vlan,2
        table=4 reg0=3 actions=strip_vlan,3
        table=4 reg0=4 actions=strip_vlan,4
    EOF         #注意:EOF前面不要有空格
    -------------------------------
    #对于broadcast来讲,我们希望一个vlan的broadcast仅仅在这个vlan里面发送,不影响其他的vlan。
    ovs-ofctl add-flows ovs1 - <<'EOF'  
        table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
        table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
        table=4 reg0=0 priority=50            actions=1
    EOF
    #所以对于register = 0的,也即是broadcast的,属于vlan 20的,则从port 1, 2出去,属于vlan 30的,则从port 1, 3, 4出去。
    -------------------------------

    ovs-ofctl dump-flows ovs1
        NXST_FLOW reply (xid=0x4):
         cookie=0x0, duration=8304.857s, table=0, n_packets=0, n_bytes=0, idle_age=8304, hard_age=7496, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,1)
         cookie=0x0, duration=8304.852s, table=0, n_packets=0, n_bytes=0, idle_age=8304, hard_age=7496, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=resubmit(,1)
         cookie=0x0, duration=8303.999s, table=0, n_packets=19, n_bytes=1330, idle_age=667, hard_age=7496, priority=0 actions=resubmit(,1)
         cookie=0x0, duration=6117.675s, table=1, n_packets=0, n_bytes=0, idle_age=6117, priority=99,in_port=2,vlan_tci=0x0000 actions=mod_vlan_vid:20,resubmit(,2)
         cookie=0x0, duration=6117.674s, table=1, n_packets=0, n_bytes=0, idle_age=6117, priority=99,in_port=3,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=6117.674s, table=1, n_packets=0, n_bytes=0, idle_age=6117, in_port=4,vlan_tci=0x0000 actions=mod_vlan_vid:30,resubmit(,2)
         cookie=0x0, duration=6420.061s, table=1, n_packets=0, n_bytes=0, idle_age=6420, priority=99,in_port=1 actions=resubmit(,2)
         cookie=0x0, duration=6421.528s, table=1, n_packets=8, n_bytes=560, idle_age=667, priority=0 actions=drop
         cookie=0x0, duration=4154.226s, table=2, n_packets=0, n_bytes=0, idle_age=4154, actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)
         cookie=0x0, duration=2436.394s, table=3, n_packets=0, n_bytes=0, idle_age=2436, priority=99,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,4)
         cookie=0x0, duration=2459.711s, table=3, n_packets=0, n_bytes=0, idle_age=2459, priority=50 actions=resubmit(,10),resubmit(,4)
         cookie=0x0, duration=125.921s, table=4, n_packets=0, n_bytes=0, idle_age=125, reg0=0x1 actions=output:1
         cookie=0x0, duration=108.820s, table=4, n_packets=0, n_bytes=0, idle_age=108, reg0=0x2 actions=strip_vlan,output:2
         cookie=0x0, duration=108.820s, table=4, n_packets=0, n_bytes=0, idle_age=108, reg0=0x3 actions=strip_vlan,output:3
         cookie=0x0, duration=108.820s, table=4, n_packets=0, n_bytes=0, idle_age=108, reg0=0x4 actions=strip_vlan,output:4
         cookie=0x0, duration=35.719s, table=4, n_packets=0, n_bytes=0, idle_age=35, priority=50,reg0=0 actions=output:1
         cookie=0x0, duration=35.719s, table=4, n_packets=0, n_bytes=0, idle_age=35, priority=99,reg0=0,dl_vlan=20 actions=output:1,strip_vlan,output:2
         cookie=0x0, duration=35.719s, table=4, n_packets=0, n_bytes=0, idle_age=35, priority=99,reg0=0,dl_vlan=30 actions=output:1,strip_vlan,output:3,output:4
         cookie=0x0, duration=3521.221s, table=10, n_packets=0, n_bytes=0, idle_age=3521, hard_age=3302, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
         cookie=0x0, duration=3178.269s, table=10, n_packets=0, n_bytes=0, idle_age=3178, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:02 actions=load:0x2->NXM_NX_REG0[0..15]
         cookie=0x0, duration=2253.273s, table=10, n_packets=0, n_bytes=0, idle_age=2253, hard_age=1349, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
         cookie=0x0, duration=1419.473s, table=10, n_packets=0, n_bytes=0, idle_age=1419, vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]

    --------------------------------------------------
    首先来测试一个multicast和broadcast
    如果是一个port 1来的vlan 30的broadcast
    ovs-appctl ofproto/trace ovs1 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
        Bridge: ovs1
        Flow: in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=1
                OpenFlow actions=resubmit(,2)

                        Resubmitted flow: unchanged
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x001e/0x0fff,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=99,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00
                                OpenFlow actions=resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,reg0=0,in_port=1,dl_vlan=30,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                        Rule: table=4 cookie=0 priority=99,reg0=0,dl_vlan=30
                                        OpenFlow actions=output:1,strip_vlan,output:3,output:4      #结果是port 1就不发送了,发送给了port 3, 4
                                        skipping output to input port
                                        Nonexistent output port
                                        Nonexistent output port

        Final flow: in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x0000
        Megaflow: recirc_id=0,in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop

    
    --------------------------------------------------
    ovs-appctl ofproto/trace ovs1 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
        Bridge: ovs1
        Flow: in_port=3,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=3,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=3,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=3,vlan_tci=0x0000
                OpenFlow actions=mod_vlan_vid:30,resubmit(,2)

                        Resubmitted flow: in_port=3,dl_vlan=30,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x0000
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=3,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=3,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=99,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00
                                OpenFlow actions=resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,reg0=0,in_port=3,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                        Rule: table=4 cookie=0 priority=99,reg0=0,dl_vlan=30
                                        OpenFlow actions=output:1,strip_vlan,output:3,output:4
                                        Nonexistent output port
                                        skipping output to input port
                                        Nonexistent output port

        Final flow: unchanged
        Megaflow: recirc_id=0,in_port=3,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=ff:ff:ff:ff:ff:f0/ff:ff:ff:ff:ff:f0,dl_type=0x0000
        Datapath actions: drop


    --------------------------------------------------
    ovs-appctl ofproto/trace ovs1 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
        Bridge: ovs1
        Flow: in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=20:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=1
                OpenFlow actions=resubmit(,2)

                        Resubmitted flow: unchanged
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=20:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x001e/0x0fff,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=50
                                OpenFlow actions=resubmit(,10),resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x001e/0x0fff,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=254 cookie=0 priority=0,reg0=0x2
                                        OpenFlow actions=drop

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,reg0=0,in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=4 cookie=0 priority=99,reg0=0,dl_vlan=30
                                        OpenFlow actions=output:1,strip_vlan,output:3,output:4      #由于这两个地址没有出现过,则除了进行学习以外,广播发送给port 3,4
                                        skipping output to input port   
                                        Nonexistent output port
                                        Nonexistent output port

        Final flow: in_port=1,vlan_tci=0x0000,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
        Megaflow: recirc_id=0,in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
        Datapath actions: drop

    
    --------------------------------------------------
    ovs-appctl ofproto/trace ovs1 in_port=4,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01 -generate  
        Bridge: ovs1
        Flow: in_port=4,vlan_tci=0x0000,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=4,vlan_tci=0x0000,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=4,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=10:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 in_port=4,vlan_tci=0x0000
                OpenFlow actions=mod_vlan_vid:30,resubmit(,2)

                        Resubmitted flow: in_port=4,dl_vlan=30,dl_vlan_pcp=0,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=4,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=10:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=4,vlan_tci=0x0000,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=50
                                OpenFlow actions=resubmit(,10),resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,in_port=4,vlan_tci=0x0000,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=10 cookie=0 vlan_tci=0x001e/0x0fff,dl_dst=10:00:00:00:00:01
                                        OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]

                                        Resubmitted flow: reg0=0x1,in_port=4,dl_vlan=30,dl_vlan_pcp=0,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000
                                        Resubmitted regs: reg0=0x1 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,reg0=0,in_port=4,vlan_tci=0x0000,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=4 cookie=0 reg0=0x1
                                        OpenFlow actions=output:1       #回复的时候,由于学习过了,则仅仅从port 1发送出去。
                                        Nonexistent output port

        Final flow: reg0=0x1,in_port=4,dl_vlan=30,dl_vlan_pcp=0,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000
        Megaflow: recirc_id=0,in_port=4,vlan_tci=0x0000,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01,dl_type=0x0000
        Datapath actions: drop

    --------------------------------------------------
    ovs-appctl ofproto/trace ovs1 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
        Bridge: ovs1
        Flow: in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000

        Rule: table=0 cookie=0 priority=0
        OpenFlow actions=resubmit(,1)

                Resubmitted flow: in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                Resubmitted  odp: drop
                Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=20:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                Rule: table=1 cookie=0 priority=99,in_port=1
                OpenFlow actions=resubmit(,2)

                        Resubmitted flow: unchanged
                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                        Resubmitted  odp: drop
                        Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=20:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                        Rule: table=2 cookie=0
                        OpenFlow actions=learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),resubmit(,3)

                                Resubmitted flow: unchanged
                                Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                Resubmitted  odp: drop
                                Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x001e/0x0fff,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
                                Rule: table=3 cookie=0 priority=50
                                OpenFlow actions=resubmit(,10),resubmit(,4)

                                        Resubmitted flow: unchanged
                                        Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,in_port=1,vlan_tci=0x001e/0x0fff,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=10 cookie=0 vlan_tci=0x001e/0x0fff,dl_dst=20:00:00:00:00:01
                                        OpenFlow actions=load:0x4->NXM_NX_REG0[0..15]

                                        Resubmitted flow: reg0=0x4,in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
                                        Resubmitted regs: reg0=0x4 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
                                        Resubmitted  odp: drop
                                        Resubmitted megaflow: recirc_id=0,reg0=0,in_port=1,vlan_tci=0x001e/0x0fff,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
                                        Rule: table=4 cookie=0 reg0=0x4
                                        OpenFlow actions=strip_vlan,output:4            #由于在回复中进行了学习,因而发送的时候,仅仅发送port 4
                                        Nonexistent output port

        Final flow: reg0=0x4,in_port=1,vlan_tci=0x0000,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
        Megaflow: recirc_id=0,in_port=1,dl_vlan=30,dl_vlan_pcp=0,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01,dl_type=0x0000
        Datapath actions: drop
实现第五个table 4: Output Processing

 

其他 

通过 Floodlight 管理 OVS(未实践)
一方面,OpenFlow 控制器可以通过 OpenFlow 协议连接到任何支持 OpenFlow 的交换机,控制器通过和交换机交换流表规则来控制数据流向。另一方面, OpenFlow 控制器向用户提供的界面或者接口,用户可以通过界面对网络架构进行动态的修改,修改交换机的流表规则等等。Floodlight 是一个基于 Apache 协议,使用 Java 开发的企业级 OpenFlow 控制器。我们在下面的例子中演示如何安装 Floodlight,并连接管理 OVS 的过程。
通过 Floodlight 管理 OVS(未实践)

 

 

https://segmentfault.com/a/1190000038460977 Open vSwitch 入门实践(1)简介
https://segmentfault.com/a/1190000038470098 Open vSwitch 入门实践(2)使用OVS构建隔离网络
https://segmentfault.com/a/1190000038489898 Open vSwitch 入门实践(3)使用OVS构建分布式隔离网络
https://segmentfault.com/a/1190000038501108 Open vSwitch 入门实践(4)使用OVS配置端口镜像
https://segmentfault.com/a/1190000038767587 Open vSwitch 入门实践(5)OVS Flow Table 流表规则
https://blog.csdn.net/qq_21127151/article/details/124262331 #CentOS7安装OVS(OpenvSwitch)
https://www.cnblogs.com/popsuper1982/p/3800525.html [转]基于 Open vSwitch 的 OpenFlow 实践
https://www.cnblogs.com/popsuper1982/p/3800431.html [转]Open vSwitch 安装及配置
https://www.openvswitch.org/ 官网

以下课程仅学习,未总结
https://www.cnblogs.com/popsuper1982/p/3800574.html Openvswitch手册(1): 架构,SSL, Manager, Bridge
https://www.cnblogs.com/popsuper1982/p/3800576.html Openvswitch手册(2): OpenFlow Controller
https://www.cnblogs.com/popsuper1982/p/3800583.html Openvswitch手册(3): sFlow, netFlow
https://www.cnblogs.com/popsuper1982/p/3800585.html Openvswitch手册(4): Mirror
https://www.cnblogs.com/popsuper1982/p/3800613.html Openvswitch手册(5): VLAN and Bonding
https://www.cnblogs.com/popsuper1982/p/3803807.html Openvswitch手册(6): QoS
https://www.cnblogs.com/popsuper1982/p/3805094.html Openvswitch手册(7): Interfaces
https://www.cnblogs.com/popsuper1982/p/3805105.html Openvswitch手册(8): ovs-vsctl的DB的操作
https://www.cnblogs.com/popsuper1982/p/3810271.html Openvswitch手册(9): Flow

posted @ 2022-06-26 09:43  雲淡風輕333  阅读(365)  评论(0编辑  收藏  举报