#!/bin/bash # # usage: # arp_update: # Send ipv6 multicast pings to all "UP" L3 interfaces including vlan interfaces to # refresh link-local addresses from neighbors. # Send gratuitous ARP/NDP requests to VLAN member neighbors to refresh # the ipv4/ipv6 neighbors state. while /bin/true; do # find L3 interfaces which are UP, send ipv6 multicast pings echo "{% for (name, prefix) in INTERFACE %} {{name}} {% endfor %}" > /tmp/intf_tmp.j2 INTERFACE=`sonic-cfggen -d -t /tmp/intf_tmp.j2` echo "{% for (name, prefix) in PORTCHANNEL_INTERFACE %} {{name}} {% endfor %}" > /tmp/pc_intf_tmp.j2 PC_INTERFACE=`sonic-cfggen -d -t /tmp/pc_intf_tmp.j2` ALL_INTERFACE="$INTERFACE $PC_INTERFACE" for intf in $ALL_INTERFACE; do ping6cmd="ping6 -I $intf -n -q -i 0 -c 1 -W 0 ff02::1 >/dev/null" intf_up=$(ip link show $intf | grep "state UP") if [[ -n "$intf_up" ]]; then eval $ping6cmd fi done VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'` for vlan in $VLAN; do # generate a list of arping commands: # arping -q -w 0 -c 1 -i ; # arping -q -w 0 -c 1 -i ; # ... arpingcmd="sed -e 's/ / -i /' -e 's/^/arping -q -w 0 -c 1 /' -e 's/$/;/'" ipcmd="ip -4 neigh show | grep $vlan | cut -d ' ' -f 1,3 | $arpingcmd" eval `eval $ipcmd` # send ipv6 multicast pings to Vlan interfaces to get/refresh link-local addrs ping6cmd="ping6 -I $vlan -n -q -i 0 -c 1 -W 0 ff02::1 >/dev/null" eval $ping6cmd # generate a list of ndisc6 commands (exclude link-local addrs since it is done above): # ndisc6 -q -w 0 -1 ; # ndisc6 -q -w 0 -1 ; # ... ndisc6cmd="sed -e 's/^/ndisc6 -q -w 0 -1 /' -e 's/$/;/'" ip6cmd="ip -6 neigh show | grep -v fe80 | grep $vlan | cut -d ' ' -f 1,3 | $ndisc6cmd" eval `eval $ip6cmd` done # sleep here before handling the mismatch as it is not required during startup sleep 300 # refresh neighbor entries from APP_DB in case of mismatch with kernel DBNEIGH=$(redis-cli -n 0 --scan --pattern NEIGH_TABLE*) KERNEIGH4=$(ip -4 neigh show | grep Vlan | cut -d ' ' -f 1,3 --output-delimiter=',') KERNEIGH6=$(ip -6 neigh show | grep -v fe80 | grep Vlan | cut -d ' ' -f 1,3 --output-delimiter=',') for neigh in $DBNEIGH; do intf="$( cut -d ':' -f 2 <<< "$neigh" )" ip="$( cut -d ':' -f 3- <<< "$neigh" )" if [[ $intf == *"Vlan"* ]]; then if [[ $ip == *"."* ]] && [[ ! $KERNEIGH4 =~ "${ip},${intf}" ]]; then pingcmd="timeout 0.2 ping -I $intf -n -q -i 0 -c 1 -W 0 $ip >/dev/null" eval $pingcmd logger "arp_update: mismatch arp entry, pinging ${ip} on ${intf}" elif [[ $ip == *":"* ]] && [[ ! $KERNEIGH6 =~ "${ip},${intf}" ]]; then ping6cmd="timeout 0.2 ping6 -I $intf -n -q -i 0 -c 1 -W 0 $ip >/dev/null" eval $ping6cmd logger "arp_update: mismatch v6 nbr entry, pinging ${ip} on ${intf}" fi fi done done