/* * Copyright (c) 2017 Cisco Systems. 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.groupbasedpolicy.renderer.vpp.lisp.bvi; import com.google.common.base.Preconditions; import com.google.common.eventbus.Subscribe; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand; import org.opendaylight.groupbasedpolicy.renderer.vpp.event.GbpSubnetEvent; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; 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.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import java.util.HashMap; import java.util.List; import java.util.concurrent.ExecutionException; /** * Created by Shakib Ahmed on 4/26/17. */ public class BviManager { private static final Logger LOG = LoggerFactory.getLogger(BviManager.class); private ConfigManagerHelper managerHelper; private HashMap<String, GbpSubnet> subnetInformation; private BviHostSpecificInfo bviHostSpecificInfo; private NeutronTenantToVniMapper neutronTenantToVniMapper; public BviManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) { managerHelper = new ConfigManagerHelper(mountedDataBrokerProvider); subnetInformation = new HashMap<>(); bviHostSpecificInfo = new BviHostSpecificInfo(); neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance(); } @Subscribe public synchronized void gbpSubnetChanged(GbpSubnetEvent event) { final GbpSubnet oldGbpSubnet = event.getBefore().orNull(); final GbpSubnet newGbpSubnet = event.getAfter().orNull(); switch (event.getDtoModificationType()) { case CREATED: Preconditions.checkNotNull(newGbpSubnet); processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet); break; case UPDATED: Preconditions.checkNotNull(oldGbpSubnet); Preconditions.checkNotNull(newGbpSubnet); processSubnetDeleted(oldGbpSubnet.getId()); processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet); break; case DELETED: Preconditions.checkNotNull(oldGbpSubnet); processSubnetDeleted(oldGbpSubnet.getId()); break; } } private void processSubnetCreated(String subnetUuid, GbpSubnet subnetInfo) { subnetInformation.put(subnetUuid, subnetInfo); } private void processSubnetDeleted(String subnetUuid) { subnetInformation.remove(subnetUuid); deleteBviIfExists(subnetUuid); } public GbpSubnet getSubnetInfo(String subnetUuid) { return subnetInformation.get(subnetUuid); } public void createBviIfNecessary(AddressEndpointWithLocation addressEp, String bridgeDomainName) { try { DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(addressEp).get(); String hostName = managerHelper.getHostName(addressEp).get(); String subnetUuid = managerHelper.getSubnet(addressEp); if (bviHostSpecificInfo.bviAlreadyExists(hostName, subnetUuid)) { return; } GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid), "Subnet UUID {} hasn't been created yet!", subnetUuid); LoopbackCommand.LoopbackCommandBuilder loopbackCommandBuilder = new LoopbackCommand.LoopbackCommandBuilder(); loopbackCommandBuilder.setInterfaceName("loop" + bviHostSpecificInfo.getBviCount(hostName)); loopbackCommandBuilder.setBridgeDomain(bridgeDomainName); loopbackCommandBuilder.setBvi(true); loopbackCommandBuilder.setEnabled(true); loopbackCommandBuilder.setVrfId(getVni(addressEp.getTenant().getValue())); loopbackCommandBuilder.setIpAddress(gbpSubnetInfo.getGatewayIp()); loopbackCommandBuilder.setIpPrefix(gbpSubnetInfo.getCidr()); loopbackCommandBuilder.setOperation(General.Operations.PUT); createBviInterface(hostName, vppDataBroker, loopbackCommandBuilder); } catch (LispConfigCommandFailedException e) { LOG.debug("LISP loopback command failed for {}", e.getMessage()); } } public void createBviInterface(String hostName, DataBroker vppDataBroker, LoopbackCommand.LoopbackCommandBuilder commandBuilder) throws LispConfigCommandFailedException { if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, commandBuilder.build(), GbpNetconfTransaction.RETRY_COUNT)) { bviHostSpecificInfo.addBviForHost(hostName, commandBuilder.getBridgeDomain(), commandBuilder.getInterfaceName()); } else { throw new LispConfigCommandFailedException("BVI could not be created for " + hostName + " and bridge domain " + commandBuilder.getBridgeDomain()); } } public void deleteBviIfExists(String subnetUuid) { List<String> hostsWithSubnet = bviHostSpecificInfo.getHostsWithSubnet(subnetUuid); hostsWithSubnet.forEach(host -> { DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(host).get(); String bviInterfaceName = bviHostSpecificInfo.getInterfaceNameForBviInHost(host, subnetUuid); GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker, VppIidFactory.getInterfaceIID(new InterfaceKey(bviInterfaceName)), GbpNetconfTransaction.RETRY_COUNT); }); } private long getVni(String tenantUuid) { return neutronTenantToVniMapper.getVni(tenantUuid); } }