原文链接: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. 建设银行网上银行MD5withRSA php版

    1. 首先通过java程序将建设银行的公钥串转成pem格式并写入文件 SignTest.java是运行程序, RSASig.java是建设银行签名算法类, bcprov-jdk15-145.jar是P ...

  2. 迷你MVVM框架 avalonjs 0.97发布

    在本版本中,王之三柱臣全部就位! mmRouter: https://github.com/RubyLouvre/mmRouter mmAnimate: https://github.com/Ruby ...

  3. Symfony 建立一个Bundle

    如果说,这个时候你萌生了一个去看一看Symfony源码的想法,个人建议还是算了,看了之后,你就会感到非常迷茫.因为他实在是大于绝大部分你使用过的框架,并且有多达近二十个的插件,使用了一些非常精巧的设计 ...

  4. MathExamLv2——周世元211606348,许燕婷211606338

    结对编程 211606348 周世元 211606338 许燕婷 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) P ...

  5. servlet中关于下载

    package com.huawei.response; import java.io.BufferedInputStream;import java.io.IOException;import ja ...

  6. aws代理

    ssh -i ~/.ssh/seoul-notification-dev.pem  ec2-user@52.79.58.125ssh -CqTnN -D localhost:7080   -i ~/. ...

  7. filebeat 笔记

    认识Beats Beats是用于单用途数据托运人的平台.它们以轻量级代理的形式安装,并将来自成百上千台机器的数据发送到Logstash或Elasticsearch. (画外音:通俗地理解,就是采集数据 ...

  8. N 秒打开一个新窗口

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  9. WSTMart开发文档

    WSTMart开发文档页面   PC版   开源版 授权版   序言   WSTMart安装协议   WSTMart电商系统安装   商城前台安装操作指南   用户中心指南   商家中心操作指南   ...

  10. PhpStorm (强大的PHP开发环境)2017.3.2 附注册方法

    最新版PhpStorm 2017正式版改进了PHP 7支持,改进代码完成功能. PhpStorm 是最好的PHP开发工具,使用它进行PHP开发将会让你感觉到编程的乐趣. 快乐无极终于从oschina看 ...