Different types of thread-safe Sets in Java

本文详细介绍了Java中四种不同类型的线程安全集合:CopyOnWriteArraySet、Collections.synchronizedSet、ConcurrentSkipListSet及ConcurrentHashMap的实现原理、使用场景与性能对比。

http://stackoverflow.com/questions/6720396/different-types-of-thread-safe-sets-in-java

1) The CopyOnWriteArraySet is a quite simple implementation - it basically has a list of elements in an array, and when changing the list, it copies the array. Iterations and other accesses which are running at this time continue with the old array, avoiding necessity of synchronization. The normally fast set operations (especially contains()) are quite slow here, as the arrays will be searched in linear time.

Use this only for really small sets which will be read (iterated) often and changed seldom. (Swings listener-sets would be an example, but these are not really sets, and should be only used from the EDT anyway.)

2) Collections.synchronizedSet will simply wrap a synchronized-block around each method of the original set. You should not access the original set directly. This means that no two methods of the set can be executed concurrently (one will block until the other finishes) - this is thread-safe, but you will not have concurrency if multiple threads are really using the set. If you use the iterator, you usually still need to synchronize externally to avoid ConcurrentModificationExceptions when modifying the set between iterator calls. The performance will be like the performance of the original set (but with some synchronization overhead, and blocking if used concurrently).

Use this if you only have low concurrency, and want to be sure all changes are immediately visible to the other threads.

3) ConcurrentSkipListSet is the concurrent SortedSet implementation, with most basic operations in O(log n). It allows concurrent adding/removing and reading/iteration, where iteration may or may not tell about changes since the iterator was created. The bulk operations are simply multiple single calls, and not atomically - other threads may observe only some of them.

Obviously you can use this only if you have some total order on your elements. This looks like an ideal candidate for high-concurrency situations, for not-too-large sets (because of the O(log n)).

4) For the ConcurrentHashMap (and the Set derived from it): Here most basic options are (on average, if you have a good and fast hashCode()) in O(1) (but might degenerate to O(n)), like for HashMap/HashSet. There is a limited concurrency for writing (the table is partitioned, and write access will be synchronized on the needed partition), while read access is fully concurrent to itself and the writing threads (but might not yet see the results of the changes currently being written). The iterator may or may not see changes since it was created, and bulk operations are not atomic. Resizing is slow (as for HashMap/HashSet), thus try to avoid this by estimating the needed size on creation.

Use this when you have large sets, a good (and fast) hash function and can estimate the set size and needed concurrency before creating the map.


内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
有以下两份代码,其中,代码1: /* Copyright(c) 2009-2025 Chengdu TP-LINK Technologies Co.Ltd. * * file srvcQos.c * brief * details * * author zhanghaoxuan * version * date 14Aug25 * * history \arg */ /**************************************************************************************************/ /* INCLUDE_FILES */ /**************************************************************************************************/ /* libc header */ #include <stdio.h> /* syscall header */ /* common header */ #include "fepTypes.h" #include "fepDefs.h" /* platform header */ #include "midware/dal.h" /* public application header */ #include "common/applError.h" #include "common/dmpComDef.h" /*private header*/ #include "srvcQos.h" #include "adQos.h" #include "qos/dalQosPub.h" #include "qos/qosPub.h" #include "qos/logQos.h" #include "qos/errQos.h" #include "data/dataQos.h" #include "data/stateQos.h" #include "l2/l2Pub.h" #include "l2/port/cfgPortPub.h" #include "l2/port/portPub.h" #include "l2/port/dalPortPub.h" #include "l2/port/statPortPub.h" #include "l2/lag/statLagPub.h" #include "l2/lag/lagPub.h" #include "tpDbg/tpdebug.h" #include "syslog/syslog.h" #include "libApp/libQos/libQos.h" #include "libDcm/libStack/libStack.h" /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ #define QOS_IFG_DELAY (10.8) #define QOS_RATE_ADJUST_PAR 1514 #define QOS_RATE_KBPS_THOUSAND 1000 #define QOS_RATE_PERCENT_HUNDRED 100 #define QOS_STORM_EXCEED_LOG_CYCLE 60 // secs #define OMADA_KEY_OSW_STORM "OSW_DET_STORM" #define OMADA_KEY_OSW_PB "OSW_PB" #define QOS_MIB_UPDATE_TIMER_NAME "qos_mib_update_tm" #define AD_QOS_RATE_ADJUST_BY_PACKET_LENGTH(factor, packet_length) \ { \ if(packet_length >= 64 && packet_length < 128) \ { \ factor = 1.04 + (packet_length-64)*0.0022; \ } \ else if(packet_length >= 128 && packet_length < 192) \ { \ factor = 1.18 + (packet_length-128)*0.0009; \ } \ else if(packet_length >= 192 && packet_length < 256) \ { \ factor = 1.24 + (packet_length-192)*0.0004; \ } \ else if(packet_length >= 256 && packet_length < 320) \ { \ factor = 1.27 + (packet_length-256)*0.0003; \ } \ else if(packet_length >= 320 && packet_length < 384) \ { \ factor = 1.29 + (packet_length-320)*0.0002; \ } \ else if(packet_length >= 384 && packet_length < 1536) \ { \ factor = 1.30 + (packet_length-384)*0.00004; \ } \ } #define PORT_UP2STR(up, str)\ if(UP_IS_VALID(up) && (NULL != (str)))\ {\ *(str)='\0';\ usUp2Str((up), (str), UP_STR_BRF_PRFX);\ } typedef struct { int updateFlag; } QOS_MIB_UPDATE_MSG; /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ extern int preQueueWeight[QOS_QUEUE_MAX_NUM]; /**************************************************************************************************/ /* EXTERN_PROTOTYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* LOCAL_PROTOTYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* VARIABLES */ /**************************************************************************************************/ static TIMER_ID qosMibUpdateTimer ; static pal_msgq_t qosSrvcMsgQ = PAL_MQ_ERROR; pal_thread_t qosTimerTaskId = PAL_THREAD_ERROR; //static int qosTrapCounter = 0; //static QOS_PORT_RATE_DIFF_STRUCT rateDiff[UP_UNIT_PORT_MAX+1]; static int qosTrapCounter = 0; static BOOL l_ingressLogEnable = FALSE; static BOOL l_egressLogEnable = FALSE; static BOOL l_bcLogEnable = FALSE; static BOOL l_mcLogEnable = FALSE; /**************************************************************************************************/ /* LOCAL_FUNCTIONS */ /**************************************************************************************************/ /* helper routine: transform the ratio rate to kbps rate*/ static void _rateValueTransform(user_port uPort, UINT32 *rateValue) { QOS_PORT_STATUS portStatus = {}; user_port_list lagMemberList = {}; user_port up = {}; int lagId = 0; int index = 0; int portRate = 0; int tmpRate = 0; int speedValue[UP_ABILITY_SPEED_END] = PORT_SPEED_VALUE; APPL_ENSURE_RET_VOID(UP_IS_VALID(uPort)); APPL_ENSURE_RET_VOID(NULL != rateValue); uplist_init(&lagMemberList); APPL_IF_ERR_DONE_VOID(adQosGetPortLinkStatus(uPort, &portStatus)); if (DISABLE == portStatus.status) { if (UP_IS_LAG(uPort)) { UP_TO_LAG(uPort, lagId); dataQosLagMemberListGet(lagId, &lagMemberList); UP_ITER_LIST_SWP(&lagMemberList, index, up) { tmpRate = QOS_PORT_MAX_RATE_KBPS(up) / QOS_RATE_KBPS_THOUSAND; if (0 == portRate || tmpRate < portRate) { portRate = tmpRate; } } } else { portRate = QOS_PORT_MAX_RATE_KBPS(uPort) / QOS_RATE_KBPS_THOUSAND; } } else { portRate = speedValue[portStatus.speedMode]; } *rateValue = (*rateValue) * portRate * (QOS_RATE_KBPS_THOUSAND / QOS_RATE_PERCENT_HUNDRED); //本应为 (rateValue/100) * (portRate*1000),为防止UINT32溢出,需要交换顺序 rateValueAdjust(rateValue); done: uplist_free(&lagMemberList); return; } static void _qosMsgRecover(QOS_AD_MSG_T qosMsg) { user_port physicalPort = {}; user_port logicPort = {}; QOS_PORT_STATUS portStatus = {}; UINT8 linkState = 0; //NTFY_QOS qosNtfy = {}; TIMER_ID recoverTimer = {}; TIMER_ID_INIT(recoverTimer); memcpy(&physicalPort, &qosMsg.qosRcvr.physicalPort, sizeof(user_port)); //物理端口 memcpy(&logicPort, &qosMsg.qosRcvr.logicPort, sizeof(user_port)); //lag端口 if (UP_CMP(physicalPort, logicPort)) /* 获取端口配置的状态 */ dataQosRcvrTimerIdLagSet(physicalPort, recoverTimer); else /*dealing with phy port*/ dataQosRcvrTimerIdPhySet(physicalPort, recoverTimer); /*check port config, if port set to disable ,do not enable this phy port*/ if (UP_CMP(physicalPort, logicPort)) { qosStatePortStatusGet(logicPort, &portStatus); } else { qosStatePortStatusGet(physicalPort, &portStatus); } stateQosPortBlockStatusSet(physicalPort, DISABLE); /* QOS_TODO:堆叠时,向master发送notify更新recovery信息 */ #if 0 if (!DEV_ROLE_LOCAL_IS_MASTER()){ memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.block = DISABLE; unit_list ul={}; UNIT_LIST_ADD(ul, UNIT_MASTER); notify_call_remote(ul, NOTIFY_QOS_STORM_CTRL_BLOCK, &qosNtfy, sizeof(qosNtfy)); } #endif QOS_DEBUG("linkStatus:%d",portStatus.status); if (portStatus.status == ENABLE) { adQosGetPortState(physicalPort, &linkState); if(linkState != ENABLE) { adQosSetPortState(physicalPort, ENABLE); } } else { adQosSetPortState(physicalPort, DISABLE); } } static void _qosRateRecoverTimerNotify(void *data) { // QOS_AD_MSG_T qosMsg = {}; // user_port *upArr = data; // // APPL_ENSURE_RET_VOID(data != NULL); // // qosMsg.qosRcvr.physicalPort = upArr[0]; // qosMsg.qosRcvr.logicPort = upArr[1]; // qosMsg.type = QOS_MSG_RCVR; QOS_AD_MSG_T qosMsg = {}; APPL_ENSURE_RET_VOID(data != NULL); user_port *upArr = (user_port*) data; qosMsg.qosRcvr.physicalPort = upArr[0]; qosMsg.qosRcvr.logicPort = upArr[1]; qosMsg.type = QOS_MSG_RCVR; _qosMsgRecover(qosMsg); } static STATUS _qosPortMibUpdateCb() { // DW("_qosPortMibUpdateCb"); int ret = ERR_NO_ERROR; char *key = NULL; void *handler = NULL; user_port logicPort = {}; user_port physicalPort = {}; QOS_PORT_RATE_DIFF_STRUCT rateDiff = {}; UINT64 ingressVal = 0; UINT64 egressVal = 0; UINT64 bcVal = 0; UINT64 mcVal = 0; UINT32 rate = 0; TIMER_ID recoverTimer; TIMER_ID_INIT(recoverTimer); struct timespec timer = {}; char strUp[STR_STRUP_SIZE] = {}; char timerName[STR_TIMER_NAME_SIZE] = {}; APPQOS_ADCFG_OPT optCfg = {}; QOS_PORT_STATUS portStatus = {}; UINT32 lagId = 0; UINT8 shutdownFlag = 0; NTFY_QOS qosNtfy = {}; MAC_ADDRESS sysMac = {}; char macStr[STR_MAC_SIZE] = {}; char portStr[STR_STRUP_SIZE] = {}; memset(macStr, 0, 20); libStkSysDevMacGet(UNIT_CURRENT, sysMac); ether2str(macStr, sysMac, CSL_UPCASE, STR_TRANS_CLI); qosTrapCounter++; if (qosTrapCounter >= QOS_STORM_EXCEED_LOG_CYCLE) { qosTrapCounter = 0; l_ingressLogEnable = TRUE; l_egressLogEnable = TRUE; l_bcLogEnable = TRUE; l_mcLogEnable = TRUE; } /* 置位flag */ BOOL f_ingressLogEnable = FALSE; BOOL f_egressLogEnable = FALSE; BOOL f_bcLogEnable = FALSE; BOOL f_mcLogEnable = FALSE; dal_ado_t *adoi; adoi = dalAsdoiCreate(DMP_DEV_NAME_SWITCHMAC, DAL_MOD_PORT, DAL_CFG_TYPE_ENTRY); APPL_ENSURE_DONE(ret, adoi, ERR_NO_MEMORY); dalAdoiEntryTableAppend(adoi, DAL_PORT_K_MIB); dalAdoiEntryOperAppend(adoi, DAL_PORT_K_MIB, DAL_OPER_GET_ALL); if (PFM_ERR_C_OK != dalGet(adoi)) { ret = ERR_BAD_PARAM; goto done; } if (NULL != (handler = DAL_ADOI_ENTRY(adoi, DAL_PORT_K_MIB))) { DAL_ADOI_ENTRY_LOOP(handler) { if(NULL == (key = DAL_ADOI_ENTRY_KEY(handler)) || !DAL_ADOI_ENTRY_KEY_MATCH(handler, DAL_PORT_K_MIB_ALL)) { continue; } DAL_PORT_KEY_MIB_PARSE_TO_UP(key, physicalPort); /* QOS_TODO:所有端口启用功能并且link-up时存在性能问题 get交换机的时间戳,通过绝对时间来处理 */ adQosGetPortLinkStatus(physicalPort, &portStatus); if (portStatus.status == DISABLE) { continue; } /* KEY inner field&value loop */ if (DAL_ADOI_ENTRY_KEY_EMPTY(handler)) { QOS_DEBUG_COMMON("Invalid operation: deleting Fixed entries!"); } else { DAL_ADOI_ENTRY_FIELD_LOOP(handler, key) { if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_RXBYTEDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.rxbyteDiff); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_TXBYTEDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.txbyteDiff); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_BCNUMDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.bcNumDiff); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_MCNUMDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.mcNumDiff); } } } qosGetLagIdOfPort(physicalPort, &lagId); if (lagId) { UP_FROM_LAG(logicPort, lagId); } else { memcpy(&logicPort, &physicalPort, sizeof(user_port)); } ret = dataQosGetPortConfig(logicPort, &optCfg); if (ret != ERR_NO_ERROR) { continue; } if(optCfg.stormLogging) { QOS_DEBUG("upIdx:%d, rxbyteDiff:%d, txbyteDiff:%d, bcNumDiff:%d, mcNumDiff:%d", UP_INDEX(logicPort), rateDiff.rxbyteDiff, rateDiff.txbyteDiff, rateDiff.bcNumDiff, rateDiff.mcNumDiff); } /* 入口带宽阈值 Byte/s */ ingressVal = (UINT64)(optCfg.ingressRateValue) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; /*1(sec)*1000*/ /* 出口带宽阈值 Byte/s */ egressVal = (UINT64)(optCfg.egressRateValue) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; if (QOS_RATE_MODE_PPS != optCfg.rateMode) //PPS(包速率模式)、KBPS(kbit模式)、RATIO(端口带宽模式) { if (QOS_RATE_MODE_KBPS == optCfg.rateMode) { /* 广播流量阈值 */ bcVal = (UINT64)(optCfg.bcRate) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; /* 组播流量阈值 */ mcVal = (UINT64)(optCfg.mcRate) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; } else if (QOS_RATE_MODE_RATIO == optCfg.rateMode) { rate = optCfg.bcRate; _rateValueTransform(logicPort, &rate); bcVal = (UINT64)(rate)*QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; rate = optCfg.mcRate; _rateValueTransform(logicPort, &rate); mcVal = (UINT64)(rate)*QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; } } else { bcVal = (UINT64)optCfg.bcRate; /*1 sec*/ mcVal = (UINT64)optCfg.mcRate; } /* 入口带宽超限 */ if (optCfg.ingressRateValue && rateDiff.rxbyteDiff > ingressVal) { if (l_ingressLogEnable) { //QOS_TODO: snmp trap、controller log f_ingressLogEnable = TRUE; QDW("ingress exceed:%d", UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.ingressRate = optCfg.ingressRateValue; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_BANDWIDTH_INGRESS, &qosNtfy); //触发告警 PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_PORT_INGRESS_REACH, portStr); //触发日志 } } else { /*bc trap & notify*/ if (optCfg.bcRate && QOS_RATE_MODE_PPS != optCfg.rateMode && (rateDiff.rxbyteDiff > bcVal)&&(QOS_RATE_ADJUST_PAR * rateDiff.bcNumDiff >= bcVal)) { double factor = 1; int packet_length = rateDiff.rxbyteDiff/rateDiff.bcNumDiff; AD_QOS_RATE_ADJUST_BY_PACKET_LENGTH(factor, packet_length); QOS_DEBUG_COMMON("factor %4f, rateValNew.rxbyteDiff %d",factor,rateDiff.rxbyteDiff); if(rateDiff.rxbyteDiff >= factor * bcVal) { shutdownFlag = TRUE; if (l_bcLogEnable) { //QOS_TODO: snmp trap、controller log f_bcLogEnable = TRUE; QDW("bc exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.bcastRate = optCfg.bcRate; qosNtfy.bcastMode = optCfg.rateMode; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_STORM_CTRL_BCAST, &qosNtfy); stateQosPortStormOccursSet(physicalPort, QOS_RATE_STORM_MODE_BC, TRUE); if (optCfg.stormLogging) { PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_BCSTORM_CONTROL_REACH, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_DETECTED, OMADA_KEY_OSW_STORM, OMD_ALERT_REPORT, portStr, (ULONG)"Broadcast", (ULONG)macStr, (ULONG)portStr, 0, 0, 0); } } } } if (optCfg.bcRate && QOS_RATE_MODE_PPS == optCfg.rateMode && rateDiff.bcNumDiff >= bcVal) { shutdownFlag = TRUE; if (l_bcLogEnable) { //QOS_TODO: snmp trap、controller log f_bcLogEnable = TRUE; QDW("bc exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.bcastRate = optCfg.bcRate; qosNtfy.bcastMode = optCfg.rateMode; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_STORM_CTRL_BCAST, &qosNtfy); stateQosPortStormOccursSet(physicalPort, QOS_RATE_STORM_MODE_BC, TRUE); if (optCfg.stormLogging) { PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_BCSTORM_CONTROL_REACH, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_DETECTED, OMADA_KEY_OSW_STORM, OMD_ALERT_REPORT, portStr, (ULONG)"Broadcast", (ULONG)macStr, (ULONG)portStr, 0, 0, 0); } } } /*mc trap & notify*/ if (optCfg.mcRate && QOS_RATE_MODE_PPS != optCfg.rateMode && (rateDiff.rxbyteDiff > mcVal) && (QOS_RATE_ADJUST_PAR * rateDiff.mcNumDiff >= mcVal)) { double factor = 1; int packet_length = rateDiff.rxbyteDiff/rateDiff.mcNumDiff; AD_QOS_RATE_ADJUST_BY_PACKET_LENGTH(factor, packet_length); QOS_DEBUG_COMMON("factor %4f, rateValNew.rxbyteDiff %d",factor,rateDiff.rxbyteDiff); if(rateDiff.rxbyteDiff >= factor * mcVal) { shutdownFlag = TRUE; if (l_mcLogEnable) { //QOS_TODO: snmp trap、controller log f_mcLogEnable = TRUE; QDW("mc exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.mcastRate = optCfg.mcRate; qosNtfy.mcastMode = optCfg.rateMode; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_STORM_CTRL_MCAST, &qosNtfy); stateQosPortStormOccursSet(physicalPort, QOS_RATE_STORM_MODE_MC, TRUE); if (optCfg.stormLogging) { PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_MCSTORM_CONTROL_REACH, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_DETECTED, OMADA_KEY_OSW_STORM, OMD_ALERT_REPORT, portStr, (ULONG)"Multicast", (ULONG)macStr, (ULONG)portStr, 0, 0, 0); } } } } } if (optCfg.egressRateValue && rateDiff.txbyteDiff > egressVal) { if (l_egressLogEnable) { //QOS_TODO: snmp trap、syslog、controller log f_egressLogEnable = TRUE; QDW("egress exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.egressRate = optCfg.egressRateValue; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_BANDWIDTH_EGRESS, &qosNtfy); PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_PORT_EGRESS_REACH, portStr); } } /*if port belong to a LAG, the optCfg is LAG rate Config*/ if (optCfg.stormOper == QOS_STORM_EXCEED_SHUTDOWN && shutdownFlag /* && portStatus */) { QOS_DEBUG("QOS_STORM_EXCEED_SHUTDOWN"); shutdownFlag = FALSE; adQosSetPortState(physicalPort, DISABLE); stateQosPortBlockStatusSet(physicalPort, ENABLE); PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_PORT_STORM_CONTROL_SHUTDOWN, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_SHUTDOWN, OMADA_KEY_OSW_PB, OMD_ALERT_REPORT, portStr, (ULONG)macStr, (ULONG)portStr, 0, 0, 0, 0); //QOS_TODO:堆叠时,向master发送notify更新block信息 if (optCfg.recoverTime) { if (UP_IS_LAG(logicPort)) dataQosRcvrTimerIdLagGet(physicalPort,&recoverTimer); else dataQosRcvrTimerIdPhyGet(logicPort,&recoverTimer); /*add timer, LAG member set their own logic timer ID: check the timer value, if not 0, LAG has a timer*/ /* controller独有bug,定时器存在,需删除*/ if (TIMER_ID_IS_VALID(recoverTimer)) { DEL_TIMER(recoverTimer); } timer.tv_sec = optCfg.recoverTime; timer.tv_nsec = 0; user_port upArr[2] = {}; upArr[0] = physicalPort; upArr[1] = logicPort; usUp2Str(upArr[0],strUp,UP_STR_BRF_PRFX); snprintf(timerName, sizeof(timerName), "qosRecoverTime:%s",strUp); if (UP_IS_LAG(logicPort)) { recoverTimer = add_timer(timerName, &timer, _qosRateRecoverTimerNotify, upArr, sizeof(upArr), EXECUTE_SINGLE); if (TIMER_ID_IS_VALID(recoverTimer)) dataQosRcvrTimerIdLagSet(physicalPort, recoverTimer); } else { recoverTimer = add_timer(timerName, &timer, _qosRateRecoverTimerNotify, upArr, sizeof(upArr), EXECUTE_SINGLE); if (TIMER_ID_IS_VALID(recoverTimer)) dataQosRcvrTimerIdPhySet(physicalPort, recoverTimer); } } } if(f_ingressLogEnable) { l_ingressLogEnable = FALSE; f_ingressLogEnable = FALSE; } if(f_egressLogEnable) { l_egressLogEnable = FALSE; f_egressLogEnable = FALSE; } if(f_bcLogEnable) { l_bcLogEnable = FALSE; f_bcLogEnable = FALSE; } if(f_mcLogEnable) { l_mcLogEnable = FALSE; f_mcLogEnable = FALSE; } }//end loop handler } done: if(adoi) { dalAdoiDestroy(adoi); } return ret; } static void _managerTimerHandleTask() { int status = 0; int pri = 0; QOS_MIB_UPDATE_MSG msg = {}; while (1) { //一直阻塞,usec置为PAL_MQ_WAIT_FOREVER status = pal_msgQ_receive(qosSrvcMsgQ, (char *)(&msg), sizeof(QOS_MIB_UPDATE_MSG), PAL_MQ_WAIT_FOREVER, (UINT *)&pri); if (PAL_MQ_ERROR == status) { continue; } /* 接收到消息则执行 */ _qosPortMibUpdateCb(); } } static void _managerTimerHandle(void *param) { QOS_MIB_UPDATE_MSG msg = {}; msg.updateFlag = true; pal_msgQ_send(qosSrvcMsgQ, (char *)&msg, sizeof(QOS_MIB_UPDATE_MSG), 0, PAL_MQ_WAIT_NOWAIT); } static int _qosMibUpdatePthreadInit() { qosTimerTaskId = pal_thread_create("qosTimerTaskId", 10 * 1024, 0, _managerTimerHandleTask, NULL); if (PAL_THREAD_ERROR == qosTimerTaskId) { DBG("create task fail"); } D("_qosMibUpdatePthreadInit ok"); return ERR_NO_ERROR; } STATUS _qosMibUpdateStartTimerInit() { TIMER_ID_INIT(qosMibUpdateTimer); struct timespec updateTimer = {}; updateTimer.tv_sec = 1; updateTimer.tv_nsec = 0; qosMibUpdateTimer = add_timer("qos_mib_update_timer", &updateTimer, _managerTimerHandle, NULL, 0, EXECUTE_FOREVER); APPL_ENSURE_RET_VAL(TIMER_ID_IS_VALID(qosMibUpdateTimer), ERR_INIT); D("_qosMibUpdateStartTimerInit ok"); return ERR_NO_ERROR; } static int _qosMibUpdateQueueInit() { qosSrvcMsgQ = pal_msgQ_create("/qosMibUpdateTimerQueue", 10, sizeof(QOS_MIB_UPDATE_MSG), PAL_MQ_READ_WRITE); if (PAL_MQ_ERROR == qosSrvcMsgQ) { pal_msgQ_destroy("/qosMibUpdateTimerQueue"); } D("_qosMibUpdateQueueInit ok"); return ERR_NO_ERROR; } /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ STATUS srvcQosInit() { /* 初始化任务线程 */ APPL_IF_ERR_RET(_qosMibUpdatePthreadInit()); /* 初始化消息队列 */ APPL_IF_ERR_RET(_qosMibUpdateQueueInit()); /* 初始化定时器 */ _qosMibUpdateStartTimerInit(); // PFM_IF_FAIL_RET_VAL(dalStatChgSub(DMP_DEV_NAME_SWITCHMAC, DAL_SWITCHMAC_STAT_MIBUPDATE, _qosPortMibUpdateCb), ERR_QOS_INIT); return ERR_NO_ERROR; } 代码2: static void _rateValueTransform(user_port uPort, UINT32 *rateValue) { QOS_PORT_STATUS portStatus = {}; user_port_list lagMemberList = {}; user_port up = {}; int lagId = 0; int index = 0; int portRate = 0; int tmpRate = 0; int speedValue[UP_ABILITY_SPEED_END] = PORT_SPEED_VALUE; APPL_ENSURE_RET_VOID(UP_IS_VALID(uPort)); APPL_ENSURE_RET_VOID(NULL != rateValue); uplist_init(&lagMemberList); APPL_IF_ERR_DONE_VOID(adQosGetPortLinkStatus(uPort, &portStatus)); if (DISABLE == portStatus.status) { if (UP_IS_LAG(uPort)) { UP_TO_LAG(uPort, lagId); dataQosLagMemberListGet(lagId, &lagMemberList); UP_ITER_LIST_SWP(&lagMemberList, index, up) { tmpRate = QOS_PORT_MAX_RATE_KBPS(up) / QOS_RATE_KBPS_THOUSAND; if (0 == portRate || tmpRate < portRate) { portRate = tmpRate; } } } else { portRate = QOS_PORT_MAX_RATE_KBPS(uPort) / QOS_RATE_KBPS_THOUSAND; } } else { portRate = speedValue[portStatus.speedMode]; } *rateValue = (*rateValue) * portRate * (QOS_RATE_KBPS_THOUSAND / QOS_RATE_PERCENT_HUNDRED); //本应为 (rateValue/100) * (portRate*1000),为防止UINT32溢出,需要交换顺序 rateValueAdjust(rateValue); done: uplist_free(&lagMemberList); return; } static void _qosMsgRecover(QOS_AD_MSG_T qosMsg) { user_port physicalPort = {}; user_port logicPort = {}; QOS_PORT_STATUS portStatus = {}; UINT8 linkState = 0; //NTFY_QOS qosNtfy = {}; TIMER_ID recoverTimer = {}; TIMER_ID_INIT(recoverTimer); memcpy(&physicalPort, &qosMsg.qosRcvr.physicalPort, sizeof(user_port)); //物理端口 memcpy(&logicPort, &qosMsg.qosRcvr.logicPort, sizeof(user_port)); //lag端口 if (UP_CMP(physicalPort, logicPort)) /* 获取端口配置的状态 */ dataQosRcvrTimerIdLagSet(physicalPort, recoverTimer); else /*dealing with phy port*/ dataQosRcvrTimerIdPhySet(physicalPort, recoverTimer); /*check port config, if port set to disable ,do not enable this phy port*/ if (UP_CMP(physicalPort, logicPort)) { qosStatePortStatusGet(logicPort, &portStatus); } else { qosStatePortStatusGet(physicalPort, &portStatus); } stateQosPortBlockStatusSet(physicalPort, DISABLE); /* QOS_TODO:堆叠时,向master发送notify更新recovery信息 */ #if 0 if (!DEV_ROLE_LOCAL_IS_MASTER()){ memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.block = DISABLE; unit_list ul={}; UNIT_LIST_ADD(ul, UNIT_MASTER); notify_call_remote(ul, NOTIFY_QOS_STORM_CTRL_BLOCK, &qosNtfy, sizeof(qosNtfy)); } #endif QOS_DEBUG("linkStatus:%d",portStatus.status); if (portStatus.status == ENABLE) { adQosGetPortState(physicalPort, &linkState); if(linkState != ENABLE) { adQosSetPortState(physicalPort, ENABLE); } } else { adQosSetPortState(physicalPort, DISABLE); } } static void _qosRateRecoverTimerNotify(void *data) { QOS_AD_MSG_T qosMsg = {}; user_port *upArr = data; APPL_ENSURE_RET_VOID(data != NULL); qosMsg.qosRcvr.physicalPort = upArr[0]; qosMsg.qosRcvr.logicPort = upArr[1]; qosMsg.type = QOS_MSG_RCVR; _qosMsgRecover(qosMsg); } static STATUS _qosPortMibUpdateCb(dal_ado_t *adoi, dal_attr *attr) { int ret = ERR_NO_ERROR; char *key = NULL; void *handler = NULL; user_port logicPort = {}; user_port physicalPort = {}; QOS_PORT_RATE_DIFF_STRUCT rateDiff = {}; UINT64 ingressVal = 0; UINT64 egressVal = 0; UINT64 bcVal = 0; UINT64 mcVal = 0; UINT32 rate = 0; TIMER_ID recoverTimer; TIMER_ID_INIT(recoverTimer); struct timespec timer = {}; char strUp[STR_STRUP_SIZE] = {}; char timerName[STR_TIMER_NAME_SIZE] = {}; APPQOS_ADCFG_OPT optCfg = {}; QOS_PORT_STATUS portStatus = {}; UINT32 lagId = 0; UINT8 shutdownFlag = 0; NTFY_QOS qosNtfy = {}; MAC_ADDRESS sysMac = {}; char macStr[STR_MAC_SIZE] = {}; char portStr[STR_STRUP_SIZE] = {}; memset(macStr, 0, 20); libStkSysDevMacGet(UNIT_CURRENT, sysMac); ether2str(macStr, sysMac, CSL_UPCASE, STR_TRANS_CLI); qosTrapCounter++; if (qosTrapCounter >= QOS_STORM_EXCEED_LOG_CYCLE) { qosTrapCounter = 0; l_ingressLogEnable = TRUE; l_egressLogEnable = TRUE; l_bcLogEnable = TRUE; l_mcLogEnable = TRUE; } /* 置位flag */ BOOL f_ingressLogEnable = FALSE; BOOL f_egressLogEnable = FALSE; BOOL f_bcLogEnable = FALSE; BOOL f_mcLogEnable = FALSE; if (NULL != (handler = DAL_ADOI_ENTRY(adoi, DAL_PORT_K_MIB))) { DAL_ADOI_ENTRY_LOOP(handler) { if(NULL == (key = DAL_ADOI_ENTRY_KEY(handler)) || !DAL_ADOI_ENTRY_KEY_MATCH(handler, DAL_PORT_K_MIB_ALL)) { continue; } DAL_PORT_KEY_MIB_PARSE_TO_UP(key, physicalPort); /* QOS_TODO:所有端口启用功能并且link-up时存在性能问题 get交换机的时间戳,通过绝对时间来处理 */ adQosGetPortLinkStatus(physicalPort, &portStatus); if (portStatus.status == DISABLE) { continue; } /* KEY inner field&value loop */ if (DAL_ADOI_ENTRY_KEY_EMPTY(handler)) { QOS_DEBUG_COMMON("Invalid operation: deleting Fixed entries!"); } else { DAL_ADOI_ENTRY_FIELD_LOOP(handler, key) { if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_RXBYTEDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.rxbyteDiff); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_TXBYTEDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.txbyteDiff); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_BCNUMDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.bcNumDiff); } else if (DAL_ADOI_ENTRY_FIELD_MATCH(handler, DAL_PORT_K_MIB_F_MCNUMDIFF)) { dalAdoiGetEntryUI64(adoi, DAL_PORT_K_MIB, &rateDiff.mcNumDiff); } } } qosGetLagIdOfPort(physicalPort, &lagId); if (lagId) { UP_FROM_LAG(logicPort, lagId); } else { memcpy(&logicPort, &physicalPort, sizeof(user_port)); } ret = dataQosGetPortConfig(logicPort, &optCfg); if (ret != ERR_NO_ERROR) { continue; } if(optCfg.stormLogging) {QOS_DEBUG("upIdx:%d, rxbyteDiff:%d, txbyteDiff:%d, bcNumDiff:%d, mcNumDiff:%d", UP_INDEX(logicPort), rateDiff.rxbyteDiff, rateDiff.txbyteDiff, rateDiff.bcNumDiff, rateDiff.mcNumDiff);} ingressVal = (UINT64)(optCfg.ingressRateValue) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; /*1(sec)*1000*/ egressVal = (UINT64)(optCfg.egressRateValue) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; if (QOS_RATE_MODE_PPS != optCfg.rateMode) { if (QOS_RATE_MODE_KBPS == optCfg.rateMode) { bcVal = (UINT64)(optCfg.bcRate) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; } else if (QOS_RATE_MODE_RATIO == optCfg.rateMode) { rate = optCfg.bcRate; _rateValueTransform(logicPort, &rate); bcVal = (UINT64)(rate)*QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; } if (QOS_RATE_MODE_KBPS == optCfg.rateMode) { mcVal = (UINT64)(optCfg.mcRate) * QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; } else if (QOS_RATE_MODE_RATIO == optCfg.rateMode) { rate = optCfg.mcRate; _rateValueTransform(logicPort, &rate); mcVal = (UINT64)(rate)*QOS_RATE_KBPS_THOUSAND / QOS_IFG_DELAY; } } else { bcVal = (UINT64)optCfg.bcRate; /*1 sec*/ mcVal = (UINT64)optCfg.mcRate; } if (optCfg.ingressRateValue && rateDiff.rxbyteDiff > ingressVal) { if (l_ingressLogEnable) { //QOS_TODO: snmp trap、controller log f_ingressLogEnable = TRUE; QDW("ingress exceed:%d", UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.ingressRate = optCfg.ingressRateValue; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_BANDWIDTH_INGRESS, &qosNtfy); PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_PORT_INGRESS_REACH, portStr); } } else { /*bc trap & notify*/ if (optCfg.bcRate && QOS_RATE_MODE_PPS != optCfg.rateMode && (rateDiff.rxbyteDiff > bcVal)&&(QOS_RATE_ADJUST_PAR * rateDiff.bcNumDiff >= bcVal)) { double factor = 1; int packet_length = rateDiff.rxbyteDiff/rateDiff.bcNumDiff; AD_QOS_RATE_ADJUST_BY_PACKET_LENGTH(factor, packet_length); QOS_DEBUG_COMMON("factor %4f, rateValNew.rxbyteDiff %d",factor,rateDiff.rxbyteDiff); if(rateDiff.rxbyteDiff >= factor * bcVal) { shutdownFlag = TRUE; if (l_bcLogEnable) { //QOS_TODO: snmp trap、controller log f_bcLogEnable = TRUE; QDW("bc exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.bcastRate = optCfg.bcRate; qosNtfy.bcastMode = optCfg.rateMode; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_STORM_CTRL_BCAST, &qosNtfy); stateQosPortStormOccursSet(physicalPort, QOS_RATE_STORM_MODE_BC, TRUE); if (optCfg.stormLogging) { PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_BCSTORM_CONTROL_REACH, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_DETECTED, OMADA_KEY_OSW_STORM, OMD_ALERT_REPORT, portStr, (ULONG)"Broadcast", (ULONG)macStr, (ULONG)portStr, 0, 0, 0); } } } } if (optCfg.bcRate && QOS_RATE_MODE_PPS == optCfg.rateMode && rateDiff.bcNumDiff >= bcVal) { shutdownFlag = TRUE; if (l_bcLogEnable) { //QOS_TODO: snmp trap、controller log f_bcLogEnable = TRUE; QDW("bc exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.bcastRate = optCfg.bcRate; qosNtfy.bcastMode = optCfg.rateMode; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_STORM_CTRL_BCAST, &qosNtfy); stateQosPortStormOccursSet(physicalPort, QOS_RATE_STORM_MODE_BC, TRUE); if (optCfg.stormLogging) { PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_BCSTORM_CONTROL_REACH, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_DETECTED, OMADA_KEY_OSW_STORM, OMD_ALERT_REPORT, portStr, (ULONG)"Broadcast", (ULONG)macStr, (ULONG)portStr, 0, 0, 0); } } } /*mc trap & notify*/ if (optCfg.mcRate && QOS_RATE_MODE_PPS != optCfg.rateMode && (rateDiff.rxbyteDiff > mcVal) && (QOS_RATE_ADJUST_PAR * rateDiff.mcNumDiff >= mcVal)) { double factor = 1; int packet_length = rateDiff.rxbyteDiff/rateDiff.mcNumDiff; AD_QOS_RATE_ADJUST_BY_PACKET_LENGTH(factor, packet_length); QOS_DEBUG_COMMON("factor %4f, rateValNew.rxbyteDiff %d",factor,rateDiff.rxbyteDiff); if(rateDiff.rxbyteDiff >= factor * mcVal) { shutdownFlag = TRUE; if (l_mcLogEnable) { //QOS_TODO: snmp trap、controller log f_mcLogEnable = TRUE; QDW("mc exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.mcastRate = optCfg.mcRate; qosNtfy.mcastMode = optCfg.rateMode; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_STORM_CTRL_MCAST, &qosNtfy); stateQosPortStormOccursSet(physicalPort, QOS_RATE_STORM_MODE_MC, TRUE); if (optCfg.stormLogging) { PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_MCSTORM_CONTROL_REACH, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_DETECTED, OMADA_KEY_OSW_STORM, OMD_ALERT_REPORT, portStr, (ULONG)"Multicast", (ULONG)macStr, (ULONG)portStr, 0, 0, 0); } } } } } if (optCfg.egressRateValue && rateDiff.txbyteDiff > egressVal) { if (l_egressLogEnable) { //QOS_TODO: snmp trap、syslog、controller log f_egressLogEnable = TRUE; QDW("egress exceed:%d",UP_PORT(physicalPort)); memset(&qosNtfy, 0, sizeof(qosNtfy)); qosNtfy.physicalPort = physicalPort; qosNtfy.egressRate = optCfg.egressRateValue; stateQosSnmpTrapSet(QOS_SNMP_TRAP_TYPE_BANDWIDTH_EGRESS, &qosNtfy); PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_PORT_EGRESS_REACH, portStr); } } /*if port belong to a LAG, the optCfg is LAG rate Config*/ if (optCfg.stormOper == QOS_STORM_EXCEED_SHUTDOWN && shutdownFlag /* && portStatus */) { QOS_DEBUG("QOS_STORM_EXCEED_SHUTDOWN"); shutdownFlag = FALSE; adQosSetPortState(physicalPort, DISABLE); stateQosPortBlockStatusSet(physicalPort, ENABLE); PORT_UP2STR(physicalPort, portStr); QOS_ADD_LOG_ONE_PARA(LOG_QOS_PORT_STORM_CONTROL_SHUTDOWN, portStr); syslogAdd_omada(QOS_LOG_MODULE_NAME, LOG_OMADA_STORM_SHUTDOWN, OMADA_KEY_OSW_PB, OMD_ALERT_REPORT, portStr, (ULONG)macStr, (ULONG)portStr, 0, 0, 0, 0); //QOS_TODO:堆叠时,向master发送notify更新block信息 if (optCfg.recoverTime) { if (UP_IS_LAG(logicPort)) dataQosRcvrTimerIdLagGet(physicalPort,&recoverTimer); else dataQosRcvrTimerIdPhyGet(logicPort,&recoverTimer); /*add timer, LAG member set their own logic timer ID: check the timer value, if not 0, LAG has a timer*/ /* controller独有bug,定时器存在,需删除*/ if (TIMER_ID_IS_VALID(recoverTimer)) { DEL_TIMER(recoverTimer); } timer.tv_sec = optCfg.recoverTime; timer.tv_nsec = 0; user_port upArr[2] = {}; upArr[0] = physicalPort; upArr[1] = logicPort; usUp2Str(upArr[0],strUp,UP_STR_BRF_PRFX); snprintf(timerName, sizeof(timerName), "qosRecoverTime:%s",strUp); if (UP_IS_LAG(logicPort)) { recoverTimer = add_timer(timerName, &timer, _qosRateRecoverTimerNotify, upArr, sizeof(upArr), EXECUTE_SINGLE); if (TIMER_ID_IS_VALID(recoverTimer)) dataQosRcvrTimerIdLagSet(physicalPort, recoverTimer); } else { recoverTimer = add_timer(timerName, &timer, _qosRateRecoverTimerNotify, upArr, sizeof(upArr), EXECUTE_SINGLE); if (TIMER_ID_IS_VALID(recoverTimer)) dataQosRcvrTimerIdPhySet(physicalPort, recoverTimer); } } } if(f_ingressLogEnable){ l_ingressLogEnable = FALSE; f_ingressLogEnable = FALSE; } if(f_egressLogEnable){ l_egressLogEnable = FALSE; f_egressLogEnable = FALSE; } if(f_bcLogEnable){ l_bcLogEnable = FALSE; f_bcLogEnable = FALSE; } if(f_mcLogEnable){ l_mcLogEnable = FALSE; f_mcLogEnable = FALSE; } } } return ret; } 其中,代码1在第二次广播风暴后关闭端口后无法开启,而代码2在第二次广播风暴后关闭端口在恢复时间后开启,试分析原因,并给出详细解决方案
11-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值