package org.batfish.grammar.routing_table.eos; 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.eos.EosRoutingTableParser.*; public class EosRoutingTableExtractor extends EosRoutingTableParserBaseListener implements RoutingTableExtractor { private static int toInteger(Token t) { return Integer.parseInt(t.getText()); } private String _currentVrfName; private SortedSet<Route> _currentVrfRoutes; private final String _hostname; @SuppressWarnings("unused") private EosRoutingTableCombinedParser _parser; private RoutesByVrf _routesByVrf; private final String _text; @SuppressWarnings("unused") private final Warnings _w; public EosRoutingTableExtractor(String hostname, String text, EosRoutingTableCombinedParser 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 enterEos_routing_table(Eos_routing_tableContext ctx) { _routesByVrf = new RoutesByVrf(); } @Override public void enterVrf_declaration(Vrf_declarationContext ctx) { _currentVrfName = ctx.identifier().getText(); initVrf(_currentVrfName); } @Override public void exitRoute(RouteContext ctx) { if (_currentVrfName == null) { _currentVrfName = Configuration.DEFAULT_VRF_NAME; initVrf(_currentVrfName); } RoutingProtocol protocol = toProtocol(ctx.protocol()); Prefix prefix = new Prefix(ctx.IP_PREFIX().getText()); int admin; int cost; Ip nextHopIp; for (int i = 0; i < ctx.nexthopifaces.size(); i++) { String nextHopInterface = ctx.nexthopifaces.get(i).getText(); // TODO: support EOS route tags int tag = Route.UNSET_ROUTE_TAG; // TODO: support EOS next hop String nextHop = Route.UNSET_NEXT_HOP; if (ctx.IS_DIRECTLY_CONNECTED() != null) { admin = 0; cost = 0; nextHopIp = Route.UNSET_ROUTE_NEXT_HOP_IP; } else { admin = toInteger(ctx.admin); cost = toInteger(ctx.cost); nextHopIp = new Ip(ctx.nexthops.get(i).getText()); } Route route = new Route(_hostname, _currentVrfName, prefix, nextHopIp, nextHop, nextHopInterface, admin, cost, protocol, 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 vrfName) { _currentVrfRoutes = _routesByVrf.get(vrfName); if (_currentVrfRoutes == null) { _currentVrfRoutes = new TreeSet<>(); _routesByVrf.put(vrfName, _currentVrfRoutes); } } @Override public void processParseTree(ParserRuleContext tree) { ParseTreeWalker walker = new ParseTreeWalker(); walker.walk(this, tree); } private RoutingProtocol toProtocol(ProtocolContext ctx) { String protocolStr = ctx.getText(); switch (protocolStr) { case "BE": return RoutingProtocol.BGP; case "BI": return RoutingProtocol.IBGP; case "C": return RoutingProtocol.CONNECTED; case "S": return RoutingProtocol.STATIC; case "O": return RoutingProtocol.OSPF; case "IA": return RoutingProtocol.OSPF_IA; case "OE1": return RoutingProtocol.OSPF_E1; case "OE2": return RoutingProtocol.OSPF_E2; case "IL1": return RoutingProtocol.ISIS_L1; case "IL2": return RoutingProtocol.ISIS_L2; case "AB": case "AO": return RoutingProtocol.AGGREGATE; default: throw convError(RoutingProtocol.class, ctx); } } }