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