Modify openflow table 64/32464/1
authorShixing Liu <liushixing@huawei.com>
Wed, 13 Jan 2016 03:48:02 +0000 (11:48 +0800)
committerShixing Liu <liushixing@huawei.com>
Wed, 13 Jan 2016 03:48:46 +0000 (11:48 +0800)
Change-Id: I3fcf07db490c3324758eed807b5519fa6ab50e25
Signed-off-by: Shixing Liu <liushixing@huawei.com>
nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/FlowUtils.java

index 03c3fe61dace6b20f564249804bb8756f45f91be..deae9b896b0a7b4ed42270788537e3a2c2f37a9f 100644 (file)
@@ -98,6 +98,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPathBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPort;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.VirtualLinks;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.arps.VirtualArp;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.arps.VirtualArpBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink;\r
@@ -139,6 +140,10 @@ public class FlowUtils implements AutoCloseable {
     private static final int ETH_TYPE_MPLS = 0x8847;\r
     private static final int ETH_TYPE_ARP = 0x0806;\r
 \r
+    private static final short IP_PROTO_ICMP = 1;\r
+    private static final short IP_PROTO_TCP = 6;\r
+    private static final short IP_PROTO_UDP = 17;\r
+\r
     private final DataBroker dataBroker;\r
     private final PacketProcessingService packetProcessingService;\r
 \r
@@ -651,7 +656,52 @@ public class FlowUtils implements AutoCloseable {
     /**\r
      * TODO\r
      *\r
-     * @author Shixing Liu\r
+     * @author Zhigang Ji\r
+     * @param userId TODO\r
+     * @param physicalNodeId TODO\r
+     * @param physicalPortId TODO\r
+     */\r
+    private void configExternalInPortFlowTableForArp(UserId userId,\r
+                                                     PhysicalNodeId physicalNodeId,\r
+                                                     PhysicalPortId physicalPortId) {\r
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();\r
+        List<Instruction> instructionList = new LinkedList<Instruction>();\r
+        List<Action> actionList = new LinkedList<Action>();\r
+\r
+        EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_ARP)).build());\r
+        EthernetMatch ethernetMatch = ethernetMatchBuilder.build();\r
+\r
+        Match match = new MatchBuilder().setInPort(createNodeConnectorId(physicalPortId)).setEthernetMatch(ethernetMatch).build();\r
+\r
+        OutputAction outputAction = new OutputActionBuilder().setMaxLength(0xffff).setOutputNodeConnector(new Uri(OutputPortValues.CONTROLLER.toString())).build();\r
+        OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build();\r
+        Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build();\r
+        actionList.add(actionOutput);\r
+\r
+        ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build();\r
+        ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build();\r
+        Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build();\r
+        instructionList.add(instructionApply);\r
+\r
+        Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build();\r
+\r
+        FlowId flowId = new FlowId(UUID.randomUUID().toString());\r
+        FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(IN_PORT_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY + 1);\r
+        Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build();\r
+\r
+        NodeId nodeId = createNodeId(physicalNodeId);\r
+        InstanceIdentifier<Flow> flowInsId = generateFlowInsId(userId, nodeId, IN_PORT_TABLE_ID, flowId);\r
+\r
+        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true);\r
+        writeTransaction.submit();\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * TODO\r
+     *\r
+     * @author Shixing Liu, Zhigang Ji\r
      * @param user TODO\r
      * @param virtualNetwork TODO\r
      * @param userIntentVnMapping TODO\r
@@ -663,6 +713,7 @@ public class FlowUtils implements AutoCloseable {
                                    UserIntentVnMapping userIntentVnMapping,\r
                                    UserVnPnMapping userVnPnMapping,\r
                                    PhysicalNetwork physicalNetwork) {\r
+        VirtualNetworkHelper virtualNetworkHelper = virtualNetworkHelpers.get(virtualNetwork.getNetworkId());\r
         List<VnPnMappingResult> vnPnMappingResults = userVnPnMapping.getVnPnMappingResult();\r
 \r
         for(VnPnMappingResult vnPnMappingResult:vnPnMappingResults){\r
@@ -671,6 +722,8 @@ public class FlowUtils implements AutoCloseable {
                 VirtualPortId virtualPortid = new VirtualPortId(vnPnMappingResult.getVirtualResourceEntityId().getValue());\r
                 VirtualNodeId virtualNodeId = new VirtualNodeId(vnPnMappingResult.getParentVirtualResourceEntityId().getValue());\r
 \r
+                VirtualPort virtualPort = null;\r
+\r
                 VirtualPort.PortType virtualPortType = VirtualPort.PortType.Internal;\r
                 VirtualNode.NodeType virtualNodeType = VirtualNode.NodeType.Vswitch;\r
 \r
@@ -678,9 +731,10 @@ public class FlowUtils implements AutoCloseable {
                 for (VirtualNode virtualNode : virtualNodes) {\r
                     if (virtualNode.getNodeId().equals(virtualNodeId)){\r
                         virtualNodeType = virtualNode.getNodeType();\r
-                        for (VirtualPort virtualPort : virtualNode.getVirtualPort()) {\r
-                            if (virtualPort.getPortId().equals(virtualPortid)){\r
-                                virtualPortType = virtualPort.getPortType();\r
+                        for (VirtualPort virtualPort1 : virtualNode.getVirtualPort()) {\r
+                            if (virtualPort1.getPortId().equals(virtualPortid)){\r
+                                virtualPort = virtualPort1;\r
+                                virtualPortType = virtualPort1.getPortType();\r
                                 break;\r
                             }\r
                         }\r
@@ -688,16 +742,28 @@ public class FlowUtils implements AutoCloseable {
                     }\r
                 }\r
 \r
+                // Added by Zhigang Ji to avoid NullPointerException.\r
+                if ( null == virtualPort ) {\r
+                    continue;\r
+                }\r
+\r
                 PhysicalNodeId physicalDestNodeId =\r
                         new PhysicalNodeId(vnPnMappingResult.getParentPhysicalResourceEntityId().getValue());\r
-\r
                 PhysicalPortId physicalDestPortId =\r
                         new PhysicalPortId(vnPnMappingResult.getPhysicalResourceEntityId().getValue());\r
 \r
                 if (virtualPortType == VirtualPort.PortType.External) {\r
                     configExternalInPortFlowTable(userVnPnMapping.getUserId(), physicalDestNodeId, physicalDestPortId, virtualNodeType);\r
+\r
+                    // Added by Zhigang Ji to configurate flow entries to\r
+                    // capture and send arp packets to controller.\r
+                    if ( virtualNetworkHelper.isLayer2ExternalVirtualPort(virtualPort) ) {\r
+                        configExternalInPortFlowTableForArp(user.getUserId(), physicalDestNodeId, physicalDestPortId);\r
+                    }\r
                 } else {\r
-                    configInternalInPortFlowTable(userVnPnMapping.getUserId(), physicalDestNodeId, physicalDestPortId);\r
+                    // Deleted by Zhigang Ji, because of repetitive\r
+                    // configurating for internal physical ports.\r
+//                    configInternalInPortFlowTable(userVnPnMapping.getUserId(), physicalDestNodeId, physicalDestPortId);\r
                 }\r
             }\r
         }\r
@@ -714,12 +780,14 @@ public class FlowUtils implements AutoCloseable {
                 }\r
             }\r
         }\r
+\r
+        return;\r
        }\r
 \r
     /**\r
      * TODO\r
      *\r
-     * @author Shixing Liu\r
+     * @author Shixing Liu, Zhigang Ji\r
      * @param user TODO\r
      * @param virtualNetwork TODO\r
      * @param userIntentVnMapping TODO\r
@@ -731,122 +799,214 @@ public class FlowUtils implements AutoCloseable {
                                   UserIntentVnMapping userIntentVnMapping,\r
                                   UserVnPnMapping userVnPnMapping,\r
                                   PhysicalNetwork physicalNetwork) {\r
-\r
         LOG.debug("nemo:meter updateMeterTable()");\r
+\r
+        // Added by Zhigang Ji for only handling physical paths\r
+        // corresponding to virtual links in this user's virtual network.\r
+        VirtualLinks virtualLinks = virtualNetwork.getVirtualLinks();\r
+        if ( null == virtualLinks ) {\r
+            LOG.debug("VirtualLinks is null");\r
+            return;\r
+        }\r
+        if ( null == virtualLinks.getVirtualLink() ) {\r
+            LOG.debug("VirtualLink list is null");\r
+            return;\r
+        }\r
+        List<VirtualLink> virtualLinkList = virtualLinks.getVirtualLink();\r
+        if ( virtualLinkList.isEmpty() ) {\r
+            LOG.debug("VirtualLink list is empty.");\r
+            return;\r
+        }\r
+\r
         PhysicalPaths physicalPaths = physicalNetwork.getPhysicalPaths();\r
+        // Added by Zhigang Ji to avoid NullPointerException.\r
+        if ( null == physicalPaths ) {\r
+            LOG.debug("PhysicalPaths is null");\r
+            return;\r
+        }\r
         if(null == physicalPaths.getPhysicalPath()){\r
-            LOG.debug("PhysicalPath are null");\r
+            LOG.debug("PhysicalPath list is null.");\r
             return;\r
         }\r
-\r
         List<PhysicalPath> physicalPathList = physicalPaths.getPhysicalPath();\r
+        // Added by Zhigang Ji to avoid handling empty list.\r
+        if ( physicalPathList.isEmpty() ) {\r
+            LOG.debug("PhysicalPath list is empty.");\r
+            return;\r
+        }\r
 \r
         PhysicalLinks physicalLinks = physicalNetwork.getPhysicalLinks();\r
+        // Added by Zhigang Ji to avoid NullPointerException.\r
+        if ( null == physicalLinks ) {\r
+            LOG.debug("PhysicalLinks is null");\r
+            return;\r
+        }\r
+        if ( null == physicalLinks.getPhysicalLink() ) {\r
+            LOG.debug("PhysicalLink list is null.");\r
+            return;\r
+        }\r
         List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink>\r
                 physicalLinksList = physicalLinks.getPhysicalLink();\r
+        // Added by Zhigang Ji to avoid handling empty list.\r
+        if ( physicalLinksList.isEmpty() ) {\r
+            LOG.debug("PhysicalLink list is empty.");\r
+            return;\r
+        }\r
 \r
-        for(PhysicalPath physicalPath:physicalPathList) {\r
-            if(physicalPath.getBandwidth() > 0 ) {\r
-                LOG.debug("nemo: meter physicalPath.getBandwidth() = {}", physicalPath.getBandwidth());\r
-                if(meterIdsOfPhysicalPaths.containsKey(physicalPath.getPathId())== false){\r
-                    LOG.debug("nemo:meter meterIdsOfPhysicalPaths.containsKey(physicalPath.getPathId())== false");\r
-                    org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink\r
-                            physicalLinkInPath = physicalPath.getPhysicalLink().get(0);\r
+        // Added by Zhigang Ji for getting physical path that virtual link is mapped to.\r
+        List<VnPnMappingResult> vnPnMappingResults = userVnPnMapping.getVnPnMappingResult();\r
+        if ( null == vnPnMappingResults ) {\r
+            LOG.debug("VnPnMappingResult list is null.");\r
+            return;\r
+        }\r
+        if ( vnPnMappingResults.isEmpty() ) {\r
+            LOG.debug("VnPnMappingResult list is empty.");\r
+            return;\r
+        }\r
 \r
-                    LOG.debug("nemo:meter physicalLinkInPath" + physicalLinkInPath.getLinkId().getValue());\r
-                    for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink physicalLink : physicalLinksList) {\r
-                        LOG.debug("nemo:meter physicalLink " + physicalLink.getLinkId().getValue());\r
-                        if (physicalLinkInPath.getLinkId().getValue().equals(physicalLink.getLinkId().getValue())) {\r
+        // Added by Zhigang Ji to optimize data store writing.\r
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();\r
 \r
-                            LOG.debug("nemo:meter find plink for ppath.");\r
-                            PhysicalNodeId physicalSrcNodeId = physicalLink.getSrcNodeId();\r
-                            PhysicalPortId physicalSrcPortId = physicalLink.getSrcPortId();\r
+        VnPnMappingResult vnPnMappingResult;\r
+        PhysicalPathId physicalPathId;\r
+        PhysicalPath physicalPath;\r
 \r
-                            LOG.debug("nemo:meter meterIdGenerators.size() = " + meterIdGenerators.size());\r
-                            LOG.debug("nemo:meter physicalSrcNodeId =" + physicalSrcNodeId.getValue());\r
-\r
-                            LOG.debug("nemo:meter Assign meter id");\r
-                            Long meterId = (long)0;\r
-                            if(meterIdGenerators.containsKey(physicalSrcNodeId) == false){\r
-                                LOG.debug("meterIdGenerators.containsKey(physicalSrcNodeId) == false");\r
-                                MeterIdGenerator meterIdGenerator = new MeterIdGenerator();\r
-                                meterIdGenerators.put(physicalSrcNodeId, meterIdGenerator);\r
-                                meterId = meterIdGenerators.get(physicalSrcNodeId).generateMeterId();\r
-                                meterIdsOfPhysicalPaths.put(physicalPath.getPathId(),meterId);\r
-                            }\r
-                            else{\r
-                                LOG.debug("meterIdGenerators.containsKey(physicalSrcNodeId) == true");\r
-                                meterId = meterIdGenerators.get(physicalSrcNodeId).generateMeterId();\r
-                                meterIdsOfPhysicalPaths.put(physicalPath.getPathId(),meterId);\r
-                            }\r
+        // Modified by Zhigang Ji to only handle physical paths that\r
+        // virtual links in this user's virtual network are mapped to.\r
+        for ( VirtualLink virtualLink : virtualLinkList ) {\r
+            if ( 0 >= virtualLink.getBandwidth() ) {\r
+                continue;\r
+            }\r
+\r
+            vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults,\r
+                    new VirtualResourceEntityId(virtualLink.getLinkId().getValue()));\r
+            if ( null == vnPnMappingResult ) {\r
+                LOG.error("Can't get vn-pn mapping result for virtual link {}.",\r
+                        virtualLink.getLinkId().getValue());\r
+                continue;\r
+            }\r
 \r
-                            //Generate meter flow entries\r
-                            LOG.debug("nemo:meter Generate meter flow entries");\r
-                            NodeKey nodeKey = new NodeKey(new NodeId(physicalSrcNodeId.getValue()));\r
-                            MeterKey meterKey = new MeterKey(new MeterId(meterId));\r
-\r
-                            InstanceIdentifier<Meter> meterInsId = generateMeterInsId(userVnPnMapping.getUserId(), nodeKey, meterKey);\r
-\r
-                            /*\r
-                            MeterBandHeaderBuilder meterBandHeaderBuilder = new MeterBandHeaderBuilder();\r
-                            MeterBandTypesBuilder meterBandTypesB = new MeterBandTypesBuilder();\r
-                            MeterBandType bandFlag = new MeterBandType(true, false, false);\r
-                            meterBandTypesB.setFlags(bandFlag);// _ofpmbtDrop\r
-                            DropBuilder drop = new DropBuilder();\r
-                            drop.setDropBurstSize(physicalPath.getBandwidth() / 2);\r
-                            drop.setDropRate(physicalPath.getBandwidth());\r
-                            Drop drp = drop.build();\r
-                            meterBandHeaderBuilder.setBandType(drp);\r
-                            meterBandHeaderBuilder.setMeterBandTypes(meterBandTypesB.build());\r
-                            MeterBandHeader meterBH = meterBandHeaderBuilder.build();\r
-                            MeterBuilder meterBuilder = new MeterBuilder();\r
-                            meterBuilder.setMeterBandHeaders(meterBandHeadersBuilder.setMeterBandHeader(meterBandHeaders).build());\r
-                            */\r
-\r
-                            MeterBuilder meterBuilder = new MeterBuilder();\r
-                            MeterBandHeaderBuilder meterBandHeaderBuilder = new MeterBandHeaderBuilder();\r
-                            MeterBandHeadersBuilder meterBandHeadersBuilder = new MeterBandHeadersBuilder();\r
-                            MeterBandTypesBuilder meterBandTypesB = new MeterBandTypesBuilder();\r
-\r
-                            meterBandHeaderBuilder.setKey(new MeterBandHeaderKey(new BandId(physicalPath.getBandwidth())));\r
-                            meterBandHeaderBuilder.setBandBurstSize((long)0);\r
-                            meterBandHeaderBuilder.setBandRate(physicalPath.getBandwidth());\r
-\r
-                            MeterBandType bandFlag = new MeterBandType(true, false, false);\r
-                            meterBandTypesB.setFlags(bandFlag);// _ofpmbtDrop\r
-                            DropBuilder drop = new DropBuilder();\r
-                            drop.setDropBurstSize((long)0);\r
-                            drop.setDropRate(physicalPath.getBandwidth());\r
-                            Drop drp = drop.build();\r
-                            meterBandHeaderBuilder.setBandType(drp);\r
-                            meterBandHeaderBuilder.setMeterBandTypes(meterBandTypesB.build());\r
-\r
-                            MeterBandHeader meterBH = meterBandHeaderBuilder.build();\r
-                            List<MeterBandHeader> meterBandHeaders = new ArrayList<MeterBandHeader>();\r
-                            meterBandHeaders.add(0, meterBH);\r
-\r
-                            meterBuilder.setKey(new MeterKey(new MeterId(meterId)));\r
-                            meterBuilder.setBarrier(false);\r
-\r
-                            meterBuilder.setFlags(new MeterFlags(false, true, false, true));\r
-\r
-                            meterBuilder.setContainerName("container." + physicalPath.getPathId());\r
-                            meterBuilder.setMeterName("meter." + physicalPath.getPathId());\r
-                            meterBandHeadersBuilder.setMeterBandHeader(meterBandHeaders);\r
-                            meterBuilder.setMeterBandHeaders(meterBandHeadersBuilder.build());\r
-\r
-                            Meter meter = meterBuilder.build();\r
-\r
-                            WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();\r
-                            writeTransaction.put(LogicalDatastoreType.CONFIGURATION, meterInsId, meter);\r
-                            writeTransaction.submit();\r
-                            LOG.debug("nemo:meter writeTransaction.submit();");\r
-                            break;\r
+            physicalPathId = new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue());\r
+            physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId);\r
+            if ( null == physicalPath ) {\r
+                LOG.error("Can't get physical path {} that virtual link {} is mapped to.",\r
+                        physicalPathId.getValue(), virtualLink.getLinkId().getValue());\r
+                continue;\r
+            }\r
+            if ( physicalPath.getPhysicalLink().isEmpty() ) {\r
+                LOG.warn("Physical path {} corresponding to virtual link {} " +\r
+                        "whose bandwidth is greater than zero is an null path.",\r
+                        physicalPathId.getValue(), virtualLink.getLinkId().getValue());\r
+                continue;\r
+            }\r
+\r
+            LOG.debug("nemo: meter virtualLink.getBandwidth() = {}", virtualLink.getBandwidth());\r
+            LOG.debug("nemo: meter physicalPath.getBandwidth() = {}", physicalPath.getBandwidth());\r
+            // Modified by Zhigang Ji to optimize boolean expression.\r
+            if ( !meterIdsOfPhysicalPaths.containsKey(physicalPath.getPathId()) ) {\r
+                LOG.debug("nemo:meter meterIdsOfPhysicalPaths.containsKey(physicalPath.getPathId())== false");\r
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink\r
+                        physicalLinkInPath = physicalPath.getPhysicalLink().get(0);\r
+\r
+                LOG.debug("nemo:meter physicalLinkInPath " + physicalLinkInPath.getLinkId().getValue());\r
+                for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink physicalLink : physicalLinksList) {\r
+                    LOG.debug("nemo:meter physicalLink " + physicalLink.getLinkId().getValue());\r
+                    if (physicalLinkInPath.getLinkId().getValue().equals(physicalLink.getLinkId().getValue())) {\r
+                        LOG.debug("nemo:meter find plink for ppath.");\r
+                        PhysicalNodeId physicalSrcNodeId = physicalLink.getSrcNodeId();\r
+\r
+                        LOG.debug("nemo:meter meterIdGenerators.size() = " + meterIdGenerators.size());\r
+                        LOG.debug("nemo:meter physicalSrcNodeId = " + physicalSrcNodeId.getValue());\r
+\r
+                        LOG.debug("nemo:meter Assign meter id");\r
+                        Long meterId = (long)0;\r
+                        // Modified by Zhigang Ji to optimize boolean expression.\r
+                        if(!meterIdGenerators.containsKey(physicalSrcNodeId)){\r
+                            LOG.debug("nemo:meterIdGenerators.containsKey(physicalSrcNodeId) == false");\r
+                            MeterIdGenerator meterIdGenerator = new MeterIdGenerator();\r
+                            meterIdGenerators.put(physicalSrcNodeId, meterIdGenerator);\r
+                            // Modified by Zhigang Ji to optimize meter id generation.\r
+                            meterId = meterIdGenerator.generateMeterId();\r
+                            meterIdsOfPhysicalPaths.put(physicalPath.getPathId(),meterId);\r
                         }\r
+                        else{\r
+                            LOG.debug("nemo:meterIdGenerators.containsKey(physicalSrcNodeId) == true");\r
+                            meterId = meterIdGenerators.get(physicalSrcNodeId).generateMeterId();\r
+                            meterIdsOfPhysicalPaths.put(physicalPath.getPathId(),meterId);\r
+                        }\r
+\r
+                        // Generate meter flow entries.\r
+                        LOG.debug("nemo:meter Generate meter flow entries");\r
+                        NodeKey nodeKey = new NodeKey(new NodeId(physicalSrcNodeId.getValue()));\r
+                        MeterKey meterKey = new MeterKey(new MeterId(meterId));\r
+\r
+                        InstanceIdentifier<Meter> meterInsId = generateMeterInsId(userVnPnMapping.getUserId(), nodeKey, meterKey);\r
+\r
+                        /*\r
+                        MeterBandHeaderBuilder meterBandHeaderBuilder = new MeterBandHeaderBuilder();\r
+                        MeterBandTypesBuilder meterBandTypesB = new MeterBandTypesBuilder();\r
+                        MeterBandType bandFlag = new MeterBandType(true, false, false);\r
+                        meterBandTypesB.setFlags(bandFlag);// _ofpmbtDrop\r
+                        DropBuilder drop = new DropBuilder();\r
+                        drop.setDropBurstSize(physicalPath.getBandwidth() / 2);\r
+                        drop.setDropRate(physicalPath.getBandwidth());\r
+                        Drop drp = drop.build();\r
+                        meterBandHeaderBuilder.setBandType(drp);\r
+                        meterBandHeaderBuilder.setMeterBandTypes(meterBandTypesB.build());\r
+                        MeterBandHeader meterBH = meterBandHeaderBuilder.build();\r
+                        MeterBuilder meterBuilder = new MeterBuilder();\r
+                        meterBuilder.setMeterBandHeaders(meterBandHeadersBuilder.setMeterBandHeader(meterBandHeaders).build());\r
+                        */\r
+\r
+                        MeterBuilder meterBuilder = new MeterBuilder();\r
+                        MeterBandHeaderBuilder meterBandHeaderBuilder = new MeterBandHeaderBuilder();\r
+                        MeterBandHeadersBuilder meterBandHeadersBuilder = new MeterBandHeadersBuilder();\r
+                        MeterBandTypesBuilder meterBandTypesB = new MeterBandTypesBuilder();\r
+\r
+                        meterBandHeaderBuilder.setKey(new MeterBandHeaderKey(new BandId(physicalPath.getBandwidth())));\r
+                        meterBandHeaderBuilder.setBandBurstSize((long)0);\r
+                        meterBandHeaderBuilder.setBandRate(physicalPath.getBandwidth());\r
+\r
+                        MeterBandType bandFlag = new MeterBandType(true, false, false);\r
+                        meterBandTypesB.setFlags(bandFlag);// _ofpmbtDrop\r
+                        DropBuilder drop = new DropBuilder();\r
+                        drop.setDropBurstSize((long)0);\r
+                        drop.setDropRate(physicalPath.getBandwidth());\r
+                        Drop drp = drop.build();\r
+                        meterBandHeaderBuilder.setBandType(drp);\r
+                        meterBandHeaderBuilder.setMeterBandTypes(meterBandTypesB.build());\r
+\r
+                        MeterBandHeader meterBH = meterBandHeaderBuilder.build();\r
+                        List<MeterBandHeader> meterBandHeaders = new ArrayList<MeterBandHeader>();\r
+                        meterBandHeaders.add(0, meterBH);\r
+\r
+                        meterBuilder.setKey(new MeterKey(new MeterId(meterId)));\r
+                        meterBuilder.setBarrier(false);\r
+\r
+                        meterBuilder.setFlags(new MeterFlags(false, true, false, true));\r
+\r
+                        meterBuilder.setContainerName("container." + physicalPath.getPathId());\r
+                        meterBuilder.setMeterName("meter." + physicalPath.getPathId());\r
+                        meterBandHeadersBuilder.setMeterBandHeader(meterBandHeaders);\r
+                        meterBuilder.setMeterBandHeaders(meterBandHeadersBuilder.build());\r
+\r
+                        Meter meter = meterBuilder.build();\r
+\r
+                        // Delete newWriteOnlyTransaction and submit below\r
+                        // to optimize data store writing - Zhigang Ji.\r
+                        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, meterInsId, meter);\r
+                        LOG.debug("nemo:meter writeTransaction.put(...);");\r
+                        // Deleted by Zhigang Ji.\r
+//                        break;\r
                     }\r
                 }\r
             }\r
         }\r
+\r
+        // Added by Zhigang Ji to optimize data store writing.\r
+        writeTransaction.submit();\r
+\r
+        return;\r
     }\r
 \r
     /**\r
@@ -3033,20 +3193,42 @@ public class FlowUtils implements AutoCloseable {
                               org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow nemoFlow,\r
                               PhysicalPort physicalPort) {\r
         List<MatchItem> matchItems = nemoFlow.getMatchItem();\r
+        MatchItem ethTypeMatchItem = getMatchItem(matchItems, new MatchItemName("eth-type"));\r
         MatchItem srcIpMatchItem = getMatchItem(matchItems, new MatchItemName("src-ip"));\r
         MatchItem dstIpMatchItem = getMatchItem(matchItems, new MatchItemName("dst-ip"));\r
+        MatchItem protoMatchItem = getMatchItem(matchItems, new MatchItemName("proto"));\r
+        MatchItem srcPortMatchItem = getMatchItem(matchItems, new MatchItemName("src-port"));\r
+        MatchItem dstPortMatchItem = getMatchItem(matchItems, new MatchItemName("dst-port"));\r
 \r
         EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder();\r
         Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder();\r
+        IpMatchBuilder ipMatchBuilder = new IpMatchBuilder();\r
+        TcpMatchBuilder tcpMatchBuilder = new TcpMatchBuilder();\r
+        UdpMatchBuilder udpMatchBuilder = new UdpMatchBuilder();\r
         MetadataBuilder metadataBuilder = null;\r
         boolean containEthernetMatch = false;\r
         boolean containIpv4Match = false;\r
+        boolean containIpMatch = false;\r
+        boolean containTcpMatch = false;\r
+        boolean containUdpMatch = false;\r
 \r
         if ( null != userId ) {\r
             metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId)));\r
         }\r
 \r
-        if ( null != srcIpMatchItem || null != dstIpMatchItem ) {\r
+        if ( null != ethTypeMatchItem ) {\r
+            String ethTypeMatchItemValue = ethTypeMatchItem.getMatchItemValue().getStringValue();\r
+\r
+            if ( ethTypeMatchItemValue.equals("ip") ) {\r
+                ethernetMatchBuilder = ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_IP)).build());\r
+                containEthernetMatch = true;\r
+            }\r
+\r
+            if ( ethTypeMatchItemValue.equals("arp") ) {\r
+                ethernetMatchBuilder = ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_ARP)).build());\r
+                containEthernetMatch = true;\r
+            }\r
+        } else if ( null != srcIpMatchItem || null != dstIpMatchItem ) {\r
             ethernetMatchBuilder = ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_IP)).build());\r
             containEthernetMatch = true;\r
         }\r
@@ -3063,6 +3245,55 @@ public class FlowUtils implements AutoCloseable {
             containIpv4Match = true;\r
         }\r
 \r
+        if ( null != protoMatchItem ) {\r
+            String protoMatchItemValue = protoMatchItem.getMatchItemValue().getStringValue();\r
+\r
+            if ( protoMatchItemValue.equals("icmp") ) {\r
+                ipMatchBuilder = ipMatchBuilder.setIpProtocol(IP_PROTO_ICMP);\r
+                containIpMatch = true;\r
+            }\r
+\r
+            if ( protoMatchItemValue.equals("tcp") ) {\r
+                ipMatchBuilder = ipMatchBuilder.setIpProtocol(IP_PROTO_TCP);\r
+                containIpMatch = true;\r
+\r
+                if ( null != srcPortMatchItem ) {\r
+                    Long srcPortMatchItemValue = srcPortMatchItem.getMatchItemValue().getIntValue();\r
+                    tcpMatchBuilder = tcpMatchBuilder.setTcpSourcePort(new PortNumber(srcPortMatchItemValue.intValue()));\r
+                    containTcpMatch = true;\r
+                }\r
+\r
+                if ( null != dstPortMatchItem ) {\r
+                    Long dstPortMatchItemValue = dstPortMatchItem.getMatchItemValue().getIntValue();\r
+                    tcpMatchBuilder = tcpMatchBuilder.setTcpDestinationPort(new PortNumber(dstPortMatchItemValue.intValue()));\r
+                    containTcpMatch = true;\r
+                }\r
+            }\r
+\r
+            if ( protoMatchItemValue.equals("udp") ) {\r
+                ipMatchBuilder = ipMatchBuilder.setIpProtocol(IP_PROTO_UDP);\r
+                containIpMatch = true;\r
+\r
+                if ( null != srcPortMatchItem ) {\r
+                    Long srcPortMatchItemValue = srcPortMatchItem.getMatchItemValue().getIntValue();\r
+                    udpMatchBuilder = udpMatchBuilder.setUdpSourcePort(new PortNumber(srcPortMatchItemValue.intValue()));\r
+                    containUdpMatch = true;\r
+                }\r
+\r
+                if ( null != dstPortMatchItem ) {\r
+                    Long dstPortMatchItemValue = dstPortMatchItem.getMatchItemValue().getIntValue();\r
+                    udpMatchBuilder = udpMatchBuilder.setUdpDestinationPort(new PortNumber(dstPortMatchItemValue.intValue()));\r
+                    containUdpMatch = true;\r
+                }\r
+            }\r
+        } else {\r
+            if ( null != srcPortMatchItem || null != dstPortMatchItem ) {\r
+                LOG.error("If the match item src-port or dst-port is specified, " +\r
+                        "the match item proto must be specified to be tcp or udp " +\r
+                        "in NEMO flow {}.", nemoFlow.getFlowId().getValue());\r
+            }\r
+        }\r
+\r
         MatchBuilder matchBuilder = new MatchBuilder();\r
 \r
         if ( null != physicalPort ) {\r
@@ -3081,6 +3312,18 @@ public class FlowUtils implements AutoCloseable {
             matchBuilder = matchBuilder.setLayer3Match(ipv4MatchBuilder.build());\r
         }\r
 \r
+        if ( containIpMatch ) {\r
+            matchBuilder = matchBuilder.setIpMatch(ipMatchBuilder.build());\r
+        }\r
+\r
+        if ( containTcpMatch ) {\r
+            matchBuilder = matchBuilder.setLayer4Match(tcpMatchBuilder.build());\r
+        }\r
+\r
+        if ( containUdpMatch ) {\r
+            matchBuilder = matchBuilder.setLayer4Match(udpMatchBuilder.build());\r
+        }\r
+\r
         return matchBuilder.build();\r
     }\r
 \r