Bug 4996 - Wrong flows when using SFC coexistence 09/34109/1
authorSam Hague <shague@redhat.com>
Thu, 4 Feb 2016 23:17:28 +0000 (18:17 -0500)
committerSam Hague <shague@redhat.com>
Thu, 4 Feb 2016 23:42:15 +0000 (23:42 +0000)
Signed-off-by: Sam Hague <shague@redhat.com>
(cherry picked from commit e0bf1166f4ad2515859ab43080a28115975a2cf5)

Change-Id: I0874c752f8777d8a3f6a7f8f60db22c605c986a3
Signed-off-by: Sam Hague <shague@redhat.com>
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatches.java [new file with mode: 0644]
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclUtils.java [new file with mode: 0644]
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java
openstack/net-virt-sfc/impl/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatchesTest.java [new file with mode: 0644]
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/it/utils/AclUtils.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java

diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatches.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatches.java
new file mode 100644 (file)
index 0000000..0de13ec
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2016 Red Hat, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services;
+
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+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.matches.ace.type.AceEth;
+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.AceIp;
+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.AceIpv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AclMatches {
+    private static final Logger LOG = LoggerFactory.getLogger(AclMatches.class);
+    MatchBuilder matchBuilder;
+    Matches matches;
+
+    public AclMatches(Matches matches) {
+        matchBuilder = new MatchBuilder();
+        this.matches = matches;
+    }
+
+    /**
+     * Convert the ACL into an OpenFlow {@link MatchBuilder}
+     * @return {@link MatchBuilder}
+     */
+    //TODO: Matches will overwrite previous matches for ethernet and ip since these methods
+    // can be called successively for the same ACL.
+    // This requires fixing the MatchUtils to preserve previously set fields.
+    protected MatchBuilder buildMatch() {
+        if (matches.getAceType() instanceof AceEth) {
+            addEthMatch();
+        } else if (matches.getAceType() instanceof AceIp) {
+            addIpMatch();
+        }
+
+        LOG.info("buildMatch: {}", matchBuilder.build());
+        return matchBuilder;
+    }
+
+    private void addEthMatch() {
+        AceEth aceEth = (AceEth) matches.getAceType();
+        MatchUtils.createEthSrcDstMatch(matchBuilder, aceEth.getSourceMacAddress(),
+                aceEth.getDestinationMacAddress());
+    }
+
+    private void addIpMatch() {
+        AceIp aceIp = (AceIp)matches.getAceType();
+
+        if (aceIp.getDscp() != null) {
+            MatchUtils.addDscp(matchBuilder, aceIp.getDscp().getValue());
+        }
+
+        if (aceIp.getProtocol() != null) {
+            addIpProtocolMatch(aceIp);
+        }
+
+        if (aceIp.getAceIpVersion() instanceof AceIpv4) {
+            addIpV4Match(aceIp);
+        }
+
+        if (aceIp.getAceIpVersion() instanceof AceIpv6) {
+            addIpV6Match(aceIp);
+        }
+    }
+
+    private void addIpProtocolMatch(AceIp aceIp) {
+        int srcPort = 0;
+        int dstPort = 0;
+
+        // TODO Ranges are not supported yet
+        if (aceIp.getSourcePortRange() != null && aceIp.getSourcePortRange().getLowerPort() != null) {
+            srcPort = aceIp.getSourcePortRange().getLowerPort().getValue();
+        }
+        if (aceIp.getDestinationPortRange() != null && aceIp.getDestinationPortRange().getLowerPort() != null) {
+            dstPort = aceIp.getDestinationPortRange().getLowerPort().getValue();
+        }
+        MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
+        MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), srcPort, dstPort);
+    }
+
+    private void addIpV4Match(AceIp aceIp) {
+        AceIpv4 aceIpv4 = (AceIpv4)aceIp.getAceIpVersion();
+
+        MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(MatchUtils.ETHERTYPE_IPV4));
+        matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, aceIpv4.getSourceIpv4Network(),
+                aceIpv4.getDestinationIpv4Network());
+    }
+
+    private void addIpV6Match(AceIp aceIp) {
+        AceIpv6 aceIpv6 = (AceIpv6)aceIp.getAceIpVersion();
+
+        MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(MatchUtils.ETHERTYPE_IPV6));
+        matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, aceIpv6.getSourceIpv6Network(),
+                aceIpv6.getDestinationIpv6Network());
+    }
+}
diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclUtils.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclUtils.java
new file mode 100644 (file)
index 0000000..585eab7
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2016 Red Hat, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
+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.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
+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.Ace;
+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.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.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;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.SourcePortRangeBuilder;
+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.acl.rev150105.RedirectToSfcBuilder;
+
+public class AclUtils {
+    private static final String ACLNAME= "httpAcl";
+    private static final String RULENAME= "httpRule";
+    private static final String SFCNAME = "SFC";
+
+    public MatchesBuilder matchesBuilder(MatchesBuilder matchesBuilder, int dstPort) {
+        SourcePortRangeBuilder sourcePortRangeBuilder = new SourcePortRangeBuilder()
+                .setLowerPort(PortNumber.getDefaultInstance("0"))
+                .setUpperPort(PortNumber.getDefaultInstance("0"));
+
+        PortNumber portNumber = new PortNumber(dstPort);
+        DestinationPortRangeBuilder destinationPortRangeBuilder = new DestinationPortRangeBuilder()
+                .setLowerPort(portNumber)
+                .setUpperPort(portNumber);
+
+        AceIpBuilder aceIpBuilder = new AceIpBuilder()
+                .setSourcePortRange(sourcePortRangeBuilder.build())
+                .setDestinationPortRange(destinationPortRangeBuilder.build())
+                .setProtocol((short)6);
+
+        return matchesBuilder.setAceType(aceIpBuilder.build());
+    }
+
+    public ActionsBuilder actionsBuilder(ActionsBuilder actionsBuilder, Boolean permit) {
+        return actionsBuilder.setPacketHandling(new PermitBuilder().setPermit(permit).build());
+    }
+
+    public ActionsBuilder actionsBuilder(ActionsBuilder actionsBuilder, String sfcName, boolean renderRsp) {
+        RedirectToSfcBuilder redirectToSfcBuilder = new RedirectToSfcBuilder()
+                .setSfcName(sfcName)
+                .setRenderRsp(renderRsp);
+
+        return actionsBuilder.addAugmentation(RedirectToSfc.class, redirectToSfcBuilder.build());
+    }
+
+    public AceBuilder aceBuilder(AceBuilder accessListEntryBuilder,
+                                 String ruleName,
+                                 MatchesBuilder matchesBuilder,
+                                 ActionsBuilder actionsBuilder) {
+        return accessListEntryBuilder
+                .setRuleName(ruleName)
+                .setMatches(matchesBuilder.build())
+                .setActions(actionsBuilder.build());
+    }
+
+    public AccessListEntriesBuilder accessListEntriesBuidler(AccessListEntriesBuilder accessListEntriesBuilder,
+                                                             AceBuilder aceBuilder) {
+        List<Ace> aceList = new ArrayList<>();
+        aceList.add(aceBuilder.build());
+
+        return accessListEntriesBuilder.setAce(aceList);
+    }
+
+    public AclBuilder aclBuilder(AclBuilder aclBuilder,
+                                 String aclName,
+                                 AccessListEntriesBuilder accessListEntriesBuilder) {
+        return aclBuilder
+                .setAclName(aclName)
+                .setAccessListEntries(accessListEntriesBuilder.build());
+    }
+
+    public AccessListsBuilder accessListsbuilder(AccessListsBuilder accessListsBuilder,
+                                                 AclBuilder aclBuilder) {
+        List<Acl> aclList = new ArrayList<>();
+        aclList.add(aclBuilder.build());
+
+        return accessListsBuilder.setAcl(aclList);
+    }
+
+    public AccessListsBuilder accessListsBuilder(boolean renderRsp) {
+        String ruleName = RULENAME;
+        String sfcName = SFCNAME;
+        MatchesBuilder matchesBuilder = matchesBuilder(new MatchesBuilder(), 80);
+        ActionsBuilder actionsBuilder = actionsBuilder(new ActionsBuilder(), sfcName, renderRsp);
+        AceBuilder accessListEntryBuilder =
+                aceBuilder(new AceBuilder(), ruleName, matchesBuilder, actionsBuilder);
+        AccessListEntriesBuilder accessListEntriesBuilder =
+                accessListEntriesBuidler(new AccessListEntriesBuilder(), accessListEntryBuilder);
+        AclBuilder accessListBuilder =
+                aclBuilder(new AclBuilder(), ACLNAME, accessListEntriesBuilder);
+        AccessListsBuilder accessListsBuilder =
+                accessListsbuilder(new AccessListsBuilder(), accessListBuilder);
+        return accessListsBuilder;
+    }
+}
index c6442e6aecb12b3931d4136fe65b22e7a6624637..3cee6f055dc0eb64ba179101590e371b23a20fcb 100644 (file)
@@ -133,7 +133,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         initFlowBuilder(flowBuilder, flowName, getTable(), FlowID.FLOW_INGRESSCLASS,
                 (short)nshHeader.getNshNsp(), nshHeader.getNshNsi());
 
-        MatchBuilder matchBuilder = buildMatch(matches);
+        MatchBuilder matchBuilder = new AclMatches(matches).buildMatch();
         MatchUtils.addNxRegMatch(matchBuilder,
                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
         flowBuilder.setMatch(matchBuilder.build());
@@ -508,31 +508,6 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         return actionList;
     }
 
-    public MatchBuilder buildMatch(Matches matches) {
-        MatchBuilder matchBuilder = new MatchBuilder();
-
-        if (matches.getAceType() instanceof AceIp) {
-            AceIp aceIp = (AceIp)matches.getAceType();
-            if (aceIp.getAceIpVersion() instanceof AceIpv4) {
-                MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
-                MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
-                        aceIp.getDestinationPortRange().getLowerPort().getValue());
-            } else {
-                MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
-                MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
-                        aceIp.getDestinationPortRange().getLowerPort().getValue());
-            }
-        } else if (matches.getAceType() instanceof AceEth) {
-            AceEth aceEth = (AceEth) matches.getAceType();
-            MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(aceEth.getSourceMacAddress().getValue()));
-            MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(aceEth.getDestinationMacAddress().getValue()),
-                    new MacAddress(aceEth.getDestinationMacAddressMask().getValue()));
-        }
-
-        LOG.info("buildMatch: {}", matchBuilder.build());
-        return matchBuilder;
-    }
-
     private static FlowID flowSet[] = {FlowID.FLOW_INGRESSCLASS, FlowID.FLOW_EGRESSCLASS,
             FlowID.FLOW_EGRESSCLASSBYPASS, FlowID.FLOW_SFARP};
 
diff --git a/openstack/net-virt-sfc/impl/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatchesTest.java b/openstack/net-virt-sfc/impl/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatchesTest.java
new file mode 100644 (file)
index 0000000..591989f
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2016 Red Hat, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+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.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+
+public class AclMatchesTest {
+    @Test
+    public void buildMatchTest() {
+        AclUtils aclUtils = new AclUtils();
+        MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createIpProtocolMatch(matchBuilder, (short)6);
+        MatchUtils.addLayer4Match(matchBuilder, 6, 0, 80);
+        assertEquals(matchBuilder.build(), aclMatches.buildMatch().build());
+    }
+}
index 760bf6152d9af4eb39ce52ffd9dc30e0106e496a..0f5e574c231c7c900e1d0fe06844e3dc364e81a2 100644 (file)
@@ -41,8 +41,7 @@ public class AclUtils extends AbstractUtils {
         AceIpBuilder aceIpBuilder = new AceIpBuilder()
                 .setSourcePortRange(sourcePortRangeBuilder.build())
                 .setDestinationPortRange(destinationPortRangeBuilder.build())
-                .setProtocol((short)6)
-                .setAceIpVersion(new AceIpv4Builder().build());
+                .setProtocol((short)6);
 
         return matchesBuilder.setAceType(aceIpBuilder.build());
     }
index cbb73c0d2097ba3e9c34a0c17e2fb096916e629a..97d381f9abbf219e29e7f318f5b91fabed5ae408 100644 (file)
@@ -14,6 +14,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
@@ -37,6 +38,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
@@ -96,12 +98,15 @@ public class MatchUtils {
     public static final short ICMP_SHORT = 1;
     public static final short TCP_SHORT = 6;
     public static final short UDP_SHORT = 17;
+    public static final short SCTP_SHORT = 132;
     public static final String TCP = "tcp";
     public static final String UDP = "udp";
     private static final int TCP_SYN = 0x0002;
     public static final String ICMP = "icmp";
     public static final String ICMPV6 = "icmpv6";
     public static final short ALL_ICMP = -1;
+    public static final long ETHERTYPE_IPV4 = 0x0800;
+    public static final long ETHERTYPE_IPV6 = 0x86dd;
 
     /**
      * Create Ingress Port Match dpidLong, inPort
@@ -150,6 +155,27 @@ public class MatchUtils {
         return matchBuilder;
     }
 
+    public static MatchBuilder createEthSrcDstMatch(MatchBuilder matchBuilder, MacAddress srcMac, MacAddress dstMac) {
+        EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+        if (srcMac != null) {
+            EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder();
+            ethSourceBuilder.setAddress(new MacAddress(srcMac));
+            ethernetMatch.setEthernetSource(ethSourceBuilder.build());
+        }
+        if (dstMac != null) {
+            EthernetDestinationBuilder ethDestinationBuild = new EthernetDestinationBuilder();
+            ethDestinationBuild.setAddress(new MacAddress(dstMac));
+            ethernetMatch.setEthernetDestination(ethDestinationBuild.build());
+        }
+        if (matchBuilder.getEthernetMatch() != null && matchBuilder.getEthernetMatch().getEthernetType() != null) {
+            ethernetMatch.setEthernetType(matchBuilder.getEthernetMatch().getEthernetType());
+        }
+
+        matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+        return matchBuilder;
+    }
+
     /**
      * Create Ethernet Source Match
      *
@@ -1254,6 +1280,20 @@ public class MatchUtils {
         return matchBuilder;
     }
 
+    /**
+     * Add a DSCP match to an existing match
+     * @param matchBuilder Map matchBuilder MatchBuilder Object with a match
+     * @param dscpValue
+     * @return {@link MatchBuilder}
+     */
+    public static MatchBuilder addDscp(MatchBuilder matchBuilder, short dscpValue) {
+        createEtherTypeMatch(matchBuilder, new EtherType(ETHERTYPE_IPV4));
+        return matchBuilder.setIpMatch(
+                new IpMatchBuilder()
+                        .setIpDscp(new Dscp(dscpValue))
+                        .build());
+    }
+
     /**
      * Add a layer4 match to an existing match
      *
@@ -1286,6 +1326,16 @@ public class MatchUtils {
                 udpMatch.setUdpDestinationPort(new PortNumber(destPort));
             }
             matchBuilder.setLayer4Match(udpMatch.build());
+        } else if (SCTP_SHORT == protocol) {
+            ipmatch.setIpProtocol(SCTP_SHORT);
+            SctpMatchBuilder sctpMatchBuilder = new SctpMatchBuilder();
+            if (0 != srcPort) {
+                sctpMatchBuilder.setSctpSourcePort(new PortNumber(srcPort));
+            }
+            if (0 != destPort) {
+                sctpMatchBuilder.setSctpDestinationPort(new PortNumber(destPort));
+            }
+            matchBuilder.setLayer4Match(sctpMatchBuilder.build());
         }
         matchBuilder.setIpMatch(ipmatch.build());