目录

简介

先决条件

要求

使用的组件

背景信息

用于获取信息的工具

所有单行命令的列表

仅获取交换矩阵内枝叶的节点ID:

验证是否存在接口重置：

检查最高评级的接口：

查找所有STP拓扑更改：

确保存在组播RPF丢弃：

验证是否有太多数据包获得Glean:

QoS丢弃统计信息：

接口丢弃:

FCS错误（非堆叠CRC错误）

FCS +堆叠CRC错误

输出缓冲区丢弃

输出错误

清除所有接口计数器

BGP会话问题：

OSPF会话问题：

传送到CPU的主数据包

从部署所有特定合同关系的apic检查整个交换矩阵

检查封装已部署的位置并获取相应的epg

交换矩阵中所有节点的内存利用率：

检验istack上的丢包（丢弃异常数据包）

合同验证

简介

本文档介绍我们检测交换矩阵整体问题的不同方法。

先决条件

要求

- 思科建议了解ACI

- Bash基础知识

使用的组件

本文档不限于特定的软件和硬件版本。

使用的设备：

- 运行版本4.2(3)的思科ACI

本文档中的信息都是基于特定实验室环境中的设备编写的。本文档中使用的所有设备最初均采用原始（默认）配置。如果您的网络处于活动状态，请确保您了解所有命令的潜在影响。

背景信息

用于获取信息的工具

- 用于替换：sed “s/<oldword >/<new wordk>/g” g定义它不止执行一次。

- 用于从头到尾抓取行：sed“/<beginning/,/end/p>”。将 — n(noprint)选项与/p打印标志相结合，以复制grep的功能。

- Sed可以通过使用“；”多次使用，例如：将：sed /<oldword >/<new wordk>/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