1. syncd应用启动
1.1 syncd应用启动参数
syncd应用启动初始化时可以设置参数,如下图所示:
 
-d
-p file
sai.profile
 
-t startType
  
STRING_SAI_START_TYPE_COLD_BOOT
STRING_SAI_START_TYPE_WARM_BOOT
STRING_SAI_START_TYPE_FAST_BOOT
STRING_SAI_START_TYPE_FASTFAST_BOOT
STRING_SAI_START_TYPE_UNKNOWN
-u
-S
-U
-C
-s
-z mode
SAI_REDIS_COMMUNICATION_MODE_REDIS_ASYNC
SAI_REDIS_COMMUNICATION_MODE_REDIS_SYNC
SAI_REDIS_COMMUNICATION_MODE_ZMQ_SYNC
-l
-g index
-x
-x file
 
-b breakConfig
SAI_OBJECT_TYPE_ACL_TABLE
-r
-m file
 
-h
最终barefoot的启动命令为:
 
/usr/bin/syncd -u -l -p /usr/share/sonic/hwsku/sai.profile
不支持热重启没有指定上下文配置不允许同步模式
1.2 syncd应用启动初始化
初始化启动位于
syncd_main.cpp
 
设置syncd应用的日志存放检查syncd应用是否支持热重启 – 不支持解析syncd应用启动时设置的参数
默认信息
 
设置的参数信息
    
m_enableTempView = true
m_enableSaiBulkSupport = true
m_profileMapFile = "/usr/share/sonic/hwsku/sai.profile"
gPortMap
VendorSai
Syncd
1.3 
Syncd
Syncd
初始化启动位于
syncd.cpp
 传入参数: 
VendorSai
CommandLineOptions
isWarmStart
成员变量赋初值
  
m_commandLineOptions
CommandLineOptions
m_isWarmStart
bool
false
m_firstInitWasPerformed
false
m_asicInitViewMode
false
m_vendorSai
VendorSai
m_veryFirstRun
false
m_enableSyncMode
false
m_timerWatchdog
TimerWatchdog
根据api类型分别设置Log级别 – 
SAI_LOG_LEVEL_NOTICE
根据启动参数获取上下文信息,如果参数没有设置,则获取默认的:
 
{"guid":0,"name":"syncd","dbAsic":"ASIC_DB","dbCounters":"COUNTERS_DB","dbFlex":"FLEX_COUNTER_DB","dbState":"STATE_DB","zmqEnable":"false","zmqEndpoint":"ipc:///tmp/zmq_ep","zmqNtfEndpoint":"ipc:///tmp/zmq_ntf_ep"}
如果上下文中允许使用ZeroMQ机制(
m_contextConfig->m_zmqEnable=true
m_commandLineOptions->m_enableSyncMode=true
  
m_commandLineOptions->m_enableSyncMode = false;
m_commandLineOptions->m_redisCommunicationMode = SAI_REDIS_COMMUNICATION_MODE_ZMQ_SYNC;
 不执行,因为
m_contextConfig->m_zmqEnable=false
m_commandLineOptions->m_enableSyncMode=false
如果启动参数中允许同步模式(
m_commandLineOptions->m_enableSyncMode=true
  
m_enableSyncMode = true;
m_contextConfig->m_zmqEnable = false;
m_commandLineOptions->m_redisCommunicationMode = SAI_REDIS_COMMUNICATION_MODE_REDIS_SYNC;
 不执行,因为
m_commandLineOptions->m_enableSyncMode=false
如果启动参数中设置的通信模式是基于ZeroMQ机制的同步模式(
m_commandLineOptions->m_redisCommunicationMode = SAI_REDIS_COMMUNICATION_MODE_ZMQ_SYNC
  
m_contextConfig->m_zmqEnable = true;
m_enableSyncMode = true;
 不执行,因为
m_commandLineOptions->m_redisCommunicationMode=SAI_REDIS_COMMUNICATION_MODE_REDIS_ASYNC
 上述三个判断说明如果支持ZeroMQ机制,那么将优先使用基于ZeroMQ机制的同步模式进行通信。  
初始化成员变量
std::shared_ptr<FlexCounterManager> m_manager
COUNTERS_DB
如果启动参数中设置了·
-p file
sai.profile
m_profileMap
  
SAI_VS_GLOBAL_CONTEXT
SAI_KEY_VS_CONTEXT_CONFIG
SAI_KEY_WARM_BOOT_WRITE_FILE
var/warmboot/sai-warmboot.bin
SAI_KEY_WARM_BOOT_READ_FILE
/var/warmboot/sai-warmboot.bin
sai.profile
SAI_KEY_WARM_BOOT_WRITE_FILE
SAI_KEY_WARM_BOOT_READ_FILE
初始化与
asic_db
判断是否允许启动ZeroMQ机制,初始化成员变量
std::shared_ptr<NotificationProducerBase> m_notifications
std::shared_ptr<sairedis::SelectableChannel> m_selectableChannel
  允许(
m_contextConfig->m_zmqEnable=true
    使用
ZeroMQNotificationProducer
m_notifications
ZeroMQSelectableChannel
m_selectableChannel
ZeroMQChannel
m_enableSyncMode = true;
m_contextConfig->m_zmqEnable=false
    使用
RedisNotificationProducer
m_notifications
RedisSelectableChannel
m_selectableChannel
RedisChannel
m_enableSyncMode = m_commandLineOptions->m_redisCommunicationMode == SAI_REDIS_COMMUNICATION_MODE_REDIS_SYNC;
m_notifications
m_selectableChannel
m_communicationChannel
初始化notification相关成员对象,启动notification处理线程,写入asic_db: switch相关事件通知,比如交换机状态变化、端口状态变化、fdb事件等,有两个来源:
  syncd应用启动的时候: 根据配置文件得到热重启能力,然后更新启动类型接收来自orchagent应用的通知: 如果通知中的object类型是
SAI_OBJECT_TYPE_SWITCH
ASIC_DB RESTARTQUERY CHANNEL
初始化
FLEX_COUNTER_DB
  
FLEX_COUNTER_TABLE
FLEX_COUNTER_GROUP_TABLE
初始化成员对象
std::shared_ptr<sairedis::VirtualObjectIdManager> m_virtualObjectIdManager
初始化成员对象
std::shared_ptr<VirtualOidTranslator> m_translator
  vid: 表示虚拟的object id,用于在orchagent以及syncd之间作为参数传递rid: 表示调用sdk真正创建了对象之后得到的object id判断是否是第一次运行,赋值标志位
m_veryFirstRun
HGETALL HIDDEN
  
  
根据当前启动参数判断启动类型,并且更新
m_profileMap
SAI_BOOT_TYPE
performStartupLogic()
 
m_profileMap[SAI_KEY_BOOT_TYPE] = "SAI_START_TYPE_COLD_BOOT";
SAI_START_TYPE_COLD_BOOT = 0
调用
vendorSai->initialize()
  
sai_api_initialize()
sai_metadata_apis_query()
初始化成员
std::shared_ptr<BreakConfig> m_breakConfig
启动循环
Syncd::run()
Syncd::run()
初始化热重启table对象: 
STATE_DB:WARM_RESTART_TABLE
runMainLoop = true
Select
s
onSyncdStart()
s
s->select()
epoll
  处理来自
asic_db
RESTARTQUERY
NotificationConsumer
FLEX_COUNTER_DB
FLEX_COUNTER_TABLE
ConsumerTable
FLEX_COUNTER_DB
FLEX_COUNTER_GROUP_TABLE
ConsumerTable
orchagent
asic_db
syncd
false
  如果是热重启,将结束信息以及一些标志位写入
state_db
WARM_RESTART_TABLE
VendorSai::uninitialize()
2 事件通知预处理
2.1 通知消息读取

上述过程是读取内核中的事件通知过程:
epoll_wait查询当前存在的连接是否有events遍历得到的fd,针对每个fd:
  调用
Selectable::readData()
m_ready
m_ready
  从集合中删除,并且更新时间戳如果该订阅对象没有events,继续循环如果该订阅对象有events,返回该对象作为待处理的events对象;如果不只一条event,重新将该fd插入到有序集合中更新订阅对象中待处理的消息数量,退出循环  
在添加消费者的过程中实际上存在两类消费者,一类是
NotificationConsumer
ConsumerTable
 事件通知读取 – readData():
 首先
s->select()
如果是
ConsumerTable
 
PUBLISH ASIC_STATE_CHANNEL G
NotificationConsumer
m_queue
2.2 事件通知预处理 – pop()
以单个事件处理为例。首先分析一下从队列中取出一个事件的过程:
 事件通知预处理 – pop():
如果是
ConsumerTable
m_buffer
ConsumerTable::pops()
  使用
EVALSHA
consumer_table_pops.lua
ASIC_STATE_KEY_VALUE_OP_QUEUE
ASIC_DB
ASIC_STATE
key
ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE:oid:0x%
<key,op,values>
vector
m_buffer
NotificationConsumer
m_queue

上图是事件通知的通用处理操作:
从key值反序列出对应的object type以及object id:
  
key
SAI_OBJECT_TYPE_ACL_TABLE:oid:0x%
{"object type":"SAI_OBJECT_TYPE_ACL_TABLE", "oid":"oid:0x%"}
判断object type是否有效
构造属性列表对象,主要是检查属性的有效性,以及针对属性value的反序列化
 
如果事件类型是
SAI_OBJECT_TYPE_SWITCH
isInitViewMode(): 当前配置信息是false,所以不执行
如果不是get操作,需要将所有属性的vid转换为rid
调用sdk库获取object type对应的meta信息
 
根据meta信息判断调用哪一个处理方法,以acl为例,调用
Syncd::processOid()
sai_status_t processOid(
    _In_ sai_object_type_t objectType,
    _In_ const std::string &strObjectId,
    _In_ sai_common_api_t api,
    _In_ uint32_t attr_count,
    _In_ sai_attribute_t *attr_list);
  
objectType
SAI_OBJECT_TYPE_ACL_TABLE
strObjectId
oid:0x%
api
SAI_COMMON_API_CREATE
attr_count
attr_list
当前操作如果是GET操作,需要向asic_db写入响应;如果是其他操作,如果是同步模式则需要写入响应,如果是异步模式,则直接返回成功 – 响应的写入与读取也是基于redis的订阅/发布机制,不再赘述
3 acl事件处理
在处理各种操作之前,调用sdk库获取object type对应的meta信息 – 
info
3.1 CREATE
调用
processOidCreate()
create
sai_status_t processOidCreate(
    _In_ sai_object_type_t objectType,
    _In_ const std::string &strObjectId,
    _In_ uint32_t attr_count,
    _In_ sai_attribute_t *attr_list);
主要步骤只有两步:
调用
VendorSai::create()

主要看一下每一个方法向下调用过程中的参数变化与处理:
VendorSai::create()
 virtual sai_status_t create(
    _In_ sai_object_type_t objectType,
    _Out_ sai_object_id_t* objectId,
    _In_ sai_object_id_t switchId,
    _In_ uint32_t attr_count,
    _In_ const sai_attribute_t *attr_list)
  
objectType
SAI_OBJECT_TYPE_ACL_TABLE
objectId
switchId
attr_count
attr_list
 处理:
  调用sdk库获取object type对应的meta信息
info
info
create
info->create()
object id
objectId
info->create()
 最终调用的是sdk中
saimetadata.c
sai_metadata_generic_create_SAI_OBJECT_TYPE_ACL_TABLE()
sai_status_t sai_metadata_generic_create_SAI_OBJECT_TYPE_ACL_TABLE(
    _Inout_ sai_object_meta_key_t *meta_key,
    _In_ sai_object_id_t switch_id,
    _In_ uint32_t attr_count,
    _In_ const sai_attribute_t *attr_list)
{
    return sai_metadata_sai_acl_api->create_acl_table(&meta_key->objectkey.key.object_id, switch_id, attr_count, attr_list);
}
  
meta_key
{ .objecttype = objectType, .objectkey = { .key = { .object_id = 0 } } }
.objectkey = { .key = { .object_id = 0 } }
switchId
attr_count
attr_list
 然后与orchagent应用中调用sairedis api的过程类似,
sai_metadata_sai_acl_api
sai_api_initialize()
sai_api_query()
saiacl.app
acl_api
sai_status_t sai_create_acl_table(_Out_ sai_object_id_t *acl_table_id,
    _In_ sai_object_id_t switch_id,
    _In_ uint32_t attr_count,
    _In_ const sai_attribute_t *attr_list) 
 其中
acl_table_id
meta_key
.objectkey
  检查属性列表与table类型是否匹配将属性列表信息转化为符合switch store的对应属性信息最后调用
bf_switch_object_create()
bf_switch_object_create()
switch_status_t bf_switch_object_create(const switch_object_type_t  object_type, 
    const std::set<smi::attr_w> &attrs,
    switch_object_id_t &object_handle) {
    return smi::api::smi_object_create(object_type, attrs, object_handle);
}
  
object_type
SAI_OBJECT_TYPE_ACL_TABLE
attrs
object_handle
smi::api::smi_object_create()
switch_status_t smi_object_create(const switch_object_type_t object_type,
    const std::set<attr_w> &attrs,
    switch_object_id_t &object_handle);
  检查当前类型的table是否支持这些属性调用
switch_store::object_create()
switch_store::object_create()
switch_status_t object_create(const switch_object_type_t object_type,
    const std::set<attr_w> &attrs,
    switch_object_id_t &object_id);
  检查object type以及属性信息 – 比上一步骤中的检查更底层一点??检查triggers,如果存在create之前执行的trigger,执行
oid_create()
db::object_create()
create_keys()
create_membership()
未完待续…
 
                
 
                 
                 
                





 
                