2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bgp.parser.impl;
10 import static org.hamcrest.CoreMatchers.containsString;
11 import static org.junit.Assert.assertArrayEquals;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertThat;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17 import io.netty.buffer.ByteBuf;
18 import io.netty.buffer.Unpooled;
19 import java.net.UnknownHostException;
20 import org.junit.BeforeClass;
21 import org.junit.Test;
22 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
23 import org.opendaylight.protocol.bgp.parser.BGPError;
24 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
25 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
26 import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
27 import org.opendaylight.protocol.util.ByteArray;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.NotifyBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.OpenBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.ProtocolVersion;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefresh;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefreshBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
40 import org.opendaylight.yangtools.yang.binding.Notification;
42 public class ParserTest {
44 private static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
45 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
46 (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
47 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
49 private static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
50 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
51 (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
53 private static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
54 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
55 (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
57 private static final byte[] updMsgWithUnrecognizedAttribute = new byte[] {
58 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
59 (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,
60 (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,
61 (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,
62 (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,
63 (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,
64 (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,
65 (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,
66 (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
69 private static final byte[] RR_MSG = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
70 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
71 (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01 };
73 static MessageRegistry reg;
76 public static void setupClass() throws Exception {
77 reg = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance().getMessageRegistry();
81 public void testHeaderErrors() throws BGPParsingException, BGPDocumentedException {
82 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 };
83 wrong = ByteArray.cutBytes(wrong, 16);
85 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(wrong));
86 fail("Exception should have occcured.");
87 } catch (final IllegalArgumentException e) {
88 assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage());
95 public void testBadMsgType() throws BGPParsingException {
96 final byte[] bytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
97 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
98 (byte) 0x00, (byte) 0x13, (byte) 0x08 };
100 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
101 fail("Exception should have occured.");
102 } catch (final BGPDocumentedException e) {
103 assertEquals(BGPError.BAD_MSG_TYPE, e.getError());
110 public void testKeepAliveMsg() throws BGPParsingException, BGPDocumentedException {
111 final Notification keepAlive = new KeepaliveBuilder().build();
112 final ByteBuf buffer = Unpooled.buffer();
113 ParserTest.reg.serializeMessage(keepAlive, buffer);
114 assertArrayEquals(keepAliveBMsg, ByteArray.getAllBytes(buffer));
116 final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)));
118 assertTrue(m instanceof Keepalive);
122 public void testBadKeepAliveMsg() throws BGPParsingException {
123 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
124 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
125 (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
128 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
129 fail("Exception should have occured.");
130 } catch (final BGPDocumentedException e) {
131 assertThat(e.getMessage(), containsString("Message length field not within valid range."));
132 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
139 public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException {
140 final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
141 new ProtocolVersion((short) 4)).build();
142 final ByteBuf bytes = Unpooled.buffer();
143 ParserTest.reg.serializeMessage(open, bytes);
144 assertArrayEquals(openBMsg, ByteArray.getAllBytes(bytes));
146 final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
148 assertTrue(m instanceof Open);
149 assertEquals(100, ((Open) m).getMyAsNumber().intValue());
150 assertEquals(180, ((Open) m).getHoldTimer().intValue());
151 assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
152 assertTrue(((Open) m).getBgpParameters().isEmpty());
156 public void testBadHoldTimeError() throws BGPParsingException {
157 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
158 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
159 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
160 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
163 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
164 fail("Exception should have occured.");
165 } catch (final BGPDocumentedException e) {
166 assertEquals("Hold time value not acceptable.", e.getMessage());
167 assertEquals(BGPError.HOLD_TIME_NOT_ACC, e.getError());
174 public void testBadMsgLength() throws BGPParsingException {
175 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
176 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
177 (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
178 (byte) 0xff, (byte) 0xff };
181 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
182 fail("Exception should have occured.");
183 } catch (final BGPDocumentedException e) {
184 assertEquals("Open message too small.", e.getMessage());
185 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
190 public void testBadVersion() throws BGPParsingException {
191 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
192 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
193 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
194 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
197 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
198 fail("Exception should have occured.");
199 } catch (final BGPDocumentedException e) {
200 assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
201 assertEquals(BGPError.VERSION_NOT_SUPPORTED, e.getError());
208 public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException {
209 Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
210 BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
211 final ByteBuf bytes = Unpooled.buffer();
212 ParserTest.reg.serializeMessage(notMsg, bytes);
213 assertArrayEquals(notificationBMsg, ByteArray.subByte(bytes.array(),0,bytes.writerIndex()));
215 Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
217 assertTrue(m instanceof Notify);
218 assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
219 assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
221 notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
222 BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
226 ParserTest.reg.serializeMessage(notMsg, bytes);
228 m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
230 assertTrue(m instanceof Notify);
231 assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
232 assertNull(((Notify) m).getData());
236 public void testWrongLength() throws BGPParsingException {
237 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
238 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
239 (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
242 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
243 fail("Exception should have occured.");
244 } catch (final BGPDocumentedException e) {
245 assertEquals("Notification message too small.", e.getMessage());
246 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
253 public void testUnrecognizedError() throws BGPParsingException, BGPDocumentedException {
254 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
255 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
256 (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
259 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
260 fail("Exception should have occured.");
261 } catch (final IllegalArgumentException e) {
262 assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
269 public void testParseUpdMsgWithUnrecognizedAttribute() throws BGPDocumentedException, BGPParsingException {
271 reg.parseMessage(Unpooled.copiedBuffer(updMsgWithUnrecognizedAttribute));
272 fail("Exception should have occured.");
273 } catch (final BGPDocumentedException e) {
274 assertEquals("Well known attribute not recognized.", e.getMessage());
275 assertEquals(BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED, e.getError());
282 public void testRouteRefreshMsg() throws BGPDocumentedException, BGPParsingException {
283 final Notification rrMsg = new RouteRefreshBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build();
284 final ByteBuf buffer = Unpooled.buffer();
285 ParserTest.reg.serializeMessage(rrMsg, buffer);
286 assertArrayEquals(RR_MSG, ByteArray.getAllBytes(buffer));
288 final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)));
290 assertTrue(m instanceof RouteRefresh);