https://github.com/opencomputeproject/SAI

The Switch Abstraction Interface defines the API to provide a vendor-independent way of controlling forwarding elements, such as a switching ASIC, an NPU or a software switch in a uniform manner.

简单理解,SAI是对转发芯片进行一层功能抽象,SDK为每个模块(如VLAN/PORT/FDB等)提供一组函数集,API通过函数集调用SDK接口从而实现转发面的配置管理;另外实现了一套事件处理回调处理。

不足之处:

1)转发芯片功能抽象不稳定,导致接口或参数频繁变化

2)无协议报文处理模块

3)事件处理功能不完整

4)函数集居然不是注册方式

1、main(saiserver.cpp)

1)创建转发芯片:create_switch

sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api);

attr[0].id = SAI_SWITCH_ATTR_INIT_SWITCH;
attr[0].value.booldata = true;

attr[1].id = SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY;
attr[1].value.ptr = reinterpret_cast<sai_pointer_t>(&on_switch_state_change); //注册事件处理函数

attr[2].id = SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY;
attr[2].value.ptr = reinterpret_cast<sai_pointer_t>(&on_shutdown_request);

attr[3].id = SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY;
attr[3].value.ptr = reinterpret_cast<sai_pointer_t>(&on_fdb_event);

attr[4].id = SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY;
attr[4].value.ptr = reinterpret_cast<sai_pointer_t>(&on_port_state_change);

attr[5].id = SAI_SWITCH_ATTR_PACKET_EVENT_NOTIFY;
attr[5].value.ptr = reinterpret_cast<sai_pointer_t>(&on_packet_event);

sai_switch_api->create_switch(&gSwitchId, attrSz, attr);

2)stub版本的创建芯片

const sai_switch_api_t switch_api = {
stub_initialize_switch,
stub_shutdown_switch,
stub_connect_switch,
stub_disconnect_switch,
stub_set_switch_attribute,
stub_get_switch_attribute,
};

sai_status_t stub_initialize_switch(_In_ sai_switch_profile_id_t profile_id,
_In_reads_z_(SAI_MAX_HARDWARE_ID_LEN) char * switch_hardware_id,
_In_reads_opt_z_(SAI_MAX_FIRMWARE_PATH_NAME_LEN) char* firmware_path_name,
_In_ sai_switch_notification_t * switch_notifications)

memcpy(&g_notification_callbacks, switch_notifications, sizeof(g_notification_callbacks));

db_init_vlan();
db_init_next_hop_group();

3)创建rpc线程

start_sai_thrift_rpc_server(SWITCH_SAI_THRIFT_RPC_SERVER_PORT);

2、rpc线程

static void * switch_sai_thrift_rpc_server_thread(void *arg) {
int port = *(int *) arg;
shared_ptr<switch_sai_rpcHandler> handler(new switch_sai_rpcHandler());
shared_ptr<TProcessor> processor(new switch_sai_rpcProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}

3、功能处理,以创建vlan为例  //class switch_sai_rpcHandler

1) sai_thrift_object_id_t sai_thrift_create_vlan(const std_sai_thrift_attr_vctr_t &thrift_attr_list)

sai_api_query(SAI_API_VLAN, reinterpret_cast<void**>(&vlan_api));  //获取vlan模块函数集
sai_thrift_parse_vlan_attributes(thrift_attr_list, attr_list);
vlan_api->create_vlan(&vlanObjId, gSwitchId, attr_size, attr_list);  //创建vlan

2)sai_api_query

sai_status_t sai_api_query(_In_ sai_api_t sai_api_id, _Out_ void** api_method_table)
case SAI_API_VLAN:
*(const sai_vlan_api_t**)api_method_table = &vlan_api;   //各芯片提供各个模块的函数集
return SAI_STATUS_SUCCESS;
case SAI_API_ROUTE:
*(const sai_route_api_t**)api_method_table = &route_api;
return SAI_STATUS_SUCCESS;

3)stub or sdk

const sai_vlan_api_t vlan_api = {
stub_create_vlan,
stub_remove_vlan,
stub_set_vlan_attribute,
stub_get_vlan_attribute,
stub_add_ports_to_vlan,
stub_remove_ports_from_vlan,
stub_remove_all_vlans,
stub_get_vlan_stats,
NULL
};

4、获取函数集,sai_api_query

switch (sai_api_id) {
case SAI_API_SWITCH:
*(const sai_switch_api_t**)api_method_table = &switch_api;
return SAI_STATUS_SUCCESS;

case SAI_API_PORT:
*(const sai_port_api_t**)api_method_table = &port_api;
return SAI_STATUS_SUCCESS;

case SAI_API_FDB:
*(const sai_fdb_api_t**)api_method_table = &fdb_api;
return SAI_STATUS_SUCCESS;

case SAI_API_VLAN:
*(const sai_vlan_api_t**)api_method_table = &vlan_api;
return SAI_STATUS_SUCCESS;

case SAI_API_VIRTUAL_ROUTER:
*(const sai_virtual_router_api_t**)api_method_table = &router_api;
return SAI_STATUS_SUCCESS;

case SAI_API_ROUTE:
*(const sai_route_api_t**)api_method_table = &route_api;
return SAI_STATUS_SUCCESS;

case SAI_API_NEXT_HOP:
*(const sai_next_hop_api_t**)api_method_table = &next_hop_api;
return SAI_STATUS_SUCCESS;

case SAI_API_NEXT_HOP_GROUP:
*(const sai_next_hop_group_api_t**)api_method_table = &next_hop_group_api;
return SAI_STATUS_SUCCESS;

case SAI_API_ROUTER_INTERFACE:
*(const sai_router_interface_api_t**)api_method_table = &router_interface_api;
return SAI_STATUS_SUCCESS;

case SAI_API_NEIGHBOR:
*(const sai_neighbor_api_t**)api_method_table = &neighbor_api;
return SAI_STATUS_SUCCESS;

case SAI_API_QOS_MAPS:
/* TODO : implement */
return SAI_STATUS_NOT_IMPLEMENTED;

case SAI_API_ACL:
/* TODO : implement */
return SAI_STATUS_NOT_IMPLEMENTED;

case SAI_API_HOST_INTERFACE:
*(const sai_hostif_api_t**)api_method_table = &host_interface_api;
return SAI_STATUS_SUCCESS;

模块划分:

typedef enum _sai_api_t
{
SAI_API_UNSPECIFIED = 0, /**< unspecified API */
SAI_API_SWITCH = 1, /**< sai_switch_api_t */
SAI_API_PORT = 2, /**< sai_port_api_t */
SAI_API_FDB = 3, /**< sai_fdb_api_t */
SAI_API_VLAN = 4, /**< sai_vlan_api_t */
SAI_API_VIRTUAL_ROUTER = 5, /**< sai_virtual_router_api_t */
SAI_API_ROUTE = 6, /**< sai_route_api_t */
SAI_API_NEXT_HOP = 7, /**< sai_next_hop_api_t */
SAI_API_NEXT_HOP_GROUP = 8, /**< sai_next_hop_group_api_t */
SAI_API_ROUTER_INTERFACE = 9, /**< sai_router_interface_api_t */
SAI_API_NEIGHBOR = 10, /**< sai_neighbor_api_t */
SAI_API_ACL = 11, /**< sai_acl_api_t */
SAI_API_HOSTIF = 12, /**< sai_hostif_api_t */
SAI_API_MIRROR = 13, /**< sai_mirror_api_t */
SAI_API_SAMPLEPACKET = 14, /**< sai_samplepacket_api_t */
SAI_API_STP = 15, /**< sai_stp_api_t */
SAI_API_LAG = 16, /**< sai_lag_api_t */
SAI_API_POLICER = 17, /**< sai_policer_api_t */
SAI_API_WRED = 18, /**< sai_wred_api_t */
SAI_API_QOS_MAP = 19, /**< sai_qos_map_api_t */
SAI_API_QUEUE = 20, /**< sai_queue_api_t */
SAI_API_SCHEDULER = 21, /**< sai_scheduler_api_t */
SAI_API_SCHEDULER_GROUP = 22, /**< sai_scheduler_group_api_t */
SAI_API_BUFFER = 23, /**< sai_buffer_api_t */
SAI_API_HASH = 24, /**< sai_hash_api_t */
SAI_API_UDF = 25, /**< sai_udf_api_t */
SAI_API_TUNNEL = 26, /**< sai_tunnel_api_t */
SAI_API_L2MC = 27, /**< sai_l2mc_api_t */
SAI_API_IPMC = 28, /**< sai_ipmc_api_t */
SAI_API_RPF_GROUP = 29, /**< sai_rpf_group_api_t */
SAI_API_L2MC_GROUP = 30, /**< sai_l2mc_group_api_t */
SAI_API_IPMC_GROUP = 31, /**< sai_ipmc_group_api_t */
SAI_API_MCAST_FDB = 32, /**< sai_mcast_fdb_api_t */
SAI_API_BRIDGE = 33, /**< sai_bridge_api_t */
SAI_API_TAM = 34, /**< sai_tam_api_t */
SAI_API_SEGMENTROUTE = 35, /**< sai_segmentroute_api_t */
SAI_API_MPLS = 36, /**< sai_mpls_api_t */
SAI_API_UBURST = 37, /**< sai_uburst_api_t */
SAI_API_MAX = 38, /**< total number of APIs */
} sai_api_t;

转载于:https://www.cnblogs.com/soul-stone/p/7787983.html

SAI:Switch Abstraction Interface相关推荐

  1. 华为-vlan间路由之SVI(switch virtual interface)

    SVI(switch virtual interface) (使用多层交换机 配置 vlanif接口) 交换机: vlan batch 10 20 interface GigabitEthernet0 ...

  2. R语言switch语句语法、实战:Switch语句用来处理嵌套的if else处理起来比较困难或者麻烦的条件判断问题

    R语言switch语句语法.实战:Switch语句用来处理嵌套的if else处理起来比较困难或者麻烦的条件判断问题 目录

  3. jenkis编译报错:需要class,interface或enum

    现象: 1.jenkis编译报错:需要class,interface或enum 2.使用ant进行编译ok. 解决方法: 1. Jenkis重新编译一个以前成功的svn版本,直至编译成功. 2.Jen ...

  4. NLP炼丹笔记:Switch Transformers 朴实无华 大招秒杀

    作者:九羽,公众号:炼丹笔记 Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient S ...

  5. 网络工程师交换试验手册之十八:SWITCH的基本配置

    实验目的  熟悉交换机的基本操作  为定义控制台密码  为交换更改主机名称  为交换机控制台的添加IP地址和默认网关等 实验设备: 1912交换机和2924交换机. 1900系列交换机的基本配 ...

  6. 【C语言简单说】十一:switch 补

    昨天丧心病狂的更新了十节.我都懵逼了... *~ ( ̄﹏ ̄) ** 今天继续,来说一下...那个...另外一个分支switch. 直接上代码,学过了if的孩子就会觉得很简单的了: #include&l ...

  7. c语言学习加强营(一):switch分支

    #include <stdio.h> #include <stdlib.h>int main(int argc, char **argv) {int num = 0;if (a ...

  8. java学习(26):switch

    /扩展练习: 任务5:switch语句 编写控制台Java程序,使用Scanner对象相关方法接收用户输入的年份和月份, 输出这个月有多少天.(提示:闰年计算方法为:能被4整除单不能被100整除:或者 ...

  9. Java基础篇:switch语句

    switch语句是Java的多路分支语句.它提供了一种基于一个表达式的值来使程序执行不同部分的简单方法.因此,它提供了一个比一系列if-else-if语句更好的选择.switch语句的通用形式如下: ...

  10. 教妹学Java(十四):switch 语句详解

    大家好,我是沉默王二,一个和黄家驹一样身高,和刘德华一样颜值的程序员.本篇文章通过我和三妹对话的形式来谈一谈"switch 语句". 教妹学 Java,没见过这么有趣的标题吧?&q ...

最新文章

  1. Windows/Linux TCP Socket网络编程简介及测试代码
  2. 一网打尽数据结构中线性表链表的相关算法
  3. cmd指令大全指令_Linux 超全实用指令大全 | CSDN 博文精选
  4. 2015!我来了,你在哪里?今年第一篇
  5. 判断任意控制台输入的十进制数是否为水仙花数
  6. day36 fullstack gevent模块 IO阻塞和非阻塞 IO多路复用 异步IO介绍 其他的补充
  7. 01. Node js Hello world
  8. leetcode题库3-- 无重复字符的最长子串
  9. 使用CucumberJS,让JavaScript与行为驱动开发结合
  10. c语言进程池原理及实现
  11. FreeCAD源码分析:Assembly4模块
  12. Windows 11正式版来了!一文带你免费升级、镜像下载、最低系统要求
  13. 中南大学复试上机:1021:机器人走迷宫
  14. 语音通知API - onealert的语音通告替代调研
  15. 刷脸支付到来用户连密码都不需要
  16. 硬件学习(一)电容作用
  17. ElasticSearch学习(十)—— 增加身份认证
  18. 线上宠物店一体化服务小程序设计与开发
  19. 如何充分发挥 Scrapy 的异步能力【转载】
  20. 对偶线性规划——问题转化

热门文章

  1. sql server 替换字符串中的某些字符
  2. 软件工程导论患者监护系统
  3. IDEA 常用快捷键
  4. vscode设置字体颜色
  5. C语言算三角形外心坐标,三角形外心坐标公式(含C语言代码)
  6. linux系统如何启动rpcbind,在Linux系统上关闭rpcbind、postfix、rpc.statd、hpiod服务的方法...
  7. 电赛练习之旋转倒立摆PID调节
  8. 2020年数据库系统工程师下午真题及答案解析
  9. eclipse添加windowsBuilder的方法
  10. Linux多线程编程入门