import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.netvirt.elanmanager.exceptions.MacNotFoundException;
import java.util.Collection;
List<ElanInstance> getElanInstances();
List<String> getElanInterfaces(String elanInstanceName);
+ void createExternalElanNetwork(ElanInstance elanInstance);
+
+ void createExternalElanNetworks(Node node);
+
}
if segment-type is vlan, this ID is a vlan identifier. If segment-type
is vxlan, this ID is a vni";
}
+ leaf physical-network-name {
+ type string;
+ description "Optional. The name of the phyiscal network attached to the ELAN.";
+ }
leaf mac-timeout {
type uint32 {
range "0..65535";
elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
- // only if vni is present in elanInfo, perform the following
- if (ElanUtils.isVxlan(elanInfo)) {
+ // only if ELAN can connect to external netowrk, perform the following
+ if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) {
Flow flowEntity2 = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true),
5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/true),
getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
protected void add(InstanceIdentifier<Node> identifier, Node node) {
logger.debug("ElanOvsdbNodeListener.add, new node detected {}", node);
doNodeUpdate(node);
+ elanProvider.createExternalElanNetworks(node);
}
private void doNodeUpdate(Node node) {
import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
import org.opendaylight.netvirt.elan.utils.ElanConstants;
import org.opendaylight.netvirt.elan.utils.ElanUtils;
+import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
import org.opendaylight.genius.itm.api.IITMProvider;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.statistics.rev150824.ElanStatisticsService;
+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.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import com.google.common.base.Optional;
+
public class ElanServiceProvider implements BindingAwareProvider, IElanService, AutoCloseable {
private IdManagerService idManager;
public void setGenerateIntBridgeMac(boolean generateIntBridgeMac) {
this.generateIntBridgeMac = generateIntBridgeMac;
}
+
+ @Override
+ public void createExternalElanNetworks(Node node) {
+ if (!bridgeMgr.isIntegrationBridge(node)) {
+ return;
+ }
+
+ List<ElanInstance> elanInstances = getElanInstances();
+ if (elanInstances == null || elanInstances.isEmpty()) {
+ logger.trace("No ELAN instances found");
+ return;
+ }
+
+ for (ElanInstance elanInstance : elanInstances) {
+ String interfaceName = getExtInterfaceName(node, elanInstance.getPhysicalNetworkName());
+ createExternalElanNetwork(elanInstance, node, interfaceName);
+ }
+ }
+
+ @Override
+ public void createExternalElanNetwork(ElanInstance elanInstance) {
+ if (elanInstance.getPhysicalNetworkName() == null) {
+ logger.trace("No physical network attached to {}", elanInstance.getElanInstanceName());
+ return;
+ }
+
+ List<Node> nodes = bridgeMgr.southboundUtils.getOvsdbNodes();
+ if (nodes == null || nodes.isEmpty()) {
+ logger.trace("No OVS nodes found while creating external network for ELAN {}",
+ elanInstance.getElanInstanceName());
+ return;
+ }
+
+ for (Node node : nodes) {
+ if (bridgeMgr.isIntegrationBridge(node)) {
+ String interfaceName = getExtInterfaceName(node, elanInstance.getPhysicalNetworkName());
+ createExternalElanNetwork(elanInstance, node, interfaceName);
+ }
+ }
+ }
+
+ private void createExternalElanNetwork(ElanInstance elanInstance, Node node, String interfaceName) {
+ if (interfaceName == null) {
+ logger.trace("No physial interface is attached to {} node {}", elanInstance.getPhysicalNetworkName(),
+ node.getNodeId().getValue());
+ }
+
+ String elanInterfaceName = createIetfInterfaces(elanInstance, interfaceName);
+ addElanInterface(elanInstance.getElanInstanceName(), elanInterfaceName, null, null);
+ }
+
+ /**
+ * Create ietf-interfaces based on the ELAN segment type.<br>
+ * For segment type flat - create transparent interface pointing to the
+ * patch-port attached to the physnet port.<br>
+ * For segment type vlan - create trunk interface pointing to the patch-port
+ * attached to the physnet port + trunk-member interface pointing to the
+ * trunk interface.
+ *
+ * @param elanInstance
+ * ELAN instance
+ * @param parentRef
+ * parent interface name
+ * @return the name of the interface to be added to the ELAN instance i.e.
+ * trunk-member name for vlan network and transparent for flat
+ * network or null otherwise
+ */
+ private String createIetfInterfaces(ElanInstance elanInstance, String parentRef) {
+ String interfaceName = null;
+
+ try {
+ if (ElanUtils.isFlat(elanInstance)) {
+ interfaceName = parentRef + IfmConstants.OF_URI_PREFIX + "flat";
+ interfaceManager.createVLANInterface(interfaceName, parentRef, null, null, null,
+ IfL2vlan.L2vlanMode.Transparent);
+ } else if (ElanUtils.isVlan(elanInstance)) {
+ String trunkName = parentRef + IfmConstants.OF_URI_PREFIX + "trunk";
+ interfaceManager.createVLANInterface(interfaceName, parentRef, null, null, null,
+ IfL2vlan.L2vlanMode.Trunk);
+ Long segmentationId = elanInstance.getSegmentationId();
+ interfaceName = parentRef + IfmConstants.OF_URI_PREFIX + segmentationId;
+ interfaceManager.createVLANInterface(interfaceName, trunkName, null, segmentationId.intValue(), null,
+ IfL2vlan.L2vlanMode.TrunkMember);
+ }
+ } catch (InterfaceAlreadyExistsException e) {
+ logger.trace("Interface {} was already created", interfaceName);
+ }
+
+ return interfaceName;
+ }
+
+ private String getExtInterfaceName(Node node, String physicalNetworkName) {
+ if (physicalNetworkName == null) {
+ return null;
+ }
+
+ String providerMappingValue = bridgeMgr.getProviderMappingValue(node, physicalNetworkName);
+ if (providerMappingValue == null) {
+ logger.trace("No provider mapping found for physicalNetworkName {} node {}", physicalNetworkName,
+ node.getNodeId().getValue());
+ return null;
+ }
+
+ return bridgeMgr.southboundUtils.getDataPathId(node) + IfmConstants.OF_URI_SEPARATOR
+ + bridgeMgr.getIntBridgePortNameFor(node, providerMappingValue);
+ }
+
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeFlat;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVxlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
&& elanInstance.getSegmentType().isAssignableFrom(SegmentTypeVxlan.class)
&& elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId().longValue() != 0;
}
+
+ public static boolean isVlan(ElanInstance elanInstance) {
+ return elanInstance != null && elanInstance.getSegmentType() != null
+ && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeVlan.class)
+ && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId().longValue() != 0;
+ }
+
+ public static boolean isFlat(ElanInstance elanInstance) {
+ return elanInstance != null && elanInstance.getSegmentType() != null
+ && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeFlat.class);
+ }
}
import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.ext.rev150712.NetworkL3Extension;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
LOG.error("Neutronvpn doesn't support gre network provider type for this network {}.", input);
return;
}
- //Create ELAN instance for this network
- createElanInstance(input);
- if ( input.getAugmentation(NetworkL3Extension.class) != null &&
- input.getAugmentation(NetworkL3Extension.class).isExternal()) {
+ // Create ELAN instance for this network
+ ElanInstance elanInstance = createElanInstance(input);
+ // Create ELAN interface and IETF interfaces for the physical network
+ NeutronvpnServiceAccessor.getElanProvider().createExternalElanNetwork(elanInstance);
+ if (input.getAugmentation(NetworkL3Extension.class).isExternal()) {
nvpnNatManager.addExternalNetwork(input);
NeutronvpnUtils.addToNetworkCache(input);
}
return;
}
//Delete ELAN instance for this network
- deleteElanInstance(input.getUuid().getValue());
+ String elanInstanceName = input.getUuid().getValue();
+ deleteElanInstance(elanInstanceName);
if (input.getAugmentation(NetworkL3Extension.class).isExternal()) {
nvpnNatManager.removeExternalNetwork(input);
NeutronvpnUtils.removeFromNetworkCache(input);
}
+
+ // TODO: delete elan-interfaces for physnet port
}
@Override
}
}
- private void createElanInstance(Network input) {
+ private ElanInstance createElanInstance(Network input) {
String elanInstanceName = input.getUuid().getValue();
Class<? extends SegmentTypeBase> segmentType = NeutronvpnUtils.getSegmentTypeFromNeutronNetwork(input);
String segmentationId = NeutronUtils.getSegmentationIdFromNeutronNetwork(input);
+ String physicalNetworkName = NeutronvpnUtils.getPhysicalNetworkName(input);
ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName);
if (segmentType != null) {
elanInstanceBuilder.setSegmentType(segmentType);
if (segmentationId != null) {
elanInstanceBuilder.setSegmentationId(Long.valueOf(segmentationId));
}
+ if (physicalNetworkName != null) {
+ elanInstanceBuilder.setPhysicalNetworkName(physicalNetworkName);
+ }
}
elanInstanceBuilder.setKey(new ElanInstanceKey(elanInstanceName));
ElanInstance elanInstance = elanInstanceBuilder.build();
InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
.child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInstance);
+ return elanInstance;
}
private void deleteElanInstance(String elanInstanceName) {
Uuid networkId = input.getNetworkId();
Network network = NeutronvpnUtils.getNeutronNetwork(broker, networkId);
if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
- //FIXME: This should be removed when support for VLAN and GRE network types is added
- LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}."
+ //FIXME: This should be removed when support for GRE network types is added
+ LOG.error("neutron vpn doesn't support gre network provider type for the port {} which is part of network {}."
+ " Skipping the processing of Subnet remove DCN", input.getName(), network);
return;
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.netvirt.neutronvpn;
+
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
+
+/**
+ * FIXME :This is a temp hack to access OSGi services from blueprint.
+ * Can be removed after neutronvpn migration to blueprint is complete https://git.opendaylight.org/gerrit/#/c/39001/
+ *
+ */
+public class NeutronvpnServiceAccessor {
+ private static IElanService elanProvider;
+
+ public NeutronvpnServiceAccessor(IElanService elanProvider) {
+ NeutronvpnServiceAccessor.elanProvider = elanProvider;
+ }
+
+ public static IElanService getElanProvider() {
+ return elanProvider;
+ }
+
+}
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.portsecurity.rev150712.PortSecurityExtension;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.neutron.networks.network.Segments;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
return providerExtension != null ? NETWORK_MAP.get(providerExtension.getNetworkType()) : null;
}
+ public static String getPhysicalNetworkName(Network network) {
+ NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+ return providerExtension != null ? providerExtension.getPhysicalNetwork() : null;
+ }
static InstanceIdentifier<VpnPortipToPort> buildVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child
(VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
--- /dev/null
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="elanProvider" interface="org.opendaylight.netvirt.elanmanager.api.IElanService" availability="optional" />
+ <bean id="neutronvpnServiceAccessor" class="org.opendaylight.netvirt.neutronvpn.NeutronvpnServiceAccessor">
+ <argument ref="elanProvider" />
+ </bean>
+</blueprint>
\ No newline at end of file