有以下两份代码,其中,代码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在第二次广播风暴后关闭端口在恢复时间后开启,试分析原因,并给出详细解决方案
最新发布