mirror of https://github.com/grpc/grpc-java.git
xds: replace PriorityHeap with simpler logic that keeps track of top matches (#8225)
This commit is contained in:
parent
1cd925c3dd
commit
54b4e93927
|
|
@ -40,10 +40,8 @@ import java.net.InetAddress;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
|
@ -307,88 +305,55 @@ public final class XdsClientWrapperForServerSds {
|
|||
return cidrInt.equals(addrInt);
|
||||
}
|
||||
|
||||
private static class QueueElement {
|
||||
FilterChain filterChain;
|
||||
int indexOfMatchingPrefixRange;
|
||||
private static int getMatchingPrefixLength(
|
||||
FilterChainMatch filterChainMatch, InetAddress address, boolean forDestination) {
|
||||
byte[] addressBytes = address.getAddress();
|
||||
boolean isIPv6 = address instanceof Inet6Address;
|
||||
List<CidrRange> cidrRanges =
|
||||
forDestination
|
||||
? filterChainMatch.getPrefixRanges()
|
||||
: filterChainMatch.getSourcePrefixRanges();
|
||||
int matchingPrefixLength;
|
||||
|
||||
public QueueElement(FilterChain filterChain, InetAddress address, boolean forDestination) {
|
||||
this.filterChain = filterChain;
|
||||
FilterChainMatch filterChainMatch = filterChain.getFilterChainMatch();
|
||||
byte[] addressBytes = address.getAddress();
|
||||
boolean isIPv6 = address instanceof Inet6Address;
|
||||
List<CidrRange> cidrRanges =
|
||||
forDestination
|
||||
? filterChainMatch.getPrefixRanges()
|
||||
: filterChainMatch.getSourcePrefixRanges();
|
||||
indexOfMatchingPrefixRange = -1;
|
||||
if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match
|
||||
matchingPrefixLength = 0;
|
||||
} else {
|
||||
matchingPrefixLength = -1;
|
||||
int index = 0;
|
||||
for (CidrRange cidrRange : cidrRanges) {
|
||||
InetAddress cidrAddr = cidrRange.getAddressPrefix();
|
||||
boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address;
|
||||
if (isIPv6 == cidrIsIpv6) {
|
||||
byte[] cidrBytes = cidrAddr.getAddress();
|
||||
int prefixLen = cidrRange.getPrefixLen();
|
||||
if (isCidrMatching(cidrBytes, addressBytes, prefixLen)
|
||||
&& prefixLen > matchingPrefixLength) {
|
||||
matchingPrefixLength = prefixLen;
|
||||
indexOfMatchingPrefixRange = index;
|
||||
}
|
||||
if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match
|
||||
matchingPrefixLength = 0;
|
||||
} else {
|
||||
matchingPrefixLength = -1;
|
||||
for (CidrRange cidrRange : cidrRanges) {
|
||||
InetAddress cidrAddr = cidrRange.getAddressPrefix();
|
||||
boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address;
|
||||
if (isIPv6 == cidrIsIpv6) {
|
||||
byte[] cidrBytes = cidrAddr.getAddress();
|
||||
int prefixLen = cidrRange.getPrefixLen();
|
||||
if (isCidrMatching(cidrBytes, addressBytes, prefixLen)
|
||||
&& prefixLen > matchingPrefixLength) {
|
||||
matchingPrefixLength = prefixLen;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
return matchingPrefixLength;
|
||||
}
|
||||
|
||||
// use prefix_ranges (CIDR) and get the most specific matches
|
||||
private static List<FilterChain> filterOnIpAddress(
|
||||
List<FilterChain> filterChains, InetAddress address, boolean forDestination) {
|
||||
PriorityQueue<QueueElement> heap = new PriorityQueue<>(10, new QueueElementComparator());
|
||||
|
||||
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());
|
||||
// curent list of top ones
|
||||
ArrayList<FilterChain> topOnes = new ArrayList<>(filterChains.size());
|
||||
int topMatchingPrefixLen = -1;
|
||||
while (!heap.isEmpty()) {
|
||||
QueueElement element = heap.remove();
|
||||
if (topMatchingPrefixLen == -1) {
|
||||
topMatchingPrefixLen = element.matchingPrefixLength;
|
||||
} else {
|
||||
if (element.matchingPrefixLength < topMatchingPrefixLen) {
|
||||
break;
|
||||
for (FilterChain filterChain : filterChains) {
|
||||
int currentMatchingPrefixLen =
|
||||
getMatchingPrefixLength(filterChain.getFilterChainMatch(), address, forDestination);
|
||||
|
||||
if (currentMatchingPrefixLen >= 0) {
|
||||
if (currentMatchingPrefixLen < topMatchingPrefixLen) {
|
||||
continue;
|
||||
}
|
||||
if (currentMatchingPrefixLen > topMatchingPrefixLen) {
|
||||
topMatchingPrefixLen = currentMatchingPrefixLen;
|
||||
topOnes.clear();
|
||||
}
|
||||
topOnes.add(filterChain);
|
||||
}
|
||||
topOnes.add(element.filterChain);
|
||||
}
|
||||
return topOnes;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue