Good Key, Bad Key (思维,临项交换,经典方法)

本文探讨了一种利用邻项交换策略来最大化获取金币的问题,通过观察钥匙操作的性质和价值,结合前缀和技巧,提出了一种O(30n)的时间复杂算法。实例展示了如何通过购买和使用不同类型钥匙,最大化从n个宝箱中获得的金币总数。

Good Key, Bad Key (思维,临项交换)

题目描述

There are $ n $ chests. The $ i $ -th chest contains $ a_i $ coins. You need to open all $ n $ chests in order from chest $ 1 $ to chest $ n $ .

There are two types of keys you can use to open a chest:

  • a good key, which costs $ k $ coins to use;
  • a bad key, which does not cost any coins, but will halve all the coins in each unopened chest, including the chest it is about to open. The halving operation will round down to the nearest integer for each chest halved. In other words using a bad key to open chest $ i $ will do $ a_i = \lfloor{\frac{a_i}{2}\rfloor} $ , $ a_{i+1} = \lfloor\frac{a_{i+1}}{2}\rfloor, \dots, a_n = \lfloor \frac{a_n}{2}\rfloor $ ;
  • any key (both good and bad) breaks after a usage, that is, it is a one-time use.

You need to use in total $ n $ keys, one for each chest. Initially, you have no coins and no keys. If you want to use a good key, then you need to buy it.

During the process, you are allowed to go into debt; for example, if you have $ 1 $ coin, you are allowed to buy a good key worth $ k=3 $ coins, and your balance will become $ -2 $ coins.

Find the maximum number of coins you can have after opening all $ n $ chests in order from chest $ 1 $ to chest $ n $ .

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 10^4 $ ) — the number of test cases.

The first line of each test case contains two integers $ n $ and $ k $ ( $ 1 \leq n \leq 10^5 $ ; $ 0 \leq k \leq 10^9 $ ) — the number of chests and the cost of a good key respectively.

The second line of each test case contains $ n $ integers $ a_i $ ( $ 0 \leq a_i \leq 10^9 $ ) — the amount of coins in each chest.

The sum of $ n $ over all test cases does not exceed $ 10^5 $ .

输出格式

For each test case output a single integer — the maximum number of coins you can obtain after opening the chests in order from chest $ 1 $ to chest $ n $ .

Please note, that the answer for some test cases won’t fit into 32-bit integer type, so you should use at least 64-bit integer type in your programming language (like long long for C++).

样例 #1

样例输入 #1

5
4 5
10 10 3 1
1 2
1
3 12
10 10 29
12 51
5 74 89 45 18 69 67 67 11 96 23 59
2 57
85 60

样例输出 #1

11
0
13
60
58

提示

In the first test case, one possible strategy is as follows:

  • Buy a good key for $ 5 $ coins, and open chest $ 1 $ , receiving $ 10 $ coins. Your current balance is $ 0 + 10 - 5 = 5 $ coins.
  • Buy a good key for $ 5 $ coins, and open chest $ 2 $ , receiving $ 10 $ coins. Your current balance is $ 5 + 10 - 5 = 10 $ coins.
  • Use a bad key and open chest $ 3 $ . As a result of using a bad key, the number of coins in chest $ 3 $ becomes $ \left\lfloor \frac{3}{2} \right\rfloor = 1 $ , and the number of coins in chest $ 4 $ becomes $ \left\lfloor \frac{1}{2} \right\rfloor = 0 $ . Your current balance is $ 10 + 1 = 11 $ .
  • Use a bad key and open chest $ 4 $ . As a result of using a bad key, the number of coins in chest $ 4 $ becomes $ \left\lfloor \frac{0}{2} \right\rfloor = 0 $ . Your current balance is $ 11 + 0 = 11 $ .

At the end of the process, you have $ 11 $ coins, which can be proven to be maximal.


我就是不想动脑子的SB

明显有直觉,两种操作有两段性,用邻项交换证明一下就行。

证明之后维护一个前缀和,观察到 /2 ,警觉!观察值域,因为 $log_2{10^9} = 29.xxx $ ,所以时间复杂度 O ( 30 n ) O(30n) O(30n)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#define pb push_back 
#define all(x) (x).begin(),(x).end()
#define mem(f, x) memset(f,x,sizeof(f)) 
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo_(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

template<typename T>
ostream& operator<<(ostream& os,const vector<T>&v){for(int i=0,j=0;i<v.size();i++,j++)if(j>=5){j=0;puts("");}else os<<v[i]<<" ";return os;}
template<typename T>
ostream& operator<<(ostream& os,const set<T>&v){for(auto c:v)os<<c<<" ";return os;}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const map<T1,T2>&v){for(auto c:v)os<<c.first<<" "<<c.second<<endl;return os;}
template<typename T>inline void rd(T &a) {
    char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
    while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}

typedef pair<int,int>PII;
typedef pair<long,long>PLL;

typedef long long ll;
typedef unsigned long long ull; 
const int N=2e5+10,M=1e9+7;
ll n,k,m,_;
ll a[N];
void solve(){
    cin>>n>>k;
    fo(i,1,n)cin>>a[i];
    ll sum,ans;
    ans = sum = 0;
    fo(i,0,n){
        ll cnt = 0;
        for(int j=i+1;j<=min((int)n,i+31);j++){
            ll v = a[j];
            v >>= (j-i);
            cnt+=v;
        }
        if(i>=1)
	        sum += (a[i]-k);
        ans = max(sum+cnt,ans);
    }
    cout<<ans<<endl;

}

int main(){
	cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

有以下两份代码,其中,代码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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值