Remove RIBImpl's use of DataBroker
[bgpcep.git] / bgp / rib-impl / src / test / java / org / opendaylight / protocol / bgp / rib / impl / GracefulRestartTest.java
1 /*
2  * Copyright (c) 2018 AT&T Intellectual Property. 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.assertFalse;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.opendaylight.protocol.bgp.rib.impl.CheckUtil.checkIdleState;
15 import static org.opendaylight.protocol.bgp.rib.impl.CheckUtil.checkStateIsNotRestarting;
16 import static org.opendaylight.protocol.bgp.rib.impl.CheckUtil.checkUpState;
17 import static org.opendaylight.protocol.util.CheckUtil.checkReceivedMessages;
18 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
19 import static org.opendaylight.protocol.util.CheckUtil.waitFutureSuccess;
20
21 import com.google.common.collect.ImmutableMap;
22 import io.netty.channel.Channel;
23 import io.netty.channel.ChannelFuture;
24 import java.net.InetSocketAddress;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Optional;
33 import java.util.Set;
34 import java.util.stream.Collectors;
35 import org.junit.After;
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.mockito.Mockito;
39 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
40 import org.opendaylight.protocol.bgp.mode.impl.add.all.paths.AllPathSelection;
41 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
42 import org.opendaylight.protocol.bgp.rib.impl.config.BgpPeer;
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.IpPrefix;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.bgp.rib.rib.loc.rib.tables.routes.Ipv4RoutesCase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.bgp.rib.rib.loc.rib.tables.routes.Ipv6RoutesCase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Open;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.OpenBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.ProtocolVersion;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Update;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.BgpParameters;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlri;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.BgpRib;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.RibId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.Rib;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.RibKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpOrigin;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv6AddressFamily;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.UnicastSubsequentAddressFamily;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
71 import org.opendaylight.yangtools.yang.binding.Notification;
72 import org.opendaylight.yangtools.yang.common.Uint16;
73 import org.opendaylight.yangtools.yang.common.Uint8;
74
75 public class GracefulRestartTest extends AbstractAddPathTest {
76
77     private BGPSessionImpl session;
78     private BGPSessionImpl sessionv6;
79     private BGPPeer peer;
80     private BGPPeer nonIpv4;
81     private final Set<TablesKey> afiSafiAdvertised = new HashSet<>();
82     private final Set<TablesKey> gracefulAfiSafiAdvertised = new HashSet<>();
83     private RIBImpl ribImpl;
84     private Channel serverChannel;
85     private final SimpleSessionListener listener = new SimpleSessionListener();
86     private final BgpParameters parameters = createParameter(false, true, Collections.singletonMap(TABLES_KEY, true));
87     private static final int DEFERRAL_TIMER = 5;
88     private static final RibId RIBID = new RibId("test-rib");
89     private static final Ipv4Prefix PREFIX2 = new Ipv4Prefix("2.2.2.2/32");
90     private static final Ipv6Prefix PREFIX3 = new Ipv6Prefix("dead:beef::/64");
91     private static final Ipv6AddressNoZone IPV6_NEXT_HOP = new Ipv6AddressNoZone("dead:beef::1");
92     private static final TablesKey IPV6_TABLES_KEY = new TablesKey(Ipv6AddressFamily.class,
93             UnicastSubsequentAddressFamily.class);
94
95     private static final InstanceIdentifier<LocRib> LOC_RIB_IID = InstanceIdentifier.builder(BgpRib.class)
96             .child(Rib.class, new RibKey(RIBID))
97             .child(LocRib.class)
98             .build();
99     private static final InstanceIdentifier<Tables> IPV4_IID = LOC_RIB_IID.builder()
100             .child(Tables.class,TABLES_KEY)
101             .build();
102     private static final InstanceIdentifier<Tables> IPV6_IID = LOC_RIB_IID.builder()
103             .child(Tables.class, IPV6_TABLES_KEY)
104             .build();
105
106     @Override
107     @Before
108     public void setUp() throws Exception {
109         super.setUp();
110         final Map<TablesKey, PathSelectionMode> pathTables
111                 = ImmutableMap.of(TABLES_KEY, new AllPathSelection());
112         final ArrayList<BgpTableType> tableTypes = new ArrayList<>(TABLES_TYPE);
113         tableTypes.add(new BgpTableTypeImpl(Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class));
114         this.ribImpl = new RIBImpl(this.tableRegistry, RIBID, AS_NUMBER, BGP_ID, this.ribExtension,
115                 this.serverDispatcher, this.codecsRegistry,
116                 getDomBroker(), this.policies, tableTypes, pathTables);
117
118         this.ribImpl.instantiateServiceInstance();
119         final ChannelFuture channelFuture = this.serverDispatcher.createServer(
120             new InetSocketAddress(RIB_ID, PORT.toJava()));
121         waitFutureSuccess(channelFuture);
122         this.serverChannel = channelFuture.channel();
123
124         gracefulAfiSafiAdvertised.add(TABLES_KEY);
125         afiSafiAdvertised.add(TABLES_KEY);
126         afiSafiAdvertised.add(IPV6_TABLES_KEY);
127         final BgpPeer bgpPeer = Mockito.mock(BgpPeer.class);
128         Mockito.doReturn(GRACEFUL_RESTART_TIME).when(bgpPeer).getGracefulRestartTimer();
129         Mockito.doReturn(Optional.empty()).when(bgpPeer).getErrorHandling();
130         Mockito.doReturn(createParameter(false, true, Collections.singletonMap(TABLES_KEY, false))
131                 .getOptionalCapabilities()).when(bgpPeer).getBgpFixedCapabilities();
132         this.peer = configurePeer(this.tableRegistry, PEER1, this.ribImpl, parameters, PeerRole.Ibgp,
133                 this.serverRegistry, afiSafiAdvertised, gracefulAfiSafiAdvertised, Collections.emptyMap(), bgpPeer);
134         this.session = createPeerSession(PEER1, parameters, this.listener);
135     }
136
137     @Override
138     @After
139     public void tearDown() throws Exception {
140         waitFutureSuccess(this.serverChannel.close());
141         this.session.close();
142         super.tearDown();
143     }
144
145     /**
146      * Test graceful restart of a non-IPv4 peer.
147      * {@link BGPPeer#releaseConnection(boolean)} should not throw NPE and binding chain should be closed
148      * successfully.
149      *
150      * @throws InterruptedException on create peer session.
151      */
152     @Test
153     public void nonIpv4PeerGracefulRestart() throws InterruptedException {
154         BgpParameters parametersv6 = PeerUtil.createBgpParameters(Collections.singletonList(IPV6_TABLES_KEY),
155                 Collections.emptyList(), Collections.singletonMap(IPV6_TABLES_KEY, true),
156                 GRACEFUL_RESTART_TIME);
157         gracefulAfiSafiAdvertised.add(IPV6_TABLES_KEY);
158         this.nonIpv4 = configurePeer(this.tableRegistry, PEER2, this.ribImpl, parametersv6, PeerRole.Ibgp,
159                 this.serverRegistry, afiSafiAdvertised, gracefulAfiSafiAdvertised);
160         this.sessionv6 = createPeerSession(PEER2, parametersv6, this.listener);
161         final Open open = createClassicOpen(true);
162         this.sessionv6.writeAndFlush(open);
163         checkIdleState(this.nonIpv4);
164         synchronized (this.nonIpv4) {
165             assertNull(this.nonIpv4.ribOutChain);
166         }
167     }
168
169     /**
170      * Test correct behavior when connection restart is unnoticed.
171      * "Correct" means that the previous TCP session MUST be closed, and the new one retained.
172      * Since the previous connection is considered to be terminated, no NOTIFICATION message should be sent.
173      */
174     @Test
175     public void resetConnectionOnOpenTest() {
176
177         checkReceivedMessages(this.listener, 2);
178         final Open open = createClassicOpen(true);
179         this.session.writeAndFlush(open);
180         checkIdleState(this.peer);
181         checkReceivedMessages(this.listener, 2);
182     }
183
184     /**
185      * Test that routes from peer that has advertised the Graceful Restart Capability MUST be retained
186      * for all the address families that were previously received in the Graceful Restart Capability.
187      *
188      * @throws Exception on reading Rib failure
189      */
190     @Test
191     public void retainRoutesOnPeerRestartTest() throws Exception {
192         final List<Ipv4Prefix> ipv4Prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1), new Ipv4Prefix(PREFIX2));
193         final List<Ipv6Prefix> ipv6Prefixes = Collections.singletonList(new Ipv6Prefix(PREFIX3));
194         insertRoutes(ipv4Prefixes, ipv6Prefixes);
195         checkLocRibIpv4Routes(2);
196         checkLocRibIpv6Routes(1);
197
198         this.session.close();
199         checkIdleState(this.peer);
200         checkLocRibIpv4Routes(2);
201         checkLocRibIpv6Routes(0);
202     }
203
204     /**
205      * If the session does not get re-established within the "Restart Time"
206      * that the peer advertised previously, the Receiving Speaker MUST
207      * delete all the stale routes from the peer that it is retaining.
208      *
209      * @throws Exception on reading Rib failure
210      */
211     @Test
212     public void removeRoutesOnHoldTimeExpireTest() throws Exception {
213         retainRoutesOnPeerRestartTest();
214         checkStateIsNotRestarting(peer, GRACEFUL_RESTART_TIME);
215         checkLocRibIpv4Routes(0);
216         checkLocRibIpv6Routes(0);
217     }
218
219     /**
220      * Once the session is re-established, if the Graceful
221      * Restart Capability is not received in the re-established session at
222      * all, then the Receiving Speaker MUST immediately remove all the stale
223      * routes from the peer that it is retaining for that address family.
224      *
225      * @throws Exception on reading Rib failure
226      */
227     @Test
228     public void removeRoutesOnMissingGracefulRestartTest() throws Exception {
229         retainRoutesOnPeerRestartTest();
230         this.session = createPeerSession(PEER1, createParameter(false, true, null), this.listener);
231         checkUpState(listener);
232         checkLocRibIpv4Routes(0);
233         checkLocRibIpv6Routes(0);
234     }
235
236     /**
237      * Once the session is re-established, if a specific address family is not included
238      * in the newly received Graceful Restart Capability, then the Receiving Speaker
239      * MUST immediately remove all the stale routes from the peer that it is retaining
240      * for that address family.
241      *
242      *
243      * @throws Exception on reading Rib failure
244      */
245     @Test
246     public void removeRoutesOnMissingGracefulRestartAfiSafiTest() throws Exception {
247         retainRoutesOnPeerRestartTest();
248         this.session = createPeerSession(PEER1, createParameter(false, true,
249                 Collections.singletonMap(TABLES_KEY, false)), this.listener);
250         checkUpState(listener);
251         checkUpState(this.peer);
252         checkLocRibIpv4Routes(0);
253         checkLocRibIpv6Routes(0);
254     }
255
256     /**
257      * Once the End-of-RIB marker for an address family is received from the peer, it MUST
258      * immediately remove any routes from the peer that are still marked as stale for that
259      * address family.
260      *
261      * @throws Exception on reading Rib failure
262      */
263     @Test
264     public void removeStaleRoutesAfterRestartTest() throws Exception {
265         retainRoutesOnPeerRestartTest();
266         this.session = createPeerSession(PEER1, createParameter(false, true,
267                 Collections.singletonMap(TABLES_KEY, true)), this.listener);
268         checkUpState(this.listener);
269         final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
270         insertRoutes(ipv4prefixes, null);
271         insertRoutes(null, null);
272         checkLocRibIpv4Routes(1);
273         checkLocRibIpv6Routes(0);
274     }
275
276     /**
277      * Perform local graceful restart and verify routes are preserved.
278      *
279      * @throws Exception on reading Rib failure
280      */
281     @Test
282     public void performLocalGracefulRestart() throws Exception {
283         final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1), new Ipv4Prefix(PREFIX2));
284         final List<Ipv6Prefix> ipv6prefixes = Arrays.asList(new Ipv6Prefix(PREFIX3));
285         insertRoutes(ipv4prefixes, ipv6prefixes);
286         checkLocRibIpv4Routes(2);
287         checkLocRibIpv6Routes(1);
288
289         this.peer.restartGracefully(DEFERRAL_TIMER).get();
290         this.session = createPeerSession(PEER1, this.parameters, this.listener);
291         checkUpState(this.listener);
292         checkUpState(this.peer);
293         checkLocRibIpv4Routes(2);
294         checkLocRibIpv6Routes(0);
295     }
296
297     /**
298      * Wait with route selection until EOT is received.
299      *
300      * @throws Exception on reading Rib failure
301      */
302     @Test
303     public void waitForEORonLocalGracefulRestart() throws Exception {
304         performLocalGracefulRestart();
305         final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
306         final List<Ipv6Prefix> ipv6prefixes = Arrays.asList(new Ipv6Prefix(PREFIX3));
307         insertRoutes(ipv4prefixes, ipv6prefixes);
308         checkLocRibIpv4Routes(2);
309         checkLocRibIpv6Routes(0);
310         insertRoutes(null, null);
311         checkLocRibIpv4Routes(2);
312         checkLocRibIpv6Routes(1);
313     }
314
315     /**
316      * Wait with route selection until deferral time is expired.
317      *
318      * @throws Exception on reading Rib failure
319      */
320     @Test
321     public void waitForDeferralTimerOnLocalGracefulRestart() throws Exception {
322         performLocalGracefulRestart();
323         final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
324         final List<Ipv6Prefix> ipv6prefixes = Arrays.asList(new Ipv6Prefix(PREFIX3));
325         insertRoutes(ipv4prefixes, ipv6prefixes);
326         checkLocRibIpv4Routes(2);
327         checkLocRibIpv6Routes(0);
328         checkStateIsNotRestarting(this.peer, DEFERRAL_TIMER);
329         checkLocRibIpv4Routes(2);
330         checkLocRibIpv6Routes(1);
331     }
332
333     /**
334      * After graceful restart is performed from peer side we have to re-advertise routes followed by
335      * End-of-RIB marker.
336      *
337      * @throws Exception on reading Rib failure
338      */
339     @Test
340     public void verifySendEORafterRestartTest() throws Exception {
341         final SimpleSessionListener listener2 = new SimpleSessionListener();
342         configurePeer(this.tableRegistry, PEER2, this.ribImpl, this.parameters, PeerRole.Ebgp,
343                 this.serverRegistry, afiSafiAdvertised, gracefulAfiSafiAdvertised);
344         final BGPSessionImpl session2 = createPeerSession(PEER2, this.parameters, listener2);
345         final List<Ipv4Prefix> ipv4Prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
346         final List<Ipv4Prefix> ipv4Prefixes2 = Arrays.asList(new Ipv4Prefix(PREFIX2));
347         final List<Ipv6Prefix> ipv6Prefixes = Collections.singletonList(new Ipv6Prefix(PREFIX3));
348         insertRoutes(ipv4Prefixes, ipv6Prefixes);
349         insertRoutes(ipv4Prefixes2, PEER2, null, null, session2, BgpOrigin.Egp);
350         checkLocRibIpv4Routes(2);
351         checkLocRibIpv6Routes(1);
352         org.opendaylight.protocol.util.CheckUtil.checkReceivedMessages(this.listener, 3);
353         // verify sending of Ipv4 EOT, Ipv6 EOT and Ipv4 update with route
354         checkReceivedMessages(this.listener, 3);
355         assertTrue(this.listener.getListMsg().get(0) instanceof Update);
356         assertTrue(BgpPeerUtil.isEndOfRib((Update)this.listener.getListMsg().get(0)));
357         assertTrue(this.listener.getListMsg().get(1) instanceof Update);
358         assertTrue(BgpPeerUtil.isEndOfRib((Update)this.listener.getListMsg().get(1)));
359         assertTrue(this.listener.getListMsg().get(2) instanceof Update);
360         assertFalse(BgpPeerUtil.isEndOfRib((Update)this.listener.getListMsg().get(2)));
361
362         this.session.close();
363         checkIdleState(this.peer);
364         checkLocRibIpv4Routes(2);
365         checkLocRibIpv6Routes(0);
366         // verify nothing new was sent
367         checkReceivedMessages(this.listener, 3);
368
369         this.session = createPeerSession(PEER1, createParameter(false, true,
370                 Collections.singletonMap(TABLES_KEY, true)), this.listener);
371         checkUpState(listener);
372         checkUpState(this.peer);
373         org.opendaylight.protocol.util.CheckUtil.checkReceivedMessages(this.listener, 6);
374         // verify sending of Ipv4 update with route, Ipv4 EOT and Ipv6 EOT; order can vary based on ODTC order
375         final List<Notification> subList = this.listener.getListMsg().subList(3, 6);
376         int eotCount = 0;
377         int routeUpdateCount = 0;
378         for (Notification message : subList) {
379             if (BgpPeerUtil.isEndOfRib((Update) message)) {
380                 eotCount++;
381             } else {
382                 routeUpdateCount++;
383             }
384         }
385         assertEquals(2, eotCount);
386         assertEquals(1, routeUpdateCount);
387     }
388
389     private void checkLocRibIpv4Routes(final int expectedRoutesOnDS) throws Exception {
390         readDataOperational(getDataBroker(), IPV4_IID, table -> {
391             int size = 0;
392             final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes();
393             if (routesCase != null && routesCase.getIpv4Routes() != null
394                     && routesCase.getIpv4Routes().getIpv4Route() != null) {
395                 size = routesCase.getIpv4Routes().getIpv4Route().size();
396             }
397             assertEquals(expectedRoutesOnDS, size);
398             return table;
399         });
400     }
401
402     private void checkLocRibIpv6Routes(final int expectedRoutesOnDS) throws Exception {
403         readDataOperational(getDataBroker(), IPV6_IID, table -> {
404             int size = 0;
405             final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) table.getRoutes();
406             if (routesCase != null && routesCase.getIpv6Routes() != null
407                     && routesCase.getIpv6Routes().getIpv6Route() != null) {
408                 size = routesCase.getIpv6Routes().getIpv6Route().size();
409             }
410             assertEquals(expectedRoutesOnDS, size);
411             return table;
412         });
413     }
414
415     private void insertRoutes(final List<Ipv4Prefix> ipv4prefixes, final List<Ipv6Prefix> ipv6prefixes) {
416         insertRoutes(ipv4prefixes, PEER1, ipv6prefixes, IPV6_NEXT_HOP, this.session, BgpOrigin.Igp);
417     }
418
419     private static void insertRoutes(final List<Ipv4Prefix> ipv4prefixes, final Ipv4AddressNoZone ipv4NeighborAddress,
420                               final List<Ipv6Prefix> ipv6prefixes, final Ipv6AddressNoZone ipv6NeighborAddress,
421                               final BGPSessionImpl session, final BgpOrigin peerRole) {
422         if (ipv4prefixes == null && ipv6prefixes == null) {
423             waitFutureSuccess(session.writeAndFlush(BgpPeerUtil.createEndOfRib(TABLES_KEY)));
424             waitFutureSuccess(session.writeAndFlush(BgpPeerUtil.createEndOfRib(IPV6_TABLES_KEY)));
425             return;
426         }
427
428         if (ipv4prefixes != null && !ipv4prefixes.isEmpty()) {
429             final MpReachNlri reachIpv4 = PeerUtil.createMpReachNlri(new IpAddressNoZone(ipv4NeighborAddress),
430                     ipv4prefixes.stream()
431                             .map(IpPrefix::new)
432                             .collect(Collectors.toList()));
433             final Update update1 = PeerUtil.createUpdate(peerRole, Collections.emptyList(), 100, reachIpv4, null);
434             waitFutureSuccess(session.writeAndFlush(update1));
435         }
436
437         if (ipv6prefixes != null && !ipv4prefixes.isEmpty()) {
438             final MpReachNlri reachIpv6 = PeerUtil.createMpReachNlri(new IpAddressNoZone(ipv6NeighborAddress),
439                     ipv6prefixes.stream()
440                             .map(IpPrefix::new)
441                             .collect(Collectors.toList()));
442             final Update update2 = PeerUtil.createUpdate(peerRole, Collections.emptyList(), 100, reachIpv6, null);
443             waitFutureSuccess(session.writeAndFlush(update2));
444         }
445     }
446
447     private static Open createClassicOpen(final boolean addGraceful) {
448         final Map<TablesKey, Boolean> graceful = new HashMap<>();
449         if (addGraceful) {
450             graceful.put(new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class), true);
451         }
452         return new OpenBuilder()
453                 .setMyAsNumber(Uint16.valueOf(AS))
454                 .setHoldTimer(Uint16.valueOf(HOLDTIMER))
455                 .setVersion(new ProtocolVersion(Uint8.valueOf(4)))
456                 .setBgpParameters(Collections.singletonList(createParameter(false, true, graceful)))
457                 .setBgpIdentifier(PEER1)
458                 .build();
459     }
460 }