OVS——大杂烩

本文深入解析Open vSwitch(OVS)架构,涵盖DPDK数据通路、OVSDB通信、核心组件、数据结构抽象关系。介绍了OVS如何通过DPDK加速处理,以及vswitchd如何与ovsdb-server通过JSON数据交互,详细阐述了数据结构关系,包括ofproto_class、dpif_class、netdev_class等,适合对OVS感兴趣的读者深入理解。
摘要由CSDN通过智能技术生成

其他资料

http://docs.openvswitch.org/en/latest/tutorials/ovs-conntrack/

OVS架构解析--dpdk datapath数据通路

1.  架构说明

1.1.  整体架构

OVS(openvswitch)是开源的虚拟交换机。也是当前市场上云环境中部署份额最大的交换机。支持 openflow协议,ovsdb协议管理。

一个OVS实例包括,ovsdb-server、ovs-vswitchd、datapath快转模块(linux内核中实现,可选的。dpdk模式是在用户态实现快转,并不需要内核态的datapath模块)。

 

  • ovsdb-server:作用是对ovsdb操作。
  • ovs-vswitchd:核心模块,作用是实现OpenFlow交换机、和controller通信、和db通信、实现用户态转发、和内核态快转路径通信。
  • datapath:在内核空间实现报文快速转发。

上图从整体架构说明了ovs的工作方式。ovs包括ovsdb配置管理方式和openflow流表转发控制方式。

 

  1. ovsdb配置管理方式:管理者通过OVSDB管理协议管理OVS交换机。OVSDB管理协议的规范文件是RFC 7047(The Open vSwitch Database Management Protocol)。RFC7047主要包括,定义OVSDB的结构、交互协议(JSON-RPC)、DB的操作类型。
  2. openflow流表控制方式:controller控制器通过OpenFlow协议给OVS交换机下发流表,控制交换机的转发行为。controller不通过OVSDB,而是直接向OVS交换机下发流表。

 

1.2.  核心组件及其关联关系

ovsdb-server和ovs-vswitchd之间是通过socket交互信息。

ovs-vswitchd通过netlink和内核态快转模块通信。

比如通过ovs-vsctl命令增加ovs交换机接口,ovs-vsctl会通过ovsdb-server向ovsdb更新数据,ovs-vswitchd监测到ovsdb变化时,会更新交换机配置,比如添加接口。

dpdk方式的ovs除了不使用内核模块外,架构和图中相同。

1.3.    内部模块及其关联关系

为了有个整体的了解,下面列几张整体的架构图,不做详细解释,后文会有流程解释。
 

2.  vswitchd和ovsdb通信

IDL:接口描述语言。IDL是用来描述软件组件接口的一种计算机语言。IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信交流。也就是说,用一种通用的格式,比如下面数据就是描述一个Open_vSwitch表,最后生成C语言描述的表操作.c文件
 
 
使用ovsschema格式定义数据库表,IDL解析器会把该文件内容解析成对数据库初始化、操作等函数,生成ovsdb-idl.c文件。
 

2.1.  建立连接

ovsdb_idl_create建立一个ovsdb的连接session,形如:idl =ovsdb_idl_create(remote, &ovsrec_idl_class, true, true)。

remote类似:unix:/var/run/openvswitch/db.sock。

后续使用该idl(struct ovsdb_idl)和ovsdb通信,更新数据。

2.2.  接收数据

使用jsonrpc_session_recv函数接收数据,形如:msg = jsonrpc_session_recv(idl->session)。

接收消息的结构是:

struct jsonrpc_msg {

    enum jsonrpc_msg_type type;

    char *method;              /* Request or notification only. */

    struct json *params;       /* Request or notification only. */

    struct json *result;       /* Successful reply only. */

    struct json *error;         /* Error reply only. */

    struct json *id;           /* Request or reply only. */

};

 

其中type是JSON-RPC 1.0定义的消息类型,包括request、notification、reply、error:

/* Messages. */

enum jsonrpc_msg_type {

    JSONRPC_REQUEST,          /* Request. */

    JSONRPC_NOTIFY,           /* Notification.*/

    JSONRPC_REPLY,            /* Successfulreply. */

   JSONRPC_ERROR              /* Error reply. */

};

 

params、result、error、id是不同类型的消息对应的消息数据。

当解析消息后,监测到需要更新本地数据时,调用ovsdb_idl_parse_update函数,解析消息并更新本地数据。
 

2.3.  json数据解析

 

/* A JSON value. */

struct json {

    enum json_type type;

    union {

        struct shash *object;  /* Contains "struct json *"s. */

        struct json_array array;

        long long int integer;

        double real;

        char *string;

    } u;

};

 

type字段:说明了该json数据是联合体中的哪一种类型。

/* Type of a JSON value. */

enum json_type {

    JSON_NULL,                 /* null */

    JSON_FALSE,                /* false */

    JSON_TRUE,                 /* true */

    JSON_OBJECT,               /* {"a": b, "c": d, ...}*/

    JSON_ARRAY,                /* [1, 2, 3, ...] */

    JSON_INTEGER,              /* 123. */

    JSON_REAL,                 /* 123.456. */

    JSON_STRING,               /* "..." */

    JSON_N_TYPES

};

 

联合体u:表示数据可以解析的类型。

例如,当type是JSON_OBJECT类型时,且是update2更新操作,那么object字段保存着多个数据表,每张表数据中又携带着待更新的多个row数据,和每row对应的操作(modify、insert、delete、initial)。然后遍历每个表的每行数据,并执行对应的数据操作(modify、insert、delete、initial)对本地数据更新。

注:本地数据和远端的OVSDB并不相同,本地数据是vswitchd从数据库取出数据后临时放到本地结构中的。

2.4.  更新数据改变标记

当监听到ovsdb-server发来的rpc消息时,如果数据库发送改变就改变对应的change_seqno。后续vswitchd根据change_seqno的值是否发生了变化,决定是否重新配置ovs交换机。

3.  dpdk加速处理

3.1.  ovs dpdk加速配置

在使用dpdk 类型的datapath加速之前,需要设置dpdk-init=true启动参数。

设置方法:

ovs-vsctl --no-wait set Open_vSwitch .other_config:dpdk-init=true

设置dpdk的相关参数,都通过other_config选项完成。

主要的参数有:

 

  • dpdk-init

 

指定ovs是否初始化和支持dpdk端口。

 

  • dpdk-lcore-mask

 

指明dpdk使用的逻辑核。同dpdk的-c参数。

 

  • dpdk-socket-mem

 

指明不同numa节点提前申请的大页内存。同dpdk的--socket-mem参数。

 

  • dpdk-hugepage-dir

 

大页文件系统mount的目录。同dpdk的--huge-dir参数。

 

  • vhost-sock-dir

 

设置vhost-user 套接字的路径。

 

  • dpdk-extra

 

其他的dpdk配置参数。

3.2.  dpdk初始化

 

主要包括:

1)    dpdk eal初始化。

2)    启动dpdk接口状态监控线程(使用dpdk的库函数),如果状态发送变化,则更新netdev设备的变化标记。

3)     注册dpdk类型的netdev class。其中包括dpdk设备类型,ring类型、vhost、vhost client类型。

 

4.  数据结构抽象关系

4.1.  分层抽象

 
 

 

  • ofproto  class

 

openflow交换机实现类,用来实现一个openflow交换机。主要包括创建、构造、操作openflowflow等相关方法。

 

  • dpif  class

 

datapath接口类,用来和datapath交互。主要包括datapath的open、run、端口操作、端口数据监听等相关方法。datapath是数据面的一种抽象。

 

  • netdev  class

 

网络设备抽象类,用来和网络设备交互。主要包括网卡的设置、网卡结构的抽象、数据包发送接收等相关方法。

 

 

  • ofproto  class

 

openflow交换机实现类,用来实现一个openflow交换机。主要包括创建、构造、操作openflowflow等相关方法。

 

  • dpif  class

 

datapath接口类,用来和datapath交互。主要包括datapath的open、run、端口操作、端口数据监听等相关方法。datapath是数据面的一种抽象。

 

  • netdev  class

 

网络设备抽象类,用来和网络设备交互。主要包括网卡的设置、网卡结构的抽象、数据包发送接收等相关方法。

 

bridge网桥通过ofproto  class构造一个openflow交换机。再通过dpif  class打开(如果没有对应类型的datapath,就创建一个)对应类型的datapath通路。使用netdev  class构造一个抽象网络设备,上层抽象为端口,然后对网络设备收发包等操作。

         需要说明的是,datapath是按类型分类的,现在ovs有两种类型的datapath:system(对应linux内核数据通路)、netdev(dpdk用户态数据通路)。所以使用同一种datapath类型的ovs网桥共享同一个datapath对象。如下图所示。

 


 

4.2.  主要数据结构关系

该部分说明的内容是关于dpdk类型的datapath。

 

 

注:A  B,表示A是一个变量而非指针,它的结构和内容是B。

流程解释如下:

1)        bridge层

 

1.1    struct  bridge对应每个ovs网桥最上层的结构。它通过成员指针变量ofproto,联系到struct  ofproto交换机结构内容。

 

2)        ofproto层

 

2.1   由于联系到的struct ofproto内容是struct ofproto_dpif结构的一个up成员变量。所以通过struct ofproto地址可以cast到struct ofproto_dpif结构内容,通过该内容和dpif层交互。

 

2.2   通过struct ofproto_dpif的成员指针变量dpif_backer,联系到struct  dpif_backer结构内容。该结构是dpif操作的入口点。

 

3)        dpif层

 

3.1   通过struct  dpif_backer的成员指针变量dpif,联系到structdpif结构内容。

 

3.2  由于struct dpif结构内容是struct  dpif_netdev结构的dpif成员变量,所以通过structdpif地址可以cast到struct dpif_netdev结构内容。

 

3.3   struct dpif_netdev结构内容中有指针成员变量dp,通过dp可以联系到struct  dp_netdev结构内容。该内容是datapath的抽象结构内容。

 

4)        datapath层

 

4.1  struct  dp_netdev的成员指针变量ports是一个表结构,它联系着多个port端口内容。端口的结构是struct  dp_netdev_port。struct  dp_netdev另外一个成员指针变量netdev,联系着dp层的struct  netdev结构内容,该结构内容是网卡的逻辑抽象。

 

4.2  struct  dp_netdev_port的指针成员变量rxqs也是一个表结构,它联系着多个队列内容。队列的结构是struct  dp_netdev_rxq.它的成员变量core_id表示该队列所在的core。

 

4.3   通过struct dp_netdev_rxq的成员指针变量rxq,联系到dp层的struct  netdev_rxq结构内容。structdp_netdev_rxq的成员变量queue_id表示该队列id。

 

5)        netdev层

 

5.1   由于struct  netdev结构内容是struct  netdev_dpdk结构的一个up成员变量。所以通过struct  netdev地址可以cast到struct  netdev_dpdk结构内容。

 

5.2    通过struct  detdev_dpdk结构内容的成员指针变量netdev_class和dpdk类型网卡交互。

5.3   由于struct netdev_rxq结构内容是struct netdev_rxq_dpdk结构内容的一个up成员变量。所以通过struct netdev_rxq地址可以cast到struct netdev_rxq_dpdk结构内容。该内容是dpdk类型的netdev_rxq,它的成员变量port_id是dpdk网络设备的port。

 

 

5.  vswitchd启动

简要的概括下vswitchd启动的内容。

1)   和ovsdb-server通信初始化,建立

2)   dpdk初始化

3)   ofproto(OpenFlow交换机)初始化

4)   netdev初始化

5)   网桥配置

 

更新网桥(添加、删除)

 

更新端口

 

创建ofproto(OpenFlow交换机),创建或打开dpif_backer

 

添加端口,添加到pmd中

 

配置网桥、端口属性

 

datapath run

 

dp_netdev的pmd更新

 

dpif_run(运行dpif-netdev的datapath,配置netdev等,接收发送报文)

 

ofproto run,配置ofproto需要的参数和功能(netflow、sflow、ipfix、mac学习)

 

OpenFlow控制器连接相关run

 

 

 

6.  附录-数据结构查询

6.1.  ofproto_class

是一个OpenFlow交换机的实现类结构,提供的类功能很多,主要分为:

1.        工厂函数功能。如初始化、枚举支持的datapath类型。

2.        datapath类型处理。

3.        OpenFlow交换机功能。如构造、运行等。

4.        OpenFlow流表功能。

5.        OpenFlow配置。

6.        OpenFlow计量。

7.        OpenFlow 1.1 group功能。

8.        获取datapath信息功能。

9.        连接表功能。

 

 

6.2.  dpif_class

datapath接口实现类,每种datapath都有对应的接口实现实例。dpif有两种实现类:dpif_netlink_class、dpif_netdev_class。即system、netdev。比如,dpdk的netdevdatapath类型的实现实例dpif_netdev_class。

 

 

6.3.  netdev_class

网络设备实现类。包括抽象的设备结构和收发包功能。

6.4.  bridge

6.5.  ofproto

6.6.  port

6.7.  iface

6.8.  ofport

6.9.  ofport_dpif

6.10.  ofproto_port

6.11.  dpif_port

dp向dpif返回的端口信息。

6.12.  ofproto_dpif

6.13.  dpif_backer

datapath类型共享实现实例。

6.14.  udpif

6.15.  dpif

datapath接口。

6.16.  dpif_netdev

netdev类型的datapath的接口。

6.17.  dp_netdev

基于网络设备接口的datapath。

6.18.  dp_netdev_port

基于netdev类型的datapath的端口。

挂载在dp_netdev的ports成员中。

6.19.  netdev

抽象的网络设备。

6.20.  netdev_dpdk

dpdk类型的netdev结构,继承自netdev结构。

6.21.  dp_netdev_rxq

用来表示core和队列的对应关系。

6.22.  netdev_rxq

网络设备的收包队列结构,以队列区分。

6.23.  netdev_rxq_dpdk

dpdk的收包队列结构,继承自netdev_rxq.

端口号和netdev_dpdk中的端口号相同。

使用dpdk的接口函数rte_zmalloc申请,受dpdk的内存管理控制。

6.24.  dp_netdev_pmd_thread

6.25.  rxq_poll

6.26.  tx_port

OVS 架构

OVS 是产品级的虚拟交换机,大量应用在生产环境中,支撑整个数据中心虚拟网络的运转。OVS 基于 SDN 的思想,将整个核心架构分为控制面和数据面,数据面负责数据的交换工作,控制面实现交换策略,指导数据面工作。

431521-20171224102317818-1090106576.png

从整体上看,OVS 可以划分为三大块,管理面、数据面和控制面。

数据面就是以用户态的 ovs-vswitchd 和内核态的 datapath 为主的转发模块,以及与之相关联的数据库模块 ovsdb-server,控制面主要是由 ovs-ofctl 模块负责,基于 OpenFlow 协议与数据面进行交互。而管理面则是由 OVS 提供的各种工具来负责,这些工具的提供也是为了方便用户对底层各个模块的控制管理,提高用户体验。下面就对这些工具进行一个逐一的阐述。

ovs-ofctl:这个是控制面的模块,但本质上它也是一个管理工具,主要是基于 OpenFlow 协议对 OpenFlow 交换机进行监控和管理,通过它可以显示一个 OpenFlow 交换机的当前状态,包括功能、配置和表中的项。使用时,有很多参数,我们可以通过 ovs-ofctl --help 查看。

  1.  
    常用命令:
  2.  
     
  3.  
    ovs-ofctl show switch-name :输出交换机信息,包括其流量表和端口信息。
  4.  
     
  5.  
    ovs-ofctl dump-ports switch-name:输出交换机的端口统计信息,包括收发包、丢包、错误包等数量。
  6.  
     
  7.  
    ovs-ofctl add-flow switch-name:为交换机配置流策略。

ovs-dpctl:用来配置交换机的内核模块 datapath,它可以创建,修改和删除 datapath,一般,单个机器上的 datapath 有 256 条(0-255)。一条 datapath 对应一个虚拟网络设备。该工具还可以统计每条 datapath 上的设备通过的流量,打印流的信息等,更过参数通过 ovs-dpctl --help 查看。

  1.  
    常用命令:
  2.  
     
  3.  
    ovs-dpctl show :显示所有 datapath 的基本信息。
  4.  
     
  5.  
    ovs-dpctl dump-dps :显示所有 datapath 的名字。
  6.  
     
  7.  
    ovs-dpctl dump-flows DP :显示一条 datapath DP 上的流信息。

ovs-appctl:查询和控制运行中的 OVS 守护进程,包括 ovs-switchd,datapath,OpenFlow 控制器等,兼具 ovs-ofctl、ovs-dpctl 的功能,是一个非常强大的命令。ovs-vswitchd 等进程启动之后就以一个守护进程的形式运行,为了能够很好的让用户控制这些进程,就有了这个命令。详细可以 ovs-appctl --help 查看。

ovs-vsctl:查询和更新 ovs-vswitchd 的配置,这也是一个很强大的命令,网桥、端口、协议等相关的命令都由它来完成。此外,还负责和 ovsdb-server 相关的数据库操作。

  1.  
    常用命令:
  2.  
     
  3.  
    ovs-vsctl show :显示主机上已有的网桥及端口信息。
  4.  
     
  5.  
    ovs-vsctl add-br br0:添加网桥 br0。

ovsdb-client:访问 ovsdb-server 的客户端程序,通过 ovsdb-server 执行一些数据库操作。

  1.  
    常用命令:
  2.  
     
  3.  
    ovsdb-client dump:用来查看ovsdb内容。
  4.  
     
  5.  
    ovsdb-client transact :用来执行一条类 sql。

ovsdb-tool:和 ovsdb-client 要借助 ovsdb-server 才能进行相关数据库操作不同,ovsdb-tool 可以直接操作数据库。

OVS 源码结构

OVS 源码结构中,主要包含以下几个主要的模块,数据交换逻辑在 vswitchd 和 datapath 中实现,vswitchd 是最核心的模块,OpenFlow 的相关逻辑都在 vswitchd 中实现,datapath 则不是必须的模块。ovsdb 用于存储 vswitch 本身的配置信息,如端口、拓扑、规则等。控制面部分采用的是 OVS 自家实现的 OVN,和其他控制器相比,OVN 对 OVS 和 OpenStack 有更好的兼容性和性能。

431521-20171224102359443-1589744207.png

从图中可以看出 OVS 的分层结构,最上层 vswitchd 主要与 ovsdb 通信,做配置下发和更新等,中间层是 ofproto ,用于和 OpenFlow 控制器通信,并基于下层的 ofproto provider 提供的接口,完成具体的设备操作和流表操作等工作。

dpif 层实现对流表的操作。

netdev 层实现了对网络设备(如 Ethernet)的抽象,基于 netdev provider 接口实现多种不同平台的设备,如 Linux 内核的 system, tap, internal 等,dpdk 系的 vhost, vhost-user 等,以及隧道相关的 gre, vxlan 等。

数据转发流程

通过一个例子来看看 OVS 中数据包是如何进行转发的。

431521-20171224102412506-951322711.png

1)ovs 的 datapath 接收到从 ovs 连接的某个网络端口发来的数据包,从数据包中提取源/目的 IP、源/目的 MAC、端口等信息。

2)ovs 在内核态查看流表结构(通过 hash),如果命中,则快速转发。

3)如果没有命中,内核态不知道如何处置这个数据包,所以,通过 netlink upcall 机制从内核态通知用户态,发送给 ovs-vswitchd 组件处理。

4)ovs-vswitchd 查询用户态精确流表和模糊流表,如果还不命中,在 SDN 控制器接入的情况下,经过 OpenFlow 协议,通告给控制器,由控制器处理。

5)如果模糊命中, ovs-vswitchd 会同时刷新用户态精确流表和内核态精确流表,如果精确命中,则只更新内核态流表。

6)刷新后,重新把该数据包注入给内核态 datapath 模块处理。

7)datapath 重新发起选路,查询内核流表,匹配;报文转发,结束。

总结

OVS 为了方便用户操作,提供了很多管理工具,我们平常在使用过程中只需记住每个工具的作用,具体的命令可以使用 -h 或 --help 查看。

创建一个OVS 交换机

创建一个叫ovs-switch的交换机

  1.  
    $ ovs-vsctl add-br ovs-switch
  2.  
     

创建一个端口 p0,设置端口 p0 的 OpenFlow 端口编号为 100(如果在创建端口的时候没有指定 OpenFlow 端口编号,OVS 会自动生成一个)。

 

  1.  
    $ ovs-vsctl add-port ovs-switch p0 -- set Interface p0 ofport_request=100
  2.  
     

设置网络接口设备的类型为"internal"。对于 internal 类型的的网络接口,OVS 会同时在 Linux 系统中创建一个可以用来收发数据的模拟网络设备。我们可以为这个网络设备配置 IP 地址、进行数据监听等操作。

 

  1.  
    $ ovs-vsctl set Interface p0 type=internal
  2.  
    $ ethtool -i p0
  3.  
    driver: openvswitch
  4.  
    version:
  5.  
    firmware-version:
  6.  
    bus-info:
  7.  
    supports-statistics: no
  8.  
    supports-test: no
  9.  
    supports-eeprom-access: no
  10.  
    supports-register-dump: no

为了避免网络接口上的地址和本机已有网络地址冲突,我们可以创建一个虚拟网络空间 ns0,把 p0 接口移入网络空间 ns0,并配置 IP 地址为 192.168.1.100

 

  1.  
    $ ip netns add ns0
  2.  
    $ ip link set p0 netns ns0
  3.  
    $ ip netns exec ns0 ip addr add 192.168.1.100/24 dev p0
  4.  
    $ ip netns exec ns0 ifconfig p0 promisc up

使用同样的方法创建端口 p1、p2

 

 

创建的端口信息

 

端口

说明

p0

IP 地址: 192.168.1.100/24
网络名称空间: ns0
网络接口 MAC地址: 66:4e:cc:ae:4d:20
OpenFlow Port Number: 100

p1

IP 地址: 192.168.1.101/24
网络名称空间: ns1
网络接口 MAC地址: 46:54:8a:95:dd:f8
OpenFlow Port Number: 101

p2

IP 地址: 192.168.1.102/24, 
网络名称空间: ns2
网络接口 MAC地址: 86:3b:c8:d0:44:10
OpenFlow Port Number: 102

   

创建所有的端口之后, 查看 OVS 交换机的信息

 

  1.  
    $ ovs-vsctl show
  2.  
    30282710-d401-4187-8e13-52388f693df7
  3.  
    Bridge ovs-switch
  4.  
    Port "p0"
  5.  
    Interface "p0"
  6.  
    type: internal
  7.  
    Port "p2"
  8.  
    Interface "p2"
  9.  
    type: internal
  10.  
    Port "p1"
  11.  
    Interface "p1"
  12.  
    type: internal
  13.  
    Port ovs-switch
  14.  
    Interface ovs-switch
  15.  
    type: internal

 

使用 ovs-ofctl 创建并测试 OpenFlow 命令

查看 Open vSwitch 中的端口信息。从输出结果中,可以获得交换机对应的 datapath ID (dpid),以及每个端口的 OpenFlow 端口编号,端口名称,当前状态等等。

  1.  
    $ ovs-ofctl show ovs-switch
  2.  
    OFPT_FEATURES_REPLY (xid= 0x2): dpid:00001232a237ea45
  3.  
    n_tables: 254, n_buffers:256
  4.  
    capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
  5.  
    actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST
  6.  
    SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE
  7.  
    100(p0): addr:54:01:00:00:00:00
  8.  
    config: PORT_DOWN
  9.  
    state: LINK_DOWN
  10.  
    speed: 0 Mbps now, 0 Mbps max
  11.  
    101(p1): addr:54:01:00:00:00:00
  12.  
    config: PORT_DOWN
  13.  
    state: LINK_DOWN
  14.  
    speed: 0 Mbps now, 0 Mbps max
  15.  
    102(p2): addr:54:01:00:00:00:00
  16.  
    config: PORT_DOWN
  17.  
    state: LINK_DOWN
  18.  
    speed: 0 Mbps now, 0 Mbps max
  19.  
    LOCAL(ovs-switch): addr: 12:32:a2:37:ea:45
  20.  
    config: 0
  21.  
    state: 0
  22.  
    speed: 0 Mbps now, 0 Mbps max
  23.  
    OFPT_GET_CONFIG_REPLY (xid= 0x4): frags=normal miss_send_len=0

 

如果想获得网络接口的 OpenFlow 编号,也可以在 OVS 的数据库中查询

 

  1.  
    $ ovs-vsctl get Interface p0 ofport
  2.  
    100

 

查看 datapath 的信息

 

 
   
  1.  
    $ ovs-dpctl show
  2.  
    system@ovs-system:
  3.  
    lookups: hit: 12173 missed:712 lost:0
  4.  
    flows: 0
  5.  
    port 0: ovs-system (internal)
  6.  
    port 1: ovs-switch (internal)
  7.  
    port 2: p0 (internal)
  8.  
    port 3: p1 (internal)
  9.  
    port 4: p2 (internal)

屏蔽数据包

屏蔽所有进入 OVS 的以太网广播数据包

 

  1.  
    $ ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
  2.  
     

 

 屏蔽 STP 协议的广播数据包

 

  1.  
    $ ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
  2.  
     

 

修改数据包

添加新的 OpenFlow 条目,修改从端口 p0 收到的数据包的源地址为 9.181.137.1

 

  1.  
    $ ovs-ofctl add-flow ovs-switch "priority=1 idle_timeout=0,\
  2.  
    in_port=100,actions=mod_nw_src:9.181.137.1,normal"
从端口 p0(192.168.1.100)发送测试数据到端口 p1(192.168.1.101)

$ ip netns exec ns0 ping 192.168.1.101

在接收端口 p1 监控数据,发现接收到的数据包的来源已经被修改为 9.181.137.1

 

 
   
  1.  
    $ ip netns exec ns1 tcpdump -i p1 icmp
  2.  
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  3.  
    listening on p1, link-type EN10MB (Ethernet), capture size 65535 bytes
  4.  
    15:59:16.885770 IP 9.181.137.1 > 192.168.1.101: ICMP echo request, id 23111, seq 457, length 64
  5.  
    15:59:17.893809 IP 9.181.137.1 > 192.168.1.101: ICMP echo request, id 23111, seq 458, length 64

 

重定向数据包

添加新的 OpenFlow 条目,重定向所有的 ICMP 数据包到端口 p2

 

  1.  
    $ ovs-ofctl add-flow ovs-switch idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:102
  2.  
     

 

 从端口 p0 (192.168.1.100)发送数据到端口 p1(192.168.1.101)

 

  1.  
    $ ip netns exec ns0 ping 192.168.1.101
  2.  
     

 

 在端口 p2 上监控数据,发现数据包已被转发到端口 p2

 

  1.  
    $ ip netns exec ns3 tcpdump -i p2 icmp
  2.  
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  3.  
    listening on p2, link-type EN10MB (Ethernet), capture size 65535 bytes
  4.  
    16:07:35.677770 IP 192.168.1.100 > 192.168.1.101: ICMP echo request, id 23147, seq 25, length 64
  5.  
    16:07:36.685824 IP 192.168.1.100 > 192.168.1.101: ICMP echo request, id 23147, seq 26, length 64

 

修改数据包的 VLAN Tag

除了使用"ping"、"tcpdump"和"iperf" 等 Linux 命令以外,我们也可以使用 OVS 提供的 ovs-appctl ofproto/trace 工具来测试 OVS 对数据包的转发状况。ovs-appctl ofproto/trace 可以用来生成测试用的模拟数据包,并一步步的展示 OVS 对数据包的流处理过程。在以下的例子中,我们演示一下如何使用这个命令:

修改端口 p1 的 VLAN tag 为 101,使端口 p1 成为一个隶属于 VLAN 101 的端口

 

  1.  
    $ ovs-vsctl set Port p1 tag=101
  2.  
     

 

 现在由于端口 p0 和 p1 属于不同的 VLAN,它们之间无法进行数据交换。我们使用 ovs-appctl ofproto/trace 生成一个从端口 p0 发送到端口 p1 的数据包,这个数据包不包含任何 VLAN tag,并观察 OVS 的处理过程

在第一行输出中,"Flow:"之后的字段描述了输入的流的信息。由于我们没有指定太多信息,所以多数字段 (例如 dl_type 和 vlan_tci)被 OVS 设置为空值。

在第二行的输出中,"Rule:" 之后的字段描述了匹配成功的流表项。

在第三行的输出中,"OpenFlow actions"之后的字段描述了实际执行的操作。

最后一段以"Final flow"开始的字段是整个处理过程的总结,"Datapath actions: 4,1"代表数据包被发送到 datapath 的 4 和 1 号端口。

 

  1.  
    $ ovs-appctl ofproto/trace ovs-switch in_port= 100,dl_src=66:4e:cc:ae:4d:20,
  2.  
    dl_dst= 46:54:8a:95:dd:f8 -generate
  3.  
    Flow:metadata= 0,in_port=100,vlan_tci=0x0000,dl_src=66:4e:cc:ae:4d:20,
  4.  
    dl_dst= 46:54:8a:95:dd:f8,dl_type=0x0000
  5.  
    Rule: table= 0 cookie=0 priority=0
  6.  
    OpenFlow actions=NORMAL
  7.  
    no learned MAC for destination, flooding
  8.  
     
  9.  
    Final flow: unchanged
  10.  
    Relevant fields: skb_priority= 0,in_port=100,vlan_tci=0x0000/0x1fff,\
  11.  
    dl_src= 66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000,nw_frag=no
  12.  
    Datapath actions: 4,1


创建一条新的 Flow:对于从端口 p0 进入交换机的数据包,如果它不包含任何 VLAN tag,则自动为它添加 VLAN tag 101

 

 

  1.  
    $ ovs-ofctl add-flow ovs-switch "priority=3,in_port=100,dl_vlan=0xffff,\
  2.  
     

actions=mod_vlan_vid:101,normal"

 

 再次尝试从端口 p0 发送一个不包含任何 VLAN tag 的数据包,发现数据包进入端口 p0 之后, 会被加上 VLAN tag101, 同时转发到端口 p1 上

 

  1.  
    $ ovs-appctl ofproto/trace ovs-switch in_port= 100,dl_src=66:4e:cc:ae:4d:20,
  2.  
    dl_dst= 46:54:8a:95:dd:f8 –generate
  3.  
    Flow: metadata= 0,in_port=100,vlan_tci=0x0000,dl_src=66:4e:cc:ae:4d:20,
  4.  
    dl_dst= 46:54:8a:95:dd:f8,dl_type=0x0000
  5.  
    Rule: table= 0 cookie=0 priority=3,in_port=100,vlan_tci=0x0000
  6.  
    OpenFlow actions=mod_vlan_vid: 101,NORMAL
  7.  
    forwarding to learned port
  8.  
     
  9.  
    Final flow: metadata= 0,in_port=100,dl_vlan=101,dl_vlan_pcp=0,dl_src=66:4e:cc:ae:4d:20,
  10.  
    dl_dst= 46:54:8a:95:dd:f8,dl_type=0x0000
  11.  
    Relevant fields: skb_priority= 0,in_port=100,vlan_tci=0x0000/0x1fff,dl_src=66:4e:cc:ae:4d:20,
  12.  
    dl_dst= 46:54:8a:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值