27

详解SDN限速之meter表

 4 years ago
source link: https://www.sdnlab.com/24306.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

001.png

网络限速有很多种方式,比如网卡限速,队列限速,meter表限速。其中meter表限速是颇具代表性的限速方式。因为网卡限速和队列限速都是传统网络的限速方式,而meter表是SDN架构下的限速方式。本篇主要介绍meter限速。

由于meter表是OpenFlow13出现的特性,而Open VSwitch 2.8.0以上的版本才支持OpenFlow13。

002.png

所以本文实验环境: Ubuntu1604 desktop + Mininet + ovs2.8.1
安装顺序:先安装mininet所有组件,然后编译安装ovs2.8.1

原理

meter表限速的原理是丢弃多余数据包。首先创建一个转发的流表。比如:

  1. 交换机上有流表:1端口进来的流量从2端口出去,in_port=1,actions=output:2
  2. 这个时候再创建一个meter表,作用是:速度超过10M的流量丢弃,meter=1,type=drop,rate=10000
  3. 最后修改流表使用该meter表。in_port=1,actions=meter:1,output:2

这是从1端口进来的流量,在从2端口转发出去之前会被meter表处理,处理方式就是丢弃掉超过10M的流量,然后再转发到2口。

以上就是meter表的工作原理,使用的是伪命令。下面具体分析meter表

数据结构:

meter表的数据结构如下:

struct ofp_meter_mod { struct ofp_header header; uint16_t command; /* One of OFPMC_*. */ uint16_t flags; /* One of OFPMF_*. */ uint32_t meter_id; /* Meter instance. */ struct ofp_meter_band_header bands[0]; /* The bands length is inferred from the length field in the header. */ };
1
2
3
4
5
6
7
8
structofp_meter_mod{
structofp_header header;
uint16_t command;/* One of OFPMC_*. */
uint16_t flags;/* One of OFPMF_*. */
uint32_t meter_id;/* Meter instance. */
structofp_meter_band_header bands[0];/* The bands length is inferred from the length field in the header. */
};
 

003.png

command:

command字段是表示该meter表的操作,是增加、修改或者删除 meter表。

/* Meter commands */ enum ofp_meter_mod_command { OFPMC_ADD, /* New meter. */ OFPMC_MODIFY, /* Modify specified meter. */ OFPMC_DELETE, /* Delete specified meter. */ };
1
2
3
4
5
6
7
/* Meter commands */
enumofp_meter_mod_command{
OFPMC_ADD,/* New meter. */
OFPMC_MODIFY,/* Modify specified meter. */
OFPMC_DELETE,/* Delete specified meter. */
};
 

flags:

flag字段能够表示的信息很多,一个16位的字节,能够表示:

  1. meter表限速的单位。默认单位是 kb/s
  2. 更换成 packet/s 的算法
  3. 是否开启burst
  4. 是否统计
enum ofp_meter_flags { OFPMF_KBPS = 1 << 0, /* Rate value in kb/s (kilo-bit per second). */ OFPMF_PKTPS = 1 << 1, /* Rate value in packet/sec. */ OFPMF_BURST = 1 << 2, /* Do burst size. */ OFPMF_STATS = 1 << 3, /* Collect statistics. */ };
1
2
3
4
5
6
7
enumofp_meter_flags{
OFPMF_KBPS=1<<0,/* Rate value in kb/s (kilo-bit per second). */
OFPMF_PKTPS=1<<1,/* Rate value in packet/sec. */
OFPMF_BURST=1<<2,/* Do burst size. */
OFPMF_STATS=1<<3,/* Collect statistics. */
};
 

meter_id:

meter_id 这个字段是meter表的身份id,在交换机中是唯一的。memter_id的定义是从1开始的,最大值是根据交换机能够支持的最大数值而定。

band:

/* Common header for all meter bands */ struct ofp_meter_band_header { uint16_t type; /* One of OFPMBT_*. */ uint16_t len; /* Length in bytes of this band. */ uint32_t rate; /* Rate for this band. */ uint32_t burst_size; /* Size of bursts. */ };
1
2
3
4
5
6
7
8
/* Common header for all meter bands */
structofp_meter_band_header{
uint16_t type;/* One of OFPMBT_*. */
uint16_t len;/* Length in bytes of this band. */
uint32_t rate;/* Rate for this band. */
uint32_t burst_size;/* Size of bursts. */
};
 

004.png

band字段是一个速度band数组。它可以包含多个数量的计量带,并且每一个计量带都可以重复。同一时间只有一个计量带生效,如果数据包的速度超过所有的计量带,那么配置的速度最高的计量带会被使用。

/* Common header for all meter bands */ struct ofp_meter_band_header { uint16_t type; /* One of OFPMBT_*. */ uint16_t len; /* Length in bytes of this band. */ uint32_t rate; /* Rate for this band. */ uint32_t burst_size; /* Size of bursts. */ };

1
2
3
4
5
6
7
8
9
 
/* Common header for all meter bands */
structofp_meter_band_header{
uint16_t type;/* One of OFPMBT_*. */
uint16_t len;/* Length in bytes of this band. */
uint32_t rate;/* Rate for this band. */
uint32_t burst_size;/* Size of bursts. */
};
 

005.png

type:

The type field must be one of the following: /* Meter band types */ enum ofp_meter_band_type { OFPMBT_DROP = 1, /* Drop packet. */ OFPMBT_DSCP_REMARK = 2, /* Remark DSCP in the IP header. */ OFPMBT_EXPERIMENTER = 0xFFFF /* Experimenter meter band. */ };
1
2
3
4
5
6
7
8
The type field must be one of the following:
/* Meter band types */
enumofp_meter_band_type{
OFPMBT_DROP=1,/* Drop packet. */
OFPMBT_DSCP_REMARK=2,/* Remark DSCP in the IP header. */
OFPMBT_EXPERIMENTER=0xFFFF/* Experimenter meter band. */
};
 

type字段是指高出限速值的数据包的处理方式。主要有丢弃设置优先丢弃。一个openflow交换机可能不会支持所有的band的type值,也不是所有的meter都要支持全部的type值。

type中三种处理动作:

  • drop:计量带OFPMBT_DROP定义了一个简单的速度限制器,会丢弃掉超过该值的数据包
  • remark:OFPMBT_DSCP_REMARK 字段定义了一个简单的DiffServ 策略,当超过定义值的数据包到来时,其ip头部中的丢弃字段DSCP会被标记。这样该ip数据包就会优先被丢弃。

ip数据包:

006.png

服务类型:占 8 位,用来获得更好的服务.这个字段在旧标准中叫做服务类型,但实际上一直没有被使用过.1998年IETF把这个字段改名为区分服务 DS(Differentiated Services).只有在使用区分服务时,这个字段才起作用.

  • experimenter:该类型应该是被用于创新实验使用的,可以自定义超出定义值的数据包处理方式。

len

len字段表示的该band的数据包的长度

rate:

rate字段表示可能作用于数据包的值即限速的值。rate字段的单位是kb每秒,除非在flags字段包含了OFPMF_PKTPS,这时rate的单位是 packet/s

brust_size:

brust_size字段只有在flags字段包含了OFPMC_BURST才会被使用。它主要用于在使用meter表时突发的大量数据包或者字节时。burst的单位是kb,当flags包含OFPMF_PKTPS时,burst的单位为 packet

meter使用

拓扑创建

使用mininet创建一个最简单的拓扑,一个控制器,一个交换机,两个主机。mininet是SDN中网络仿真器,用来创建控制器、交换机、主机等网络设备。mn命令创建一个自带的控制器,ovs交换机和主机。

007.png

iperf工具是用来测量网络带宽的常用命令。

服务端开启一个监听 iperf -s,客户端连接服务端,测试带宽iperf -c 10.0.0.1。默认是TCP连接,可以测试出两个主机之间的带宽。

在没有限速之前测试其速度大小。可以看出其速度是27.5GB/s。测得的速度和机器的性能有关,当前的实验环境机器是4核 8G SSD固态盘。

008.png

设置datapath

设置datapath为用户态。datapath一般来说是运行在内核态,如果想实现限速功能,就需要将其设置成用户态。

ovs-vsctl set bridge s1 datapath_type=netdev ovs-vsctl set bridge s1 protocols=OpenFlow13
1
2
3
ovs-vsctl set bridge s1 datapath_type=netdev
ovs-vsctl set bridge s1 protocols=OpenFlow13
 

009.png

下发meter表

下发限速的meter表。名字:s1;速度:5M;动作:丢弃;id:1

ovs-ofctl add-meter s1 meter=1,kbps,band=type=drop,rate=5000 -O OpenFlow13
1
2
ovs-ofctl add-meter s1 meter=1,kbps,band=type=drop,rate=5000-OOpenFlow13
 

010.png

ovs-ofctl dump-meter s1 -O openflow13
1
2
ovs-ofctl dump-meter s1-Oopenflow13
 

011.png

下发流表,并使用meter表

下发转发的流表。匹配进端口为1,转发动作为meter:1,output:2meter:1表示匹配到的流表首先交给meter表处理,就是超过5M的数据包丢弃掉,然后在交给output:2,从2端口转发出去。

ovs-ofctl add-flow s1 priority=200,in_port=1,action=meter:1,output:2 -O OpenFlow13 ovs-ofctl add-flow s1 priority=200,in_port=2,output:1 -O OpenFlow13
1
2
3
ovs-ofctl add-flow s1 priority=200,in_port=1,action=meter:1,output:2-OOpenFlow13
ovs-ofctl add-flow s1 priority=200,in_port=2,output:1-OOpenFlow13
 

012.png

关闭tx校验

datapath_type 设置为 netdev 之后,就是将datapath从内核态转化到用户态,这时datapath收到数据包会校验数据包并且校验不会通过而丢弃数据包。这是很多时候为什么datapath_type=netdev之后,主机之间能够ping通,但是不能够使用iperf测量带宽的原因。需要将tx-checksumming关闭掉。

1、 关闭主机的网卡的tx校验

013.png

root@ljk-VirtualBox:/home/ljk/Desktop# ethtool -K enp0s3 tx off Cannot get device udp-fragmentation-offload settings: Operation not supported Cannot get device udp-fragmentation-offload settings: Operation not supported Actual changes: tx-checksumming: off tx-checksum-ip-generic: off tcp-segmentation-offload: off tx-tcp-segmentation: off [requested on]
1
2
3
4
5
6
7
8
9
root@ljk-VirtualBox:/home/ljk/Desktop# ethtool -K enp0s3 tx off
Cannot get device udp-fragmentation-offload settings:Operation notsupported
Cannot get device udp-fragmentation-offload settings:Operation notsupported
Actual changes:
tx-checksumming:off
    tx-checksum-ip-generic:off
tcp-segmentation-offload:off
    tx-tcp-segmentation:off[requested on]
 

2、 关闭iperf客户端的tx校验

014.png

验证

通过iperf验证速度可以得到此时的带宽为5M。注意在iperf打流是使用UDP的流测量准确度会高与TCP。
客户端以10M的速度打流

iperf -u -c 10.0.0.2 -b 10M -i 5 -t 20
1
2
iperf-u-c10.0.0.2-b10M-i5-t20
 

015.png

服务端接收并验证。可以看到meter限速是5M,而服务端的速度也接近这个值,说明限速是成功的。

iperf -u -s
1
iperf-u-s

016.png

多band(计量带)meter表

前面介绍band时说过一个meter表中可以包含多个band,当一个merer表有多个计量带时,以小于当前带宽的最大的rate作为限速的速度,下面测试多个计量带时限速的表现。

下发多计量带meter表

设置meter表有多个计量带,rate=5000,以及rate=12000。就是rate=5M和rate=12M

ovs-ofctl add-meter s1 meter=1,kbps,band=type=drop,rate=5000,rate=12000 -O OpenFlow13
1
ovs-ofctl add-meter s1 meter=1,kbps,band=type=drop,rate=5000,rate=12000-OOpenFlow13

以高于rate的带宽验证

客户端以15M的带宽打流

017.png

服务端接收到的带宽为12M左右。

018.png

15M的带宽,限速在12M,而不是5M。所以符合多计量带的限速规则。

以带宽限速中间范围值验证

两个限速为5M和12M,客户端以中间值8M带宽测试

019.png

服务端接收到的带宽为5M左右,限速符合多计量带规则。

020.png

burst_size 瞬时流量

burst 令牌桶原理

在计量带中有一个参数叫做burst_size,这个参数为非必填字段,但是从这个字段能够体现限流的操作的基本原理。burst_size是令牌桶的容量。所谓令牌桶,原理如下图:

021.png

令牌桶的意义在于:每一个数据包想要被转发都需要得到一个令牌,而令牌来至于令牌桶。令牌桶以一个速度获得令牌,该速度就是限速的速度,超过令牌桶容量的令牌会溢出,同时数据包转发以一定的速度消耗令牌,这就是限速的原理。而burse_size 指的就是令牌桶的容量。

令牌桶的作用是面对突发的大量数据请求可以瞬间消耗令牌桶内的令牌,所以有burse_size的效果就是某个大流量到来的瞬间限速的速度等于令牌桶的容量+限速的速度

下发携带burst_size参数的meter表

下发meter表,设置 rate=5000burst_size=5000,所以理论上瞬时的限速值为rate+burst_size = 10M

ovs-ofctl -O OpenFlow13 add-meter s1 meter=3,kbps,burst,band=type=drop,rate=5000,burst_size=5000
1
ovs-ofctl-OOpenFlow13 add-meter s1 meter=3,kbps,burst,band=type=drop,rate=5000,burst_size=5000

验证

客户端以15M的带宽打流

022.png

设置服务端每秒输出一次带宽,从显示可以看出,第1秒中的速度达到10M,然后速度下降稳定在5M左右。

iperf -u -s -i 1
1
2
iperf-u-s-i1
 

023.png

分析:第1s内15M的带宽的流量到来,瞬间消耗了令牌桶的令牌 5000k ,同时加上稳定下发到令牌桶中的令牌 5000k/s,两方面加起来就是10M左右,所以第1s带宽能瞬间达到10M。如果后面带宽小于限速的5M,令牌桶内的令牌会慢慢积累起来,等待一下次高峰流量的到来。

小结

使用meter表能够完成很多创新的场景,比如 Qos,差异化服务等,希望通过本篇文章能够让学习SDN的童鞋掌握meter表的常规使用,实现更多自己的网络创新。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK