Fixup Augmentable and Identifiable methods changing
[netvirt.git] / statistics / impl / src / main / java / org / opendaylight / netvirt / statistics / CountersServiceUtils.java
1 /*
2  * Copyright (c) 2017 HPE, 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.netvirt.statistics;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.atomic.AtomicLong;
14 import org.opendaylight.genius.mdsalutil.ActionInfo;
15 import org.opendaylight.genius.mdsalutil.InstructionInfo;
16 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
17 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
20 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
21 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
22 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
23 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
24 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
25 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Destination;
26 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source;
27 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
28 import org.opendaylight.genius.mdsalutil.matches.MatchTcpDestinationPort;
29 import org.opendaylight.genius.mdsalutil.matches.MatchTcpSourcePort;
30 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
31 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
32 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
33 import org.opendaylight.genius.utils.ServiceIndex;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.EgressElementCountersRequestConfig;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.IngressElementCountersRequestConfig;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60
61 public final class CountersServiceUtils {
62
63     public static final Long COUNTERS_PULL_END = Long.valueOf(100000);
64     public static final Long COUNTERS_PULL_START = Long.valueOf(1);
65     public static final short COUNTER_TABLE_COUNTER_FLOW_PRIORITY = 50;
66     public static final short COUNTER_TABLE_DEFAULT_FLOW_PRIORITY = 1;
67     public static final BigInteger COOKIE_COUNTERS_BASE = new BigInteger("7000000", 16);
68     public static final short EGRESS_COUNTERS_DEFAULT_FLOW_PRIORITY = 50;
69     public static final short INGRESS_COUNTERS_DEFAULT_FLOW_PRIORITY = 2;
70     public static final short EGRESS_COUNTERS_SERVICE_INDEX =
71             ServiceIndex.getIndex(NwConstants.EGRESS_COUNTERS_SERVICE_NAME, NwConstants.EGRESS_COUNTERS_SERVICE_INDEX);
72     public static final short INGRESS_COUNTERS_SERVICE_INDEX = ServiceIndex
73             .getIndex(NwConstants.INGRESS_COUNTERS_SERVICE_NAME, NwConstants.INGRESS_COUNTERS_SERVICE_INDEX);
74
75     public static final String COUNTER_FLOW_NAME = "COUNTER";
76     public static final String COUNTERS_PULL_NAME = "CountersPull";
77     public static final String DEFAULT_EGRESS_COUNTER_FLOW_PREFIX = "Egress_Counters_Default";
78     public static final String DEFAULT_INGRESS_COUNTER_FLOW_PREFIX = "Ingress_Counters_Default";
79     public static final String EGRESS_COUNTER_RESULT_ID = "Incoming Traffic";
80     public static final String INGRESS_COUNTER_RESULT_ID = "Outgoing Traffic";
81
82     public static final InstanceIdentifier<EgressElementCountersRequestConfig> EECRC_IDENTIFIER =
83             InstanceIdentifier.builder(EgressElementCountersRequestConfig.class).build();
84     public static final InstanceIdentifier<IngressElementCountersRequestConfig> IECRC_IDENTIFIER =
85             InstanceIdentifier.builder(IngressElementCountersRequestConfig.class).build();
86
87     private static AtomicLong flowIdInc = new AtomicLong(2);
88
89     private CountersServiceUtils() { }
90
91     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
92             BigInteger cookie, List<Instruction> instructions) {
93         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
94                 .setInstruction(instructions);
95         return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
96                 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
97                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
98     }
99
100     public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short priority,
101             Class<? extends ServiceModeBase> mode) {
102         return InstanceIdentifier.builder(ServiceBindings.class)
103                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, mode))
104                 .child(BoundServices.class, new BoundServicesKey(priority)).build();
105     }
106
107     public static MatchInfoBase buildLPortTagMatch(int lportTag, ElementCountersDirection direction) {
108         if (ElementCountersDirection.INGRESS.equals(direction)) {
109             return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG);
110         } else if (ElementCountersDirection.EGRESS.equals(direction)) {
111             return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
112                     MetaDataUtil.getLportTagMaskForReg6());
113         }
114         return null;
115     }
116
117     public static List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos,
118             ElementCountersDirection direction) {
119         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
120         if (ElementCountersDirection.EGRESS.equals(direction)) {
121             dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
122         }
123
124         List<InstructionInfo> instructions = new ArrayList<>();
125         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
126         instructions.add(new InstructionApplyActions(actionsInfos));
127         return instructions;
128     }
129
130     public static List<MatchInfoBase> getCounterFlowMatch(ElementCountersRequest ecr, int lportTag,
131             ElementCountersDirection direction) {
132         List<MatchInfoBase> matches = new ArrayList<>();
133         if (ecr.isFilterExist(CountersUtils.ELEMENT_COUNTERS_IP_FILTER_GROUP_NAME, CountersUtils.IP_FILTER_NAME)) {
134             String ipFilter = ecr.getFilterFromFilterGroup(CountersUtils.ELEMENT_COUNTERS_IP_FILTER_GROUP_NAME,
135                     CountersUtils.IP_FILTER_NAME);
136             matches.addAll(buildIpMatches(ipFilter, direction));
137         }
138
139         boolean tcpFilterExist = buildTcpMatchIfExists(ecr, matches);
140
141         if (!tcpFilterExist) {
142             buildUdpMatchIfExists(ecr, matches);
143         }
144
145         matches.add(CountersServiceUtils.buildLPortTagMatch(lportTag, direction));
146
147         return matches;
148     }
149
150     public static Short getTableId(ElementCountersDirection direction) {
151         if (ElementCountersDirection.INGRESS.equals(direction)) {
152             return NwConstants.INGRESS_COUNTERS_TABLE;
153         } else if (ElementCountersDirection.EGRESS.equals(direction)) {
154             return NwConstants.EGRESS_COUNTERS_TABLE;
155         }
156         return null;
157     }
158
159     public static NodeRef buildNodeRef(BigInteger dpId) {
160         return new NodeRef(InstanceIdentifier.builder(Nodes.class)
161                 .child(Node.class, new NodeKey(new NodeId(CountersUtils.OF_PREFIX + dpId))).build());
162     }
163
164     public static Flow createFlowOnTable(Match match, int priority, short tableId) {
165         return createFlowOnTable(match, priority, tableId, null, null);
166     }
167
168     public static Flow createFlowOnTable(Match match, int priority, short tableId, BigInteger cookie,
169             Integer timeout) {
170         FlowBuilder fb = new FlowBuilder();
171         if (match != null) {
172             fb.setMatch(match);
173         }
174         FlowId flowId = createFlowId();
175         fb.setTableId(tableId);
176         fb.setIdleTimeout(0).setHardTimeout(0);
177         fb.setId(flowId);
178         if (timeout != null) {
179             fb.setHardTimeout(timeout);
180         }
181         if (cookie != null) {
182             fb.setCookie(new FlowCookie(cookie));
183         }
184
185         fb.setPriority(priority);
186         Flow flow = fb.build();
187         return flow;
188     }
189
190     public static FlowId createFlowId() {
191         return getFlowIdUsingCounter();
192     }
193
194     private static FlowId getFlowIdUsingCounter() {
195         return new FlowId(String.valueOf(flowIdInc.incrementAndGet()));
196     }
197
198     private static boolean buildUdpMatchIfExists(ElementCountersRequest ecr, List<MatchInfoBase> matches) {
199         boolean udpFilterExist = false;
200         if (ecr.isFilterGroupExist(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME)) {
201             udpFilterExist = true;
202             matches.add(MatchIpProtocol.UDP);
203         }
204         if (ecr.isFilterExist(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
205                 CountersUtils.UDP_SRC_PORT_FILTER_NAME)) {
206             Integer udpSrcPort =
207                     Integer.valueOf(ecr.getFilterFromFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
208                             CountersUtils.UDP_SRC_PORT_FILTER_NAME));
209             matches.add(new MatchUdpSourcePort(udpSrcPort));
210         }
211         if (ecr.isFilterExist(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
212                 CountersUtils.UDP_DST_PORT_FILTER_NAME)) {
213             Integer udpDstPort =
214                     Integer.valueOf(ecr.getFilterFromFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
215                             CountersUtils.UDP_DST_PORT_FILTER_NAME));
216             matches.add(new MatchUdpDestinationPort(udpDstPort));
217         }
218
219         return udpFilterExist;
220     }
221
222     private static boolean buildTcpMatchIfExists(ElementCountersRequest ecr, List<MatchInfoBase> matches) {
223         boolean tcpFilterExist = false;
224         if (ecr.isFilterGroupExist(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME)) {
225             tcpFilterExist = true;
226             matches.add(MatchIpProtocol.TCP);
227         }
228         if (ecr.isFilterExist(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
229                 CountersUtils.TCP_SRC_PORT_FILTER_NAME)) {
230             int tcpSrcPort = Integer.parseInt(ecr.getFilterFromFilterGroup(
231                     CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME, CountersUtils.TCP_SRC_PORT_FILTER_NAME));
232             matches.add(new MatchTcpSourcePort(tcpSrcPort));
233         }
234         if (ecr.isFilterExist(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
235                 CountersUtils.TCP_DST_PORT_FILTER_NAME)) {
236             int tcpDstPort = Integer.parseInt(ecr.getFilterFromFilterGroup(
237                     CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME, CountersUtils.TCP_DST_PORT_FILTER_NAME));
238             matches.add(new MatchTcpDestinationPort(tcpDstPort));
239         }
240
241         return tcpFilterExist;
242     }
243
244     private static List<MatchInfoBase> buildIpMatches(String ip, ElementCountersDirection direction) {
245         List<MatchInfoBase> flowMatches = new ArrayList<>();
246         IpAddress ipAddress = new IpAddress(ip.toCharArray());
247         if (ipAddress.getIpv4Address() != null) {
248             flowMatches.add(MatchEthernetType.IPV4);
249             flowMatches.add(direction == ElementCountersDirection.EGRESS
250                     ? new MatchIpv4Source(ipAddress.getIpv4Address().getValue(), "32")
251                     : new MatchIpv4Destination(ipAddress.getIpv4Address().getValue(), "32"));
252         } else {
253             flowMatches.add(MatchEthernetType.IPV6);
254             flowMatches.add(direction == ElementCountersDirection.EGRESS
255                     ? new MatchIpv6Source(ipAddress.getIpv6Address().getValue() + "/128")
256                     : new MatchIpv6Destination(ipAddress.getIpv6Address().getValue() + "/128"));
257         }
258         return flowMatches;
259     }
260
261 }