Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOS:Advertise ConnectedRoute when redistributing between different EIGRP #8590

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Expand Up @@ -9,6 +9,7 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.batfish.datamodel.eigrp.EigrpMetric;
import org.batfish.datamodel.route.nh.NextHopInterface;

/**
Expand All @@ -18,17 +19,34 @@
@ParametersAreNonnullByDefault
public final class ConnectedRoute extends AbstractRoute {

static final String PROP_EIGRP_METRIC = "eigrp-metric";
static final String PROP_PROCESS_ASN = "process-asn";

/** AS number of the EIGRP process that installed this route in the RIB */
@Nullable final long _processAsn;

@Nonnull final EigrpMetric _metric;

@JsonCreator
@SuppressWarnings("unused")
private static ConnectedRoute create(
@Nullable @JsonProperty(PROP_NETWORK) Prefix network,
@Nullable @JsonProperty(PROP_NEXT_HOP_INTERFACE) String nextHopInterface,
@Nullable @JsonProperty(PROP_NEXT_HOP_IP) String nextHopIp,
@JsonProperty(PROP_ADMINISTRATIVE_COST) int adminCost,
@JsonProperty(PROP_TAG) long tag) {
@JsonProperty(PROP_TAG) long tag,
@Nullable @JsonProperty(PROP_EIGRP_METRIC) EigrpMetric metric,
@Nullable @JsonProperty(PROP_PROCESS_ASN) Long processAsn) {
checkArgument(network != null, "Cannot create connected route: missing %s", PROP_NETWORK);
checkArgument(
processAsn != null, "Cannot create connected route: missing %s", PROP_PROCESS_ASN);
return new ConnectedRoute(
network, firstNonNull(nextHopInterface, Route.UNSET_NEXT_HOP_INTERFACE), adminCost, tag);
network,
firstNonNull(nextHopInterface, Route.UNSET_NEXT_HOP_INTERFACE),
adminCost,
tag,
metric,
processAsn);
}

/** Create a connected route with admin cost of 0 */
Expand All @@ -40,6 +58,17 @@ public ConnectedRoute(Prefix network, String nextHopInterface, int adminCost) {
this(network, nextHopInterface, adminCost, Route.UNSET_ROUTE_TAG);
}

@JsonProperty(PROP_EIGRP_METRIC)
@Nonnull
public final EigrpMetric getEigrpMetric() {
return _metric;
}

@JsonProperty(PROP_PROCESS_ASN)
public long getProcessAsn() {
return _processAsn;
}

@Override
public String toString() {
return "ConnectedRoute{"
Expand All @@ -49,12 +78,28 @@ public String toString() {
+ _admin
+ ", _tag="
+ _tag
+ ", _metric"
+ _metric
+ ", _processAsn="
+ _processAsn
+ '}';
}

public ConnectedRoute(Prefix network, String nextHopInterface, int adminCost, long tag) {
this(network, nextHopInterface, adminCost, tag, null, -1);
}

public ConnectedRoute(
Prefix network,
String nextHopInterface,
int adminCost,
long tag,
@Nullable EigrpMetric metric,
long processAsn) {
super(network, adminCost, tag, false, false);
_metric = metric;
_nextHop = NextHopInterface.of(nextHopInterface);
_processAsn = processAsn;
}

@Override
Expand All @@ -69,6 +114,8 @@ public RoutingProtocol getProtocol() {

/** Builder for {@link ConnectedRoute} */
public static final class Builder extends AbstractRouteBuilder<Builder, ConnectedRoute> {
@Nullable protected Long _processAsn;
@Nullable protected EigrpMetric _eigrpMetric;

@Nonnull
@Override
Expand All @@ -77,8 +124,28 @@ public ConnectedRoute build() {
_nextHop != null && _nextHop instanceof NextHopInterface,
"ConnectedRoute must have %s",
PROP_NEXT_HOP_INTERFACE);
if (_eigrpMetric == null || _processAsn == null) {
return new ConnectedRoute(
getNetwork(), ((NextHopInterface) _nextHop).getInterfaceName(), getAdmin(), getTag());
}

return new ConnectedRoute(
getNetwork(), ((NextHopInterface) _nextHop).getInterfaceName(), getAdmin(), getTag());
getNetwork(),
((NextHopInterface) _nextHop).getInterfaceName(),
getAdmin(),
getTag(),
_eigrpMetric,
_processAsn);
}

public Builder setProcessAsn(@Nullable Long processAsn) {
_processAsn = processAsn;
return this;
}

public Builder setEigrpMetric(@Nonnull EigrpMetric metric) {
_eigrpMetric = metric;
return this;
}

@Nonnull
Expand Down
Expand Up @@ -3,6 +3,7 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Objects;
import org.batfish.datamodel.ConnectedRoute;
import org.batfish.datamodel.EigrpRoute;
import org.batfish.datamodel.routing_policy.Environment;
import org.batfish.datamodel.routing_policy.Result;
Expand All @@ -29,11 +30,15 @@ public <T, U> T accept(BooleanExprVisitor<T, U> visitor, U arg) {

@Override
public Result evaluate(Environment environment) {
if (!(environment.getOriginalRoute() instanceof EigrpRoute)) {
return new Result(false);
if (environment.getOriginalRoute() instanceof EigrpRoute) {
EigrpRoute route = (EigrpRoute) environment.getOriginalRoute();
return new Result(route.getProcessAsn() == _asn);
} else if (environment.getOriginalRoute() instanceof ConnectedRoute) {
ConnectedRoute route = (ConnectedRoute) environment.getOriginalRoute();
return new Result(route.getProcessAsn() == _asn);
}
EigrpRoute route = (EigrpRoute) environment.getOriginalRoute();
return new Result(route.getProcessAsn() == _asn);

return new Result(false);
}

@Override
Expand Down
Expand Up @@ -32,6 +32,7 @@
import org.batfish.datamodel.AnnotatedRoute;
import org.batfish.datamodel.ConcreteInterfaceAddress;
import org.batfish.datamodel.Configuration;
import org.batfish.datamodel.ConnectedRoute;
import org.batfish.datamodel.EigrpExternalRoute;
import org.batfish.datamodel.EigrpInternalRoute;
import org.batfish.datamodel.EigrpRoute;
Expand Down Expand Up @@ -573,6 +574,9 @@ private EigrpExternalRoute computeEigrpExportRoute(
// Set the metric to match the route metric by default for EIGRP into EIGRP
if (unannotatedPotentialRoute instanceof EigrpRoute) {
outputRouteBuilder.setEigrpMetric(((EigrpRoute) unannotatedPotentialRoute).getEigrpMetric());
} else if (unannotatedPotentialRoute instanceof ConnectedRoute) {
outputRouteBuilder.setEigrpMetric(
((ConnectedRoute) unannotatedPotentialRoute).getEigrpMetric());
}

if (!exportPolicy.process(potentialExportRoute, outputRouteBuilder, _process, Direction.OUT)) {
Expand Down
Expand Up @@ -90,6 +90,7 @@
import org.batfish.datamodel.collections.NodeInterfacePair;
import org.batfish.datamodel.dataplane.rib.RibGroup;
import org.batfish.datamodel.dataplane.rib.RibId;
import org.batfish.datamodel.eigrp.EigrpInterfaceSettings;
import org.batfish.datamodel.isis.IsisEdge;
import org.batfish.datamodel.isis.IsisInterfaceLevelSettings;
import org.batfish.datamodel.isis.IsisInterfaceMode;
Expand Down Expand Up @@ -794,7 +795,7 @@ private static Stream<ConnectedRoute> generateConnectedRoutes(@Nonnull Interface
.map(
addr ->
generateConnectedRoute(
addr, iface.getName(), iface.getAddressMetadata().get(addr)));
addr, iface.getName(), iface.getAddressMetadata().get(addr), iface.getEigrp()));
}

/**
Expand All @@ -820,6 +821,16 @@ static ConnectedRoute generateConnectedRoute(
@Nonnull ConcreteInterfaceAddress address,
@Nonnull String ifaceName,
@Nullable ConnectedRouteMetadata metadata) {
return generateConnectedRoute(address, ifaceName, metadata, null);
}

@VisibleForTesting
@Nonnull
static ConnectedRoute generateConnectedRoute(
@Nonnull ConcreteInterfaceAddress address,
@Nonnull String ifaceName,
@Nullable ConnectedRouteMetadata metadata,
@Nullable EigrpInterfaceSettings eigrp) {
ConnectedRoute.Builder builder =
ConnectedRoute.builder().setNetwork(address.getPrefix()).setNextHopInterface(ifaceName);
if (metadata != null) {
Expand All @@ -830,6 +841,10 @@ static ConnectedRoute generateConnectedRoute(
builder.setTag(metadata.getTag());
}
}
if (eigrp != null) {
builder.setProcessAsn(eigrp.getAsn());
builder.setEigrpMetric(eigrp.getMetric());
}
return builder.build();
}

Expand Down
Expand Up @@ -1272,7 +1272,9 @@ private static If convertEigrpRedistributionPolicy(
Conjunction eigrpExportConditions = new Conjunction();
BooleanExpr matchExpr;
if (protocol == RoutingProtocol.EIGRP) {
matchExpr = new MatchProtocol(RoutingProtocol.EIGRP, RoutingProtocol.EIGRP_EX);
matchExpr =
new MatchProtocol(
RoutingProtocol.EIGRP, RoutingProtocol.EIGRP_EX, RoutingProtocol.CONNECTED);

Long otherAsn =
(Long) policy.getSpecialAttributes().get(EigrpRedistributionPolicy.EIGRP_AS_NUMBER);
Expand Down
Expand Up @@ -16,6 +16,7 @@
import org.batfish.datamodel.Ip;
import org.batfish.datamodel.Prefix;
import org.batfish.datamodel.eigrp.ClassicMetric;
import org.batfish.datamodel.eigrp.EigrpMetric;
import org.batfish.datamodel.eigrp.EigrpMetricValues;
import org.batfish.datamodel.eigrp.EigrpMetricVersion;
import org.batfish.datamodel.eigrp.EigrpProcess;
Expand Down Expand Up @@ -96,13 +97,20 @@ public void setUp() {

@Test
public void testRedistributeNoPolicy() {
EigrpMetric originalMetric =
ClassicMetric.builder()
.setValues(EigrpMetricValues.builder().setBandwidth(2e9).setDelay(4e5).build())
.build();

// Do not crash
_routingProcess.redistribute(
RibDelta.adding(
new AnnotatedRoute<>(
ConnectedRoute.builder()
.setNetwork(Prefix.parse("1.1.1.0/24"))
.setNextHopInterface("Eth0")
.setProcessAsn(10L)
.setEigrpMetric(originalMetric)
.build(),
"vrf")));
}
Expand Down
Expand Up @@ -72,6 +72,8 @@
import org.batfish.datamodel.VrfLeakConfig;
import org.batfish.datamodel.bgp.BgpTopology;
import org.batfish.datamodel.eigrp.ClassicMetric;
import org.batfish.datamodel.eigrp.EigrpInterfaceSettings;
import org.batfish.datamodel.eigrp.EigrpMetric;
import org.batfish.datamodel.eigrp.EigrpMetricValues;
import org.batfish.datamodel.eigrp.EigrpMetricVersion;
import org.batfish.datamodel.eigrp.EigrpTopology;
Expand Down Expand Up @@ -855,6 +857,19 @@ public void testGenerateConnectedRoute() {
String nextHopInterface = "Eth0";
ConcreteInterfaceAddress address = ConcreteInterfaceAddress.parse("1.1.1.1/24");
Prefix prefix = address.getPrefix();
EigrpMetric originalMetric =
ClassicMetric.builder()
.setValues(EigrpMetricValues.builder().setBandwidth(1d).setDelay(1d).build())
.build();
EigrpInterfaceSettings originalEigrpInterfaceSettings =
EigrpInterfaceSettings.builder()
.setAsn(10L)
.setEnabled(true)
.setExportPolicy("~EIGRP_EXPORT_POLICY_default_1_Ethernet0~")
.setImportPolicy("IMPORT-POLICY")
.setMetric(originalMetric)
.setPassive(true)
.build();

assertThat(
generateConnectedRoute(address, nextHopInterface, null),
Expand All @@ -873,6 +888,21 @@ public void testGenerateConnectedRoute() {
.setNextHopInterface(nextHopInterface)
.setTag(7L)
.build()));

assertThat(
generateConnectedRoute(
address,
nextHopInterface,
ConnectedRouteMetadata.builder().setTag(7).build(),
originalEigrpInterfaceSettings),
equalTo(
ConnectedRoute.builder()
.setNetwork(prefix)
.setNextHopInterface(nextHopInterface)
.setTag(7L)
.setProcessAsn(10L)
.setEigrpMetric(originalMetric)
.build()));
}

@Test
Expand Down