Merge "Revert "Bug 1205 - AS path segment value encoded by 2 bytes""
[bgpcep.git] / bgp / parser-impl / src / test / java / org / opendaylight / protocol / bgp / parser / 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.parser.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 com.google.common.collect.Lists;
19 import com.google.common.collect.Maps;
20 import io.netty.buffer.ByteBuf;
21 import io.netty.buffer.Unpooled;
22 import java.net.UnknownHostException;
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.Map;
26 import org.junit.BeforeClass;
27 import org.junit.Test;
28 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
29 import org.opendaylight.protocol.bgp.parser.BGPError;
30 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
31 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
32 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
33 import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
34 import org.opendaylight.protocol.util.ByteArray;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateAddressFamily;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateSubsequentAddressFamily;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.NotifyBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.OpenBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.ProtocolVersion;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParametersBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.MultiprotocolCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.multiprotocol._case.MultiprotocolCapabilityBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
52 import org.opendaylight.yangtools.yang.binding.Notification;
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     public static final byte[] updateMsg = {
84         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
85         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x51, 0x02, 0x00, 0x00, 0x00, 0x36, 0x40, 0x01, 0x01, 0x00, 0x40, 0x02,
86         0x1a, 0x02, 0x06, 0x00, 0x00, (byte) 0xfe, 0x55, 0x00, 0x00, (byte) 0xfc, 0x12, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x02, (byte) 0xbd, 0x00, 0x00, 0x0d, 0x1c, 0x00, 0x00, 0x6a, 0x74, 0x40, 0x03,
87         0x04, 0x0a, 0x20, 0x00, (byte) 0xfe, (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x04, 0x00, 0x00, 0x00, 0x64, 0x18, (byte) 0xa8, (byte) 0xa1, (byte) 0xf7
88     };
89
90     static MessageRegistry reg;
91
92     @BeforeClass
93     public static void setupClass() throws Exception {
94         reg = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance().getMessageRegistry();
95     }
96
97     @Test
98     public void testHeaderErrors() throws BGPParsingException, BGPDocumentedException {
99         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 };
100         wrong = ByteArray.cutBytes(wrong, 16);
101         try {
102             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(wrong));
103             fail("Exception should have occcured.");
104         } catch (final IllegalArgumentException e) {
105             assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage());
106             return;
107         }
108         fail();
109     }
110
111     @Test
112     public void testBadMsgType() throws BGPParsingException {
113         final byte[] bytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
114             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
115             (byte) 0x00, (byte) 0x13, (byte) 0x08 };
116         try {
117             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
118             fail("Exception should have occured.");
119         } catch (final BGPDocumentedException e) {
120             assertEquals(BGPError.BAD_MSG_TYPE, e.getError());
121             return;
122         }
123         fail();
124     }
125
126     @Test
127     public void testKeepAliveMsg() throws BGPParsingException, BGPDocumentedException {
128         final Notification keepAlive = new KeepaliveBuilder().build();
129         ByteBuf buffer = Unpooled.buffer();
130         ParserTest.reg.serializeMessage(keepAlive, buffer);
131         assertArrayEquals(keepAliveBMsg, ByteArray.getAllBytes(buffer));
132
133         final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)));
134
135         assertTrue(m instanceof Keepalive);
136     }
137
138     @Test
139     public void testBadKeepAliveMsg() throws BGPParsingException {
140         final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
141             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
142             (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
143
144         try {
145             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
146             fail("Exception should have occured.");
147         } catch (final BGPDocumentedException e) {
148             assertThat(e.getMessage(), containsString("Message length field not within valid range."));
149             assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
150             return;
151         }
152         fail();
153     }
154
155     @Test
156     public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException {
157         final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
158             new ProtocolVersion((short) 4)).build();
159         ByteBuf bytes = Unpooled.buffer();
160         ParserTest.reg.serializeMessage(open, bytes);
161         assertArrayEquals(openBMsg, ByteArray.getAllBytes(bytes));
162
163         final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
164
165         assertTrue(m instanceof Open);
166         assertEquals(100, ((Open) m).getMyAsNumber().intValue());
167         assertEquals(180, ((Open) m).getHoldTimer().intValue());
168         assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
169         assertTrue(((Open) m).getBgpParameters().isEmpty());
170     }
171
172     @Test
173     public void testBadHoldTimeError() throws BGPParsingException {
174         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
175             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
176             (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
177             (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
178
179         try {
180             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
181             fail("Exception should have occured.");
182         } catch (final BGPDocumentedException e) {
183             assertEquals("Hold time value not acceptable.", e.getMessage());
184             assertEquals(BGPError.HOLD_TIME_NOT_ACC, e.getError());
185             return;
186         }
187         fail();
188     }
189
190     @Test
191     public void testBadMsgLength() throws BGPParsingException {
192         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
193             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
194             (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
195             (byte) 0xff, (byte) 0xff };
196
197         try {
198             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
199             fail("Exception should have occured.");
200         } catch (final BGPDocumentedException e) {
201             assertEquals("Open message too small.", e.getMessage());
202             assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
203         }
204     }
205
206     @Test
207     public void testBadVersion() throws BGPParsingException {
208         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
209             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
210             (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
211             (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
212
213         try {
214             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
215             fail("Exception should have occured.");
216         } catch (final BGPDocumentedException e) {
217             assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
218             assertEquals(BGPError.VERSION_NOT_SUPPORTED, e.getError());
219             return;
220         }
221         fail();
222     }
223
224     @Test
225     public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException {
226         Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
227             BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
228         ByteBuf bytes = Unpooled.buffer();
229         ParserTest.reg.serializeMessage(notMsg, bytes);
230         assertArrayEquals(notificationBMsg, ByteArray.subByte(bytes.array(),0,bytes.writerIndex()));
231
232         Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
233
234         assertTrue(m instanceof Notify);
235         assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
236         assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
237
238         notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
239             BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
240
241         bytes.clear();
242
243         ParserTest.reg.serializeMessage(notMsg, bytes);
244
245         m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
246
247         assertTrue(m instanceof Notify);
248         assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
249         assertNull(((Notify) m).getData());
250     }
251
252     @Test
253     public void testWrongLength() throws BGPParsingException {
254         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
255             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
256             (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
257
258         try {
259             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
260             fail("Exception should have occured.");
261         } catch (final BGPDocumentedException e) {
262             assertEquals("Notification message too small.", e.getMessage());
263             assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
264             return;
265         }
266         fail();
267     }
268
269     @Test
270     public void testUnrecognizedError() throws BGPParsingException, BGPDocumentedException {
271         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
272             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
273             (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
274
275         try {
276             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
277             fail("Exception should have occured.");
278         } catch (final IllegalArgumentException e) {
279             assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
280             return;
281         }
282         fail();
283     }
284
285     @Test
286     public void testTLVParser() throws UnknownHostException {
287
288         final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
289         final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class);
290
291         final List<BgpParameters> tlvs = Lists.newArrayList();
292
293         tlvs.add(new BgpParametersBuilder().setCParameters(
294             new MultiprotocolCaseBuilder().setMultiprotocolCapability(
295                 new MultiprotocolCapabilityBuilder().setAfi(LinkstateAddressFamily.class).setSafi(
296                     LinkstateSubsequentAddressFamily.class).build()).build()).build());
297         tlvs.add(new BgpParametersBuilder().setCParameters(
298             new MultiprotocolCaseBuilder().setMultiprotocolCapability(
299                 new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build());
300
301         final Map<BgpTableType, Boolean> tableTypes = Maps.newHashMap();
302         tableTypes.put(t1, true);
303         tableTypes.put(t2, true);
304         final Open open = new OpenBuilder().setMyAsNumber(72).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("172.20.160.170")).setVersion(
305             new ProtocolVersion((short) 4)).setBgpParameters(tlvs).build();
306
307         ByteBuf result = Unpooled.buffer();
308         ParserTest.reg.serializeMessage(open, result);
309
310         // the capabilities can be swapped.
311         assertTrue(Arrays.equals(openWithCpblt1, ByteArray.getAllBytes(result)) || Arrays.equals(openWithCpblt2, ByteArray.getAllBytes(result)));
312     }
313 }