BUG-113: switch BGP to proper activators
[bgpcep.git] / bgp / rib-impl / src / test / java / org / opendaylight / protocol / bgp / rib / impl / ParserTest.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.rib.impl;
9
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
18 import java.net.UnknownHostException;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.Map;
22
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;
50
51 import com.google.common.collect.Lists;
52 import com.google.common.collect.Maps;
53
54 public class ParserTest {
55
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 };
60
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 };
64
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 };
68
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 };
75
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 };
82
83         final MessageRegistry factory =
84                         BGPExtensionConsumerContextImpl.getSingletonInstance().getMessageRegistry();
85
86         @Test
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);
91                 try {
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());
96                         return;
97                 }
98                 fail();
99         }
100
101         @Test
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 };
106                 try {
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());
111                         return;
112                 }
113                 fail();
114         }
115
116         @Test
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);
121
122                 final Notification m = this.factory.parseMessage(bytes);
123
124                 assertTrue(m instanceof Keepalive);
125         }
126
127         @Test
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 };
132
133                 try {
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());
139                         return;
140                 }
141                 fail();
142         }
143
144         @Test
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);
150
151                 final Notification m = this.factory.parseMessage(bytes);
152
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());
158         }
159
160         @Test
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 };
166
167                 try {
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());
173                         return;
174                 }
175                 fail();
176         }
177
178         @Test
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 };
184
185                 try {
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());
191                 }
192         }
193
194         @Test
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 };
200
201                 try {
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());
207                         return;
208                 }
209                 fail();
210         }
211
212         @Test
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);
218
219                 Notification m = this.factory.parseMessage(bytes);
220
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());
224
225                 notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
226                                 BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
227                 bytes = this.factory.serializeMessage(notMsg);
228
229                 m = this.factory.parseMessage(bytes);
230
231                 assertTrue(m instanceof Notify);
232                 assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
233                 assertNull(((Notify) m).getData());
234         }
235
236         @Test
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 };
241
242                 try {
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());
248                         return;
249                 }
250                 fail();
251         }
252
253         @Test
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 };
258
259                 try {
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());
264                         return;
265                 }
266                 fail();
267         }
268
269         @Test
270         public void testTLVParser() throws UnknownHostException {
271
272                 final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
273                 final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class);
274
275                 final List<BgpParameters> tlvs = Lists.newArrayList();
276
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());
284
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();
290
291                 final byte[] result = this.factory.serializeMessage(open);
292
293                 // the capabilities can be swapped.
294                 assertTrue(Arrays.equals(openWithCpblt1, result) || Arrays.equals(openWithCpblt2, result));
295         }
296 }