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