Skip to main content
开放网络的先行者与推动者—星融元
加入我们技术支持(Support)  TEL:(+86)4000989811

标签: 技术实现

REST API在SONiC中的实现


关注星融元


REST API 是什么?

REST API是一种面向资源的接口设计,所有的接口设计都是针对资源来设计的。简单理解就是用URI定位资源,用HTTP(GET、POST、DELETE、PUT、PATCH)描述操作。

目前,SONiC有一个原生RESTAPI框架,基于Golang实现,但功能仅有VLAN、VLAN interface、VXLAN tunnel、路由,功能上侧重业务。而星融元(Asterfusion)的REST API早于社区的原生REST API开发,并选择了具有轻量化,性能高的优点的Tornado框架,且一直在沿用。星融元(Asterfusion)REST API可以与SONiC原生REST API同时使用,未来,也将会贡献给社区。

下面我们来详细介绍一下星融元( Asterfusion )REST API软件:

星融元( Asterfusion )REST API基于Tornado框架开发,通过Nginx实现https方式访问。并在docker容器中运行,开销低,安全性高。同时为了解决RESTAPI在docker容器中不方便做一些系统级的操作如config reload、reboot等问题,我们在HOST上增加了sys-proxy模块,用于REST API直接调用HOST上的命令。

Tornado 是什么?

Tornado是一种 Web 服务器软件的开源版本。Tornado 和主流Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,效率高。

  • URI说明:https://<SWITCH_IP>[:端口号]/rest/<version>/<resource>
  • SWITCH_IP:为交换机的管理口IP;
  • 端口号:RESTAPI绑定的https端口号,默认为4430;
  • 版本:V3.0,属于RESTAPI的接口版本
  • resource是由各功能模块定义,详细说明请联系support@asterfusion.com索取《用户指导-CX系列产品RESTAPI手册》

星融元 REST API 的基本框架

星融元REST API 的软件框图 图 1 星融元(Asterfusion) RESTAPI 的软件框图

星融(Asterfusion)REST API运行在一个独立的docker容器中,因为设备web管理组件也运行在其中,所以命名为web-server。

在该容器中,主要包括Ngnix和REST API两大组件。其中Ngnix用于https的代理。

红色虚线中的部分基于Tornado框架实现。其中,service模块为REST API的主入口,它会监听对应端口,注册所有功能模块,并完成整个RESTAPI服务的初始化。

图中Modules就是这些功能模块,包括system、interface、router interface、VLAN等。每个模块包括schema、handler、adapter三部分。

最底层是wrapper层,封装了对数据库的操作。

RESTAPI服务还支持定时任务,比如用于采集接口的各种计数,并计算秒级速率。另外,还提供了一个与HOST进行交互的通道,当RESTAPI服务需要调用系统级的命令时,如reboot,config reload等,会与运行在HOST上的sys-proxy进行通信,用于系统命令的调用。

星融元 REST API 的代码结构

星融元 REST API 的代码结构
图2 星融元 REST API 的代码结构

REST API目录下是不同版本的REST API代码目录,Asterfusion REST API已经迭代到了V3版本。

V3目录下,有REST API服务主入口serivce.py和目录common、modules、task、wrapper。

common目录下是一些公共类、函数的实现。modules目录下是所有功能模块的实现,目前已实现的模块有:system、interface、VLAN、MAC、routerinterface、VRF、route、VXLAN、 BGP、EVPN、LAG、MC-LAG、LLDP、ECMP。在每一个module的目录里,都存在__init__.py、handler.py、adapter.py、schema.py这几个文件。

每个模块URI的格式统一在__init__.py里定义,如BGP是:

urls=[[r’/protocols/bgp-neighbors/([0-9a-fA-F.:]*)/?’, handler.BGPNeighborHandler]]

在handler.py中,定义了POST、DELETE、PATCH、GET、PUT方法的顶层实现。每个方法的具体逻辑由adapter.py中的函数实现。schema.py定义了每个模块对数据类型和范围的检查,如果检查不通过,会直接返回错误码。

task目录实现了轮询任务,目前有一个轮询任务是接口实时流量速率的计算。

wrapper是数据库原子级操作的一个封装层,adapter会调用wrapper层的函数。

星融元 REST API 基本功能介绍

星融元REST API基本功能介绍

星融元REST API 的特性

  • 高性能:基于非阻塞式的Tornado实现,并使用了hiredis库读写Redis数据库,效率更高;Nginx可以基于URI将不同的http请求分发到不同的RESTAPI进程,在多核CPU设备中效率更高。
  • 易扩展性:如果增加新模块只需要在modules目录下增加新的目录和代码即可。
  • POST、PATCH、PUT、DELETE操作有详细的返回数据,返错时会根据返回的数据直接定位到原因,如下图:POST、PATCH、PUT、DELETE操作详细的返回数据
  • 详细的log机制,每次REST API调用都会详细的log,如下图REST API调用都会详细的log

星融元 REST API 如何配置业务?举例IP Route和BGP-EVPN典型场景

场景1:IP Route

如上图所示,两个Server通过两个CX系列交换机进行三层通信,需要在两个交换机上创建routerinterface,并配置路由。

交换机A的配置:

  • 创建三层口:配置流程创建三层口
  • 创建路由:创建路由

交换机B的配置:

  • 创建三层口:
  • 创建路由:创建路由

场景2:BGP-EVPN

典型的Leaf-Spine场景

如上图所示,这是一个典型的Leaf-Spine场景,VM-A1和VM-A2属于同一个子网,它们需要通过VXLAN隧道进行二层通信,VM-B1属于另一个子网,它需要和VM-A2通过VXLAN隧道进行三层通信。

该场景需要配置每个交换机的BGP及BGP邻居、EVPN参数、创建VLAN和三层口并进行EVPN MAP相关的配置,分配L2VNI和L3VNI。

交换机192.168.10.1的配置:

  • 系统配置:系统配置
  • BGP邻居及相关三层口:BGP邻居及相关三层口BGP邻居及相关三层口
  • VLAN及三层口配置:VLAN及三层口配置VLAN及三层口配置VLAN及三层口配置
  • EVPN MAP:EVPN MAP

交换机192.168.10.2的配置:

  • 系统配置:系统配置
  • BGP邻居及相关三层口:BGP邻居及相关三层口BGP邻居及相关三层口

交换机192.168.10.3的配置:

  • 系统配置:系统配置
  • BGP邻居及相关三层口:BGP邻居及相关三层口BGP邻居及相关三层口
  • VLAN及三层口配置:VLAN及三层口配置VLAN及三层口配置VLAN及三层口配置
  • EVPN MAPEVPN MAP

相关文章

MC-LAG/VLAG在SONiC中的实现


关注星融元


什么是MC-LAG?

MC-LAG(Multi Chassis Link Aggregation Group,跨设备链路聚合组)是一种实现跨设备链路聚合的机制,通过将一台设备与另外两台设备进行跨设备链路聚合,保留了普通链路聚合的所有优点,同时提供了设备级别的冗余。

MC-LAG提供了一种横向虚拟化技术,将两台物理设备虚拟成单台逻辑设备,这台虚拟出来的“单个设备”与其相连的上行或下行设备实现“一对一”链路聚合。

物理拓扑与逻辑视图 图1 物理拓扑与逻辑视图[/caption]

如图1所示,MC-LAG组对外表现为一台逻辑设备,用于链路聚合;MC-LAG交换机组内部署Ethernet或LAG类型的peer-link用于MC-LAG之间协议信息交互,以及承担故障场景下的东西向流量。MC-LAG组对外表现为单一节点,相对于传统组网,在实现冗余备份时不会带来环路风险,同时链路聚合的负载均衡模式不会导致链路闲置,链路利用更加高效。

VLAG(Virtual Link Aggregation Group,虚拟链路聚合组)是一种在MC-LAG基础上发展而来的技术,其控制面逻辑与MC-LAG完全相同,区别在于VLAG设备组之间搭建VXLAN隧道,以该VXLAN隧道作为peer-link,摆脱了MC-LAG中需要在成员设备之间预留专门物理链路的限制。

如图2所示,Server端通过MC-LAG机制与另外两台设备S1、S2进行跨设备链路聚合。

MC-LAG基本拓扑 图2 MC-LAG基本拓扑[/caption]

MC-LAG/VLAG的名词解释

MC-LAG/VLAG的控制面

控制协议ICCP

SONiC在MC-LAG控制面采用轻量级的ICCP协议,在保障功能的前提下,只进行少量的一致性检测和信息同步。

ICCP(Inter-Chassis Communication Protocol,设备间交流协议),是在RFC7275中定义的标准协议。ICCP协议使用TCP端口8888在MC-LAG peer间建立连接,轻量级的ICCP协议会进行配置一致性检查、ARP表项和MAC表项同步。

ICCPD容器

在SONiC中容器ICCPD用来维护MC-LAG的控制层,ICCPD容器与其他模块的关联如图3所示。

ICCPD容器与其他模块关联图

  1. 容器ICCPD启动后,运行iccpd,mclagmgrd,mclagsyncd守护进程。iccpd为协议运行主进程,mclagsyncd通过TCP socket与iccpd进程交互信息;mclagmgrd通过调用iccpd提供的mclagdctl命令与iccpd进程进行交互。
  2. ICCPD容器启动时从CONFIG_DB中读取MC-LAG配置表项,mclagmgrd监听CONFIG_DB中MC-LAG配置表项变化。MC-LAG配置表项变化
  3. mclagsyncd监听ASIC DB中FDB表项变化信息,通知给iccpd进程。
  4. iccpd通过使用netlink消息与内核交互。当触发RTM_NEWLINK或RTM_DELLINK消息时,则更新端口所在vlan的信息;当触发RTM_NEWNEIGH或RTM_DELNEIGH,则更新本地ARP表项;当触发RTM_NEWADDR时,则更新本地MAC地址信息。另一方面,iccpd发送netlink消息来修改内核层端口的mac地址以及写入ARP表项。
  5. mclagsyncd从iccpd进程接收协议处理结果,修改APP_DB中相关表项。如APP_FDB_TABLE下发MAC表项,APP_ISOLATION_GROUP_TABLE添加隔离信息,APP_PORT_TABLE或APP_LAG_TABLE或APP_VXLAN_TUNNEL_TABLE写入端口mac学习属性。
  6. Orchagent订阅APP DB,之后的处理不再是ICCPD关心的范畴。

邻居建立

MC-LAG peer两台设备以local_ip和peer_ip为TCP连接的源地址和目的地址建立ICCP邻居。

MC-LAG peer两台设备分别承担Active和Standby角色。根据配置信息中的local_ip和peer_ip数字的大小比较,数字较小者作为Active端,TCP连接的Client端;数字较大者作为Standby端,TCP连接的Server端,Client端会主动向server发起连接请求。

当ICCP连接建立完成之后,MC-LAG peer根据peer-link的端口类型,修改APP_DB中的APP_PORT_TABLE或APP_LAG_TABLE或APP_VXLAN_TUNNEL_TABLE表项,关闭peer-link的mac学习功能。

关闭peer-link的mac学习功能

MC-LAG peer的Active,Standby角色仅为控制层面的概念,在数据转发面,MC-LAG peer各自决定流量转发路径,地位相同。

ICCP信息同步

在MC-LAG peer之间会同步以下信息:

  1. 系统信息:同步MC-LAG成员端口的MAC地址,保证MC-LAG peer向Server发送的LACP报文中“system ID”域相同,实现跨设备链路聚合。具体做法是当Standby端收到Active端的system MAC信息后,发送netlink消息,将本地MC-LAG成员端口的system ID修改为和Active端一致。
  2. MC-LAG成员端口配置信息:记录本地和对端MC-LAG成员端口的名称等信息,用来做一致性检查。
  3. MC-LAG成员端口状态信息:记录本地和对端MC-LAG成员端口状态,保证无故障情况下peer-link到MC-LAG成员端口的隔离,对端MC-LAG成员端口故障情况下peer-link到同名端口的隔离解除。隔离是向APP_DB中配置表项,隔离解除删除该表项。MC-LAG成员端口状态信息
  4. ARP信息:与MC-LAG成员端口相关的ARP表项会在MC-LAG peer之间进行同步。当收到对端的ARP消息之后,通过发送netlink消息在本地更新ARP表项。
  5. FDB信息:与MC-LAG成员端口相关的FDB表项会在MC-LAG peer之间进行同步。当收到对端的FDB消息之后,通过修改APP_DB中表项,更新本地FDB表项。
  6. FDB信息
  7. 心跳检测

在SONiC中,以1s为时间间隔向对端发送心跳报文,在连续15个周期没收到心跳报文时,则被判定为超时,ICCP连接断开。

一致性检测

SONiC使用轻量级ICCP协议进行以下属性的一致性检测:MC-LAG peer关于local_ip,peer_ip的配置对称;MC-LAG成员端口配置相同:名称、数量、加入的VLAN,VLAN的路由口IP,VLAN的路由口MAC地址;MC-LAG peer中peer-link的端口类型保持一致。

典型组网

MC-LAG中典型组网及配置如图4所示。

MC-LAG典型组网 图4 MC-LAG典型组网[/caption]

MC-LAN配置信息

MC-LAN配置信息

MC-LAG/VLAG场景下流量转发的配置

以图5配置为例,介绍一下配置VLAG场景下的二层流量转发情况。

VLAG组网配置
图5 VLAG组网配置

VLAG组网配置

VLAG组网配置

无故障流量转发

在无故障情况下,Server1与Server2之间的流量转发路径如图6中橙色曲线所示。

无故障流量转发 图6 无故障流量转发

  1. Server1上的广播流量通过PortChannel0001选路到达S1,在Vlan300中广播,复制到PortChannel0310到达Server2,复制到VTTNL1隧道封装经undelay网络到达S2。由于在S2上开启VTTNL1到PortChannel0310和PortChannel0300的转发隔离,广播报文不会回环到Server1,也不会第二次到达Server2。同时,由于VTTNL1的MAC学习功能被关闭,S2上关于Server1的FDB表项不会迁移到VTTNL1。
  2. Server1往Server2的单播流量通过PortChannel0001选路到达S1,在S1上查询FDB表项单播到达Server2。由于S1与S2的FDB表项同步,若选路到S2,也可查询FDB表项单播到达S2。

链路故障场景

当链路发生故障时,Server1与Server2之间的流量转发如图7所示。

链路故障流量转发 图7 链路故障流量转发

  1. S1上的PortChannel0310状态切换为down,Server2与S1之间的通信发生故障,S1和Server2直接感知该故障。
  2. Server2向Server1方向的广播和单播流量均直接通过S2进行转发。
  3. Server1向Server2方向的广播流量,当经过S2转发,则直接广播到达Server2;当经过S1时,广播复制到VTTNL1上,隧道封装经underlay网络到达S2后解封装,由于S2上已解除VTTNL1到PortChannel0310的单向隔离,则可在S2上广播复制到Server2。
  4. Server1向Server2方向的已知单播流量,当经过S2转发,则直接单播到达Server2;当经过S1时,由于S1上已将出接口为PortChannel0310的FDB表项重定向到VTTNL1上,则单播流量会经过VTTNL1隧道到达S2。由于S2上已解除VTTNL1到PortChannel0310的单向隔离,隧道报文解封装查询FDB表项经PortChannel0310单播转发到Server2。

设备故障场景

当MC-LAG组内成员设备发生故障时,Server1和Server2之间的流量转发如图8所示:

设备故障流量转发 图8 设备故障流量转发

  1. 如图8所示,S1设备发生故障,Server1和Server2之间ICCP连接断开。
  2. Server1和Server2均感知S1故障。Server1和Server2之间的流量均由S2承担,如图8橙色曲线所示。

相关文章

一文了解SONiC内部通信模型


关注星融元


SONiC使用Redis提供的两种机制:

  • publish/subscribe
  • keyspace

封装出多种通信模型,建立以Redis数据库为中心的的消息传递机制。同时也通过调用Linux工具命令对系统进行配置,并以发送和监听netlink消息的方式与内核通信。SONiC使用了多个Redis数据库,用来存放不同的配置、状态和控制表项等信息。

数据库说明如下:
数据库说明

以数据库为中心的模型

模型1:SubscriberStateTable

使用keyspace机制,向订阅者传递key-value消息。该机制不需要执行PUBLISH通知,对于每个修改数据库的操作,都会产生keyspace的事件消息,订阅者通过监听指定KEY,来获取所有对该KEY修改事件的通知。在SONiC中,该通信模型常用于对CONFIG_DB和STATE_DB的监听处理。

对CONFIG_DB的修改一般用于对系统进行配置操作,如使用命令行来配置系统功能,SONiC在sonic-py-swsssdk组件中封装了对CONFIG_DB的操作,根据传递data是否为空执行hmset或delete操作。

这里以监听CONFIG_DB配置VLAN为例说明。

VlanMgr在初始化时监听CFG_VLAN_TABLE_NAME和CFG_VLAN_MEMBER_TABLE_NAME,当通过config命令添加vlan 100的操作,在CONFIG_DB中生成名为”VLAN|Vlan100″的KEY,此时会产生keyspace的事件消息,触发VlanMgr::doTask(Consumer &consumer)来处理。这里的Consumer即是通过orch类封装过的SubscriberStateTable。

模型2:NotificationProducer & NotificationConsumer

使用Redis的publish/subscribe模型直接封装实现,通过消息队列来传递信息,内容可以灵活定义。在SONiC中,该通信模型主要用于orchagent和SYNCD之间的事件通知,例如FDB事件、端口状态变化等等。

以FDB事件为例,SYNCD收到来自底层驱动的FDB事件,调用对数据库的hset或del操作更新ASIC_DB中的FDB表项,同时作为Notification生产者发送名为“fdb_event”的通知消息。

以数据库为中心通信模型

图1 以数据库为中心通信模型

Notification的消费者流程在fdborch中实现,通知消息触发:

FdbOrch::doTas (NotificationConsumer&consumer)

来进行后续处理,更新orchagent中的FDB信息。

模型3:ProducerStateTable &ConsumerStateTable

使用Redis的publish/subscribe模型封装,通过publish通知KEY修改事件,利用KeySet机制来传递信息。该通信模型通过集合(set)来传递key-value信息,不指定操作动作,当传递的value为空时,对应操作为del,当传递的value非空,对应操作为set。

在SONiC中,该通信模型用于围绕APPL_DB的消息传递,生产者一般为cfgmgr或应用组件的syncd进程,消费者则是orchagent。

这种通信模型,在publish通知KEY修改事件前允许对key-value进行多次操作,操作过程不保证执行顺序。这样做的好处是不必在每次设置key-value时都触发事件通知,可以提升处理效率,但对orchagent处理流程有一定要求。orchagent作为消费者,在Consumer::execute过程中取出所有待处理的key-value信息,加入待处理的m_toSync映射表,当m_toSync映射表还有未处理完的信息时,会将新任务与旧任务合并,然后交由每个orch实例处理。

Orchagent调度处理采用epoll事件通知模型,事件触发即会产生调度;在调度处理中,可能出现因资源依赖等因素导致任务处理无法完成,此时可以选择将任务保留在m_toSync中等待下一次调度处理。在大规模控制表项和较复杂逻辑关系的场景下,这种调度机制可能出现因资源限制、依赖条件不满足等因素导致的频繁或无效调度,Asterfusion通过优化处理顺序、改进批量操作以及在STATE_DB中设置状态标志等改进方式,提高了组件运行效率并增强了可靠性。

模型4:ProducerTable& ConsumerTable

使用Redis的publish/subscribe模型封装,通过publish通知KEY修改事件,利用KeyValueOpQueues机制来传递信息。该通信模型通过有序链表(list)来传递key-value-op三元消息,在SONiC中,该模型用于围绕ASIC_DB和FLEX_COUNTER_DB的消息传递。与模型3相比,该模型保证了操作的严格执行顺序,在syncd执行SAI API调用时保证了对底层ASIC的操作时序。

与内核的通信方式

SONiC中应用模块与内核通信主要用于处理网络接口事件和路由等,包括向内核发送消息和获取内核消息,一般通过netlink机制或调用系统工具来完成。SONiC中使用的teamd、FRR等开源组件与内核存在依赖关系,采用这种通信机制在减少模块耦合性的同时,可以尽量减少对原有开源组件的修改。

向内核发送消息一般有两种方式:一种是通过调用Linux工具命令,如调用ip命令配置网络接口IP地址和设置VRF,又如调用bridge命令配置VLAN;另一种方式是直接发送netlink消息,例如通过NETLINK_ROUTE生成内核路由表。调用工具命令方式比较简单,用封装的swss::exec方法最终通过popen执行拼装好的command指令。对netlink消息操作则是通过以libnl库为基础封装的NetLink类来完成,同时SWSS也定义了一套NetDispatcher机制来实现netlink消息监听和分发处理。

这里以neighsyncd为例进行说明。

neighsyncd通过NetDispatcher提供的方法注册RTM_NEWNEIGH和RTM_DELNEIGH两类netlink消息类型的回调函数,当触发netlink消息事件时,调用NetDispatcher的onNetlinkMessage方法来处理。这里通过netlink消息类型来查找之前注册的回调函数,并最终调用nl_msg_parse来执行回调函数。neighsyncd的回调函数根据netlink携带的信息组织生成邻居表项,并向APP_NEIGH_TABLE写入相应键值。在生成邻居表项过程中,使用了SWSS实现的一种名为linkcache的机制,该机制缓存曾经使用的NETLINK_ROUTE消息,通过网络接口索引来查询网络接口名称。

下面以teamd流程示例来说明聚合组配置和聚合过程的通信流程。

teamd聚合组配置

聚合组配置流程

图2 聚合组配置流程

(1) 通过CLI创建名称为PortChannel0001的聚合组,并加入聚合组成员口Ethernet0和Ethernet4,在CONFIG_DB中生成配置表项。
生成配置表项

(2) teamdmgrd进程监听相应键值变化,调用doLagTask和doLagMemberTask方法处理。

(3) doLagTask方法解析参数并生成所需的配置文件conf,通过调用teamd命令创建并配置聚合组,并调用ip命令设置聚合组接口MAC地址和管理状态;doLagMemberTask方法中先判断聚合组及待加入聚合组成员接口状态是否满足要求,如果满足则调用teamdctl和ip命令来配置聚合成员接口,这里会将聚合成员口设置为down,否则挂起当前任务后续再处理。

doLagTask方法解析参数并生成所需的配置文件conf

(4) teamdmgrd作为生产者将聚合组和成员的配置信息写入APPL_DB。

(5) portsorch作为消费者订阅APP_LAG_TABLEAPP_LAG_MEMBER_TABLE进行处理。
portsorch作为消费者订阅APP_LAG_TABLEAPP_LAG_MEMBER_TABLE进行处理

(6) portsorch调用sairedis的API,检查参数类型合法性并将LAG配置信息写入ASIC_DB。

(7) SYNCD订阅ASIC_DB中的LAG相关表项并处理。
SYNCD订阅ASIC_DB中的LAG相关表项(8) SYNCD调用ASIC SDK对SAI API的实现,并通过ASICdriver下发到底层芯片。

teamd聚合过程

(1) teamsyncd初始化阶段注册监听RTM_NEWLINK和RTM_DELLINK类型的netlink消息,同时也会注册teamd的操作handler,用于处理teamd聚合成员口状态变化以及teamd参数变化触发的事件。

teamd聚合流程图3 teamd聚合流程

(2) teamsyncd处理两类消息。一类是netlink消息,当触发NEWLINK或DELLINK时对应操作STATE_LAG_TABLE设置聚合组状态;另一类是teamd状态变化消息,当teamd通过LACP交互及内部状态机产生聚合成员口状态变化,调用TeamSync::TeamPortSync::onChange进行处理。

(3) teamd感知聚合成员口发生状态变化,teamsyncd从teamd获取当前聚合成员列表和状态,与变化前的聚合成员列表进行比较。如果聚合成员已存在且状态发生变化,则直接修改相应的APP_LAG_MEMBER_TABLE成员状态,如果成员列表发生变化,则向APP_LAG_MEMBER_TABLE添加新增的成员口并设置成员状态以及删除不存在的成员口。
APP_LAG_MEMBER_TABLE

(4) portsorch作为消费者订阅APP_LAG_MEMBER_TABLE进行处理,根据聚合成员口状态设置SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE和SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE,决定是否允许通过该成员口接收流量以及从该成员口发送流量。

(5) portsorch调用sairedis的API,并更新LAG Member配置表项及属性到ASIC_DB。
portsorch调用sairedis的API

(6) SYNCD订阅ASIC_DB中的LAG Member表项并处理。

(7) 调用ASIC SDK对SAI API的实现,并通过ASIC driver下发到底层芯片。

相关文章

对星融元产品感兴趣?

立即联系!

返回顶部

© 星融元数据技术(苏州)有限公司 苏ICP备17070048号-2