More changes for SFC
authorSam Hague <shague@redhat.com>
Thu, 5 Nov 2015 15:10:01 +0000 (10:10 -0500)
committerSam Hague <shague@redhat.com>
Thu, 5 Nov 2015 15:10:31 +0000 (10:10 -0500)
Change-Id: I1e6b52b9726d6fe85ccde01a57bdb927821690ca
Signed-off-by: Sam Hague <shague@redhat.com>
openstack/net-virt-sfc/api/src/main/yang/netvirt-classifier.yang
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcClassifierListener.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/INetvirtSfcOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/NetvirtSfcOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/SfcClassifier.java
openstack/net-virt-sfc/it/pom.xml
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/AclUtils.java

index df4dd39e8d6351807116f2baf8a56bd54702960b..5e01309128afde1990aa54d2e891ba0da8875c7a 100644 (file)
@@ -38,6 +38,12 @@ module netvirt-sfc-classifier {
                     leaf name {
                         type string;
                     }
+                    leaf direction {
+                        type enumeration {
+                            enum ingress;
+                            enum egress;
+                        }
+                    }
                 }
             }
         }
index 078b64b5e49447b623a498404ebf731fcca9cc89..34fc5a380045d05de11141e7d76df976d94f3d51 100644 (file)
@@ -116,11 +116,11 @@ public class NetvirtSfcClassifierListener extends AbstractDataTreeListener<Class
             return;
         }
 
-        if (addDataObj.getBridges() != null) {
-            for (Bridge bridge : addDataObj.getBridges().getBridge()) {
-                provider.addClassifierRules(bridge, acl);
-            }
-        }
+        //if (addDataObj.getBridges() != null) {
+        //    for (Bridge bridge : addDataObj.getBridges().getBridge()) {
+                provider.addClassifierRules(addDataObj.getBridges(), acl);
+        //    }
+        //}
     }
 
     public InstanceIdentifier<Classifier> getClassifierIid() {
index 7cb081733ed6468d1fe6df163131d06c795d446b..a85dde8d3f52167fcb2cc482a12ead26f4deb346 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13;
 
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
 
@@ -26,6 +27,7 @@ public interface INetvirtSfcOF13Provider {
      * @param acl - Access list includes rules that need to be installed in a SFF.
      */
     void addClassifierRules(Bridge bridge, Acl acl);
+    void addClassifierRules(Bridges bridges, Acl acl);
 
     /**
      * Method removes the OF rules corresponding to rules within ACL
index d5e89e5b700d4e30c75bd9d701c8daf8bf85eef0..5b2d94e2cb0abcfae78cb566f1fc20f55ca1a139 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13;
 
 import com.google.common.base.Preconditions;
 
+import com.google.common.collect.Iterables;
 import java.util.List;
 import java.util.StringTokenizer;
 
@@ -40,6 +41,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -52,20 +54,14 @@ import org.slf4j.LoggerFactory;
  * Open vSwitch OpenFlow 1.3 Networking Provider for Netvirt SFC
  * @author Arun Yerra
  */
-public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
+public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider {
     private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcOF13Provider.class);
     private static final short TABLE_0_CLASSIFIER = 0;
-    //private static final short TABLE_1_L2FORWARD = 30;
-    //private static final short TABLE_2_L3FORWARD = 40;
     private static final short TABLE_3_INGR_ACL = 50;
 
-    public static final long REG_VALUE_FROM_LOCAL = 0x1L;
-    public static final long REG_VALUE_FROM_REMOTE = 0x2L;
-    public static final Class<? extends NxmNxReg> REG_FIELD = NxmNxReg0.class;
     private volatile NodeCacheManager nodeCacheManager;
     private volatile Southbound southbound;
     private MdsalUtils mdsalUtils;
-    private DataBroker dataBroker;
     private SfcClassifier sfcClassifier;
 
     // TBD:: Remove these constants after integrating with openstack.
@@ -83,7 +79,6 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
      */
     public NetvirtSfcOF13Provider(final DataBroker dataBroker) {
         Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
-        this.dataBroker = dataBroker;
         mdsalUtils = new MdsalUtils(dataBroker);
         this.setDependencies(null);
         sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
@@ -95,22 +90,27 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
 
     @Override
     public void addClassifierRules(Bridge bridge, Acl acl) {
-        Preconditions.checkNotNull(bridge, "Input bridge cannot be NULL!");
+
+    }
+
+    @Override
+    public void addClassifierRules(Bridges bridges, Acl acl) {
+        Preconditions.checkNotNull(bridges, "Input bridge cannot be NULL!");
         Preconditions.checkNotNull(acl, "Input accesslist cannot be NULL!");
 
-        Node bridgeNode = getBridgeNode(bridge.getName());
-        if (bridgeNode == null) {
-            LOG.debug("bridge {} not yet configured. Skip processing !!", bridge.getName());
-            return;
-        }
+        //Node bridgeNode = getBridgeNode(bridge.getName());
+        //if (bridgeNode == null) {
+        //    LOG.debug("bridge {} not yet configured. Skip processing !!", bridge.getName());
+        //    return;
+        //}
 
         // TODO: Find all nodes needing the classifier and add classifier to them
         for (Ace ace : acl.getAccessListEntries().getAce()) {
-            processAclEntry(ace, bridgeNode, true);
+            processAclEntry(ace, bridges, true);
         }
     }
 
-    private void processAclEntry(Ace entry, Node srcNode, boolean write) {
+    private void processAclEntry(Ace entry, Bridges bridges, boolean write) {
         Matches matches = entry.getMatches();
         if (matches == null) {
             LOG.warn("processAclEntry: matches not found");
@@ -118,8 +118,7 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
         }
 
         RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
-        LOG.debug("Processing ACL entry = {} on Node = {} sfcRedirect = {}", entry.getRuleName(),
-                srcNode.getNodeId(), sfcRedirect);
+        LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
         if (sfcRedirect == null) {
             LOG.warn("processAClEntry: sfcRedirect is null");
             return;
@@ -168,52 +167,111 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
         }
 
         LOG.info("processAclEntry: RSP: {}", rsp);
-
-        // Find the first Hop within an RSP.
-        // The classifier flow needs to send all matched traffic to this first hop SFF.
         List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
         if (pathHopList.isEmpty()) {
             LOG.warn("Service Path = {} has empty hops!!", sfpName);
             return;
         }
 
-        RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
-                .readRenderedServicePathFirstHop(new RspName(rspName));
+        for (Bridge bridge : bridges.getBridge()) {
+            if (bridge.getDirection().getIntValue() == 0) {
+                Node bridgeNode = getBridgeNode(bridge.getName());
+                if (bridgeNode == null) {
+                    LOG.debug("processAclEntry: bridge {} not yet configured. Skip processing !!", bridge.getName());
+                    continue;
+                }
 
-        LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
-                firstRspHop.getPort().getValue().intValue());
-        long tunnelOfPort = southbound.getOFPort(srcNode, CLIENT_GPE_PORT_NAME);
-        if (tunnelOfPort == 0L) {
-            LOG.error("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
-                    CLIENT_GPE_PORT_NAME, tunnelOfPort, srcNode);
-            return;
-        }
+                long tunnelOfPort = southbound.getOFPort(bridgeNode, CLIENT_GPE_PORT_NAME);
+                if (tunnelOfPort == 0L) {
+                    LOG.error("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
+                            CLIENT_GPE_PORT_NAME, tunnelOfPort, bridgeNode);
+                    return;
+                }
 
-        long localOfPort = southbound.getOFPort(srcNode, CLIENT_PORT_NAME);
-        if (localOfPort == 0L) {
-            LOG.error("programAclEntry: Could not identify local port {} -> OF ({}) on {}",
-                    CLIENT_GPE_PORT_NAME, localOfPort, srcNode);
-            return;
-        }
+                long localOfPort = southbound.getOFPort(bridgeNode, CLIENT_PORT_NAME);
+                if (localOfPort == 0L) {
+                    LOG.error("programAclEntry: Could not identify local port {} -> OF ({}) on {}",
+                            CLIENT_GPE_PORT_NAME, localOfPort, bridgeNode);
+                    return;
+                }
 
-        NshUtils nshHeader = new NshUtils();
-        // C1 is the normal overlay dest ip and c2 is the vnid
-        // Hardcoded for now, netvirt integration will have those values
-        nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
-        nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID));
-        nshHeader.setNshNsp(rsp.getPathId());
+                // Find the first Hop within an RSP.
+                // The classifier flow needs to send all matched traffic to this first hop SFF.
+                RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+                        .readRenderedServicePathFirstHop(new RspName(rspName));
+
+                LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
+                        firstRspHop.getPort().getValue().intValue());
+
+                NshUtils nshHeader = new NshUtils();
+                // C1 is the normal overlay dest ip and c2 is the vnid
+                // Hardcoded for now, netvirt integration will have those values
+                nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
+                nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID));
+                nshHeader.setNshNsp(rsp.getPathId());
+
+                RenderedServicePathHop firstHop = pathHopList.get(0);
+                nshHeader.setNshNsi(firstHop.getServiceIndex());
+                nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
+                nshHeader.setNshTunUdpPort(firstRspHop.getPort());
+                LOG.debug("The Nsh Header = {}", nshHeader);
+
+                handleLocalInPort(southbound.getDataPathId(bridgeNode), rsp.getPathId().toString(), localOfPort,
+                        TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL, matches, true);
+
+                handleSfcClassiferFlows(southbound.getDataPathId(bridgeNode), TABLE_3_INGR_ACL, entry.getRuleName(),
+                        matches, nshHeader, tunnelOfPort, true);
+            } else {
+                Node bridgeNode = getBridgeNode(bridge.getName());
+                if (bridgeNode == null) {
+                    LOG.debug("processAclEntry: bridge {} not yet configured. Skip processing !!", bridge.getName());
+                    continue;
+                }
+
+                long tunnelOfPort = southbound.getOFPort(bridgeNode, SERVER_GPE_PORT_NAME);
+                if (tunnelOfPort == 0L) {
+                    LOG.error("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
+                            CLIENT_GPE_PORT_NAME, tunnelOfPort, bridgeNode);
+                    return;
+                }
+
+                long localOfPort = southbound.getOFPort(bridgeNode, SERVER_PORT_NAME);
+                if (localOfPort == 0L) {
+                    LOG.error("programAclEntry: Could not identify local port {} -> OF ({}) on {}",
+                            CLIENT_GPE_PORT_NAME, localOfPort, bridgeNode);
+                    return;
+                }
+
+                RenderedServicePathHop lastRspHop = Iterables.getLast(rsp.getRenderedServicePathHop());
+
+                LOG.debug("programAclEntry: Last Hop #: {}, nsi: {}", lastRspHop.getHopNumber().intValue(),
+                        lastRspHop.getServiceIndex().intValue() - 1);
 
-        RenderedServicePathHop firstHop = pathHopList.get(0);
-        nshHeader.setNshNsi(firstHop.getServiceIndex());
-        nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
-        nshHeader.setNshTunUdpPort(firstRspHop.getPort());
-        LOG.debug("The Nsh Header = {}", nshHeader);
+                NshUtils nshHeader = new NshUtils();
+                nshHeader.setNshNsp(rsp.getPathId());
+                nshHeader.setNshNsi((short)(lastRspHop.getServiceIndex().intValue() - 1));
+                nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID));
+                LOG.debug("programAclEntry: The Nsh Header = {}", nshHeader);
 
-        handleLocalInPort(southbound.getDataPathId(srcNode), rsp.getPathId().toString(), localOfPort,
-                TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL, true);
+                //handleLocalEgressPort(southbound.getDataPathId(bridgeNode), rsp.getPathId().toString(), localOfPort,
+                //        TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL, true);
+
+                handleEgressSfcClassiferFlows(southbound.getDataPathId(bridgeNode),
+                        TABLE_0_CLASSIFIER, entry.getRuleName(), matches, nshHeader, tunnelOfPort, localOfPort, true);
+            }
+        }
+    }
+
+    private void handleLocalEgressPort(long dataPathId, String s, long localOfPort, short writeTable,
+                                       short gotoTable, boolean write) {
+
+    }
 
-        handleSfcClassiferFlows(southbound.getDataPathId(srcNode), TABLE_3_INGR_ACL, entry.getRuleName(),
-                matches, nshHeader, tunnelOfPort, true);
+    private void handleEgressSfcClassiferFlows(long dataPathId, short writeTable, String ruleName,
+                                               Matches matches, NshUtils nshHeader, long tunnelOfPort,
+                                               long outOfPort, boolean write) {
+        sfcClassifier.programEgressSfcClassiferFlows(dataPathId, writeTable, ruleName, matches, nshHeader,
+                tunnelOfPort, outOfPort, write);
     }
 
     private void handleSfcClassiferFlows(long dataPathId, short writeTable, String ruleName,
@@ -310,8 +368,8 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
     }
 
     public void handleLocalInPort(long dpidLong, String segmentationId, Long inPort,
-                                  short writeTable, short goToTableId, boolean write) {
-        sfcClassifier.programLocalInPort(dpidLong, segmentationId, inPort, writeTable, goToTableId, write);
+                                  short writeTable, short goToTableId, Matches matches, boolean write) {
+        sfcClassifier.programLocalInPort(dpidLong, segmentationId, inPort, writeTable, goToTableId, matches, write);
     }
 
     private void setDependencies(ServiceReference serviceReference) {
index e113464bc695aa43e211056d67e82610042ecd75..414db06f1fc47ecaa591875bdf25e012b5659df4 100644 (file)
@@ -10,11 +10,13 @@ package org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13;
 
 import com.google.common.collect.Lists;
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.List;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
@@ -26,11 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
@@ -41,15 +39,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
-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.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -79,7 +72,7 @@ public class SfcClassifier {
     public void programSfcClassiferFlows(Long dpidLong, short writeTable, String ruleName, Matches match,
                                          NshUtils nshHeader, long tunnelOfPort, boolean write) {
         String nodeName = OPENFLOW + dpidLong;
-        NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         MatchBuilder matchBuilder = buildMatch(match);
@@ -99,7 +92,7 @@ public class SfcClassifier {
             List<Action> actionList = getNshAction(nshHeader);
             ActionBuilder ab = new ActionBuilder();
 
-            ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + tunnelOfPort)));
+            ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(tunnelOfPort, nodeName)));
             ab.setOrder(actionList.size());
             ab.setKey(new ActionKey(actionList.size()));
             actionList.add(ab.build());
@@ -123,6 +116,65 @@ public class SfcClassifier {
         }
     }
 
+    public void programEgressSfcClassiferFlows(Long dpidLong, short writeTable, String ruleName,
+                                               Matches match, NshUtils nshHeader,
+                                               long tunnelOfPort, long outOfPort, boolean write) {
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
+        flowBuilder.setMatch(
+                MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshMetaC2())).build());
+        flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
+        flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
+
+        String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setBarrier(true);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+
+        if (write) {
+            List<Action> actionList = new ArrayList<>();
+            ActionBuilder ab = new ActionBuilder();
+
+            ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD).build(),
+                    BigInteger.valueOf(REG_VALUE_FROM_REMOTE)));
+            ab.setOrder(0);
+            ab.setKey(new ActionKey(0));
+            actionList.add(ab.build());
+
+            ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(dpidLong, outOfPort)));
+            ab.setOrder(1);
+            ab.setKey(new ActionKey(1));
+            actionList.add(ab.build());
+
+            ApplyActionsBuilder aab = new ApplyActionsBuilder();
+            aab.setAction(actionList);
+
+            InstructionBuilder ib = new InstructionBuilder();
+            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+            ib.setOrder(0);
+            ib.setKey(new InstructionKey(0));
+            List<Instruction> instructions = new ArrayList<>();
+            instructions.add(ib.build());
+
+            InstructionsBuilder isb = new InstructionsBuilder();
+            isb.setInstruction(instructions);
+
+            flowBuilder.setInstructions(isb.build());
+            writeFlow(flowBuilder, nodeBuilder);
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
+    }
+
     private List<Action> getNshAction(NshUtils header) {
         // Build the Actions to Add the NSH Header
         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load =
@@ -150,13 +202,14 @@ public class SfcClassifier {
     }
 
     public void programLocalInPort(Long dpidLong, String segmentationId, Long inPort,
-                                   short writeTable, short goToTableId, boolean write) {
+                                   short writeTable, short goToTableId, Matches match, boolean write) {
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
-        NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
+        MatchBuilder matchBuilder = buildMatch(match);
+        flowBuilder.setMatch(matchBuilder.build());
         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
         String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
         flowBuilder.setId(new FlowId(flowId));
@@ -205,36 +258,6 @@ public class SfcClassifier {
         }
     }
 
-/*
-    public InstructionsBuilder buildActions(String ruleName, Actions actions, String datapathId) {
-        InstructionBuilder ib = new InstructionBuilder();
-
-        if (actions.getPacketHandling() instanceof Deny) {
-            InstructionUtils.createDropInstructions(ib);
-        } else if (actions.getPacketHandling() instanceof Permit) {
-            //Permit actPermit = (Permit) actions.getPacketHandling();
-        } else {
-            InstructionUtils.createDropInstructions(ib);
-        }
-
-        ib.setOrder(0);
-        ib.setKey(new InstructionKey(0));
-        // Instructions List Stores Individual Instructions
-        List<Instruction> instructions = Lists.newArrayList();
-        instructions.add(ib.build());
-
-        // Call the InstructionBuilder Methods Containing Actions
-        ib = this.getMutablePipelineInstructionBuilder();
-        ib.setOrder(1);
-        ib.setKey(new InstructionKey(1));
-        instructions.add(ib.build());
-
-        // Add InstructionBuilder to the Instruction(s)Builder List
-        InstructionsBuilder isb = new InstructionsBuilder();
-        isb.setInstruction(instructions);
-        return isb;
-    }*/
-
     public MatchBuilder buildMatch(Matches matches) {
         MatchBuilder matchBuilder = new MatchBuilder();
 
@@ -244,7 +267,7 @@ public class SfcClassifier {
                 //AceIpv4 aceIpv4 = (AceIpv4) aceIp.getAceIpVersion();
                 //MatchUtils.createSrcL3IPv4Match(matchBuilder, aceIpv4.getSourceIpv4Network());
                 //MatchUtils.createDstL3IPv4Match(matchBuilder, aceIpv4.getDestinationIpv4Network());
-                //MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
+                MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
                 MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
                         aceIp.getDestinationPortRange().getLowerPort().getValue().intValue());
             }
@@ -255,59 +278,19 @@ public class SfcClassifier {
                     new MacAddress(aceEth.getDestinationMacAddressMask().getValue()));
         }
 
+        LOG.info("buildMatch: {}", matchBuilder.build());
         return matchBuilder;
     }
 
     protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
         LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}", flowBuilder.build(), nodeBuilder.build());
-        mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder), nodeBuilder.build());
-        mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
+        mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, FlowUtils.createNodePath(nodeBuilder),
+                nodeBuilder.build());
+        mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, FlowUtils.createFlowPath(flowBuilder, nodeBuilder),
                 flowBuilder.build());
     }
 
-    /*private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
-        LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}",
-                flowBuilder.build(), nodeBuilder.build());
-        WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
-        modification.put(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder),
-                nodeBuilder.build(), true);
-        modification.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
-                flowBuilder.build(), true);
-
-        CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
-        try {
-            commitFuture.get();  // TODO: Make it async (See bug 1362)
-            LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName());
-        } catch (Exception e) {
-            LOG.error(e.getMessage(), e);
-            modification.cancel();
-        }
-    }*/
-
     protected void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
-        mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder));
-    }
-
-    private NodeBuilder createNodeBuilder(String nodeId) {
-        NodeBuilder builder = new NodeBuilder();
-        builder.setId(new NodeId(nodeId));
-        builder.setKey(new NodeKey(builder.getId()));
-        return builder;
-    }
-
-    private static InstanceIdentifier<Flow> createFlowPath(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
-        return InstanceIdentifier.builder(Nodes.class)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
-                        nodeBuilder.getKey())
-                .augmentation(FlowCapableNode.class)
-                .child(Table.class, new TableKey(flowBuilder.getTableId()))
-                .child(Flow.class, flowBuilder.getKey()).build();
-    }
-
-    private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
-    createNodePath(NodeBuilder nodeBuilder) {
-        return InstanceIdentifier.builder(Nodes.class)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
-                        nodeBuilder.getKey()).build();
+        mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, FlowUtils.createFlowPath(flowBuilder, nodeBuilder));
     }
 }
index 9075b486ecd3a937bfcc631f9cf43355ed1adbea..67b04335ea4996eb339b72c38423e5b922297b12 100644 (file)
@@ -49,6 +49,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>openstack.net-virt-sfc-features-test</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>utils.mdsal-openflow</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>utils.mdsal-utils</artifactId>
index 49e8c6958ca47e02e2ad6854d884b3038ba8b2a0..f59ca24f59190e6d14c389d2ba83a192b235634d 100644 (file)
@@ -15,13 +15,16 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.ops4j.pax.exam.CoreOptions.composite;
 import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties;
 import static org.ops4j.pax.exam.CoreOptions.vmOption;
+import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
+import static org.ops4j.pax.exam.MavenUtils.asInProject;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
 
-import java.io.IOException;
+import java.math.BigInteger;
 import java.util.List;
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -41,6 +44,8 @@ import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ClassifierUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
@@ -50,10 +55,18 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.MatchesBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 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.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.Nshc1CaseValue;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
@@ -149,9 +162,13 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
 
     private Option[] getOtherOptions() {
         return new Option[] {
+                wrappedBundle(
+                        mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
+                                .version(asInProject())
+                                .type("jar")),
                 configureConsole().startLocalConsole(),
                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
-                keepRuntimeFolder()
+                        keepRuntimeFolder()
         };
     }
 
@@ -461,30 +478,133 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
             Thread.sleep(1000);
         }
 
-        SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
         Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
         assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
         long datapathId = southbound.getDataPathId(bridgeNode);
-        //sfcClassifier.programSfcClassiferFlows();
-        sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
+
+        SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
+        //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
 
         NshUtils nshUtils = new NshUtils(new Ipv4Address("192.168.50.71"), new PortNumber(6633),
                 (long)10, (short)255, (long)4096, (long)4096);
         MatchesBuilder matchesBuilder = aclUtils.createMatches(new MatchesBuilder(), 80);
-        sfcClassifier.programSfcClassiferFlows(datapathId, (short)50, "test", matchesBuilder.build(),
+        sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
                 nshUtils, (long)2, true);
 
+        nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
+        //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
+        //        nshUtils, (long)2, (long)3, true);
+
         //try {
         //    System.in.read();
         //} catch (IOException e) {
         //    e.printStackTrace();
         //}
 
-        Thread.sleep(15000);
+        /*NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+        FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, (short) 0);
+        Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+        assertNotNull("Could not find flow in config", flow);
+        flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+        assertNotNull("Could not find flow in operational", flow);*/
+
+        MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+        FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, (short) 0, "test", null,
+                nshUtils, (long) 2, matchBuilder);
+        Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+        assertNotNull("Could not find flow in config", flow);
+        flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+        assertNotNull("Could not find flow in operational", flow);
+
+        //nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+        //flowBuilder = getEgressSfcClassifierFlow(datapathId, (short) 0, "test", nshUtils, (long) 2);
+        //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+        //assertNotNull("Could not find flow in config", flow);
+        //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+        //assertNotNull("Could not find flow in operational", flow);
+
+        LOG.info("***** Go look for flows *****");
+        Thread.sleep(30000);
         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
         Thread.sleep(1000);
         assertTrue(southboundUtils.deleteBridge(connectionInfo, INTEGRATION_BRIDGE_NAME));
         Thread.sleep(1000);
         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
     }
+
+    private FlowBuilder getLocalInPortFlow(long dpidLong, String segmentationId, long inPort, short writeTable) {
+        MatchBuilder matchBuilder = new MatchBuilder();
+
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
+        String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setStrict(true);
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        return flowBuilder;
+    }
+
+    public FlowBuilder getSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, Matches match,
+                                             NshUtils nshHeader, long tunnelOfPort, MatchBuilder matchBuilder) {
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        flowBuilder.setMatch(matchBuilder.build());
+
+        String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp();
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setBarrier(true);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        return flowBuilder;
+    }
+
+    private FlowBuilder getEgressSfcClassifierFlow(long dpidLong, short writeTable, String ruleName,
+                                                   NshUtils nshHeader, long tunnelOfPort) {
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
+        flowBuilder.setMatch(
+                MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshNsp())).build());
+        flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
+        flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
+
+        String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setStrict(true);
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        return flowBuilder;
+    }
+
+    private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store)
+            throws InterruptedException {
+        Flow flow = null;
+        for (int i = 0; i < 10; i++) {
+            flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
+            if (flow != null) {
+                LOG.info("flow({}): {}", store, flow);
+                break;
+            }
+            Thread.sleep(1000);
+        }
+        return flow;
+    }
 }
index dd6cce50dce3072505e21e58898bb567e934cdf6..6880841f523af11d239361ec69b791cac142360c 100644 (file)
@@ -20,6 +20,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.MatchesBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.DestinationPortRangeBuilder;
 
@@ -32,6 +34,8 @@ public class AclUtils {
 
         AceIpBuilder aceIpBuilder = new AceIpBuilder();
         aceIpBuilder.setDestinationPortRange(destinationPortRangeBuilder.build());
+        aceIpBuilder.setProtocol((short)6);
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
         matchesBuilder.setAceType(aceIpBuilder.build());
 
         return matchesBuilder;