Correct FlowRegistryKeyFactory
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / registry / flow / FlowRegistryKeyFactory.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. 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 package org.opendaylight.openflowplugin.impl.registry.flow;
9
10 import static java.util.Objects.requireNonNull;
11 import static java.util.Objects.requireNonNullElse;
12
13 import java.util.Objects;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.openflowplugin.api.OFConstants;
16 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
17 import org.opendaylight.openflowplugin.impl.util.MatchNormalizationUtil;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
23 import org.opendaylight.yangtools.yang.common.Uint16;
24 import org.opendaylight.yangtools.yang.common.Uint64;
25 import org.opendaylight.yangtools.yang.common.Uint8;
26
27 public final class FlowRegistryKeyFactory {
28     // Temporary use, we will overwrite this. We do not have a flow ID and are about to make one up
29     // from the contents -- but for that we need a Flow object. But for that we need a FlowId, but
30     // ... so we set a dummy value and overwrite it afterwards.
31     public static final FlowKey DUMMY_FLOW_KEY = new FlowKey(new FlowId("__DUMMY_ID_FOR_ALIEN__"));
32
33     private FlowRegistryKeyFactory() {
34         // Hide implicit constructor
35     }
36
37     public static @NonNull FlowRegistryKey create(final Uint8 version, final @NonNull Flow flow) {
38         //TODO: mandatory flow input values (or default values) should be specified via yang model
39         final Uint8 tableId = requireNonNull(flow.getTableId(), "flow tableId must not be null");
40         final Uint16 priority = requireNonNullElse(flow.getPriority(), OFConstants.DEFAULT_FLOW_PRIORITY);
41         final Uint64 cookie = requireNonNullElse(flow.getCookie(), OFConstants.DEFAULT_FLOW_COOKIE).getValue();
42         Match match = MatchNormalizationUtil.normalizeMatch(
43             requireNonNullElse(flow.getMatch(), OFConstants.EMPTY_MATCH), version);
44         return new FlowRegistryKeyDto(tableId.toJava(), priority.toJava(), cookie, match);
45     }
46
47     private static final class FlowRegistryKeyDto implements FlowRegistryKey {
48         private final short tableId;
49         private final int priority;
50         private final Uint64 cookie;
51         private final Match match;
52
53         private FlowRegistryKeyDto(final short tableId, final int priority, final @NonNull Uint64 cookie,
54                                    final @NonNull Match match) {
55             this.tableId = tableId;
56             this.priority = priority;
57             this.cookie = cookie;
58             this.match = match;
59         }
60
61         @Override
62         public boolean equals(final Object obj) {
63             return this == obj || obj instanceof FlowRegistryKey that
64                 && priority == that.getPriority() && tableId == that.getTableId() && cookie.equals(that.getCookie())
65                 && equalMatch(that.getMatch());
66         }
67
68         private boolean equalMatch(final Match input) {
69             GeneralAugMatchNodesNodeTableFlow thisAug = match.augmentation(GeneralAugMatchNodesNodeTableFlow.class);
70             GeneralAugMatchNodesNodeTableFlow inputAug = input.augmentation(GeneralAugMatchNodesNodeTableFlow.class);
71             if (thisAug != inputAug) {
72                 if (thisAug != null) {
73                     if (inputAug == null) {
74                         return false;
75                     }
76                     if (!Objects.equals(match.getEthernetMatch(), input.getEthernetMatch())) {
77                         return false;
78                     }
79                     if (!Objects.equals(match.getIcmpv4Match(), input.getIcmpv4Match())) {
80                         return false;
81                     }
82                     if (!Objects.equals(match.getIcmpv6Match(), input.getIcmpv6Match())) {
83                         return false;
84                     }
85                     if (!Objects.equals(match.getInPhyPort(), input.getInPhyPort())) {
86                         return false;
87                     }
88                     if (!Objects.equals(match.getInPort(), input.getInPort())) {
89                         return false;
90                     }
91                     if (!Objects.equals(match.getIpMatch(), input.getIpMatch())) {
92                         return false;
93                     }
94                     if (!Objects.equals(match.getLayer3Match(), input.getLayer3Match())) {
95                         return false;
96                     }
97                     if (!Objects.equals(match.getLayer4Match(), input.getLayer4Match())) {
98                         return false;
99                     }
100                     if (!Objects.equals(match.getMetadata(), input.getMetadata())) {
101                         return false;
102                     }
103                     if (!Objects.equals(match.getProtocolMatchFields(), input.getProtocolMatchFields())) {
104                         return false;
105                     }
106                     if (!Objects.equals(match.getTcpFlagsMatch(), input.getTcpFlagsMatch())) {
107                         return false;
108                     }
109                     if (!Objects.equals(match.getTunnel(), input.getTunnel())) {
110                         return false;
111                     }
112                     if (!Objects.equals(match.getVlanMatch(), input.getVlanMatch())) {
113                         return false;
114                     }
115                     for (var inputExtensionList : inputAug.nonnullExtensionList().values()) {
116                         if (!thisAug.nonnullExtensionList().containsValue(inputExtensionList)) {
117                             return false;
118                         }
119                     }
120                 }
121             } else {
122                 return getMatch().equals(input);
123             }
124             return true;
125         }
126
127         @Override
128         public int hashCode() {
129             int result = tableId;
130             result = 31 * result + priority;
131             result = 31 * result + cookie.hashCode();
132             result = 31 * result + match.hashCode();
133             return result;
134         }
135
136         @Override
137         public String toString() {
138             return "FlowRegistryKeyDto{"
139                     + "tableId=" + tableId
140                     + ", priority=" + priority
141                     + ", cookie=" + cookie
142                     + ", match=" + match
143                     + '}';
144         }
145
146         @Override
147         public short getTableId() {
148             return tableId;
149         }
150
151         @Override
152         public int getPriority() {
153             return priority;
154         }
155
156         @Override
157         public Uint64 getCookie() {
158             return cookie;
159         }
160
161         @Override
162         public Match getMatch() {
163             return match;
164         }
165     }
166 }