All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.openflowplugin.impl.util.MatchNormalizationUtil Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
 * Copyright (c) 2024 PANTHEON.tech, s.r.o.
 *
 * 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.impl.util;

import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Arbitrary;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Prefix;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6AddressWithoutMask;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Arbitrary;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Prefix;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddress;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddressMask;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
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.Ipv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
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.Ipv6Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchArbitraryBitMask;
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._3.match.TunnelIpv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
import org.opendaylight.yangtools.yang.common.Uint8;

/**
 * Utility class for match normalization.
 */
// FIXME: rename to MatchNormalizer, move to FlowRegistryKeyFactory's package and hide
public final class MatchNormalizationUtil {
    public static final @NonNull MatchNormalizationUtil VERSION_1_0 =
        new MatchNormalizationUtil(OFConstants.OFP_VERSION_1_0);
    public static final @NonNull MatchNormalizationUtil VERSION_1_3 =
        new MatchNormalizationUtil(OFConstants.OFP_VERSION_1_3);
    private static final LoadingCache CACHE = CacheBuilder.newBuilder()
        .weakValues().build(new CacheLoader<>() {
            @Override
            public MatchNormalizationUtil load(final Uint8 key) {
                return new MatchNormalizationUtil(key);
            }
        });

    private final AddressNormalizationUtil addressNormalizer;

    private MatchNormalizationUtil(final Uint8 version) {
        addressNormalizer = AddressNormalizationUtil.ofVersion(OpenflowVersion.ofVersion(version));
    }

    public static @NonNull MatchNormalizationUtil ofVersion(final Uint8 version) {
        if (OFConstants.OFP_VERSION_1_3.equals(version)) {
            return VERSION_1_3;
        } else if (OFConstants.OFP_VERSION_1_0.equals(version)) {
            return VERSION_1_0;
        } else {
            return CACHE.getUnchecked(version);
        }
    }

    /**
     * Normalize match.
     *
     * @param match   the OpenFlow match
     * @return normalized OpenFlow match
     */
    public @NonNull Match normalizeMatch(@NonNull final Match match) {
        var builder = new MatchBuilder(match);
        builder = normalizeExtensionMatch(builder);
        builder = normalizeEthernetMatch(builder);
        builder = normalizeArpMatch(builder);
        builder = normalizeTunnelIpv4Match(builder);
        builder = normalizeIpv4Match(builder);
        builder = normalizeIpv4MatchArbitraryBitMask(builder);
        builder = normalizeIpv6Match(builder);
        builder = normalizeIpv6MatchArbitraryBitMask(builder);
        builder = normalizeInPortMatch(builder);
        builder = normalizeInPhyPortMatch(builder);
        return builder.build();
    }

    @VisibleForTesting
    @NonNull MatchBuilder normalizeInPortMatch(final @NonNull MatchBuilder match) {
        final var inPort = match.getInPort();
        if (inPort != null) {
            final var inPortUri = addressNormalizer.normalizeProtocolAgnosticPort(inPort);
            if (inPortUri != null) {
                match.setInPort(new NodeConnectorId(inPortUri));
            }
        }
        return match;
    }

    @VisibleForTesting
    @NonNull MatchBuilder normalizeInPhyPortMatch(final @NonNull MatchBuilder match) {
        final var inPhyPort = match.getInPhyPort();
        if (inPhyPort != null) {
            final var inPhyPortUri = addressNormalizer.normalizeProtocolAgnosticPort(inPhyPort);
            if (inPhyPortUri != null) {
                match.setInPhyPort(new NodeConnectorId(inPhyPortUri));
            }
        }
        return match;
    }

    @VisibleForTesting
    static @NonNull MatchBuilder normalizeArpMatch(final @NonNull MatchBuilder match) {
        if (match.getLayer3Match() instanceof ArpMatch arp) {
            final var builder = new ArpMatchBuilder(arp)
                .setArpSourceTransportAddress(normalizeIpv4Prefix(arp.getArpSourceTransportAddress()))
                .setArpTargetTransportAddress(normalizeIpv4Prefix(arp.getArpTargetTransportAddress()));

            final var arpSource = arp.getArpSourceHardwareAddress();
            if (arpSource != null) {
                builder.setArpSourceHardwareAddress(new ArpSourceHardwareAddressBuilder(arpSource)
                    .setAddress(normalizeMacAddress(arpSource.getAddress()))
                    .setMask(normalizeMacAddress(arpSource.getMask()))
                    .build());
            }
            final var arpTarget = arp.getArpTargetHardwareAddress();
            if (arpTarget != null) {
                builder.setArpTargetHardwareAddress(new ArpTargetHardwareAddressBuilder(arpTarget)
                    .setAddress(normalizeMacAddress(arpTarget.getAddress()))
                    .setMask(normalizeMacAddress(arpTarget.getMask()))
                    .build());
            }
            match.setLayer3Match(builder.build());
        }
        return match;
    }

    @VisibleForTesting
    static @NonNull MatchBuilder normalizeTunnelIpv4Match(final @NonNull MatchBuilder match) {
        if (match.getLayer3Match() instanceof TunnelIpv4Match tunnelIpv4) {
            match.setLayer3Match(new TunnelIpv4MatchBuilder(tunnelIpv4)
                .setTunnelIpv4Source(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Source()))
                .setTunnelIpv4Destination(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Destination()))
                .build());
        }
        return match;
    }

    @VisibleForTesting
    static @NonNull MatchBuilder normalizeIpv4Match(final @NonNull MatchBuilder match) {
        if (match.getLayer3Match() instanceof Ipv4Match ipv4) {
            match.setLayer3Match(new Ipv4MatchBuilder(ipv4)
                .setIpv4Source(normalizeIpv4Prefix(ipv4.getIpv4Source()))
                .setIpv4Destination(normalizeIpv4Prefix(ipv4.getIpv4Destination()))
                .build());
        }
        return match;
    }

    @NonNull
    @VisibleForTesting
    static MatchBuilder normalizeIpv4MatchArbitraryBitMask(final @NonNull MatchBuilder match) {
        if (match.getLayer3Match() instanceof Ipv4MatchArbitraryBitMask ipv4arbitrary) {
            match.setLayer3Match(new Ipv4MatchBuilder()
                .setIpv4Source(normalizeIpv4Arbitrary(
                    ipv4arbitrary.getIpv4SourceAddressNoMask(),
                    ipv4arbitrary.getIpv4SourceArbitraryBitmask()))
                .setIpv4Destination(normalizeIpv4Arbitrary(
                    ipv4arbitrary.getIpv4DestinationAddressNoMask(),
                    ipv4arbitrary.getIpv4DestinationArbitraryBitmask()))
                .build());
        }
        return match;
    }

    @VisibleForTesting
    static @NonNull MatchBuilder normalizeIpv6Match(final @NonNull MatchBuilder match) {
        if (match.getLayer3Match() instanceof Ipv6Match ipv6) {
            match.setLayer3Match(new Ipv6MatchBuilder(ipv6)
                .setIpv6NdSll(normalizeMacAddress(ipv6.getIpv6NdSll()))
                .setIpv6NdTll(normalizeMacAddress(ipv6.getIpv6NdTll()))
                .setIpv6NdTarget(normalizeIpv6AddressWithoutMask(ipv6.getIpv6NdTarget()))
                .setIpv6Source(normalizeIpv6Prefix(ipv6.getIpv6Source()))
                .setIpv6Destination(normalizeIpv6Prefix(ipv6.getIpv6Destination()))
                .build());
        }
        return match;
    }

    @VisibleForTesting
    static @NonNull MatchBuilder normalizeIpv6MatchArbitraryBitMask(final @NonNull MatchBuilder match) {
        if (match.getLayer3Match() instanceof Ipv6MatchArbitraryBitMask ipv6Arbitrary) {
            match.setLayer3Match(new Ipv6MatchBuilder()
                .setIpv6Source(normalizeIpv6Arbitrary(
                    ipv6Arbitrary.getIpv6SourceAddressNoMask(),
                    ipv6Arbitrary.getIpv6SourceArbitraryBitmask()))
                .setIpv6Destination(normalizeIpv6Arbitrary(
                    ipv6Arbitrary.getIpv6DestinationAddressNoMask(),
                    ipv6Arbitrary.getIpv6DestinationArbitraryBitmask()))
                .build());
        }
        return match;
    }

    @VisibleForTesting
    static @NonNull MatchBuilder normalizeEthernetMatch(final @NonNull MatchBuilder match) {
        final var eth = match.getEthernetMatch();
        if (eth != null) {
            final var builder = new EthernetMatchBuilder(eth);
            final var source = eth.getEthernetSource();
            if (source != null) {
                builder.setEthernetSource(new EthernetSourceBuilder(source)
                    .setAddress(normalizeMacAddress(source.getAddress()))
                    .setMask(normalizeMacAddressMask(source.getMask()))
                    .build());
            }
            final var dest = eth.getEthernetDestination();
            if (dest != null) {
                builder.setEthernetDestination(new EthernetDestinationBuilder(dest)
                    .setAddress(normalizeMacAddress(dest.getAddress()))
                    .setMask(normalizeMacAddressMask(dest.getMask()))
                    .build());
            }
            match.setEthernetMatch(builder.build());
        }
        return match;
    }

    private static @NonNull MatchBuilder normalizeExtensionMatch(@NonNull final MatchBuilder match) {
        return new MatchBuilder(MatchUtil.transformMatch(match.build(), Match.class));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy