原文链接:https://blog.csdn.net/bc_vnetwork/article/details/65630475

1.  SFC底层实现原理

port chain和ovs driver/agent

Port Chain插件架构图:

SFC Port Chain Plugin

+-------------------------------+

|  +-------------------------+  |

|  |    Port Chain API       |  |

|  +-------------------------+  |

|  |    Port Chain Database  |  |

|  +-------------------------+  |

|  |    Driver Manager       |  |

|  +-------------------------+  |

|  |    Common Driver API    |  |

|  +-------------------------+  |

|               |               |

|  +-------------------------+  |

|  |        OVS Driver       |  |

|  +-------------------------+  |

+---------------|--------------+

| rpc

+----------------+

|    OVS Agent   |

| ext sfc driver |

+----------------+

目前networking-sfc项目中的基于ovs的sfc实现还是用的mpls, nsh可能要Pike版本才能支持。

以下下列配置为例, 创建业务链串联sf1, sf2, sf3 三台nfv虚拟机, 并从VM1处发包进入业务链:

+------+     +------+        +------+

| SF1  |     | SF2  |        | SF3  |

+------+     +------+        +------+

p1|   |p2    p3|   |p4       p5|   |p6

|   |        |   |           |   |

VM 1-->----+   +--------+   +-----------+   +---->

根据代码中的一些限制(参考后面"限制"章节), p1必须和logical-source-port在一个子网中, p2、p3必须在一个子网中, p4、p5必须在一个子网中。

所以, 本示例中, 我们定义p1的子网为: 1.0.0.0/24, p2的子网为: 2.0.0.0/24, p3的子网为: 2.0.0.0/24, p4的子网为: 3.0.0.0/24, p5的子网为: 3.0.0.0/24, p6子网为4.0.0.0/24。

$ openstack network create sfc-net-1

$ openstack network create sfc-net-2

$ openstack network create sfc-net-3

$ openstack network create sfc-net-4

$ openstack network create sfc-net-5

$ openstack network create sfc-net-6

$ openstack subnet create --network sfc-net-1 --subnet-range 1.0.0.0/24 sfc-subnet-1

$ openstack subnet create --network sfc-net-2 --subnet-range 2.0.0.0/24 sfc-subnet-2

$ openstack subnet create --network sfc-net-3 --subnet-range 3.0.0.0/24 sfc-subnet-3

$ openstack subnet create --network sfc-net-4 --subnet-range 4.0.0.0/24 sfc-subnet-4

# 创建虚拟机, 命名为sfc-vm-1, 加入2个网络: sfc-net-1, sfc-net-2

# 创建虚拟机, 命名为sfc-vm-2, 加入2个网络: sfc-net-2, sfc-net-3

# 创建虚拟机, 命名为sfc-vm-3, 加入2个网络: sfc-net-3, sfc-net-4

# 修改虚拟机sfc-vm-1的nova port名字为: p1, p2

# 修改虚拟机sfc-vm-2的nova port名字为: p3, p4

# 修改虚拟机sfc-vm-3的nova port名字为: p5, p6

$ openstack sfc port pair create --ingress p1 --egress p2 port-pair-1

$ openstack sfc port pair create --ingress p3 --egress p4 port-pair-2

$ openstack sfc port pair create --ingress p5 --egress p6 port-pair-3

$ openstack sfc port pair group create --port-pair port-pair-1 port-pair-group-1

$ openstack sfc port pair group create --port-pair port-pair-2 port-pair-group-2

$ openstack sfc port pair group create --port-pair port-pair-3 port-pair-group-3

$ openstack sfc flow classifier create --source-ip-prefix 1.0.0.0/24 --logical-source-port p1 sfc-flow-class-1

$ openstack sfc port chain create --flow-classifier sfc-flow-class-1 --port-pair-group port-pair-group-1 --port-pair-group port-pair-group-2 --port-pair-group port-pair-group-3 sfc-port-chain-1

和以前的代码有区别, 现在sfc分为2大模块: 流分类(flow classifier)和sfc(业务链), 2大模块各自可以配置独立的驱动, 目前都只是通过ovs实现。按照官方想法, 以后流分类(sg,fw, qos, sfc等模块均包含流分类)这个功能会抽象出来统一维护。

核心流程代码流程在/services/sfc/drivers/ovs/driver.py中, 其中最核心的create_port_chain()作用如下: 通过用户输入的port-pair, port-group, port-chain信息, 生成path_nodes列表, path_nodes包括: 状态, 业务链中位置nsi (nsh index), 节点类型(src_node, sf_node, dst_node), 下一跳信息(port-pair列表和加权信息, 可以看出这里能做负载均衡),业务链id(分配的nsp id) 等等。

[

{

"status": "building",

"nsi": 255,

"portpair_details": [

"524c85b9-7038-43ac-bb29-7a90e62900fd"

],

"node_type": "src_node",

"next_hop": "[{\"portpair_id\": \"5197be46-cc98-4ac6-93a6-1759e963b1fe\", \"weight\": 1}]",

"next_group_id": 1,

"nsp": 1,

"fwd_path": true,

"id": "fd1b1ba6-01d7-4905-94f4-aa3bd8e6dc6d",

"tenant_id": "1af813712bdf42789fc90832dc5ce8be",

"portchain_id": "350fb8b7-cc89-49f7-888b-f80f8a0248a6",

"project_id": "1af813712bdf42789fc90832dc5ce8be"

},

{

"status": "building",

"nsi": 251,

"portpair_details": [],

"node_type": "dst_node",

"next_hop": null,

"next_group_id": null,

"nsp": 1,

"fwd_path": true,

"id": "5e34e41c-9db5-4ab4-8c94-e5e68092773f",

"tenant_id": "1af813712bdf42789fc90832dc5ce8be",

"portchain_id": "350fb8b7-cc89-49f7-888b-f80f8a0248a6",

"project_id": "1af813712bdf42789fc90832dc5ce8be"

},

{

"status": "building",

"nsi": 254,

"portpair_details": [

"5197be46-cc98-4ac6-93a6-1759e963b1fe"

],

"node_type": "sf_node",

"next_hop": "[{\"portpair_id\": \"018c8bf0-b93e-4732-9c50-23be5422bdb9\", \"weight\": 1}]",

"next_group_id": 2,

"nsp": 1,

"fwd_path": true,

"id": "d63f0bcf-2743-401f-85bc-41dea3ab7ed6",

"tenant_id": "1af813712bdf42789fc90832dc5ce8be",

"portchain_id": "350fb8b7-cc89-49f7-888b-f80f8a0248a6",

"project_id": "1af813712bdf42789fc90832dc5ce8be"

},

{

"status": "building",

"nsi": 253,

"portpair_details": [

"018c8bf0-b93e-4732-9c50-23be5422bdb9"

],

"node_type": "sf_node",

"next_hop": "[{\"portpair_id\": \"64bb88a2-1390-4c8f-b78f-011e9857e2b4\", \"weight\": 1}]",

"next_group_id": 3,

"nsp": 1,

"fwd_path": true,

"id": "6d864f84-bd8b-415b-8b15-0137057cc15a",

"tenant_id": "1af813712bdf42789fc90832dc5ce8be",

"portchain_id": "350fb8b7-cc89-49f7-888b-f80f8a0248a6",

"project_id": "1af813712bdf42789fc90832dc5ce8be"

},

{

"status": "building",

"nsi": 252,

"portpair_details": [

"64bb88a2-1390-4c8f-b78f-011e9857e2b4"

],

"node_type": "sf_node",

"next_hop": null,

"next_group_id": null,

"nsp": 1,

"fwd_path": true,

"id": "099da96f-01b0-4f3b-9aab-1281960aeb4f",

"tenant_id": "1af813712bdf42789fc90832dc5ce8be",

"portchain_id": "350fb8b7-cc89-49f7-888b-f80f8a0248a6",

"project_id": "1af813712bdf42789fc90832dc5ce8be"

}

]

如果用户创建的是非对称链(单向), 那么就创建出一条path_nodes。如果用户创建的是对称链(双向), 那么就创建出一条fwd_path_nodes和一条rev_path_nodes。

然后根据path_nodes里的信息, 调用_update_path_nodes()-> _update_path_node_flowrules(), RPC调用ovs-agent上的sfc extension driver方法 :update_flow_rules(), 最终下流表配置到ovs上。

现有的OVS Driver/agent都会被改造和扩展支持service chain。

OVS agent会在br-int和br-tun网桥上下发一些额外流表:

1. 流量分类流表: 会在br-int集成网桥中, 下发流表, 用来做流量分类(即flow-classifier)。

2. Service Function转发流表: 会在br-tun网桥上下发流表, 使需要走service chain的流量通过tunnel走到下一个port chain 端口。而br-int也会用来终结Service Function Path.

这里, ovs-agent会通过封装mpls header来标示chain path。其中, mpls label用来表示chain path id, mpls ttl表示chain hop index(指下一跳, 是该chain上的第几个port).

MPLS报文头封装结构如下:

在这里mpls用于模拟nsh协议报文:

mpls_label字段定义为: nsp<<8 | nsi

mpls_ttl定义为: nsi

nsp即NSH Path ID

nsi即NSH index

511: 即0001 | 11111111 意义为: 业务链ID: 1, 节点位置为255

510: 即0001 | 11111110 意义为: 业务链ID: 1, 节点位置为254

509: 即0001 | 11111101 意义为: 业务链ID: 1, 节点位置为253

port信息:

p1: 997(qvof5ea457f-b7): addr: fa:16:3e:4d:10:37

p2: 998(qvo28855064-04): addr:92:8c:c8:c6:41:22

p3: 999(qvo84b4cdbb-af): addr:fe:ae:86:22:eb:cc

p4: 1000(qvo68434f35-f6): addr:0e:d7:5d:60:e2:ad

p5: 1001(qvofdaf5c1c-01): addr:16:29:4f:32:40:1b

p6: 1002(qvo704baa4f-59): addr:ba:9c:5e:a4:36:4b

br-int flow信息:

每一跳入口的sfc flow匹配和负载均衡, 在table:0中实现:

table=0, priority=30,ip,in_port=997 ,nw_src=1.0.0.0/24 actions=group:1【匹配p1端口和流分类规则, 转发到group:1,做第1跳的出口负载均衡,并转发给第1个NFV虚拟机】

table=0, priority=30,ip,in_port=998 ,nw_src=1.0.0.0/24 actions=group:2【匹配p2端口和流分类规则, 转发到group:2,做第2跳的出口负载均衡,并转发给第2个NFV虚拟机】

table=0, priority=30,ip,in_port=1000 ,nw_src=1.0.0.0/24 actions=group:3【匹配p4端口和流分类规则, 转发到group:2,做第3跳的出口负载均衡,并转发给第3个NFV虚拟机】

table=0, priority=30,ip,in_port=1002 ,nw_src=1.0.0.0/24 actions=NORMAL 【匹配p6(即业务链出端口), 然后走正常转发流程】

每一跳出口的sfc报头封装, 在table:5中实现:

table=5, priority=0,ip,dl_dst=fa:16:3e:4d:10:37 actions=push_mpls:0x8847,set_field:511->mpls_label,set_mpls_ttl(255),push_vlan:0x8100,set_field:4150->vlan_vid,resubmit(,10) 【匹配发往p1 tap的报文,封装sfc头(这里是mpls),并打上本地vlan, 发往远端计算节点或发给本地table:10】

table=5, priority=0,ip,dl_dst=fa:16:3e:b5:64:7e actions=push_mpls:0x8847,set_field:510->mpls_label,set_mpls_ttl(254),push_vlan:0x8100,set_field:4128->vlan_vid,resubmit(,10) 【匹配发往p3 tap的报文,封装sfc头(这里是mpls),并打上本地vlan, 发往远端计算节点或发给本地table:10】

table=5, priority=0,ip,dl_dst=fa:16:3e:51:39:b6 actions=push_mpls:0x8847,set_field:509->mpls_label,set_mpls_ttl(253),push_vlan:0x8100,set_field:4169->vlan_vid,resubmit(,10) 【匹配发往p5 tap的报文,封装sfc头(这里是mpls),并打上本地vlan, 发往远端计算节点或发给本地table:10】

本地sfc报头解封装,并发往nfv虚拟机, 在table:10中实现:

table=10, priority=1,mpls,dl_vlan=54,dl_dst=fa:16:3e:4d:10:37,mpls_label=511 actions=pop_vlan,pop_mpls:0x0800,output:997【p1在本地, 匹配目的mac为p1的业务链1报文, mpls解封装, 并发送p1】

table=10, priority=1,mpls,dl_vlan=32,dl_dst=fa:16:3e:b5:64:7e,mpls_label=510 actions=pop_vlan,pop_mpls:0x0800,output:999【p3在本地, 匹配目的mac为p1的业务链1报文, mpls解封装, 并发送p3】

table=10, priority=1,mpls,dl_vlan=73,dl_dst=fa:16:3e:51:39:b6,mpls_label=509 actions=pop_vlan,pop_mpls:0x0800,output:1001【p5在本地, 匹配目的mac为p5的业务链1报文, mpls解封装, 并发送p5】

br-int group信息, 这里主要是用来在每个sf出口处做负载均衡的:

group_id=1,type=select,bucket=actions=set_field:fa:16:3e:4d:10:37->eth_dst,resubmit(,5)【修改目的mac为p1 tap口,并转发到table 5】

group_id=2,type=select,bucket=actions=set_field:fa:16:3e:b5:64:7e->eth_dst,resubmit(,5)【修改目的mac为p3 tap口,并转发到table 5】

group_id=3,type=select,bucket=actions=set_field:fa:16:3e:51:39:b6->eth_dst,resubmit(,5)【修改目的mac为p5 tap口,并转发到table 5】

发包验证:

为了减少安全组和port-security对实验的影响, 放开所有NFV虚拟机的安全组, 关闭port-security。

# neutron port-update 68434f35-f6fc-4c64-bbd3-55aca8f7b6ef --no-security-groups

# neutron port-update 68434f35-f6fc-4c64-bbd3-55aca8f7b6ef --port_security_enabled=True

...

在目的主机sfc-vm-3上开启sshd服务:

# systemctl start sshd

在sfc-vm-1上配置ARP:

# arp -s 2.0.0.1 fa:16:3e:ee:ee:ee

在sfc-vm-2上配置路由转发, 把eth0的流量转发到eth1上去:

# echo 1 > /proc/sys/net/ipv4/ip_forward

# ip route add 10.0.0.0/24 dev eth1

# arp -s 4.0.0.8 fa:16:3e:ee:ee:dd

在sfc-vm-1上ssh 4.0.0.8(即sfc-vm-3的p6端口):

SFC-VM-1抓图:

sfc-vm-2中间节点报文抓取截图:

sfc-vm-2 eth0口:

sfc-vm-2 eth1口:

sfc-vm-3上抓图, 能够正确抓到从sfc-vm-2发过来的报文:

计算节点上br-int的流表信息, 可以发现报文确实走的相应流表, 流表统计上

总结如下:

OVS agent在br-int中加了以下流用来实现sfc portchain:

1. table:0 增加sfc流表用来匹配流分类规则, 然后转发给group表做负载均衡

2. table:5 封装sfc头部, 并转发给下一跳nfv虚拟机, 可能在远端节点走br-tun或本地节点走table:10

3. table:10做sfc报头解封装, 并转发给nfv虚拟机

2.  限制

1. 目前不支持nsh头。

networking-sfc项目底层ovs驱动暂时是借用了mpls来实现sfc报文封装的, 其最终目标会通过使用标准nsh报文头来封装sfc。目前底层的openvswitch官方组件还不支持nsh解析、处理, 不过有人fork了ovs的代码自己实现了nsh标准:

https://github.com/pritesh/ovs/tree/nsh-v8

2. 业务链上的logical_source_port必须和整条链上第一个port-pair group中的所有port_pair上的ingress port在一个subnet中, 否则会报"Cross-subnetchain not supported"

3. 业务链上的相邻的2个port-pair group中, 前一个port-pair group中的所有port-pair上的egress port必须和后一个port-pair group上的所有port-pair上的ingress port在一个subnet中, 否则会报"Cross-subnetchain not supported"

4. 命令openstack sfc flow classifier create, 中必须指定logicalsource port, 文档中没有指出。

5. symmetric链中, 必须指定logicaldestination port

6. flow classifier中只能指定ethertype=IPv6或者IPv4,

3.  参考资料

Neutron SFC

Wiki

https://wiki.openstack.org/wiki/Neutron/ServiceInsertionAndChaining

Blueprints

https://blueprints.launchpad.net/neutron/+spec/openstack-service-chain-framework

https://blueprints.launchpad.net/neutron/+spec/intent-based-service-chaining

https://blueprints.launchpad.net/neutron/+spec/neutron-api-extension-for-service-chaining

https://blueprints.launchpad.net/neutron/+spec/common-service-chaining-driver-api

https://blueprints.launchpad.net/neutron/+spec/service-registration-and-integration-for-service-chaining

API Spec

https://docs.openstack.org/developer/networking-sfc/

https://github.com/openstack/networking-sfc/blob/master/doc/source/api.rst

https://review.openstack.org/#/c/208663/8/doc/source/portchain-ovs-driver-agent.rst

代码review

https://review.openstack.org/#/q/topic:networking-sfc,n,z

OpenStack cli

https://review.openstack.org/#/c/344920/

OVS NSH

http://openvswitch.org/support/ovscon2015/16/1040-elzur.pdf

OpenStack 业务链networking-sfc介绍 (2) - 底层原理的更多相关文章

  1. OpenStack 业务链networking-sfc介绍 (1) - 概述

    原文链接:https://blog.csdn.net/bc_vnetwork/article/details/65630355 1.  Service Function Chain概述 Neutron ...

  2. Docker底层原理介绍

    1.docker介绍 1.1什么是docker Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻 ...

  3. 最简单的HashMap底层原理介绍

    HashMap 底层原理  1.HashMap底层概述 2.JDK1.7实现方式 3.JDK1.8实现方式 4.关键名词 5.相关问题 1.HashMap底层概述 在JDK1.7中HashMap采用的 ...

  4. JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能

    摘要: 理解浏览器渲染. 原文:JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这是专门探索 J ...

  5. 拜托!面试请不要再问我Spring Cloud底层原理

    概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓 ...

  6. 深入源码分析SpringMVC底层原理(二)

    原文链接:深入源码分析SpringMVC底层原理(二) 文章目录 深入分析SpringMVC请求处理过程 1. DispatcherServlet处理请求 1.1 寻找Handler 1.2 没有找到 ...

  7. 《React Native 精解与实战》书籍连载「React Native 底层原理」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

  8. 并发之volatile底层原理

    15.深入分析Volatile的实现原理 14.java多线程编程底层原理剖析以及volatile原理 13.Java中Volatile底层原理与应用 12.Java多线程-java.util.con ...

  9. 拜托!面试请不要再问我Spring Cloud底层原理[z]

    [z]https://juejin.im/post/5be13b83f265da6116393fc7 拜托!面试请不要再问我Spring Cloud底层原理 欢迎关注微信公众号:石杉的架构笔记(id: ...

随机推荐

  1. 基于 Lucene 的桌面文件搜索

    开源2010年,自己在学习 Lucene 时开发的一款桌面文件搜索工具,这么多年过去了,代码一直静静存放在自己的硬盘上,与其让其沉睡,不如分享出来. 这款工具带有明显的模仿 Everything 的痕 ...

  2. html 1.0 鼠标放上去会亮 onmouseover onmouseout 以及this标签的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. java 重定向和转发 的区别

    重定向方式的含义是第一个页面通知浏览器发送一个新的页面请求.因为,当你使用重定向时,浏览器中所显示的URL会变成新页面的URL, 而当使用转发时,该URL会保持不变. 重定向的速度比转发慢,因为浏览器 ...

  4. 2 数据库开发--MySQL下载(windows)

    Windows:(mysql) 操作: 0.下载安装mysql www.mysql.org downloads->进入社区community community 5.7.21 下载5.6 Mic ...

  5. 【转】楼天城楼教主的acm心路历程(作为励志用)

    利用假期空闲之时,将这几年GCJ,ACM,TopCoder 参加的一些重要比赛作个回顾.昨天是GCJ2006 的回忆,今天时间上更早一些吧,我现在还清晰记得3 年前,我刚刚参加ACM 时参加北京赛区2 ...

  6. 如何在ArcMap中监听键盘鼠标事件(转)

    如何在ArcMap中监听键盘鼠标事件(转) Link: http://www.cnblogs.com/dyllove98/p/3155551.html 昨天有个朋友想要实现一个功能,就是在ArcMap ...

  7. 【hdu3507】Print Article 【斜率优化dp】

    题意 https://cn.vjudge.net/problem/HDU-3507 分析 斜率优化的模板题 #include <cstdio> #include <cstring&g ...

  8. 79. Word Search (Array; DFS,Back-Track)

    Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...

  9. Oracle之SYSDBA的使用

    曾经没加名字可以创建一个表却要加名字才可以查出来,但只是偶然吧! 如果真的使用了SYSDBA,必须加名字

  10. sql时间戳转日期格式

    FROM_UNIXTIME(ctime, '%Y-%m-%d %H:%i:%s')