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.junit.Assert.assertArrayEquals;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertThat;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.junit.matchers.JUnitMatchers.containsString;
18 import com.google.common.collect.Lists;
19 import com.google.common.collect.Maps;
21 import io.netty.buffer.ByteBuf;
22 import io.netty.buffer.Unpooled;
24 import java.net.UnknownHostException;
25 import java.util.Arrays;
26 import java.util.List;
29 import org.junit.BeforeClass;
30 import org.junit.Test;
31 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
32 import org.opendaylight.protocol.bgp.parser.BGPError;
33 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
34 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
35 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
36 import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
37 import org.opendaylight.protocol.util.ByteArray;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateAddressFamily;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateSubsequentAddressFamily;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.NotifyBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.OpenBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.ProtocolVersion;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParametersBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.MultiprotocolCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.multiprotocol._case.MultiprotocolCapabilityBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
55 import org.opendaylight.yangtools.yang.binding.Notification;
57 public class ParserTest {
59 public static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
60 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
61 (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
62 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
64 public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
65 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
66 (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
68 public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
69 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
70 (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
72 public static final byte[] openWithCpblt1 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
73 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
74 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
75 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
76 (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x40,
77 (byte) 0x04, (byte) 0x00, (byte) 0x47 };
79 public static final byte[] openWithCpblt2 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
80 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
81 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
82 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
83 (byte) 0x40, (byte) 0x04, (byte) 0x00, (byte) 0x47, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x00,
84 (byte) 0x01, (byte) 0x00, (byte) 0x01 };
86 static MessageRegistry reg;
89 public static void setupClass() throws Exception {
90 reg = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance().getMessageRegistry();
94 public void testHeaderErrors() throws BGPParsingException, BGPDocumentedException {
95 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 };
96 wrong = ByteArray.cutBytes(wrong, 16);
98 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(wrong));
99 fail("Exception should have occcured.");
100 } catch (final IllegalArgumentException e) {
101 assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage());
108 public void testBadMsgType() throws BGPParsingException {
109 final byte[] bytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
110 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
111 (byte) 0x00, (byte) 0x13, (byte) 0x08 };
113 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
114 fail("Exception should have occured.");
115 } catch (final BGPDocumentedException e) {
116 assertEquals(BGPError.BAD_MSG_TYPE, e.getError());
123 public void testKeepAliveMsg() throws BGPParsingException, BGPDocumentedException {
124 final Notification keepAlive = new KeepaliveBuilder().build();
125 ByteBuf buffer = Unpooled.buffer();
126 ParserTest.reg.serializeMessage(keepAlive, buffer);
127 assertArrayEquals(keepAliveBMsg, ByteArray.getAllBytes(buffer));
129 final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)));
131 assertTrue(m instanceof Keepalive);
135 public void testBadKeepAliveMsg() throws BGPParsingException {
136 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
137 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
138 (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
141 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
142 fail("Exception should have occured.");
143 } catch (final BGPDocumentedException e) {
144 assertThat(e.getMessage(), containsString("Message length field not within valid range."));
145 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
152 public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException {
153 final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
154 new ProtocolVersion((short) 4)).build();
155 ByteBuf bytes = Unpooled.buffer();
156 ParserTest.reg.serializeMessage(open, bytes);
157 assertArrayEquals(openBMsg, ByteArray.getAllBytes(bytes));
159 final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
161 assertTrue(m instanceof Open);
162 assertEquals(100, ((Open) m).getMyAsNumber().intValue());
163 assertEquals(180, ((Open) m).getHoldTimer().intValue());
164 assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
165 assertTrue(((Open) m).getBgpParameters().isEmpty());
169 public void testBadHoldTimeError() throws BGPParsingException {
170 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
171 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
172 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
173 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
176 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
177 fail("Exception should have occured.");
178 } catch (final BGPDocumentedException e) {
179 assertEquals("Hold time value not acceptable.", e.getMessage());
180 assertEquals(BGPError.HOLD_TIME_NOT_ACC, e.getError());
187 public void testBadMsgLength() throws BGPParsingException {
188 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
189 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
190 (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
191 (byte) 0xff, (byte) 0xff };
194 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
195 fail("Exception should have occured.");
196 } catch (final BGPDocumentedException e) {
197 assertEquals("Open message too small.", e.getMessage());
198 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
203 public void testBadVersion() throws BGPParsingException {
204 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
205 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
206 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
207 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
210 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
211 fail("Exception should have occured.");
212 } catch (final BGPDocumentedException e) {
213 assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
214 assertEquals(BGPError.VERSION_NOT_SUPPORTED, e.getError());
221 public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException {
222 Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
223 BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
224 ByteBuf bytes = Unpooled.buffer();
225 ParserTest.reg.serializeMessage(notMsg, bytes);
226 assertArrayEquals(notificationBMsg, ByteArray.subByte(bytes.array(),0,bytes.writerIndex()));
228 Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
230 assertTrue(m instanceof Notify);
231 assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
232 assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
234 notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
235 BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
239 ParserTest.reg.serializeMessage(notMsg, bytes);
241 m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
243 assertTrue(m instanceof Notify);
244 assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
245 assertNull(((Notify) m).getData());
249 public void testWrongLength() throws BGPParsingException {
250 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
251 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
252 (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
255 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
256 fail("Exception should have occured.");
257 } catch (final BGPDocumentedException e) {
258 assertEquals("Notification message too small.", e.getMessage());
259 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
266 public void testUnrecognizedError() throws BGPParsingException, BGPDocumentedException {
267 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
268 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
269 (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
272 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
273 fail("Exception should have occured.");
274 } catch (final IllegalArgumentException e) {
275 assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
282 public void testTLVParser() throws UnknownHostException {
284 final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
285 final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class);
287 final List<BgpParameters> tlvs = Lists.newArrayList();
289 tlvs.add(new BgpParametersBuilder().setCParameters(
290 new MultiprotocolCaseBuilder().setMultiprotocolCapability(
291 new MultiprotocolCapabilityBuilder().setAfi(LinkstateAddressFamily.class).setSafi(
292 LinkstateSubsequentAddressFamily.class).build()).build()).build());
293 tlvs.add(new BgpParametersBuilder().setCParameters(
294 new MultiprotocolCaseBuilder().setMultiprotocolCapability(
295 new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build());
297 final Map<BgpTableType, Boolean> tableTypes = Maps.newHashMap();
298 tableTypes.put(t1, true);
299 tableTypes.put(t2, true);
300 final Open open = new OpenBuilder().setMyAsNumber(72).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("172.20.160.170")).setVersion(
301 new ProtocolVersion((short) 4)).setBgpParameters(tlvs).build();
303 ByteBuf result = Unpooled.buffer();
304 ParserTest.reg.serializeMessage(open, result);
306 // the capabilities can be swapped.
307 assertTrue(Arrays.equals(openWithCpblt1, ByteArray.getAllBytes(result)) || Arrays.equals(openWithCpblt2, ByteArray.getAllBytes(result)));