2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
3 * Copyright (c) 2024 PANTHEON.tech, s.r.o.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl.util;
11 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Arbitrary;
12 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Prefix;
13 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6AddressWithoutMask;
14 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Arbitrary;
15 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Prefix;
16 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddress;
17 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddressMask;
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 org.eclipse.jdt.annotation.NonNull;
24 import org.opendaylight.openflowplugin.api.OFConstants;
25 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchArbitraryBitMask;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4Match;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
44 import org.opendaylight.yangtools.yang.common.Uint8;
47 * Utility class for match normalization.
49 // FIXME: rename to MatchNormalizer, move to FlowRegistryKeyFactory's package and hide
50 public final class MatchNormalizationUtil {
51 public static final @NonNull MatchNormalizationUtil VERSION_1_0 =
52 new MatchNormalizationUtil(OFConstants.OFP_VERSION_1_0);
53 public static final @NonNull MatchNormalizationUtil VERSION_1_3 =
54 new MatchNormalizationUtil(OFConstants.OFP_VERSION_1_3);
55 private static final LoadingCache<Uint8, @NonNull MatchNormalizationUtil> CACHE = CacheBuilder.newBuilder()
56 .weakValues().build(new CacheLoader<>() {
58 public MatchNormalizationUtil load(final Uint8 key) {
59 return new MatchNormalizationUtil(key);
63 private final AddressNormalizationUtil addressNormalizer;
65 private MatchNormalizationUtil(final Uint8 version) {
66 addressNormalizer = AddressNormalizationUtil.ofVersion(OpenflowVersion.ofVersion(version));
69 public static @NonNull MatchNormalizationUtil ofVersion(final Uint8 version) {
70 if (OFConstants.OFP_VERSION_1_3.equals(version)) {
72 } else if (OFConstants.OFP_VERSION_1_0.equals(version)) {
75 return CACHE.getUnchecked(version);
82 * @param match the OpenFlow match
83 * @return normalized OpenFlow match
85 public @NonNull Match normalizeMatch(@NonNull final Match match) {
86 var builder = new MatchBuilder(match);
87 builder = normalizeExtensionMatch(builder);
88 builder = normalizeEthernetMatch(builder);
89 builder = normalizeArpMatch(builder);
90 builder = normalizeTunnelIpv4Match(builder);
91 builder = normalizeIpv4Match(builder);
92 builder = normalizeIpv4MatchArbitraryBitMask(builder);
93 builder = normalizeIpv6Match(builder);
94 builder = normalizeIpv6MatchArbitraryBitMask(builder);
95 builder = normalizeInPortMatch(builder);
96 builder = normalizeInPhyPortMatch(builder);
97 return builder.build();
101 @NonNull MatchBuilder normalizeInPortMatch(final @NonNull MatchBuilder match) {
102 final var inPort = match.getInPort();
103 if (inPort != null) {
104 final var inPortUri = addressNormalizer.normalizeProtocolAgnosticPort(inPort);
105 if (inPortUri != null) {
106 match.setInPort(new NodeConnectorId(inPortUri));
113 @NonNull MatchBuilder normalizeInPhyPortMatch(final @NonNull MatchBuilder match) {
114 final var inPhyPort = match.getInPhyPort();
115 if (inPhyPort != null) {
116 final var inPhyPortUri = addressNormalizer.normalizeProtocolAgnosticPort(inPhyPort);
117 if (inPhyPortUri != null) {
118 match.setInPhyPort(new NodeConnectorId(inPhyPortUri));
125 static @NonNull MatchBuilder normalizeArpMatch(final @NonNull MatchBuilder match) {
126 if (match.getLayer3Match() instanceof ArpMatch arp) {
127 final var builder = new ArpMatchBuilder(arp)
128 .setArpSourceTransportAddress(normalizeIpv4Prefix(arp.getArpSourceTransportAddress()))
129 .setArpTargetTransportAddress(normalizeIpv4Prefix(arp.getArpTargetTransportAddress()));
131 final var arpSource = arp.getArpSourceHardwareAddress();
132 if (arpSource != null) {
133 builder.setArpSourceHardwareAddress(new ArpSourceHardwareAddressBuilder(arpSource)
134 .setAddress(normalizeMacAddress(arpSource.getAddress()))
135 .setMask(normalizeMacAddress(arpSource.getMask()))
138 final var arpTarget = arp.getArpTargetHardwareAddress();
139 if (arpTarget != null) {
140 builder.setArpTargetHardwareAddress(new ArpTargetHardwareAddressBuilder(arpTarget)
141 .setAddress(normalizeMacAddress(arpTarget.getAddress()))
142 .setMask(normalizeMacAddress(arpTarget.getMask()))
145 match.setLayer3Match(builder.build());
151 static @NonNull MatchBuilder normalizeTunnelIpv4Match(final @NonNull MatchBuilder match) {
152 if (match.getLayer3Match() instanceof TunnelIpv4Match tunnelIpv4) {
153 match.setLayer3Match(new TunnelIpv4MatchBuilder(tunnelIpv4)
154 .setTunnelIpv4Source(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Source()))
155 .setTunnelIpv4Destination(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Destination()))
162 static @NonNull MatchBuilder normalizeIpv4Match(final @NonNull MatchBuilder match) {
163 if (match.getLayer3Match() instanceof Ipv4Match ipv4) {
164 match.setLayer3Match(new Ipv4MatchBuilder(ipv4)
165 .setIpv4Source(normalizeIpv4Prefix(ipv4.getIpv4Source()))
166 .setIpv4Destination(normalizeIpv4Prefix(ipv4.getIpv4Destination()))
174 static MatchBuilder normalizeIpv4MatchArbitraryBitMask(final @NonNull MatchBuilder match) {
175 if (match.getLayer3Match() instanceof Ipv4MatchArbitraryBitMask ipv4arbitrary) {
176 match.setLayer3Match(new Ipv4MatchBuilder()
177 .setIpv4Source(normalizeIpv4Arbitrary(
178 ipv4arbitrary.getIpv4SourceAddressNoMask(),
179 ipv4arbitrary.getIpv4SourceArbitraryBitmask()))
180 .setIpv4Destination(normalizeIpv4Arbitrary(
181 ipv4arbitrary.getIpv4DestinationAddressNoMask(),
182 ipv4arbitrary.getIpv4DestinationArbitraryBitmask()))
189 static @NonNull MatchBuilder normalizeIpv6Match(final @NonNull MatchBuilder match) {
190 if (match.getLayer3Match() instanceof Ipv6Match ipv6) {
191 match.setLayer3Match(new Ipv6MatchBuilder(ipv6)
192 .setIpv6NdSll(normalizeMacAddress(ipv6.getIpv6NdSll()))
193 .setIpv6NdTll(normalizeMacAddress(ipv6.getIpv6NdTll()))
194 .setIpv6NdTarget(normalizeIpv6AddressWithoutMask(ipv6.getIpv6NdTarget()))
195 .setIpv6Source(normalizeIpv6Prefix(ipv6.getIpv6Source()))
196 .setIpv6Destination(normalizeIpv6Prefix(ipv6.getIpv6Destination()))
203 static @NonNull MatchBuilder normalizeIpv6MatchArbitraryBitMask(final @NonNull MatchBuilder match) {
204 if (match.getLayer3Match() instanceof Ipv6MatchArbitraryBitMask ipv6Arbitrary) {
205 match.setLayer3Match(new Ipv6MatchBuilder()
206 .setIpv6Source(normalizeIpv6Arbitrary(
207 ipv6Arbitrary.getIpv6SourceAddressNoMask(),
208 ipv6Arbitrary.getIpv6SourceArbitraryBitmask()))
209 .setIpv6Destination(normalizeIpv6Arbitrary(
210 ipv6Arbitrary.getIpv6DestinationAddressNoMask(),
211 ipv6Arbitrary.getIpv6DestinationArbitraryBitmask()))
218 static @NonNull MatchBuilder normalizeEthernetMatch(final @NonNull MatchBuilder match) {
219 final var eth = match.getEthernetMatch();
221 final var builder = new EthernetMatchBuilder(eth);
222 final var source = eth.getEthernetSource();
223 if (source != null) {
224 builder.setEthernetSource(new EthernetSourceBuilder(source)
225 .setAddress(normalizeMacAddress(source.getAddress()))
226 .setMask(normalizeMacAddressMask(source.getMask()))
229 final var dest = eth.getEthernetDestination();
231 builder.setEthernetDestination(new EthernetDestinationBuilder(dest)
232 .setAddress(normalizeMacAddress(dest.getAddress()))
233 .setMask(normalizeMacAddressMask(dest.getMask()))
236 match.setEthernetMatch(builder.build());
241 private static @NonNull MatchBuilder normalizeExtensionMatch(@NonNull final MatchBuilder match) {
242 return new MatchBuilder(MatchUtil.transformMatch(match.build(), Match.class));