2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.protocol.bgp.rib.impl.config;
10 import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil.INSTANCE;
12 import com.google.common.collect.ImmutableList;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.HashMap;
16 import java.util.List;
18 import java.util.Optional;
20 import java.util.stream.Collectors;
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
24 import org.opendaylight.protocol.bgp.mode.impl.add.all.paths.AllPathSelection;
25 import org.opendaylight.protocol.bgp.mode.impl.add.n.paths.AddPathBestNPathSelection;
26 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
27 import org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandlingSupport;
28 import org.opendaylight.protocol.bgp.parser.spi.pojo.RevisedErrorHandlingSupportImpl;
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.graceful.restart.GracefulRestart;
38 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ErrorHandling;
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.Timers;
41 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Transport;
42 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.transport.Config;
43 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.NeighborKey;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.peer.group.PeerGroup;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
47 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
48 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4UNICAST;
49 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.PeerType;
50 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.SendReceive;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.add.path.capability.AddressFamilies;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.add.path.capability.AddressFamiliesBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.GlobalAddPathsConfig;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.GlobalConfigAugmentation;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborAddPathsConfig;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborPeerGroupConfig;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborTransportConfig;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.PeerGroupTransportConfig;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.TransportConfig;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.ClusterIdentifier;
68 import org.opendaylight.yangtools.yang.binding.Augmentation;
69 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
70 import org.opendaylight.yangtools.yang.common.Uint16;
72 final class OpenConfigMappingUtil {
73 static final String APPLICATION_PEER_GROUP_NAME = "application-peers";
74 static final Optional<String> APPLICATION_PEER_GROUP_NAME_OPT = Optional.of(APPLICATION_PEER_GROUP_NAME);
75 static final int HOLDTIMER = 90;
76 private static final AfiSafi IPV4_AFISAFI = new AfiSafiBuilder().setAfiSafiName(IPV4UNICAST.class).build();
77 private static final List<AfiSafi> DEFAULT_AFISAFI = ImmutableList.of(IPV4_AFISAFI);
78 private static final int CONNECT_RETRY = 30;
79 private static final PortNumber PORT = new PortNumber(Uint16.valueOf(179).intern());
81 private OpenConfigMappingUtil() {
85 static String getRibInstanceName(final InstanceIdentifier<?> rootIdentifier) {
86 return rootIdentifier.firstKeyOf(Protocol.class).getName();
89 static KeyMapping getNeighborKey(final Neighbor neighbor) {
90 if (neighbor.getConfig() != null) {
91 final String authPassword = neighbor.getConfig().getAuthPassword();
92 if (authPassword != null) {
93 return KeyMapping.getKeyMapping(INSTANCE.inetAddressFor(neighbor.getNeighborAddress()), authPassword);
99 static InstanceIdentifier<Neighbor> getNeighborInstanceIdentifier(
100 final InstanceIdentifier<Bgp> rootIdentifier,
101 final NeighborKey neighborKey) {
102 return rootIdentifier.child(Neighbors.class).child(Neighbor.class, neighborKey);
105 static String getNeighborInstanceName(final InstanceIdentifier<?> rootIdentifier) {
106 return Ipv4Util.toStringIP(rootIdentifier.firstKeyOf(Neighbor.class).getNeighborAddress());
109 //make sure IPv4 Unicast (RFC 4271) when required
110 static List<AfiSafi> getAfiSafiWithDefault(
111 final BgpCommonAfiSafiList afiSAfis, final boolean setDeafultIPv4) {
112 if (afiSAfis == null || afiSAfis.getAfiSafi() == null) {
113 return setDeafultIPv4 ? DEFAULT_AFISAFI : Collections.emptyList();
115 final List<AfiSafi> afiSafi = afiSAfis.getAfiSafi();
116 if (setDeafultIPv4) {
117 final boolean anyMatch = afiSafi.stream()
118 .anyMatch(input -> input.getAfiSafiName().equals(IPV4UNICAST.class));
120 final List<AfiSafi> newAfiSafi = new ArrayList<>(afiSafi.size() + 1);
121 newAfiSafi.addAll(afiSafi);
122 newAfiSafi.add(IPV4_AFISAFI);
129 static ClusterIdentifier getGlobalClusterIdentifier(final org.opendaylight.yang.gen.v1.http.openconfig.net
130 .yang.bgp.rev151009.bgp.global.base.Config globalConfig) {
131 final GlobalConfigAugmentation globalConfigAugmentation
132 = globalConfig.augmentation(GlobalConfigAugmentation.class);
133 if (globalConfigAugmentation != null && globalConfigAugmentation.getRouteReflectorClusterId() != null) {
134 return new ClusterIdentifier(globalConfigAugmentation.getRouteReflectorClusterId().getIpv4Address());
136 return new ClusterIdentifier(globalConfig.getRouterId());
139 static @Nullable ClusterIdentifier getNeighborClusterIdentifier(
140 final @Nullable RouteReflector routeReflector, final @Nullable PeerGroup peerGroup) {
141 if (peerGroup != null) {
142 final ClusterIdentifier clusteriId = extractClusterId(peerGroup.getRouteReflector());
143 if (clusteriId != null) {
148 return extractClusterId(routeReflector);
151 private static ClusterIdentifier extractClusterId(final RouteReflector routeReflector) {
152 if (routeReflector != null) {
153 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.route
154 .reflector.Config config = routeReflector.getConfig();
155 if (config != null && config.getRouteReflectorClusterId() != null) {
156 return new ClusterIdentifier(config.getRouteReflectorClusterId().getIpv4Address());
162 static Map<BgpTableType, PathSelectionMode> toPathSelectionMode(final List<AfiSafi> afiSafis,
163 final BGPTableTypeRegistryConsumer tableTypeRegistry) {
164 final Map<BgpTableType, PathSelectionMode> pathSelectionModes = new HashMap<>();
165 for (final AfiSafi afiSafi : afiSafis) {
166 final BgpNeighborAddPathsConfig afiSafi2 = afiSafi.augmentation(GlobalAddPathsConfig.class);
167 if (afiSafi2 != null) {
168 final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
169 if (bgpTableType.isPresent()) {
170 final short sendMax = afiSafi2.getSendMax().toJava();
171 final PathSelectionMode selectionMode;
173 selectionMode = new AddPathBestNPathSelection(sendMax);
175 selectionMode = new AllPathSelection();
177 pathSelectionModes.put(bgpTableType.get(), selectionMode);
181 return pathSelectionModes;
184 static boolean isApplicationPeer(final Neighbor neighbor) {
185 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group
186 .Config config = neighbor.getConfig();
187 if (config != null) {
188 final NeighborPeerGroupConfig config1 = config.augmentation(NeighborPeerGroupConfig.class);
189 if (config1 != null) {
190 final String peerGroup = config1.getPeerGroup();
191 return peerGroup != null && peerGroup.equals(APPLICATION_PEER_GROUP_NAME);
197 static List<AddressFamilies> toAddPathCapability(final List<AfiSafi> afiSafis,
198 final BGPTableTypeRegistryConsumer tableTypeRegistry) {
199 final List<AddressFamilies> addPathCapability = new ArrayList<>();
200 for (final AfiSafi afiSafi : afiSafis) {
201 final BgpNeighborAddPathsConfig afiSafi1 = afiSafi.augmentation(NeighborAddPathsConfig.class);
202 final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
203 if (afiSafi1 != null && bgpTableType.isPresent()) {
204 final AddressFamiliesBuilder builder = new AddressFamiliesBuilder(bgpTableType.get());
205 builder.setSendReceive(toSendReceiveMode(afiSafi1));
206 addPathCapability.add(builder.build());
209 return addPathCapability;
212 private static SendReceive toSendReceiveMode(final BgpNeighborAddPathsConfig addPath) {
213 if (addPath.isReceive() && addPath.getSendMax() != null) {
214 return SendReceive.Both;
216 if (addPath.getSendMax() != null) {
217 return SendReceive.Send;
219 return SendReceive.Receive;
222 private static boolean isRrClient(final BgpNeighborGroup neighbor) {
223 final RouteReflector routeReflector = neighbor.getRouteReflector();
224 if (routeReflector != null && routeReflector.getConfig() != null) {
225 return routeReflector.getConfig().isRouteReflectorClient();
230 static List<BgpTableType> toTableTypes(final List<AfiSafi> afiSafis,
231 final BGPTableTypeRegistryConsumer tableTypeRegistry) {
232 return afiSafis.stream()
233 .map(afiSafi -> tableTypeRegistry.getTableType(afiSafi.getAfiSafiName()))
234 .filter(Optional::isPresent)
236 .collect(Collectors.toList());
239 static Set<TablesKey> toTableKey(final List<AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer
241 return afiSafis.stream()
242 .map(afiSafi -> tableTypeRegistry.getTableKey(afiSafi.getAfiSafiName()))
243 .filter(Optional::isPresent)
245 .collect(Collectors.toSet());
248 static boolean isActive(final Neighbor neighbor, final PeerGroup peerGroup) {
249 Optional<Boolean> activeConnection = peerGroup == null ? Optional.empty() : isActive(peerGroup.getTransport());
250 if (!activeConnection.isPresent()) {
251 activeConnection = isActive(neighbor.getTransport());
253 return activeConnection.orElse(Boolean.TRUE);
256 private static Optional<Boolean> isActive(final Transport transport) {
257 if (transport != null) {
258 final Config config = transport.getConfig();
259 if (config != null) {
260 final Boolean passive = config.isPassiveMode();
261 if (passive != null) {
262 return Optional.of(!passive);
266 return Optional.empty();
269 static PeerRole toPeerRole(final BgpNeighborGroup neighbor) {
270 if (isRrClient(neighbor)) {
271 return PeerRole.RrClient;
274 if (neighbor.getConfig() != null) {
275 final PeerType peerType = neighbor.getConfig().getPeerType();
276 if (peerType == PeerType.EXTERNAL) {
277 return PeerRole.Ebgp;
278 } else if (peerType == PeerType.INTERNAL) {
279 return PeerRole.Ibgp;
285 static @NonNull PeerRole toPeerRole(final Neighbor neighbor, final PeerGroup peerGroup) {
286 PeerRole role = null;
287 if (peerGroup != null) {
288 role = toPeerRole(peerGroup);
292 role = toPeerRole(neighbor);
296 return PeerRole.Ibgp;
301 static int getHoldTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
303 if (peerGroup != null) {
304 hold = getHoldTimer(peerGroup.getTimers());
308 hold = getHoldTimer(neighbor.getTimers());
318 private static @Nullable Integer getHoldTimer(final Timers timers) {
319 if (timers == null) {
322 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
323 .Config config = timers.getConfig();
324 if (config != null && config.getHoldTime() != null) {
325 return config.getHoldTime().intValue();
330 static int getGracefulRestartTimer(final Neighbor neighbor, final PeerGroup peerGroup, final int holdTimer) {
332 if (peerGroup != null) {
333 timer = getGracefulRestartTimer(peerGroup.getGracefulRestart());
337 timer = getGracefulRestartTimer(neighbor.getGracefulRestart());
341 * RFC4724: "A suggested default for the Restart Time is a value less than or
342 * equal to the HOLDTIME carried in the OPEN."
344 return timer == null ? holdTimer : timer.toJava();
347 private static @Nullable Uint16 getGracefulRestartTimer(final GracefulRestart gracefulRestart) {
348 if (gracefulRestart != null) {
349 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.graceful.restart.graceful
350 .restart.Config config = gracefulRestart.getConfig();
351 if (config != null) {
352 return config.getRestartTime();
358 static @NonNull AsNumber getRemotePeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009
359 .bgp.neighbor.group.Config config, final PeerGroup peerGroup, final AsNumber localAs) {
360 AsNumber neighborAs = null;
361 if (peerGroup != null) {
362 neighborAs = getRemotePeerAs(peerGroup.getConfig());
365 if (neighborAs == null) {
366 neighborAs = getRemotePeerAs(config);
369 if (neighborAs == null) {
375 private static AsNumber getRemotePeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
376 .rev151009.bgp.neighbor.group.@Nullable Config config) {
377 return config == null ? null : config.getPeerAs();
380 static @NonNull AsNumber getLocalPeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
381 .rev151009.bgp.neighbor.group.@Nullable Config config, final @NonNull AsNumber globalAs) {
382 if (config != null) {
383 final AsNumber peerAs = config.getLocalAs();
384 if (peerAs != null) {
391 static int getRetryTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
392 Integer retryTimer = null;
393 if (peerGroup != null) {
394 retryTimer = getRetryTimer(peerGroup.getTimers());
397 if (retryTimer == null) {
398 retryTimer = getRetryTimer(neighbor.getTimers());
401 if (retryTimer == null) {
402 return CONNECT_RETRY;
408 private static @Nullable Integer getRetryTimer(final Timers timers) {
409 if (timers == null) {
412 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
413 .Config config = timers.getConfig();
414 if (config != null && config.getConnectRetry() != null) {
415 return config.getConnectRetry().intValue();
420 static @NonNull PortNumber getPort(final Neighbor neighbor, final PeerGroup peerGroup) {
421 PortNumber port = null;
422 if (peerGroup != null) {
423 port = getPort(peerGroup.getTransport(), PeerGroupTransportConfig.class);
427 port = getPort(neighbor.getTransport(), NeighborTransportConfig.class);
437 private static <T extends TransportConfig & Augmentation<Config>> @Nullable PortNumber getPort(
438 final @Nullable Transport transport, final Class<T> augment) {
439 if (transport != null) {
440 final Config config = transport.getConfig();
441 if (config != null) {
442 final T peerTc = config.augmentation(augment);
443 if (peerTc != null) {
444 return peerTc.getRemotePort();
451 static @Nullable IpAddress getLocalAddress(@Nullable final Transport transport) {
452 if (transport != null && transport.getConfig() != null) {
453 final BgpNeighborTransportConfig.LocalAddress localAddress = transport.getConfig().getLocalAddress();
454 if (localAddress != null) {
455 return localAddress.getIpAddress();
461 static @Nullable RevisedErrorHandlingSupport getRevisedErrorHandling(final PeerRole role,final PeerGroup peerGroup,
462 final Neighbor neighbor) {
463 Optional<Boolean> enabled = getRevisedErrorHandling(neighbor);
464 if (!enabled.isPresent()) {
465 enabled = getRevisedErrorHandling(peerGroup);
467 if (!enabled.orElse(Boolean.FALSE)) {
472 return RevisedErrorHandlingSupportImpl.forExternalPeer();
476 return RevisedErrorHandlingSupportImpl.forInternalPeer();
478 throw new IllegalStateException("Unhandled role " + role);
482 private static Optional<Boolean> getRevisedErrorHandling(final BgpNeighborGroup group) {
484 return Optional.empty();
486 final ErrorHandling errorHandling = group.getErrorHandling();
487 if (errorHandling == null) {
488 return Optional.empty();
490 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.error.handling
491 .Config config = errorHandling.getConfig();
492 return config == null ? Optional.empty() : Optional.of(config.isTreatAsWithdraw());