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
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;
18 import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeProtocolAgnosticPort;
20 import com.google.common.annotations.VisibleForTesting;
21 import com.google.common.collect.ImmutableMap;
23 import java.util.Optional;
25 import java.util.function.Function;
26 import java.util.stream.Collectors;
27 import java.util.stream.Stream;
28 import org.eclipse.jdt.annotation.NonNull;
29 import org.opendaylight.openflowplugin.api.OFConstants;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchArbitraryBitMask;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4Match;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
50 * Utility class for match normalization.
52 public final class MatchNormalizationUtil {
53 // Cache normalizers for common OpenFlow versions
54 private static final Map<Short, Set<Function<MatchBuilder, MatchBuilder>>> NORMALIZERS = ImmutableMap
55 .<Short, Set<Function<MatchBuilder, MatchBuilder>>>builder()
56 .put(OFConstants.OFP_VERSION_1_0, createNormalizers(OFConstants.OFP_VERSION_1_0)
57 .collect(Collectors.toSet()))
58 .put(OFConstants.OFP_VERSION_1_3, createNormalizers(OFConstants.OFP_VERSION_1_3)
59 .collect(Collectors.toSet()))
62 private MatchNormalizationUtil() {
63 throw new RuntimeException("Creating instance of util classes is prohibited");
69 * @param match the OpenFlow match
70 * @param version the OpenFlow version
71 * @return normalized OpenFlow match
74 public static Match normalizeMatch(@NonNull final Match match, final short version) {
75 final MatchBuilder matchBuilder = new MatchBuilder(match);
77 Optional.ofNullable(NORMALIZERS.get(version))
78 .orElseGet(() -> createNormalizers(version).collect(Collectors.toSet()))
79 .forEach(normalizer -> normalizer.apply(matchBuilder));
81 return matchBuilder.build();
85 private static Stream<Function<MatchBuilder, MatchBuilder>> createNormalizers(final short version) {
87 MatchNormalizationUtil::normalizeExtensionMatch,
88 MatchNormalizationUtil::normalizeEthernetMatch,
89 MatchNormalizationUtil::normalizeArpMatch,
90 MatchNormalizationUtil::normalizeTunnelIpv4Match,
91 MatchNormalizationUtil::normalizeIpv4Match,
92 MatchNormalizationUtil::normalizeIpv4MatchArbitraryBitMask,
93 MatchNormalizationUtil::normalizeIpv6Match,
94 MatchNormalizationUtil::normalizeIpv6MatchArbitraryBitMask,
95 (match) -> normalizeInPortMatch(match, version),
96 (match) -> normalizeInPhyPortMatch(match, version));
100 private static MatchBuilder normalizeExtensionMatch(@NonNull final MatchBuilder match) {
101 return new MatchBuilder(MatchUtil.transformMatch(match.build(), Match.class));
106 static MatchBuilder normalizeInPortMatch(@NonNull final MatchBuilder match, final short version) {
108 .ofNullable(match.getInPort())
109 .flatMap(inPort -> Optional.ofNullable(normalizeProtocolAgnosticPort(inPort, version)))
110 .map(inPortUri -> match.setInPort(new NodeConnectorId(inPortUri)))
116 static MatchBuilder normalizeInPhyPortMatch(@NonNull final MatchBuilder match, final short version) {
118 .ofNullable(match.getInPhyPort())
119 .flatMap(inPhyPort -> Optional.ofNullable(normalizeProtocolAgnosticPort(inPhyPort, version)))
120 .map(inPhyPortUri -> match.setInPhyPort(new NodeConnectorId(inPhyPortUri)))
126 static MatchBuilder normalizeArpMatch(@NonNull final MatchBuilder match) {
128 .ofNullable(match.getLayer3Match())
129 .filter(ArpMatch.class::isInstance)
130 .map(ArpMatch.class::cast)
131 .map(arp -> match.setLayer3Match(new ArpMatchBuilder(arp)
132 .setArpSourceHardwareAddress(Optional
133 .ofNullable(arp.getArpSourceHardwareAddress())
134 .map(arpSource -> new ArpSourceHardwareAddressBuilder(arpSource)
135 .setAddress(normalizeMacAddress(arpSource.getAddress()))
136 .setMask(normalizeMacAddress(arpSource.getMask()))
138 .orElse(arp.getArpSourceHardwareAddress()))
139 .setArpTargetHardwareAddress(Optional
140 .ofNullable(arp.getArpTargetHardwareAddress())
141 .map(arpTarget -> new ArpTargetHardwareAddressBuilder(arpTarget)
142 .setAddress(normalizeMacAddress(arpTarget.getAddress()))
143 .setMask(normalizeMacAddress(arpTarget.getMask()))
145 .orElse(arp.getArpTargetHardwareAddress()))
146 .setArpSourceTransportAddress(normalizeIpv4Prefix(arp.getArpSourceTransportAddress()))
147 .setArpTargetTransportAddress(normalizeIpv4Prefix(arp.getArpTargetTransportAddress()))
156 static MatchBuilder normalizeTunnelIpv4Match(@NonNull final MatchBuilder match) {
158 .ofNullable(match.getLayer3Match())
159 .filter(TunnelIpv4Match.class::isInstance)
160 .map(TunnelIpv4Match.class::cast)
161 .map(tunnelIpv4 -> match.setLayer3Match(new TunnelIpv4MatchBuilder(tunnelIpv4)
162 .setTunnelIpv4Source(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Source()))
163 .setTunnelIpv4Destination(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Destination()))
170 static MatchBuilder normalizeIpv4Match(@NonNull final MatchBuilder match) {
172 .ofNullable(match.getLayer3Match())
173 .filter(Ipv4Match.class::isInstance)
174 .map(Ipv4Match.class::cast)
175 .map(ipv4 -> match.setLayer3Match(new Ipv4MatchBuilder(ipv4)
176 .setIpv4Source(normalizeIpv4Prefix(ipv4.getIpv4Source()))
177 .setIpv4Destination(normalizeIpv4Prefix(ipv4.getIpv4Destination()))
184 static MatchBuilder normalizeIpv4MatchArbitraryBitMask(@NonNull final MatchBuilder match) {
186 .ofNullable(match.getLayer3Match())
187 .filter(Ipv4MatchArbitraryBitMask.class::isInstance)
188 .map(Ipv4MatchArbitraryBitMask.class::cast)
189 .map(ipv4arbitrary -> match.setLayer3Match(new Ipv4MatchBuilder()
190 .setIpv4Source(normalizeIpv4Arbitrary(
191 ipv4arbitrary.getIpv4SourceAddressNoMask(),
192 ipv4arbitrary.getIpv4SourceArbitraryBitmask()))
193 .setIpv4Destination(normalizeIpv4Arbitrary(
194 ipv4arbitrary.getIpv4DestinationAddressNoMask(),
195 ipv4arbitrary.getIpv4DestinationArbitraryBitmask()))
203 static MatchBuilder normalizeIpv6Match(@NonNull final MatchBuilder match) {
205 .ofNullable(match.getLayer3Match())
206 .filter(Ipv6Match.class::isInstance)
207 .map(Ipv6Match.class::cast)
208 .map(ipv6 -> match.setLayer3Match(new Ipv6MatchBuilder(ipv6)
209 .setIpv6NdSll(normalizeMacAddress(ipv6.getIpv6NdSll()))
210 .setIpv6NdTll(normalizeMacAddress(ipv6.getIpv6NdTll()))
211 .setIpv6NdTarget(normalizeIpv6AddressWithoutMask(ipv6.getIpv6NdTarget()))
212 .setIpv6Source(normalizeIpv6Prefix(ipv6.getIpv6Source()))
213 .setIpv6Destination(normalizeIpv6Prefix(ipv6.getIpv6Destination()))
221 static MatchBuilder normalizeIpv6MatchArbitraryBitMask(@NonNull final MatchBuilder match) {
223 .ofNullable(match.getLayer3Match())
224 .filter(Ipv6MatchArbitraryBitMask.class::isInstance)
225 .map(Ipv6MatchArbitraryBitMask.class::cast)
226 .map(ipv6Arbitrary -> match.setLayer3Match(new Ipv6MatchBuilder()
227 .setIpv6Source(normalizeIpv6Arbitrary(
228 ipv6Arbitrary.getIpv6SourceAddressNoMask(),
229 ipv6Arbitrary.getIpv6SourceArbitraryBitmask()))
230 .setIpv6Destination(normalizeIpv6Arbitrary(
231 ipv6Arbitrary.getIpv6DestinationAddressNoMask(),
232 ipv6Arbitrary.getIpv6DestinationArbitraryBitmask()))
239 static MatchBuilder normalizeEthernetMatch(@NonNull final MatchBuilder match) {
241 .ofNullable(match.getEthernetMatch())
242 .map(eth -> match.setEthernetMatch(new EthernetMatchBuilder(eth)
243 .setEthernetSource(Optional
244 .ofNullable(eth.getEthernetSource())
245 .map(filter -> new EthernetSourceBuilder(filter)
246 .setAddress(normalizeMacAddress(filter.getAddress()))
247 .setMask(normalizeMacAddressMask(filter.getMask()))
249 .orElse(eth.getEthernetSource()))
250 .setEthernetDestination(Optional
251 .ofNullable(eth.getEthernetDestination())
252 .map(filter -> new EthernetDestinationBuilder(filter)
253 .setAddress(normalizeMacAddress(filter.getAddress()))
254 .setMask(normalizeMacAddressMask(filter.getMask()))
256 .orElse(eth.getEthernetDestination()))