目錄

簡介

必要條件

需求

採用元件

背景資訊

用於獲取資訊的工具

所有單行命令的清單

僅獲取交換矩陣內枝葉的節點ID:

驗證是否有介面重設：

檢查最高評級介面：

查詢所有STP拓撲更改：

確保是否存在多播RPF丟棄：

驗證是否有太多資料包獲得Glean:

QoS丟棄統計資訊：

介面捨棄：

FCS錯誤（非堆積CRC錯誤）

FCS +儲存的CRC錯誤

輸出緩衝區丟棄

輸出錯誤

清除所有介面計數器

BGP會話問題：

OSPF會話問題：

被傳送到CPU的主要資料包

從部署所有特定合約關係的apic檢查整個交換矩陣

檢查封裝已在何處部署並獲得相應的epg

交換矩陣中所有節點的記憶體利用率：

驗證istack上的丟棄（異常資料包被點選）

合約驗證

簡介

本文描述了我們在交換矩陣上檢測整體問題的不同方法。

必要條件

需求

- 思科建議瞭解ACI

- 巴什語基礎知識

採用元件

本文件所述內容不限於特定軟體和硬體版本。

使用的裝置：

- 運行版本4.2(3)的Cisco ACI

本文中的資訊是根據特定實驗室環境內的裝置所建立。文中使用到的所有裝置皆從已清除（預設）的組態來啟動。如果您的網路運作中，請確保您瞭解任何指令可能造成的影響。

背景資訊

用於獲取資訊的工具

- 用於替代：sed "s/<oldword >/<new wordk>/g" g定義它執行多次。

- 用於自始至終抓取線條：sed "/<beginning/,/end/p>"。將 — n(noprint)選項與/p列印標誌相結合，以複製grep的功能。

- Sed可以通過使用「；」使用多次，例如：將：sed s/<oldword >/<new word>/g;s/<oldword2 >/<new wordk2>/g"

- awk -F '<field_separator>' '{print $2}'在本特定示例中，您按定義的FIELD_SEPARATOR拆分行，並列印第2個分隔的區塊。兩個語法都做了完全相同的事情。

- awk '{ print $1, $2 }'列印每個輸入記錄的前兩個欄位，這兩個欄位之間有一個空格。

- sort | uniq 報告重複的行。按發生次數使用-c字首行。

- sort -nrk <column>對行進行最大排序。-n表示數字排序， -k表示鍵，以便我們可以修改列，如果要定義最低值，可以刪除 — r

- python -m json.tool以漂亮的格式顯示JSON。

所有單行命令的清單

僅獲取交換矩陣內枝葉的節點ID:

1. 在清單中：

APIC#acidiag fnvread | grep leaf | awk '{print $1}'

2. 在用逗號作為分隔符的行中：

APIC#acidiag fnvread | grep leaf | awk '{print $1}' | sed -z 's/\n/,/g;s/,$/\n/'

驗證是否有介面重設：

資訊在重置數最高的介面上排序。

APIC#moquery -c ethpm.PhysIf | egrep "dn|lastLinkStChg|resetCtr" | tr -d "\n" | sed "s/dn/\ndn/g;s/lastLinkStChg/\tlastLinkStChg/g;s/resetCtr/\tresetCtr/g" | sort -nrk 9 | more

較慢選項

APIC#for leaf in `acidiag fnvread | grep leaf | awk '{print $1}'`; do echo; echo " -> leaf ID: $leaf  "; fabric $leaf  show interface  | sed -n '/net[0-9]\/[0-9]\+ is up/,/Tx pause/p'  | egrep "is up|Last link flapped|interface resets" | grep -v Dedicated | tr -d "\n" | sed "s/resets/rests\n/g" | sort -nrk 9   ; done;

檢查最高分級介面：

若要尋找接收最多流量的位置：

查詢交換矩陣，查詢輸出吞吐量超過特定值(b)的所有介面。 m的值定義b是gb、mb還是kb。

要按gb篩選，請將m設定為125000000。要按mb篩選，請將m設定為125000。要按kb篩選，請將m設定為125。

APIC#bash

APIC#b=1; m=125000;b=$((b*m)); printf "%-65s %25s\n", "Node/Interface" "Bits/Second"; icurl 'http://localhost:7777/api/class/eqptEgrTotal5min.json?query-target-filter=gt(eqptEgrTotal5min.bytesRateLast,"'$b'")&order-by=eqptEgrTotal5min.bytesRateLast|desc' 2>/dev/null | python -m json.tool | egrep "dn|bytesRateLast" | sed -e 's/\s\+//g' | tr -d '\n' | sed -e 's/\"bytesRateLast\"/\n\"bytesRateLast\"/g' | sed -r '/^\s*$/d' | awk -F "\"" '{ printf "%-65s %25.2f\n", $8,$4*8}'

APIC#for leaf in `acidiag fnvread | grep leaf | awk '{print $1}'`; do echo; echo " -> leaf ID: $leaf  "; fabric $leaf  show int | sed -n '/net[0-9]\/[0-9]\+ is up/,/Tx pause/p' | egrep -i '[0-9]+ is up|30 seconds input' | tr -d '\n' | sed 's/packets\/sec/\n/g' | sort -n -r -k 10 ; done;

查詢所有STP拓撲更改：

1. 該命令將進入每個枝葉，並驗證是否有任何最近的拓撲更改以及哪些介面：

APIC#for node in `acidiag fnvread | grep leaf | awk '{print $1}'`; do echo; echo "node ID: $node "; fabric $node  show mcp internal info vlan all |  grep -A 2 -B 4 "Last TC flush at"  | sed -z 's/\n/ /g' | sed 's/--/\n/g;s/  $/\n/' | sort -n -r -k 22  ; done;

2. 該命令進入每個枝葉，並驗證PVRSTP更改的最大計數以及可見的介面：

APIC#for node in `acidiag fnvread | grep leaf | awk '{print $1}'`; do echo; echo "node ID: $node "; fabric $node  show mcp internal info vlan all |  grep -A 2 -B 4 "Last TC flush at"  | sed -z 's/\n/ /g' | sed 's/--/\n/g;s/  $/\n/' | sort -n -r -k 11 ; done;

確保是否存在多播RPF丟棄：

這需要在當時用於單個枝葉，並且它驗證所有RPF丟棄的所有已啟用的pim VRF:

APIC#for vrf in `show ip mroute summary vrf all | grep 'IP Multicast Routing Table for VR' | awk '{print $7}' | sed 's/"//g' `  ; do echo; echo -e "VRF  id: $vrf: \n" ; show ip mroute summary rpf-failed vrf $vrf | egrep "Source count: [1-9][0-9]*|[1-9]\.[0-9]{3}|LEAF|leaf" | sed -n '/Group.*count: [1-9][0-9]*/,/bps  [0-9]*/p' | awk '{print $1, $2}' | sed 's/,/ - SRC \/ pckt:\n/g' ; done;

驗證是否有太多資料包獲得Glean:

1. 交換矩陣ARP閃爍：

APIC#for leaf in `acidiag fnvread | grep leaf | awk '{print $1}'`; do echo; echo " -> leaf ID: $leaf  "; fabric $leaf show ip arp internal event-history event | grep glean | grep "Received pkt Fabric-Glean" | awk -F 'log_collect_arp_glean;' '{print $2}' | awk -F 'info =' '{print $1}' | sort | uniq -c ; done;

2. ARP收集收到的資料包：

APIC#for leaf in `acidiag fnvread | grep leaf | awk '{print $1}'`; do echo; echo " -> leaf ID: $leaf  "; fabric $leaf show ip arp internal event-history event | grep "Received glean packet" | awk -F 'log_collect_arp_glean;' '{print $2}' | awk -F 'info =' '{print $1}' | sort | uniq -c ; done;

QoS丟棄統計資訊：

驗證整個交換矩陣接收的QoS丟包：

APIC#moquery -c qosmIfClass -f 'qosm.IfClass.RxDropPacketsCount!="0"' | egrep "RxDropPacketsCount|dn" | awk '{print $3}' | tr -d "\n" | sed 's/level[0-9]/level\t\n/g'| sed 's/plane/plane\n/g' | awk -F 'topology/' '{print $2}'

驗證整個交換矩陣的QoS傳輸丟棄：

APIC#moquery -c qosmIfClass -f 'qosm.IfClass.TxDropPacketsCount!="0"' | egrep "TxDropPacketsCount|dn" | awk '{print $3}' | tr -d "\n" | sed 's/level[0-9]/level\t\n/g'| sed 's/plane/plane\n/g' | awk -F 'topology/' '{print $2}'

介面捨棄：

FCS錯誤（非堆積CRC錯誤）

APIC#moquery -c rmonDot3Stats -f 'rmon.Dot3Stats.fCSErrors>="1"' | egrep "dn|fCSErrors"

FCS +儲存的CRC錯誤

APIC#moquery -c rmonEtherStats -f 'rmon.EtherStats.cRCAlignErrors>="1"' | egrep "dn|cRCAlignErrors"

輸出緩衝區丟棄

APIC#moquery -c rmonEgrCounters -f 'rmon.EgrCounters.bufferdroppkts>="1"' | egrep "dn|bufferdroppkts"

輸出錯誤

APIC#moquery -c rmonIfOut -f 'rmon.IfOut.errors>="1"' | egrep "dn|errors"

清除所有介面計數器

用於獲取交換矩陣節點清單的命令

APIC# acidiag fnvread | egrep " active" | egrep "leaf|spine" | awk '{print $1}' | sed -e 'H;${x;s/\n/,/g;s/^,//;p;};d'

101,102,103,204,205,206,301,1001,1002,2001,2002

用於清除以前清單的計數器的命令

APIC# fabric 101,102,103,204,205,206,301,1001,1002,2001,2002 clear counters interface all

BGP會話問題：

檢查交換矩陣底層上是否有任何BGP作業階段出現問題

APIC#moquery -c bgpPeerEntry -f 'bgp.PeerEntry.operSt!="established" and  bgp.PeerEntry.dn*"overlay-1"' | egrep "dn|operSt" | tr -d "\n" | sed "s/dn/\ndn/g;s/operSt/\t-\toperSt/g"

檢查任何BGP作業階段

APIC#moquery -c bgpPeerEntry -f 'bgp.PeerEntry.operSt!="established" | egrep "dn|operSt" | tr -d "\n" | sed "s/dn/\ndn/g;s/operSt/\t-\toperSt/g"

OSPF會話問題：

識別未處於完全狀態的會話。

APIC#moquery -c ospfAdjEp -f 'ospf.AdjEp.operSt!="full"' | egrep "dn|peerIp" | tr -d '\n' | sed "s/dn           : topology\//\nNode : /g;s/peerIp/\tpeerIp/g;s/       //g" | sed "s/\/sys.*dom-/ VRF: /g;s/\/if-\[/ Interface : /g;s/\]\/adj-/ Adj: /g"

識別不斷擺動的作業階段，並將資訊排序到最高位數：

APIC#moquery -c ospfAdjStats -f 'ospf.AdjStats.stChgCnt!="0"' | egrep "dn|stChgCnt" | tr -d "\n" | tr -d " " | sed "s/dn:topology\//\nNode: /g;s/\/adjstatsstChgCnt:/\tADJ changes: /g;s/\/if-\[/ Interface: /g;s/\]\/adj-/ Adj /g" | sed "s/\/sys.*dom-/ VRF: /g" | sort -nrk 11

被傳送到CPU的主資料包

考慮：此命令調試500個資料包。對於較小的金額，請修改 — c後的數字。

lEAF#tcpdump -i kpm_inb -c 500 > /tmp/cpu-dp.txt

LEAF#cat /tmp/cpu-dp.txt | grep IP | awk '{print $3 , $4 , $5}' | grep -v $HOSTNAME | awk -F ':' '{print $1}' | sort | uniq -c | sort -nrk 1

直接連線，而不建立新檔案：

LEAF#tcpdump -i kpm_inb -c 500 | grep IP | awk '{print $3 , $4 , $5}' | grep -v $HOSTNAME | awk -F ':' '{print $1}' | sort | uniq -c | sort -nrk 1

從部署所有特定合約關係的apic檢查整個交換矩陣

APIC#moquery -c actrlRule -f 'actrl.Rule.sPcTag=="32783" and actrl.Rule.dPcTag=="46" and actrl.Rule.scopeId=="2818048"'

檢查封裝已在何處部署並獲得相應的epg

APIC#moquery -c l2CktEp -f 'l2.CktEp.encap=="vlan-3018"'

交換矩陣中所有節點的記憶體利用率：

APIC#bash

APIC# clear ; echo -e "Node ID\t\tFree Memory\tUsed Memory" ; moquery -c procSysMemHist15min -f 'proc.SysMemHist15min.index=="1"' | grep dn | awk -F " " '{print $3}' | xargs -n 1 -I {} sh -c 'freeAvg=`moquery -d {} | grep freeAvg | sed -E -e "s/[[:blank:]]+/ /g" | cut -d " " -f3` ; usedAvg=`moquery -d {} | grep usedAvg | sed -E -e "s/[[:blank:]]+/ /g" | cut -d " " -f3` ; totalAvg=`moquery -d {} | grep totalAvg | sed -E -e "s/[[:blank:]]+/ /g" | cut -d " " -f3` ; node=`echo {} | cut -d "/" -f3` ; freeAdj=$(( freeAvg * 100 )) ; usedAdj=$(( usedAvg * 100 )) ; percFree=$(( freeAdj / totalAvg )) ; percUtil=$(( usedAdj / totalAvg )) ; echo -e "$node\tFree% : $percFree\tUsed% : $percUtil"'

驗證istack上的丟棄（異常資料包被點選）

檢查TX丟棄。使用sort -nk 6 -r的命令：

APIC# cat istack_debug | egrep "Protocol:|x_pkts_dropped" | tr -d "\n" | sed "s/Protocol/\nProtocol/g" | sort -nk 6 -r | more

合約驗證

複查特定合約的所有關係。使用指令碼替換合約和租戶的名稱：

APIC# CONTRACT='brc-<contract-name>'

APIC# TN='<tenant>'

#CHECK CONSUMERS

#To get the count of epgs consuming a contract (excluding vzany consumer):

APIC#icurl -g 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=subtree&target-subtree-class=vzRtCons,vzConsDef&rsp-subtree-include=count&query-target-filter=or(eq(vzRtCons.tCl,"fvAEPg"),eq(vzRtCons.tCl,"l2extInstP"),eq(vzRtCons.tCl,"l3extInstP"),wcard(vzConsDef.dn,"uni/tn-'.*'/inherited-\[uni/tn-"))'

#To list all epg objects consuming a contract (excluding vzany consumers):

APIC#icurl -g 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=subtree&target-subtree-class=vzRtCons,vzConsDef&query-target-filter=or(eq(vzRtCons.tCl,"fvAEPg"),eq(vzRtCons.tCl,"l2extInstP"),eq(vzRtCons.tCl,"l3extInstP"),wcard(vzConsDef.dn,"uni/tn-'.*'/inherited-\[uni/tn-"))' | python -m json.tool

#To get the count of vzanys consuming a contract:

APIC#icurl 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=children&target-subtree-class=vzRtAnyToCons&rsp-subtree-include=count'

#To list all vzany objects consuming a contract:

APIC#icurl 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=children&target-subtree-class=vzRtAnyToCons' | python -m json.tool

#CHECK PROVIDERS

#To get the count of epgs providing a contract (excluding vzany consumer):

APIC#icurl -g 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=subtree&target-subtree-class=vzRtProv,vzProvDef&rsp-subtree-include=count&query-target-filter=or(eq(vzRtProv.tCl,"fvAEPg"),eq(vzRtProv.tCl,"l2extInstP"),eq(vzRtProv.tCl,"l3extInstP"),wcard(vzProvDef.dn,"uni/tn-'.*'/inherited-\[uni/tn-"))'

#To list all epg objects providing a contract (excluding vzany consumers):

APIC#icurl -g 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=subtree&target-subtree-class=vzRtProv,vzProvDef&query-target-filter=or(eq(vzRtProv.tCl,"fvAEPg"),eq(vzRtProv.tCl,"l2extInstP"),eq(vzRtProv.tCl,"l3extInstP"),wcard(vzProvDef.dn,"uni/tn-'.*'/inherited-\[uni/tn-"))' | python -m json.tool

#To get the count of vzanys providing a contract:

APIC#icurl 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=children&target-subtree-class=vzRtAnyToProv&rsp-subtree-include=count'

#To list all vzany objects providing a contract:

APIC#icurl 'http://localhost:7777/api/node/mo/uni/tn-'$TN'/'$CONTRACT'.json?query-target=children&target-subtree-class=vzRtAnyToProv' | python -m json.tool