d4bd0f6c412b0ceb650b1b158bad46004d404e41
[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 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 javax.annotation.Nonnull;
23 import javax.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.rib.spi.BGPPeerTracker;
29 import org.opendaylight.protocol.concepts.KeyMapping;
30 import org.opendaylight.protocol.util.Ipv4Util;
31 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.BgpCommonAfiSafiList;
32 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
33 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafiBuilder;
34 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborAddPathsConfig;
35 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborGroup;
36 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.RouteReflector;
37 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Timers;
38 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Transport;
39 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.transport.Config;
40 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
41 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.NeighborKey;
42 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.peer.group.PeerGroup;
43 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4UNICAST;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.PeerType;
47 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.BgpTableType;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.SendReceive;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.mp.capabilities.add.path.capability.AddressFamilies;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.mp.capabilities.add.path.capability.AddressFamiliesBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.GlobalAddPathsConfig;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.GlobalConfigAugmentation;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.NeighborAddPathsConfig;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.NeighborClusterIdConfig;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.NeighborPeerGroupConfig;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.NeighborTransportConfig;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.PeerGroupTransportConfig;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.RouteReflectorClusterIdConfig;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerRole;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
65 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
66
67 public final class OpenConfigMappingUtil {
68
69     static final String APPLICATION_PEER_GROUP_NAME = "application-peers";
70     static final int HOLDTIMER = 90;
71     private static final AfiSafi IPV4_AFISAFI = new AfiSafiBuilder().setAfiSafiName(IPV4UNICAST.class).build();
72     private static final List<AfiSafi> DEFAULT_AFISAFI = ImmutableList.of(IPV4_AFISAFI);
73     private static final int CONNECT_RETRY = 30;
74     private static final PortNumber PORT = new PortNumber(179);
75
76     private OpenConfigMappingUtil() {
77         throw new UnsupportedOperationException();
78     }
79
80     public static String getRibInstanceName(final InstanceIdentifier<?> rootIdentifier) {
81         return rootIdentifier.firstKeyOf(Protocol.class).getName();
82     }
83
84     @Nullable
85     private static Integer getHoldTimer(final Timers timers) {
86         if (timers == null) {
87             return null;
88         }
89         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
90                 .Config config = timers.getConfig();
91         if (config != null && config.getHoldTime() != null) {
92             return config.getHoldTime().intValue();
93         }
94         return null;
95     }
96
97     @Nullable
98     private static AsNumber getPeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
99             .rev151009.bgp.neighbor.group.Config config) {
100         if (config != null) {
101             final AsNumber peerAs = config.getPeerAs();
102             if (peerAs != null) {
103                 return peerAs;
104             }
105         }
106         return null;
107     }
108
109     @Nullable
110     private static Boolean isActive(final Transport transport) {
111         if (transport != null) {
112             final Config config = transport.getConfig();
113             if (config != null && config.isPassiveMode() != null) {
114                 return !config.isPassiveMode();
115             }
116         }
117         return null;
118     }
119
120     @Nullable
121     private static Integer getRetryTimer(final Timers timers) {
122         if (timers == null) {
123             return null;
124         }
125         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
126                 .Config config = timers.getConfig();
127         if (config != null && config.getConnectRetry() != null) {
128             return config.getConnectRetry().intValue();
129         }
130         return null;
131     }
132
133     public static KeyMapping getNeighborKey(final Neighbor neighbor) {
134         if (neighbor.getConfig() != null) {
135             final String authPassword = neighbor.getConfig().getAuthPassword();
136             if (authPassword != null) {
137                 return KeyMapping.getKeyMapping(INSTANCE.inetAddressFor(neighbor.getNeighborAddress()), authPassword);
138             }
139         }
140         return null;
141     }
142
143     public static InstanceIdentifier<Neighbor> getNeighborInstanceIdentifier(
144             final InstanceIdentifier<Bgp> rootIdentifier,
145             final NeighborKey neighborKey) {
146         return rootIdentifier.child(Neighbors.class).child(Neighbor.class, neighborKey);
147     }
148
149     public static String getNeighborInstanceName(final InstanceIdentifier<?> rootIdentifier) {
150         return Ipv4Util.toStringIP(rootIdentifier.firstKeyOf(Neighbor.class).getNeighborAddress());
151     }
152
153     @Nullable
154     private static PortNumber getPort(@Nullable final Transport transport) {
155         if (transport != null) {
156             final Config config = transport.getConfig();
157             if (config != null) {
158                 final NeighborTransportConfig peerTc = config.getAugmentation(NeighborTransportConfig.class);
159                 if (peerTc != null) {
160                     return peerTc.getRemotePort();
161                 }
162                 final PeerGroupTransportConfig peerGroupTc = config.getAugmentation(PeerGroupTransportConfig.class);
163                 if (peerGroupTc != null) {
164                     return peerGroupTc.getRemotePort();
165                 }
166             }
167         }
168         return null;
169     }
170
171     //make sure IPv4 Unicast (RFC 4271) when required
172     public static List<AfiSafi> getAfiSafiWithDefault(
173             final BgpCommonAfiSafiList afiSAfis, final boolean setDeafultIPv4) {
174         if (afiSAfis == null || afiSAfis.getAfiSafi() == null) {
175             return setDeafultIPv4 ? DEFAULT_AFISAFI : Collections.emptyList();
176         }
177         final List<AfiSafi> afiSafi = afiSAfis.getAfiSafi();
178         if (setDeafultIPv4) {
179             final boolean anyMatch = afiSafi.stream()
180                     .anyMatch(input -> input.getAfiSafiName().equals(IPV4UNICAST.class));
181             if (!anyMatch) {
182                 afiSafi.add(IPV4_AFISAFI);
183             }
184         }
185         return afiSafi;
186     }
187
188     public static ClusterIdentifier getGlobalClusterIdentifier(final org.opendaylight.yang.gen.v1.http.openconfig.net
189             .yang.bgp.rev151009.bgp.global.base.Config globalConfig) {
190         final RouteReflectorClusterIdConfig configAug
191                 = globalConfig.getAugmentation(GlobalConfigAugmentation.class);
192         if (configAug != null && configAug.getRouteReflectorClusterId() != null) {
193             return new ClusterIdentifier(configAug.getRouteReflectorClusterId().getIpv4Address());
194         }
195         return new ClusterIdentifier(globalConfig.getRouterId());
196     }
197
198     @Nullable
199     public static ClusterIdentifier getNeighborClusterIdentifier(@Nullable final org.opendaylight.yang.gen.v1.http
200             .openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Config config) {
201         if (config != null) {
202             final RouteReflectorClusterIdConfig configAug = config.getAugmentation(NeighborClusterIdConfig.class);
203             if (configAug != null && configAug.getRouteReflectorClusterId() != null) {
204                 return new ClusterIdentifier(configAug.getRouteReflectorClusterId().getIpv4Address());
205             }
206         }
207         return null;
208     }
209
210     public static Map<BgpTableType, PathSelectionMode> toPathSelectionMode(final List<AfiSafi> afiSafis,
211             final BGPTableTypeRegistryConsumer tableTypeRegistry, final BGPPeerTracker peerTracker) {
212         final Map<BgpTableType, PathSelectionMode> pathSelectionModes = new HashMap<>();
213         for (final AfiSafi afiSafi : afiSafis) {
214             final BgpNeighborAddPathsConfig afiSafi2 = afiSafi.getAugmentation(GlobalAddPathsConfig.class);
215             if (afiSafi2 != null) {
216                 final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
217                 if (bgpTableType.isPresent()) {
218                     final Short sendMax = afiSafi2.getSendMax();
219                     final PathSelectionMode selectionMode;
220                     if (sendMax > 1) {
221                         selectionMode = new AddPathBestNPathSelection(sendMax.longValue(), peerTracker);
222                     } else {
223                         selectionMode = new AllPathSelection(peerTracker);
224                     }
225                     pathSelectionModes.put(bgpTableType.get(), selectionMode);
226                 }
227             }
228         }
229         return pathSelectionModes;
230     }
231
232     public static boolean isApplicationPeer(final Neighbor neighbor) {
233         final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group
234                 .Config config = neighbor.getConfig();
235         if (config != null) {
236             final NeighborPeerGroupConfig config1 = config.getAugmentation(NeighborPeerGroupConfig.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,
246             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
247         final List<AddressFamilies> addPathCapability = new ArrayList<>();
248         for (final AfiSafi afiSafi : afiSafis) {
249             final BgpNeighborAddPathsConfig afiSafi1 = afiSafi.getAugmentation(NeighborAddPathsConfig.class);
250             final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
251             if (afiSafi1 != null && bgpTableType.isPresent()) {
252                 final AddressFamiliesBuilder builder = new AddressFamiliesBuilder(bgpTableType.get());
253                 builder.setSendReceive(toSendReceiveMode(afiSafi1));
254                 addPathCapability.add(builder.build());
255             }
256         }
257         return addPathCapability;
258     }
259
260     private static SendReceive toSendReceiveMode(final BgpNeighborAddPathsConfig addPath) {
261         if (addPath.isReceive() && addPath.getSendMax() != null) {
262             return SendReceive.Both;
263         }
264         if (addPath.getSendMax() != null) {
265             return SendReceive.Send;
266         }
267         return SendReceive.Receive;
268     }
269
270     public static PeerRole toPeerRole(final BgpNeighborGroup neighbor) {
271         if (isRrClient(neighbor)) {
272             return PeerRole.RrClient;
273         }
274
275         if (neighbor.getConfig() != null) {
276             final PeerType peerType = neighbor.getConfig().getPeerType();
277             if (peerType == PeerType.EXTERNAL) {
278                 return PeerRole.Ebgp;
279             } else if (peerType == PeerType.INTERNAL) {
280                 return PeerRole.Ibgp;
281             }
282         }
283         return null;
284     }
285
286     private static boolean isRrClient(final BgpNeighborGroup neighbor) {
287         final RouteReflector routeReflector = neighbor.getRouteReflector();
288         if (routeReflector != null && routeReflector.getConfig() != null) {
289             return routeReflector.getConfig().isRouteReflectorClient();
290         }
291         return false;
292     }
293
294     public static List<BgpTableType> toTableTypes(final List<AfiSafi> afiSafis,
295             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
296         return afiSafis.stream()
297                 .map(afiSafi -> tableTypeRegistry.getTableType(afiSafi.getAfiSafiName()))
298                 .filter(Optional::isPresent)
299                 .map(Optional::get)
300                 .collect(Collectors.toList());
301     }
302
303     public static Set<TablesKey> toTableKey(final List<AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer
304             tableTypeRegistry) {
305         return afiSafis.stream()
306                 .map(afiSafi -> tableTypeRegistry.getTableKey(afiSafi.getAfiSafiName()))
307                 .filter(Optional::isPresent)
308                 .map(Optional::get)
309                 .collect(Collectors.toSet());
310     }
311
312     @Nonnull
313     public static boolean isActive(final Neighbor neighbor, final PeerGroup peerGroup) {
314         Boolean activeConnection = null;
315         if (peerGroup != null) {
316             activeConnection = isActive(peerGroup.getTransport());
317         }
318
319         if (activeConnection == null) {
320             activeConnection = isActive(neighbor.getTransport());
321         }
322         if (activeConnection == null) {
323             return true;
324         }
325         return activeConnection;
326     }
327
328     @Nonnull
329     public static PeerRole toPeerRole(final Neighbor neighbor, final PeerGroup peerGroup) {
330         PeerRole role = null;
331         if (peerGroup != null) {
332             role = toPeerRole(peerGroup);
333         }
334
335         if (role == null) {
336             role = toPeerRole(neighbor);
337         }
338
339         if (role == null) {
340             return PeerRole.Ibgp;
341         }
342         return role;
343     }
344
345     public static int getHoldTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
346         Integer hold = null;
347         if (peerGroup != null) {
348             hold = getHoldTimer(peerGroup.getTimers());
349         }
350
351         if (hold == null) {
352             hold = getHoldTimer(neighbor.getTimers());
353         }
354
355         if (hold == null) {
356             return HOLDTIMER;
357         }
358
359         return hold;
360     }
361
362     @Nonnull
363     public static AsNumber getPeerAs(final Neighbor neighbor, final PeerGroup peerGroup, final AsNumber localAs) {
364         AsNumber neighborAs = null;
365         if (peerGroup != null) {
366             neighborAs = getPeerAs(peerGroup.getConfig());
367         }
368
369         if (neighborAs == null) {
370             neighborAs = getPeerAs(neighbor.getConfig());
371         }
372
373         if (neighborAs == null) {
374             return localAs;
375         }
376         return neighborAs;
377     }
378
379     @Nonnull
380     public static int getRetryTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
381         Integer retryTimer = null;
382         if (peerGroup != null) {
383             retryTimer = getRetryTimer(peerGroup.getTimers());
384         }
385
386         if (retryTimer == null) {
387             retryTimer = getRetryTimer(neighbor.getTimers());
388         }
389
390         if (retryTimer == null) {
391             return CONNECT_RETRY;
392         }
393
394         return retryTimer;
395     }
396
397     @Nonnull
398     public static PortNumber getPort(final Neighbor neighbor, final PeerGroup peerGroup) {
399         PortNumber port = null;
400         if (peerGroup != null) {
401             port = getPort(peerGroup.getTransport());
402         }
403
404         if (port == null) {
405             port = getPort(neighbor.getTransport());
406         }
407
408         if (port == null) {
409             return PORT;
410         }
411
412         return port;
413     }
414 }