Last active
March 18, 2021 08:26
-
-
Save dosaboy/7bdd004d33d7eb39a93835576227ad4a 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/7bdd004d33d7eb39a93835576227ad4a | |
# | |
# Authors: | |
# - edward.hope-morley@canonical.com | |
# | |
# Tested on Ubuntu Bionic Ussuri | |
# | |
# Description: | |
# Fix arp entries affected by https://bugs.launchpad.net/neutron/+bug/1916761. | |
# | |
# This currently only fixes entries for ports that exist and performs lookup | |
# based on tap device mac address since ip address is not available. It also | |
# filters ports that do not have an iptables NAT rule since we only care | |
# about ports used with FIPs since thats the only traffic impacted by this | |
# bug. | |
# | |
# By default this script is read-only and will print suggested commands to | |
# run. If you want to have commands executed automatically you can set | |
# export NON_INTERACTIVE=true before running the script. | |
# | |
# Logs to stdout or syslog if NON_INTERACTIVE=true | |
# | |
# e.g.to run as a cron every minute add the following to crontab: | |
# | |
# * * * * * NON_INTERACTIVE=true /path/to/fix-lp1916761-dvr-arp-cache.sh | |
# | |
declare -A ifaces=() | |
declare -a fix_commands=() | |
auto_execute=${NON_INTERACTIVE:-false} | |
logger=tee | |
$auto_execute && logger=logger | |
( | |
readarray -t taps<<<`ip -br a| sed -rn 's/^(tap[[:alnum:]\-]+).+/\1/p'` | |
if ((${#taps[@]})) && [[ -n ${taps[0]} ]]; then | |
echo "Checking (${#taps[@]}) tap devices: ${taps[@]}" | |
for tap in ${taps[@]}; do | |
# get mac address | |
ifaces[$tap]=`ip -br l| grep $tap| awk '{print $3}'` | |
done | |
fi | |
if ! ((${#ifaces[@]})); then | |
echo "INFO: nothing to fix - exiting" | |
exit 0 | |
fi | |
for ns in `find /var/run/netns/ -name qrouter-\*`; do | |
ns=`basename $ns` | |
((${#taps[@]})) && [ -n "${taps[0]}" ] || continue | |
for iface in ${!ifaces[@]}; do | |
libvirt_mac=fa:${ifaces[$iface]:3} | |
readarray -t entries<<<`sudo ip netns exec $ns ip n| grep $libvirt_mac| grep PERMANENT` | |
((${#entries[@]})) && [[ -n ${entries[0]} ]] || continue | |
for perm in "${entries[@]}"; do | |
# if port has no NAT rule just ignore it | |
addr=`echo $perm| cut -d ' ' -f 1` | |
sudo ip netns exec $ns iptables -t nat -S| egrep "[SD]NAT"| grep -q $addr | |
(($?==0)) || continue | |
ip_n_cmd=`echo "$perm"| sed -r 's/PERMANENT/nud reachable/g'` | |
fix_commands+=( "sudo ip netns exec $ns ip n replace $ip_n_cmd" ) | |
done | |
done | |
done | |
if ! ((${#fix_commands[@]})); then | |
echo "INFO: nothing to fix - exiting" | |
exit 0 | |
else | |
echo "INFO: found ${#fix_commands[@]} arp entries that need fixing" | |
fi | |
if $auto_execute; then | |
echo "INFO: auto-executing commands to fix arp entries:" | |
for cmd in "${fix_commands[@]}"; do | |
echo "INFO: executing '$cmd'" | |
$cmd | |
done | |
else | |
echo "INFO: run the following commands to fix arp entries:" | |
for cmd in "${fix_commands[@]}"; do | |
echo $cmd | |
done | |
fi | |
echo -e "\nDone." | |
) | $logger |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment