Merge "DeviceManager holds deviceContexts registry"
[openflowplugin.git] / applications / statistics-manager / src / main / java / org / opendaylight / openflowplugin / applications / statistics / manager / impl / helper / FlowComparatorFactory.java
1 /*
2  * Copyright IBM Corporation, 2013.  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 package org.opendaylight.openflowplugin.applications.statistics.manager.impl.helper;
9
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
14
15 public final class FlowComparatorFactory {
16
17     private FlowComparatorFactory() {
18         // NOOP
19     }
20
21     private static final Collection<SimpleComparator<Match>> MATCH_COMPARATORS = new ArrayList<>();
22     static {
23         MATCH_COMPARATORS.add(MatchComparatorFactory.createEthernet());
24         MATCH_COMPARATORS.add(MatchComparatorFactory.createIcmpv4());
25         MATCH_COMPARATORS.add(MatchComparatorFactory.createInPhyPort());
26         MATCH_COMPARATORS.add(MatchComparatorFactory.createInPort());
27         MATCH_COMPARATORS.add(MatchComparatorFactory.createIp());
28         MATCH_COMPARATORS.add(MatchComparatorFactory.createL3());
29         MATCH_COMPARATORS.add(MatchComparatorFactory.createL4());
30         MATCH_COMPARATORS.add(MatchComparatorFactory.createProtocolMatchFields());
31         MATCH_COMPARATORS.add(MatchComparatorFactory.createMetadata());
32         MATCH_COMPARATORS.add(MatchComparatorFactory.createNull());
33         MATCH_COMPARATORS.add(MatchComparatorFactory.createTunnel());
34         MATCH_COMPARATORS.add(MatchComparatorFactory.createVlan());
35     }
36
37     public static SimpleComparator<Flow> createContainerName() {
38         return new SimpleComparator<Flow>() {
39             /**
40              * Compares flows by container name
41              */
42             @Override
43             public boolean areObjectsEqual(Flow statsFlow, Flow storedFlow) {
44                 if (statsFlow.getContainerName() == null) {
45                     if (storedFlow.getContainerName() != null) {
46                         return false;
47                     }
48                 } else if (!statsFlow.getContainerName().equals(storedFlow.getContainerName())) {
49                     return false;
50                 }
51                 return true;
52             }
53         };
54     }
55
56     public static SimpleComparator<Flow> createPriority() {
57         return new SimpleComparator<Flow>() {
58             /**
59              * Compares flows by priority
60              */
61             @Override
62             public boolean areObjectsEqual(final Flow statsFlow, final Flow storedFlow) {
63                 if (storedFlow.getPriority() == null) {
64                     if (statsFlow.getPriority() != null && statsFlow.getPriority() != 0x8000) {
65                         return false;
66                     }
67                 } else if (!statsFlow.getPriority().equals(storedFlow.getPriority())) {
68                     return false;
69                 }
70                 return true;
71             }
72         };
73     }
74
75     public static SimpleComparator<Flow> createTableId() {
76         return new SimpleComparator<Flow>() {
77             /**
78              * Compares flows by table ID
79              */
80             @Override
81             public boolean areObjectsEqual(final Flow statsFlow, final Flow storedFlow) {
82                 if (statsFlow.getTableId() == null) {
83                     if (storedFlow.getTableId() != null) {
84                         return false;
85                     }
86                 } else if (!statsFlow.getTableId().equals(storedFlow.getTableId())) {
87                     return false;
88                 }
89                 return true;
90             }
91         };
92     }
93
94     public static SimpleComparator<Flow> createCookie() {
95         return new SimpleComparator<Flow>() {
96             /**
97              * Compares flows by cookie value
98              */
99             @Override
100             public boolean areObjectsEqual(final Flow statsFlow, final Flow storedFlow) {
101                 if (statsFlow.getCookie() == null) {
102                     if (storedFlow.getCookie() != null) {
103                         return false;
104                     }
105                 } else if (!statsFlow.getCookie().equals(storedFlow.getCookie())) {
106                     return false;
107                 }
108                 return true;
109             }
110         };
111     }
112
113     public static SimpleComparator<Flow> createMatch() {
114         return new SimpleComparator<Flow>() {
115             /**
116              * Compares flows by whole match
117              */
118             @Override
119             public boolean areObjectsEqual(final Flow statsFlow, final Flow storedFlow) {
120                 if (statsFlow.getMatch() == null) {
121                     if (storedFlow.getMatch() != null) {
122                         return false;
123                     }
124                 } else if (!compareMatches(statsFlow.getMatch(), storedFlow.getMatch())) {
125                     return false;
126                 }
127                 return true;
128             }
129         };
130     }
131
132
133     /**
134      * Explicit equals method to compare the 'match' for flows stored in the data-stores and flow fetched from the switch.
135      * Flow installation process has three steps
136      * 1) Store flow in config data store
137      * 2) and send it to plugin for installation
138      * 3) Flow gets installed in switch
139      *
140      * The flow user wants to install and what finally gets installed in switch can be slightly different.
141      * E.g, If user installs flow with src/dst ip=10.0.0.1/24, when it get installed in the switch
142      * src/dst ip will be changes to 10.0.0.0/24 because of netmask of 24. When statistics manager fetch
143      * stats it gets 10.0.0.0/24 rather then 10.0.0.1/24. Custom match takes care of by using masked ip
144      * while comparing two ip addresses.
145      *
146      * Sometimes when user don't provide few values that is required by flow installation request, like
147      * priority,hard timeout, idle timeout, cookies etc, plugin usages default values before sending
148      * request to the switch. So when statistics manager gets flow statistics, it gets the default value.
149      * But the flow stored in config data store don't have those defaults value. I included those checks
150      * in the customer flow/match equal function.
151      *
152      *
153      * @param statsMatch
154      * @param storedMatch
155      * @return
156      */
157     private static boolean compareMatches(final Match statsMatch, final Match storedMatch) {
158         if (statsMatch == storedMatch) {
159             return true;
160         }
161
162         for (SimpleComparator<Match> matchComp : MATCH_COMPARATORS) {
163             if (!matchComp.areObjectsEqual(statsMatch, storedMatch)) {
164                 return false;
165             }
166         }
167         return true;
168     }
169 }