Skip to content

Commit

Permalink
AclIpSpace: flatten if possible during union (#3609)
Browse files Browse the repository at this point in the history
Makes `union(union(a, b), c)` equivalent to `union(a, b, c)` instead of nested.

Concerns that this may hurt forwarding analysis caching, but in practice we've
seen little difference, maybe improvement, in computation time.
  • Loading branch information
dhalperi committed Apr 15, 2019
1 parent 62d18b7 commit aa63673
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,26 @@ public static Builder rejecting(Iterable<IpSpace> ipSpaces) {
return union(Arrays.asList(ipSpaces));
}

/**
* When an {@link AclIpSpace} is a pure union (list of only permit lines), flattens it into the
* permitted spaces.
*
* <p>This function makes {@code union(union(a, b), c)} equivalent to {@code union(a, b, c)}.
*/
private static Stream<IpSpace> flattenAclIpSpacesForUnion(IpSpace space) {
if (!(space instanceof AclIpSpace)) {
return Stream.of(space);
}
AclIpSpace aclSpace = (AclIpSpace) space;
List<AclIpSpaceLine> lines = aclSpace.getLines();
if (lines.stream().allMatch(l -> l.getAction() == LineAction.PERMIT)) {
// This is just a big union, flatten it into the list of spaces it unions.
return lines.stream().map(AclIpSpaceLine::getIpSpace);
}
// Not a pure union, so don't flatten.
return Stream.of(aclSpace);
}

/**
* Set-theoretic union of multiple {@link IpSpace IP spaces}.<br>
* {@code null} ipSpaces are ignored. If all arguments are {@code null}, returns {@code null}.
Expand All @@ -225,6 +245,7 @@ public static Builder rejecting(Iterable<IpSpace> ipSpaces) {
IpSpace[] nonNullSpaces =
StreamSupport.stream(ipSpaces.spliterator(), false)
.filter(Objects::nonNull)
.flatMap(AclIpSpace::flattenAclIpSpacesForUnion)
.toArray(IpSpace[]::new);
if (nonNullSpaces.length == 0) {
// no constraint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ public void testUnion() {
assertThat(union(EmptyIpSpace.INSTANCE, ipSpace), equalTo(ipSpace));
}

@Test
public void testUnionNested() {
IpIpSpace a = Ip.parse("1.2.3.4").toIpSpace();
IpIpSpace b = Ip.parse("1.2.3.5").toIpSpace();
IpIpSpace c = Ip.parse("1.2.3.6").toIpSpace();
assertThat(union(a, b, c), equalTo(union(union(a, b), c)));
assertThat(union(a, b, c), equalTo(union(a, union(b, c))));
}

@Test
public void testStopWhenEmpty() {
IpSpace space =
Expand Down
52 changes: 18 additions & 34 deletions tests/parsing-tests/unit-tests-nodes.ref
Original file line number Diff line number Diff line change
Expand Up @@ -20491,23 +20491,15 @@
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.AclIpSpace",
"lines" : [
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.4"
}
},
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.5"
}
}
]
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.4"
}
},
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.5"
}
},
{
Expand Down Expand Up @@ -20597,23 +20589,15 @@
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.AclIpSpace",
"lines" : [
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.4"
}
},
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.5"
}
}
]
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.4"
}
},
{
"action" : "PERMIT",
"ipSpace" : {
"class" : "org.batfish.datamodel.IpWildcardIpSpace",
"ipWildcard" : "1.2.3.5"
}
},
{
Expand Down

0 comments on commit aa63673

Please sign in to comment.