X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=bgp%2Fparser-impl%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fprotocol%2Fbgp%2Fparser%2Fimpl%2FParserTest.java;h=75577bff2a00e4e81f2fddaaa6eaacc322c77329;hb=0fdeddbe3d072a88428599421191f0f60b2864e4;hp=0ff66fc6d5a08f75103bca5b21925de22b2f04ef;hpb=45557b1279fddda785387d0b60a517d0941a2ae2;p=bgpcep.git diff --git a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ParserTest.java b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ParserTest.java index 0ff66fc6d5..75577bff2a 100644 --- a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ParserTest.java +++ b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ParserTest.java @@ -7,296 +7,407 @@ */ package org.opendaylight.protocol.bgp.parser.impl; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.junit.matchers.JUnitMatchers.containsString; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - import org.junit.BeforeClass; import org.junit.Test; import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; import org.opendaylight.protocol.bgp.parser.BGPError; -import org.opendaylight.protocol.bgp.parser.BGPMessageFactory; -import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl; -import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactoryImpl; +import org.opendaylight.protocol.bgp.parser.BGPParsingException; +import org.opendaylight.protocol.bgp.parser.impl.message.update.NextHopAttributeParser; +import org.opendaylight.protocol.bgp.parser.impl.message.update.OriginAttributeParser; +import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry; import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext; -import org.opendaylight.protocol.framework.DeserializerException; -import org.opendaylight.protocol.framework.DocumentedException; import org.opendaylight.protocol.util.ByteArray; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateAddressFamily; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateSubsequentAddressFamily; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Keepalive; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.KeepaliveBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Notify; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.NotifyBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Open; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.OpenBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.ProtocolVersion; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.open.BgpParameters; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.open.BgpParametersBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.BgpTableType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.open.bgp.parameters.c.parameters.CMultiprotocolBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.open.bgp.parameters.c.parameters.c.multiprotocol.MultiprotocolCapabilityBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Keepalive; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.KeepaliveBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Notify; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.NotifyBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Open; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.OpenBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.ProtocolVersion; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Update; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.RouteRefresh; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.RouteRefreshBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.UnicastSubsequentAddressFamily; import org.opendaylight.yangtools.yang.binding.Notification; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint8; public class ParserTest { - - public static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, - (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 }; - - public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 }; - - public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 }; - - public static final byte[] openWithCpblt1 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4, - (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, - (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x40, - (byte) 0x04, (byte) 0x00, (byte) 0x47 }; - - public static final byte[] openWithCpblt2 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4, - (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, - (byte) 0x40, (byte) 0x04, (byte) 0x00, (byte) 0x47, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x00, - (byte) 0x01, (byte) 0x00, (byte) 0x01 }; - - static BGPMessageFactory factory; - - @BeforeClass - public static void setupClass() throws Exception { - factory = new BGPMessageFactoryImpl(ServiceLoaderBGPExtensionProviderContext.createConsumerContext().getMessageRegistry()); - } - - @Test - public void testHeaderErrors() throws DeserializerException, DocumentedException { - byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00 }; - wrong = ByteArray.cutBytes(wrong, 16); - try { - ParserTest.factory.parse(wrong); - fail("Exception should have occcured."); - } catch (final IllegalArgumentException e) { - assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage()); - return; - } - fail(); - } - - @Test - public void testBadMsgType() throws DeserializerException { - final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0x13, (byte) 0x08 }; - try { - ParserTest.factory.parse(bytes); - fail("Exception should have occured."); - } catch (final DocumentedException e) { - assertEquals(BGPError.BAD_MSG_TYPE, ((BGPDocumentedException) e).getError()); - return; - } - fail(); - } - - @Test - public void testKeepAliveMsg() throws DeserializerException, DocumentedException { - final Notification keepAlive = new KeepaliveBuilder().build(); - final byte[] bytes = ParserTest.factory.put(keepAlive); - assertArrayEquals(keepAliveBMsg, bytes); - - final Notification m = ParserTest.factory.parse(bytes); - - assertTrue(m instanceof Keepalive); - } - - @Test - public void testBadKeepAliveMsg() throws DeserializerException { - final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 }; - - try { - ParserTest.factory.parse(bytes); - fail("Exception should have occured."); - } catch (final DocumentedException e) { - assertThat(e.getMessage(), containsString("Message length field not within valid range.")); - assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError()); - return; - } - fail(); - } - - @Test - public void testOpenMessage() throws UnknownHostException, DeserializerException, DocumentedException { - final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion( - new ProtocolVersion((short) 4)).build(); - final byte[] bytes = ParserTest.factory.put(open); - assertArrayEquals(openBMsg, bytes); - - final Notification m = ParserTest.factory.parse(bytes); - - assertTrue(m instanceof Open); - assertEquals(100, ((Open) m).getMyAsNumber().intValue()); - assertEquals(180, ((Open) m).getHoldTimer().intValue()); - assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier()); - assertTrue(((Open) m).getBgpParameters().isEmpty()); - } - - @Test - public void testBadHoldTimeError() throws DeserializerException { - final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14, - (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 }; - - try { - ParserTest.factory.parse(bMsg); - fail("Exception should have occured."); - } catch (final DocumentedException e) { - assertEquals("Hold time value not acceptable.", e.getMessage()); - assertEquals(BGPError.HOLD_TIME_NOT_ACC, ((BGPDocumentedException) e).getError()); - return; - } - fail(); - } - - @Test - public void testBadMsgLength() throws DeserializerException { - final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff, - (byte) 0xff, (byte) 0xff }; - - try { - ParserTest.factory.parse(bMsg); - fail("Exception should have occured."); - } catch (final DocumentedException e) { - assertEquals("Open message too small.", e.getMessage()); - assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError()); - } - } - - @Test - public void testBadVersion() throws DeserializerException { - final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14, - (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 }; - - try { - ParserTest.factory.parse(bMsg); - fail("Exception should have occured."); - } catch (final DocumentedException e) { - assertEquals("BGP Protocol version 8 not supported.", e.getMessage()); - assertEquals(BGPError.VERSION_NOT_SUPPORTED, ((BGPDocumentedException) e).getError()); - return; - } - fail(); - } - - @Test - public void testNotificationMsg() throws DeserializerException, DocumentedException { - Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode( - BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build(); - byte[] bytes = ParserTest.factory.put(notMsg); - assertArrayEquals(notificationBMsg, bytes); - - Notification m = ParserTest.factory.parse(bytes); - - assertTrue(m instanceof Notify); - assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode())); - assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData()); - - notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode( - BGPError.CONNECTION_NOT_SYNC.getSubcode()).build(); - bytes = ParserTest.factory.put(notMsg); - - m = ParserTest.factory.parse(bytes); - - assertTrue(m instanceof Notify); - assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode())); - assertNull(((Notify) m).getData()); - } - - @Test - public void testWrongLength() throws DeserializerException { - final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 }; - - try { - ParserTest.factory.parse(bMsg); - fail("Exception should have occured."); - } catch (final DocumentedException e) { - assertEquals("Notification message too small.", e.getMessage()); - assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError()); - return; - } - fail(); - } - - @Test - public void testUnrecognizedError() throws DeserializerException, DocumentedException { - final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa }; - - try { - ParserTest.factory.parse(bMsg); - fail("Exception should have occured."); - } catch (final IllegalArgumentException e) { - assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage()); - return; - } - fail(); - } - - @Test - public void testTLVParser() throws UnknownHostException { - - final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class); - final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class); - - final List tlvs = Lists.newArrayList(); - - tlvs.add(new BgpParametersBuilder().setCParameters( - new CMultiprotocolBuilder().setMultiprotocolCapability( - new MultiprotocolCapabilityBuilder().setAfi(LinkstateAddressFamily.class).setSafi( - LinkstateSubsequentAddressFamily.class).build()).build()).build()); - tlvs.add(new BgpParametersBuilder().setCParameters( - new CMultiprotocolBuilder().setMultiprotocolCapability( - new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build()); - - final Map tableTypes = Maps.newHashMap(); - tableTypes.put(t1, true); - tableTypes.put(t2, true); - final Open open = new OpenBuilder().setMyAsNumber(72).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("172.20.160.170")).setVersion( - new ProtocolVersion((short) 4)).setBgpParameters(tlvs).build(); - - final byte[] result = ParserTest.factory.put(open); - - // the capabilities can be swapped. - assertTrue(Arrays.equals(openWithCpblt1, result) || Arrays.equals(openWithCpblt2, result)); - } + private static final byte[] OPEN_BMSG = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, + (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 + }; + + private static final byte[] KEEPALIVE_BMSG = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x13, (byte) 0x04 + }; + + private static final byte[] NOTIFICATION_BMSG = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 + }; + + private static final byte[] UPD_MSG_WITH_UNRECOGNIZED_ATTRIBUTE = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x79, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x62, (byte) 0x90, (byte) 0x0e, (byte) 0x00, (byte) 0x34, (byte) 0x40, (byte) 0x04, (byte) 0x47, + (byte) 0x04, (byte) 0x0a, (byte) 0x19, (byte) 0x02, (byte) 0x1b, (byte) 0x00, (byte) 0x00, (byte) 0x01, + (byte) 0x00, (byte) 0x27, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x1a, (byte) 0x02, + (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x48, (byte) 0x02, + (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x02, + (byte) 0x03, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x43, (byte) 0x40, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, + (byte) 0x40, (byte) 0x05, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte )0x64, (byte) 0x00, + (byte) 0x63, (byte) 0x19, (byte) 0x04, (byte) 0x02, (byte) 0x00, (byte) 0x08, (byte) 0x4f, (byte) 0x66, + (byte) 0x2d, (byte) 0x39, (byte) 0x6b, (byte) 0x2d, (byte) 0x30, (byte) 0x33, (byte) 0x04, (byte) 0x03, + (byte) 0x00, (byte) 0x01, (byte) 0x72, (byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x04, (byte) 0x2b, + (byte) 0x2b, (byte) 0x2b, (byte) 0x2b + }; + + // Update message with one IPv4 prefix NLRI and all mandatory path attributes present + private static final byte[] UPD_MSG_WITH_MANDATORY_ATTRIBUTES_PRESENT = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x38, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1c, (byte) 0x40, + (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x40, (byte) 0x03, + (byte) 0x04, (byte) 0x0a, (byte) 0x12, (byte) 0xa2, (byte) 0xf1, (byte) 0x80, (byte) 0x04, (byte) 0x04, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x05, (byte) 0x04, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x20, (byte) 0xc0, (byte) 0xa8, (byte) 0xfe, (byte) 0x03 + }; + + // Update message with one IPv4 prefix NLRI and all mandatory path attributes except ORIGIN present + private static final byte[] UPD_MSG_WITH_ONE_MANDATORY_ATTRIBUTE_NOT_PRESENT = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x34, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x18, (byte) 0x40, + (byte) 0x02, (byte) 0x00, (byte) 0x40, (byte) 0x03, (byte) 0x04, (byte) 0x0a, (byte) 0x12, (byte) 0xa2, + (byte) 0xf1, (byte) 0x80, (byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x40, (byte) 0x05, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x20, + (byte) 0xc0, (byte) 0xa8, (byte) 0xfe, (byte) 0x03 + }; + + // Update message with one IPv4 prefix NLRI and ORIGIN, AS_PATH and NEXT_HOP mandatory path attributes not present + private static final byte[] UPD_MSG_WITH_MULTIPLE_MANDATORY_ATTRIBUTES_NOT_PRESENT = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x2a, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0e, (byte) 0x80, + (byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x05, + (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x20, (byte) 0xc0, (byte) 0xa8, + (byte) 0xfe, (byte) 0x03 + }; + + private static final byte[] RR_MSG = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x17, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01 + }; + + private static MessageRegistry reg; + + @BeforeClass + public static void setupClass() throws Exception { + reg = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance().getMessageRegistry(); + } + + @Test + public void testHeaderErrors() throws BGPParsingException, BGPDocumentedException { + byte[] wrong = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00 + }; + wrong = ByteArray.cutBytes(wrong, 16); + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(wrong), null); + fail("Exception should have occcured."); + } catch (final IllegalArgumentException e) { + assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", + e.getMessage()); + return; + } + fail(); + } + + @Test + public void testBadMsgType() throws BGPParsingException { + final byte[] bytes = { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x13, (byte) 0x08 + }; + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals(BGPError.BAD_MSG_TYPE, e.getError()); + return; + } + fail(); + } + + @Test + public void testKeepAliveMsg() throws BGPParsingException, BGPDocumentedException { + final Notification keepAlive = new KeepaliveBuilder().build(); + final ByteBuf buffer = Unpooled.buffer(); + ParserTest.reg.serializeMessage(keepAlive, buffer); + assertArrayEquals(KEEPALIVE_BMSG, ByteArray.getAllBytes(buffer)); + + final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)), null); + assertTrue(m instanceof Keepalive); + } + + @Test + public void testBadKeepAliveMsg() throws BGPParsingException { + final byte[] bytes = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 + }; + + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertThat(e.getMessage(), containsString("Message length field not within valid range.")); + assertEquals(BGPError.BAD_MSG_LENGTH, e.getError()); + return; + } + fail(); + } + + @Test + public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException { + final Notification open = new OpenBuilder() + .setMyAsNumber(Uint16.valueOf(100)) + .setHoldTimer(Uint16.valueOf(180)) + .setBgpIdentifier(new Ipv4AddressNoZone("20.20.20.20")) + .setVersion(new ProtocolVersion(Uint8.valueOf(4))) + .build(); + final ByteBuf bytes = Unpooled.buffer(); + ParserTest.reg.serializeMessage(open, bytes); + assertArrayEquals(OPEN_BMSG, ByteArray.getAllBytes(bytes)); + + final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes), null); + assertTrue(m instanceof Open); + + final Open mo = (Open) m; + assertEquals(100, mo.getMyAsNumber().intValue()); + assertEquals(180, mo.getHoldTimer().intValue()); + assertEquals(new Ipv4Address("20.20.20.20"), mo.getBgpIdentifier()); + assertTrue(mo.getBgpParameters().isEmpty()); + } + + @Test + public void testBadHoldTimeError() throws BGPParsingException { + final byte[] bMsg = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, + (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 + }; + + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals("Hold time value not acceptable.", e.getMessage()); + assertEquals(BGPError.HOLD_TIME_NOT_ACC, e.getError()); + return; + } + fail(); + } + + @Test + public void testBadMsgLength() throws BGPParsingException { + final byte[] bMsg = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, + (byte) 0xff, (byte) 0xff, (byte) 0xff + }; + + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals("Open message too small.", e.getMessage()); + assertEquals(BGPError.BAD_MSG_LENGTH, e.getError()); + } + } + + @Test + public void testBadVersion() throws BGPParsingException { + final byte[] bMsg = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, + (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 + }; + + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals("BGP Protocol version 8 not supported.", e.getMessage()); + assertEquals(BGPError.VERSION_NOT_SUPPORTED, e.getError()); + return; + } + fail(); + } + + @Test + public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException { + Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()) + .setErrorSubcode(BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build(); + final ByteBuf bytes = Unpooled.buffer(); + ParserTest.reg.serializeMessage(notMsg, bytes); + assertArrayEquals(NOTIFICATION_BMSG, ByteArray.subByte(bytes.array(),0,bytes.writerIndex())); + + Notification msg = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes), null); + + assertTrue(msg instanceof Notify); + assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) msg).getErrorCode(), + ((Notify) msg).getErrorSubcode())); + assertArrayEquals(new byte[] { 4, 9 }, ((Notify) msg).getData()); + + notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode( + BGPError.CONNECTION_NOT_SYNC.getSubcode()).build(); + + bytes.clear(); + + ParserTest.reg.serializeMessage(notMsg, bytes); + + msg = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes), null); + + assertTrue(msg instanceof Notify); + assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) msg).getErrorCode(), + ((Notify) msg).getErrorSubcode())); + assertNull(((Notify) msg).getData()); + } + + @Test + public void testWrongLength() throws BGPParsingException { + final byte[] bMsg = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 + }; + + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals("Notification message too small.", e.getMessage()); + assertEquals(BGPError.BAD_MSG_LENGTH, e.getError()); + return; + } + fail(); + } + + @Test + public void testUnrecognizedError() throws BGPParsingException, BGPDocumentedException { + final byte[] bMsg = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa + }; + + try { + ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg), null); + fail("Exception should have occured."); + } catch (final IllegalArgumentException e) { + assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage()); + return; + } + fail(); + } + + @Test + public void testParseUpdMsgWithUnrecognizedAttribute() throws BGPDocumentedException, BGPParsingException { + try { + reg.parseMessage(Unpooled.copiedBuffer(UPD_MSG_WITH_UNRECOGNIZED_ATTRIBUTE), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals("Well known attribute not recognized.", e.getMessage()); + assertEquals(BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED, e.getError()); + return; + } + fail(); + } + + @Test + public void testParseUpdMsgWithMandatoryAttributesPresent() throws BGPDocumentedException, BGPParsingException { + try { + final Notification msg = reg.parseMessage(Unpooled.copiedBuffer(UPD_MSG_WITH_MANDATORY_ATTRIBUTES_PRESENT), + null); + assertTrue(msg instanceof Update); + } catch (final BGPDocumentedException e) { + fail("Exception should not have occured."); + } + } + + @Test + public void testParseUpdMsgWithOneMandatoryAttributeNotPresent() + throws BGPDocumentedException, BGPParsingException { + try { + reg.parseMessage(Unpooled.copiedBuffer(UPD_MSG_WITH_ONE_MANDATORY_ATTRIBUTE_NOT_PRESENT), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals(BGPError.MANDATORY_ATTR_MISSING_MSG + "ORIGIN", e.getMessage()); + assertEquals(BGPError.WELL_KNOWN_ATTR_MISSING, e.getError()); + assertArrayEquals(new byte[] { OriginAttributeParser.TYPE }, e.getData()); + return; + } + fail(); + } + + @Test + public void testParseUpdMsgWithMultipleMandatoryAttributesNotPresent() + throws BGPDocumentedException, BGPParsingException { + try { + reg.parseMessage(Unpooled.copiedBuffer(UPD_MSG_WITH_MULTIPLE_MANDATORY_ATTRIBUTES_NOT_PRESENT), null); + fail("Exception should have occured."); + } catch (final BGPDocumentedException e) { + assertEquals(BGPError.MANDATORY_ATTR_MISSING_MSG + "NEXT_HOP", e.getMessage()); + assertEquals(BGPError.WELL_KNOWN_ATTR_MISSING, e.getError()); + assertArrayEquals(new byte[] { NextHopAttributeParser.TYPE }, e.getData()); + return; + } + fail(); + } + + @Test + public void testRouteRefreshMsg() throws BGPDocumentedException, BGPParsingException { + final Notification rrMsg = new RouteRefreshBuilder().setAfi(Ipv4AddressFamily.class) + .setSafi(UnicastSubsequentAddressFamily.class).build(); + final ByteBuf buffer = Unpooled.buffer(); + ParserTest.reg.serializeMessage(rrMsg, buffer); + assertArrayEquals(RR_MSG, ByteArray.getAllBytes(buffer)); + + final Notification m = ParserTest.reg.parseMessage( + Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)), null); + + assertTrue(m instanceof RouteRefresh); + } }