+ assertArrayEquals(INPUT_BYTES.get(6), ByteArray.readAllBytes(buffer));
+ }
+
+ /*
+ * Tests IPv4 NEXT_HOP, ATOMIC_AGGREGATE, COMMUNITY, NLRI with multiple paths.
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 60 <- length (96) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 31 <- total path attribute length (49)
+ * 40 <- attribute flags
+ * 01 <- attribute type code (origin)
+ * 01 <- attribute length
+ * 00 <- Origin value (IGP)
+ * 40 <- attribute flags
+ * 02 <- attribute type code (as path)
+ * 06 <- attribute length
+ * 02 <- AS_SEQUENCE
+ * 01 <- path segment count
+ * 00 00 fd ea <- path segment value (65002)
+ * 40 <- attribute flags
+ * 03 <- attribute type code (Next Hop)
+ * 04 <- attribute length
+ * 0a 00 00 02 <- value (10.0.0.2)
+ * 80 <- attribute flags
+ * 04 <- attribute type code (multi exit disc)
+ * 04 <- attribute length
+ * 00 00 00 00 <- value
+ * 40 <- attribute flags
+ * 06 <- attribute type code (atomic aggregate)
+ * 00 <- attribute length
+ * C0 <- attribute flags
+ * 08 <- attribute type code (community)
+ * 10 <- attribute length
+ * FF FF FF 01 <- value (NO_EXPORT)
+ * FF FF FF 02 <- value (NO_ADVERTISE)
+ * FF FF FF 03 <- value (NO_EXPORT_SUBCONFED)
+ * FF FF FF 10 <- unknown Community
+ *
+ * //NLRI
+ * 00 00 00 01 <- path-id (1)
+ * 18 ac 11 02 <- IPv4 Prefix (172.17.1.0 / 24)
+ * 00 00 00 01 <- path-id (2)
+ * 18 ac 11 01 <- IPv4 Prefix (172.17.1.0 / 24)
+ * 00 00 00 01 <- path-id (1)
+ * 18 ac 11 00 <- IPv4 Prefix (172.17.0.0 / 24)
+ */
+ @Test
+ public void testUpdateMessageNlriAddPath() throws Exception {
+ final byte[] body = ByteArray.cutBytes(updatesWithMultiplePath.get(0), MessageUtil.COMMON_HEADER_LENGTH);
+ final int messageLength = ByteArray.bytesToInt(ByteArray.subByte(updatesWithMultiplePath.get(0),
+ MessageUtil.MARKER_LENGTH, LENGTH_FIELD_LENGTH));
+ final Update message = BGPParserTest.updateParser.parseMessageBody(Unpooled.copiedBuffer(body), messageLength,
+ mpConstraint);
+
+ // check fields
+
+ assertNull(message.getWithdrawnRoutes());
+
+ // attributes
+ final List<AsNumber> asNumbers = new ArrayList<>();
+ asNumbers.add(new AsNumber(Uint32.valueOf(65002)));
+ final List<Segments> asPath = new ArrayList<>();
+ asPath.add(new SegmentsBuilder().setAsSequence(asNumbers).build());
+
+ final Ipv4NextHopCase nextHop = new Ipv4NextHopCaseBuilder().setIpv4NextHop(
+ new Ipv4NextHopBuilder().setGlobal(new Ipv4Address("10.0.0.2")).build()).build();
+
+ final List<Communities> comms = new ArrayList<>();
+ comms.add((Communities) CommunityUtil.NO_EXPORT);
+ comms.add((Communities) CommunityUtil.NO_ADVERTISE);
+ comms.add((Communities) CommunityUtil.NO_EXPORT_SUBCONFED);
+ comms.add((Communities) CommunityUtil.create(NoopReferenceCache.getInstance(), 0xFFFF, 0xFF10));
+
+ final UpdateBuilder builder = new UpdateBuilder();
+
+ // check nlri
+
+ final List<Nlri> nlris = new ArrayList<>();
+ nlris.add(new NlriBuilder().setPrefix(new Ipv4Prefix("172.17.1.0/24")).setPathId(new PathId(Uint32.ONE))
+ .build());
+ nlris.add(new NlriBuilder().setPrefix(new Ipv4Prefix("172.17.1.0/24")).setPathId(new PathId(Uint32.valueOf(2)))
+ .build());
+ nlris.add(new NlriBuilder().setPrefix(new Ipv4Prefix("172.17.0.0/24")).setPathId(new PathId(Uint32.ONE))
+ .build());
+
+ assertEquals(nlris, message.getNlri());
+
+ builder.setNlri(nlris);
+
+ // check path attributes
+
+ final Attributes attrs = message.getAttributes();
+
+ final AttributesBuilder paBuilder = new AttributesBuilder();
+
+ paBuilder.setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build());
+ assertEquals(paBuilder.getOrigin(), attrs.getOrigin());
+
+ paBuilder.setAsPath(new AsPathBuilder().setSegments(asPath).build());
+ assertEquals(paBuilder.getAsPath(), attrs.getAsPath());
+
+ paBuilder.setCNextHop(nextHop);
+ assertEquals(paBuilder.getCNextHop(), attrs.getCNextHop());
+
+ paBuilder.setMultiExitDisc(new MultiExitDiscBuilder().setMed(Uint32.ZERO).build());
+ assertEquals(paBuilder.getMultiExitDisc(), attrs.getMultiExitDisc());
+
+ paBuilder.setAtomicAggregate(new AtomicAggregateBuilder().build());
+ assertEquals(paBuilder.getAtomicAggregate(), attrs.getAtomicAggregate());
+
+ paBuilder.setCommunities(comms);
+ assertEquals(paBuilder.getCommunities(), attrs.getCommunities());
+
+ paBuilder.setUnrecognizedAttributes(Collections.emptyList());
+
+ builder.setAttributes(paBuilder.build());
+
+ assertEquals(builder.build(), message);
+
+ final ByteBuf buffer = Unpooled.buffer();
+ BGPParserTest.updateParser.serializeMessage(message, buffer);
+ assertArrayEquals(updatesWithMultiplePath.get(0), ByteArray.readAllBytes(buffer));
+ }
+
+ /*
+ * Tests withdrawn routes with multiple paths.
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 29 <- length (41) - including header
+ * 02 <- message type
+ * 00 12 <- withdrawn routes length (18)
+ * 00 00 00 01 <- path-id (1)
+ * 1e ac 10 00 04 <- route (172.16.0.4)
+ * 00 00 00 02 <- path-id (2)
+ * 1e ac 10 00 04 <- route (172.16.0.4)
+ * 00 00 <- total path attribute length
+ *
+ */
+ @Test
+ public void testUpdateMessageWithdrawAddPath() throws Exception {
+ final byte[] body = ByteArray.cutBytes(updatesWithMultiplePath.get(1), MessageUtil.COMMON_HEADER_LENGTH);
+ final int messageLength = ByteArray.bytesToInt(ByteArray.subByte(updatesWithMultiplePath.get(1),
+ MessageUtil.MARKER_LENGTH, LENGTH_FIELD_LENGTH));
+ final Update message = BGPParserTest.updateParser.parseMessageBody(Unpooled.copiedBuffer(body), messageLength,
+ mpConstraint);
+
+ // attributes
+ final List<WithdrawnRoutes> withdrawnRoutes = new ArrayList<>();
+ withdrawnRoutes.add(new WithdrawnRoutesBuilder().setPrefix(new Ipv4Prefix("172.16.0.4/30"))
+ .setPathId(new PathId(Uint32.ONE)).build());
+ withdrawnRoutes.add(new WithdrawnRoutesBuilder().setPrefix(new Ipv4Prefix("172.16.0.4/30"))
+ .setPathId(new PathId(Uint32.valueOf(2))).build());
+
+ // check API message
+ final Update expectedMessage = new UpdateBuilder().setWithdrawnRoutes(withdrawnRoutes).build();
+
+ assertEquals(expectedMessage.getWithdrawnRoutes(), message.getWithdrawnRoutes());
+
+ final ByteBuf buffer = Unpooled.buffer();
+ BGPParserTest.updateParser.serializeMessage(message, buffer);
+ assertArrayEquals(updatesWithMultiplePath.get(1), ByteArray.readAllBytes(buffer));
+ }
+
+ /*
+ * Tests withdrawn routes with malformed attribute.
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 35 <- length (53) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 1a <- total path attribute length (26)
+ * 40 <- attribute flags
+ * 01 <- attribute type code (origin)
+ * 02 <- WRONG attribute length
+ * 00 <- Origin value (IGP)
+ * 40 <- attribute flags
+ * 03 <- attribute type code (Next Hop)
+ * 04 <- attribute length
+ * 0a 00 00 02 <- value (10.0.0.2)
+ * 40 <- attribute flags
+ * 0e <- attribute type code (MP_REACH)
+ * 00 01 <- AFI (Ipv4)
+ * 01 <- SAFI (Unicast)
+ * 04 <- next hop length
+ * ff ff ff ff <- next hop
+ * 00 <- reserved
+ * 18 <- length
+ * 0a 00 01 <- prefix (10.0.1.0)
+ * //NLRI
+ * 18 <- length
+ * 0a 00 02 <- prefix (10.0.2.0)
+ */
+ @Test
+ public void testUpdateMessageWithMalformedAttribute() throws BGPDocumentedException {
+ final byte[] body = ByteArray.cutBytes(INPUT_BYTES.get(7), MessageUtil.COMMON_HEADER_LENGTH);
+ final int messageLength = ByteArray.bytesToInt(ByteArray.subByte(INPUT_BYTES.get(6), MessageUtil.MARKER_LENGTH,
+ LENGTH_FIELD_LENGTH));
+ final PeerSpecificParserConstraintImpl constraint = new PeerSpecificParserConstraintImpl();
+ constraint.addPeerConstraint(RevisedErrorHandlingSupport.class,
+ RevisedErrorHandlingSupportImpl.forExternalPeer());
+ final Update message = BGPParserTest.updateParser.parseMessageBody(Unpooled.copiedBuffer(body), messageLength,
+ constraint);
+ assertNotNull(message);
+ assertNull(message.getNlri());
+ final List<WithdrawnRoutes> withdrawnRoutes = message.getWithdrawnRoutes();
+ assertNotNull(withdrawnRoutes);
+ assertEquals(1, withdrawnRoutes.size());