Skip to content

Commit

Permalink
Arista EOS validate vlan and vni numbers during extraction (#8220)
Browse files Browse the repository at this point in the history
Follow-on to #8197
  • Loading branch information
arifogel committed Apr 6, 2022
1 parent 1acef90 commit fee133c
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,8 @@
public class AristaControlPlaneExtractor extends AristaParserBaseListener
implements SilentSyntaxListener, ControlPlaneExtractor {
private static final IntegerSpace ADMIN_DISTANCE_SPACE = IntegerSpace.of(Range.closed(1, 255));
private static final IntegerSpace VLAN_RANGE = IntegerSpace.of(Range.closed(1, 4094));
private static final IntegerSpace VNI_RANGE = IntegerSpace.of(Range.closed(1, 16777215));

@Override
public String getInputText() {
Expand Down Expand Up @@ -1037,12 +1039,13 @@ private static int toInteger(Token t) {
return Integer.parseInt(t.getText());
}

private static int toInteger(Vlan_idContext ctx) {
return Integer.parseInt(ctx.getText());
private @Nonnull Optional<Integer> toInteger(ParserRuleContext messageCtx, Vlan_idContext ctx) {
return toIntegerInSpace(messageCtx, ctx, VLAN_RANGE, "VLAN number");
}

private static int toInteger(Vni_numberContext ctx) {
return Integer.parseInt(ctx.getText());
private @Nonnull Optional<Integer> toInteger(
ParserRuleContext messageCtx, Vni_numberContext ctx) {
return toIntegerInSpace(messageCtx, ctx, VNI_RANGE, "VNI number");
}

private static String toInterfaceName(Interface_nameContext ctx) {
Expand Down Expand Up @@ -1139,26 +1142,56 @@ private static SubRange toSubRange(SubrangeContext ctx) {
}
}

private static SubRange toSubRange(Vlan_subrangeContext ctx) {
// TODO: validate values
int low = toInteger(ctx.low);
if (ctx.DASH() != null) {
int high = toInteger(ctx.high);
return new SubRange(low, high);
} else {
return SubRange.singleton(low);
private @Nonnull Optional<SubRange> toSubRange(
ParserRuleContext messageCtx, Vlan_subrangeContext ctx) {
Optional<Integer> maybeLow = toInteger(messageCtx, ctx.low);
if (!maybeLow.isPresent()) {
// already warned
return Optional.empty();
}
int low = maybeLow.get();
if (ctx.high == null) {
return Optional.of(SubRange.singleton(low));
}
Optional<Integer> maybeHigh = toInteger(messageCtx, ctx.high);
if (!maybeHigh.isPresent()) {
// already warned
return Optional.empty();
}
int high = maybeHigh.get();
if (low > high) {
warn(
messageCtx,
String.format("Invalid VLAN range with high VLAN < low VLAN: %s", getFullText(ctx)));
return Optional.empty();
}
return Optional.of(new SubRange(low, high));
}

private static SubRange toSubRange(Vni_subrangeContext ctx) {
// TODO: validate values
int low = toInteger(ctx.low);
if (ctx.DASH() != null) {
int high = toInteger(ctx.high);
return new SubRange(low, high);
} else {
return SubRange.singleton(low);
private @Nonnull Optional<SubRange> toSubRange(
ParserRuleContext messageCtx, Vni_subrangeContext ctx) {
Optional<Integer> maybeLow = toInteger(messageCtx, ctx.low);
if (!maybeLow.isPresent()) {
// already warned
return Optional.empty();
}
int low = maybeLow.get();
if (ctx.high == null) {
return Optional.of(SubRange.singleton(low));
}
Optional<Integer> maybeHigh = toInteger(messageCtx, ctx.high);
if (!maybeHigh.isPresent()) {
// already warned
return Optional.empty();
}
int high = maybeHigh.get();
if (low > high) {
warn(
messageCtx,
String.format("Invalid VNI range with high VNI < low VNI: %s", getFullText(ctx)));
return Optional.empty();
}
return Optional.of(new SubRange(low, high));
}

private static String unquote(String text) {
Expand Down Expand Up @@ -3546,29 +3579,27 @@ public void exitEos_vxif_vxlan_udp_port(Eos_vxif_vxlan_udp_portContext ctx) {

@Override
public void enterEos_vxif_vxlan_vlan_vni_range(Eos_vxif_vxlan_vlan_vni_rangeContext ctx) {
List<Integer> vnis = new ArrayList<>();
List<Integer> vlans = new ArrayList<>();

List<SubRange> vlanRange =
ctx.vlans.vlan_range_list.stream()
.map(AristaControlPlaneExtractor::toSubRange)
.collect(Collectors.toList());

for (SubRange subRange : vlanRange) {
for (int i = subRange.getStart(); i <= subRange.getEnd(); i++) {
vlans.add(i);
ImmutableList.Builder<Integer> vlansBuilder = ImmutableList.builder();
for (Vlan_subrangeContext rangeCtx : ctx.vlans.vlan_range_list) {
Optional<SubRange> maybeRange = toSubRange(ctx, rangeCtx);
if (!maybeRange.isPresent()) {
// already warned
return;
}
maybeRange.get().asStream().forEach(vlansBuilder::add);
}
List<SubRange> vniRange =
ctx.vnis.vni_range_list.stream()
.map(AristaControlPlaneExtractor::toSubRange)
.collect(Collectors.toList());
List<Integer> vlans = vlansBuilder.build();

for (SubRange subRange : vniRange) {
for (int i = subRange.getStart(); i <= subRange.getEnd(); i++) {
vnis.add(i);
ImmutableList.Builder<Integer> vnisBuilder = ImmutableList.builder();
for (Vni_subrangeContext rangeCtx : ctx.vnis.vni_range_list) {
Optional<SubRange> maybeRange = toSubRange(ctx, rangeCtx);
if (!maybeRange.isPresent()) {
// already warned
return;
}
maybeRange.get().asStream().forEach(vnisBuilder::add);
}
List<Integer> vnis = vnisBuilder.build();

if (vlans.size() != vnis.size()) {
warn(ctx, "Need to have 1:1 mapping of vlan to vni");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,16 @@ public void testVxlanVniNewSyntax() {
AristaConfiguration config = parseVendorConfig("arista_vxlan_new_syntax_invalid");
assertThat(
config.getWarnings().getParseWarnings(),
contains(hasComment("Need to have 1:1 mapping of vlan to vni")));
containsInAnyOrder(
hasComment("Need to have 1:1 mapping of vlan to vni"),
hasComment("Expected VLAN number in range 1-4094, but got '0'"),
hasComment("Expected VLAN number in range 1-4094, but got '0'"),
hasComment("Expected VLAN number in range 1-4094, but got '4095'"),
hasComment("Invalid VLAN range with high VLAN < low VLAN: 2-1"),
hasComment("Expected VNI number in range 1-16777215, but got '0'"),
hasComment("Expected VNI number in range 1-16777215, but got '0'"),
hasComment("Expected VNI number in range 1-16777215, but got '16777216'"),
hasComment("Invalid VNI range with high VNI < low VNI: 2-1")));
assertThat(config.getEosVxlan().getVlanVnis(), anEmptyMap());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,33 @@ hostname arista_vxlan_new_syntax
!
interface Vxlan1
vxlan udp-port 4789
! New Syntax
! invalid size not equal (test absence of key `12`)
! New Syntax
! invalid size not equal (test absence of key `12`)
vxlan vlan 12 vni 13,14

! invalid: vlan out of range
vxlan vlan 0 vni 1

! invalid: low vlan out of range
vxlan vlan 0-1 vni 1-2

! invalid: high vlan out of range
vxlan vlan 4094-4095 vni 1-2

! invalid: reversed vlan range
vxlan vlan 2-1 vni 1-2

! invalid: vni out of range
vxlan vlan 1 vni 0

! invalid: low vni out of range
vxlan vlan 1-2 vni 0-1

! invalid: high vni out of range
vxlan vlan 1-2 vni 16777215-16777216

! invalid: reversed vni range
vxlan vlan 1-2 vni 2-1

!
no ip routing

0 comments on commit fee133c

Please sign in to comment.