/* * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.vpnservice.interfacemgr.commons; import com.google.common.base.Optional; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.vpnservice.interfacemgr.IfmUtil; import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.Profile; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; public class AlivenessMonitorUtils { private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorUtils.class); private static final long FAILURE_THRESHOLD = 4; private static final long MONITORING_INTERVAL = 10000; private static final long MONITORING_WINDOW = 4; public static void startLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker, Interface trunkInterface) { //LLDP monitoring for the trunk interface String trunkInterfaceName = trunkInterface.getName(); IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class); if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class) && ifTunnel.isInternal()) { MonitorStartInput lldpMonitorInput = new MonitorStartInputBuilder().setConfig(new ConfigBuilder() .setSource(new SourceBuilder().setEndpointType(getInterfaceForMonitoring(trunkInterfaceName, ifTunnel.getTunnelSource())).build()) .setMode(MonitoringMode.OneOne) .setProfileId(allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, ifTunnel.getMonitorInterval(), MONITORING_WINDOW, EtherTypes.Lldp)).build()).build(); try { Future> result = alivenessMonitorService.monitorStart(lldpMonitorInput); RpcResult rpcResult = result.get(); long monitorId; if (rpcResult.isSuccessful()) { monitorId = rpcResult.getResult().getMonitorId(); createOrUpdateInterfaceMonitorIdMap(dataBroker, trunkInterfaceName, monitorId); createOrUpdateMonitorIdInterfaceMap(dataBroker, trunkInterfaceName, monitorId); LOG.trace("Started LLDP monitoring with id {}", monitorId); } else { LOG.warn("RPC Call to start monitoring returned with Errors {}", rpcResult.getErrors()); } } catch (InterruptedException | ExecutionException e) { LOG.warn("Exception when starting monitoring", e); } } } public static void stopLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker, Interface trunkInterface) { IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class); if(!(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)&& ifTunnel.isInternal())){ return; } LOG.debug("stop LLDP monitoring for {}", trunkInterface.getName()); List monitorIds = getMonitorIdForInterface(dataBroker, trunkInterface.getName()); if (monitorIds == null) { LOG.error("Monitor Id doesn't exist for Interface {}", trunkInterface); return; } for (Long monitorId : monitorIds) { String interfaceName = getInterfaceFromMonitorId(dataBroker, monitorId); if (interfaceName != null) { MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(monitorId).build(); alivenessMonitorService.monitorStop(input); removeMonitorIdInterfaceMap(dataBroker, monitorId); removeMonitorIdFromInterfaceMonitorIdMap(dataBroker, interfaceName, monitorId); return; } } } public static String getInterfaceFromMonitorId(DataBroker broker, Long monitorId) { InstanceIdentifier id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build(); Optional interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker); if(interfaceMonitorIdMap.isPresent()) { return interfaceMonitorIdMap.get().getInterfaceName(); } return null; } private static void removeMonitorIdInterfaceMap(DataBroker broker, long monitorId) { InstanceIdentifier id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build(); Optional monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker); if(monitorIdInterfaceMap.isPresent()) { MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id); } } private static void removeMonitorIdFromInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) { InstanceIdentifier id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build(); Optional interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker); if(interfaceMonitorIdMap.isPresent()) { InterfaceMonitorId interfaceMonitorIdInstance = interfaceMonitorIdMap.get(); List existingMonitorIds = interfaceMonitorIdInstance.getMonitorId(); if (existingMonitorIds != null && existingMonitorIds.contains(monitorId)) { existingMonitorIds.remove(monitorId); InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder(); interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build(); MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance); } } } private static org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface getInterfaceForMonitoring(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress ipAddress) { return new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint. endpoint.type.InterfaceBuilder().setInterfaceIp(ipAddress).setInterfaceName(interfaceName).build(); } public static void handleTunnelMonitorUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker, Interface interfaceOld, Interface interfaceNew) { String interfaceName = interfaceNew.getName(); IfTunnel ifTunnelNew = interfaceNew.getAugmentation(IfTunnel.class); if(!(ifTunnelNew.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)&& ifTunnelNew.isInternal())){ return; } LOG.debug("handling tunnel monitoring updates for interface {}", interfaceName); stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceOld); if(ifTunnelNew.isMonitorEnabled()) { startLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew); // Delete old profile from Aliveness Manager IfTunnel ifTunnelOld = interfaceOld.getAugmentation(IfTunnel.class); if(ifTunnelNew.getMonitorInterval() != ifTunnelOld.getMonitorInterval()) { LOG.debug("deleting older monitor profile for interface {}", interfaceName); long profileId = allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, ifTunnelOld.getMonitorInterval(), MONITORING_WINDOW, EtherTypes.Lldp); MonitorProfileDeleteInput profileDeleteInput = new MonitorProfileDeleteInputBuilder().setProfileId(profileId).build(); alivenessMonitorService.monitorProfileDelete(profileDeleteInput); } } } public static void createOrUpdateInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) { InterfaceMonitorId interfaceMonitorIdInstance; List existingMonitorIds; InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder(); InstanceIdentifier id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build(); Optional interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker); if (interfaceMonitorIdMap.isPresent()) { interfaceMonitorIdInstance = interfaceMonitorIdMap.get(); existingMonitorIds = interfaceMonitorIdInstance.getMonitorId(); if (existingMonitorIds == null) { existingMonitorIds = new ArrayList<>(); } if (!existingMonitorIds.contains(monitorId)) { existingMonitorIds.add(monitorId); interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build(); MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance); } } else { existingMonitorIds = new ArrayList<>(); existingMonitorIds.add(monitorId); interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setMonitorId(existingMonitorIds).setKey(new InterfaceMonitorIdKey(infName)).setInterfaceName(infName).build(); MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance); } } public static void createOrUpdateMonitorIdInterfaceMap(DataBroker broker,String infName, long monitorId) { MonitorIdInterface monitorIdInterfaceInstance; String existinginterfaceName; MonitorIdInterfaceBuilder monitorIdInterfaceBuilder = new MonitorIdInterfaceBuilder(); InstanceIdentifier id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build(); Optional monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker); if(monitorIdInterfaceMap.isPresent()) { monitorIdInterfaceInstance = monitorIdInterfaceMap.get(); existinginterfaceName = monitorIdInterfaceInstance.getInterfaceName(); if(!existinginterfaceName.equals(infName)) { monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build(); MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance); } } else { monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setMonitorId(monitorId).setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build(); MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance); } } public static List getMonitorIdForInterface(DataBroker broker, String infName) { InstanceIdentifier id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build(); Optional interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker); if(interfaceMonitorIdMap.isPresent()) { return interfaceMonitorIdMap.get().getMonitorId(); } return null; } public static long createMonitorProfile(AlivenessMonitorService alivenessMonitor, MonitorProfileCreateInput monitorProfileCreateInput) { try { Future> result = alivenessMonitor.monitorProfileCreate(monitorProfileCreateInput); RpcResult rpcResult = result.get(); if(rpcResult.isSuccessful()) { return rpcResult.getResult().getProfileId(); } else { LOG.warn("RPC Call to Get Profile Id Id returned with Errors {}.. Trying to fetch existing profile ID", rpcResult.getErrors()); try{ Profile createProfile = monitorProfileCreateInput.getProfile(); Future> existingProfile = alivenessMonitor.monitorProfileGet(buildMonitorGetProfile(createProfile.getMonitorInterval(), createProfile.getMonitorWindow(), createProfile.getFailureThreshold(), createProfile.getProtocolType())); RpcResult rpcGetResult = existingProfile.get(); if(rpcGetResult.isSuccessful()){ return rpcGetResult.getResult().getProfileId(); }else{ LOG.warn("RPC Call to Get Existing Profile Id returned with Errors {}", rpcGetResult.getErrors()); } }catch(Exception e){ LOG.warn("Exception when getting existing profile",e); } } } catch (InterruptedException | ExecutionException e) { LOG.warn("Exception when allocating profile Id",e); } return 0; } private static MonitorProfileGetInput buildMonitorGetProfile(long monitorInterval, long monitorWindow, long failureThreshold, EtherTypes protocolType){ MonitorProfileGetInputBuilder buildGetProfile = new MonitorProfileGetInputBuilder(); org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.get.input.ProfileBuilder profileBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.get.input.ProfileBuilder(); profileBuilder.setFailureThreshold(failureThreshold); profileBuilder.setMonitorInterval(monitorInterval); profileBuilder.setMonitorWindow(monitorWindow); profileBuilder.setProtocolType(protocolType); buildGetProfile.setProfile(profileBuilder.build()); return (buildGetProfile.build()); }; public static long allocateProfile(AlivenessMonitorService alivenessMonitor, long FAILURE_THRESHOLD, long MONITORING_INTERVAL, long MONITORING_WINDOW, EtherTypes etherTypes) { MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder(). setProfile(new ProfileBuilder().setFailureThreshold(FAILURE_THRESHOLD) .setMonitorInterval(MONITORING_INTERVAL).setMonitorWindow(MONITORING_WINDOW). setProtocolType(etherTypes).build()).build(); return createMonitorProfile(alivenessMonitor, input); } public static long allocateDefaultProfile(AlivenessMonitorService alivenessMonitor, EtherTypes etherType ) { MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder(). setProfile(getDefaultMonitorProfile(etherType)).build(); return createMonitorProfile(alivenessMonitor, input); } public static Profile getDefaultMonitorProfile(EtherTypes etherType) { ProfileBuilder profileBuilder = new ProfileBuilder(); profileBuilder.setProtocolType(etherType); profileBuilder.setFailureThreshold(FAILURE_THRESHOLD) .setMonitorInterval(MONITORING_INTERVAL).setMonitorWindow(MONITORING_WINDOW).setProtocolType(etherType); return profileBuilder.build(); } }