2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.netvirt.vpnmanager;
10 import com.google.common.base.Optional;
12 import java.util.concurrent.ConcurrentHashMap;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.genius.arputil.api.ArpConstants;
17 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
18 import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
19 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.EtherTypes;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorProfileCreateInput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorProfileCreateInputBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorProfileCreateOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorProfileGetInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorProfileGetInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorProfileGetOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorStartInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorStartInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorStartOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorStopInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitorStopInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.MonitoringMode;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.endpoint.type.Interface;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.endpoint.type.InterfaceBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.params.DestinationBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.params.SourceBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.create.input.Profile;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.create.input.ProfileBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.start.input.ConfigBuilder;
45 import org.opendaylight.yangtools.yang.common.RpcResult;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 public final class AlivenessMonitorUtils {
51 private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorUtils.class);
52 private static Map<Long, MacEntry> alivenessCache = new ConcurrentHashMap<>();
54 private AlivenessMonitorUtils() { }
56 public static void startArpMonitoring(MacEntry macEntry, Long arpMonitorProfileId,
57 AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
58 INeutronVpnManager neutronVpnService,
59 IInterfaceManager interfaceManager) {
60 if (interfaceManager.isExternalInterface(macEntry.getInterfaceName())) {
61 LOG.debug("ARP monitoring is currently not supported through external interfaces,"
62 + "skipping ARP monitoring from interface {} for IP {} (last known MAC {})",
63 macEntry.getInterfaceName(), macEntry.getIpAddress().getHostAddress(), macEntry.getMacAddress());
66 Optional<IpAddress> gatewayIpOptional =
67 VpnUtil.getGatewayIpAddressFromInterface(macEntry.getInterfaceName(), neutronVpnService);
68 if (!gatewayIpOptional.isPresent()) {
69 LOG.error("Error while retrieving GatewayIp for interface{}", macEntry.getInterfaceName());
72 final IpAddress gatewayIp = gatewayIpOptional.get();
73 Optional<String> gatewayMacOptional = VpnUtil.getGWMacAddressFromInterface(macEntry,
74 gatewayIp, dataBroker);
75 if (!gatewayMacOptional.isPresent()) {
76 LOG.error("Error while retrieving GatewayMac for interface{}", macEntry.getInterfaceName());
79 final PhysAddress gatewayMac = new PhysAddress(gatewayMacOptional.get());
80 if (arpMonitorProfileId == null || arpMonitorProfileId.equals(0L)) {
81 Optional<Long> profileIdOptional = allocateProfile(alivenessMonitorService,
82 ArpConstants.FAILURE_THRESHOLD, ArpConstants.ARP_CACHE_TIMEOUT_MILLIS,
83 ArpConstants.MONITORING_WINDOW, EtherTypes.Arp);
84 if (!profileIdOptional.isPresent()) {
85 LOG.error("Error while allocating Profile Id for alivenessMonitorService");
88 arpMonitorProfileId = profileIdOptional.get();
91 IpAddress targetIp = new IpAddress(new Ipv4Address(macEntry.getIpAddress().getHostAddress()));
92 MonitorStartInput arpMonitorInput = new MonitorStartInputBuilder().setConfig(new ConfigBuilder()
93 .setSource(new SourceBuilder().setEndpointType(getSourceEndPointType(macEntry.getInterfaceName(),
94 gatewayIp, gatewayMac)).build())
95 .setDestination(new DestinationBuilder().setEndpointType(getEndPointIpAddress(targetIp)).build())
96 .setMode(MonitoringMode.OneOne)
97 .setProfileId(arpMonitorProfileId).build()).build();
99 Future<RpcResult<MonitorStartOutput>> result = alivenessMonitorService.monitorStart(arpMonitorInput);
100 RpcResult<MonitorStartOutput> rpcResult = result.get();
102 if (rpcResult.isSuccessful()) {
103 monitorId = rpcResult.getResult().getMonitorId();
104 createOrUpdateInterfaceMonitorIdMap(monitorId, macEntry);
105 LOG.trace("Started ARP monitoring with id {}", monitorId);
107 LOG.warn("RPC Call to start monitoring returned with Errors {}", rpcResult.getErrors());
109 } catch (InterruptedException | ExecutionException e) {
110 LOG.warn("Exception when starting monitoring", e);
114 public static void stopArpMonitoring(AlivenessMonitorService alivenessMonitorService,
116 MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(monitorId).build();
118 JdkFutures.addErrorLogging(alivenessMonitorService.monitorStop(input), LOG, "Stop monitoring");
120 alivenessCache.remove(monitorId);
124 private static void createOrUpdateInterfaceMonitorIdMap(long monitorId, MacEntry macEntry) {
125 alivenessCache.put(monitorId, macEntry);
128 private static Interface getSourceEndPointType(String interfaceName, IpAddress ipAddress,
130 return new InterfaceBuilder()
131 .setInterfaceIp(ipAddress)
132 .setInterfaceName(interfaceName)
133 .setMacAddress(gwMac)
137 public static Optional<Long> allocateProfile(AlivenessMonitorService alivenessMonitor,
138 long failureThreshold, long monitoringInterval,
139 long monitoringWindow, EtherTypes etherTypes) {
140 MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder()
141 .setProfile(new ProfileBuilder().setFailureThreshold(failureThreshold)
142 .setMonitorInterval(monitoringInterval).setMonitorWindow(monitoringWindow)
143 .setProtocolType(etherTypes).build()).build();
144 return createMonitorProfile(alivenessMonitor, input);
147 // TODO Clean up the exception handling
148 @SuppressWarnings("checkstyle:IllegalCatch")
149 public static Optional<Long> createMonitorProfile(AlivenessMonitorService alivenessMonitor,
150 MonitorProfileCreateInput monitorProfileCreateInput) {
152 Future<RpcResult<MonitorProfileCreateOutput>> result =
153 alivenessMonitor.monitorProfileCreate(monitorProfileCreateInput);
154 RpcResult<MonitorProfileCreateOutput> rpcResult = result.get();
155 if (rpcResult.isSuccessful()) {
156 return Optional.of(rpcResult.getResult().getProfileId());
158 LOG.warn("RPC Call to Get Profile Id Id returned with Errors {}.. Trying to fetch existing profile ID",
159 rpcResult.getErrors());
161 Profile createProfile = monitorProfileCreateInput.getProfile();
162 Future<RpcResult<MonitorProfileGetOutput>> existingProfile =
163 alivenessMonitor.monitorProfileGet(buildMonitorGetProfile(createProfile.getMonitorInterval(),
164 createProfile.getMonitorWindow(), createProfile.getFailureThreshold(),
165 createProfile.getProtocolType()));
166 RpcResult<MonitorProfileGetOutput> rpcGetResult = existingProfile.get();
167 if (rpcGetResult.isSuccessful()) {
168 return Optional.of(rpcGetResult.getResult().getProfileId());
170 LOG.warn("RPC Call to Get Existing Profile Id returned with Errors {}",
171 rpcGetResult.getErrors());
173 } catch (Exception e) {
174 LOG.warn("Exception when getting existing profile", e);
177 } catch (InterruptedException | ExecutionException e) {
178 LOG.warn("Exception when allocating profile Id", e);
180 return Optional.absent();
183 private static MonitorProfileGetInput buildMonitorGetProfile(long monitorInterval,
184 long monitorWindow, long failureThreshold, EtherTypes protocolType) {
185 MonitorProfileGetInputBuilder buildGetProfile = new MonitorProfileGetInputBuilder();
186 org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.get.input
189 new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.get
190 .input.ProfileBuilder();
191 profileBuilder.setFailureThreshold(failureThreshold)
192 .setMonitorInterval(monitorInterval)
193 .setMonitorWindow(monitorWindow)
194 .setProtocolType(protocolType);
195 buildGetProfile.setProfile(profileBuilder.build());
196 return buildGetProfile.build();
199 public static MacEntry getMacEntryFromMonitorId(Long monitorId) {
200 return alivenessCache.get(monitorId);
203 private static org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411
204 .endpoint.endpoint.type.IpAddress getEndPointIpAddress(IpAddress ip) {
205 return new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411
206 .endpoint.endpoint.type.IpAddressBuilder().setIpAddress(ip).build();
209 public static java.util.Optional<Long> getMonitorIdFromInterface(MacEntry macEntry) {
210 java.util.Optional<Long> monitorId = alivenessCache.entrySet().parallelStream()
211 .filter(map -> macEntry.equals(map.getValue()))
212 .map(Map.Entry::getKey)