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
9 package org.opendaylight.protocol.bgp.rib.impl.config;
11 import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil.INSTANCE;
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;
19 import java.util.Optional;
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.parser.spi.RevisedErrorHandlingSupport;
29 import org.opendaylight.protocol.bgp.parser.spi.pojo.RevisedErrorHandlingSupportImpl;
30 import org.opendaylight.protocol.concepts.KeyMapping;
31 import org.opendaylight.protocol.util.Ipv4Util;
32 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.BgpCommonAfiSafiList;
33 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
34 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafiBuilder;
35 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborAddPathsConfig;
36 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborGroup;
37 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.BgpNeighborTransportConfig;
38 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.graceful.restart.GracefulRestart;
39 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ErrorHandling;
40 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.RouteReflector;
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.Transport;
43 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.transport.Config;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.NeighborKey;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.peer.group.PeerGroup;
47 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
48 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
49 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4UNICAST;
50 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.PeerType;
51 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.SendReceive;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.add.path.capability.AddressFamilies;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.add.path.capability.AddressFamiliesBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.GlobalAddPathsConfig;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.GlobalConfigAugmentation;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborAddPathsConfig;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborPeerGroupConfig;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborTransportConfig;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.PeerGroupTransportConfig;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.TransportConfig;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.ClusterIdentifier;
69 import org.opendaylight.yangtools.yang.binding.Augmentation;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 final class OpenConfigMappingUtil {
74 static final String APPLICATION_PEER_GROUP_NAME = "application-peers";
75 static final Optional<String> APPLICATION_PEER_GROUP_NAME_OPT = Optional.of(APPLICATION_PEER_GROUP_NAME);
76 static final int HOLDTIMER = 90;
77 private static final AfiSafi IPV4_AFISAFI = new AfiSafiBuilder().setAfiSafiName(IPV4UNICAST.class).build();
78 private static final List<AfiSafi> DEFAULT_AFISAFI = ImmutableList.of(IPV4_AFISAFI);
79 private static final int CONNECT_RETRY = 30;
80 private static final PortNumber PORT = new PortNumber(179);
82 private OpenConfigMappingUtil() {
83 throw new UnsupportedOperationException();
86 static String getRibInstanceName(final InstanceIdentifier<?> rootIdentifier) {
87 return rootIdentifier.firstKeyOf(Protocol.class).getName();
91 private static Integer getHoldTimer(final Timers timers) {
95 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
96 .Config config = timers.getConfig();
97 if (config != null && config.getHoldTime() != null) {
98 return config.getHoldTime().intValue();
104 private static AsNumber getRemotePeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
105 .rev151009.bgp.neighbor.group.Config config) {
106 if (config != null) {
107 final AsNumber peerAs = config.getPeerAs();
108 if (peerAs != null) {
116 private static Integer getRetryTimer(final Timers timers) {
117 if (timers == null) {
120 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.timers
121 .Config config = timers.getConfig();
122 if (config != null && config.getConnectRetry() != null) {
123 return config.getConnectRetry().intValue();
128 static KeyMapping getNeighborKey(final Neighbor neighbor) {
129 if (neighbor.getConfig() != null) {
130 final String authPassword = neighbor.getConfig().getAuthPassword();
131 if (authPassword != null) {
132 return KeyMapping.getKeyMapping(INSTANCE.inetAddressFor(neighbor.getNeighborAddress()), authPassword);
138 static InstanceIdentifier<Neighbor> getNeighborInstanceIdentifier(
139 final InstanceIdentifier<Bgp> rootIdentifier,
140 final NeighborKey neighborKey) {
141 return rootIdentifier.child(Neighbors.class).child(Neighbor.class, neighborKey);
144 static String getNeighborInstanceName(final InstanceIdentifier<?> rootIdentifier) {
145 return Ipv4Util.toStringIP(rootIdentifier.firstKeyOf(Neighbor.class).getNeighborAddress());
149 private static <T extends TransportConfig & Augmentation<Config>> PortNumber getPort(
150 @Nullable final Transport transport, final Class<T> augment) {
151 if (transport != null) {
152 final Config config = transport.getConfig();
153 if (config != null) {
154 final T peerTc = config.augmentation(augment);
155 if (peerTc != null) {
156 return peerTc.getRemotePort();
163 //make sure IPv4 Unicast (RFC 4271) when required
164 static List<AfiSafi> getAfiSafiWithDefault(
165 final BgpCommonAfiSafiList afiSAfis, final boolean setDeafultIPv4) {
166 if (afiSAfis == null || afiSAfis.getAfiSafi() == null) {
167 return setDeafultIPv4 ? DEFAULT_AFISAFI : Collections.emptyList();
169 final List<AfiSafi> afiSafi = afiSAfis.getAfiSafi();
170 if (setDeafultIPv4) {
171 final boolean anyMatch = afiSafi.stream()
172 .anyMatch(input -> input.getAfiSafiName().equals(IPV4UNICAST.class));
174 afiSafi.add(IPV4_AFISAFI);
180 static ClusterIdentifier getGlobalClusterIdentifier(final org.opendaylight.yang.gen.v1.http.openconfig.net
181 .yang.bgp.rev151009.bgp.global.base.Config globalConfig) {
182 final GlobalConfigAugmentation globalConfigAugmentation
183 = globalConfig.augmentation(GlobalConfigAugmentation.class);
184 if (globalConfigAugmentation != null && globalConfigAugmentation.getRouteReflectorClusterId() != null) {
185 return new ClusterIdentifier(globalConfigAugmentation.getRouteReflectorClusterId().getIpv4Address());
187 return new ClusterIdentifier(globalConfig.getRouterId());
191 static ClusterIdentifier getNeighborClusterIdentifier(
192 @Nullable final RouteReflector routeReflector,
193 @Nullable final PeerGroup peerGroup) {
194 if (peerGroup != null) {
195 final ClusterIdentifier clusteriId = extractClusterId(peerGroup.getRouteReflector());
196 if (clusteriId != null) {
201 return extractClusterId(routeReflector);
204 private static ClusterIdentifier extractClusterId(final RouteReflector routeReflector) {
205 if (routeReflector != null) {
206 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.route
207 .reflector.Config config = routeReflector.getConfig();
208 if (config != null && config.getRouteReflectorClusterId() != null) {
209 return new ClusterIdentifier(config.getRouteReflectorClusterId().getIpv4Address());
215 static Map<BgpTableType, PathSelectionMode> toPathSelectionMode(final List<AfiSafi> afiSafis,
216 final BGPTableTypeRegistryConsumer tableTypeRegistry) {
217 final Map<BgpTableType, PathSelectionMode> pathSelectionModes = new HashMap<>();
218 for (final AfiSafi afiSafi : afiSafis) {
219 final BgpNeighborAddPathsConfig afiSafi2 = afiSafi.augmentation(GlobalAddPathsConfig.class);
220 if (afiSafi2 != null) {
221 final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
222 if (bgpTableType.isPresent()) {
223 final int sendMax = afiSafi2.getSendMax();
224 final PathSelectionMode selectionMode;
226 selectionMode = new AddPathBestNPathSelection(sendMax);
228 selectionMode = new AllPathSelection();
230 pathSelectionModes.put(bgpTableType.get(), selectionMode);
234 return pathSelectionModes;
237 static boolean isApplicationPeer(final Neighbor neighbor) {
238 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group
239 .Config config = neighbor.getConfig();
240 if (config != null) {
241 final NeighborPeerGroupConfig config1 = config.augmentation(NeighborPeerGroupConfig.class);
242 if (config1 != null) {
243 final String peerGroup = config1.getPeerGroup();
244 return peerGroup != null && peerGroup.equals(APPLICATION_PEER_GROUP_NAME);
250 static List<AddressFamilies> toAddPathCapability(final List<AfiSafi> afiSafis,
251 final BGPTableTypeRegistryConsumer tableTypeRegistry) {
252 final List<AddressFamilies> addPathCapability = new ArrayList<>();
253 for (final AfiSafi afiSafi : afiSafis) {
254 final BgpNeighborAddPathsConfig afiSafi1 = afiSafi.augmentation(NeighborAddPathsConfig.class);
255 final Optional<BgpTableType> bgpTableType = tableTypeRegistry.getTableType(afiSafi.getAfiSafiName());
256 if (afiSafi1 != null && bgpTableType.isPresent()) {
257 final AddressFamiliesBuilder builder = new AddressFamiliesBuilder(bgpTableType.get());
258 builder.setSendReceive(toSendReceiveMode(afiSafi1));
259 addPathCapability.add(builder.build());
262 return addPathCapability;
265 private static SendReceive toSendReceiveMode(final BgpNeighborAddPathsConfig addPath) {
266 if (addPath.isReceive() && addPath.getSendMax() != null) {
267 return SendReceive.Both;
269 if (addPath.getSendMax() != null) {
270 return SendReceive.Send;
272 return SendReceive.Receive;
275 private static boolean isRrClient(final BgpNeighborGroup neighbor) {
276 final RouteReflector routeReflector = neighbor.getRouteReflector();
277 if (routeReflector != null && routeReflector.getConfig() != null) {
278 return routeReflector.getConfig().isRouteReflectorClient();
283 static List<BgpTableType> toTableTypes(final List<AfiSafi> afiSafis,
284 final BGPTableTypeRegistryConsumer tableTypeRegistry) {
285 return afiSafis.stream()
286 .map(afiSafi -> tableTypeRegistry.getTableType(afiSafi.getAfiSafiName()))
287 .filter(Optional::isPresent)
289 .collect(Collectors.toList());
292 static Set<TablesKey> toTableKey(final List<AfiSafi> afiSafis, final BGPTableTypeRegistryConsumer
294 return afiSafis.stream()
295 .map(afiSafi -> tableTypeRegistry.getTableKey(afiSafi.getAfiSafiName()))
296 .filter(Optional::isPresent)
298 .collect(Collectors.toSet());
301 static boolean isActive(final Neighbor neighbor, final PeerGroup peerGroup) {
302 Boolean activeConnection = null;
303 if (peerGroup != null) {
304 activeConnection = isActive(peerGroup.getTransport());
307 if (activeConnection == null) {
308 activeConnection = isActive(neighbor.getTransport());
310 if (activeConnection == null) {
313 return activeConnection;
317 private static Boolean isActive(final Transport transport) {
318 if (transport != null) {
319 final Config config = transport.getConfig();
320 if (config != null && config.isPassiveMode() != null) {
321 return !config.isPassiveMode();
327 static PeerRole toPeerRole(final BgpNeighborGroup neighbor) {
328 if (isRrClient(neighbor)) {
329 return PeerRole.RrClient;
332 if (neighbor.getConfig() != null) {
333 final PeerType peerType = neighbor.getConfig().getPeerType();
334 if (peerType == PeerType.EXTERNAL) {
335 return PeerRole.Ebgp;
336 } else if (peerType == PeerType.INTERNAL) {
337 return PeerRole.Ibgp;
344 static PeerRole toPeerRole(final Neighbor neighbor, final PeerGroup peerGroup) {
345 PeerRole role = null;
346 if (peerGroup != null) {
347 role = toPeerRole(peerGroup);
351 role = toPeerRole(neighbor);
355 return PeerRole.Ibgp;
360 static int getHoldTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
362 if (peerGroup != null) {
363 hold = getHoldTimer(peerGroup.getTimers());
367 hold = getHoldTimer(neighbor.getTimers());
377 static int getGracefulRestartTimer(final Neighbor neighbor, final PeerGroup peerGroup, final int holdTimer) {
378 Integer timer = null;
379 if (peerGroup != null) {
380 timer = getGracefulRestartTimer(peerGroup.getGracefulRestart());
384 timer = getGracefulRestartTimer(neighbor.getGracefulRestart());
388 * RFC4724: "A suggested default for the Restart Time is a value less than or
389 * equal to the HOLDTIME carried in the OPEN."
399 private static Integer getGracefulRestartTimer(final GracefulRestart gracefulRestart) {
400 if (gracefulRestart != null) {
401 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.graceful.restart.graceful
402 .restart.Config config = gracefulRestart.getConfig();
403 if (config != null) {
404 return config.getRestartTime();
411 static AsNumber getRemotePeerAs(final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009
412 .bgp.neighbor.group.Config config, final PeerGroup peerGroup, final AsNumber localAs) {
413 AsNumber neighborAs = null;
414 if (peerGroup != null) {
415 neighborAs = getRemotePeerAs(peerGroup.getConfig());
418 if (neighborAs == null) {
419 neighborAs = getRemotePeerAs(config);
422 if (neighborAs == null) {
429 static AsNumber getLocalPeerAs(@Nullable final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
430 .rev151009.bgp.neighbor.group.Config config, @Nonnull final AsNumber globalAs) {
431 if (config != null) {
432 final AsNumber peerAs = config.getLocalAs();
433 if (peerAs != null) {
440 static int getRetryTimer(final Neighbor neighbor, final PeerGroup peerGroup) {
441 Integer retryTimer = null;
442 if (peerGroup != null) {
443 retryTimer = getRetryTimer(peerGroup.getTimers());
446 if (retryTimer == null) {
447 retryTimer = getRetryTimer(neighbor.getTimers());
450 if (retryTimer == null) {
451 return CONNECT_RETRY;
458 static PortNumber getPort(final Neighbor neighbor, final PeerGroup peerGroup) {
459 PortNumber port = null;
460 if (peerGroup != null) {
461 port = getPort(peerGroup.getTransport(), PeerGroupTransportConfig.class);
465 port = getPort(neighbor.getTransport(), NeighborTransportConfig.class);
476 static IpAddress getLocalAddress(@Nullable final Transport transport) {
477 if (transport != null && transport.getConfig() != null) {
478 final BgpNeighborTransportConfig.LocalAddress localAddress = transport.getConfig().getLocalAddress();
479 if (localAddress != null) {
480 return localAddress.getIpAddress();
487 static RevisedErrorHandlingSupport getRevisedErrorHandling(final PeerRole role,final PeerGroup peerGroup,
488 final Neighbor neighbor) {
489 Boolean enabled = getRevisedErrorHandling(neighbor);
490 if (enabled == null) {
491 enabled = getRevisedErrorHandling(peerGroup);
493 if (!Boolean.TRUE.equals(enabled)) {
498 return RevisedErrorHandlingSupportImpl.forExternalPeer();
502 return RevisedErrorHandlingSupportImpl.forInternalPeer();
504 throw new IllegalStateException("Unhandled role " + role);
509 private static @org.eclipse.jdt.annotation.Nullable Boolean getRevisedErrorHandling(final BgpNeighborGroup group) {
513 final ErrorHandling errorHandling = group.getErrorHandling();
514 if (errorHandling == null) {
517 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.error.handling
518 .Config config = errorHandling.getConfig();
519 return config == null ? null : config.isTreatAsWithdraw();