X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=neutron%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fovsdb%2Fneutron%2Fprovider%2FOF10Provider.java;fp=neutron%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fovsdb%2Fneutron%2Fprovider%2FOF10ProviderManager.java;h=a0cb62d685ccadaec8f8173d50627ee7bd5f114c;hb=f6cf705bbea44e417a52b32587ec47670e990fc9;hp=1093b34b9733e353500db8f7c8d265514ab83bfb;hpb=f953056d4180ec1e9672f7810cb4318f6d02ffd7;p=netvirt.git diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10ProviderManager.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10Provider.java similarity index 57% rename from neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10ProviderManager.java rename to neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10Provider.java index 1093b34b97..a0cb62d685 100644 --- a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10ProviderManager.java +++ b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10Provider.java @@ -5,7 +5,7 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * - * Authors : Madhu Venugopal, Brent Salisbury + * Authors : Madhu Venugopal, Brent Salisbury, Sam Hague, Dave Tucker */ package org.opendaylight.ovsdb.neutron.provider; @@ -18,6 +18,7 @@ import java.util.Set; import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; import org.opendaylight.controller.sal.action.ActionType; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.utils.EtherTypes; @@ -34,9 +35,10 @@ import org.opendaylight.ovsdb.lib.table.Bridge; import org.opendaylight.ovsdb.lib.table.Interface; import org.opendaylight.ovsdb.lib.table.Port; import org.opendaylight.ovsdb.lib.table.Table; -import org.opendaylight.ovsdb.neutron.AdminConfigManager; -import org.opendaylight.ovsdb.neutron.InternalNetworkManager; -import org.opendaylight.ovsdb.neutron.TenantNetworkManager; +import org.opendaylight.ovsdb.neutron.NetworkHandler; +import org.opendaylight.ovsdb.neutron.IAdminConfigManager; +import org.opendaylight.ovsdb.neutron.IInternalNetworkManager; +import org.opendaylight.ovsdb.neutron.ITenantNetworkManager; import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal; import org.opendaylight.ovsdb.plugin.OVSDBConfigService; import org.opendaylight.ovsdb.plugin.StatusWithUuid; @@ -44,11 +46,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class OF10ProviderManager extends ProviderNetworkManager { - private static final Logger logger = LoggerFactory.getLogger(OF10ProviderManager.class); +public class OF10Provider implements NetworkProvider { + private static final Logger logger = LoggerFactory.getLogger(OF10Provider.class); private static final int INGRESS_TUNNEL_FLOW_PRIORITY = 100; private static final int EGRESS_TUNNEL_FLOW_PRIORITY = 100; - private static final int FLOOD_TUNNEL_FLOW_PRIORITY = 1; + private static final int DROP_FLOW_PRIORITY = 10; + private static final int FLOOD_TUNNEL_FLOW_PRIORITY = 50; + + private IAdminConfigManager adminConfigManager; + private IInternalNetworkManager internalNetworkManager; + private ITenantNetworkManager tenantNetworkManager; + + public OF10Provider(IAdminConfigManager adminConfigManager, + IInternalNetworkManager internalNetworkManager, + ITenantNetworkManager tenantNetworkManager) { + this.adminConfigManager = adminConfigManager; + this.internalNetworkManager = internalNetworkManager; + this.tenantNetworkManager = tenantNetworkManager; + } @Override public boolean hasPerTenantTunneling() { @@ -56,20 +71,33 @@ class OF10ProviderManager extends ProviderNetworkManager { } private Status getTunnelReadinessStatus (Node node, String tunnelKey) { - InetAddress srcTunnelEndPoint = AdminConfigManager.getManager().getTunnelEndPoint(node); + InetAddress srcTunnelEndPoint = adminConfigManager.getTunnelEndPoint(node); if (srcTunnelEndPoint == null) { logger.error("Tunnel Endpoint not configured for Node {}", node); return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node); } - if (!InternalNetworkManager.getManager().isInternalNetworkOverlayReady(node)) { + if (!internalNetworkManager.isInternalNetworkOverlayReady(node)) { logger.warn("{} is not Overlay ready. It might be an OpenStack Controller Node", node); return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready"); } - if (!TenantNetworkManager.getManager().isTenantNetworkPresentInNode(node, tunnelKey)) { - logger.debug(node+" has no VM corresponding to segment "+ tunnelKey); - return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey); + if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) { + logger.debug(node+" has no network corresponding to segment "+ tunnelKey); + return new Status(StatusCode.NOTACCEPTABLE, node+" has no network corresponding to segment "+ tunnelKey); + } + return new Status(StatusCode.SUCCESS); + } + + private Status getVlanReadinessStatus (Node node, String segmentationId) { + if (!internalNetworkManager.isInternalNetworkOverlayReady(node)) { + logger.warn("{} is not Overlay ready. It might be an OpenStack Controller Node", node); + return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready"); + } + + if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, segmentationId)) { + logger.debug(node+" has no network corresponding to segment "+ segmentationId); + return new Status(StatusCode.NOTACCEPTABLE, node+" has no network corresponding to segment "+ segmentationId); } return new Status(StatusCode.SUCCESS); } @@ -80,14 +108,14 @@ class OF10ProviderManager extends ProviderNetworkManager { * and rewrite the Corresponding internal Vlan and pass it on to br-int via the patch port. */ private void programLocalIngressTunnelBridgeRules(Node node, int tunnelOFPort, int internalVlan, int patchPort) { - String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()); - if (brIntId == null) { + String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName()); + if (brNetId == null) { logger.error("Failed to initialize Flow Rules for {}", node); return; } try { OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); - Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId); + Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId); Set dpids = bridge.getDatapath_id(); if (dpids == null || dpids.size() == 0) return; Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0])); @@ -111,14 +139,14 @@ class OF10ProviderManager extends ProviderNetworkManager { } private void removeLocalIngressTunnelBridgeRules(Node node, int tunnelOFPort, int internalVlan, int patchPort) { - String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()); - if (brIntId == null) { + String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName()); + if (brNetId == null) { logger.error("Failed to remove Flow Rules for {}", node); return; } try { OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); - Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId); + Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId); Set dpids = bridge.getDatapath_id(); if (dpids == null || dpids.size() == 0) return; Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0])); @@ -141,14 +169,14 @@ class OF10ProviderManager extends ProviderNetworkManager { */ private void programRemoteEgressTunnelBridgeRules(Node node, int patchPort, String attachedMac, int internalVlan, int tunnelOFPort) { - String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()); - if (brIntId == null) { + String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName()); + if (brNetId == null) { logger.error("Failed to initialize Flow Rules for {}", node); return; } try { OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); - Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId); + Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId); Set dpids = bridge.getDatapath_id(); if (dpids == null || dpids.size() == 0) return; Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0])); @@ -175,14 +203,14 @@ class OF10ProviderManager extends ProviderNetworkManager { private void removeRemoteEgressTunnelBridgeRules(Node node, int patchPort, String attachedMac, int internalVlan, int tunnelOFPort) { - String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()); - if (brIntId == null) { + String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName()); + if (brNetId == null) { logger.error("Failed to initialize Flow Rules for {}", node); return; } try { OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); - Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId); + Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId); Set dpids = bridge.getDatapath_id(); if (dpids == null || dpids.size() == 0) return; Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0])); @@ -203,14 +231,14 @@ class OF10ProviderManager extends ProviderNetworkManager { * Also perform the Strip-Vlan action. */ private void programFloodEgressTunnelBridgeRules(Node node, int patchPort, int internalVlan, int tunnelOFPort) { - String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()); - if (brIntId == null) { + String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName()); + if (brNetId == null) { logger.error("Failed to initialize Flow Rules for {}", node); return; } try { OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); - Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId); + Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId); Set dpids = bridge.getDatapath_id(); if (dpids == null || dpids.size() == 0) return; Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0])); @@ -257,14 +285,14 @@ class OF10ProviderManager extends ProviderNetworkManager { } private void removeFloodEgressTunnelBridgeRules(Node node, int patchPort, int internalVlan, int tunnelOFPort) { - String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()); - if (brIntId == null) { + String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName()); + if (brNetId == null) { logger.error("Failed to remove Flow Rules for {}", node); return; } try { OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); - Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId); + Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId); Set dpids = bridge.getDatapath_id(); if (dpids == null || dpids.size() == 0) return; Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0])); @@ -291,12 +319,12 @@ class OF10ProviderManager extends ProviderNetworkManager { private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node, Interface intf, boolean local) { - String networkId = TenantNetworkManager.getManager().getNetworkIdForSegmentationId(segmentationId); + String networkId = tenantNetworkManager.getNetworkIdForSegmentationId(segmentationId); if (networkId == null) { - logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId); + logger.debug("Tenant Network not found with Segmentation-id {}", segmentationId); return; } - int internalVlan = TenantNetworkManager.getManager().getInternalVlan(node, networkId); + int internalVlan = tenantNetworkManager.getInternalVlan(node, networkId); if (internalVlan == 0) { logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId); return; @@ -307,12 +335,12 @@ class OF10ProviderManager extends ProviderNetworkManager { return; } - String attachedMac = externalIds.get(TenantNetworkManager.EXTERNAL_ID_VM_MAC); + String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC); if (attachedMac == null) { logger.error("No AttachedMac seen in {}", intf); return; } - String patchInt = AdminConfigManager.getManager().getPatchToIntegration(); + String patchInt = adminConfigManager.getPatchToIntegration(); int patchOFPort = -1; try { @@ -367,12 +395,12 @@ class OF10ProviderManager extends ProviderNetworkManager { private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node, Interface intf, boolean local) { - String networkId = TenantNetworkManager.getManager().getNetworkIdForSegmentationId(segmentationId); + String networkId = tenantNetworkManager.getNetworkIdForSegmentationId(segmentationId); if (networkId == null) { - logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId); + logger.debug("Tenant Network not found with Segmentation-id {}",segmentationId); return; } - int internalVlan = TenantNetworkManager.getManager().getInternalVlan(node,networkId); + int internalVlan = tenantNetworkManager.getInternalVlan(node,networkId); if (internalVlan == 0) { logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId); return; @@ -383,12 +411,12 @@ class OF10ProviderManager extends ProviderNetworkManager { return; } - String attachedMac = externalIds.get(TenantNetworkManager.EXTERNAL_ID_VM_MAC); + String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC); if (attachedMac == null) { logger.error("No AttachedMac seen in {}", intf); return; } - String patchInt = AdminConfigManager.getManager().getPatchToIntegration(); + String patchInt = adminConfigManager.getPatchToIntegration(); int patchOFPort = -1; try { @@ -441,48 +469,376 @@ class OF10ProviderManager extends ProviderNetworkManager { } } + private String getIntModVlanFlowName (int inOFPort, String fromVlan, String toVlan) { + return "int_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan; + } + + private String getIntDropFlowName (int inOFPort) { + return "int_drop_"+inOFPort; + } + + private String getNetModVlanFlowName (int inOFPort, String fromVlan, String toVlan) { + return "net_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan; + } + + private String getNetDropFlowName (int inOFPort) { + return "net_drop_"+inOFPort; + } + + private String getNetFwdFlowName (int inOFPort, int outOFPort, String vlan) { + return "net_fwd_"+vlan+"_"+inOFPort+"_"+outOFPort; + } + + private void deleteRule (Node node, Node ofNode, String flowName) { + logger.debug("deleteRule: node: {} / {}, flowName: {}", node, ofNode, flowName); + + try { + this.deleteStaticFlow(ofNode, flowName); + } catch (Exception e) { + logger.error("deleteRule: Failed to delete Flow Rule for {} / {}", node, ofNode, e); + } + } + + /* in_port=p actions=drop */ + private void programDropRule (Node node, Node ofNode, int inOFPort, String flowName) { + logger.debug("programDropRule: node: {} / {}, inOfPort: {}, flowName: {}", + node, ofNode, inOFPort, flowName); + + try { + FlowConfig flow = new FlowConfig(); + flow.setName(flowName); + flow.setNode(ofNode); + flow.setInstallInHw(true); + flow.setPriority(DROP_FLOW_PRIORITY+""); + flow.setIngressPort(inOFPort+""); + List actions = new ArrayList(); + actions.add(ActionType.DROP+""); + flow.setActions(actions); + Status status = this.addStaticFlow(ofNode, flow); + logger.debug("programDropRule: Flow Programming Status {} for Flow {} on {} / {}", + status, flow, node, ofNode); + } catch (Exception e) { + logger.error("programDropRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e); + } + } + + /* in_port=p2,dl_vlan=v actions=mod_vlan_vid,[NORMAL|output:p2] */ + private void programModVlanRule (Node node, Node ofNode, int inOFPort, int outOFPort, String fromVlan, + String toVlan, String flowName) { + logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, fromVlan: {}, toVlan: {}, flowName: {}", + node, ofNode, inOFPort, fromVlan, toVlan, flowName); + + try { + FlowConfig flow = new FlowConfig(); + flow.setName(flowName); + flow.setNode(ofNode); + flow.setInstallInHw(true); + flow.setPriority(INGRESS_TUNNEL_FLOW_PRIORITY+""); + flow.setIngressPort(inOFPort+""); + flow.setVlanId(fromVlan); + List actions = new ArrayList(); + actions.add(ActionType.SET_VLAN_ID+"="+toVlan); + if (outOFPort == -1) { + actions.add(ActionType.HW_PATH.toString()); + } else { + actions.add(ActionType.OUTPUT.toString()+"="+outOFPort); + } + flow.setActions(actions); + Status status = this.addStaticFlow(ofNode, flow); + logger.debug("programModVlanRule: Flow Programming Status {} for Flow {} on {} / {}", + status, flow, node, ofNode); + } catch (Exception e) { + logger.error("programModVlanRule: Failed to initialize Flow Rule for {} / {}", node, ofNode, e); + } + } + + /* in_port=p1,dl_vlan=v actions=output:p2 */ + private void programForwardRule (Node node, Node ofNode, int inOFPort, int outOFPort, String vlan, String flowName) { + logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, outOFPort: {}, flowName: {}", + node, ofNode, inOFPort, outOFPort, flowName); + + try { + FlowConfig flow = new FlowConfig(); + flow.setName(flowName); + flow.setNode(ofNode); + flow.setInstallInHw(true); + flow.setPriority(EGRESS_TUNNEL_FLOW_PRIORITY + ""); + flow.setIngressPort(inOFPort + ""); + flow.setVlanId(vlan); + List actions = new ArrayList(); + actions.add(ActionType.OUTPUT.toString()+"="+outOFPort); + flow.setActions(actions); + Status status = this.addStaticFlow(ofNode, flow); + logger.debug("programForwardRule: Flow Programming Status {} for Flow {} on {} / {}", + status, flow, node, ofNode); + } catch (Exception e) { + logger.error("programForwardRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e); + } + } + + public int getOFPort (Node node, String portName) { + int ofPort = -1; + try { + OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); + Map> intfs = ovsdbTable.getRows(node, Interface.NAME.getName()); + if (intfs != null) { + for (Table row : intfs.values()) { + Interface intf = (Interface)row; + if (intf.getName().equalsIgnoreCase(portName)) { + Set of_ports = intf.getOfport(); + if (of_ports == null || of_ports.size() <= 0) { + logger.error("Could not identify patch port {} on {}", portName, node); + continue; + } + ofPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue(); + logger.debug("Identified port {} -> OF ({}) on {}", portName, ofPort, node); + break; + } + } + } + } catch (Exception e) { + logger.error("", e); + } + + return ofPort; + } + + /* + * Transient class to return all the vlan network data needed for flow programming. + */ + public class vlanNet { + public int patchIntOfPort; + public int patchNetOfPort; + public int physicalOfPort; + public int internalVlan; + + public vlanNet (NeutronNetwork network, Node node, Interface intf) { + patchIntOfPort = -1; + patchNetOfPort = -1; + physicalOfPort = -1; + internalVlan = 0; + + initializeVlanNet(network, node, intf); + } + + public boolean isValid () { + if ((patchIntOfPort != -1) && (patchNetOfPort != -1) && (physicalOfPort != -1) && (internalVlan != -1)) { + return true; + } else { + return false; + } + } + + public int getPatchIntOfPort () { + return patchIntOfPort; + } + + public int getPatchNetOfPort () { + return patchNetOfPort; + } + + public int getphysicalOfPort () { + return physicalOfPort; + } + + public int getInternalVlan () { + return internalVlan; + } + + public void initializeVlanNet (NeutronNetwork network, Node node, Interface intf) { + internalVlan = tenantNetworkManager.getInternalVlan(node, network.getNetworkUUID()); + if (internalVlan == 0) { + logger.debug("No InternalVlan provisioned for Tenant Network {}", network.getNetworkUUID()); + return; + } + + /* Get ofports for patch ports and physical interface. */ + String patchToNetworkName = adminConfigManager.getPatchToNetwork(); + String patchToIntegrationName = adminConfigManager.getPatchToIntegration(); + String physNetName = adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork()); + + patchIntOfPort = getOFPort(node, patchToNetworkName); + if (patchIntOfPort == -1) { + logger.error("Cannot identify {} interface on {}", patchToNetworkName, node); + return; + } + + patchNetOfPort = getOFPort(node, patchToIntegrationName); + if (patchNetOfPort == -1) { + logger.error("Cannot identify {} interface on {}", patchToIntegrationName, node); + return; + } + + physicalOfPort = getOFPort(node, physNetName); + if (physicalOfPort == -1) { + logger.error("Cannot identify {} interface on {}", physNetName, node); + return; + } + } + } + + private Node getOFNode (Node node, String bridgeName) { + String brUUID = internalNetworkManager.getInternalBridgeUUID(node, bridgeName); + if (brUUID == null) { + logger.error("getOFNode: Unable to find {} UUID on node {}", bridgeName, node); + return null; + } + + try { + OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); + Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brUUID); + Set dpids = bridge.getDatapath_id(); + if (dpids == null || dpids.size() == 0) { + return null; + } + Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0])); + Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong); + return ofNode; + } catch (Exception e) { + logger.error("deleteRule: Failed to delete Flow Rule for {}", node, e); + } + + return null; + } + + /* + * Vlan isolation uses a patch port between br-int and br-net. Anything received on one end of + * the patch is piped to the other end of the patch so the incoming packets from the network would + * arrive untouched at the patch port on br-int. + * + * Program OF1.0 Flow rules on br-net in the ingress direction from the network + * and egress direction towards the network. + * The logic is to simply match on the incoming patch OF-Port and internal vlan, + * rewrite the internal vlan to the external vlan and forward out the physical port. + * There is also a flow to match the externally tagged packets from the physical port + * rewrite the external tag to the internal tag and forward to the patch port. + * + * priority=100,in_port=1,dl_vlan=1 actions=mod_vlan_vid:2001,output:2 + * priority=100,in_port=2,dl_vlan=2001 actions=mod_vlan_vid:1actions=output:1 + */ + + private void programVlanRules (NeutronNetwork network, Node node, Interface intf) { + vlanNet vlanNet = new vlanNet(network, node, intf); + if (vlanNet.isValid()) { + String netBrName = adminConfigManager.getNetworkBridgeName(); + String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+""); + String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID()); + + Node netOFNode = getOFNode(node, netBrName); + if (netOFNode == null) { + logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node); + return; + } + + /* Program flows on br-net */ + deleteRule(node, netOFNode, "NORMAL"); + programModVlanRule(node, netOFNode, vlanNet.getPatchNetOfPort(), vlanNet.getphysicalOfPort(), + vlanNet.getInternalVlan()+"", network.getProviderSegmentationID(), intModVlanFlowName); + programModVlanRule(node, netOFNode, vlanNet.getphysicalOfPort(), vlanNet.getPatchNetOfPort(), + network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"", netModVlanFlowName); + } + } + + private void removeVlanRules (NeutronNetwork network, Node node, Interface intf) { + vlanNet vlanNet = new vlanNet(network, node, intf); + if (vlanNet.isValid()) { + String netBrName = adminConfigManager.getNetworkBridgeName(); + String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+""); + String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID()); + + Node netOFNode = getOFNode(node, netBrName); + if (netOFNode == null) { + logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node); + return; + } + + deleteRule(node, netOFNode, intModVlanFlowName); + deleteRule(node, netOFNode, netModVlanFlowName); + } + } + @Override - public Status handleInterfaceUpdate(String tunnelType, String tunnelKey, Node srcNode, Interface intf) { - Status status = getTunnelReadinessStatus(srcNode, tunnelKey); - if (!status.isSuccess()) return status; + public Status handleInterfaceUpdate(NeutronNetwork network, Node srcNode, Interface intf) { + logger.debug("handleInterfaceUpdate: networkType: {}, segmentationId: {}, srcNode: {}, intf: {}", + network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf.getName()); - IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this); - List nodes = connectionService.getNodes(); - nodes.remove(srcNode); - for (Node dstNode : nodes) { - status = getTunnelReadinessStatus(dstNode, tunnelKey); - if (!status.isSuccess()) continue; - InetAddress src = AdminConfigManager.getManager().getTunnelEndPoint(srcNode); - InetAddress dst = AdminConfigManager.getManager().getTunnelEndPoint(dstNode); - status = addTunnelPort(srcNode, tunnelType, src, dst, tunnelKey); - if (status.isSuccess()) { - this.programTunnelRules(tunnelType, tunnelKey, dst, srcNode, intf, true); + if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) { + Status status = getVlanReadinessStatus(srcNode, network.getProviderSegmentationID()); + if (!status.isSuccess()) { + return status; + } else { + this.programVlanRules(network, srcNode, intf); + return new Status(StatusCode.SUCCESS); } - addTunnelPort(dstNode, tunnelType, dst, src, tunnelKey); - if (status.isSuccess()) { - this.programTunnelRules(tunnelType, tunnelKey, src, dstNode, intf, false); + } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || + network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) { + Status status = getTunnelReadinessStatus(srcNode, network.getProviderSegmentationID()); + if (!status.isSuccess()) return status; + + IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this); + List nodes = connectionService.getNodes(); + nodes.remove(srcNode); + for (Node dstNode : nodes) { + status = getTunnelReadinessStatus(dstNode, network.getProviderSegmentationID()); + if (!status.isSuccess()) continue; + InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode); + InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode); + status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst, network.getProviderSegmentationID()); + if (status.isSuccess()) { + this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true); + } + addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src, network.getProviderSegmentationID()); + if (status.isSuccess()) { + this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false); + } } + return new Status(StatusCode.SUCCESS); + } else { + return new Status(StatusCode.BADREQUEST); } - return new Status(StatusCode.SUCCESS); } @Override - public Status handleInterfaceDelete(String tunnelType, String tunnelKey, Node srcNode, Interface intf, boolean isLastInstanceOnNode) { + public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode, Interface intf, boolean isLastInstanceOnNode) { Status status = new Status(StatusCode.SUCCESS); + logger.debug("handleInterfaceDelete: srcNode: {}, networkType: {}, intf: {}, type: {}, isLast: {}", + srcNode, (network != null) ? network.getProviderNetworkType() : "", + intf.getName(), intf.getType(), isLastInstanceOnNode); - IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this); - List nodes = connectionService.getNodes(); - nodes.remove(srcNode); - for (Node dstNode : nodes) { - InetAddress src = AdminConfigManager.getManager().getTunnelEndPoint(srcNode); - InetAddress dst = AdminConfigManager.getManager().getTunnelEndPoint(dstNode); - this.removeTunnelRules(tunnelType, tunnelKey, dst, srcNode, intf, true); + List phyIfName = adminConfigManager.getAllPhysicalInterfaceNames(srcNode); + if ((network != null) && network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) { if (isLastInstanceOnNode) { - status = deleteTunnelPort(srcNode, tunnelType, src, dst, tunnelKey); + this.removeVlanRules(network, srcNode, intf); } - this.removeTunnelRules(tunnelType, tunnelKey, src, dstNode, intf, false); - if (status.isSuccess() && isLastInstanceOnNode) { - deleteTunnelPort(dstNode, tunnelType, dst, src, tunnelKey); + } else if (intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) { + /* Delete tunnel port */ + try { + OvsDBMap options = intf.getOptions(); + InetAddress src = InetAddress.getByName(options.get("local_ip")); + InetAddress dst = InetAddress.getByName(options.get("remote_ip")); + String key = options.get("key"); + status = deleteTunnelPort(srcNode, intf.getType(), src, dst, key); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } else if (phyIfName.contains(intf.getName())) { + deletePhysicalPort(srcNode, intf.getName()); + } else { + /* delete all other interfaces */ + IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this); + List nodes = connectionService.getNodes(); + nodes.remove(srcNode); + for (Node dstNode : nodes) { + InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode); + InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode); + this.removeTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true); + if (isLastInstanceOnNode) { + status = deleteTunnelPort(srcNode, network.getProviderNetworkType(), src, dst, network.getProviderSegmentationID()); + } + this.removeTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false); + if (status.isSuccess() && isLastInstanceOnNode) { + deleteTunnelPort(dstNode, network.getProviderNetworkType(), dst, src, network.getProviderSegmentationID()); + } } } return status; @@ -524,14 +880,14 @@ class OF10ProviderManager extends ProviderNetworkManager { return false; } - private String getTunnelPortUuid(Node node, String tunnelName, String bridgeUUID) throws Exception { + private String getPortUuid(Node node, String portName, String bridgeUUID) throws Exception { OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID); if (bridge != null) { Set ports = bridge.getPorts(); for (UUID portUUID : ports) { Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString()); - if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return portUUID.toString(); + if (port != null && port.getName().equalsIgnoreCase(portName)) return portUUID.toString(); } } return null; @@ -540,7 +896,7 @@ class OF10ProviderManager extends ProviderNetworkManager { private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) { try { String bridgeUUID = null; - String tunnelBridgeName = AdminConfigManager.getManager().getTunnelBridgeName(); + String tunnelBridgeName = adminConfigManager.getNetworkBridgeName(); OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); Map> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName()); if (bridgeTable != null) { @@ -609,34 +965,34 @@ class OF10ProviderManager extends ProviderNetworkManager { } } - private Status deleteTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) { + private Status deletePort(Node node, String bridgeName, String portName) { try { String bridgeUUID = null; - String tunnelBridgeName = AdminConfigManager.getManager().getTunnelBridgeName(); OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); Map> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName()); if (bridgeTable != null) { for (String uuid : bridgeTable.keySet()) { Bridge bridge = (Bridge)bridgeTable.get(uuid); - if (bridge.getName().equals(tunnelBridgeName)) { + if (bridge.getName().equals(bridgeName)) { bridgeUUID = uuid; break; } } } if (bridgeUUID == null) { - logger.debug("Could not find Bridge {} in {}", tunnelBridgeName, node); + logger.debug("Could not find Bridge {} in {}", bridgeName, node); return new Status(StatusCode.SUCCESS); } - String portName = getTunnelName(tunnelType, key, dst); - String tunnelPortUUID = this.getTunnelPortUuid(node, portName, bridgeUUID); - Status status = ovsdbTable.deleteRow(node, Port.NAME.getName(), tunnelPortUUID); - if (!status.isSuccess()) { - logger.error("Failed to delete Tunnel port {} in {} status : {}", portName, bridgeUUID, status); - return status; + String portUUID = this.getPortUuid(node, portName, bridgeUUID); + Status status = new Status(StatusCode.SUCCESS); + if (portUUID != null) { + status = ovsdbTable.deleteRow(node, Port.NAME.getName(), portUUID); + if (!status.isSuccess()) { + logger.error("Failed to delete port {} in {} status : {}", portName, bridgeUUID, status); + return status; + } + logger.debug("Port {} delete status : {}", portName, status); } - - logger.debug("Tunnel {} delete status : {}", portName, status); return status; } catch (Exception e) { logger.error("Exception in deleteTunnelPort", e); @@ -644,27 +1000,39 @@ class OF10ProviderManager extends ProviderNetworkManager { } } + private Status deleteTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) { + String tunnelBridgeName = adminConfigManager.getNetworkBridgeName(); + String portName = getTunnelName(tunnelType, key, dst); + Status status = deletePort(node, tunnelBridgeName, portName); + return status; + } + + private Status deletePhysicalPort(Node node, String phyIntfName) { + String netBridgeName = adminConfigManager.getNetworkBridgeName(); + Status status = deletePort(node, netBridgeName, phyIntfName); + return status; + } + @Override public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) { IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this); List nodes = connectionService.getNodes(); for (Node srcNode : nodes) { - this.handleInterfaceUpdate(tunnelType, tunnelKey, srcNode, null); + this.handleInterfaceUpdate(null, srcNode, null); } return new Status(StatusCode.SUCCESS); } @Override public void initializeFlowRules(Node node) { - this.initializeFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName()); - this.initializeFlowRules(node, AdminConfigManager.getManager().getTunnelBridgeName()); - this.initializeFlowRules(node, AdminConfigManager.getManager().getExternalBridgeName()); + this.initializeFlowRules(node, adminConfigManager.getIntegrationBridgeName()); + this.initializeFlowRules(node, adminConfigManager.getExternalBridgeName()); } private void initializeFlowRules(Node node, String bridgeName) { String brIntId = this.getInternalBridgeUUID(node, bridgeName); if (brIntId == null) { - if (bridgeName == AdminConfigManager.getManager().getExternalBridgeName()){ + if (bridgeName == adminConfigManager.getExternalBridgeName()){ logger.debug("Failed to initialize Flow Rules for bridge {} on node {}. Is the Neutron L3 agent running on this node?"); } else { @@ -750,8 +1118,25 @@ class OF10ProviderManager extends ProviderNetworkManager { IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance( IForwardingRulesManager.class, "default", this); if (frm.getStaticFlow(flowName, ofNode) == null) { - logger.debug("Flow doese not exist {} on {}. Skipping deletion.", flowName, ofNode); + logger.debug("Flow does not exist {} on {}. Skipping deletion.", flowName, ofNode); return new Status(StatusCode.SUCCESS); } return frm.removeStaticFlow(flowName,ofNode); - }} + } + + private String getInternalBridgeUUID (Node node, String bridgeName) { + try { + OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); + Map> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName()); + if (bridgeTable == null) return null; + for (String key : bridgeTable.keySet()) { + Bridge bridge = (Bridge)bridgeTable.get(key); + if (bridge.getName().equals(bridgeName)) return key; + } + } catch (Exception e) { + logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e); + } + return null; + } + +}