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 java.net.UnknownHostException;
19 import java.util.Arrays;
20 import java.util.List;
23 import org.junit.BeforeClass;
24 import org.junit.Test;
25 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
26 import org.opendaylight.protocol.bgp.parser.BGPError;
27 import org.opendaylight.protocol.bgp.parser.BGPMessageFactory;
28 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
29 import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactoryImpl;
30 import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
31 import org.opendaylight.protocol.framework.DeserializerException;
32 import org.opendaylight.protocol.framework.DocumentedException;
33 import org.opendaylight.protocol.util.ByteArray;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateAddressFamily;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateSubsequentAddressFamily;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Keepalive;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.KeepaliveBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Notify;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.NotifyBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Open;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.OpenBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.ProtocolVersion;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.open.BgpParameters;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.open.BgpParametersBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.BgpTableType;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.open.bgp.parameters.c.parameters.CMultiprotocolBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.open.bgp.parameters.c.parameters.c.multiprotocol.MultiprotocolCapabilityBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
51 import org.opendaylight.yangtools.yang.binding.Notification;
53 import com.google.common.collect.Lists;
54 import com.google.common.collect.Maps;
56 public class ParserTest {
58 public static final byte[] openBMsg = new byte[] { (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,
60 (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
61 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
63 public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
64 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
65 (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
67 public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
68 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
69 (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
71 public static final byte[] openWithCpblt1 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
72 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
73 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
74 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
75 (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x40,
76 (byte) 0x04, (byte) 0x00, (byte) 0x47 };
78 public static final byte[] openWithCpblt2 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
79 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
80 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
81 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
82 (byte) 0x40, (byte) 0x04, (byte) 0x00, (byte) 0x47, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x00,
83 (byte) 0x01, (byte) 0x00, (byte) 0x01 };
85 static BGPMessageFactory factory;
88 public static void setupClass() throws Exception {
89 factory = new BGPMessageFactoryImpl(ServiceLoaderBGPExtensionProviderContext.createConsumerContext().getMessageRegistry());
93 public void testHeaderErrors() throws DeserializerException, DocumentedException {
94 byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
95 (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.factory.parse(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 DeserializerException {
109 final byte[] bytes = new byte[] { (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.factory.parse(bytes);
114 fail("Exception should have occured.");
115 } catch (final DocumentedException e) {
116 assertEquals(BGPError.BAD_MSG_TYPE, ((BGPDocumentedException) e).getError());
123 public void testKeepAliveMsg() throws DeserializerException, DocumentedException {
124 final Notification keepAlive = new KeepaliveBuilder().build();
125 final byte[] bytes = ParserTest.factory.put(keepAlive);
126 assertArrayEquals(keepAliveBMsg, bytes);
128 final Notification m = ParserTest.factory.parse(bytes);
130 assertTrue(m instanceof Keepalive);
134 public void testBadKeepAliveMsg() throws DeserializerException {
135 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
136 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
137 (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
140 ParserTest.factory.parse(bytes);
141 fail("Exception should have occured.");
142 } catch (final DocumentedException e) {
143 assertThat(e.getMessage(), containsString("Message length field not within valid range."));
144 assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
151 public void testOpenMessage() throws UnknownHostException, DeserializerException, DocumentedException {
152 final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
153 new ProtocolVersion((short) 4)).build();
154 final byte[] bytes = ParserTest.factory.put(open);
155 assertArrayEquals(openBMsg, bytes);
157 final Notification m = ParserTest.factory.parse(bytes);
159 assertTrue(m instanceof Open);
160 assertEquals(100, ((Open) m).getMyAsNumber().intValue());
161 assertEquals(180, ((Open) m).getHoldTimer().intValue());
162 assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
163 assertTrue(((Open) m).getBgpParameters().isEmpty());
167 public void testBadHoldTimeError() throws DeserializerException {
168 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
169 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
170 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
171 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
174 ParserTest.factory.parse(bMsg);
175 fail("Exception should have occured.");
176 } catch (final DocumentedException e) {
177 assertEquals("Hold time value not acceptable.", e.getMessage());
178 assertEquals(BGPError.HOLD_TIME_NOT_ACC, ((BGPDocumentedException) e).getError());
185 public void testBadMsgLength() throws DeserializerException {
186 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
187 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
188 (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
189 (byte) 0xff, (byte) 0xff };
192 ParserTest.factory.parse(bMsg);
193 fail("Exception should have occured.");
194 } catch (final DocumentedException e) {
195 assertEquals("Open message too small.", e.getMessage());
196 assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
201 public void testBadVersion() throws DeserializerException {
202 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
203 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
204 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
205 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
208 ParserTest.factory.parse(bMsg);
209 fail("Exception should have occured.");
210 } catch (final DocumentedException e) {
211 assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
212 assertEquals(BGPError.VERSION_NOT_SUPPORTED, ((BGPDocumentedException) e).getError());
219 public void testNotificationMsg() throws DeserializerException, DocumentedException {
220 Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
221 BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
222 byte[] bytes = ParserTest.factory.put(notMsg);
223 assertArrayEquals(notificationBMsg, bytes);
225 Notification m = ParserTest.factory.parse(bytes);
227 assertTrue(m instanceof Notify);
228 assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
229 assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
231 notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
232 BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
233 bytes = ParserTest.factory.put(notMsg);
235 m = ParserTest.factory.parse(bytes);
237 assertTrue(m instanceof Notify);
238 assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
239 assertNull(((Notify) m).getData());
243 public void testWrongLength() throws DeserializerException {
244 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
245 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
246 (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
249 ParserTest.factory.parse(bMsg);
250 fail("Exception should have occured.");
251 } catch (final DocumentedException e) {
252 assertEquals("Notification message too small.", e.getMessage());
253 assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
260 public void testUnrecognizedError() throws DeserializerException, DocumentedException {
261 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
262 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
263 (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
266 ParserTest.factory.parse(bMsg);
267 fail("Exception should have occured.");
268 } catch (final IllegalArgumentException e) {
269 assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
276 public void testTLVParser() throws UnknownHostException {
278 final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
279 final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class);
281 final List<BgpParameters> tlvs = Lists.newArrayList();
283 tlvs.add(new BgpParametersBuilder().setCParameters(
284 new CMultiprotocolBuilder().setMultiprotocolCapability(
285 new MultiprotocolCapabilityBuilder().setAfi(LinkstateAddressFamily.class).setSafi(
286 LinkstateSubsequentAddressFamily.class).build()).build()).build());
287 tlvs.add(new BgpParametersBuilder().setCParameters(
288 new CMultiprotocolBuilder().setMultiprotocolCapability(
289 new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build());
291 final Map<BgpTableType, Boolean> tableTypes = Maps.newHashMap();
292 tableTypes.put(t1, true);
293 tableTypes.put(t2, true);
294 final Open open = new OpenBuilder().setMyAsNumber(72).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("172.20.160.170")).setVersion(
295 new ProtocolVersion((short) 4)).setBgpParameters(tlvs).build();
297 final byte[] result = ParserTest.factory.put(open);
299 // the capabilities can be swapped.
300 assertTrue(Arrays.equals(openWithCpblt1, result) || Arrays.equals(openWithCpblt2, result));