Cleanup MatchUtil
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / util / MatchNormalizationUtil.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.impl.util;
10
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;
19
20 import com.google.common.annotations.VisibleForTesting;
21 import com.google.common.collect.ImmutableMap;
22 import java.util.Map;
23 import java.util.Optional;
24 import java.util.Set;
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;
48
49 /**
50  * Utility class for match normalization.
51  */
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()))
60             .build();
61
62     private MatchNormalizationUtil() {
63         throw new RuntimeException("Creating instance of util classes is prohibited");
64     }
65
66     /**
67      * Normalize match.
68      *
69      * @param match   the OpenFlow match
70      * @param version the OpenFlow version
71      * @return normalized OpenFlow match
72      */
73     @NonNull
74     public static Match normalizeMatch(@NonNull final Match match, final short version) {
75         final MatchBuilder matchBuilder = new MatchBuilder(match);
76
77         Optional.ofNullable(NORMALIZERS.get(version))
78                 .orElseGet(() -> createNormalizers(version).collect(Collectors.toSet()))
79                 .forEach(normalizer -> normalizer.apply(matchBuilder));
80
81         return matchBuilder.build();
82     }
83
84     @NonNull
85     private static Stream<Function<MatchBuilder, MatchBuilder>> createNormalizers(final short version) {
86         return Stream.of(
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));
97     }
98
99     @NonNull
100     private static MatchBuilder normalizeExtensionMatch(@NonNull final MatchBuilder match) {
101         return new MatchBuilder(MatchUtil.transformMatch(match.build(), Match.class));
102     }
103
104     @NonNull
105     @VisibleForTesting
106     static MatchBuilder normalizeInPortMatch(@NonNull final MatchBuilder match, final short version) {
107         return Optional
108                 .ofNullable(match.getInPort())
109                 .flatMap(inPort -> Optional.ofNullable(normalizeProtocolAgnosticPort(inPort, version)))
110                 .map(inPortUri -> match.setInPort(new NodeConnectorId(inPortUri)))
111                 .orElse(match);
112     }
113
114     @NonNull
115     @VisibleForTesting
116     static MatchBuilder normalizeInPhyPortMatch(@NonNull final MatchBuilder match, final short version) {
117         return Optional
118                 .ofNullable(match.getInPhyPort())
119                 .flatMap(inPhyPort -> Optional.ofNullable(normalizeProtocolAgnosticPort(inPhyPort, version)))
120                 .map(inPhyPortUri -> match.setInPhyPort(new NodeConnectorId(inPhyPortUri)))
121                 .orElse(match);
122     }
123
124     @NonNull
125     @VisibleForTesting
126     static MatchBuilder normalizeArpMatch(@NonNull final MatchBuilder match) {
127         return Optional
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()))
137                                         .build())
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()))
144                                         .build())
145                                 .orElse(arp.getArpTargetHardwareAddress()))
146                         .setArpSourceTransportAddress(normalizeIpv4Prefix(arp.getArpSourceTransportAddress()))
147                         .setArpTargetTransportAddress(normalizeIpv4Prefix(arp.getArpTargetTransportAddress()))
148                         .build())
149                 )
150                 .orElse(match);
151     }
152
153
154     @NonNull
155     @VisibleForTesting
156     static MatchBuilder normalizeTunnelIpv4Match(@NonNull final MatchBuilder match) {
157         return Optional
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()))
164                         .build()))
165                 .orElse(match);
166     }
167
168     @NonNull
169     @VisibleForTesting
170     static MatchBuilder normalizeIpv4Match(@NonNull final MatchBuilder match) {
171         return Optional
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()))
178                         .build()))
179                 .orElse(match);
180     }
181
182     @NonNull
183     @VisibleForTesting
184     static MatchBuilder normalizeIpv4MatchArbitraryBitMask(@NonNull final MatchBuilder match) {
185         return Optional
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()))
196                         .build()))
197                 .orElse(match);
198     }
199
200
201     @NonNull
202     @VisibleForTesting
203     static MatchBuilder normalizeIpv6Match(@NonNull final MatchBuilder match) {
204         return Optional
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()))
214                         .build()))
215                 .orElse(match);
216     }
217
218
219     @NonNull
220     @VisibleForTesting
221     static MatchBuilder normalizeIpv6MatchArbitraryBitMask(@NonNull final MatchBuilder match) {
222         return Optional
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()))
233                         .build()))
234                 .orElse(match);
235     }
236
237     @NonNull
238     @VisibleForTesting
239     static MatchBuilder normalizeEthernetMatch(@NonNull final MatchBuilder match) {
240         return Optional
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()))
248                                         .build())
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()))
255                                         .build())
256                                 .orElse(eth.getEthernetDestination()))
257                         .build()))
258                 .orElse(match);
259     }
260
261 }