--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
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());
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};
--- /dev/null
+/*
+ * 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());
+ }
+}
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());
}
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;
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;
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
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
*
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
*
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());