Skip to content

Commit

Permalink
juniper parse and partially convert condition (#6658)
Browse files Browse the repository at this point in the history
- parse, convert policy-statement from condition
- parse, partially convert policy-options condition if-route-exists
  - TODO: VI design and implementation for checking route existence in RP
    - just return false for if-route-exists for now
  • Loading branch information
arifogel committed Feb 25, 2021
1 parent 5644d4d commit e2c2c78
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ COMPRESS_CONFIGURATION_FILES

CONDITION
:
'condition'
'condition' -> pushMode(M_Name)
;

CONFEDERATION
Expand Down Expand Up @@ -1824,6 +1824,8 @@ IDS_OPTION
'ids-option'
;

IF_ROUTE_EXISTS: 'if-route-exists';

IGMP
:
'igmp'
Expand Down Expand Up @@ -5610,6 +5612,8 @@ SYSTEM_SERVICES
'system-services'
;

TABLE: 'table';

TACACS
:
'tacacs'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ ip_option
| TIMESTAMP
;

ip_prefix: IP_PREFIX;

ip_protocol
:
AH
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,26 @@ po_community

po_condition
:
CONDITION null_filler
CONDITION name = junos_name
(
apply
| pocond_if_route_exists
)
;

pocond_if_route_exists
:
IF_ROUTE_EXISTS
(
pocondi_prefix
| pocondi_table
)
;

pocondi_prefix: prefix=ip_prefix;

pocondi_table: TABLE name=variable;

po_policy_statement
:
POLICY_STATEMENT name = variable
Expand Down Expand Up @@ -124,6 +141,7 @@ pops_from
| popsf_as_path_group
| popsf_color
| popsf_community
| popsf_condition
| popsf_family
| popsf_instance
| popsf_interface
Expand Down Expand Up @@ -191,6 +209,8 @@ popsf_community
COMMUNITY name = variable
;

popsf_condition: CONDITION name = junos_name;

popsf_family
:
FAMILY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static org.batfish.representation.juniper.JuniperStructureType.AUTHENTICATION_KEY_CHAIN;
import static org.batfish.representation.juniper.JuniperStructureType.BGP_GROUP;
import static org.batfish.representation.juniper.JuniperStructureType.COMMUNITY;
import static org.batfish.representation.juniper.JuniperStructureType.CONDITION;
import static org.batfish.representation.juniper.JuniperStructureType.DHCP_RELAY_SERVER_GROUP;
import static org.batfish.representation.juniper.JuniperStructureType.FIREWALL_FILTER;
import static org.batfish.representation.juniper.JuniperStructureType.FIREWALL_FILTER_TERM;
Expand Down Expand Up @@ -77,6 +78,7 @@
import static org.batfish.representation.juniper.JuniperStructureUsage.POLICY_STATEMENT_FROM_AS_PATH;
import static org.batfish.representation.juniper.JuniperStructureUsage.POLICY_STATEMENT_FROM_AS_PATH_GROUP;
import static org.batfish.representation.juniper.JuniperStructureUsage.POLICY_STATEMENT_FROM_COMMUNITY;
import static org.batfish.representation.juniper.JuniperStructureUsage.POLICY_STATEMENT_FROM_CONDITION;
import static org.batfish.representation.juniper.JuniperStructureUsage.POLICY_STATEMENT_FROM_INSTANCE;
import static org.batfish.representation.juniper.JuniperStructureUsage.POLICY_STATEMENT_FROM_INTERFACE;
import static org.batfish.representation.juniper.JuniperStructureUsage.POLICY_STATEMENT_POLICY;
Expand Down Expand Up @@ -299,6 +301,7 @@
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Intir_memberContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Intir_member_rangeContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Ip_optionContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Ip_prefixContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Ip_protocolContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Ipsec_authentication_algorithmContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Ipsec_protocolContext;
Expand Down Expand Up @@ -362,12 +365,16 @@
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Po_as_pathContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Po_as_path_groupContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Po_communityContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Po_conditionContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Po_policy_statementContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Po_prefix_listContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Poapg_as_pathContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Poc_invert_matchContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Poc_membersContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Poc_members_memberContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Pocond_if_route_existsContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Pocondi_prefixContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Pocondi_tableContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Policy_expressionContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Poplt_ip6Context;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Poplt_network6Context;
Expand All @@ -378,6 +385,7 @@
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Popsf_as_path_groupContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Popsf_colorContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Popsf_communityContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Popsf_conditionContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Popsf_familyContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Popsf_instanceContext;
import org.batfish.grammar.flatjuniper.FlatJuniperParser.Popsf_interfaceContext;
Expand Down Expand Up @@ -629,6 +637,7 @@
import org.batfish.representation.juniper.BgpGroup.BgpGroupType;
import org.batfish.representation.juniper.CommunityMember;
import org.batfish.representation.juniper.ConcreteFirewallFilter;
import org.batfish.representation.juniper.Condition;
import org.batfish.representation.juniper.DhcpRelayGroup;
import org.batfish.representation.juniper.DhcpRelayServerGroup;
import org.batfish.representation.juniper.Family;
Expand Down Expand Up @@ -730,6 +739,7 @@
import org.batfish.representation.juniper.PsFromAsPath;
import org.batfish.representation.juniper.PsFromColor;
import org.batfish.representation.juniper.PsFromCommunity;
import org.batfish.representation.juniper.PsFromCondition;
import org.batfish.representation.juniper.PsFromFamily;
import org.batfish.representation.juniper.PsFromInstance;
import org.batfish.representation.juniper.PsFromInterface;
Expand Down Expand Up @@ -2009,6 +2019,8 @@ static String unquote(String text) {

private NatRuleSet _currentNatRuleSet;

private Condition _currentCondition;

private PolicyStatement _currentPolicyStatement;

private PrefixList _currentPrefixList;
Expand Down Expand Up @@ -6134,6 +6146,46 @@ public void exitVlt_l3_interface(Vlt_l3_interfaceContext ctx) {
_currentNamedVlan.setL3Interface(name);
}

@Override
public void enterPo_condition(Po_conditionContext ctx) {
String name = toString(ctx.name);
_currentCondition = _currentLogicalSystem.getConditions().computeIfAbsent(name, Condition::new);
_configuration.defineFlattenedStructure(CONDITION, name, ctx, _parser);
}

@Override
public void exitPo_condition(Po_conditionContext ctx) {
_currentCondition = null;
}

@Override
public void enterPocond_if_route_exists(Pocond_if_route_existsContext ctx) {
_currentCondition.getOrCreateIfRouteExists();
}

@Override
public void exitPocondi_prefix(Pocondi_prefixContext ctx) {
_currentCondition.getIfRouteExists().setPrefix(toPrefix(ctx.prefix));
}

@Override
public void exitPocondi_table(Pocondi_tableContext ctx) {
_currentCondition.getIfRouteExists().setTable(unquote(ctx.name.getText()));
}

private static @Nonnull Prefix toPrefix(Ip_prefixContext ctx) {
return Prefix.parse(ctx.getText());
}

@Override
public void exitPopsf_condition(Popsf_conditionContext ctx) {
todo(ctx);
String name = toString(ctx.name);
_configuration.referenceStructure(
CONDITION, name, POLICY_STATEMENT_FROM_CONDITION, getLine(ctx.getStart()));
_currentPsTerm.getFroms().addFromCondition(new PsFromCondition(name));
}

@Nullable
private IpWildcard formIpWildCard(Fftfa_address_mask_prefixContext ctx) {
IpWildcard ipWildcard = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.batfish.representation.juniper;

import java.io.Serializable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

@ParametersAreNonnullByDefault
public final class Condition implements Serializable {

public Condition(String name) {
_name = name;
}

public @Nonnull IfRouteExists getOrCreateIfRouteExists() {
if (_ifRouteExists == null) {
_ifRouteExists = new IfRouteExists();
}
return _ifRouteExists;
}

public @Nullable IfRouteExists getIfRouteExists() {
return _ifRouteExists;
}

public @Nonnull String getName() {
return _name;
}

private final @Nonnull String _name;
private @Nullable IfRouteExists _ifRouteExists;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.batfish.representation.juniper;

import java.io.Serializable;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.batfish.datamodel.Prefix;

/** Subcondition checking existence of a route in a table */
@ParametersAreNonnullByDefault
public final class IfRouteExists implements Serializable {

@Nullable
public Prefix getPrefix() {
return _prefix;
}

public void setPrefix(@Nullable Prefix prefix) {
_prefix = prefix;
}

@Nullable
public String getTable() {
return _table;
}

public void setTable(@Nullable String table) {
_table = table;
}

private @Nullable Prefix _prefix;
private @Nullable String _table;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import static org.batfish.datamodel.acl.AclLineMatchExprs.or;
import static org.batfish.datamodel.bgp.AllowRemoteAsOutMode.ALWAYS;
import static org.batfish.datamodel.bgp.AllowRemoteAsOutMode.EXCEPT_FIRST;
import static org.batfish.datamodel.routing_policy.statement.Statements.ReturnFalse;
import static org.batfish.datamodel.routing_policy.statement.Statements.ReturnTrue;
import static org.batfish.representation.juniper.JuniperStructureType.ADDRESS_BOOK;
import static org.batfish.representation.juniper.NatPacketLocation.interfaceLocation;
import static org.batfish.representation.juniper.NatPacketLocation.routingInstanceLocation;
Expand Down Expand Up @@ -201,6 +203,11 @@ public final class JuniperConfiguration extends VendorConfiguration {
return String.format("%s %s", policyName, termName);
}

@VisibleForTesting
public static @Nonnull String computeConditionRoutingPolicyName(@Nonnull String conditionName) {
return String.format("~CONDITION~%s", conditionName);
}

@VisibleForTesting
public static TraceElement matchingFirewallFilter(String filename, String filterName) {
return TraceElement.builder()
Expand Down Expand Up @@ -1319,7 +1326,7 @@ static RoutingPolicy generateDefaultPseudoProtocolImportPolicy(@Nonnull Configur
RoutingProtocol.STATIC,
RoutingProtocol.AGGREGATE),
ImmutableList.of(Statements.ReturnTrue.toStaticStatement()),
ImmutableList.of(Statements.ReturnFalse.toStaticStatement()))))
ImmutableList.of(ReturnFalse.toStaticStatement()))))
.build();
}

Expand Down Expand Up @@ -2598,7 +2605,7 @@ private static RoutingPolicy buildInstanceImportRoutingPolicy(
new If(
new FirstMatchChain(policyCalls),
ImmutableList.of(Statements.ReturnTrue.toStaticStatement()),
ImmutableList.of(Statements.ReturnFalse.toStaticStatement()))))
ImmutableList.of(ReturnFalse.toStaticStatement()))))
.build();
}

Expand Down Expand Up @@ -2638,7 +2645,7 @@ private static org.batfish.datamodel.dataplane.rib.RibGroup toRibGroup(
new If(
new FirstMatchChain(policyCalls),
ImmutableList.of(Statements.ReturnTrue.toStaticStatement()),
ImmutableList.of(Statements.ReturnFalse.toStaticStatement()))))
ImmutableList.of(ReturnFalse.toStaticStatement()))))
.build();
return new org.batfish.datamodel.dataplane.rib.RibGroup(
rg.getName(), importRibs, policyName, exportRib);
Expand Down Expand Up @@ -2751,6 +2758,33 @@ private PacketPolicy toPacketPolicy(ConcreteFirewallFilter filter) {
return new PacketPolicy(filter.getName(), builder.build(), new Return(Drop.instance()));
}

private @Nonnull RoutingPolicy toRoutingPolicy(@Nonnull Condition condition) {
String name = computeConditionRoutingPolicyName(condition.getName());
RoutingPolicy rp = new RoutingPolicy(name, _c);
If top = new If();
top.getTrueStatements().add(ReturnTrue.toStaticStatement());
top.getFalseStatements().add(ReturnFalse.toStaticStatement());
top.setGuard(toBooleanExpr(condition));
rp.getStatements().add(top);
return rp;
}

private @Nonnull BooleanExpr toBooleanExpr(@Nonnull Condition condition) {
IfRouteExists ifr = condition.getIfRouteExists();
if (ifr == null) {
// TODO: verify empty condition means true
return BooleanExprs.TRUE;
}
Prefix prefix = ifr.getPrefix();
if (prefix == null) {
// TODO: verify missing prefix means true
return BooleanExprs.TRUE;
}
// TODO: handle table
// TODO: implement in VI
return BooleanExprs.FALSE;
}

private RoutingPolicy toRoutingPolicy(PolicyStatement ps) {
// Ensure map of VRFs referenced in routing policies is initialized
if (_vrfReferencesInPolicies == null) {
Expand Down Expand Up @@ -2832,6 +2866,10 @@ private BooleanExpr toGuard(PsFroms froms) {
if (!froms.getFromCommunities().isEmpty()) {
conj.getConjuncts().add(new Disjunction(toBooleanExprs(froms.getFromCommunities())));
}
if (!froms.getFromConditions().isEmpty()) {
// TODO: verify these are disjoined
conj.getConjuncts().add(new Disjunction(toBooleanExprs(froms.getFromConditions())));
}
if (froms.getFromFamily() != null) {
conj.getConjuncts().add(froms.getFromFamily().toBooleanExpr(this, _c, _w));
}
Expand Down Expand Up @@ -3042,6 +3080,7 @@ private void processLogicalSystemConfiguration(
_masterLogicalSystem.setNatStatic(ls.getNatStatic());
// TODO: something with NTP servers?
_masterLogicalSystem.getPolicyStatements().putAll(ls.getPolicyStatements());
_masterLogicalSystem.getConditions().putAll(ls.getConditions());
_masterLogicalSystem.getPrefixLists().putAll(ls.getPrefixLists());
_masterLogicalSystem.getRouteFilters().putAll(ls.getRouteFilters());
_masterLogicalSystem.getRoutingInstances().clear();
Expand Down Expand Up @@ -3174,6 +3213,15 @@ private Configuration toVendorIndependentConfiguration() throws VendorConversion
// convert interfaces. Before policies because some policies depend on interfaces
convertInterfaces();

// convert conditions to RoutingPolicy objects
_masterLogicalSystem
.getConditions()
.forEach(
(conditionName, condition) -> {
RoutingPolicy rp = toRoutingPolicy(condition);
_c.getRoutingPolicies().put(rp.getName(), rp);
});

// convert policy-statements to RoutingPolicy objects
for (Entry<String, PolicyStatement> e : _masterLogicalSystem.getPolicyStatements().entrySet()) {
String name = e.getKey();
Expand Down Expand Up @@ -3468,6 +3516,7 @@ private Configuration toVendorIndependentConfiguration() throws VendorConversion
JuniperStructureUsage.POLICY_STATEMENT_THEN_ADD_COMMUNITY,
JuniperStructureUsage.POLICY_STATEMENT_THEN_DELETE_COMMUNITY,
JuniperStructureUsage.POLICY_STATEMENT_THEN_SET_COMMUNITY);
markConcreteStructure(JuniperStructureType.CONDITION);
markConcreteStructure(
JuniperStructureType.FIREWALL_FILTER,
JuniperStructureUsage.INTERFACE_FILTER,
Expand Down

0 comments on commit e2c2c78

Please sign in to comment.