Rename multiprotocol augmentations
[bgpcep.git] / bgp / rib-impl / src / test / java / org / opendaylight / protocol / bgp / rib / impl / AbstractAddPathTest.java
1 /*
2  * Copyright (c) 2016 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.mockito.ArgumentMatchers.any;
11 import static org.mockito.Mockito.doReturn;
12 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
13 import static org.opendaylight.protocol.util.CheckUtil.waitFutureSuccess;
14
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.Lists;
17 import io.netty.channel.epoll.Epoll;
18 import io.netty.channel.nio.NioEventLoopGroup;
19 import io.netty.util.concurrent.Future;
20 import java.net.InetSocketAddress;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Optional;
26 import java.util.Set;
27 import java.util.concurrent.TimeUnit;
28 import org.junit.After;
29 import org.junit.Assert;
30 import org.junit.Before;
31 import org.mockito.Mock;
32 import org.mockito.Mockito;
33 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
34 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
35 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
36 import org.opendaylight.protocol.bgp.inet.RIBActivator;
37 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
38 import org.opendaylight.protocol.bgp.parser.BGPError;
39 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
40 import org.opendaylight.protocol.bgp.parser.impl.BGPActivator;
41 import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
42 import org.opendaylight.protocol.bgp.parser.spi.pojo.SimpleBGPExtensionProviderContext;
43 import org.opendaylight.protocol.bgp.rib.impl.config.BgpPeer;
44 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
45 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
46 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
47 import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext;
48 import org.opendaylight.protocol.util.InetSocketAddressUtil;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.bgp.rib.rib.loc.rib.tables.routes.Ipv4RoutesCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.DestinationIpv4Builder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4PrefixesBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.routes.Ipv4Routes;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.routes.ipv4.routes.Ipv4Route;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.routes.ipv4.routes.Ipv4RouteKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationIpv4CaseBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.NotifyBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Open;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.OpenBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Update;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.UpdateBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.BgpParameters;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.AsPathBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.ClusterIdBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.LocalPrefBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.MultiExitDiscBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.OriginBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.OriginatorIdBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.as.path.SegmentsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.update.message.WithdrawnRoutesBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesReachBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlriBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.BgpRib;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpId;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpOrigin;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.ClusterIdentifier;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv6AddressFamily;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.UnicastSubsequentAddressFamily;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.next.hop.c.next.hop.Ipv4NextHopCaseBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.next.hop.c.next.hop.ipv4.next.hop._case.Ipv4NextHopBuilder;
92 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
93 import org.opendaylight.yangtools.yang.binding.Notification;
94 import org.opendaylight.yangtools.yang.common.Uint16;
95 import org.opendaylight.yangtools.yang.common.Uint32;
96
97 public abstract class AbstractAddPathTest extends DefaultRibPoliciesMockTest {
98     private static final int RETRY_TIMER = 10;
99     static final String RIB_ID = "127.0.0.1";
100     static final BgpId BGP_ID = new BgpId(RIB_ID);
101     static final Ipv4AddressNoZone PEER1 = new Ipv4AddressNoZone("127.0.0.2");
102     static final Ipv4AddressNoZone PEER2 = new Ipv4AddressNoZone("127.0.0.3");
103     static final Ipv4AddressNoZone PEER3 = new Ipv4AddressNoZone("127.0.0.4");
104     static final Ipv4AddressNoZone PEER4 = new Ipv4AddressNoZone("127.0.0.5");
105     static final Ipv4AddressNoZone PEER5 = new Ipv4AddressNoZone("127.0.0.6");
106     static final Ipv4AddressNoZone PEER6 = new Ipv4AddressNoZone("127.0.0.7");
107     static final AsNumber AS_NUMBER = new AsNumber(Uint32.valueOf(AS));
108     static final Uint16 PORT = Uint16.valueOf(InetSocketAddressUtil.getRandomPort());
109     static final Ipv4Prefix PREFIX1 = new Ipv4Prefix("1.1.1.1/32");
110     private static final ClusterIdentifier CLUSTER_ID = new ClusterIdentifier(RIB_ID);
111     static final int HOLDTIMER = 2180;
112     private static final Ipv4AddressNoZone NH1 = new Ipv4AddressNoZone("2.2.2.2");
113     static final Update UPD_100 = createSimpleUpdate(PREFIX1, new PathId(Uint32.ONE), CLUSTER_ID, 100);
114     static final Update UPD_50 = createSimpleUpdate(PREFIX1, new PathId(Uint32.TWO), CLUSTER_ID, 50);
115     static final Update UPD_200 = createSimpleUpdate(PREFIX1, new PathId(Uint32.valueOf(3)), CLUSTER_ID, 200);
116     static final Update UPD_20 = createSimpleUpdate(PREFIX1, new PathId(Uint32.ONE), CLUSTER_ID, 20);
117     static final Update UPD_NA_100 = createSimpleUpdate(PREFIX1, null, CLUSTER_ID, 100);
118     static final Update UPD_NA_100_EBGP = createSimpleUpdateEbgp(PREFIX1);
119     static final Update UPD_NA_200 = createSimpleUpdate(PREFIX1, null, CLUSTER_ID, 200);
120     static final Update UPD_NA_200_EBGP = createSimpleUpdateEbgp(PREFIX1);
121     static final TablesKey TABLES_KEY = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
122     static final List<BgpTableType> TABLES_TYPE = ImmutableList.of(new BgpTableTypeImpl(TABLES_KEY.getAfi(),
123         TABLES_KEY.getSafi()));
124     static final Set<TablesKey> AFI_SAFIS_ADVERTIZED = Collections.singleton(TABLES_KEY);
125
126     static final InstanceIdentifier<BgpRib> BGP_IID = InstanceIdentifier.create(BgpRib.class);
127     static final int GRACEFUL_RESTART_TIME = 5;
128     @Mock
129     protected ClusterSingletonServiceProvider clusterSingletonServiceProvider;
130     BGPDispatcherImpl serverDispatcher;
131     final RIBExtensionProviderContext ribExtension = new SimpleRIBExtensionProviderContext();
132     private final BGPExtensionProviderContext context = new SimpleBGPExtensionProviderContext();
133     private final RIBActivator ribActivator = new RIBActivator();
134     private BGPActivator bgpActivator;
135     private NioEventLoopGroup worker;
136     private NioEventLoopGroup boss;
137     private org.opendaylight.protocol.bgp.inet.BGPActivator inetActivator;
138     protected StrictBGPPeerRegistry serverRegistry;
139     protected ConstantCodecsRegistry codecsRegistry;
140
141     private List<BGPDispatcherImpl> clientDispatchers;
142
143     @Override
144     @Before
145     public void setUp() throws Exception {
146         super.setUp();
147
148         this.ribActivator.startRIBExtensionProvider(this.ribExtension, this.mappingService.currentSerializer());
149
150         this.bgpActivator = new BGPActivator();
151         this.inetActivator = new org.opendaylight.protocol.bgp.inet.BGPActivator();
152         this.bgpActivator.start(this.context);
153         this.inetActivator.start(this.context);
154         if (!Epoll.isAvailable()) {
155             this.worker = new NioEventLoopGroup();
156             this.boss = new NioEventLoopGroup();
157         }
158         this.serverRegistry = new StrictBGPPeerRegistry();
159         this.serverDispatcher = new BGPDispatcherImpl(this.context.getMessageRegistry(), this.boss, this.worker,
160             this.serverRegistry);
161         doReturn(Mockito.mock(ClusterSingletonServiceRegistration.class)).when(this.clusterSingletonServiceProvider)
162             .registerClusterSingletonService(any(ClusterSingletonService.class));
163
164         this.codecsRegistry = new ConstantCodecsRegistry(mappingService.currentSerializer());
165         this.clientDispatchers = new ArrayList<>();
166     }
167
168     @Override
169     @After
170     public void tearDown() throws Exception {
171         this.serverDispatcher.close();
172         if (!Epoll.isAvailable()) {
173             this.worker.shutdownGracefully(0, 0, TimeUnit.SECONDS);
174             this.boss.shutdownGracefully(0, 0, TimeUnit.SECONDS);
175         }
176         this.clientDispatchers.forEach(BGPDispatcherImpl::close);
177         this.clientDispatchers = null;
178
179         super.tearDown();
180     }
181
182     void sendRouteAndCheckIsOnLocRib(final BGPSessionImpl session, final Ipv4Prefix prefix, final long localPreference,
183         final int expectedRoutesOnDS) throws Exception {
184         waitFutureSuccess(session.writeAndFlush(createSimpleUpdate(prefix, null, null, localPreference)));
185         checkLocRib(expectedRoutesOnDS);
186     }
187
188     void sendWithdrawalRouteAndCheckIsOnLocRib(final BGPSessionImpl session, final Ipv4Prefix prefix,
189         final long localPreference, final int expectedRoutesOnDS) throws Exception {
190         waitFutureSuccess(session.writeAndFlush(createSimpleWithdrawalUpdate(prefix, localPreference)));
191         checkLocRib(expectedRoutesOnDS);
192     }
193
194     void sendNotification(final BGPSessionImpl session) {
195         final Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode())
196             .setErrorSubcode(BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
197         waitFutureSuccess(session.writeAndFlush(notMsg));
198     }
199
200     void causeBGPError(final BGPSessionImpl session) {
201         final Open openObj = new OpenBuilder().setBgpIdentifier(new Ipv4AddressNoZone("1.1.1.1"))
202             .setHoldTimer(Uint16.valueOf(50)).setMyAsNumber(Uint16.valueOf(72)).build();
203         waitFutureSuccess(session.writeAndFlush(openObj));
204     }
205
206     private void checkLocRib(final int expectedRoutesOnDS) throws Exception {
207         // FIXME: remove this sleep
208         Thread.sleep(100);
209         readDataOperational(getDataBroker(), BGP_IID, bgpRib -> {
210             final Ipv4RoutesCase routes = (Ipv4RoutesCase) bgpRib.getRib().values().iterator().next().getLocRib()
211                     .getTables().values().iterator().next().getRoutes();
212             final int size;
213             if (routes != null) {
214                 final Ipv4Routes routesCase = routes.getIpv4Routes();
215                 if (routesCase != null) {
216                     final Map<Ipv4RouteKey, Ipv4Route> routeList = routesCase.getIpv4Route();
217                     size = routeList == null ? 0 : routeList.size();
218                 } else {
219                     size = 0;
220                 }
221             } else {
222                 size = 0;
223             }
224
225             Assert.assertEquals(expectedRoutesOnDS, size);
226             return bgpRib;
227         });
228     }
229
230     void checkPeersPresentOnDataStore(final int numberOfPeers) throws Exception {
231         readDataOperational(getDataBroker(), BGP_IID, bgpRib -> {
232             Assert.assertEquals(numberOfPeers, bgpRib.getRib().values().iterator().next().getPeer().size());
233             return bgpRib;
234         });
235     }
236
237     BGPSessionImpl createPeerSession(final Ipv4AddressNoZone peer, final BgpParameters bgpParameters,
238         final SimpleSessionListener sessionListener) throws InterruptedException {
239         return createPeerSession(peer, bgpParameters, sessionListener, AS_NUMBER);
240     }
241
242     BGPSessionImpl createPeerSession(final Ipv4AddressNoZone peer, final BgpParameters bgpParameters,
243                                      final SimpleSessionListener sessionListener,
244                                      final AsNumber remoteAsNumber) throws InterruptedException {
245         final StrictBGPPeerRegistry clientRegistry = new StrictBGPPeerRegistry();
246         final BGPDispatcherImpl clientDispatcher = new BGPDispatcherImpl(this.context.getMessageRegistry(), this.boss,
247                 this.worker, clientRegistry);
248
249         clientDispatchers.add(clientDispatcher);
250         clientRegistry.addPeer(new IpAddressNoZone(new Ipv4AddressNoZone(RIB_ID)), sessionListener,
251                 new BGPSessionPreferences(remoteAsNumber, HOLDTIMER, new BgpId(peer),
252                         AS_NUMBER, Lists.newArrayList(bgpParameters)));
253
254         return connectPeer(peer, clientDispatcher);
255     }
256
257     static BGPPeer configurePeer(final BGPTableTypeRegistryConsumer tableRegistry, final Ipv4AddressNoZone peerAddress,
258             final RIBImpl ribImpl, final BgpParameters bgpParameters, final PeerRole peerRole,
259             final BGPPeerRegistry bgpPeerRegistry) {
260         return configurePeer(tableRegistry, peerAddress, ribImpl, bgpParameters, peerRole, bgpPeerRegistry,
261                 AFI_SAFIS_ADVERTIZED, Collections.emptySet());
262     }
263
264     static BGPPeer configurePeer(final BGPTableTypeRegistryConsumer tableRegistry,
265             final Ipv4AddressNoZone peerAddress, final RIBImpl ribImpl, final BgpParameters bgpParameters,
266             final PeerRole peerRole, final BGPPeerRegistry bgpPeerRegistry, final Set<TablesKey> afiSafiAdvertised,
267             final Set<TablesKey> gracefulAfiSafiAdvertised) {
268         final BgpPeer bgpPeer = Mockito.mock(BgpPeer.class);
269         doReturn(Optional.empty()).when(bgpPeer).getErrorHandling();
270         return configurePeer(tableRegistry, peerAddress, ribImpl, bgpParameters, peerRole, bgpPeerRegistry,
271                 afiSafiAdvertised, gracefulAfiSafiAdvertised, Collections.emptyMap(), bgpPeer);
272     }
273
274     static BGPPeer configurePeer(final BGPTableTypeRegistryConsumer tableRegistry, final Ipv4AddressNoZone peerAddress,
275             final RIBImpl ribImpl, final BgpParameters bgpParameters, final PeerRole peerRole,
276             final BGPPeerRegistry bgpPeerRegistry, final Set<TablesKey> afiSafiAdvertised,
277             final Set<TablesKey> gracefulAfiSafiAdvertised, final Map<TablesKey, Integer> llGracefulTimersAdvertised,
278             final BgpPeer peer) {
279         final IpAddressNoZone ipAddress = new IpAddressNoZone(peerAddress);
280
281         final BGPPeer bgpPeer = new BGPPeer(tableRegistry, new IpAddressNoZone(peerAddress), null, ribImpl, peerRole,
282                 null, null, null, afiSafiAdvertised, gracefulAfiSafiAdvertised, llGracefulTimersAdvertised, peer);
283         final List<BgpParameters> tlvs = Lists.newArrayList(bgpParameters);
284         bgpPeerRegistry.addPeer(ipAddress, bgpPeer,
285                 new BGPSessionPreferences(AS_NUMBER, HOLDTIMER, new BgpId(RIB_ID), AS_NUMBER, tlvs));
286         bgpPeer.instantiateServiceInstance();
287         return bgpPeer;
288     }
289
290     private static BGPSessionImpl connectPeer(final Ipv4Address localAddress, final BGPDispatcherImpl dispatcherImpl)
291             throws InterruptedException {
292         final Future<BGPSessionImpl> future = dispatcherImpl
293                 .createClient(new InetSocketAddress(localAddress.getValue(), PORT.toJava()),
294                         new InetSocketAddress(RIB_ID, PORT.toJava()), RETRY_TIMER, true);
295         Thread.sleep(200);
296         waitFutureSuccess(future);
297         Thread.sleep(100);
298         return future.getNow();
299     }
300
301     static BgpParameters createParameter(final boolean addPath) {
302         return createParameter(addPath, false, null);
303     }
304
305     static BgpParameters createParameter(final boolean addPath,
306                                          final boolean addIpv6,
307                                          final Map<TablesKey, Boolean> gracefulTables) {
308         final TablesKey ipv4Key = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
309         final List<TablesKey> advertisedTables = Lists.newArrayList(ipv4Key);
310         if (addIpv6) {
311             final TablesKey ipv6Key = new TablesKey(Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class);
312             advertisedTables.add(ipv6Key);
313         }
314         final List<TablesKey> addPathTables = new ArrayList<>();
315         if (addPath) {
316             addPathTables.add(ipv4Key);
317         }
318         return PeerUtil.createBgpParameters(advertisedTables, addPathTables, gracefulTables, GRACEFUL_RESTART_TIME);
319     }
320
321     private static Update createSimpleUpdate(final Ipv4Prefix prefix, final PathId pathId,
322             final ClusterIdentifier clusterId, final long localPreference) {
323         final AttributesBuilder attBuilder = new AttributesBuilder();
324         attBuilder.setLocalPref(new LocalPrefBuilder().setPref(Uint32.valueOf(localPreference)).build());
325         attBuilder.setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build());
326         attBuilder.setAsPath(new AsPathBuilder().setSegments(Collections.emptyList()).build());
327         attBuilder.setMultiExitDisc(new MultiExitDiscBuilder().setMed(Uint32.ZERO).build());
328         if (clusterId != null) {
329             attBuilder.setClusterId(new ClusterIdBuilder().setCluster(Collections.singletonList(clusterId)).build());
330             attBuilder.setOriginatorId(new OriginatorIdBuilder()
331                 .setOriginator(new Ipv4AddressNoZone(clusterId))
332                 .build());
333         }
334         addAttributeAugmentation(attBuilder, prefix, pathId);
335         return new UpdateBuilder().setAttributes(attBuilder.build()).build();
336     }
337
338     private static Update createSimpleUpdateEbgp(final Ipv4Prefix prefix) {
339         final AttributesBuilder attBuilder = new AttributesBuilder();
340         attBuilder.setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build());
341         attBuilder.setAsPath(new AsPathBuilder().setSegments(Collections.singletonList(
342             new SegmentsBuilder().setAsSequence(Collections.singletonList(AS_NUMBER)).build())).build());
343         addAttributeAugmentation(attBuilder, prefix, null);
344
345         return new UpdateBuilder().setAttributes(attBuilder.build()).build();
346     }
347
348     private static void addAttributeAugmentation(final AttributesBuilder attBuilder, final Ipv4Prefix prefix,
349         final PathId pathId) {
350         attBuilder.setUnrecognizedAttributes(Collections.emptyMap());
351         attBuilder.addAugmentation(new AttributesReachBuilder()
352             .setMpReachNlri(new MpReachNlriBuilder()
353                 .setCNextHop(new Ipv4NextHopCaseBuilder()
354                     .setIpv4NextHop(new Ipv4NextHopBuilder().setGlobal(NH1).build())
355                     .build())
356                 .setAfi(Ipv4AddressFamily.class)
357                 .setSafi(UnicastSubsequentAddressFamily.class)
358                 .setAdvertizedRoutes(new AdvertizedRoutesBuilder()
359                     .setDestinationType(new DestinationIpv4CaseBuilder()
360                         .setDestinationIpv4(new DestinationIpv4Builder()
361                             .setIpv4Prefixes(Collections.singletonList(new Ipv4PrefixesBuilder()
362                                 .setPathId(pathId)
363                                 .setPrefix(new Ipv4Prefix(prefix))
364                                 .build()))
365                             .build())
366                         .build())
367                     .build())
368                 .build())
369             .build());
370     }
371
372     private static Update createSimpleWithdrawalUpdate(final Ipv4Prefix prefix, final long localPreference) {
373         final AttributesBuilder attBuilder = new AttributesBuilder();
374         attBuilder.setLocalPref(new LocalPrefBuilder().setPref(Uint32.valueOf(localPreference)).build());
375         attBuilder.setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build());
376         attBuilder.setAsPath(new AsPathBuilder().setSegments(Collections.emptyList()).build());
377         attBuilder.setUnrecognizedAttributes(Collections.emptyMap());
378         return new UpdateBuilder()
379                 .setWithdrawnRoutes(Collections.singletonList(new WithdrawnRoutesBuilder().setPrefix(prefix).build()))
380                 .build();
381     }
382 }