@@ -89,32 +89,47 @@ while /bin/true; do
89
89
eval ` eval $ip6cmd `
90
90
91
91
if [[ $SUBTYPE == " dualtor" ]]; then
92
- # manually set any remaining FAILED/INCOMPLETE entries to permanently INCOMPLETE
93
- # this prevents any remaining INCOMPLETE entries from automatically transitioning to FAILED
94
- # once these entries are incomplete, any subsequent neighbor advertisement messages
95
- # are able to resolve the entry
96
-
97
- # generates the following command for each failed or incomplete IPv6 neighbor
98
- # ip neigh replace <neighbor IPv6> dev <VLAN name> nud incomplete
99
- neigh_replace_template=" sed -e 's/^/ip neigh replace /' -e 's/,/ dev /' -e 's/$/ nud incomplete;/'"
100
- ip_neigh_replace_cmd=" ip -6 neigh show | grep -v fe80 | grep $vlan | grep -E 'FAILED|INCOMPLETE' | cut -d ' ' -f 1,3 --output-delimiter=',' | $neigh_replace_template "
101
- eval ` eval $ip_neigh_replace_cmd `
102
-
103
- # on dual ToR devices, try to resolve failed neighbor entries since
104
- # these entries will have tunnel routes installed, preventing normal
105
- # neighbor resolution (SWSS PR #2137)
106
-
107
- # since ndisc6 is a userland process, the above ndisc6 commands are
108
- # insufficient to update the kernel neighbor table for failed entries
109
-
110
- # we don't need to do this for ipv4 neighbors since arping is able to
111
- # update the kernel neighbor table
112
-
113
- # generates the following command for each failed or incomplete IPv6 neighbor
92
+ # capture all current failed/incomplete IPv6 neighbors in the kernel to avoid situations where new neighbors are learned
93
+ # in the middle of the below sequence of commands
94
+ unresolved_kernel_neighbors=$( ip -6 neigh show | grep -v fe80 | grep $vlan | grep -E ' FAILED|INCOMPLETE' )
95
+ failed_kernel_neighbors=$( echo " $unresolved_kernel_neighbors " | grep FAILED | cut -d ' ' -f 1)
96
+
97
+ # it's possible for kernel neighbors to fall out of sync with the hardware
98
+ # this can result in failed neighbors entries that don't have corresponding zero MAC neighbor entries
99
+ # and therefore don't have tunnel routes installed in the hardware
100
+ # flush these neighbors from the kernel to force relearning and resync them to the hardware:
101
+ # 1. for every FAILED or INCOMPLETE neighbor in the kernel, check if there is a corresponding zero MAC neighbor in APPL_DB
102
+ # 2. if no zero MAC neighbor entry exists, flush the kernel neighbor entry
103
+ # - generates the command 'ip neigh flush <neighbor IPv6>' for all such neighbors
104
+ unsync_neighbors=$( echo " $unresolved_kernel_neighbors " | cut -d ' ' -f 1 | xargs -I{} bash -c " if [[ -z \"\$ (sonic-db-cli APPL_DB hget NEIGH_TABLE:$vlan :{} neigh)\" ]]; then echo '{}'; fi" )
105
+ if [[ ! -z " $unsync_neighbors " ]]; then
106
+ ip_neigh_flush_cmd=" echo \" $unsync_neighbors \" | sed -e 's/^/ip neigh flush /' -e 's/$/;/'"
107
+ eval ` eval " $ip_neigh_flush_cmd " `
108
+ sleep 2
109
+ fi
110
+
111
+ # generates the following command for each FAILED or INCOMPLETE IPv6 neighbor
114
112
# timeout 0.2 ping <neighbor IPv6> -n -q -i 0 -c 1 -W 1 -I <VLAN name> >/dev/null
115
- ping6_template=" sed -e 's/^/timeout 0.2 ping /' -e 's/,/ -n -q -i 0 -c 1 -W 1 -I /' -e 's/$/ >\/dev\/null;/'"
116
- failed_ip6_neigh_cmd=" ip -6 neigh show | grep -v fe80 | grep $vlan | grep -E 'FAILED|INCOMPLETE' | cut -d ' ' -f 1,3 --output-delimiter=',' | $ping6_template "
117
- eval ` eval $failed_ip6_neigh_cmd `
113
+ if [[ ! -z " $unresolved_kernel_neighbors " ]]; then
114
+ ping6_template=" sed -e 's/^/timeout 0.2 ping /' -e 's/,/ -n -q -i 0 -c 1 -W 1 -I /' -e 's/$/ >\/dev\/null;/'"
115
+ failed_ip6_neigh_cmd=" echo \" $unresolved_kernel_neighbors \" | cut -d ' ' -f 1,3 --output-delimiter=',' | $ping6_template "
116
+ eval ` eval " $failed_ip6_neigh_cmd " `
117
+ # allow some time for any transient INCOMPLETE neighbors to transition to FAILED
118
+ sleep 5
119
+ fi
120
+
121
+ # manually set any remaining FAILED entries to permanently INCOMPLETE
122
+ # once these entries are INCOMPLETE, any subsequent neighbor advertisement messages are able to resolve the entry
123
+ # ignore INCOMPLETE neighbors since if they are transiently incomplete (i.e. new kernel neighbors that we are attempting to resolve for the first time),
124
+ # setting them to permanently incomplete here means the kernel will never generate a netlink message for that neighbor
125
+ # generates the following command for each FAILED IPv6 neighbor
126
+ # ip neigh replace <neighbor IPv6> dev <VLAN name> nud incomplete
127
+ failed_kernel_neighbors=$( ip -6 neigh show | grep -v fe80 | grep $vlan | grep -E ' FAILED' )
128
+ if [[ ! -z " $failed_kernel_neighbors " ]]; then
129
+ neigh_replace_template=" sed -e 's/^/ip neigh replace /' -e 's/,/ dev /' -e 's/$/ nud incomplete;/'"
130
+ ip_neigh_replace_cmd=" echo \" $failed_kernel_neighbors \" | cut -d ' ' -f 1,3 --output-delimiter=',' | $neigh_replace_template "
131
+ eval ` eval " $ip_neigh_replace_cmd " `
132
+ fi
118
133
fi
119
134
done
120
135
0 commit comments