From 6668c2eb3c659a76b1c84e8752852125a5085f54 Mon Sep 17 00:00:00 2001 From: Ari Fogel Date: Mon, 12 Apr 2021 14:33:09 -0700 Subject: [PATCH] IOS-XR interface ipv4/6 address parsing (#6899) - update ipv4 address parsing for XR syntax - parse and ignore ipv6 address --- .../batfish/grammar/cisco_xr/CiscoXrLexer.g4 | 6 ++ .../grammar/cisco_xr/CiscoXr_common.g4 | 8 ++- .../grammar/cisco_xr/CiscoXr_interface.g4 | 61 +++++++---------- .../CiscoXrControlPlaneExtractor.java | 68 ++++++++----------- .../grammar/cisco_xr/XrGrammarTest.java | 22 ++++++ .../cisco_xr/testconfigs/xr-interface-address | 15 ++++ 6 files changed, 103 insertions(+), 77 deletions(-) create mode 100644 projects/batfish/src/test/resources/org/batfish/grammar/cisco_xr/testconfigs/xr-interface-address diff --git a/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXrLexer.g4 b/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXrLexer.g4 index c6038ad7a12..75b99d6564b 100644 --- a/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXrLexer.g4 +++ b/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXrLexer.g4 @@ -1780,6 +1780,8 @@ ETHERNET_SERVICES: 'ethernet-services'; ETYPE: 'etype'; +EUI_64: 'eui-64'; + EVALUATE: 'evaluate'; EVENT: 'event'; @@ -2725,6 +2727,8 @@ LINK_FAIL: 'link-fail'; LINK_FAULT_SIGNALING: 'link-fault-signaling'; +LINK_LOCAL: 'link-local'; + LINK_TYPE: 'link-type'; LINKSEC: 'linksec'; @@ -4365,6 +4369,8 @@ ROUTE_PREFERENCE: 'route-preference'; ROUTE_REFLECTOR_CLIENT: 'route-reflector-client'; +ROUTE_TAG: 'route-tag'; + ROUTE_TARGET: 'route-target'; ROUTE_TYPE: 'route-type'; diff --git a/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_common.g4 b/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_common.g4 index 514385bc632..fd6ad9f21a3 100644 --- a/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_common.g4 +++ b/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_common.g4 @@ -505,6 +505,12 @@ route_distinguisher (IP_ADDRESS | bgp_asn) COLON uint_legacy ; +route_tag +: + // 1-4294967295 + uint32 +; + route_target : (IP_ADDRESS | bgp_asn) COLON uint_legacy @@ -653,4 +659,4 @@ route_policy_name: WORD; vrf_name: WORD; -access_list_name: WORD; \ No newline at end of file +access_list_name: WORD; diff --git a/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_interface.g4 b/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_interface.g4 index f057be465e5..a256f36bc43 100644 --- a/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_interface.g4 +++ b/projects/batfish/src/main/antlr4/org/batfish/grammar/cisco_xr/CiscoXr_interface.g4 @@ -249,39 +249,6 @@ if_hsrp6_ip_address IP ip = IPV6_ADDRESS NEWLINE ; -if_ip_address -: - (IP | IPV4) ADDRESS - VIRTUAL? - ( - ip = IP_ADDRESS subnet = IP_ADDRESS - | prefix = IP_PREFIX - ) - (STANDBY standby_address = IP_ADDRESS)? - (ROUTE_PREFERENCE pref=uint_legacy)? - (TAG tag=uint_legacy)? - NEWLINE -; - -if_ip_address_dhcp -: - IP ADDRESS DHCP NEWLINE -; - -if_ip_address_secondary -: - ( - IP - | IPV4 - ) ADDRESS - ( - ( - ip = IP_ADDRESS subnet = IP_ADDRESS - ) - | prefix = IP_PREFIX - ) SECONDARY DHCP_GIADDR? NEWLINE -; - if_ip_authentication : IP AUTHENTICATION @@ -519,6 +486,7 @@ if_ipv4: IPV4 if_ipv4_inner; if_ipv4_inner : if_ipv4_access_group + | if_ipv4_address | if_ipv4_null ; @@ -537,6 +505,14 @@ if_ipv4_access_group ) NEWLINE ; +if_ipv4_address: ADDRESS interface_ipv4_address SECONDARY? (ROUTE_TAG tag=route_tag)? NEWLINE; + +interface_ipv4_address +: + address = IP_ADDRESS mask = IP_ADDRESS + | prefix = IP_PREFIX +; + if_ipv4_null : // TODO: some of these should be handled or at least warn @@ -557,6 +533,7 @@ if_ipv6 if_ipv6_inner : if_ipv6_access_group + | if_ipv6_address | if_ipv6_enable | if_ipv6_traffic_filter ; @@ -574,6 +551,21 @@ if_ipv6_access_group ) NEWLINE ; +if_ipv6_address +: + ADDRESS + ( + address = IPV6_ADDRESS (LINK_LOCAL | len = ipv6_interface_address_length) + | prefix = IPV6_PREFIX EUI_64? + ) (ROUTE_TAG tag = route_tag)? NEWLINE +; + +ipv6_interface_address_length +: + // 1-128 + uint8 +; + if_ipv6_enable : ENABLE NEWLINE @@ -1680,9 +1672,6 @@ if_inner | if_hsrp6 | if_ip_proxy_arp | if_ip_verify - | if_ip_address - | if_ip_address_dhcp - | if_ip_address_secondary | if_ip_authentication | if_ip_dhcp | if_ip_flow_monitor diff --git a/projects/batfish/src/main/java/org/batfish/grammar/cisco_xr/CiscoXrControlPlaneExtractor.java b/projects/batfish/src/main/java/org/batfish/grammar/cisco_xr/CiscoXrControlPlaneExtractor.java index a1e60046c6b..ca5ea3dd5dc 100644 --- a/projects/batfish/src/main/java/org/batfish/grammar/cisco_xr/CiscoXrControlPlaneExtractor.java +++ b/projects/batfish/src/main/java/org/batfish/grammar/cisco_xr/CiscoXrControlPlaneExtractor.java @@ -466,8 +466,6 @@ import org.batfish.grammar.cisco_xr.CiscoXrParser.If_delayContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_descriptionContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_encapsulationContext; -import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ip_addressContext; -import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ip_address_secondaryContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ip_forwardContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ip_helper_addressContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ip_igmpContext; @@ -486,6 +484,7 @@ import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ip_summary_addressContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ip_verifyContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ipv4_access_groupContext; +import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ipv4_addressContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ipv6_access_groupContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_ipv6_traffic_filterContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.If_isis_metricContext; @@ -525,6 +524,7 @@ import org.batfish.grammar.cisco_xr.CiscoXrParser.Inspect_protocolContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.Int_compContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.Int_exprContext; +import org.batfish.grammar.cisco_xr.CiscoXrParser.Interface_ipv4_addressContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.Interface_is_stanzaContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.Interface_nameContext; import org.batfish.grammar.cisco_xr.CiscoXrParser.Ios_banner_headerContext; @@ -3843,48 +3843,22 @@ public void exitIf_ipv6_access_group(If_ipv6_access_groupContext ctx) { } @Override - public void exitIf_ip_address(If_ip_addressContext ctx) { - ConcreteInterfaceAddress address; - if (ctx.prefix != null) { - address = ConcreteInterfaceAddress.parse(ctx.prefix.getText()); - } else { - Ip ip = toIp(ctx.ip); - Ip mask = toIp(ctx.subnet); - address = ConcreteInterfaceAddress.create(ip, mask); + public void exitIf_ipv4_address(If_ipv4_addressContext ctx) { + Optional maybeAddress = + toConcreteInterfaceAddress(ctx, ctx.interface_ipv4_address()); + if (!maybeAddress.isPresent()) { + return; } + ConcreteInterfaceAddress address = maybeAddress.get(); for (Interface currentInterface : _currentInterfaces) { - currentInterface.setAddress(address); - } - if (ctx.STANDBY() != null) { - Ip standbyIp = toIp(ctx.standby_address); - ConcreteInterfaceAddress standbyAddress = - ConcreteInterfaceAddress.create(standbyIp, address.getNetworkBits()); - for (Interface currentInterface : _currentInterfaces) { - currentInterface.setStandbyAddress(standbyAddress); + if (ctx.SECONDARY() != null) { + currentInterface.getSecondaryAddresses().add(address); + } else { + currentInterface.setAddress(address); } } - if (ctx.ROUTE_PREFERENCE() != null) { - warn(ctx, "Unsupported: route-preference declared in interface IP address"); - } - if (ctx.TAG() != null) { - warn(ctx, "Unsupported: tag declared in interface IP address"); - } - } - - @Override - public void exitIf_ip_address_secondary(If_ip_address_secondaryContext ctx) { - Ip ip; - Ip mask; - ConcreteInterfaceAddress address; - if (ctx.prefix != null) { - address = ConcreteInterfaceAddress.parse(ctx.prefix.getText()); - } else { - ip = toIp(ctx.ip); - mask = toIp(ctx.subnet); - address = ConcreteInterfaceAddress.create(ip, mask.numSubnetBits()); - } - for (Interface currentInterface : _currentInterfaces) { - currentInterface.getSecondaryAddresses().add(address); + if (ctx.tag != null) { + warn(ctx, "Unsupported: tag declared in interface ipv4 address"); } } @@ -8538,4 +8512,18 @@ public void visitErrorNode(ErrorNode errorNode) { } return Optional.of(num); } + + private @Nonnull Optional toConcreteInterfaceAddress( + ParserRuleContext messageCtx, Interface_ipv4_addressContext ctx) { + try { + if (ctx.prefix != null) { + return Optional.of(ConcreteInterfaceAddress.parse(ctx.prefix.getText())); + } else if (ctx.address != null) { + return Optional.of(ConcreteInterfaceAddress.create(toIp(ctx.address), toIp(ctx.mask))); + } + } catch (IllegalArgumentException e) { + warn(messageCtx, "Invalid interface ipv4 address"); + } + return Optional.empty(); + } } diff --git a/projects/batfish/src/test/java/org/batfish/grammar/cisco_xr/XrGrammarTest.java b/projects/batfish/src/test/java/org/batfish/grammar/cisco_xr/XrGrammarTest.java index 7b8b067b1db..2b936d76e7e 100644 --- a/projects/batfish/src/test/java/org/batfish/grammar/cisco_xr/XrGrammarTest.java +++ b/projects/batfish/src/test/java/org/batfish/grammar/cisco_xr/XrGrammarTest.java @@ -77,6 +77,7 @@ import org.batfish.datamodel.AsPath; import org.batfish.datamodel.BgpActivePeerConfig; import org.batfish.datamodel.Bgpv4Route; +import org.batfish.datamodel.ConcreteInterfaceAddress; import org.batfish.datamodel.Configuration; import org.batfish.datamodel.ConfigurationFormat; import org.batfish.datamodel.Interface; @@ -1275,4 +1276,25 @@ public void testIpv6AccessListParsing() { // Do not crash assertNotNull(parseVendorConfig(hostname)); } + + @Test + public void testInterfaceAddressExtraction() { + String hostname = "xr-interface-address"; + CiscoXrConfiguration vc = parseVendorConfig(hostname); + + String i1Name = "GigabitEthernet0/0/0/0"; + + assertThat(vc.getInterfaces(), hasKeys(i1Name)); + + { + org.batfish.representation.cisco_xr.Interface iface = vc.getInterfaces().get(i1Name); + ConcreteInterfaceAddress primary = ConcreteInterfaceAddress.parse("10.0.0.1/31"); + ConcreteInterfaceAddress secondary1 = ConcreteInterfaceAddress.parse("10.0.0.3/31"); + ConcreteInterfaceAddress secondary2 = ConcreteInterfaceAddress.parse("10.0.0.5/31"); + + assertThat(iface.getAllAddresses(), containsInAnyOrder(primary, secondary1, secondary2)); + assertThat(iface.getAddress(), equalTo(primary)); + assertThat(iface.getSecondaryAddresses(), containsInAnyOrder(secondary1, secondary2)); + } + } } diff --git a/projects/batfish/src/test/resources/org/batfish/grammar/cisco_xr/testconfigs/xr-interface-address b/projects/batfish/src/test/resources/org/batfish/grammar/cisco_xr/testconfigs/xr-interface-address new file mode 100644 index 00000000000..58348444e09 --- /dev/null +++ b/projects/batfish/src/test/resources/org/batfish/grammar/cisco_xr/testconfigs/xr-interface-address @@ -0,0 +1,15 @@ +!RANCID-CONTENT-TYPE: cisco-xr +! +hostname xr-interface-address +! + +interface GigabitEthernet0/0/0/0 + ipv4 address 10.0.0.1/31 + ipv4 address 10.0.0.3 255.255.255.254 secondary + ipv4 address 10.0.0.5 255.255.255.254 secondary route-tag 5 + + ipv6 address dead:beef::1/126 + ipv6 address deee:beef::1 127 + ipv6 address beee:beef::1/64 route-tag 5 + ipv6 address 2::3 link-local +!