2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.impl.util;
10 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Arbitrary;
11 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Prefix;
12 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6AddressWithoutMask;
13 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Arbitrary;
14 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Prefix;
15 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddress;
16 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddressMask;
17 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeProtocolAgnosticPort;
19 import com.google.common.annotations.VisibleForTesting;
20 import com.google.common.cache.CacheBuilder;
21 import com.google.common.cache.CacheLoader;
22 import com.google.common.cache.LoadingCache;
23 import com.google.common.collect.ImmutableMap;
24 import com.google.common.collect.ImmutableSet;
25 import java.util.function.Function;
26 import java.util.stream.Stream;
27 import org.eclipse.jdt.annotation.NonNull;
28 import org.opendaylight.openflowplugin.api.OFConstants;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchArbitraryBitMask;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4Match;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
47 import org.opendaylight.yangtools.yang.common.Uint8;
50 * Utility class for match normalization.
52 public final class MatchNormalizationUtil {
53 // Cache normalizers for common OpenFlow versions
54 private static final ImmutableMap<Uint8, ImmutableSet<Function<MatchBuilder, MatchBuilder>>> COMMON_NORMALIZERS =
55 ImmutableMap.<Uint8, ImmutableSet<Function<MatchBuilder, MatchBuilder>>>builder()
56 .put(OFConstants.OFP_VERSION_1_0,
57 createNormalizers(OFConstants.OFP_VERSION_1_0).collect(ImmutableSet.toImmutableSet()))
58 .put(OFConstants.OFP_VERSION_1_3,
59 createNormalizers(OFConstants.OFP_VERSION_1_3).collect(ImmutableSet.toImmutableSet()))
61 private static final LoadingCache<Uint8, ImmutableSet<Function<MatchBuilder, MatchBuilder>>> UNCOMMON_NORMALIZERS =
62 CacheBuilder.newBuilder().weakValues().build(new CacheLoader<>() {
64 public ImmutableSet<Function<MatchBuilder, MatchBuilder>> load(final Uint8 key) {
65 return createNormalizers(key).collect(ImmutableSet.toImmutableSet());
69 private MatchNormalizationUtil() {
76 * @param match the OpenFlow match
77 * @param version the OpenFlow version
78 * @return normalized OpenFlow match
80 public static @NonNull Match normalizeMatch(@NonNull final Match match, final Uint8 version) {
81 final var matchBuilder = new MatchBuilder(match);
83 var normalizers = COMMON_NORMALIZERS.get(version);
84 if (normalizers == null) {
85 normalizers = UNCOMMON_NORMALIZERS.getUnchecked(version);
87 normalizers.forEach(normalizer -> normalizer.apply(matchBuilder));
89 return matchBuilder.build();
92 private static @NonNull Stream<Function<MatchBuilder, MatchBuilder>> createNormalizers(final Uint8 version) {
94 MatchNormalizationUtil::normalizeExtensionMatch,
95 MatchNormalizationUtil::normalizeEthernetMatch,
96 MatchNormalizationUtil::normalizeArpMatch,
97 MatchNormalizationUtil::normalizeTunnelIpv4Match,
98 MatchNormalizationUtil::normalizeIpv4Match,
99 MatchNormalizationUtil::normalizeIpv4MatchArbitraryBitMask,
100 MatchNormalizationUtil::normalizeIpv6Match,
101 MatchNormalizationUtil::normalizeIpv6MatchArbitraryBitMask,
102 match -> normalizeInPortMatch(match, version),
103 match -> normalizeInPhyPortMatch(match, version));
106 private static @NonNull MatchBuilder normalizeExtensionMatch(@NonNull final MatchBuilder match) {
107 return new MatchBuilder(MatchUtil.transformMatch(match.build(), Match.class));
111 static @NonNull MatchBuilder normalizeInPortMatch(final @NonNull MatchBuilder match, final Uint8 version) {
112 final var inPort = match.getInPort();
113 if (inPort != null) {
114 final var inPortUri = normalizeProtocolAgnosticPort(inPort, version);
115 if (inPortUri != null) {
116 match.setInPort(new NodeConnectorId(inPortUri));
123 static @NonNull MatchBuilder normalizeInPhyPortMatch(final @NonNull MatchBuilder match, final Uint8 version) {
124 final var inPhyPort = match.getInPhyPort();
125 if (inPhyPort != null) {
126 final var inPhyPortUri = normalizeProtocolAgnosticPort(inPhyPort, version);
127 if (inPhyPortUri != null) {
128 match.setInPhyPort(new NodeConnectorId(inPhyPortUri));
135 static @NonNull MatchBuilder normalizeArpMatch(final @NonNull MatchBuilder match) {
136 if (match.getLayer3Match() instanceof ArpMatch arp) {
137 final var builder = new ArpMatchBuilder(arp)
138 .setArpSourceTransportAddress(normalizeIpv4Prefix(arp.getArpSourceTransportAddress()))
139 .setArpTargetTransportAddress(normalizeIpv4Prefix(arp.getArpTargetTransportAddress()));
141 final var arpSource = arp.getArpSourceHardwareAddress();
142 if (arpSource != null) {
143 builder.setArpSourceHardwareAddress(new ArpSourceHardwareAddressBuilder(arpSource)
144 .setAddress(normalizeMacAddress(arpSource.getAddress()))
145 .setMask(normalizeMacAddress(arpSource.getMask()))
148 final var arpTarget = arp.getArpTargetHardwareAddress();
149 if (arpTarget != null) {
150 builder.setArpTargetHardwareAddress(new ArpTargetHardwareAddressBuilder(arpTarget)
151 .setAddress(normalizeMacAddress(arpTarget.getAddress()))
152 .setMask(normalizeMacAddress(arpTarget.getMask()))
155 match.setLayer3Match(builder.build());
161 static @NonNull MatchBuilder normalizeTunnelIpv4Match(final @NonNull MatchBuilder match) {
162 if (match.getLayer3Match() instanceof TunnelIpv4Match tunnelIpv4) {
163 match.setLayer3Match(new TunnelIpv4MatchBuilder(tunnelIpv4)
164 .setTunnelIpv4Source(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Source()))
165 .setTunnelIpv4Destination(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Destination()))
172 static @NonNull MatchBuilder normalizeIpv4Match(final @NonNull MatchBuilder match) {
173 if (match.getLayer3Match() instanceof Ipv4Match ipv4) {
174 match.setLayer3Match(new Ipv4MatchBuilder(ipv4)
175 .setIpv4Source(normalizeIpv4Prefix(ipv4.getIpv4Source()))
176 .setIpv4Destination(normalizeIpv4Prefix(ipv4.getIpv4Destination()))
184 static MatchBuilder normalizeIpv4MatchArbitraryBitMask(final @NonNull MatchBuilder match) {
185 if (match.getLayer3Match() instanceof Ipv4MatchArbitraryBitMask ipv4arbitrary) {
186 match.setLayer3Match(new Ipv4MatchBuilder()
187 .setIpv4Source(normalizeIpv4Arbitrary(
188 ipv4arbitrary.getIpv4SourceAddressNoMask(),
189 ipv4arbitrary.getIpv4SourceArbitraryBitmask()))
190 .setIpv4Destination(normalizeIpv4Arbitrary(
191 ipv4arbitrary.getIpv4DestinationAddressNoMask(),
192 ipv4arbitrary.getIpv4DestinationArbitraryBitmask()))
199 static @NonNull MatchBuilder normalizeIpv6Match(final @NonNull MatchBuilder match) {
200 if (match.getLayer3Match() instanceof Ipv6Match ipv6) {
201 match.setLayer3Match(new Ipv6MatchBuilder(ipv6)
202 .setIpv6NdSll(normalizeMacAddress(ipv6.getIpv6NdSll()))
203 .setIpv6NdTll(normalizeMacAddress(ipv6.getIpv6NdTll()))
204 .setIpv6NdTarget(normalizeIpv6AddressWithoutMask(ipv6.getIpv6NdTarget()))
205 .setIpv6Source(normalizeIpv6Prefix(ipv6.getIpv6Source()))
206 .setIpv6Destination(normalizeIpv6Prefix(ipv6.getIpv6Destination()))
213 static @NonNull MatchBuilder normalizeIpv6MatchArbitraryBitMask(final @NonNull MatchBuilder match) {
214 if (match.getLayer3Match() instanceof Ipv6MatchArbitraryBitMask ipv6Arbitrary) {
215 match.setLayer3Match(new Ipv6MatchBuilder()
216 .setIpv6Source(normalizeIpv6Arbitrary(
217 ipv6Arbitrary.getIpv6SourceAddressNoMask(),
218 ipv6Arbitrary.getIpv6SourceArbitraryBitmask()))
219 .setIpv6Destination(normalizeIpv6Arbitrary(
220 ipv6Arbitrary.getIpv6DestinationAddressNoMask(),
221 ipv6Arbitrary.getIpv6DestinationArbitraryBitmask()))
228 static @NonNull MatchBuilder normalizeEthernetMatch(final @NonNull MatchBuilder match) {
229 final var eth = match.getEthernetMatch();
231 final var builder = new EthernetMatchBuilder(eth);
232 final var source = eth.getEthernetSource();
233 if (source != null) {
234 builder.setEthernetSource(new EthernetSourceBuilder(source)
235 .setAddress(normalizeMacAddress(source.getAddress()))
236 .setMask(normalizeMacAddressMask(source.getMask()))
239 final var dest = eth.getEthernetDestination();
241 builder.setEthernetDestination(new EthernetDestinationBuilder(dest)
242 .setAddress(normalizeMacAddress(dest.getAddress()))
243 .setMask(normalizeMacAddressMask(dest.getMask()))
246 match.setEthernetMatch(builder.build());