package org.batfish.grammar.routing_table.nxos;
import java.util.SortedSet;
import java.util.TreeSet;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.batfish.common.BatfishException;
import org.batfish.common.Warnings;
import org.batfish.datamodel.Configuration;
import org.batfish.datamodel.Ip;
import org.batfish.datamodel.Prefix;
import org.batfish.datamodel.Route;
import org.batfish.datamodel.RoutingProtocol;
import org.batfish.datamodel.collections.RoutesByVrf;
import org.batfish.grammar.RoutingTableExtractor;
import org.batfish.grammar.routing_table.nxos.NxosRoutingTableParser.NetworkContext;
import org.batfish.grammar.routing_table.nxos.NxosRoutingTableParser.Nxos_routing_tableContext;
import org.batfish.grammar.routing_table.nxos.NxosRoutingTableParser.ProtocolContext;
import org.batfish.grammar.routing_table.nxos.NxosRoutingTableParser.RouteContext;
import org.batfish.grammar.routing_table.nxos.NxosRoutingTableParser.Vrf_declarationContext;
public class NxosRoutingTableExtractor extends
NxosRoutingTableParserBaseListener implements RoutingTableExtractor {
private static int toInteger(Token t) {
return Integer.parseInt(t.getText());
}
private Prefix _currentPrefix;
private String _currentVrfName;
private SortedSet<Route> _currentVrfRoutes;
private final String _hostname;
@SuppressWarnings("unused")
private NxosRoutingTableCombinedParser _parser;
private RoutesByVrf _routesByVrf;
private final String _text;
@SuppressWarnings("unused")
private final Warnings _w;
public NxosRoutingTableExtractor(String hostname, String text,
NxosRoutingTableCombinedParser parser, Warnings w) {
_hostname = hostname;
_text = text;
_parser = parser;
_w = w;
}
private BatfishException convError(Class<?> type, ParserRuleContext ctx) {
String typeName = type.getSimpleName();
String txt = getFullText(ctx);
return new BatfishException(
"Could not convert to " + typeName + ": " + txt);
}
@Override
public void enterNetwork(NetworkContext ctx) {
_currentPrefix = new Prefix(ctx.IP_PREFIX().getText());
}
@Override
public void enterNxos_routing_table(Nxos_routing_tableContext ctx) {
_routesByVrf = new RoutesByVrf();
}
@Override
public void enterVrf_declaration(Vrf_declarationContext ctx) {
String currentVrfName = ctx.double_quoted_string().ID().getText();
initVrf(currentVrfName);
}
@Override
public void exitRoute(RouteContext ctx) {
if (ctx.protocol().LOCAL() != null) {
return;
}
if (_currentVrfRoutes == null) {
initVrf(Configuration.DEFAULT_VRF_NAME);
}
RoutingProtocol protocol = toProtocol(ctx.protocol());
String nextHopInterface = Route.UNSET_NEXT_HOP_INTERFACE;
if (ctx.nexthopint != null) {
nextHopInterface = ctx.nexthopint.getText();
}
int admin = toInteger(ctx.admin);
int cost = toInteger(ctx.cost);
Ip nextHopIp = Route.UNSET_ROUTE_NEXT_HOP_IP;
if (protocol != RoutingProtocol.CONNECTED && ctx.nexthop != null) {
nextHopIp = new Ip(ctx.nexthop.getText());
}
Route route = new Route(_hostname, _currentVrfName, _currentPrefix,
nextHopIp, Route.UNSET_NEXT_HOP, nextHopInterface, admin, cost,
protocol, Route.UNSET_ROUTE_TAG);
_currentVrfRoutes.add(route);
}
private String getFullText(ParserRuleContext ctx) {
int start = ctx.getStart().getStartIndex();
int end = ctx.getStop().getStopIndex();
String text = _text.substring(start, end + 1);
return text;
}
@Override
public RoutesByVrf getRoutesByVrf() {
return _routesByVrf;
}
private void initVrf(String name) {
_currentVrfName = name;
_currentVrfRoutes = new TreeSet<>();
_routesByVrf.put(name, _currentVrfRoutes);
}
@Override
public void processParseTree(ParserRuleContext tree) {
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(this, tree);
}
private RoutingProtocol toProtocol(ProtocolContext ctx) {
if (ctx.BGP() != null && ctx.INTERNAL() != null) {
return RoutingProtocol.IBGP;
}
else if (ctx.BGP() != null && ctx.EXTERNAL() != null) {
return RoutingProtocol.BGP;
}
else if (ctx.DIRECT() != null) {
return RoutingProtocol.CONNECTED;
}
else if (ctx.LOCAL() != null) {
return RoutingProtocol.CONNECTED;
}
else if (ctx.INTRA() != null) {
return RoutingProtocol.OSPF;
}
else if (ctx.INTER() != null) {
return RoutingProtocol.OSPF_IA;
}
else if (ctx.TYPE_1() != null) {
return RoutingProtocol.OSPF_E1;
}
else if (ctx.TYPE_2() != null) {
return RoutingProtocol.OSPF_E2;
}
else if (ctx.STATIC() != null) {
return RoutingProtocol.STATIC;
}
else {
throw convError(RoutingProtocol.class, ctx);
}
}
}