8c3b48e0fdec1fa10294f57c90eb9f08826fb248
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / util / MatchComparatorFactory.java
1 /*
2  * Copyright (c) 2013, 2015 IBM Corporation 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 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15
16 /**
17  * Provides comparator for comparing according to various {@link Match} attributes
18  *
19  */
20 public final class MatchComparatorFactory {
21
22     private MatchComparatorFactory() {
23         // NOOP
24     }
25
26     private static final Collection<SimpleComparator<Match>> MATCH_COMPARATORS = new ArrayList<>();
27     static {
28         MATCH_COMPARATORS.add(MatchComparatorFactory.createEthernet());
29         MATCH_COMPARATORS.add(MatchComparatorFactory.createIcmpv4());
30         MATCH_COMPARATORS.add(MatchComparatorFactory.createInPhyPort());
31         MATCH_COMPARATORS.add(MatchComparatorFactory.createInPort());
32         MATCH_COMPARATORS.add(MatchComparatorFactory.createIp());
33         MATCH_COMPARATORS.add(MatchComparatorFactory.createL3());
34         MATCH_COMPARATORS.add(MatchComparatorFactory.createL4());
35         MATCH_COMPARATORS.add(MatchComparatorFactory.createProtocolMatchFields());
36         MATCH_COMPARATORS.add(MatchComparatorFactory.createMetadata());
37         MATCH_COMPARATORS.add(MatchComparatorFactory.createNull());
38         MATCH_COMPARATORS.add(MatchComparatorFactory.createTunnel());
39         MATCH_COMPARATORS.add(MatchComparatorFactory.createVlan());
40     }
41
42     public static SimpleComparator<Match> createNull() {
43         return new SimpleComparator<Match>() {
44             /**
45              * Comparation by whole object
46              */
47             @Override
48             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
49                 return (statsMatch == null) == (storedMatch == null);
50             }
51         };
52     }
53
54     public static SimpleComparator<Match> createVlan() {
55         return new SimpleComparator<Match>() {
56             /**
57              * Comparation by VLAN
58              */
59             @Override
60             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
61                 if (storedMatch == null) {
62                     return false;
63                 }
64                 if (storedMatch.getVlanMatch() == null) {
65                     if (statsMatch.getVlanMatch() != null) {
66                         return false;
67                     }
68                 } else if (!storedMatch.getVlanMatch().equals(statsMatch.getVlanMatch())) {
69                     return false;
70                 }
71                 return true;
72             }
73         };
74     }
75
76     public static SimpleComparator<Match> createTunnel() {
77         return new SimpleComparator<Match>() {
78             /**
79              * Comparation by tunnel
80              */
81             @Override
82             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
83                 if (storedMatch == null) {
84                     return false;
85                 }
86                 if (storedMatch.getTunnel() == null) {
87                     if (statsMatch.getTunnel() != null) {
88                         return false;
89                     }
90                 } else if (!storedMatch.getTunnel().equals(statsMatch.getTunnel())) {
91                     return false;
92                 }
93                 return true;
94             }
95         };
96     }
97
98     public static SimpleComparator<Match> createProtocolMatchFields() {
99         return new SimpleComparator<Match>() {
100             /**
101              * Comparation by protocol fields
102              */
103             @Override
104             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
105                 if (storedMatch == null) {
106                     return false;
107                 }
108                 if (storedMatch.getProtocolMatchFields() == null) {
109                     if (statsMatch.getProtocolMatchFields() != null) {
110                         return false;
111                     }
112                 } else if (!storedMatch.getProtocolMatchFields().equals(statsMatch.getProtocolMatchFields())) {
113                     return false;
114                 }
115                 return true;
116             }
117         };
118     }
119
120     public static SimpleComparator<Match> createMetadata() {
121         return new SimpleComparator<Match>() {
122             /**
123              * Comparation by metadata
124              */
125             @Override
126             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
127                 if (storedMatch == null) {
128                     return false;
129                 }
130                 if (storedMatch.getMetadata() == null) {
131                     if (statsMatch.getMetadata() != null) {
132                         return false;
133                     }
134                 } else if (!storedMatch.getMetadata().equals(statsMatch.getMetadata())) {
135                     return false;
136                 }
137                 return true;
138             }
139         };
140     }
141
142     public static SimpleComparator<Match> createL4() {
143         return new SimpleComparator<Match>() {
144             /**
145              * Comparation by layer4
146              */
147             @Override
148             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
149                 if (storedMatch == null) {
150                     return false;
151                 }
152                 if (storedMatch.getLayer4Match() == null) {
153                     if (statsMatch.getLayer4Match() != null) {
154                         return false;
155                     }
156                 } else if (!storedMatch.getLayer4Match().equals(statsMatch.getLayer4Match())) {
157                     return false;
158                 }
159                 return true;
160             }
161         };
162     }
163
164     public static SimpleComparator<Match> createL3() {
165         return new SimpleComparator<Match>() {
166             /**
167              * Comparation by layer3
168              */
169             @Override
170             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
171                 if (storedMatch == null) {
172                     return false;
173                 }
174                 if (storedMatch.getLayer3Match() == null) {
175                     if (statsMatch.getLayer3Match() != null) {
176                         return false;
177                     }
178                 } else if (!MatchComparatorHelper.layer3MatchEquals(statsMatch.getLayer3Match(), storedMatch.getLayer3Match())) {
179                     return false;
180                 }
181                 return true;
182             }
183         };
184     }
185
186     public static SimpleComparator<Match> createIp() {
187         return new SimpleComparator<Match>() {
188             /**
189              * Comparation by Ip
190              */
191             @Override
192             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
193                 if (storedMatch == null) {
194                     return false;
195                 }
196                 if (storedMatch.getIpMatch() == null) {
197                     if (statsMatch.getIpMatch() != null) {
198                         return false;
199                     }
200                 } else if (!storedMatch.getIpMatch().equals(statsMatch.getIpMatch())) {
201                     return false;
202                 }
203                 return true;
204             }
205         };
206     }
207
208     public static SimpleComparator<Match> createInPort() {
209         return new SimpleComparator<Match>() {
210             /**
211              * Comparation by InPort
212              */
213             @Override
214             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
215                 if (storedMatch == null) {
216                     return false;
217                 }
218                 if (storedMatch.getInPort() == null) {
219                     if (statsMatch.getInPort() != null) {
220                         return false;
221                     }
222                 } else if (!storedMatch.getInPort().equals(statsMatch.getInPort())) {
223                     return false;
224                 }
225                 return true;
226             }
227         };
228     }
229
230     public static SimpleComparator<Match> createInPhyPort() {
231         return new SimpleComparator<Match>() {
232             /**
233              * Comparation by InPhyPort
234              */
235             @Override
236             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
237                 if (storedMatch == null) {
238                     return false;
239                 }
240                 if (storedMatch.getInPhyPort() == null) {
241                     if (statsMatch.getInPhyPort() != null) {
242                         return false;
243                     }
244                 } else if (!storedMatch.getInPhyPort().equals(statsMatch.getInPhyPort())) {
245                     return false;
246                 }
247                 return true;
248             }
249         };
250     }
251
252     public static SimpleComparator<Match> createEthernet() {
253         return new SimpleComparator<Match>() {
254             /**
255              * Comparation by Ethernet
256              */
257             @Override
258             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
259                 if (storedMatch == null) {
260                     return false;
261                 }
262                 if (storedMatch.getEthernetMatch() == null) {
263                     if (statsMatch.getEthernetMatch() != null) {
264                         return false;
265                     }
266                 } else if (!MatchComparatorHelper.ethernetMatchEquals(statsMatch.getEthernetMatch(), storedMatch.getEthernetMatch())) {
267                     return false;
268                 }
269                 return true;
270             }
271         };
272     }
273
274     public static SimpleComparator<Match> createIcmpv4() {
275         return new SimpleComparator<Match>() {
276             /**
277              * Comparation by Icmpv4
278              */
279             @Override
280             public boolean areObjectsEqual(Match statsMatch, Match storedMatch) {
281                 if (storedMatch == null) {
282                     return false;
283                 }
284                 if (storedMatch.getIcmpv4Match() == null) {
285                     if (statsMatch.getIcmpv4Match() != null) {
286                         return false;
287                     }
288                 } else if (!storedMatch.getIcmpv4Match().equals(statsMatch.getIcmpv4Match())) {
289                     return false;
290                 }
291                 return true;
292             }
293         };
294     }
295
296     public static SimpleComparator<Match> createMatch() {
297         return new SimpleComparator<Match>() {
298             /**
299              * Compares flows by whole match
300              */
301             @Override
302             public boolean areObjectsEqual(final Match statsFlow, final Match storedFlow) {
303                 if (statsFlow == null) {
304                     if (storedFlow != null) {
305                         return false;
306                     }
307                 } else if (!compareMatches(statsFlow, storedFlow)) {
308                     return false;
309                 }
310                 return true;
311             }
312         };
313     }
314
315
316     /**
317      * Explicit equals method to compare the 'match' for flows stored in the data-stores and flow fetched from the switch.
318      * Flow installation process has three steps
319      * 1) Store flow in config data store
320      * 2) and send it to plugin for installation
321      * 3) Flow gets installed in switch
322      *
323      * The flow user wants to install and what finally gets installed in switch can be slightly different.
324      * E.g, If user installs flow with src/dst ip=10.0.0.1/24, when it get installed in the switch
325      * src/dst ip will be changes to 10.0.0.0/24 because of netmask of 24. When statistics manager fetch
326      * stats it gets 10.0.0.0/24 rather then 10.0.0.1/24. Custom match takes care of by using masked ip
327      * while comparing two ip addresses.
328      *
329      * Sometimes when user don't provide few values that is required by flow installation request, like
330      * priority,hard timeout, idle timeout, cookies etc, plugin usages default values before sending
331      * request to the switch. So when statistics manager gets flow statistics, it gets the default value.
332      * But the flow stored in config data store don't have those defaults value. I included those checks
333      * in the customer flow/match equal function.
334      *
335      *
336      * @param statsMatch
337      * @param storedMatch
338      * @return
339      */
340     private static boolean compareMatches(final Match statsMatch, final Match storedMatch) {
341         if (statsMatch == storedMatch) {
342             return true;
343         }
344
345         for (SimpleComparator<Match> matchComp : MATCH_COMPARATORS) {
346             if (!matchComp.areObjectsEqual(statsMatch, storedMatch)) {
347                 return false;
348             }
349         }
350         return true;
351     }
352 }