Skip to content

Instantly share code, notes, and snippets.

@lxf1992521
Last active September 10, 2019 01:39
Show Gist options
  • Save lxf1992521/ae4c398bde74edad5dc0ef5a0a600bf5 to your computer and use it in GitHub Desktop.
Save lxf1992521/ae4c398bde74edad5dc0ef5a0a600bf5 to your computer and use it in GitHub Desktop.
交换机-主机拓扑链路追踪脚本,使用 shell 语法完成
#!/bin/bash
# ============================================================
# related links:
# http://www.cisco.com/c/en/us/support/docs/ip/simple-network-management-protocol-snmp/13492-cam-snmp.html
# ============================================================
# ============ related MIB/OIDs =============================
# CISCO-CDP-MIB::cdpCacheDeviceId
# CISCO-CDP-MIB::cdpCacheDevicePort
# SNMPv2-MIB::sysName.0
# IF-MIB::ifName
# BRIDGE-MIB::dot1dBasePortIfIndex
# CISCO-VTP-MIB::vtpVlanState
# VALN: BRIDGE-MIB::dot1dTpFdbPort
# ============================================================
# port-channel: CISCO-PAGP-MIB::pagpGroupIfIndex
# LACP portchannel: IEEE8023-LAG-MIB::dot3adAggPortSelectedAggID
# Linux:
# - bond0 配合 port-channel 一起使用;
# - bond1 只能显示当前激活的那个端口,另外一个无法得到;
# - bond4 配合 LACP portchannel 一起使用;
# - bond5/6 可以同时看到所有连接的端口;
# ============================================================
cd -- "$(dirname -- "$0")" || exit
# set params
if [ "$1" == "-n" ]; then
switchmap=1
shift
fi
siwtchlist="${1:-switch.list}"
hostmacmap="${2:-host.mac}"
asamacmap="${3:-asa.mac}"
commuity=XXXXXX
# get MIB to associative arrays
mibarray() {
[ -n "$3" ] && commuity="$commuity@$3"
snmpbulkwalk -OX -OQ -v 2c -c "$commuity" $1 $2 2> /dev/null | grep -v '= No Such Instance' | sed -r "s/$2\[([^]]+)\].* = ([^ ]+)$/[\1]=\2/" | tr "\n" " "
}
# Main function
switch_host_map() {
local switchip="$1"
# hostname
local switchname=$(snmpget -Ov -OQ -v 2c -c $commuity $switchip SNMPv2-MIB::sysName.0)
[ -n "$switchname" ] || return 1
# ifname <--> port
eval local -A ifindex0ifname=( $(mibarray $switchip IF-MIB::ifName) )
eval local -A ifport0ifindex=( $(mibarray $switchip BRIDGE-MIB::dot1dBasePortIfIndex) )
# port-channel map
eval local -A ifindex0ifindex4lacpportchannel=( $(mibarray $switchip IEEE8023-LAG-MIB::dot3adAggPortSelectedAggID) )
eval local -A ifindex0ifindex4portchannel=( $(mibarray $switchip CISCO-PAGP-MIB::pagpGroupIfIndex) )
# CDP Info
eval local -A ifindex0cdpeviceid=( $(mibarray $switchip CISCO-CDP-MIB::cdpCacheDeviceId) )
eval local -A ifindex0cdpeviceport=( $(mibarray $switchip CISCO-CDP-MIB::cdpCacheDevicePort) )
# mac/ifport for every vlan
local vlanlist=$(snmpbulkwalk -Oq -v 2c -c $commuity $switchip CISCO-VTP-MIB::vtpVlanState | awk -F'[. ]' '$(NF-1) < 1002 {print $(NF-1) }')
local -A mac0ifport
for vlan in $vlanlist; do
eval mac0ifport+=( $(mibarray $switchip BRIDGE-MIB::dot1dTpFdbPort $vlan | tr : _) )
done
# ifport <---> (cdp|mac|hostname)
echo -e "\n$switchname[$switchip]:"
for ifindex in $( xargs -n 1 <<<"${!ifindex0ifname[@]}" | sort -n); do
for ifport in ${!ifport0ifindex[@]}; do
[[ ${ifport0ifindex[$ifport]} == $ifindex ]] && break
unset ifport
done
ifname=${ifindex0ifname[$ifindex]}
# cdp
cdpeviceid=${ifindex0cdpeviceid[$ifindex]}
cdpeviceport=${ifindex0cdpeviceport[$ifindex]}
# mac
maclist=""
macnum=0
for mac in ${!mac0ifport[@]}; do
[[ ${mac0ifport[$mac]} == $ifport ]] && {
maclist+="${mac//_/:}"$'\n'
((macnum++))
}
done
# portchannel
local lacpportchannelifname=""
lacpportchannelifindex=${ifindex0ifindex4lacpportchannel[$ifindex]}
[ -n "$lacpportchannelifindex" ] && [ "$lacpportchannelifindex" != 0 ] && lacpportchannelifname=${ifindex0ifname[$lacpportchannelifindex]}
portchannelifindex=${ifindex0ifindex4portchannel[$ifindex]}
local portchannelifname=""
[ -n "$portchannelifindex" ] && [ "$portchannelifindex" != "$ifindex" ] && [ "$portchannelifindex" != 0 ] &&
portchannelifname=${ifindex0ifname[$portchannelifindex]}
# interface info
if [ -n "$cdpeviceid" ]; then
echo -e "$ifname\t$cdpeviceid[$cdpeviceport]"
elif [ $macnum -eq 1 -o $macnum -eq 2 ]; then
host=$(
for mac in $maclist; do
grep -h -w $mac $hostmacmap $asamacmap | awk '{print $1}'
done | sort -u)
[ -z "$host" ] && host="<unknown>"
echo -e "$ifname\t"$host
elif [ $macnum -gt 1 ]; then
echo -e "$ifname\t<floading>"
elif [ -n "$portchannelifname" ]; then
echo -e "$ifname\t[$portchannelifname]"
elif [ -n "$lacpportchannelifname" ]; then
echo -e "$ifname\t[$lacpportchannelifname(LACP)]"
else
:
# echo -e "$ifname\t<down>"
fi
done | column -t | sed 's/^/\t/'
}
for switch in $(<$siwtchlist); do
switch_host_map $switch
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment