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;
17 import io.netty.buffer.Unpooled;
19 import java.net.UnknownHostException;
20 import java.util.Arrays;
21 import java.util.List;
24 import org.junit.BeforeClass;
25 import org.junit.Test;
26 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
27 import org.opendaylight.protocol.bgp.parser.BGPError;
28 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
29 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
30 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
31 import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
32 import org.opendaylight.protocol.util.ByteArray;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateAddressFamily;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateSubsequentAddressFamily;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.NotifyBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.OpenBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.ProtocolVersion;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParametersBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.MultiprotocolCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.multiprotocol._case.MultiprotocolCapabilityBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
50 import org.opendaylight.yangtools.yang.binding.Notification;
52 import com.google.common.collect.Lists;
53 import com.google.common.collect.Maps;
55 public class ParserTest {
57 public static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
58 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
59 (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
60 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
62 public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
63 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
64 (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
66 public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
67 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
68 (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
70 public static final byte[] openWithCpblt1 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
71 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
72 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
73 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
74 (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x40,
75 (byte) 0x04, (byte) 0x00, (byte) 0x47 };
77 public static final byte[] openWithCpblt2 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
78 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
79 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
80 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
81 (byte) 0x40, (byte) 0x04, (byte) 0x00, (byte) 0x47, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x00,
82 (byte) 0x01, (byte) 0x00, (byte) 0x01 };
84 static MessageRegistry reg;
87 public static void setupClass() throws Exception {
88 reg = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance().getMessageRegistry();
92 public void testHeaderErrors() throws BGPParsingException, BGPDocumentedException {
93 byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
94 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00 };
95 wrong = ByteArray.cutBytes(wrong, 16);
97 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(wrong));
98 fail("Exception should have occcured.");
99 } catch (final IllegalArgumentException e) {
100 assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage());
107 public void testBadMsgType() throws BGPParsingException {
108 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
109 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
110 (byte) 0x00, (byte) 0x13, (byte) 0x08 };
112 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
113 fail("Exception should have occured.");
114 } catch (final BGPDocumentedException e) {
115 assertEquals(BGPError.BAD_MSG_TYPE, e.getError());
122 public void testKeepAliveMsg() throws BGPParsingException, BGPDocumentedException {
123 final Notification keepAlive = new KeepaliveBuilder().build();
124 final byte[] bytes = ParserTest.reg.serializeMessage(keepAlive);
125 assertArrayEquals(keepAliveBMsg, bytes);
127 final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
129 assertTrue(m instanceof Keepalive);
133 public void testBadKeepAliveMsg() throws BGPParsingException {
134 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
135 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
136 (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
139 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
140 fail("Exception should have occured.");
141 } catch (final BGPDocumentedException e) {
142 assertThat(e.getMessage(), containsString("Message length field not within valid range."));
143 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
150 public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException {
151 final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
152 new ProtocolVersion((short) 4)).build();
153 final byte[] bytes = ParserTest.reg.serializeMessage(open);
154 assertArrayEquals(openBMsg, bytes);
156 final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
158 assertTrue(m instanceof Open);
159 assertEquals(100, ((Open) m).getMyAsNumber().intValue());
160 assertEquals(180, ((Open) m).getHoldTimer().intValue());
161 assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
162 assertTrue(((Open) m).getBgpParameters().isEmpty());
166 public void testBadHoldTimeError() throws BGPParsingException {
167 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
168 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
169 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
170 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
173 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
174 fail("Exception should have occured.");
175 } catch (final BGPDocumentedException e) {
176 assertEquals("Hold time value not acceptable.", e.getMessage());
177 assertEquals(BGPError.HOLD_TIME_NOT_ACC, e.getError());
184 public void testBadMsgLength() throws BGPParsingException {
185 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
186 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
187 (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
188 (byte) 0xff, (byte) 0xff };
191 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
192 fail("Exception should have occured.");
193 } catch (final BGPDocumentedException e) {
194 assertEquals("Open message too small.", e.getMessage());
195 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
200 public void testBadVersion() throws BGPParsingException {
201 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
202 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
203 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
204 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
207 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
208 fail("Exception should have occured.");
209 } catch (final BGPDocumentedException e) {
210 assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
211 assertEquals(BGPError.VERSION_NOT_SUPPORTED, e.getError());
218 public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException {
219 Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
220 BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
221 byte[] bytes = ParserTest.reg.serializeMessage(notMsg);
222 assertArrayEquals(notificationBMsg, bytes);
224 Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
226 assertTrue(m instanceof Notify);
227 assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
228 assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
230 notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
231 BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
232 bytes = ParserTest.reg.serializeMessage(notMsg);
234 m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
236 assertTrue(m instanceof Notify);
237 assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
238 assertNull(((Notify) m).getData());
242 public void testWrongLength() throws BGPParsingException {
243 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
244 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
245 (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
248 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
249 fail("Exception should have occured.");
250 } catch (final BGPDocumentedException e) {
251 assertEquals("Notification message too small.", e.getMessage());
252 assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
259 public void testUnrecognizedError() throws BGPParsingException, BGPDocumentedException {
260 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
261 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
262 (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
265 ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
266 fail("Exception should have occured.");
267 } catch (final IllegalArgumentException e) {
268 assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
275 public void testTLVParser() throws UnknownHostException {
277 final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
278 final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class);
280 final List<BgpParameters> tlvs = Lists.newArrayList();
282 tlvs.add(new BgpParametersBuilder().setCParameters(
283 new MultiprotocolCaseBuilder().setMultiprotocolCapability(
284 new MultiprotocolCapabilityBuilder().setAfi(LinkstateAddressFamily.class).setSafi(
285 LinkstateSubsequentAddressFamily.class).build()).build()).build());
286 tlvs.add(new BgpParametersBuilder().setCParameters(
287 new MultiprotocolCaseBuilder().setMultiprotocolCapability(
288 new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build());
290 final Map<BgpTableType, Boolean> tableTypes = Maps.newHashMap();
291 tableTypes.put(t1, true);
292 tableTypes.put(t2, true);
293 final Open open = new OpenBuilder().setMyAsNumber(72).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("172.20.160.170")).setVersion(
294 new ProtocolVersion((short) 4)).setBgpParameters(tlvs).build();
296 final byte[] result = ParserTest.reg.serializeMessage(open);
298 // the capabilities can be swapped.
299 assertTrue(Arrays.equals(openWithCpblt1, result) || Arrays.equals(openWithCpblt2, result));