天天看點

SAI:Switch Abstraction Interface

<a href="https://github.com/opencomputeproject/SAI" target="_blank">https://github.com/opencomputeproject/SAI</a>

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**)&amp;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&lt;sai_pointer_t&gt;(&amp;on_switch_state_change); //注冊事件處理函數

attr[2].id = SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY;

attr[2].value.ptr = reinterpret_cast&lt;sai_pointer_t&gt;(&amp;on_shutdown_request);

attr[3].id = SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY;

attr[3].value.ptr = reinterpret_cast&lt;sai_pointer_t&gt;(&amp;on_fdb_event);

attr[4].id = SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY;

attr[4].value.ptr = reinterpret_cast&lt;sai_pointer_t&gt;(&amp;on_port_state_change);

attr[5].id = SAI_SWITCH_ATTR_PACKET_EVENT_NOTIFY;

attr[5].value.ptr = reinterpret_cast&lt;sai_pointer_t&gt;(&amp;on_packet_event);

sai_switch_api-&gt;create_switch(&amp;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(&amp;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&lt;switch_sai_rpcHandler&gt; handler(new switch_sai_rpcHandler());

shared_ptr&lt;TProcessor&gt; processor(new switch_sai_rpcProcessor(handler));

shared_ptr&lt;TServerTransport&gt; serverTransport(new TServerSocket(port));

shared_ptr&lt;TTransportFactory&gt; transportFactory(new TBufferedTransportFactory());

shared_ptr&lt;TProtocolFactory&gt; 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 &amp;thrift_attr_list) 

sai_api_query(SAI_API_VLAN, reinterpret_cast&lt;void**&gt;(&amp;vlan_api));  //擷取vlan子產品函數集

sai_thrift_parse_vlan_attributes(thrift_attr_list, attr_list);

vlan_api-&gt;create_vlan(&amp;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 = &amp;vlan_api;   //各晶片提供各個子產品的函數集

return SAI_STATUS_SUCCESS;

case SAI_API_ROUTE:

*(const sai_route_api_t**)api_method_table = &amp;route_api;

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 = &amp;switch_api;

case SAI_API_PORT:

*(const sai_port_api_t**)api_method_table = &amp;port_api;

case SAI_API_FDB:

*(const sai_fdb_api_t**)api_method_table = &amp;fdb_api;

*(const sai_vlan_api_t**)api_method_table = &amp;vlan_api;

case SAI_API_VIRTUAL_ROUTER:

*(const sai_virtual_router_api_t**)api_method_table = &amp;router_api;

case SAI_API_NEXT_HOP:

*(const sai_next_hop_api_t**)api_method_table = &amp;next_hop_api;

case SAI_API_NEXT_HOP_GROUP:

*(const sai_next_hop_group_api_t**)api_method_table = &amp;next_hop_group_api;

case SAI_API_ROUTER_INTERFACE:

*(const sai_router_interface_api_t**)api_method_table = &amp;router_interface_api;

case SAI_API_NEIGHBOR:

*(const sai_neighbor_api_t**)api_method_table = &amp;neighbor_api;

case SAI_API_QOS_MAPS:

/* TODO : implement */

return SAI_STATUS_NOT_IMPLEMENTED;

case SAI_API_ACL:

case SAI_API_HOST_INTERFACE:

*(const sai_hostif_api_t**)api_method_table = &amp;host_interface_api;

子產品劃分:

typedef enum _sai_api_t

{

SAI_API_UNSPECIFIED = 0, /**&lt; unspecified API */

SAI_API_SWITCH = 1, /**&lt; sai_switch_api_t */

SAI_API_PORT = 2, /**&lt; sai_port_api_t */

SAI_API_FDB = 3, /**&lt; sai_fdb_api_t */

SAI_API_VLAN = 4, /**&lt; sai_vlan_api_t */

SAI_API_VIRTUAL_ROUTER = 5, /**&lt; sai_virtual_router_api_t */

SAI_API_ROUTE = 6, /**&lt; sai_route_api_t */

SAI_API_NEXT_HOP = 7, /**&lt; sai_next_hop_api_t */

SAI_API_NEXT_HOP_GROUP = 8, /**&lt; sai_next_hop_group_api_t */

SAI_API_ROUTER_INTERFACE = 9, /**&lt; sai_router_interface_api_t */

SAI_API_NEIGHBOR = 10, /**&lt; sai_neighbor_api_t */

SAI_API_ACL = 11, /**&lt; sai_acl_api_t */

SAI_API_HOSTIF = 12, /**&lt; sai_hostif_api_t */

SAI_API_MIRROR = 13, /**&lt; sai_mirror_api_t */

SAI_API_SAMPLEPACKET = 14, /**&lt; sai_samplepacket_api_t */

SAI_API_STP = 15, /**&lt; sai_stp_api_t */

SAI_API_LAG = 16, /**&lt; sai_lag_api_t */

SAI_API_POLICER = 17, /**&lt; sai_policer_api_t */

SAI_API_WRED = 18, /**&lt; sai_wred_api_t */

SAI_API_QOS_MAP = 19, /**&lt; sai_qos_map_api_t */

SAI_API_QUEUE = 20, /**&lt; sai_queue_api_t */

SAI_API_SCHEDULER = 21, /**&lt; sai_scheduler_api_t */

SAI_API_SCHEDULER_GROUP = 22, /**&lt; sai_scheduler_group_api_t */

SAI_API_BUFFER = 23, /**&lt; sai_buffer_api_t */

SAI_API_HASH = 24, /**&lt; sai_hash_api_t */

SAI_API_UDF = 25, /**&lt; sai_udf_api_t */

SAI_API_TUNNEL = 26, /**&lt; sai_tunnel_api_t */

SAI_API_L2MC = 27, /**&lt; sai_l2mc_api_t */

SAI_API_IPMC = 28, /**&lt; sai_ipmc_api_t */

SAI_API_RPF_GROUP = 29, /**&lt; sai_rpf_group_api_t */

SAI_API_L2MC_GROUP = 30, /**&lt; sai_l2mc_group_api_t */

SAI_API_IPMC_GROUP = 31, /**&lt; sai_ipmc_group_api_t */

SAI_API_MCAST_FDB = 32, /**&lt; sai_mcast_fdb_api_t */

SAI_API_BRIDGE = 33, /**&lt; sai_bridge_api_t */

SAI_API_TAM = 34, /**&lt; sai_tam_api_t */

SAI_API_SEGMENTROUTE = 35, /**&lt; sai_segmentroute_api_t */

SAI_API_MPLS = 36, /**&lt; sai_mpls_api_t */

SAI_API_UBURST = 37, /**&lt; sai_uburst_api_t */

SAI_API_MAX = 38, /**&lt; total number of APIs */

} sai_api_t;