xds: replace PriorityHeap with simpler logic that keeps track of top matches (#8225)

This commit is contained in:
sanjaypujare 2021-06-02 10:09:42 -07:00 committed by GitHub
parent 1cd925c3dd
commit 54b4e93927
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 36 additions and 71 deletions

View File

@ -40,10 +40,8 @@ import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.PriorityQueue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@ -307,26 +305,19 @@ public final class XdsClientWrapperForServerSds {
return cidrInt.equals(addrInt); return cidrInt.equals(addrInt);
} }
private static class QueueElement { private static int getMatchingPrefixLength(
FilterChain filterChain; FilterChainMatch filterChainMatch, InetAddress address, boolean forDestination) {
int indexOfMatchingPrefixRange;
int matchingPrefixLength;
public QueueElement(FilterChain filterChain, InetAddress address, boolean forDestination) {
this.filterChain = filterChain;
FilterChainMatch filterChainMatch = filterChain.getFilterChainMatch();
byte[] addressBytes = address.getAddress(); byte[] addressBytes = address.getAddress();
boolean isIPv6 = address instanceof Inet6Address; boolean isIPv6 = address instanceof Inet6Address;
List<CidrRange> cidrRanges = List<CidrRange> cidrRanges =
forDestination forDestination
? filterChainMatch.getPrefixRanges() ? filterChainMatch.getPrefixRanges()
: filterChainMatch.getSourcePrefixRanges(); : filterChainMatch.getSourcePrefixRanges();
indexOfMatchingPrefixRange = -1; int matchingPrefixLength;
if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match
matchingPrefixLength = 0; matchingPrefixLength = 0;
} else { } else {
matchingPrefixLength = -1; matchingPrefixLength = -1;
int index = 0;
for (CidrRange cidrRange : cidrRanges) { for (CidrRange cidrRange : cidrRanges) {
InetAddress cidrAddr = cidrRange.getAddressPrefix(); InetAddress cidrAddr = cidrRange.getAddressPrefix();
boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address; boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address;
@ -336,59 +327,33 @@ public final class XdsClientWrapperForServerSds {
if (isCidrMatching(cidrBytes, addressBytes, prefixLen) if (isCidrMatching(cidrBytes, addressBytes, prefixLen)
&& prefixLen > matchingPrefixLength) { && prefixLen > matchingPrefixLength) {
matchingPrefixLength = prefixLen; matchingPrefixLength = prefixLen;
indexOfMatchingPrefixRange = index;
}
}
index++;
} }
} }
} }
} }
return matchingPrefixLength;
private static final class QueueElementComparator implements Comparator<QueueElement> {
@Override
public int compare(QueueElement o1, QueueElement o2) {
// descending order for max heap
return o2.matchingPrefixLength - o1.matchingPrefixLength;
}
@Override
public boolean equals(Object obj) {
return obj instanceof QueueElementComparator;
}
@Override
public int hashCode() {
return super.hashCode();
}
} }
// use prefix_ranges (CIDR) and get the most specific matches // use prefix_ranges (CIDR) and get the most specific matches
private static List<FilterChain> filterOnIpAddress( private static List<FilterChain> filterOnIpAddress(
List<FilterChain> filterChains, InetAddress address, boolean forDestination) { List<FilterChain> filterChains, InetAddress address, boolean forDestination) {
PriorityQueue<QueueElement> heap = new PriorityQueue<>(10, new QueueElementComparator()); // curent list of top ones
ArrayList<FilterChain> topOnes = new ArrayList<>(filterChains.size());
for (FilterChain filterChain : filterChains) {
QueueElement element = new QueueElement(filterChain, address, forDestination);
if (element.matchingPrefixLength >= 0) {
heap.add(element);
}
}
// get the top ones
ArrayList<FilterChain> topOnes = new ArrayList<>(heap.size());
int topMatchingPrefixLen = -1; int topMatchingPrefixLen = -1;
while (!heap.isEmpty()) { for (FilterChain filterChain : filterChains) {
QueueElement element = heap.remove(); int currentMatchingPrefixLen =
if (topMatchingPrefixLen == -1) { getMatchingPrefixLength(filterChain.getFilterChainMatch(), address, forDestination);
topMatchingPrefixLen = element.matchingPrefixLength;
} else { if (currentMatchingPrefixLen >= 0) {
if (element.matchingPrefixLength < topMatchingPrefixLen) { if (currentMatchingPrefixLen < topMatchingPrefixLen) {
break; continue;
} }
if (currentMatchingPrefixLen > topMatchingPrefixLen) {
topMatchingPrefixLen = currentMatchingPrefixLen;
topOnes.clear();
}
topOnes.add(filterChain);
} }
topOnes.add(element.filterChain);
} }
return topOnes; return topOnes;
} }