package org.batfish.datamodel;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.batfish.common.util.ComparableStructure;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaDescription;
@JsonSchemaDescription("An access-list used to filter IPV6 routes")
public class Route6FilterList extends ComparableStructure<String> {
private static final String LINES_VAR = "lines";
private static final long serialVersionUID = 1L;
private transient Set<Prefix6> _deniedCache;
private List<Route6FilterLine> _lines;
private transient Set<Prefix6> _permittedCache;
@JsonCreator
public Route6FilterList(@JsonProperty(NAME_VAR) String name) {
super(name);
_lines = new ArrayList<>();
}
public void addLine(Route6FilterLine r) {
_lines.add(r);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
Route6FilterList other = (Route6FilterList) obj;
return other._lines.equals(_lines);
}
@JsonProperty(LINES_VAR)
@JsonPropertyDescription("The lines against which to check an IPV6 route")
public List<Route6FilterLine> getLines() {
return _lines;
}
private boolean newPermits(Prefix6 prefix) {
boolean accept = false;
for (Route6FilterLine line : _lines) {
Prefix6 linePrefix = line.getPrefix();
int lineBits = linePrefix.getPrefixLength();
Prefix6 truncatedLinePrefix = new Prefix6(linePrefix.getAddress(),
lineBits);
Prefix6 relevantPortion = new Prefix6(prefix.getAddress(), lineBits)
.getNetworkPrefix();
if (relevantPortion.equals(truncatedLinePrefix)) {
int prefixLength = prefix.getPrefixLength();
SubRange range = line.getLengthRange();
int min = range.getStart();
int max = range.getEnd();
if (prefixLength >= min && prefixLength <= max) {
accept = line.getAction() == LineAction.ACCEPT;
break;
}
}
}
if (accept) {
_permittedCache.add(prefix);
}
else {
_deniedCache.add(prefix);
}
return accept;
}
public boolean permits(Prefix6 prefix) {
if (_deniedCache.contains(prefix)) {
return false;
}
else if (_permittedCache.contains(prefix)) {
return true;
}
return newPermits(prefix);
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
_deniedCache = Collections.newSetFromMap(new ConcurrentHashMap<>());
_permittedCache = Collections.newSetFromMap(new ConcurrentHashMap<>());
}
@JsonProperty(LINES_VAR)
public void setLines(List<Route6FilterLine> lines) {
_lines = lines;
}
}