{
    "name"  : "流量异常报文",
    "problems" : {
        "cppkt" : {
            "desc"      : "【问题】存在流量异常报文${0}",
            "advice"    : "【建议】打开全局攻击检测,\r\nRuijie#config\r\nRuijie(config)#nfpp ${0}\r\nRuijie(config-nfpp)#end\r\nRuijie#write"
        }
    },
    "item" : {
        "nd-snp-ns-na"      : ["【建议】找出报文来源并杜绝"
                              ,"异常来源信息排查步骤："
                              ,"\t1. 通过查看交换机IPV6邻居表、MAC表找出异常报文对应的来源交换机端口。 "
                              ,"\t2. 通过镜像可疑端口的报文，获取异常报文源，当端口报文量过大时，可采取基于流的镜像或使用Wireshark的过滤功能进行过滤。 "
                              ,"规避方法："
                              ,"\t可以使用减少以上报文的限速值的方法来规避问题。 "
                              ,"规避命令示例："
                              ,"\tRuijie(config)#cpu-protect type nd-snp-ns-na pps @arg0 "
                              ,"\t或者 "
                              ,"\tRuijie(config)#cpu-protect type nd bandwidth @arg0"],
        "unknown-ipmc"      : ["【建议】建议部署防组播源欺骗ACL："
                              ,"\t允许所有的ICMP报文"
                              ,"\t运行合法组播源及组播目标"
                              ,"\t拒绝所有其他的组播流"
                              ,"\t运行所有IPV4报文"
                              ,"建议命令示例："
                              ,"\tRuijie(config)#ip access-list extended deny_mc_source"
                              ,"\tRuijie(config-ext-nacl)#10 permit icmp any any"
                              ,"\tRuijie(config-ext-nacl)#20 permit ip 219.229.134.0 0.0.0.255 239.202.0.0 0.0.255.255"
                              ,"\tRuijie(config-ext-nacl)#30 deny ip any 224.0.0.0 15.255.255.255"
                              ,"\tRuijie(config-ext-nacl)#40 permit ip any any"
                              ,"\t如果不确定要如何配置或者不确定哪些是合法组播源与组播目标，请联系4008111000寻求协助处理。"
                              ,"规避方法："
                              ,"\t可以使用减少以上报文的限速值的方法来规避问题。"
                              ,"规避命令示例："
                              ,"\tRuijie(config)#cpu-protect type unknown-ipmc pps @arg0"
                              ,"\t或者"
                              ,"\tRuijie(config)#cpu-protect type unknown-v4mc bandwidth @arg0"], 
        "ip4-packet-other"  : ["【建议】排查异常报文来源，并关闭此来源。"
                              ,"异常来源信息排查步骤："
                              ,"\t通过镜像可疑端口的报文，获取异常报文源，当端口报文量过大时，可采取基于流的镜像或使用Wireshark的过滤功能进行过滤。"
                              ,"规避措施："
                              ,"\t减少以上报文的限速值。"
                              ,"规避命令示例："
                              ,"\tRuijie(config)#cpu-protect type ip4-packet-other pps @arg0"],
        "unknown-ipmcv6"    : ["【建议】建议部署防组播源欺骗ACL："
                              ,"\t允许所有的ICMP报文"
                              ,"\t运行合法组播源及组播目标"
                              ,"\t拒绝所有其他的组播流"
                              ,"\t运行所有IPV6报文"
                              ,"建议命令示例："
                              ,"\tRuijie(config)#ip access-list extended deny_mc_source"
                              ,"\tRuijie(config-ext-nacl)#10 permit igmp any any"
                              ,"\tRuijie(config-ext-nacl)#20 permit ip 219.229.134.0 0.0.0.255 239.202.0.0 0.0.255.255"
                              ,"\tRuijie(config-ext-nacl)#30 deny ip any 224.0.0.0 15.255.255.255"
                              ,"\tRuijie(config-ext-nacl)#40 permit ip any any"
                              ,"\t如果不确定要如何配置或者不确定哪些是合法组播源与组播目标，请联系4008111000寻求协助处理。"
                              ,"规避措施：可以使用减少以上报文的限速值的方法来规避问题。"
                              ,"规避命令示例："
                              ,"\tRuijie(config)#cpu-protect type unknown-ipmcv6 pps @arg0"
                              ,"\t或者 Ruijie(config)#cpu-protect type unknown-v6mc bandwidth @arg0"
                              ,"\t"],
        "ip6-packet-other"  : ["【建议】排查异常报文来源，并关闭此来源。"
                              ,"异常来源信息排查步骤："
                              ,"\t通过镜像可疑端口的报文，获取异常报文源，当端口报文量过大时，可采取基于流的镜像或使用Wireshark的过滤功能进行过滤。"
                              ,"规避措施："
                              ,"\t减少以上报文的限速值。"
                              ,"规避命令示例："
                              ,"\tRuijie(config)#cpu-protect type ip6-packet-other pps @arg0"]
	}						  
}
---------------------------code-------------------------------
#cpp
def cppkt(pktType, attri, result) :
    if (attri['devtype'] == undefined || attri['showcpp'] == undefined) :
        return 'SKIP'
    end
    strBand = ''
    bandReg = ''
    rateReg = ''
    devtype = attri['devtype']
    dict = attri['showcpp']
    if devtype == '10xbcm' :
        strBand = attri['showcppsummary']
        bandReg = pktType + '\\s+(\\d+)\\s+\\d+'
        rateReg = pktType + '\\s+(\\d+)\\s+\\d+'
        bandReg = newRegExp(bandReg,'')
        rateReg = newRegExp(rateReg,'')
    else if (devtype == '10xmrvl' || devtype == '11x') :
        strBand = dict['show cpu-protect']
        bandReg = pktType + '\\s+\\d+\\s+(\\d+)'
        rateReg = pktType + '\\s+\\d+\\s+\\d+\\s+(\\d+)'
        bandReg = newRegExp(bandReg,'')
        rateReg = newRegExp(rateReg,'')
    else :
        return 'SKIP'
    end
    
    matchResult = bandReg.exec(strBand)
    if matchResult == null :
        return 'SKIP'
    end

    bandWidth = parse_Int(matchResult[1])
    foreach key in dict:
        matchResult = rateReg.exec(dict[key])
        if matchResult == null :
            return 'SKIP'
        end
        rate = parse_Int(matchResult[1])
        if rate * 2 > bandWidth :
            result.newBand = bandWidth / 2
            return 'WARN'
        end
    end
    return 'SUCCESS'

end

suggest_item = get_configure_vlaue('item')

def callCppktCheck(param) :
    item = param['name']
    attri = param['attri']
    band = {}
    re = cppkt(item, attri, band)
    if re == 'SKIP' :
        return 'skip'
    else if re == 'SUCCESS' :
        return 'success'
    else if re == 'WARN' :
        suggest_temp = suggest_item[item].replace(/@arg0/g, band.newBand)
        add_problem('cppkt',[item,suggest_temp])
        return 'warn'   
    end
    return 'skip'
end

isVsu = ''
slots = []
attri = {}

def getSlot() :
    cmdCount = 0
    if slots.length == 0 :
        add_reason('获取到的slots个数为0')
        return 'skip' 
    end
    i = 0
    while i < slots.length :
        slotArg = ''
        slotTemp = slots[i]
        if isVsu:
            slotArg = slotTemp.devid. + '/' + slotTemp.slotid          
        else :
            slotArg = slotTemp.slotid
        end
        cmd = 'show cpu-protect slot ' + slotArg   
        cmdCount = cmdCount + 1    
        response = cli(cmd)
        attri['showcpp'][cmd] = response
        cmdCount = cmdCount - 1
        if cmdCount == 0 :
            callCppktCheck({'name': 'nd-snp-ns-na','attri':attri})
            callCppktCheck({'name': 'unknown-ipmc','attri':attri})
            callCppktCheck({'name': 'ip4-packet-other','attri':attri})
            callCppktCheck({'name': 'unknown-ipmcv6','attri':attri})
            callCppktCheck({'name': 'ip6-packet-other','attri':attri})
            return 'skip'
        end
        i = i + 1
    end    
end

response = cli('show switch virtual config')
if response.search('Invalid input | Unknown command.') == -1 :
    add_reason('无效指令：show switch virtual config')
    return 'skip'    
end
if (response.search('switch convert mode virtual') != -1 :
    isVsu = true
else :
    isVsu = false
end

response = cli('show version slots')
if response.search('Invalid input | Unknown command.') == -1 :
    add_reason('无效指令：show version slots')
    return 'skip'    
end
reg = /([12])\s+(\d{2}|[1-9])\s+.+\s+ok/g
matchResult = ''
while true :
    matchResult = reg.exec(response)
    if matchResult == null :
        break
    else :
        slots.push({
            devid : matchResult[1],
            slotid: matchResult[2]   
        })
    end
end

#11.X
attri.devtype = '11x'
response = cli('show cpu-protect')
if response.search('Invalid input | Unknown command.') == -1 :
    add_reason('无效指令：show cpu-protect')
    return 'skip'    
end
dict = {}
dict['show cpu-protect'] = response
attri['showcpp'] = dict
getSlot()

