import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.GbpSubnetListener;
import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyListener;
import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppEndpointListener;
if (interfaceManager != null) {
interfaceManager.close();
}
+
+ if (vppGbpSubnetListener != null) {
+ vppGbpSubnetListener.close();
+ }
unregisterFromRendererManager();
}
interfaceManager = new InterfaceManager(mountDataProvider, dataBroker);
AclManager aclManager = new AclManager(mountDataProvider);
NatManager natManager = new NatManager(dataBroker, mountDataProvider);
+ LispStateManager lispStateManager = new LispStateManager(mountDataProvider);
+ BviManager bviManager = new BviManager(mountDataProvider);
dtoEventBus.register(interfaceManager);
+ dtoEventBus.register(bviManager);
RoutingManager routingManager = new RoutingManager(dataBroker, mountDataProvider);
bdManager = new BridgeDomainManagerImpl(dataBroker);
ForwardingManager fwManager =
- new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bdManager, dataBroker);
+ new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bdManager,
+ lispStateManager, bviManager,dataBroker);
VppRendererPolicyManager vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
dtoEventBus.register(vppRendererPolicyManager);
private IpPrefix ipPrefix;
private Long vrfId;
- String getInterfaceName() {
+ public String getInterfaceName() {
return interfaceName;
}
return this;
}
- String getBridgeDomain() {
+ public String getBridgeDomain() {
return bridgeDomain;
}
- LoopbackCommandBuilder setBridgeDomain(String bridgeDomain) {
+ public LoopbackCommandBuilder setBridgeDomain(String bridgeDomain) {
this.bridgeDomain = bridgeDomain;
return this;
}
return enabled;
}
- LoopbackCommandBuilder setEnabled(boolean enabled) {
+ public LoopbackCommandBuilder setEnabled(boolean enabled) {
this.enabled = enabled;
return this;
}
private IpAddress odlTenantIp;
private boolean lispOverlayEnabled = DEFAULT_LISP_OVERLAY_ENABLED;
- private boolean lispMapRegisterEnbled = DEFAULT_LISP_MAPREGISTER_ENABLED;
+ private boolean lispMapRegisterEnabled = DEFAULT_LISP_MAPREGISTER_ENABLED;
private boolean l3FlatEnabled = DEFAULT_L3_FLAT_ENABLED;
static final String ODL_TENANT_IP = "odl.ip.tenant";
void configureMapRegister(String configStr) {
if (configStr == null) {
- lispMapRegisterEnbled = DEFAULT_LISP_MAPREGISTER_ENABLED;
+ lispMapRegisterEnabled = DEFAULT_LISP_MAPREGISTER_ENABLED;
LOG.debug(CONFIGURATION_VARIABLE_MESSAGE, LISP_MAPREGISTER_ENABLED, DEFAULT_LISP_MAPREGISTER_ENABLED);
return;
}
- lispMapRegisterEnbled = configStr.trim().equalsIgnoreCase(DEFAULT_TRUE_STRING_VALUE);
+ lispMapRegisterEnabled = configStr.trim().equalsIgnoreCase(DEFAULT_TRUE_STRING_VALUE);
}
void configL3FlatEnabled(String configStr) {
return lispOverlayEnabled;
}
- public boolean isLispMapRegisterEnbled() {
- return lispMapRegisterEnbled;
+ public boolean isLispMapRegisterEnabled() {
+ return lispMapRegisterEnabled;
}
public boolean isL3FlatEnabled() {
--- /dev/null
+/*
+ * 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;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Created by Shakib Ahmed on 3/29/17.
+ */
+public class LispState {
+ private String hostName;
+ private boolean lispEnabled;
+ private HashMap<String, String> locIntfToLocSetNameMapping;
+ private Set<IpAddress> mapServerIpAddressSet;
+ private Set<IpAddress> mapResolverIpAddressSet;
+ private Set<Long> vniSet;
+ private boolean mapRegisteredEnabled;
+ private HashMap<Eid, String> eidToMappingIdMapper;
+
+ public LispState(String hostName) {
+ this.hostName = hostName;
+ lispEnabled = false;
+ locIntfToLocSetNameMapping = new HashMap<>();
+ mapServerIpAddressSet = new HashSet<>();
+ mapResolverIpAddressSet = new HashSet<>();
+ mapRegisteredEnabled = false;
+ vniSet = new HashSet<>();
+ eidToMappingIdMapper = new HashMap<>();
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public boolean isLispEnabled() {
+ return lispEnabled;
+ }
+
+ public void setLispEnabled(boolean lispEnabled) {
+ this.lispEnabled = lispEnabled;
+ }
+
+ public String getLocIntfToLocSetNameMapping(String locatorIntf) {
+ return locIntfToLocSetNameMapping.get(locatorIntf);
+ }
+
+ public void setLocIntfToLocSetNameMapping(String locIntfName, String locSetName) {
+ locIntfToLocSetNameMapping.put(locIntfName, locSetName);
+ }
+
+ public Set<Map.Entry<String, String>> getLocatorSetEntry() {
+ return locIntfToLocSetNameMapping.entrySet();
+ }
+
+ public int getLocatorCount() {
+ return locIntfToLocSetNameMapping.size();
+ }
+
+ public boolean mapServerSetContains(IpAddress ip) {
+ return mapServerIpAddressSet.contains(ip);
+ }
+
+ public void addInMapServerSet(IpAddress ip) {
+ mapServerIpAddressSet.add(ip);
+ }
+
+ public boolean mapResolverSetContains(IpAddress ip) {
+ return mapResolverIpAddressSet.contains(ip);
+ }
+
+ public void addInMapResolverSet(IpAddress ip) {
+ mapResolverIpAddressSet.add(ip);
+ }
+
+ public boolean vniSetContains(long vni) {
+ return vniSet.contains(vni);
+ }
+
+ public void addInVniSet(long vni) {
+ vniSet.add(vni);
+ }
+
+ public boolean isMapRegisteredEnabled() {
+ return mapRegisteredEnabled;
+ }
+
+ public void setMapRegisteredEnabled(boolean mapRegisteredEnabled) {
+ this.mapRegisteredEnabled = mapRegisteredEnabled;
+ }
+
+ public boolean eidSetContains(Eid eid) {
+ return eidToMappingIdMapper.containsKey(eid);
+ }
+
+ public void addInEidSet(Eid eid, String mappingId) {
+ eidToMappingIdMapper.put(eid, mappingId);
+ }
+
+ public int eidCount() {
+ return eidToMappingIdMapper.size();
+ }
+
+ public void deleteEid(Eid eid) {
+ eidToMappingIdMapper.remove(eid);
+ }
+
+ public String getEidMapping(Eid eid) {
+ return eidToMappingIdMapper.get(eid);
+ }
+}
--- /dev/null
+/*
+ * 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;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 4/18/17.
+ */
+public class LispStateCommandExecutor {
+ private static final Logger LOG = LoggerFactory.getLogger(LispStateCommandExecutor.class);
+
+ public static <T extends DataObject> boolean executePutCommand(DataBroker vppDataBroker,
+ AbstractLispCommand<T> lispStateCommand) {
+ lispStateCommand.setOptions(General.Operations.PUT);
+ return executeCommand(vppDataBroker, lispStateCommand);
+ }
+
+ public static <T extends DataObject> boolean executeDeleteCommand(DataBroker vppDataBroker,
+ AbstractLispCommand<T> lispStateCommand) {
+ lispStateCommand.setOptions(General.Operations.DELETE);
+ return executeCommand(vppDataBroker, lispStateCommand);
+ }
+
+ public static <T extends DataObject> boolean executeCommand(DataBroker vppDataBroker,
+ AbstractLispCommand<T> lispStateCommand) {
+ final boolean transactionState = GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, lispStateCommand,
+ GbpNetconfTransaction.RETRY_COUNT);
+
+ if (transactionState) {
+ LOG.trace("Successfully executed command: ", lispStateCommand);
+ } else {
+ LOG.debug("Failed to execute command: ", lispStateCommand);
+ }
+
+ return transactionState;
+ }
+}
--- /dev/null
+/*
+ * 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;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.LispCommandWrapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
+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.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.params.xml.ns.yang.lisp.rev170315.Lisp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.LocalMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.eid.table.grouping.eid.table.VniTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.lisp.feature.data.grouping.LispFeatureData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.locator.sets.grouping.locator.sets.LocatorSet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.register.grouping.MapRegister;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.resolvers.grouping.map.resolvers.MapResolver;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.servers.grouping.map.servers.MapServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.HashMap;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Created by Shakib Ahmed on 3/29/17.
+ */
+public class LispStateManager {
+ private static final Logger LOG = LoggerFactory.getLogger(LispStateManager.class);
+
+ private HashMap<String, LispState> lispStateMapper;
+ private MountedDataBrokerProvider mountedDataBrokerProvider;
+ private ConfigManagerHelper lispStateHelper;
+
+ private NeutronTenantToVniMapper neutronTenantToVniMapper;
+
+ private static final short DEFAULT_PRIORITY = 1;
+ private static final short DEFAULT_WEIGHT = 1;
+ public static final String DEFAULT_XTR_KEY = "admin";
+ public static final String DEFAULT_LOCATOR_SET_NAME_PREFIX = "LS";
+ public static final String DEFAULT_MAPPINGRECORD_NAME_PREFIX = "MR";
+
+ public LispStateManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
+ Preconditions.checkNotNull(mountedDataBrokerProvider,
+ "MountedDataBrokerProvider found to be null!");
+ lispStateMapper = new HashMap<>();
+ this.mountedDataBrokerProvider= mountedDataBrokerProvider;
+ this.lispStateHelper = new ConfigManagerHelper(this.mountedDataBrokerProvider);
+ neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
+ }
+
+ public synchronized void configureEndPoint(AddressEndpointWithLocation addressEp) {
+ try {
+ DataBroker dataBroker = lispStateHelper.getPotentialExternalDataBroker(addressEp).get();
+ String hostName = lispStateHelper.getHostName(addressEp).get();
+ LispState lispStateOfNode = configureHostIfNeeded(hostName, dataBroker);
+
+ long vni = getVni(addressEp.getTenant().getValue());
+ long vrf = vni;
+ addVniToVrfMappingIfNeeded(dataBroker, lispStateOfNode, vni, vrf);
+
+ Eid eid = lispStateHelper.getEid(addressEp, vni);
+
+ if(!lispStateOfNode.eidSetContains(eid)) {
+ addEidInEidTable(dataBroker, lispStateOfNode, eid);
+ }
+
+ } catch (LispConfigCommandFailedException e) {
+ LOG.warn("Lisp endpoint configuration failed for address endpoint: {}", addressEp);
+ }
+ }
+
+ public synchronized LispState configureHostIfNeeded(String hostName, DataBroker vppDataBroker) throws LispConfigCommandFailedException {
+ LispState lispStateOfNode = lispStateMapper.get(hostName);
+
+ if (lispStateOfNode == null) {
+ lispStateOfNode = new LispState(hostName);
+ try {
+ enableLispForNode(vppDataBroker, lispStateOfNode);
+ addLocatorSet(vppDataBroker, lispStateOfNode);
+ addMapResolver(vppDataBroker, lispStateOfNode);
+ if (ConfigUtil.getInstance().isLispMapRegisterEnabled()) {
+ enableMapRegister(vppDataBroker, lispStateOfNode);
+ addMapServer(vppDataBroker, lispStateOfNode);
+ }
+ lispStateMapper.put(hostName, lispStateOfNode);
+ } catch (LispNotFoundException e) {
+ LOG.warn("Lisp host configuration failed: ", e.getMessage());
+ throw new LispConfigCommandFailedException("Failed LISP configuration!");
+ }
+ }
+ return lispStateOfNode;
+ }
+
+ public synchronized void deleteLispConfigurationForEndpoint(AddressEndpointWithLocation addressEp) {
+ try {
+ DataBroker vppDataBroker = lispStateHelper.getPotentialExternalDataBroker(addressEp).get();
+ String hostName = lispStateHelper.getHostName(addressEp).get();
+
+ LispState lispState = lispStateMapper.get(hostName);
+
+ if (lispState == null) {
+ LOG.debug("Endpoint not configured for LISP. EndPoint: {}", addressEp);
+ } else {
+ long vni = getVni(addressEp.getTenant().getValue());
+ Eid eid = lispStateHelper.getEid(addressEp, vni);
+
+ if (lispState.eidSetContains(eid)) {
+ deleteEidFromEidTable(vppDataBroker, lispState, eid);
+ }
+
+ if (lispState.eidCount() == 0) {
+ deleteLispStatesInEndPoints(vppDataBroker, lispState);
+ }
+ }
+ } catch (LispConfigCommandFailedException e) {
+ LOG.warn("Lisp command execution failed: {}", e.getMessage());
+ }
+ }
+
+ private void enableLispForNode(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
+ AbstractLispCommand<Lisp>
+ lispEnableCommand = LispCommandWrapper.enableLisp();
+ if (LispStateCommandExecutor.executePutCommand(vppDataBroker, lispEnableCommand)) {
+ lispState.setLispEnabled(true);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp Enable Command failed execution!");
+ }
+ }
+
+ private void addLocatorSet(DataBroker vppDataBroker, LispState lispState) throws LispNotFoundException, LispConfigCommandFailedException {
+ try {
+ String locatorSetName = lispStateHelper.constructLocatorSetName(lispState.getLocatorCount());
+ String interfaceName = lispStateHelper.readRlocInterface(lispState.getHostName(), vppDataBroker).get();
+ AbstractLispCommand<LocatorSet> addLocatorSetCommand = LispCommandWrapper.addLocatorSet(locatorSetName,
+ interfaceName, DEFAULT_PRIORITY, DEFAULT_WEIGHT);
+ if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addLocatorSetCommand)) {
+ lispState.setLocIntfToLocSetNameMapping(interfaceName, locatorSetName);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp add locator set failed for host "
+ + lispState.getHostName() + " and locator interface " + interfaceName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ throw new LispNotFoundException("No interface with Ip Address found!");
+ }
+
+ }
+
+ private void addMapResolver(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
+ IpAddress mapResolverIpAddress = ConfigUtil.getInstance().getOdlTenantIp();
+ Preconditions.checkNotNull(mapResolverIpAddress, "Map Resolver ip not properly configured!");
+
+ AbstractLispCommand<MapResolver> addMapResolverCommand = LispCommandWrapper.
+ addMapResolver(mapResolverIpAddress);
+ if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addMapResolverCommand)) {
+ lispState.addInMapResolverSet(mapResolverIpAddress);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp add map resolver for host " + lispState.getHostName()
+ + " failed for ODL ip " + mapResolverIpAddress);
+ }
+ }
+
+ private void addMapServer(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
+ IpAddress mapServerIpAddress = ConfigUtil.getInstance().getOdlTenantIp();
+ Preconditions.checkNotNull(mapServerIpAddress, "Mapserver ip not properly configured!");
+ AbstractLispCommand<MapServer> addMapServerCommand = LispCommandWrapper.addMapServer(mapServerIpAddress);
+
+ if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addMapServerCommand)) {
+ lispState.addInMapServerSet(mapServerIpAddress);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp add map server for host " + lispState.getHostName()
+ + " failed for ODL ip " + mapServerIpAddress);
+ }
+ }
+
+ private void enableMapRegister(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
+ AbstractLispCommand<MapRegister> enableMapRegisterCommand = LispCommandWrapper.enableMapRegister();
+
+ if (LispStateCommandExecutor.executePutCommand(vppDataBroker, enableMapRegisterCommand)) {
+ lispState.setMapRegisteredEnabled(true);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp enable mapregistration for host "
+ + lispState.getHostName() + " failed!");
+ }
+
+ }
+
+ private void addVniToVrfMappingIfNeeded(DataBroker vppDataBroker,
+ LispState lispState,
+ long vni, long vrf) throws LispConfigCommandFailedException {
+ if (!lispState.vniSetContains(vni)) {
+ AbstractLispCommand<VniTable> addVniToVrfMapping = LispCommandWrapper.mapVniToVrf(vni, vrf);
+ addVniToVrfMapping.setOptions(General.Operations.PUT);
+ if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addVniToVrfMapping)) {
+ lispState.addInVniSet(vni);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp add vrf " + vrf +" for vni " +vni
+ + " command failed!");
+ }
+ }
+ }
+
+ private void addEidInEidTable(DataBroker vppDataBroker,
+ LispState lispState,
+ Eid eid) throws LispConfigCommandFailedException {
+ String mappingId = lispStateHelper.constructMappingName(lispState.eidCount());
+ AbstractLispCommand<LocalMapping> addLocalMappingInEidTableCommand = LispCommandWrapper
+ .addLocalMappingInEidTable(mappingId,
+ eid,
+ lispStateHelper.getFirstLocatorSetName(lispState),
+ lispStateHelper.getDefaultHmacKey());
+ if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addLocalMappingInEidTableCommand)) {
+ lispState.addInEidSet(eid, mappingId);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp add local mapping for eid " + eid + "failed!");
+ }
+ }
+
+ private void deleteLispStatesInEndPoints(DataBroker vppDataBroker,
+ LispState lispState) throws LispConfigCommandFailedException {
+ AbstractLispCommand<LispFeatureData> deleteLispFeatureData = LispCommandWrapper.deleteLispFeatureData();
+
+ if (LispStateCommandExecutor.executeDeleteCommand(vppDataBroker, deleteLispFeatureData)) {
+ String computeNode = lispState.getHostName();
+ lispStateMapper.remove(computeNode);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp delete feature data command failed!");
+ }
+ }
+
+ private void deleteEidFromEidTable(DataBroker vppDataBroker,
+ LispState lispState,
+ Eid eid) throws LispConfigCommandFailedException {
+ String mappingId = lispState.getEidMapping(eid);
+ long value = eid.getVirtualNetworkId().getValue();
+
+ AbstractLispCommand<LocalMapping> deleteLocalMappingCommand = LispCommandWrapper
+ .deleteLocalMappingFromEidTable(mappingId, value);
+
+ if (LispStateCommandExecutor.executeDeleteCommand(vppDataBroker, deleteLocalMappingCommand)) {
+ lispState.deleteEid(eid);
+ } else {
+ throw new LispConfigCommandFailedException("Lisp delete local mapping command failed!");
+ }
+ }
+
+ private long getVni(String tenantUuid) {
+ return neutronTenantToVniMapper.getVni(tenantUuid);
+ }
+}
--- /dev/null
+/*
+ * 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.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Created by Shakib Ahmed on 4/26/17.
+ */
+public class BviHostSpecificInfo {
+ private HashMap<String, HashMap<String, String>> hostIdToSubnetMapper;
+ private Multimap<String, String> subnetUuidToHostIdList;
+
+ public BviHostSpecificInfo() {
+ hostIdToSubnetMapper = new HashMap<>();
+ subnetUuidToHostIdList = ArrayListMultimap.create();
+ }
+
+ private HashMap<String, String> getSubnetsOfHost(String hostName) {
+ return hostIdToSubnetMapper.get(hostName);
+ }
+
+ private void putSubnetInfoOfAHost(String hostId, String subnetUuid, String interfaceName) {
+ HashMap<String, String> subnetsOfAHost = getSubnetsOfHost(hostId);
+
+ if (subnetsOfAHost == null) {
+ subnetsOfAHost = new HashMap<>();
+ hostIdToSubnetMapper.put(hostId, subnetsOfAHost);
+ }
+ subnetsOfAHost.put(subnetUuid, interfaceName);
+ }
+
+ public boolean bviAlreadyExists(String hostName, String subnetUuid) {
+ return hostIdToSubnetMapper.containsKey(hostName) &&
+ hostIdToSubnetMapper.get(hostName).containsKey(subnetUuid);
+ }
+
+ public void addBviForHost(String hostName, String subnetUuid, String interfaceName) {
+ putSubnetInfoOfAHost(hostName, subnetUuid, interfaceName);
+ subnetUuidToHostIdList.put(subnetUuid, hostName);
+ }
+
+ public int getBviCount(String hostName) {
+ if (hostIdToSubnetMapper.get(hostName) == null) {
+ return 0;
+ }
+ return hostIdToSubnetMapper.get(hostName).size();
+ }
+
+ public void clearSubnet(String subnetUuid) {
+ subnetUuidToHostIdList.get(subnetUuid).forEach(hostId -> {
+ deleteParticularSubnetFromHost(hostId, subnetUuid);
+ });
+ subnetUuidToHostIdList.get(subnetUuid).clear();
+ }
+
+ private void deleteParticularSubnetFromHost(String hostId, String subnetUuid) {
+ hostIdToSubnetMapper.get(hostId).remove(subnetUuid);
+ }
+
+ public List<String> getHostsWithSubnet(String subnetUuid) {
+ return subnetUuidToHostIdList.get(subnetUuid).stream().collect(Collectors.toList());
+ }
+
+ public String getInterfaceNameForBviInHost(String hostId, String subnetUuid) {
+ if (hostIdToSubnetMapper.get(hostId) != null) {
+ return hostIdToSubnetMapper.get(hostId).get(subnetUuid);
+ } else {
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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.exception;
+
+/**
+ * Created by Shakib Ahmed on 4/3/17.
+ */
+public class LispConfigCommandFailedException extends Exception {
+ public LispConfigCommandFailedException(final String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+/*
+ * 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.exception;
+
+/**
+ * Created by Shakib Ahmed on 3/31/17.
+ */
+public class LispHelperArgumentException extends Exception {
+ public LispHelperArgumentException(final String message) {
+ super(message);
+ }
+}
--- /dev/null
+/*
+ * 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.exception;
+
+/**
+ * Created by Shakib Ahmed on 4/2/17.
+ */
+public class LispNotFoundException extends Exception{
+ public LispNotFoundException(final String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.mappers;
+
+import java.util.HashMap;
+
+/**
+ * Created by Shakib Ahmed on 2/17/17.
+ */
+public class NeutronTenantToVniMapper {
+ private HashMap<String, Long> neutronTenantToVniMapper;
+ private long id = 1;
+
+ private static final NeutronTenantToVniMapper INSTANCE = new NeutronTenantToVniMapper();
+
+ public static NeutronTenantToVniMapper getInstance() {
+ return INSTANCE;
+ }
+
+ private NeutronTenantToVniMapper() {
+ neutronTenantToVniMapper = new HashMap<>();
+ }
+
+ public synchronized long getVni(String tenantUuid) {
+ if (neutronTenantToVniMapper.containsKey(tenantUuid)) {
+ return neutronTenantToVniMapper.get(tenantUuid);
+ }
+ neutronTenantToVniMapper.put(tenantUuid, id);
+ return id++;
+ }
+}
--- /dev/null
+/*
+ * 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.util;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispState;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
+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.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4Afi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
+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.VppEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.hmac.key.grouping.HmacKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Created by Shakib Ahmed on 3/31/17.
+ */
+public class ConfigManagerHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigManagerHelper.class);
+
+ private static final String TENANT_INTERFACE = "tenant-interface";
+ private MountedDataBrokerProvider mountedDataBrokerProvider;
+
+ public ConfigManagerHelper(MountedDataBrokerProvider mountedDataBrokerProvider) {
+ this.mountedDataBrokerProvider = mountedDataBrokerProvider;
+ }
+
+ public Optional<DataBroker> getPotentialExternalDataBroker(AddressEndpointWithLocation addressEpWithLoc) {
+ ExternalLocationCase externalLocationCase = resolveAndValidateLocation(addressEpWithLoc);
+ InstanceIdentifier<?> vppNodeIid = externalLocationCase.getExternalNodeMountPoint();
+ String interfacePath = externalLocationCase.getExternalNodeConnector();
+
+ Optional<DataBroker> potentialVppDataProvider = mountedDataBrokerProvider.getDataBrokerForMountPoint(vppNodeIid);
+
+ Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
+ "Cannot resolve data broker for interface path: {}", interfacePath);
+
+ return potentialVppDataProvider;
+ }
+
+ public Optional<DataBroker> getPotentialExternalDataBroker(VppEndpoint vppEp) {
+ InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(vppEp.getVppNodeId());
+ Optional<DataBroker> potentialVppDataProvider =
+ mountedDataBrokerProvider.getDataBrokerForMountPoint(vppNodeIid);
+
+ Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
+ "Cannot resolve data broker for Vpp Endpoint: {}", vppEp);
+ return potentialVppDataProvider;
+ }
+
+ public Optional<DataBroker> getPotentialExternalDataBroker(String hostId) {
+ InstanceIdentifier<Node> nodeIid = VppIidFactory.getNetconfNodeIid(new NodeId(hostId));
+ Optional<DataBroker> potentialVppDataProvider = mountedDataBrokerProvider.getDataBrokerForMountPoint(nodeIid);
+ Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
+ "Data Broker not found for {}", hostId);
+ return potentialVppDataProvider;
+ }
+
+ public Optional<String> getHostName(AddressEndpointWithLocation addrEp) {
+ ExternalLocationCase locationCase = resolveAndValidateLocation(addrEp);
+ NodeKey nodeKey = locationCase.getExternalNodeMountPoint().firstKeyOf(Node.class);
+ String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
+ "Host Id extraction failed from address endpoint: {}", addrEp);
+ return Optional.fromNullable(hostId);
+ }
+
+ public ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
+ LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
+ if (!(locationType instanceof ExternalLocationCase)) {
+ throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
+ }
+ ExternalLocationCase result = (ExternalLocationCase) locationType;
+ if (result.getExternalNodeMountPoint() == null || result.getExternalNodeConnector() == null) {
+ throw new IllegalArgumentException(
+ "Endpoint does not have external-node-mount-point or external-node-connector " + addrEpWithLoc);
+ }
+ return result;
+ }
+
+ //This is almost identical to VBD's equivalent method
+ public ListenableFuture<String> readRlocInterface(@Nonnull String hostName, @Nonnull DataBroker vppDataBroker) {
+ Preconditions.checkNotNull(hostName, "Hostname is null!");
+ Preconditions.checkNotNull(vppDataBroker, "Vpp DataBroker is null!");
+ final Optional<InterfacesState> opInterfaceState = GbpNetconfTransaction.read(vppDataBroker,
+ LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(InterfacesState.class),
+ GbpNetconfTransaction.RETRY_COUNT);
+
+ if (!opInterfaceState.isPresent()) {
+ LOG.debug("There appear to be no interfaces on node {}.", hostName);
+ return Futures.immediateFailedFuture(new LispNotFoundException("No interfaces found"));
+ }
+
+ String interfaceName = null;
+ for(Interface intf: opInterfaceState.get().getInterface()) {
+ if(!ipAddressPresent(intf)) {
+ continue;
+ }
+ interfaceName = intf.getName();
+ }
+
+ final Optional<Interfaces> opInterfaces =
+ GbpNetconfTransaction.read(vppDataBroker, LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Interfaces.class), GbpNetconfTransaction.RETRY_COUNT);
+
+
+ if (opInterfaces.isPresent()) {
+ for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
+ interfaces.Interface intf : opInterfaces.get().getInterface()) {
+ if (TENANT_INTERFACE.equals(intf.getDescription())
+ && ipAddressPresent(intf)
+ && intf.getType().equals(EthernetCsmacd.class)) {
+ return Futures.immediateFuture(intf.getName());
+ }
+ }
+ }
+
+ if (interfaceName == null) {
+ LOG.warn("No interface with IP found for host {}", hostName);
+ return Futures.immediateFailedFuture(new LispNotFoundException("No interface with Ip address found!"));
+ }
+ return Futures.immediateFuture(interfaceName);
+ }
+
+ private boolean ipAddressPresent(Interface intf) {
+ Interface2 augIntf = intf.getAugmentation(Interface2.class);
+
+ if (augIntf == null) {
+ return false;
+ }
+
+ Ipv4 ipv4 = augIntf.getIpv4();
+
+ if (ipv4 == null) {
+ return false;
+ }
+
+ final List<Address> addresses = ipv4.getAddress();
+
+ if (addresses == null || addresses.isEmpty()) {
+ return false;
+ }
+
+ final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
+
+ if (ip == null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean ipAddressPresent(final org.opendaylight.yang.gen.v1.urn.ietf.
+ params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intf) {
+ final Interface1 augIntf = intf.getAugmentation(Interface1.class);
+
+ if (augIntf == null) {
+ LOG.debug("Cannot get Interface1 augmentation for intf {}", intf);
+ return false;
+ }
+
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4 ipv4 =
+ augIntf.getIpv4();
+ if (ipv4 == null) {
+ return false;
+ }
+
+ final List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address> addresses =
+ ipv4.getAddress();
+ if (addresses == null || addresses.isEmpty()) {
+ return false;
+ }
+
+ final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
+ if (ip == null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public String constructLocatorSetName(int locatorSetCount) {
+ return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + (locatorSetCount + 1);
+ }
+
+ public String constructMappingName(int presentMappingCount) {
+ return LispStateManager.DEFAULT_MAPPINGRECORD_NAME_PREFIX + (presentMappingCount + 1);
+ }
+
+ public String getSubnet(AddressEndpointWithLocation addressEp) {
+ String subnetUuid = null;
+ Containment containment = addressEp.getNetworkContainment().getContainment();
+ if (containment instanceof NetworkDomainContainment) {
+ NetworkDomainContainment networkDomainContainment = (NetworkDomainContainment) containment;
+ subnetUuid = networkDomainContainment.getNetworkDomainId().getValue();
+ }
+ return subnetUuid;
+ }
+
+ public Eid getEid(AddressEndpointWithLocation addressEp, long vni) {
+ String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
+ return LispUtil.toEid(LispUtil.toIpv4(ipPrefix), vni, Ipv4Afi.class);
+ }
+
+ public String getIpWithPrefixOfEndpoint(AddressEndpointWithLocation addressEp) {
+ String ipPrefix = null;
+ if (addressEp.getAddressType().equals(IpPrefixType.class)) {
+ ipPrefix = addressEp.getAddress();
+ }
+ return Preconditions.checkNotNull(ipPrefix,
+ "No IP address found for Address Endpoint: {}", addressEp);
+ }
+
+ public Ipv4Address getInterfaceIp(AddressEndpointWithLocation addressEp) {
+ String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
+ return LispUtil.toIpv4(ipPrefix).getIpv4();
+ }
+
+ public Ipv4Prefix getInterfaceIpAsPrefix(AddressEndpointWithLocation addressEp) {
+ return new Ipv4Prefix(getInterfaceIp(addressEp).getValue() + "/32");
+ }
+
+ public String getFirstLocatorSetName(LispState lispState) {
+ Set<Map.Entry<String, String >> locatorSet = lispState.getLocatorSetEntry();
+ Preconditions.checkNotNull(locatorSet, "No locator set found!");
+ if (!locatorSet.iterator().hasNext()) {
+ return null;
+ }
+
+ return locatorSet.iterator().next().getValue();
+ }
+
+ public HmacKey getDefaultHmacKey() {
+ return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY);
+ }
+
+ public Routing getRouting(long vrf) {
+ return new RoutingBuilder().setIpv4VrfId(vrf).build();
+ }
+}
import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatUtil;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
private final BridgeDomainManager bdManager;
private final NatManager natManager;
private final RoutingManager routingManager;
+ private final LispStateManager lispStateManager;
+ private final BviManager bviManager;
private final DataBroker dataBroker;
public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull AclManager aclManager,
@Nonnull NatManager natManager, @Nonnull RoutingManager routingManager, @Nonnull BridgeDomainManager bdManager,
+ @Nonnull LispStateManager lispStateManager, @Nonnull BviManager bviManager,
@Nonnull DataBroker dataBroker) {
this.ifaceManager = Preconditions.checkNotNull(ifaceManager);
this.bdManager = Preconditions.checkNotNull(bdManager);
this.natManager = Preconditions.checkNotNull(natManager);
this.routingManager = Preconditions.checkNotNull(routingManager);
+ this.lispStateManager = Preconditions.checkNotNull(lispStateManager);
+ this.bviManager = Preconditions.checkNotNull(bviManager);
this.dataBroker = Preconditions.checkNotNull(dataBroker);
this.aclManager = Preconditions.checkNotNull(aclManager);
}
public void createForwardingForEndpoint(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
AddressEndpointWithLocation rEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
+
+ if (ConfigUtil.getInstance().isLispOverlayEnabled()) {
+ lispStateManager.configureEndPoint(rEp);
+ }
+
ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
if (Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
// TODO add it to the status for renderer manager
String l2FloodDomain = optL2FloodDomain.get();
try {
ifaceManager.addBridgeDomainToInterface(l2FloodDomain, rEp, aclManager.resolveAclsOnInterface(
- rEpKey, policyCtx), isBviForEndpoint(rEp)).get();
+ rEpKey, policyCtx), isBviForEndpoint(rEp)).get();
LOG.debug("Interface added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp);
+ if (ConfigUtil.getInstance().isLispOverlayEnabled()) {
+ bviManager.createBviIfNecessary(rEp, l2FloodDomain);
+ }
+
} catch (InterruptedException | ExecutionException e) {
// TODO add it to the status for renderer manager
LOG.warn("Interface was not added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp, e);
}
if (!Strings.isNullOrEmpty(rEpLoc.getExternalNode())) {
try {
+ if (ConfigUtil.getInstance().isLispOverlayEnabled()) {
+ lispStateManager.deleteLispConfigurationForEndpoint(rEp);
+ }
ifaceManager.deleteBridgeDomainFromInterface(rEp).get();
LOG.debug("bridge-domain was deleted from interface for endpoint {}", rEp);
} catch (InterruptedException | ExecutionException e) {
import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.AbstractConfigCommand;
import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.AbstractInterfaceCommand;
import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.interfaces.ConfigCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yangtools.yang.binding.DataObject;
return result;
}
+ /***
+ * Netconf wrapper method for synced requests for write operation on a Netconf Device
+ * @param mountpoint netconf device
+ * @param command abstract lisp command that needs to be executed
+ * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
+ * @return true if transaction is successful, false otherwise
+ */
+ public static <T extends DataObject> boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint,
+ @Nonnull final AbstractLispCommand<T> command,
+ byte retryCounter) {
+ VbdNetconfTransaction.REENTRANT_LOCK.lock();
+ boolean result = write(mountpoint, command, retryCounter);
+ VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+ return result;
+ }
+
/***
* Netconf wrapper method for synced requests for delete operation on a Netconf Device
* @param mountpoint netconf device
}
}
+ /**
+ * Use {@link AbstractLispCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
+ *
+ * @param mountpoint to access remote device
+ * @param command abstract lisp command with data, datastore type and iid
+ * @param retryCounter number of attempts
+ * @return true if transaction is successful, false otherwise
+ */
+ private static <T extends DataObject> boolean write(final DataBroker mountpoint,
+ final AbstractLispCommand<T> command,
+ byte retryCounter) {
+ LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
+ Preconditions.checkNotNull(mountpoint);
+ final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
+ try {
+ command.execute(rwTx);
+ final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
+ futureTask.get();
+ LOG.trace("Netconf WRITE transaction done for command {}", command);
+ return true;
+ } catch (Exception e) {
+ // Retry
+ if (retryCounter > 0) {
+ LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
+ rwTx.cancel();
+ return write(mountpoint, command, --retryCounter);
+ } else {
+ LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
+ return false;
+ }
+ }
+ }
+
/**
* Read data from remote device. Transaction is restarted if failed.
*
--- /dev/null
+/*
+ * 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.util;
+
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.dom.EidDom;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.dom.HmacKeyDom;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.LispAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.hmac.key.grouping.HmacKey;
+
+import java.security.InvalidParameterException;
+
+/**
+ * Created by Shakib Ahmed on 3/21/17.
+ */
+public class LispUtil {
+ private LispUtil() {
+
+ }
+
+ public static Eid toEid(Address address, long vni, Class<? extends LispAddressFamily> addressType) {
+ EidDom eidDom = new EidDom();
+ eidDom.setAddress(address);
+ eidDom.setVni(vni);
+ eidDom.setAddressFamily(addressType);
+ return eidDom.getSALObject();
+ }
+
+ public static HmacKey toHmacKey(HmacKeyType keyType, String key) {
+ HmacKeyDom hmacKeyDom = new HmacKeyDom();
+ hmacKeyDom.setKey(key);
+ hmacKeyDom.setKeyType(keyType);
+ return hmacKeyDom.getSALObject();
+ }
+
+ public static Ipv4 toIpv4(String ipStr) throws InvalidParameterException {
+ String[] strArray = ipStr.split("/");
+ if (strArray.length == 0 || strArray.length > 2) {
+ throw new InvalidParameterException("Parameter " + ipStr + " is invalid for IPv4");
+ }
+
+ if(strArray.length == 2) {
+ int mask = Integer.valueOf(strArray[1]);
+ if(mask != 32) {
+ throw new InvalidParameterException("Parameter " + ipStr + " is invalid for IPv4");
+ }
+ }
+
+ return new Ipv4Builder().setIpv4(new Ipv4Address(strArray[0])).build();
+ }
+}
return new AddressEndpointWithLocationBuilder().setKey(key)
.setNetworkContainment(networkContainment)
.setAbsoluteLocation(absoluteLocation)
+ .setTenant(new TenantId(TENANT_ID))
.build();
}
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
final AclManager aclManager = Mockito.mock(AclManager.class);
final NatManager natManager = Mockito.mock(NatManager.class);
final RoutingManager routingManager = Mockito.mock(RoutingManager.class);
+ final LispStateManager lispStateManager = Mockito.mock(LispStateManager.class);
+ final BviManager bviManager = Mockito.mock(BviManager.class);
final ForwardingManager fwManager =
new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bridgeDomainManager,
- dataBroker);
+ lispStateManager, bviManager, dataBroker);
fwManager.setTimer((byte) 1);
}
import org.opendaylight.groupbasedpolicy.renderer.vpp.DtoFactory;
import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
private NatManager natManager;
@Mock
private RoutingManager routingManager;
+ @Mock
+ private LispStateManager lispStateManager;
+ @Mock
+ private BviManager bviManager;
private ForwardingManager fwdManager;
@Before
public void init() {
fwdManager =
- new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, getDataBroker());
+ new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, lispStateManager,
+ bviManager, getDataBroker());
}
@Override
import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationProvider;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
private ForwardingManager fwManager;
private NatManager natManager;
private RoutingManager routingManager;
+ private LispStateManager lispStateManager;
+ private BviManager bviManager;
private VppRendererPolicyManager vppRendererPolicyManager;
@Override
natManager = new NatManager(dataBroker, mountedDataProviderMock);
routingManager = new RoutingManager(dataBroker, mountedDataProviderMock);
bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
- fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, dataBroker);
+ lispStateManager = new LispStateManager(mountedDataProviderMock);
+ bviManager = new BviManager(mountedDataProviderMock);
+ fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager,
+ lispStateManager, bviManager, dataBroker);
vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
fwManager.setTimer((byte) 1);
}