d67c38a5b00e56741d098880e0fd35c0934a83a5
[bgpcep.git] / bgp / rib-impl / src / test / java / org / opendaylight / protocol / bgp / rib / impl / FSMTest.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.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13 import static org.mockito.ArgumentMatchers.any;
14 import static org.mockito.Mockito.doAnswer;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17
18 import io.netty.channel.Channel;
19 import io.netty.channel.ChannelFuture;
20 import io.netty.channel.ChannelHandler;
21 import io.netty.channel.ChannelPipeline;
22 import io.netty.channel.EventLoop;
23 import io.netty.util.concurrent.DefaultPromise;
24 import io.netty.util.concurrent.GenericFutureListener;
25 import io.netty.util.concurrent.GlobalEventExecutor;
26 import java.net.InetAddress;
27 import java.net.InetSocketAddress;
28 import java.net.UnknownHostException;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.concurrent.TimeUnit;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.mockito.ArgumentMatchers;
35 import org.mockito.Mock;
36 import org.mockito.MockitoAnnotations;
37 import org.opendaylight.protocol.bgp.parser.BGPError;
38 import org.opendaylight.protocol.bgp.parser.BgpExtendedMessageUtil;
39 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
40 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
41 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.LinkstateAddressFamily;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.LinkstateSubsequentAddressFamily;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Keepalive;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.KeepaliveBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Notify;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Open;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.OpenBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.ProtocolVersion;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.BgpParameters;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.BgpParametersBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.OptionalCapabilities;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1Builder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.GracefulRestartCapabilityBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.MultiprotocolCapabilityBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.BgpId;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.UnicastSubsequentAddressFamily;
67 import org.opendaylight.yangtools.yang.binding.Notification;
68 import org.opendaylight.yangtools.yang.common.Uint16;
69 import org.opendaylight.yangtools.yang.common.Uint32;
70 import org.opendaylight.yangtools.yang.common.Uint8;
71
72 public class FSMTest {
73     @Mock
74     private EventLoop eventLoop;
75
76     private BGPClientSessionNegotiator clientSession;
77
78     @Mock
79     private Channel speakerListener;
80
81     @Mock
82     private ChannelPipeline pipeline;
83
84     private final BgpTableType ipv4tt
85             = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
86
87     private final BgpTableType linkstatett
88             = new BgpTableTypeImpl(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class);
89
90     private final List<Notification> receivedMsgs = new ArrayList<>();
91
92     private Open classicOpen;
93
94     @Before
95     public void setUp() throws UnknownHostException {
96         MockitoAnnotations.initMocks(this);
97         final List<BgpParameters> tlvs = new ArrayList<>();
98         final List<OptionalCapabilities> capas = new ArrayList<>();
99
100         capas.add(new OptionalCapabilitiesBuilder()
101                 .setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
102                         new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
103                                 .setAfi(this.ipv4tt.getAfi()).setSafi(this.ipv4tt.getSafi()).build()).build())
104                         .build()).build());
105         capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder()
106                 .addAugmentation(CParameters1.class,
107                         new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
108                                 .setAfi(this.linkstatett.getAfi()).setSafi(this.linkstatett.getSafi())
109                                 .build()).build()).build()).build());
110         capas.add(new OptionalCapabilitiesBuilder()
111             .setCParameters(new CParametersBuilder()
112                 .setAs4BytesCapability(new As4BytesCapabilityBuilder()
113                     .setAsNumber(new AsNumber(Uint32.valueOf(30)))
114                     .build())
115                 .build())
116             .build());
117         capas.add(new OptionalCapabilitiesBuilder()
118                 .setCParameters(BgpExtendedMessageUtil.EXTENDED_MESSAGE_CAPABILITY).build());
119         capas.add(new OptionalCapabilitiesBuilder()
120                 .setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
121                         new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder()
122                                 .build()).build()).build()).build());
123
124
125         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
126         final BGPSessionPreferences prefs = new BGPSessionPreferences(new AsNumber(Uint32.valueOf(30)), (short) 3,
127                 new BgpId("1.1.1.1"), new AsNumber(Uint32.valueOf(30)), tlvs);
128
129         final ChannelFuture f = mock(ChannelFuture.class);
130         doReturn(null).when(f).addListener(any(GenericFutureListener.class));
131
132         final InetAddress peerAddress = InetAddress.getByName("1.1.1.2");
133         doAnswer(invocation -> {
134             final Object[] args = invocation.getArguments();
135             FSMTest.this.receivedMsgs.add((Notification) args[0]);
136             return f;
137         }).when(this.speakerListener).writeAndFlush(any(Notification.class));
138         doReturn(this.eventLoop).when(this.speakerListener).eventLoop();
139         doReturn(null).when(this.eventLoop).schedule(any(Runnable.class), any(long.class),
140                 any(TimeUnit.class));
141         doReturn("TestingChannel").when(this.speakerListener).toString();
142         doReturn(new InetSocketAddress(peerAddress, 179)).when(this.speakerListener).remoteAddress();
143         doReturn(new InetSocketAddress(peerAddress, 179)).when(this.speakerListener).localAddress();
144         doReturn(this.pipeline).when(this.speakerListener).pipeline();
145         doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class),
146                 any(ChannelHandler.class));
147         doReturn(null).when(this.pipeline).replace(ArgumentMatchers.<Class<ChannelHandler>>any(), any(String.class),
148                 any(ChannelHandler.class));
149         doReturn(this.pipeline).when(this.pipeline).addLast(any(ChannelHandler.class));
150         doReturn(mock(ChannelFuture.class)).when(this.speakerListener).close();
151
152         final BGPPeerRegistry peerRegistry = new StrictBGPPeerRegistry();
153         peerRegistry.addPeer(new IpAddress(new Ipv4Address(peerAddress.getHostAddress())),
154                 new SimpleSessionListener(), prefs);
155
156         this.clientSession = new BGPClientSessionNegotiator(new DefaultPromise<>(GlobalEventExecutor.INSTANCE),
157                 this.speakerListener, peerRegistry);
158
159         this.classicOpen = new OpenBuilder()
160                 .setMyAsNumber(Uint16.valueOf(30))
161                 .setHoldTimer(Uint16.valueOf(3))
162                 .setVersion(new ProtocolVersion(Uint8.valueOf(4)))
163                 .setBgpParameters(tlvs)
164                 .setBgpIdentifier(new Ipv4Address("1.1.1.2"))
165                 .build();
166     }
167
168     @Test
169     public void testDenyPeer() {
170         this.clientSession = new BGPClientSessionNegotiator(new DefaultPromise<>(GlobalEventExecutor.INSTANCE),
171                 this.speakerListener, new StrictBGPPeerRegistry());
172         this.clientSession.channelActive(null);
173         assertEquals(1, this.receivedMsgs.size());
174         assertTrue(this.receivedMsgs.get(0) instanceof Notify);
175     }
176
177     @Test
178     public void testAccSessionChar() {
179         this.clientSession.channelActive(null);
180         assertEquals(1, this.receivedMsgs.size());
181         assertTrue(this.receivedMsgs.get(0) instanceof Open);
182         this.clientSession.handleMessage(this.classicOpen);
183         assertEquals(2, this.receivedMsgs.size());
184         assertTrue(this.receivedMsgs.get(1) instanceof Keepalive);
185         this.clientSession.handleMessage(new KeepaliveBuilder().build());
186         assertEquals(this.clientSession.getState(), BGPClientSessionNegotiator.State.FINISHED);
187     }
188
189     @Test
190     public void testNotAccChars() {
191         this.clientSession.channelActive(null);
192         assertEquals(1, this.receivedMsgs.size());
193         assertTrue(this.receivedMsgs.get(0) instanceof Open);
194         this.clientSession.handleMessage(new OpenBuilder()
195             .setMyAsNumber(Uint16.valueOf(30))
196             .setHoldTimer(Uint16.ONE)
197             .setBgpIdentifier(new Ipv4Address("127.0.0.1"))
198             .setVersion(new ProtocolVersion(Uint8.valueOf(4)))
199             .build());
200         assertEquals(2, this.receivedMsgs.size());
201         assertTrue(this.receivedMsgs.get(1) instanceof Notify);
202         final Notification m = this.receivedMsgs.get(this.receivedMsgs.size() - 1);
203         assertEquals(BGPError.UNSPECIFIC_OPEN_ERROR,
204                 BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
205     }
206
207     @Test
208     public void testNoAs4BytesCapability() {
209         this.clientSession.channelActive(null);
210         assertEquals(1, this.receivedMsgs.size());
211         assertTrue(this.receivedMsgs.get(0) instanceof Open);
212
213         final List<BgpParameters> tlvs = new ArrayList<>();
214         final List<OptionalCapabilities> capas = new ArrayList<>();
215         capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder()
216                 .addAugmentation(CParameters1.class,
217                         new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
218                                 .setAfi(this.ipv4tt.getAfi()).setSafi(this.ipv4tt.getSafi())
219                                 .build()).build()).build()).build());
220         capas.add(new OptionalCapabilitiesBuilder()
221                 .setCParameters(BgpExtendedMessageUtil.EXTENDED_MESSAGE_CAPABILITY).build());
222         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
223         // Open Message without advertised four-octet AS Number capability
224         this.clientSession.handleMessage(new OpenBuilder()
225             .setMyAsNumber(Uint16.valueOf(30))
226             .setHoldTimer(Uint16.ONE)
227             .setVersion(new ProtocolVersion(Uint8.valueOf(4)))
228             .setBgpParameters(tlvs)
229             .setBgpIdentifier(new Ipv4Address("1.1.1.2"))
230             .build());
231         assertEquals(2, this.receivedMsgs.size());
232         assertTrue(this.receivedMsgs.get(1) instanceof Notify);
233         final Notification m = this.receivedMsgs.get(this.receivedMsgs.size() - 1);
234         assertEquals(BGPError.UNSUPPORTED_CAPABILITY,
235                 BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
236         assertNotNull(((Notify) m).getData());
237     }
238
239     @Test
240     public void testBgpExtendedMessageCapability() {
241         this.clientSession.channelActive(null);
242         assertEquals(1, this.receivedMsgs.size());
243         assertTrue(this.receivedMsgs.get(0) instanceof Open);
244
245         final List<BgpParameters> tlvs = new ArrayList<>();
246         final List<OptionalCapabilities> capas = new ArrayList<>();
247         capas.add(new OptionalCapabilitiesBuilder()
248             .setCParameters(new CParametersBuilder()
249                 .addAugmentation(CParameters1.class, new CParameters1Builder()
250                     .setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
251                         .setAfi(this.ipv4tt.getAfi())
252                         .setSafi(this.ipv4tt.getSafi())
253                         .build())
254                     .build())
255                 .build())
256             .build());
257         capas.add(new OptionalCapabilitiesBuilder()
258             .setCParameters(new CParametersBuilder()
259                 .setAs4BytesCapability(new As4BytesCapabilityBuilder()
260                     .setAsNumber(new AsNumber(Uint32.valueOf(30)))
261                     .build())
262                 .build())
263             .build());
264         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
265         this.clientSession.handleMessage(new OpenBuilder()
266             .setMyAsNumber(Uint16.valueOf(30))
267             .setHoldTimer(Uint16.ONE)
268             .setVersion(new ProtocolVersion(Uint8.valueOf(4)))
269             .setBgpParameters(tlvs)
270             .setBgpIdentifier(new Ipv4Address("1.1.1.2"))
271             .build());
272         assertEquals(2, this.receivedMsgs.size());
273         assertTrue(this.receivedMsgs.get(1) instanceof Keepalive);
274     }
275
276     @Test
277     public void sendNotification() {
278         this.clientSession.channelActive(null);
279         this.clientSession.handleMessage(this.classicOpen);
280         this.clientSession.handleMessage(new KeepaliveBuilder().build());
281         assertEquals(this.clientSession.getState(), BGPClientSessionNegotiator.State.FINISHED);
282         this.clientSession.handleMessage(new OpenBuilder()
283             .setMyAsNumber(Uint16.valueOf(30))
284             .setHoldTimer(Uint16.valueOf(3))
285             .setVersion(new ProtocolVersion(Uint8.valueOf(4)))
286             .build());
287         assertEquals(3, this.receivedMsgs.size());
288         assertTrue(this.receivedMsgs.get(2) instanceof Notify);
289         final Notification m = this.receivedMsgs.get(2);
290         assertEquals(BGPError.FSM_ERROR.getCode(), ((Notify) m).getErrorCode());
291         assertEquals(BGPError.FSM_ERROR.getSubcode(), ((Notify) m).getErrorSubcode());
292     }
293
294     @Test
295     public void sameBGPIDs() {
296         this.clientSession.channelActive(null);
297         assertEquals(1, this.receivedMsgs.size());
298         assertTrue(this.receivedMsgs.get(0) instanceof Open);
299
300         this.clientSession.handleMessage(new OpenBuilder(this.classicOpen)
301                 .setBgpIdentifier(new Ipv4Address("1.1.1.1")).build());
302         assertEquals(2, this.receivedMsgs.size());
303         assertTrue(this.receivedMsgs.get(1) instanceof Notify);
304         final Notification m = this.receivedMsgs.get(this.receivedMsgs.size() - 1);
305         assertEquals(BGPError.BAD_BGP_ID, BGPError.forValue(((Notify) m).getErrorCode(),
306                 ((Notify) m).getErrorSubcode()));
307     }
308 }