BUG-5032: BGP Operational State
[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
9 package org.opendaylight.protocol.bgp.rib.impl.config;
10
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 com.google.common.primitives.Shorts;
15 import java.math.BigDecimal;
16 import java.util.ArrayList;
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.BiFunction;
24 import java.util.stream.Collectors;
25 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
26 import org.opendaylight.protocol.bgp.mode.impl.add.all.paths.AllPathSelection;
27 import org.opendaylight.protocol.bgp.mode.impl.add.n.paths.AddPathBestNPathSelection;
28 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
29 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
30 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
31 import org.opendaylight.protocol.concepts.KeyMapping;
32 import org.opendaylight.protocol.util.Ipv4Util;
33 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.BgpCommonAfiSafiList;
34 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
35 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafiBuilder;
36 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborAddPathsConfig;
37 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base.AfiSafisBuilder;
38 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base.ConfigBuilder;
39 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.RouteReflector;
40 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.RouteReflectorBuilder;
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.TimersBuilder;
43 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.TransportBuilder;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.transport.Config;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.NeighborBuilder;
47 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.NeighborKey;
48 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
49 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
50 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.GlobalBuilder;
51 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
52 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.AfiSafiType;
53 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.CommunityType;
54 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4UNICAST;
55 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.PeerType;
56 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.RrClusterIdType;
57 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
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.PortNumber;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.SendReceive;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamilies;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamiliesBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi1;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi2;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.Config1;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.Config2;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.Config2Builder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.GlobalConfigAugmentation;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.GlobalConfigAugmentationBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.NeighborConfigAugmentation;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.NeighborConfigAugmentationBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibId;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.SimpleRoutingPolicy;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.rfc2385.cfg.rev160324.Rfc2385Key;
83 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
84
85 public final class OpenConfigMappingUtil {
86
87     static final String APPLICATION_PEER_GROUP_NAME = "application-peers";
88     private static final AfiSafi IPV4_AFISAFI = new AfiSafiBuilder().setAfiSafiName(IPV4UNICAST.class).build();
89     private static final List<AfiSafi> DEFAULT_AFISAFI = ImmutableList.of(IPV4_AFISAFI);
90     private static final int HOLDTIMER = 90;
91     private static final int CONNECT_RETRY = 30;
92     private static final PortNumber PORT = new PortNumber(179);
93     private static final BigDecimal DEFAULT_KEEP_ALIVE = BigDecimal.valueOf(30);
94     private static final BigDecimal DEFAULT_MINIMUM_ADV_INTERVAL = BigDecimal.valueOf(30);
95
96     private OpenConfigMappingUtil() {
97         throw new UnsupportedOperationException();
98     }
99
100     public static String getRibInstanceName(final InstanceIdentifier<?> rootIdentifier) {
101         return rootIdentifier.firstKeyOf(Protocol.class).getName();
102     }
103
104     public static int getHoldTimer(final Neighbor neighbor) {
105         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers.Config config =
106             getTimersConfig(neighbor);
107         if (config != null && config.getHoldTime() != null) {
108             return config.getHoldTime().intValue();
109         }
110         return HOLDTIMER;
111     }
112
113     public static AsNumber getPeerAs(final Neighbor neighbor, final RIB rib) {
114         if (neighbor.getConfig() != null) {
115             final AsNumber peerAs = neighbor.getConfig().getPeerAs();
116             if (peerAs != null) {
117                 return peerAs;
118             }
119         }
120         return rib.getLocalAs();
121     }
122
123     public static boolean isActive(final Neighbor neighbor) {
124         if (neighbor.getTransport() != null) {
125             final Config config = neighbor.getTransport().getConfig();
126             if (config != null && config.isPassiveMode() != null) {
127                 return !config.isPassiveMode();
128             }
129         }
130         return true;
131     }
132
133     public static int getRetryTimer(final Neighbor neighbor) {
134         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers.Config config =
135             getTimersConfig(neighbor);
136         if (config != null && config.getConnectRetry() != null) {
137             return config.getConnectRetry().intValue();
138         }
139         return CONNECT_RETRY;
140     }
141
142     public static KeyMapping getNeighborKey(final Neighbor neighbor) {
143         if (neighbor.getConfig() != null) {
144             final String authPassword = neighbor.getConfig().getAuthPassword();
145             if (authPassword != null) {
146                 return KeyMapping.getKeyMapping(INSTANCE.inetAddressFor(neighbor.getNeighborAddress()), authPassword);
147             }
148         }
149         return null;
150     }
151
152     public static InstanceIdentifier<Neighbor> getNeighborInstanceIdentifier(final InstanceIdentifier<Bgp> rootIdentifier,
153         final NeighborKey neighborKey) {
154         return rootIdentifier.child(Neighbors.class).child(Neighbor.class, neighborKey);
155     }
156
157     public static String getNeighborInstanceName(final InstanceIdentifier<?> rootIdentifier) {
158         return Ipv4Util.toStringIP(rootIdentifier.firstKeyOf(Neighbor.class).getNeighborAddress());
159     }
160
161     public static PortNumber getPort(final Neighbor neighbor) {
162         if (neighbor.getTransport() != null) {
163             final Config config = neighbor.getTransport().getConfig();
164             if (config != null && config.getAugmentation(Config1.class) != null) {
165                 final PortNumber remotePort = config.getAugmentation(Config1.class).getRemotePort();
166                 if (remotePort != null) {
167                     return remotePort;
168                 }
169             }
170         }
171         return PORT;
172     }
173
174     //make sure IPv4 Unicast (RFC 4271) when required
175     public static List<AfiSafi> getAfiSafiWithDefault(final BgpCommonAfiSafiList afiSAfis, final boolean setDeafultIPv4) {
176         if (afiSAfis == null || afiSAfis.getAfiSafi() == null) {
177             return setDeafultIPv4 ? DEFAULT_AFISAFI : Collections.emptyList();
178         }
179         final List<AfiSafi> afiSafi = afiSAfis.getAfiSafi();
180         if (setDeafultIPv4) {
181             final boolean anyMatch = afiSafi.stream().anyMatch(input -> input.getAfiSafiName().equals(IPV4UNICAST.class));
182             if (!anyMatch) {
183                 afiSafi.add(IPV4_AFISAFI);
184             }
185         }
186         return afiSafi;
187     }
188
189     public static ClusterIdentifier getClusterIdentifier(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base.Config globalConfig) {
190         final GlobalConfigAugmentation globalConfigAugmentation = globalConfig.getAugmentation(GlobalConfigAugmentation.class);
191         if (globalConfigAugmentation != null && globalConfigAugmentation.getRouteReflectorClusterId() != null) {
192             return new ClusterIdentifier(globalConfigAugmentation.getRouteReflectorClusterId().getIpv4Address());
193         }
194         return new ClusterIdentifier(globalConfig.getRouterId());
195     }
196
197     public static SimpleRoutingPolicy getSimpleRoutingPolicy(final Neighbor neighbor) {
198         if (neighbor.getConfig() != null) {
199             final NeighborConfigAugmentation augmentation = neighbor.getConfig().getAugmentation(NeighborConfigAugmentation.class);
200             if (augmentation != null) {
201                 return augmentation.getSimpleRoutingPolicy();
202             }
203         }
204         return null;
205     }
206
207     private static org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers.Config getTimersConfig(final Neighbor neighbor) {
208         final Timers timers = neighbor.getTimers();
209         return timers != null ? timers.getConfig() : null;
210     }
211
212     public static Map<BgpTableType, PathSelectionMode> toPathSelectionMode(final List<AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
213         final Map<BgpTableType, PathSelectionMode> pathSelectionModes = new HashMap<>();
214         for (final AfiSafi afiSafi : afiSafis) {
215             final BgpNeighborAddPathsConfig afiSafi2 = afiSafi.getAugmentation(AfiSafi2.class);
216             if (afiSafi2 != null) {
217                 final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
218                 if (bgpTableType.isPresent()) {
219                     final Short sendMax = afiSafi2.getSendMax();
220                     final PathSelectionMode selectionMode;
221                     if (sendMax > 1) {
222                         selectionMode = new AddPathBestNPathSelection(sendMax.longValue());
223                     } else {
224                         selectionMode = new AllPathSelection();
225                     }
226                     pathSelectionModes.put(bgpTableType.get(), selectionMode);
227                 }
228             }
229         }
230         return pathSelectionModes;
231     }
232
233     public static boolean isApplicationPeer(final Neighbor neighbor) {
234         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Config config = neighbor.getConfig();
235         if (config != null) {
236             final Config2 config1 = config.getAugmentation(Config2.class);
237             if (config1 != null) {
238                 final String peerGroup = config1.getPeerGroup();
239                 return peerGroup != null && peerGroup.equals(APPLICATION_PEER_GROUP_NAME);
240             }
241         }
242         return false;
243     }
244
245     public static List<AddressFamilies> toAddPathCapability(final List<AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
246         final List<AddressFamilies> addPathCapability = new ArrayList<>();
247         for (final AfiSafi afiSafi : afiSafis) {
248             final BgpNeighborAddPathsConfig afiSafi1 = afiSafi.getAugmentation(AfiSafi1.class);
249             final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
250             if (afiSafi1 != null && bgpTableType.isPresent()) {
251                 final AddressFamiliesBuilder builder = new AddressFamiliesBuilder(bgpTableType.get());
252                 builder.setSendReceive(toSendReceiveMode(afiSafi1));
253                 addPathCapability.add(builder.build());
254             }
255         }
256         return addPathCapability;
257     }
258
259     private static SendReceive toSendReceiveMode(final BgpNeighborAddPathsConfig addPath) {
260         if (addPath.isReceive() && addPath.getSendMax() != null) {
261             return SendReceive.Both;
262         }
263         if (addPath.getSendMax() != null) {
264             return SendReceive.Send;
265         }
266         return SendReceive.Receive;
267     }
268
269     public static Global fromRib(final BgpId bgpId, final ClusterIdentifier clusterIdentifier, final RibId ribId,
270         final AsNumber localAs, final List<BgpTableType> localTables,
271         final Map<TablesKey, PathSelectionMode> pathSelectionStrategies, final BGPTableTypeRegistryConsumer bgpTableTypeRegistryConsumer) {
272         return toGlobalConfiguration(bgpId, clusterIdentifier, localAs, localTables, pathSelectionStrategies, bgpTableTypeRegistryConsumer);
273     }
274
275     private static Global toGlobalConfiguration(final BgpId bgpId, final ClusterIdentifier clusterIdentifier,
276         final AsNumber localAs, final List<BgpTableType> localTables,
277         final Map<TablesKey, PathSelectionMode> pathSelectionStrategies, final BGPTableTypeRegistryConsumer bgpTableTypeRegistryConsumer) {
278         final ConfigBuilder configBuilder = new ConfigBuilder();
279         configBuilder.setAs(localAs);
280         configBuilder.setRouterId(bgpId);
281         if (clusterIdentifier != null) {
282             configBuilder.addAugmentation(GlobalConfigAugmentation.class,
283                 new GlobalConfigAugmentationBuilder().setRouteReflectorClusterId(new RrClusterIdType(clusterIdentifier)).build());
284         }
285         return new GlobalBuilder().setAfiSafis(new AfiSafisBuilder().setAfiSafi(toAfiSafis(localTables,
286             (afiSafi, tableType) -> toGlobalAfiSafiAddPath(afiSafi, tableType, pathSelectionStrategies), bgpTableTypeRegistryConsumer)).build())
287             .setConfig(configBuilder.build()).build();
288     }
289
290     public static Neighbor fromBgpPeer(final List<AddressFamilies> addPathCapabilities,
291         final List<BgpTableType> advertisedTables, final Integer holdTimer, final IpAddress ipAddress,
292         final Boolean isActive, final Rfc2385Key password, final PortNumber portNumber, final Integer retryTimer,
293         final AsNumber remoteAs, final PeerRole peerRole, final SimpleRoutingPolicy simpleRoutingPolicy, final BGPTableTypeRegistryConsumer bgpTableTypeRegistryConsumer) {
294         final NeighborBuilder neighborBuilder = new NeighborBuilder();
295         neighborBuilder.setNeighborAddress(ipAddress);
296         neighborBuilder.setKey(new NeighborKey(ipAddress));
297         neighborBuilder.setAfiSafis(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.AfiSafisBuilder().setAfiSafi(toAfiSafis(advertisedTables,
298             (afiSafi, tableType) -> toNeighborAfiSafiAddPath(afiSafi, tableType, addPathCapabilities), bgpTableTypeRegistryConsumer)).build());
299         neighborBuilder.setTransport(new TransportBuilder().setConfig(
300             new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.transport.ConfigBuilder()
301                 .setPassiveMode(!isActive)
302                 .setMtuDiscovery(Boolean.FALSE)
303                 .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.Config1.class,
304                     new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.Config1Builder()
305                         .setRemotePort(portNumber).build())
306                 .build()).build());
307         neighborBuilder.setConfig(
308             new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ConfigBuilder()
309                 .setAuthPassword(password != null ? password.getValue() : null)
310                 .setPeerAs(remoteAs)
311                 .setPeerType(toPeerType(peerRole))
312                 .setSendCommunity(CommunityType.NONE)
313                 .setRouteFlapDamping(Boolean.FALSE)
314                 .addAugmentation(NeighborConfigAugmentation.class, setNeighborAugmentation(simpleRoutingPolicy))
315                 .build());
316         neighborBuilder.setTimers(new TimersBuilder().setConfig(
317             new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers.ConfigBuilder()
318                 .setHoldTime(BigDecimal.valueOf(holdTimer))
319                 .setConnectRetry(BigDecimal.valueOf(retryTimer))
320                 .setKeepaliveInterval(DEFAULT_KEEP_ALIVE)
321                 .setMinimumAdvertisementInterval(DEFAULT_MINIMUM_ADV_INTERVAL)
322                 .build()).build());
323         neighborBuilder.setRouteReflector(new RouteReflectorBuilder().setConfig(
324             new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.route.reflector.ConfigBuilder()
325                 .setRouteReflectorClient(peerRole == PeerRole.RrClient).build()).build());
326         return neighborBuilder.build();
327     }
328
329
330     public static Neighbor fromApplicationPeer(final ApplicationRibId applicationRibId, final BgpId bgpId) {
331         final NeighborBuilder neighborBuilder = new NeighborBuilder();
332         neighborBuilder.setNeighborAddress(new IpAddress(new Ipv4Address(bgpId.getValue())));
333         neighborBuilder.setKey(new NeighborKey(neighborBuilder.getNeighborAddress()));
334         neighborBuilder.setConfig(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ConfigBuilder()
335             .setDescription(applicationRibId.getValue())
336             .addAugmentation(Config2.class, new Config2Builder().setPeerGroup(APPLICATION_PEER_GROUP_NAME).build())
337             .build());
338
339         return neighborBuilder.build();
340     }
341
342     private static NeighborConfigAugmentation setNeighborAugmentation(final SimpleRoutingPolicy simpleRoutingPolicy) {
343         if (simpleRoutingPolicy != null) {
344             return new NeighborConfigAugmentationBuilder().setSimpleRoutingPolicy(simpleRoutingPolicy).build();
345         }
346         return null;
347     }
348
349     public static PeerRole toPeerRole(final Neighbor neighbor) {
350         if (isRrClient(neighbor)) {
351             return PeerRole.RrClient;
352         }
353
354         if (neighbor.getConfig() != null) {
355             final PeerType peerType = neighbor.getConfig().getPeerType();
356             if (peerType == PeerType.EXTERNAL) {
357                 return PeerRole.Ebgp;
358             }
359         }
360         return PeerRole.Ibgp;
361     }
362
363     static PeerType toPeerType(final PeerRole peerRole) {
364         switch (peerRole) {
365         case Ibgp:
366         case RrClient:
367             return PeerType.INTERNAL;
368         case Ebgp:
369             return PeerType.EXTERNAL;
370         case Internal:
371             break;
372         default:
373             break;
374         }
375         return null;
376     }
377
378     private static boolean isRrClient(final Neighbor neighbor) {
379         final RouteReflector routeReflector = neighbor.getRouteReflector();
380         if (routeReflector != null && routeReflector.getConfig() != null) {
381             return routeReflector.getConfig().isRouteReflectorClient();
382         }
383         return false;
384     }
385
386     static List<AfiSafi> toAfiSafis(final List<BgpTableType> advertizedTables, final BiFunction<AfiSafi, BgpTableType, AfiSafi> function,
387         final BGPTableTypeRegistryConsumer bgpTableTypeRegistryConsumer) {
388         final List<AfiSafi> afiSafis = new ArrayList<>(advertizedTables.size());
389         for (final BgpTableType tableType : advertizedTables) {
390             final Optional<AfiSafi> afiSafiMaybe = toAfiSafi(new BgpTableTypeImpl(tableType.getAfi(), tableType.getSafi()), bgpTableTypeRegistryConsumer);
391             if (afiSafiMaybe.isPresent()) {
392                 final AfiSafi afiSafi = function.apply(afiSafiMaybe.get(), tableType);
393                 afiSafis.add(afiSafi);
394             }
395         }
396         return afiSafis;
397     }
398
399     static AfiSafi toGlobalAfiSafiAddPath(final AfiSafi afiSafi, final BgpTableType tableType,
400         final Map<TablesKey, PathSelectionMode> multiPathTables) {
401         final PathSelectionMode pathSelection = multiPathTables.get(new TablesKey(tableType.getAfi(), tableType.getSafi()));
402         if (pathSelection == null) {
403             return afiSafi;
404         }
405         final long maxPaths;
406         if (pathSelection instanceof AddPathBestNPathSelection) {
407             maxPaths = ((AddPathBestNPathSelection) pathSelection).getNBestPaths();
408         } else {
409             maxPaths = 0L;
410         }
411         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi2 addPath = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi2Builder()
412             .setReceive(true)
413             .setSendMax(Shorts.checkedCast(maxPaths))
414             .build();
415         return new AfiSafiBuilder(afiSafi)
416             .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi2.class,
417                 addPath).build();
418     }
419
420     static AfiSafi toNeighborAfiSafiAddPath(final AfiSafi afiSafi, final BgpTableType tableType, final List<AddressFamilies> capabilities) {
421         final Optional<AddressFamilies> capability = capabilities.stream()
422             .filter(af -> af.getAfi().equals(tableType.getAfi()) && af.getSafi().equals(tableType.getSafi()))
423             .findFirst();
424         if (!capability.isPresent()) {
425             return afiSafi;
426         }
427         return new AfiSafiBuilder(afiSafi)
428             .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi1.class,
429                 fromSendReceiveMode(capability.get().getSendReceive())).build();
430     }
431
432     private static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi1 fromSendReceiveMode(final SendReceive mode) {
433         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi1Builder builder =
434             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.AfiSafi1Builder();
435         switch (mode) {
436         case Both:
437             builder.setReceive(true).setSendMax((short) 0);
438             break;
439         case Receive:
440             builder.setReceive(true);
441             break;
442         case Send:
443             builder.setReceive(false).setSendMax((short) 0);
444             break;
445         default:
446             break;
447         }
448         return builder.build();
449     }
450
451     public static Optional<AfiSafi> toAfiSafi(final BgpTableType tableType, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
452         final Optional<Class<? extends AfiSafiType>> afiSafi = tableTypeRegistry.getAfiSafiType(tableType);
453         if (afiSafi.isPresent()) {
454             return Optional.of(new AfiSafiBuilder().setAfiSafiName(afiSafi.get()).build());
455         }
456         return Optional.empty();
457     }
458
459     public static List<BgpTableType> toTableTypes(final List<AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
460         return afiSafis.stream()
461             .map(afiSafi -> tableTypeRegistry.getTableType(afiSafi.getAfiSafiName()))
462             .filter(Optional::isPresent)
463             .map(Optional::get)
464             .collect(Collectors.toList());
465     }
466
467     public static Set<TablesKey> toTableKey(final List<AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer
468         tableTypeRegistry) {
469         return afiSafis.stream()
470             .map(afiSafi -> tableTypeRegistry.getTableKey(afiSafi.getAfiSafiName()))
471             .filter(Optional::isPresent)
472             .map(Optional::get)
473             .collect(Collectors.toSet());
474     }
475 }