Update MRI projects for Aluminium
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / config / OpenConfigMappingUtil.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.config;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil.INSTANCE;
12
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.Maps;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Optional;
22 import java.util.Set;
23 import java.util.function.Function;
24 import java.util.stream.Collectors;
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
28 import org.opendaylight.protocol.bgp.mode.impl.add.all.paths.AllPathSelection;
29 import org.opendaylight.protocol.bgp.mode.impl.add.n.paths.AddPathBestNPathSelection;
30 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
31 import org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandlingSupport;
32 import org.opendaylight.protocol.bgp.parser.spi.pojo.RevisedErrorHandlingSupportImpl;
33 import org.opendaylight.protocol.concepts.KeyMapping;
34 import org.opendaylight.protocol.util.Ipv4Util;
35 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.BgpCommonAfiSafiList;
36 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
37 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafiBuilder;
38 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafiKey;
39 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborAddPathsConfig;
40 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborGroup;
41 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborTransportConfig;
42 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.graceful.restart.GracefulRestart;
43 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ErrorHandling;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.RouteReflector;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Timers;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Transport;
47 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.transport.Config;
48 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
49 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.NeighborKey;
50 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.peer.group.PeerGroup;
51 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
52 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
53 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4UNICAST;
54 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.PeerType;
55 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.SendReceive;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.add.path.capability.AddressFamilies;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.add.path.capability.AddressFamiliesBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.GlobalAddPathsConfig;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.GlobalConfigAugmentation;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborAddPathsConfig;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborPeerGroupConfig;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborTransportConfig;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.PeerGroupTransportConfig;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.TransportConfig;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.ClusterIdentifier;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
78 import org.opendaylight.yangtools.yang.common.Uint16;
79
80 final class OpenConfigMappingUtil {
81     static final String APPLICATION_PEER_GROUP_NAME = "application-peers";
82     static final Optional<String> APPLICATION_PEER_GROUP_NAME_OPT = Optional.of(APPLICATION_PEER_GROUP_NAME);
83     static final int HOLDTIMER = 90;
84     private static final AfiSafi IPV4_AFISAFI = new AfiSafiBuilder().setAfiSafiName(IPV4UNICAST.class).build();
85     private static final Map<AfiSafiKey, AfiSafi> DEFAULT_AFISAFI = ImmutableMap.of(IPV4_AFISAFI.key(), IPV4_AFISAFI);
86     private static final int CONNECT_RETRY = 30;
87     private static final PortNumber PORT = new PortNumber(Uint16.valueOf(179).intern());
88
89     private OpenConfigMappingUtil() {
90         // Hidden on purpose
91     }
92
93     static String getRibInstanceName(final InstanceIdentifier<?> rootIdentifier) {
94         return rootIdentifier.firstKeyOf(Protocol.class).getName();
95     }
96
97     static KeyMapping getNeighborKey(final Neighbor neighbor) {
98         if (neighbor.getConfig() != null) {
99             final String authPassword = neighbor.getConfig().getAuthPassword();
100             if (authPassword != null) {
101                 return KeyMapping.getKeyMapping(INSTANCE.inetAddressFor(neighbor.getNeighborAddress()), authPassword);
102             }
103         }
104         return null;
105     }
106
107     static InstanceIdentifier<Neighbor> getNeighborInstanceIdentifier(
108             final InstanceIdentifier<Bgp> rootIdentifier,
109             final NeighborKey neighborKey) {
110         return rootIdentifier.child(Neighbors.class).child(Neighbor.class, neighborKey);
111     }
112
113     static IpAddressNoZone convertIpAddress(final IpAddress addr) {
114         if (addr == null) {
115             return null;
116         }
117         final Ipv4Address ipv4 = addr.getIpv4Address();
118         if (ipv4 != null) {
119             return new IpAddressNoZone(INSTANCE.ipv4AddressNoZoneFor(ipv4));
120         }
121         final Ipv6Address ipv6 = addr.getIpv6Address();
122         checkState(ipv6 != null, "Unexpected address %s", addr);
123         return new IpAddressNoZone(INSTANCE.ipv6AddressNoZoneFor(ipv6));
124     }
125
126     static String getNeighborInstanceName(final InstanceIdentifier<?> rootIdentifier) {
127         return Ipv4Util.toStringIP(convertIpAddress(rootIdentifier.firstKeyOf(Neighbor.class).getNeighborAddress()));
128     }
129
130     //make sure IPv4 Unicast (RFC 4271) when required
131     static Map<AfiSafiKey, AfiSafi> getAfiSafiWithDefault(
132             final BgpCommonAfiSafiList afiSAfis, final boolean setDeafultIPv4) {
133         if (afiSAfis == null || afiSAfis.getAfiSafi() == null) {
134             return setDeafultIPv4 ? DEFAULT_AFISAFI : Collections.emptyMap();
135         }
136         final Map<AfiSafiKey, AfiSafi> afiSafi = afiSAfis.nonnullAfiSafi();
137         if (setDeafultIPv4 && !afiSafi.containsKey(IPV4_AFISAFI.key())) {
138             final Map<AfiSafiKey, AfiSafi> newAfiSafi = Maps.newHashMapWithExpectedSize(afiSafi.size() + 1);
139             newAfiSafi.putAll(afiSafi);
140             newAfiSafi.put(IPV4_AFISAFI.key(), IPV4_AFISAFI);
141             return newAfiSafi;
142         }
143         return afiSafi;
144     }
145
146     static ClusterIdentifier getGlobalClusterIdentifier(final org.opendaylight.yang.gen.v1.http.openconfig.net
147             .yang.bgp.rev151009.bgp.global.base.Config globalConfig) {
148         final GlobalConfigAugmentation globalConfigAugmentation
149                 = globalConfig.augmentation(GlobalConfigAugmentation.class);
150         final Ipv4Address addr;
151         if (globalConfigAugmentation != null && globalConfigAugmentation.getRouteReflectorClusterId() != null) {
152             addr = globalConfigAugmentation.getRouteReflectorClusterId().getIpv4Address();
153         } else {
154             addr = globalConfig.getRouterId();
155         }
156         return new ClusterIdentifier(IetfInetUtil.INSTANCE.ipv4AddressNoZoneFor(addr));
157     }
158
159     static @Nullable ClusterIdentifier getNeighborClusterIdentifier(
160             final @Nullable RouteReflector routeReflector, final @Nullable PeerGroup peerGroup) {
161         if (peerGroup != null) {
162             final ClusterIdentifier clusteriId = extractClusterId(peerGroup.getRouteReflector());
163             if (clusteriId != null) {
164                 return clusteriId;
165             }
166         }
167
168         return extractClusterId(routeReflector);
169     }
170
171     private static ClusterIdentifier extractClusterId(final RouteReflector routeReflector) {
172         if (routeReflector != null) {
173             final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.route
174                     .reflector.Config config = routeReflector.getConfig();
175             if (config != null && config.getRouteReflectorClusterId() != null) {
176                 return new ClusterIdentifier(IetfInetUtil.INSTANCE.ipv4AddressNoZoneFor(
177                     config.getRouteReflectorClusterId().getIpv4Address()));
178             }
179         }
180         return null;
181     }
182
183     static Map<BgpTableType, PathSelectionMode> toPathSelectionMode(final Collection<AfiSafi> afiSafis,
184             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
185         final Map<BgpTableType, PathSelectionMode> pathSelectionModes = new HashMap<>();
186         for (final AfiSafi afiSafi : afiSafis) {
187             final BgpNeighborAddPathsConfig afiSafi2 = afiSafi.augmentation(GlobalAddPathsConfig.class);
188             if (afiSafi2 != null) {
189                 final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
190                 if (bgpTableType.isPresent()) {
191                     final short sendMax = afiSafi2.getSendMax().toJava();
192                     final PathSelectionMode selectionMode;
193                     if (sendMax > 1) {
194                         selectionMode = new AddPathBestNPathSelection(sendMax);
195                     } else {
196                         selectionMode = new AllPathSelection();
197                     }
198                     pathSelectionModes.put(bgpTableType.get(), selectionMode);
199                 }
200             }
201         }
202         return pathSelectionModes;
203     }
204
205     static boolean isApplicationPeer(final Neighbor neighbor) {
206         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group
207                 .Config config = neighbor.getConfig();
208         if (config != null) {
209             final NeighborPeerGroupConfig config1 = config.augmentation(NeighborPeerGroupConfig.class);
210             if (config1 != null) {
211                 final String peerGroup = config1.getPeerGroup();
212                 return peerGroup != null && peerGroup.equals(APPLICATION_PEER_GROUP_NAME);
213             }
214         }
215         return false;
216     }
217
218     static List<AddressFamilies> toAddPathCapability(final Collection<AfiSafi> afiSafis,
219             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
220         final List<AddressFamilies> addPathCapability = new ArrayList<>();
221         for (final AfiSafi afiSafi : afiSafis) {
222             final BgpNeighborAddPathsConfig afiSafi1 = afiSafi.augmentation(NeighborAddPathsConfig.class);
223             final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
224             if (afiSafi1 != null && bgpTableType.isPresent()) {
225                 final AddressFamiliesBuilder builder = new AddressFamiliesBuilder(bgpTableType.get());
226                 builder.setSendReceive(toSendReceiveMode(afiSafi1));
227                 addPathCapability.add(builder.build());
228             }
229         }
230         return addPathCapability;
231     }
232
233     private static SendReceive toSendReceiveMode(final BgpNeighborAddPathsConfig addPath) {
234         if (addPath.isReceive() && addPath.getSendMax() != null) {
235             return SendReceive.Both;
236         }
237         if (addPath.getSendMax() != null) {
238             return SendReceive.Send;
239         }
240         return SendReceive.Receive;
241     }
242
243     private static boolean isRrClient(final BgpNeighborGroup neighbor) {
244         final RouteReflector routeReflector = neighbor.getRouteReflector();
245         if (routeReflector != null && routeReflector.getConfig() != null) {
246             return routeReflector.getConfig().isRouteReflectorClient();
247         }
248         return false;
249     }
250
251     static List<BgpTableType> toTableTypes(final Collection<AfiSafi> afiSafis,
252             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
253         return afiSafis.stream()
254                 .map(afiSafi -> tableTypeRegistry.getTableType(afiSafi.getAfiSafiName()))
255                 .filter(Optional::isPresent)
256                 .map(Optional::get)
257                 .collect(Collectors.toList());
258     }
259
260     static Set<TablesKey> toTableKey(final Map<AfiSafiKey, AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer
261             tableTypeRegistry) {
262         return afiSafis.values().stream()
263                 .map(afiSafi -> tableTypeRegistry.getTableKey(afiSafi.getAfiSafiName()))
264                 .filter(Optional::isPresent)
265                 .map(Optional::get)
266                 .collect(Collectors.toSet());
267     }
268
269     static boolean isActive(final Neighbor neighbor, final PeerGroup peerGroup) {
270         Optional<Boolean> activeConnection = peerGroup == null ? Optional.empty() : isActive(peerGroup.getTransport());
271         if (!activeConnection.isPresent()) {
272             activeConnection = isActive(neighbor.getTransport());
273         }
274         return activeConnection.orElse(Boolean.TRUE);
275     }
276
277     private static Optional<Boolean> isActive(final Transport transport) {
278         if (transport != null) {
279             final Config config = transport.getConfig();
280             if (config != null) {
281                 final Boolean passive = config.isPassiveMode();
282                 if (passive != null) {
283                     return Optional.of(!passive);
284                 }
285             }
286         }
287         return Optional.empty();
288     }
289
290     static PeerRole toPeerRole(final BgpNeighborGroup neighbor) {
291         if (isRrClient(neighbor)) {
292             return PeerRole.RrClient;
293         }
294
295         if (neighbor.getConfig() != null) {
296             final PeerType peerType = neighbor.getConfig().getPeerType();
297             if (peerType == PeerType.EXTERNAL) {
298                 return PeerRole.Ebgp;
299             } else if (peerType == PeerType.INTERNAL) {
300                 return PeerRole.Ibgp;
301             }
302         }
303         return null;
304     }
305
306     static @NonNull PeerRole toPeerRole(final Neighbor neighbor, final PeerGroup peerGroup) {
307         PeerRole role = null;
308         if (peerGroup != null) {
309             role = toPeerRole(peerGroup);
310         }
311
312         if (role == null) {
313             role = toPeerRole(neighbor);
314         }
315
316         if (role == null) {
317             return PeerRole.Ibgp;
318         }
319         return role;
320     }
321
322     static int getHoldTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
323         Integer hold = null;
324         if (peerGroup != null) {
325             hold = getHoldTimer(peerGroup.getTimers());
326         }
327
328         if (hold == null) {
329             hold = getHoldTimer(neighbor.getTimers());
330         }
331
332         if (hold == null) {
333             return HOLDTIMER;
334         }
335
336         return hold;
337     }
338
339     private static @Nullable Integer getHoldTimer(final Timers timers) {
340         if (timers == null) {
341             return null;
342         }
343         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
344                 .Config config = timers.getConfig();
345         if (config != null && config.getHoldTime() != null) {
346             return config.getHoldTime().intValue();
347         }
348         return null;
349     }
350
351     static int getGracefulRestartTimer(final Neighbor neighbor, final PeerGroup peerGroup, final int holdTimer) {
352         Uint16 timer = null;
353         if (peerGroup != null) {
354             timer = getGracefulRestartTimer(peerGroup.getGracefulRestart());
355         }
356
357         if (timer == null) {
358             timer = getGracefulRestartTimer(neighbor.getGracefulRestart());
359         }
360
361         /*
362          * RFC4724: "A suggested default for the Restart Time is a value less than or
363          * equal to the HOLDTIME carried in the OPEN."
364          */
365         return timer == null ? holdTimer : timer.toJava();
366     }
367
368     private static @Nullable Uint16 getGracefulRestartTimer(final GracefulRestart gracefulRestart) {
369         if (gracefulRestart != null) {
370             final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.graceful.restart.graceful
371                     .restart.Config config = gracefulRestart.getConfig();
372             if (config != null) {
373                 return config.getRestartTime();
374             }
375         }
376         return null;
377     }
378
379     static @NonNull AsNumber getRemotePeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009
380             .bgp.neighbor.group.Config config, final PeerGroup peerGroup, final AsNumber localAs) {
381         AsNumber neighborAs = null;
382         if (peerGroup != null) {
383             neighborAs = getRemotePeerAs(peerGroup.getConfig());
384         }
385
386         if (neighborAs == null) {
387             neighborAs = getRemotePeerAs(config);
388         }
389
390         if (neighborAs == null) {
391             return localAs;
392         }
393         return neighborAs;
394     }
395
396     private static AsNumber getRemotePeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
397             .rev151009.bgp.neighbor.group.@Nullable Config config) {
398         return config == null ? null : config.getPeerAs();
399     }
400
401     static @NonNull AsNumber getLocalPeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
402             .rev151009.bgp.neighbor.group.@Nullable Config config, final @NonNull AsNumber globalAs) {
403         if (config != null) {
404             final AsNumber peerAs = config.getLocalAs();
405             if (peerAs != null) {
406                 return peerAs;
407             }
408         }
409         return globalAs;
410     }
411
412     static int getRetryTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
413         Integer retryTimer = null;
414         if (peerGroup != null) {
415             retryTimer = getRetryTimer(peerGroup.getTimers());
416         }
417
418         if (retryTimer == null) {
419             retryTimer = getRetryTimer(neighbor.getTimers());
420         }
421
422         if (retryTimer == null) {
423             return CONNECT_RETRY;
424         }
425
426         return retryTimer;
427     }
428
429     private static @Nullable Integer getRetryTimer(final Timers timers) {
430         if (timers == null) {
431             return null;
432         }
433         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
434                 .Config config = timers.getConfig();
435         if (config != null && config.getConnectRetry() != null) {
436             return config.getConnectRetry().intValue();
437         }
438         return null;
439     }
440
441     static @NonNull PortNumber getPort(final Neighbor neighbor, final PeerGroup peerGroup) {
442         PortNumber port = null;
443         if (peerGroup != null) {
444             port = getPort(peerGroup.getTransport(), config -> config.augmentation(PeerGroupTransportConfig.class));
445         }
446
447         if (port == null) {
448             port = getPort(neighbor.getTransport(), config -> config.augmentation(NeighborTransportConfig.class));
449         }
450
451         if (port == null) {
452             return PORT;
453         }
454
455         return port;
456     }
457
458     private static @Nullable PortNumber getPort(final @Nullable Transport transport,
459             final Function<Config, TransportConfig> extractConfig) {
460         if (transport != null) {
461             final Config config = transport.getConfig();
462             if (config != null) {
463                 final TransportConfig peerTc = extractConfig.apply(config);
464                 if (peerTc != null) {
465                     return peerTc.getRemotePort();
466                 }
467             }
468         }
469         return null;
470     }
471
472     static @Nullable IpAddressNoZone getLocalAddress(@Nullable final Transport transport) {
473         if (transport != null && transport.getConfig() != null) {
474             final BgpNeighborTransportConfig.LocalAddress localAddress = transport.getConfig().getLocalAddress();
475             if (localAddress != null) {
476                 return convertIpAddress(localAddress.getIpAddress());
477             }
478         }
479         return null;
480     }
481
482     static @Nullable RevisedErrorHandlingSupport getRevisedErrorHandling(final PeerRole role,final PeerGroup peerGroup,
483             final Neighbor neighbor) {
484         Optional<Boolean> enabled = getRevisedErrorHandling(neighbor);
485         if (!enabled.isPresent()) {
486             enabled = getRevisedErrorHandling(peerGroup);
487         }
488         if (!enabled.orElse(Boolean.FALSE)) {
489             return null;
490         }
491         switch (role) {
492             case Ebgp:
493                 return RevisedErrorHandlingSupportImpl.forExternalPeer();
494             case Ibgp:
495             case Internal:
496             case RrClient:
497                 return RevisedErrorHandlingSupportImpl.forInternalPeer();
498             default:
499                 throw new IllegalStateException("Unhandled role " + role);
500         }
501     }
502
503     private static Optional<Boolean> getRevisedErrorHandling(final BgpNeighborGroup group) {
504         if (group == null) {
505             return Optional.empty();
506         }
507         final ErrorHandling errorHandling = group.getErrorHandling();
508         if (errorHandling == null) {
509             return Optional.empty();
510         }
511         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.error.handling
512             .Config config = errorHandling.getConfig();
513         return config == null ? Optional.empty() : Optional.of(config.isTreatAsWithdraw());
514     }
515 }