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