package org.batfish.question;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.batfish.common.Answerer;
import org.batfish.common.BatfishException;
import org.batfish.common.plugin.IBatfish;
import org.batfish.datamodel.BgpAdvertisement;
import org.batfish.datamodel.Configuration;
import org.batfish.datamodel.PrefixSpace;
import org.batfish.datamodel.answers.AnswerElement;
import org.batfish.datamodel.questions.Question;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
public class BgpAdvertisementsQuestionPlugin extends QuestionPlugin {
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
public static class BgpAdvertisementsAnswerElement implements AnswerElement {
private static final String ALL_REQUESTED_ADVERTISEMENTS_VAR = "allRequestedAdvertisements";
private static final String RECEIVED_EBGP_ADVERTISEMENTS_VAR = "receivedEbgpAdvertisements";
private static final String RECEIVED_IBGP_ADVERTISEMENTS_VAR = "receivedIbgpAdvertisements";
private static final String SENT_EBGP_ADVERTISEMENTS_VAR = "sentEbgpAdvertisements";
private static final String SENT_IBGP_ADVERTISEMENTS_VAR = "sentIbgpAdvertisements";
private SortedSet<BgpAdvertisement> _allRequestedAdvertisements;
private SortedMap<String, SortedSet<BgpAdvertisement>> _receivedEbgpAdvertisements;
private SortedMap<String, SortedSet<BgpAdvertisement>> _receivedIbgpAdvertisements;
private SortedMap<String, SortedSet<BgpAdvertisement>> _sentEbgpAdvertisements;
private SortedMap<String, SortedSet<BgpAdvertisement>> _sentIbgpAdvertisements;
@JsonCreator
public BgpAdvertisementsAnswerElement() {
}
public BgpAdvertisementsAnswerElement(
Map<String, Configuration> configurations, Pattern nodeRegex,
boolean ebgp, boolean ibgp, PrefixSpace prefixSpace,
boolean received, boolean sent) {
_allRequestedAdvertisements = new TreeSet<>();
_receivedEbgpAdvertisements = (received && ebgp) ? new TreeMap<>()
: null;
_sentEbgpAdvertisements = (sent && ebgp) ? new TreeMap<>() : null;
_receivedIbgpAdvertisements = (received && ibgp) ? new TreeMap<>()
: null;
_sentIbgpAdvertisements = (sent && ibgp) ? new TreeMap<>() : null;
for (Entry<String, Configuration> e : configurations.entrySet()) {
String hostname = e.getKey();
Matcher nodeMatcher = nodeRegex.matcher(hostname);
if (!nodeMatcher.matches()) {
continue;
}
Configuration configuration = e.getValue();
if (received) {
if (ebgp) {
Set<BgpAdvertisement> advertisements = configuration
.getReceivedEbgpAdvertisements();
fill(_receivedEbgpAdvertisements, hostname, advertisements,
prefixSpace);
}
if (ibgp) {
Set<BgpAdvertisement> advertisements = configuration
.getReceivedIbgpAdvertisements();
fill(_receivedIbgpAdvertisements, hostname, advertisements,
prefixSpace);
}
}
if (sent) {
if (ebgp) {
Set<BgpAdvertisement> advertisements = configuration
.getSentEbgpAdvertisements();
fill(_sentEbgpAdvertisements, hostname, advertisements,
prefixSpace);
}
if (ibgp) {
Set<BgpAdvertisement> advertisements = configuration
.getSentIbgpAdvertisements();
fill(_sentIbgpAdvertisements, hostname, advertisements,
prefixSpace);
}
}
}
}
private void fill(Map<String, SortedSet<BgpAdvertisement>> map,
String hostname, Set<BgpAdvertisement> advertisements,
PrefixSpace prefixSpace) {
SortedSet<BgpAdvertisement> placedAdvertisements = new TreeSet<>();
map.put(hostname, placedAdvertisements);
for (BgpAdvertisement advertisement : advertisements) {
if (prefixSpace.isEmpty()
|| prefixSpace.containsPrefix(advertisement.getNetwork())) {
placedAdvertisements.add(advertisement);
_allRequestedAdvertisements.add(advertisement);
}
}
}
@JsonProperty(ALL_REQUESTED_ADVERTISEMENTS_VAR)
public SortedSet<BgpAdvertisement> getAllRequestedAdvertisements() {
return _allRequestedAdvertisements;
}
@JsonIdentityReference(alwaysAsId = true)
@JsonProperty(RECEIVED_EBGP_ADVERTISEMENTS_VAR)
public SortedMap<String, SortedSet<BgpAdvertisement>> getReceivedEbgpAdvertisements() {
return _receivedEbgpAdvertisements;
}
@JsonIdentityReference(alwaysAsId = true)
@JsonProperty(RECEIVED_IBGP_ADVERTISEMENTS_VAR)
public SortedMap<String, SortedSet<BgpAdvertisement>> getReceivedIbgpAdvertisements() {
return _receivedIbgpAdvertisements;
}
@JsonIdentityReference(alwaysAsId = true)
@JsonProperty(SENT_EBGP_ADVERTISEMENTS_VAR)
public SortedMap<String, SortedSet<BgpAdvertisement>> getSentEbgpAdvertisements() {
return _sentEbgpAdvertisements;
}
@JsonIdentityReference(alwaysAsId = true)
@JsonProperty(SENT_IBGP_ADVERTISEMENTS_VAR)
public SortedMap<String, SortedSet<BgpAdvertisement>> getSentIbgpAdvertisements() {
return _sentIbgpAdvertisements;
}
@JsonProperty(ALL_REQUESTED_ADVERTISEMENTS_VAR)
public void setAllRequestedAdvertisements(
SortedSet<BgpAdvertisement> allRequestedAdvertisements) {
_allRequestedAdvertisements = allRequestedAdvertisements;
}
@JsonProperty(RECEIVED_EBGP_ADVERTISEMENTS_VAR)
public void setReceivedEbgpAdvertisements(
SortedMap<String, SortedSet<BgpAdvertisement>> receivedEbgpAdvertisements) {
_receivedEbgpAdvertisements = receivedEbgpAdvertisements;
}
@JsonProperty(RECEIVED_IBGP_ADVERTISEMENTS_VAR)
public void setReceivedIbgpAdvertisements(
SortedMap<String, SortedSet<BgpAdvertisement>> receivedIbgpAdvertisements) {
_receivedIbgpAdvertisements = receivedIbgpAdvertisements;
}
@JsonProperty(SENT_EBGP_ADVERTISEMENTS_VAR)
public void setSentEbgpAdvertisements(
SortedMap<String, SortedSet<BgpAdvertisement>> sentEbgpAdvertisements) {
_sentEbgpAdvertisements = sentEbgpAdvertisements;
}
@JsonProperty(SENT_IBGP_ADVERTISEMENTS_VAR)
public void setSentIbgpAdvertisements(
SortedMap<String, SortedSet<BgpAdvertisement>> sentIbgpAdvertisements) {
_sentIbgpAdvertisements = sentIbgpAdvertisements;
}
}
public static class BgpAdvertisementsAnswerer extends Answerer {
public BgpAdvertisementsAnswerer(Question question, IBatfish batfish) {
super(question, batfish);
}
@Override
public AnswerElement answer() {
BgpAdvertisementsQuestion question = (BgpAdvertisementsQuestion) _question;
Pattern nodeRegex;
try {
nodeRegex = Pattern.compile(question.getNodeRegex());
}
catch (PatternSyntaxException e) {
throw new BatfishException(
"Supplied regex for nodes is not a valid java regex: \""
+ question.getNodeRegex() + "\"",
e);
}
_batfish.checkDataPlaneQuestionDependencies();
Map<String, Configuration> configurations = _batfish
.loadConfigurations();
_batfish.initBgpAdvertisements(configurations);
BgpAdvertisementsAnswerElement answerElement = new BgpAdvertisementsAnswerElement(
configurations, nodeRegex, question.getEbgp(),
question.getIbgp(), question.getPrefixSpace(),
question.getReceived(), question.getSent());
return answerElement;
}
}
// <question_page_comment>
/**
* Lists BGP adverstisements in the network.
* <p>
* It can output all eBGP/iBGP advertisements that are exchanged in the
* network.
*
* @type BgpAdvertisements dataplane
*
* @param ebgp
* (True|False) which indicates if eBGP advertisements should be
* included. Default is True.
* @param ibgp
* (True|False) which indicates if iBGP advertisements should be
* included. Default is True.
* @param nodeRegex
* Regular expression for names of nodes to include. Default value
* is '.*' (all nodes).
* @param prefixRange
* Details coming. Default is entire range.
* @param received
* (True|False) which indicates if received advertisements should
* be included. Default is True.
* @param sent
* (True|False) which indicates if sent advertisements should be
* included. Default is True.
*
* @example bf_answer("BgpAdvertisements", sent='False', nodeRegex='as1.*')
* Lists all BGP advertisements received (not sent) by nodes whose
* names start with 'as1'.
*/
public static class BgpAdvertisementsQuestion extends Question {
private static final String EBGP_VAR = "ebgp";
private static final String IBGP_VAR = "ibgp";
private static final String NODE_REGEX_VAR = "nodeRegex";
private static final String PREFIX_SPACE_VAR = "prefixSpace";
private static final String RECEIVED_VAR = "received";
private static final String SENT_VAR = "sent";
private boolean _ebgp;
private boolean _ibgp;
private String _nodeRegex;
private PrefixSpace _prefixSpace;
private boolean _received;
private boolean _sent;
public BgpAdvertisementsQuestion() {
_nodeRegex = ".*";
_ebgp = true;
_ibgp = true;
_nodeRegex = ".*";
_received = true;
_sent = true;
_prefixSpace = new PrefixSpace();
}
@Override
public boolean getDataPlane() {
return true;
}
@JsonProperty(EBGP_VAR)
public boolean getEbgp() {
return _ebgp;
}
@JsonProperty(IBGP_VAR)
public boolean getIbgp() {
return _ibgp;
}
@Override
public String getName() {
return "bgpadvertisements";
}
@JsonProperty(NODE_REGEX_VAR)
public String getNodeRegex() {
return _nodeRegex;
}
@JsonProperty(PREFIX_SPACE_VAR)
public PrefixSpace getPrefixSpace() {
return _prefixSpace;
}
@JsonProperty(RECEIVED_VAR)
public boolean getReceived() {
return _received;
}
@JsonProperty(SENT_VAR)
public boolean getSent() {
return _sent;
}
@Override
public boolean getTraffic() {
return false;
}
@Override
public String prettyPrint() {
String retString = String.format(
"%s %s%s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\"",
getName(), prettyPrintBase(), EBGP_VAR, _ebgp, IBGP_VAR, _ibgp,
NODE_REGEX_VAR, _nodeRegex, PREFIX_SPACE_VAR,
_prefixSpace.toString(), RECEIVED_VAR, _received, SENT_VAR,
_sent);
return retString;
}
@JsonProperty(EBGP_VAR)
public void setEbgp(boolean ebgp) {
_ebgp = ebgp;
}
@JsonProperty(IBGP_VAR)
public void setIbgp(boolean ibgp) {
_ibgp = ibgp;
}
@JsonProperty(NODE_REGEX_VAR)
public void setNodeRegex(String nodeRegex) {
_nodeRegex = nodeRegex;
}
@JsonProperty(PREFIX_SPACE_VAR)
private void setPrefixSpace(PrefixSpace prefixSpace) {
_prefixSpace = prefixSpace;
}
@JsonProperty(RECEIVED_VAR)
public void setReceived(boolean received) {
_received = received;
}
@JsonProperty(SENT_VAR)
public void setSent(boolean sent) {
_sent = sent;
}
}
@Override
protected Answerer createAnswerer(Question question, IBatfish batfish) {
return new BgpAdvertisementsAnswerer(question, batfish);
}
@Override
protected Question createQuestion() {
return new BgpAdvertisementsQuestion();
}
}