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.rib.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.Test;
24 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
25 import org.opendaylight.protocol.bgp.parser.BGPError;
26 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
27 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
28 import org.opendaylight.protocol.bgp.parser.spi.pojo.BGPExtensionConsumerContextImpl;
29 import org.opendaylight.protocol.framework.DeserializerException;
30 import org.opendaylight.protocol.framework.DocumentedException;
31 import org.opendaylight.protocol.util.ByteArray;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateAddressFamily;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateSubsequentAddressFamily;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Keepalive;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.KeepaliveBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Notify;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.NotifyBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Open;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.OpenBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.ProtocolVersion;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.open.BgpParameters;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.open.BgpParametersBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.BgpTableType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.open.bgp.parameters.c.parameters.CMultiprotocolBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.open.bgp.parameters.c.parameters.c.multiprotocol.MultiprotocolCapabilityBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
49 import org.opendaylight.yangtools.yang.binding.Notification;
51 import com.google.common.collect.Lists;
52 import com.google.common.collect.Maps;
54 public class ParserTest {
56 public static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
57 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
58 (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
59 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
61 public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
62 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
63 (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
65 public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
66 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
67 (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
69 public static final byte[] openWithCpblt1 = 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) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
72 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
73 (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x40,
74 (byte) 0x04, (byte) 0x00, (byte) 0x47 };
76 public static final byte[] openWithCpblt2 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
77 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
78 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
79 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
80 (byte) 0x40, (byte) 0x04, (byte) 0x00, (byte) 0x47, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x00,
81 (byte) 0x01, (byte) 0x00, (byte) 0x01 };
83 final MessageRegistry factory =
84 BGPExtensionConsumerContextImpl.getSingletonInstance().getMessageRegistry();
87 public void testHeaderErrors() throws DeserializerException, DocumentedException {
88 byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
89 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00 };
90 wrong = ByteArray.cutBytes(wrong, 16);
92 this.factory.parseMessage(wrong);
93 fail("Exception should have occcured.");
94 } catch (final IllegalArgumentException e) {
95 assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage());
102 public void testBadMsgType() throws DeserializerException {
103 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
104 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
105 (byte) 0x00, (byte) 0x13, (byte) 0x08 };
107 this.factory.parseMessage(bytes);
108 fail("Exception should have occured.");
109 } catch (final DocumentedException e) {
110 assertEquals(BGPError.BAD_MSG_TYPE, ((BGPDocumentedException) e).getError());
117 public void testKeepAliveMsg() throws DeserializerException, DocumentedException {
118 final Notification keepAlive = new KeepaliveBuilder().build();
119 final byte[] bytes = this.factory.serializeMessage(keepAlive);
120 assertArrayEquals(keepAliveBMsg, bytes);
122 final Notification m = this.factory.parseMessage(bytes);
124 assertTrue(m instanceof Keepalive);
128 public void testBadKeepAliveMsg() throws DeserializerException {
129 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
130 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
131 (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
134 this.factory.parseMessage(bytes);
135 fail("Exception should have occured.");
136 } catch (final DocumentedException e) {
137 assertThat(e.getMessage(), containsString("Message length field not within valid range."));
138 assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
145 public void testOpenMessage() throws UnknownHostException, DeserializerException, DocumentedException {
146 final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
147 new ProtocolVersion((short) 4)).build();
148 final byte[] bytes = this.factory.serializeMessage(open);
149 assertArrayEquals(openBMsg, bytes);
151 final Notification m = this.factory.parseMessage(bytes);
153 assertTrue(m instanceof Open);
154 assertEquals(100, ((Open) m).getMyAsNumber().intValue());
155 assertEquals(180, ((Open) m).getHoldTimer().intValue());
156 assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
157 assertTrue(((Open) m).getBgpParameters().isEmpty());
161 public void testBadHoldTimeError() throws DeserializerException {
162 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
163 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
164 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
165 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
168 this.factory.parseMessage(bMsg);
169 fail("Exception should have occured.");
170 } catch (final DocumentedException e) {
171 assertEquals("Hold time value not acceptable.", e.getMessage());
172 assertEquals(BGPError.HOLD_TIME_NOT_ACC, ((BGPDocumentedException) e).getError());
179 public void testBadMsgLength() throws DeserializerException {
180 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
181 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
182 (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
183 (byte) 0xff, (byte) 0xff };
186 this.factory.parseMessage(bMsg);
187 fail("Exception should have occured.");
188 } catch (final DocumentedException e) {
189 assertEquals("Open message too small.", e.getMessage());
190 assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
195 public void testBadVersion() throws DeserializerException {
196 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
197 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
198 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
199 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
202 this.factory.parseMessage(bMsg);
203 fail("Exception should have occured.");
204 } catch (final DocumentedException e) {
205 assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
206 assertEquals(BGPError.VERSION_NOT_SUPPORTED, ((BGPDocumentedException) e).getError());
213 public void testNotificationMsg() throws DeserializerException, DocumentedException {
214 Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
215 BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
216 byte[] bytes = this.factory.serializeMessage(notMsg);
217 assertArrayEquals(notificationBMsg, bytes);
219 Notification m = this.factory.parseMessage(bytes);
221 assertTrue(m instanceof Notify);
222 assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
223 assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
225 notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
226 BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
227 bytes = this.factory.serializeMessage(notMsg);
229 m = this.factory.parseMessage(bytes);
231 assertTrue(m instanceof Notify);
232 assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
233 assertNull(((Notify) m).getData());
237 public void testWrongLength() throws DeserializerException {
238 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
239 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
240 (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
243 this.factory.parseMessage(bMsg);
244 fail("Exception should have occured.");
245 } catch (final DocumentedException e) {
246 assertEquals("Notification message too small.", e.getMessage());
247 assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
254 public void testUnrecognizedError() throws DeserializerException, DocumentedException {
255 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
256 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
257 (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
260 this.factory.parseMessage(bMsg);
261 fail("Exception should have occured.");
262 } catch (final IllegalArgumentException e) {
263 assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
270 public void testTLVParser() throws UnknownHostException {
272 final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
273 final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class);
275 final List<BgpParameters> tlvs = Lists.newArrayList();
277 tlvs.add(new BgpParametersBuilder().setCParameters(
278 new CMultiprotocolBuilder().setMultiprotocolCapability(
279 new MultiprotocolCapabilityBuilder().setAfi(LinkstateAddressFamily.class).setSafi(
280 LinkstateSubsequentAddressFamily.class).build()).build()).build());
281 tlvs.add(new BgpParametersBuilder().setCParameters(
282 new CMultiprotocolBuilder().setMultiprotocolCapability(
283 new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build());
285 final Map<BgpTableType, Boolean> tableTypes = Maps.newHashMap();
286 tableTypes.put(t1, true);
287 tableTypes.put(t2, true);
288 final Open open = new OpenBuilder().setMyAsNumber(72).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("172.20.160.170")).setVersion(
289 new ProtocolVersion((short) 4)).setBgpParameters(tlvs).build();
291 final byte[] result = this.factory.serializeMessage(open);
293 // the capabilities can be swapped.
294 assertTrue(Arrays.equals(openWithCpblt1, result) || Arrays.equals(openWithCpblt2, result));