From 1fc1d914e6167420694e014b354a16713c3ea5e0 Mon Sep 17 00:00:00 2001 From: Sam Hague Date: Thu, 4 Feb 2016 18:17:28 -0500 Subject: [PATCH] Bug 4996 - Wrong flows when using SFC coexistence Signed-off-by: Sam Hague (cherry picked from commit e0bf1166f4ad2515859ab43080a28115975a2cf5) Change-Id: I0874c752f8777d8a3f6a7f8f60db22c605c986a3 Signed-off-by: Sam Hague --- .../sfc/workaround/services/AclMatches.java | 106 ++++++++++++++++ .../sfc/workaround/services/AclUtils.java | 114 ++++++++++++++++++ .../services/SfcClassifierService.java | 27 +---- .../workaround/services/AclMatchesTest.java | 30 +++++ .../netvirt/sfc/it/utils/AclUtils.java | 3 +- .../utils/mdsal/openflow/MatchUtils.java | 50 ++++++++ 6 files changed, 302 insertions(+), 28 deletions(-) create mode 100644 openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatches.java create mode 100644 openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclUtils.java create mode 100644 openstack/net-virt-sfc/impl/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatchesTest.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 index 0000000000..0de13ec03e --- /dev/null +++ b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatches.java @@ -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 index 0000000000..585eab7910 --- /dev/null +++ b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclUtils.java @@ -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 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 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; + } +} diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java index c6442e6aec..3cee6f055d 100644 --- a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java +++ b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java @@ -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 index 0000000000..591989ffd6 --- /dev/null +++ b/openstack/net-virt-sfc/impl/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/AclMatchesTest.java @@ -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()); + } +} diff --git a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/it/utils/AclUtils.java b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/it/utils/AclUtils.java index 760bf6152d..0f5e574c23 100644 --- a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/it/utils/AclUtils.java +++ b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/it/utils/AclUtils.java @@ -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()); } diff --git a/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java b/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java index cbb73c0d20..97d381f9ab 100644 --- a/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java +++ b/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java @@ -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()); -- 2.36.6