Interface ofport and ofport_request support
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / OF13Provider.java
index b295957f5ac43509554581c5ef81c243eb2d629b..2ca1faf598b315b059f5ffbd74682e36d49e758c 100644 (file)
@@ -21,17 +21,14 @@ import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
-import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
-import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.controller.sal.utils.HexEncode;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.neutron.spi.NeutronNetwork;
+import org.opendaylight.neutron.spi.NeutronSecurityGroup;
 import org.opendaylight.ovsdb.lib.notation.Row;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.ClassifierProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
@@ -41,10 +38,13 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
+import org.opendaylight.ovsdb.plugin.api.Status;
+import org.opendaylight.ovsdb.plugin.api.StatusCode;
 import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
 import org.opendaylight.ovsdb.schema.openvswitch.Port;
+import org.opendaylight.ovsdb.utils.mdsal.node.StringConvertor;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
@@ -85,6 +85,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -106,10 +107,9 @@ public class OF13Provider implements NetworkingProvider {
     private static final short TABLE_0_DEFAULT_INGRESS = 0;
     private static final short TABLE_1_ISOLATE_TENANT = 10;
     private static final short TABLE_2_LOCAL_FORWARD = 20;
-    private static final String OPENFLOW = "openflow:";
     private static Long groupId = 1L;
 
-    private volatile org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService configurationService;
+    private volatile ConfigurationService configurationService;
     private volatile BridgeConfigurationManager bridgeConfigurationManager;
     private volatile TenantNetworkManager tenantNetworkManager;
     private volatile OvsdbConfigurationService ovsdbConfigurationService;
@@ -704,14 +704,14 @@ public class OF13Provider implements NetworkingProvider {
          * Action: Go to table 2
          * -------------------------------------------
          * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
+         * table=110,priority=8192,dl_vlan=2001 actions=output:2
          */
 
-        handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
-                segmentationId, ethPort, true);
+        handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, ethPort, true);
     }
 
     private void removeRemoteEgressVlanRules(Node node, Long dpid, String segmentationId,
-                                             String attachedMac, long ethPort) {
+                                             String attachedMac, long localPort, long ethPort) {
         /*
          * Table(1) Rule #1
          * ----------------
@@ -724,6 +724,19 @@ public class OF13Provider implements NetworkingProvider {
 
         //handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
         //        segmentationId, ethPort, attachedMac, false);
+
+        /*
+         * Table(1) Rule #2
+         * ----------------
+         * Match: Match VLAN ID and L2 ::::FF:FF Flooding
+         * Action: Flood to local and remote VLAN members
+         * -------------------------------------------
+         * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+         * actions=output:10 (eth port),goto_table:2
+         * table=110, priority=16384,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
+         */
+
+        handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, ethPort, false);
     }
 
     private void removePerVlanRules(Node node, Long dpid, String segmentationId, long localPort, long ethPort) {
@@ -735,8 +748,7 @@ public class OF13Provider implements NetworkingProvider {
          * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
          */
 
-        handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
-                false);
+        //handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
 
         /*
          * Table(0) Rule #2
@@ -745,8 +757,7 @@ public class OF13Provider implements NetworkingProvider {
          * Action: GOTO Local Table 2
          */
 
-        handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
-                segmentationId, ethPort, false);
+        handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, ethPort, false);
 
         /*
          * Table(1) Rule #2
@@ -759,7 +770,7 @@ public class OF13Provider implements NetworkingProvider {
          * table=110, priority=16384,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
          */
 
-        handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, ethPort, false);
+        //handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, ethPort, false);
 
         /*
          * Table(1) Rule #2
@@ -781,6 +792,7 @@ public class OF13Provider implements NetworkingProvider {
          * Action: Go to table 2
          * -------------------------------------------
          * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
+         * table=110,priority=8192,dl_vlan=2001 actions=output:2
          */
 
         handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, ethPort, false);
@@ -794,7 +806,7 @@ public class OF13Provider implements NetworkingProvider {
             Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
             Set<String> dpids = bridge.getDatapathIdColumn().getData();
             if (dpids == null || dpids.size() == 0) return 0L;
-            return HexEncode.stringToLong((String) dpids.toArray()[0]);
+            return StringConvertor.dpidStringToLong((String) dpids.toArray()[0]);
         } catch (Exception e) {
             logger.error("Error finding Bridge's OF DPID", e);
             return 0L;
@@ -822,7 +834,8 @@ public class OF13Provider implements NetworkingProvider {
             String bridgeName = configurationService.getExternalBridgeName();
             String brUuid = this.getInternalBridgeUUID(node, bridgeName);
             if (brUuid == null) {
-                logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
+                // Note: it is okay for certain nodes to not have br-ex configured; not an error
+                logger.info("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
                 return 0L;
             }
 
@@ -841,7 +854,7 @@ public class OF13Provider implements NetworkingProvider {
                 return;
             }
 
-            Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             if (of_ports == null || of_ports.size() <= 0) {
                 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
                 return;
@@ -896,7 +909,7 @@ public class OF13Provider implements NetworkingProvider {
                 return;
             }
 
-            Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             if (of_ports == null || of_ports.size() <= 0) {
                 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
                 return;
@@ -942,7 +955,7 @@ public class OF13Provider implements NetworkingProvider {
                 return;
             }
 
-            Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             if (of_ports == null || of_ports.size() <= 0) {
                 logger.debug("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
                 return;
@@ -982,7 +995,8 @@ public class OF13Provider implements NetworkingProvider {
                         if (!local) {
                             programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
                         }
-                        logger.trace("program local ingress tunnel rules: node" + node.getNodeIDString() + " intf " + intf.getName());
+                        logger.trace("program local ingress tunnel rules: node"
+                                + node.getId().getValue() + " intf " + intf.getName());
                         if (local) {
                             programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
                         }
@@ -1007,7 +1021,7 @@ public class OF13Provider implements NetworkingProvider {
                 return;
             }
 
-            Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             if (of_ports == null || of_ports.size() <= 0) {
                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
                 return;
@@ -1070,7 +1084,7 @@ public class OF13Provider implements NetworkingProvider {
                 return;
             }
 
-            Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             int timeout = 6;
             while ((of_ports == null) && (timeout > 0)) {
                 of_ports = intf.getOpenFlowPortColumn().getData();
@@ -1150,7 +1164,7 @@ public class OF13Provider implements NetworkingProvider {
                 return;
             }
 
-            Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             if (of_ports == null || of_ports.size() <= 0) {
                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
                 return;
@@ -1188,7 +1202,7 @@ public class OF13Provider implements NetworkingProvider {
                         }
                         logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
 
-                        removeRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
+                        removeRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, localPort, ethOFPort);
                         if (isLastInstanceOnNode) {
                             removePerVlanRules(node, dpid, network.getProviderSegmentationID(), localPort, ethOFPort);
                         }
@@ -1215,13 +1229,20 @@ public class OF13Provider implements NetworkingProvider {
             for (Node dstNode : nodes) {
                 InetAddress src = configurationService.getTunnelEndPoint(srcNode);
                 InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
-                Status status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst);
-                if (status.isSuccess()) {
-                    this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
-                }
-                addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src);
-                if (status.isSuccess()) {
-                    this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
+                if ((src != null) && (dst != null)) {
+                    Status status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst);
+                    if (status.isSuccess()) {
+                        this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
+                    }
+                    addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src);
+                    if (status.isSuccess()) {
+                        this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
+                    }
+                } else {
+                    logger.warn("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table. " +
+                            "Check source {} or destination {}",
+                            src != null ? src.getHostAddress() : "null",
+                            dst != null ? dst.getHostAddress() : "null");
                 }
             }
         }
@@ -1292,12 +1313,21 @@ public class OF13Provider implements NetworkingProvider {
                 for (Node dstNode : nodes) {
                     InetAddress src = configurationService.getTunnelEndPoint(srcNode);
                     InetAddress dst = configurationService.getTunnelEndPoint(dstNode);
-                    logger.info("Remove tunnel rules for interface " + intf.getName() + " on srcNode " + srcNode.getNodeIDString());
-                    this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
-                            dst, srcNode, intf, true, isLastInstanceOnNode);
-                    logger.info("Remove tunnel rules for interface " + intf.getName() + " on dstNode " + dstNode.getNodeIDString());
-                    this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
-                            src, dstNode, intf, false, isLastInstanceOnNode);
+                    if ((src != null) && (dst != null)) {
+                        logger.info("Remove tunnel rules for interface "
+                                + intf.getName() + " on srcNode " + srcNode.getId().getValue());
+                        this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
+                                dst, srcNode, intf, true, isLastInstanceOnNode);
+                        logger.info("Remove tunnel rules for interface "
+                                + intf.getName() + " on dstNode " + dstNode.getId().getValue());
+                        this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
+                                src, dstNode, intf, false, isLastInstanceOnNode);
+                    } else {
+                        logger.warn("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table. ",
+                                "Check source {} or destination {}",
+                                src != null ? src.getHostAddress() : "null",
+                                dst != null ? dst.getHostAddress() : "null");
+                    }
                 }
             }
         }
@@ -1357,7 +1387,7 @@ public class OF13Provider implements NetworkingProvider {
 
     private void writeNormalRule(Long dpidLong) {
 
-        String nodeName = OPENFLOW + dpidLong;
+        String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
 
         MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
@@ -1371,7 +1401,7 @@ public class OF13Provider implements NetworkingProvider {
         List<Instruction> instructions = Lists.newArrayList();
 
         // Call the InstructionBuilder Methods Containing Actions
-        InstructionUtils.createNormalInstructions(ib);
+        InstructionUtils.createNormalInstructions(nodeName, ib);
         ib.setOrder(0);
         ib.setKey(new InstructionKey(0));
         instructions.add(ib.build());
@@ -1537,6 +1567,7 @@ public class OF13Provider implements NetworkingProvider {
      * Match: Vlan ID
      * Action: Output port eth interface
      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
+     * table=110,priority=8192,dl_vlan=2001 actions=output:2
      */
 
     private void handleVlanMiss(Long dpidLong, Short writeTable,
@@ -1589,11 +1620,11 @@ public class OF13Provider implements NetworkingProvider {
      * Match: vlan ID and dMAC (::::FF:FF)
      * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
      * actions=strip_vlan, output:2,3,4,5
+     * table=110,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
      */
 
-    private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable,
-            String segmentationId, Long localPort, Long ethPort,
-            boolean write) {
+    private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable, String segmentationId,
+                                         Long localPort, Long ethPort, boolean write) {
         l2ForwardingProvider.programLocalVlanBcastOut(dpidLong, segmentationId, localPort, ethPort, write);
     }
 
@@ -1813,7 +1844,7 @@ public class OF13Provider implements NetworkingProvider {
             InstructionBuilder ib,
             Long dpidLong, Long port ,
             List<Instruction> instructions) {
-        NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
+        NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
         logger.debug("createOutputGroupInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
 
         List<Action> actionList = Lists.newArrayList();
@@ -1969,7 +2000,7 @@ public class OF13Provider implements NetworkingProvider {
     protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
             Long dpidLong, Long port , List<Instruction> instructions) {
 
-        NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
+        NodeConnectorId ncid = new NodeConnectorId(Constants.OPENFLOW_NODE_PREFIX + dpidLong + ":" + port);
         logger.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
 
         List<Action> actionList = Lists.newArrayList();
@@ -2087,8 +2118,9 @@ public class OF13Provider implements NetworkingProvider {
         for (Node ovsNode : ovsNodes) {
             Long brIntDpid = this.getIntegrationBridgeOFDPID(ovsNode);
             Long brExDpid = this.getExternalBridgeDpid(ovsNode);
-            logger.debug("Compare openflowNode to OVS node {} vs {} and {}", openflowNode.getID(), brIntDpid, brExDpid);
-            String openflowID = openflowNode.getID().toString();
+            logger.debug("Compare openflowNode to OVS node {} vs {} and {}",
+                    openflowNode.getId().getValue(), brIntDpid, brExDpid);
+            String openflowID = openflowNode.getId().getValue();
             if (openflowID.contains(brExDpid.toString())) {
                 this.initializeFlowRules(ovsNode, configurationService.getExternalBridgeName());
                 this.triggerInterfaceUpdates(ovsNode);
@@ -2100,6 +2132,11 @@ public class OF13Provider implements NetworkingProvider {
         }
     }
 
+    @Override
+    public void notifyFlowCapableNodeEvent(Long dpid, org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
+        mdsalConsumer.notifyFlowCapableNodeCreateEvent(Constants.OPENFLOW_NODE_PREFIX + dpid, action);
+    }
+
     public static NodeBuilder createNodeBuilder(String nodeId) {
         NodeBuilder builder = new NodeBuilder();
         builder.setId(new NodeId(nodeId));