Last active
October 29, 2020 17:02
-
-
Save dosaboy/f0f0b88a0fcb3553d3eeb21c9bb3963e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -u | |
# Origin: https://gist.github.com/dosaboy/f0f0b88a0fcb3553d3eeb21c9bb3963e | |
# | |
# Authors: | |
# - edward.hope-morley@canonical.com | |
# | |
# Tested on Ubuntu Bionic | |
# | |
# Description: | |
# Discover incorrect arp entries for rfp/fpr interfaces | |
# | |
declare -A map=() | |
declare -A rfps_mac_actual=() | |
declare -A rfps_mac_cache=() | |
declare -A rfps_gw_actual=() | |
declare -A rfps_gw_cache=() | |
declare -A rfps_entry=() | |
declare -A fprs_mac_actual=() | |
declare -A fprs_mac_cache=() | |
declare -A fprs_gw_actual=() | |
declare -A fprs_gw_cache=() | |
declare -A fprs_entry=() | |
for ns in `find /var/run/netns/ -name qrouter-\*`; do | |
ns=`basename $ns` | |
readarray -t interfaces<<<`sudo ip netns exec $ns ip -4 -br a| sed -rn 's/^(rfp-[[:alnum:]\-]+)@.+/\1/p'` | |
((${#interfaces[@]})) && [ -n "${interfaces[0]}" ] || continue | |
for iface in ${interfaces[@]}; do | |
rfps_mac_actual[${ns}_$iface]=`ip netns exec $ns ip a s| grep "${iface}@" -A 1| sed -rn 's/.+link\/ether\s+([[:alnum:]\:]+)\s+.+/\1/p'` | |
rfps_gw_actual[${ns}_$iface]=`ip netns exec $ns ip -4 a s| grep "${iface}@" -A 1| sed -rn 's/.+inet\s+([[:digit:]\.]+)\/[[:digit:]]+\s+.+/\1/p'` | |
rfps_mac_cache[${ns}_$iface]=`ip netns exec $ns ip n| sed -rn "s/.+dev\s+${iface}\s+lladdr\s+([[:alnum:]\:]+)\s*.*/\1/p"` | |
rfps_gw_cache[${ns}_$iface]=`ip netns exec $ns ip n| sed -rn "s/(^[[:digit:]\.]+).+dev\s+${iface}\s+.+/\1/p"` | |
rfps_entry[${ns}_$iface]=`ip netns exec $ns ip n| grep $iface` | |
done | |
done | |
for ns in `find /var/run/netns/ -name fip-\*`; do | |
ns=`basename $ns` | |
readarray -t interfaces<<<`sudo ip netns exec $ns ip -4 -br a| sed -rn 's/^(fpr-[[:alnum:]\-]+)@.+/\1/p'` | |
((${#interfaces[@]})) && [ -n "${interfaces[0]}" ] || continue | |
for iface in ${interfaces[@]}; do | |
fprs_mac_actual[${ns}_$iface]=`ip netns exec $ns ip a s| grep "${iface}@" -A 1| sed -rn 's/.+link\/ether\s+([[:alnum:]\:]+)\s+.+/\1/p'` | |
fprs_gw_actual[${ns}_$iface]=`ip netns exec $ns ip -4 a s| grep "${iface}@" -A 1| sed -rn 's/.+inet\s+([[:digit:]\.]+)\/[[:digit:]]+\s+.+/\1/p'` | |
fprs_mac_cache[${ns}_$iface]=`ip netns exec $ns ip n| sed -rn "s/.+dev\s+${iface}\s+lladdr\s+([[:alnum:]\:]+)\s*.*/\1/p"` | |
fprs_gw_cache[${ns}_$iface]=`ip netns exec $ns ip n| sed -rn "s/(^[[:digit:]\.]+).+dev\s+${iface}\s+.+/\1/p"` | |
fprs_entry[${ns}_$iface]=`ip netns exec $ns ip n| grep $iface` | |
map[$iface]=$ns | |
done | |
done | |
declare -a cleanup_commands=() | |
declare -A hits=() | |
count=0 | |
for rfp in ${!rfps_mac_actual[@]}; do | |
((count+=2)) | |
ns=${rfp%%_*} | |
iface=${rfp##*_} | |
rfp_mac_actual=${rfps_mac_actual[$rfp]} | |
rfp_mac_cache=${rfps_mac_cache[$rfp]} | |
rfp_gw_actual=${rfps_gw_actual[$rfp]} | |
rfp_gw_cache=${rfps_gw_cache[$rfp]} | |
fpr_name="fpr${iface#*rfp}" | |
fip_ns=${map[$fpr_name]} | |
fpr_key="${fip_ns}_$fpr_name" | |
fpr_mac_actual=${fprs_mac_actual[$fpr_key]} | |
fpr_mac_cache=${fprs_mac_cache[$fpr_key]} | |
fpr_gw_actual=${fprs_gw_actual[$fpr_key]} | |
fpr_gw_cache=${fprs_gw_cache[$fpr_key]} | |
if ! [[ $rfp_mac_cache == $fpr_mac_actual ]]; then | |
hits[$ns]=0 | |
old="`echo ${rfps_entry[$rfp]}| sed -rn 's/(.+\s+)[[:alpha:]]+$/\1/p'`" | |
if [ -n "$old" ]; then | |
cleanup_commands+=( "sudo ip netns exec $ns ip n del $old" ) | |
new=`echo $old| sed -e "s/$rfp_mac_cache/$fpr_mac_actual/g" -e "s/$rfp_gw_cache/$fpr_gw_actual/g"` | |
else | |
new="$fpr_gw_actual dev $iface lladdr $fpr_mac_actual" | |
fi | |
cleanup_commands+=( "sudo ip netns exec $ns ip n add $new nud permanent" ) | |
cleanup_commands+=( "((\$?==0)) || sudo ip netns exec $ns ip n replace $new nud permanent" ) | |
fi | |
if ! [[ $fpr_mac_cache == $rfp_mac_actual ]]; then | |
hits[$fip_ns]=0 | |
old="`echo ${fprs_entry[$fpr_key]}| sed -rn 's/(.+\s+)[[:alpha:]]+$/\1/p'`" | |
if [ -n "$old" ]; then | |
cleanup_commands+=( "sudo ip netns exec $fip_ns ip n del $old" ) | |
new=`echo $old| sed -e "s/$fpr_mac_cache/$rfp_mac_actual/g" -e "s/$fpr_gw_cache/$rfp_gw_actual/g"` | |
else | |
new="$rfp_gw_actual dev $fpr_name lladdr $rfp_mac_actual" | |
fi | |
cleanup_commands+=( "sudo ip netns exec $fip_ns ip n add $new nud permanent" ) | |
cleanup_commands+=( "((\$?==0)) || sudo ip netns exec $fip_ns ip n replace $new nud permanent" ) | |
fi | |
done | |
if ((${#cleanup_commands[@]})); then | |
echo -e "Checked $count namespaces and found ${#hits[@]} namespaces with bad arp entries:\n" | |
for cmd in "${cleanup_commands[@]}"; do | |
echo $cmd | |
done | |
else | |
echo "Checked $count namespaces and no issues found." | |
fi | |
echo -e "\nDone." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment