/*
* Copyright (c) 2016 Cisco Systems, 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.openflowplugin.openflow.md.core.sal.convertor.match;
import java.util.Iterator;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.IpConversionUtil;
import org.opendaylight.openflowplugin.openflow.md.util.ActionUtil;
import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowWildcardsV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10Builder;
/**
* The type Match convertor v 10.
*/
public class MatchConvertorV10Impl implements MatchConvertor<MatchV10> {
/**
* default MAC
*/
private static final MacAddress zeroMac = new MacAddress("00:00:00:00:00:00");
/**
* default IPv4
*/
private static final Ipv4Address zeroIPv4 = new Ipv4Address("0.0.0.0");
/*
* The value 0xffff (OFP_VLAN_NONE) is used to indicate
* that no VLAN ID is set for OF Flow.
*/
private static final Integer OFP_VLAN_NONE = 0xffff;
private static boolean convertL4UdpDstMatch(final MatchV10Builder matchBuilder,
final UdpMatch udpMatch) {
if (udpMatch.getUdpDestinationPort() != null) {
matchBuilder.setTpDst(udpMatch.getUdpDestinationPort().getValue());
return false;
}
return true;
}
private static boolean convertL4UdpSrcMatch(final MatchV10Builder matchBuilder,
final UdpMatch udpMatch) {
if (udpMatch.getUdpSourcePort() != null) {
matchBuilder.setTpSrc(udpMatch.getUdpSourcePort().getValue());
return false;
}
return true;
}
private static boolean convertL4TpDstMatch(final MatchV10Builder matchBuilder,
final TcpMatch tcpMatch) {
if (tcpMatch.getTcpDestinationPort() != null) {
matchBuilder.setTpDst(tcpMatch.getTcpDestinationPort().getValue());
return false;
}
return true;
}
private static boolean convertL4TpSrcMatch(final MatchV10Builder matchBuilder,
final TcpMatch tcpMatch) {
if (tcpMatch.getTcpSourcePort() != null) {
matchBuilder.setTpSrc(tcpMatch.getTcpSourcePort().getValue());
return false;
}
return true;
}
private static boolean convertNwTos(final MatchV10Builder matchBuilder,
final IpMatch ipMatch) {
if (ipMatch.getIpDscp() != null) {
matchBuilder.setNwTos(ActionUtil.dscpToTos(ipMatch.getIpDscp().getValue()));
return false;
}
return true;
}
private static boolean convertNwProto(final MatchV10Builder matchBuilder, final IpMatch ipMatch) {
if (ipMatch.getIpProtocol() != null) {
matchBuilder.setNwProto(ipMatch.getIpProtocol());
return false;
}
return true;
}
/**
* Method splits the IP address and its mask and set their respective values in MatchV10Builder instance.
* Wildcard value of the IP mask will be determined by Openflow java encoding library.
*
* @param matchBuilder match builder
* @param ipv4 ip v4 match
*/
private static void convertL3Ipv4DstMatch(final MatchV10Builder matchBuilder,
final Ipv4Match ipv4) {
if (ipv4.getIpv4Destination() != null) {
Iterator<String> addressParts = IpConversionUtil.PREFIX_SPLITTER.split(ipv4.getIpv4Destination().getValue()).iterator();
Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
Integer prefix = buildPrefix(addressParts);
matchBuilder.setNwDst(ipv4Address);
matchBuilder.setNwDstMask(prefix.shortValue());
}
}
/**
* Method splits the IP address and its mask and set their respective values in MatchV10Builder instance.
* Wildcard value of the IP mask will be determined by Openflow java encoding library.
*
* @param matchBuilder match builder
* @param ipv4 ip v4 match
*/
private static void convertL3Ipv4SrcMatch(final MatchV10Builder matchBuilder,
final Ipv4Match ipv4) {
if (ipv4.getIpv4Source() != null) {
Iterator<String> addressParts = IpConversionUtil.PREFIX_SPLITTER.split(ipv4.getIpv4Source().getValue()).iterator();
Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
int prefix = buildPrefix(addressParts);
matchBuilder.setNwSrc(ipv4Address);
matchBuilder.setNwSrcMask((short) prefix);
}
}
private static int buildPrefix(final Iterator<String> addressParts) {
int prefix = 32;
if (addressParts.hasNext()) {
prefix = Integer.parseInt(addressParts.next());
}
return prefix;
}
private static boolean convertDlVlanPcp(final MatchV10Builder matchBuilder,
final VlanMatch vlanMatch) {
if (vlanMatch.getVlanPcp() != null) {
matchBuilder.setDlVlanPcp(vlanMatch.getVlanPcp().getValue());
return false;
}
return true;
}
private static boolean convertDlVlan(final MatchV10Builder matchBuilder, final VlanMatch vlanMatch) {
if (vlanMatch.getVlanId() != null) {
int vlanId = vlanMatch.getVlanId().getVlanId().getValue();
matchBuilder.setDlVlan((vlanId == 0 ? OFP_VLAN_NONE : vlanId));
return false;
}
return true;
}
private static boolean convertEthernetDlType(final MatchV10Builder matchBuilder,
final EthernetMatch ethernetMatch) {
if (ethernetMatch.getEthernetType() != null) {
matchBuilder.setDlType(ethernetMatch.getEthernetType().getType().getValue().intValue());
return false;
}
return true;
}
private static boolean convertEthernetDlSrc(final MatchV10Builder matchBuilder,
final EthernetMatch ethernetMatch) {
if (ethernetMatch.getEthernetSource() != null) {
matchBuilder.setDlSrc(ethernetMatch.getEthernetSource().getAddress());
return false;
}
return true;
}
private static boolean convertEthernetDlDst(final MatchV10Builder matchBuilder,
final EthernetMatch ethernetMatch) {
if (ethernetMatch.getEthernetDestination() != null) {
matchBuilder.setDlDst(ethernetMatch.getEthernetDestination().getAddress());
return false;
}
return true;
}
private static boolean convertInPortMatch(final MatchV10Builder matchBuilder, final NodeConnectorId inPort) {
if (inPort != null) {
matchBuilder.setInPort(InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF10, inPort).intValue());
return false;
}
return true;
}
/**
* Method builds openflow 1.0 specific match (MatchV10) from MD-SAL match.
*
* @param match MD-SAL match
* @param convertorExecutor
* @return OF-API match
*/
@Override
public MatchV10 convert(final Match match, ConvertorExecutor convertorExecutor) {
MatchV10Builder matchBuilder = new MatchV10Builder();
boolean _dLDST = true;
boolean _dLSRC = true;
boolean _dLTYPE = true;
boolean _dLVLAN = true;
boolean _dLVLANPCP = true;
boolean _iNPORT = true;
boolean _nWPROTO = true;
boolean _nWTOS = true;
boolean _tPDST = true;
boolean _tPSRC = true;
matchBuilder.setInPort(0);
matchBuilder.setDlDst(zeroMac);
matchBuilder.setDlSrc(zeroMac);
matchBuilder.setDlType(0);
matchBuilder.setDlVlan(OFP_VLAN_NONE);
matchBuilder.setDlVlanPcp((short) 0);
matchBuilder.setNwDst(zeroIPv4);
matchBuilder.setNwDstMask((short) 0);
matchBuilder.setNwSrc(zeroIPv4);
matchBuilder.setNwSrcMask((short) 0);
matchBuilder.setNwProto((short) 0);
matchBuilder.setNwTos((short) 0);
matchBuilder.setTpSrc(0);
matchBuilder.setTpDst(0);
if (match != null) {
EthernetMatch ethernetMatch = match.getEthernetMatch();
if (ethernetMatch != null) {
_dLDST = convertEthernetDlDst(matchBuilder, ethernetMatch);
_dLSRC = convertEthernetDlSrc(matchBuilder, ethernetMatch);
_dLTYPE = convertEthernetDlType(matchBuilder, ethernetMatch);
}
VlanMatch vlanMatch = match.getVlanMatch();
if (vlanMatch != null) {
_dLVLAN = convertDlVlan(matchBuilder, vlanMatch);
_dLVLANPCP = convertDlVlanPcp(matchBuilder, vlanMatch);
}
NodeConnectorId inPort = match.getInPort();
if (inPort != null) {
_iNPORT = convertInPortMatch(matchBuilder, inPort);
}
Layer3Match l3Match = match.getLayer3Match();
if (l3Match != null) {
if (l3Match instanceof Ipv4Match) {
Ipv4Match ipv4 = (Ipv4Match) l3Match;
convertL3Ipv4SrcMatch(matchBuilder, ipv4);
convertL3Ipv4DstMatch(matchBuilder, ipv4);
}
}
IpMatch ipMatch = match.getIpMatch();
if (ipMatch != null) {
_nWPROTO = convertNwProto(matchBuilder, ipMatch);
_nWTOS = convertNwTos(matchBuilder, ipMatch);
}
Layer4Match layer4Match = match.getLayer4Match();
if (layer4Match != null) {
if (layer4Match instanceof TcpMatch) {
TcpMatch tcpMatch = (TcpMatch) layer4Match;
_tPSRC = convertL4TpSrcMatch(matchBuilder, tcpMatch);
_tPDST = convertL4TpDstMatch(matchBuilder, tcpMatch);
} else if (layer4Match instanceof UdpMatch) {
UdpMatch udpMatch = (UdpMatch) layer4Match;
_tPSRC = convertL4UdpSrcMatch(matchBuilder, udpMatch);
_tPDST = convertL4UdpDstMatch(matchBuilder, udpMatch);
}
} else {
Icmpv4Match icmpv4Match = match.getIcmpv4Match();
if (icmpv4Match != null) {
Short type = icmpv4Match.getIcmpv4Type();
if (type != null) {
matchBuilder.setTpSrc(type.intValue());
_tPSRC = false;
}
Short code = icmpv4Match.getIcmpv4Code();
if (code != null) {
matchBuilder.setTpDst(code.intValue());
_tPDST = false;
}
}
}
}
FlowWildcardsV10 wildCards = new FlowWildcardsV10(
_dLDST, _dLSRC, _dLTYPE, _dLVLAN,
_dLVLANPCP, _iNPORT, _nWPROTO, _nWTOS, _tPDST, _tPSRC);
matchBuilder.setWildcards(wildCards);
return matchBuilder.build();
}
}