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