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.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;
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.IpAddressNoZone;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
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;
72 public class FSMTest {
74 private EventLoop eventLoop;
76 private BGPClientSessionNegotiator clientSession;
79 private Channel speakerListener;
82 private ChannelPipeline pipeline;
84 private final BgpTableType ipv4tt
85 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
87 private final BgpTableType linkstatett
88 = new BgpTableTypeImpl(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class);
90 private final List<Notification> receivedMsgs = new ArrayList<>();
92 private Open classicOpen;
95 public void setUp() throws UnknownHostException {
96 MockitoAnnotations.initMocks(this);
97 final List<BgpParameters> tlvs = new ArrayList<>();
98 final List<OptionalCapabilities> capas = new ArrayList<>();
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())
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)))
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());
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);
129 final ChannelFuture f = mock(ChannelFuture.class);
130 doReturn(null).when(f).addListener(any(GenericFutureListener.class));
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]);
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();
152 final BGPPeerRegistry peerRegistry = new StrictBGPPeerRegistry();
153 peerRegistry.addPeer(new IpAddressNoZone(new Ipv4AddressNoZone(peerAddress.getHostAddress())),
154 new SimpleSessionListener(), prefs);
156 this.clientSession = new BGPClientSessionNegotiator(new DefaultPromise<>(GlobalEventExecutor.INSTANCE),
157 this.speakerListener, peerRegistry);
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 Ipv4AddressNoZone("1.1.1.2"))
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);
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);
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 Ipv4AddressNoZone("127.0.0.1"))
198 .setVersion(new ProtocolVersion(Uint8.valueOf(4)))
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()));
208 public void testNoAs4BytesCapability() {
209 this.clientSession.channelActive(null);
210 assertEquals(1, this.receivedMsgs.size());
211 assertTrue(this.receivedMsgs.get(0) instanceof Open);
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 Ipv4AddressNoZone("1.1.1.2"))
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());
240 public void testBgpExtendedMessageCapability() {
241 this.clientSession.channelActive(null);
242 assertEquals(1, this.receivedMsgs.size());
243 assertTrue(this.receivedMsgs.get(0) instanceof Open);
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())
257 capas.add(new OptionalCapabilitiesBuilder()
258 .setCParameters(new CParametersBuilder()
259 .setAs4BytesCapability(new As4BytesCapabilityBuilder()
260 .setAsNumber(new AsNumber(Uint32.valueOf(30)))
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 Ipv4AddressNoZone("1.1.1.2"))
272 assertEquals(2, this.receivedMsgs.size());
273 assertTrue(this.receivedMsgs.get(1) instanceof Keepalive);
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)))
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());
295 public void sameBGPIDs() {
296 this.clientSession.channelActive(null);
297 assertEquals(1, this.receivedMsgs.size());
298 assertTrue(this.receivedMsgs.get(0) instanceof Open);
300 this.clientSession.handleMessage(new OpenBuilder(this.classicOpen)
301 .setBgpIdentifier(new Ipv4AddressNoZone("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()));