blob: f130732dc71a14022eddf349449566f2bc0f67fa [file] [log] [blame]
hjtsao1e8a1bd2018-10-22 11:02:00 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.drivers.p4runtime;
17
18import org.onosproject.net.DeviceId;
19import org.onosproject.net.behaviour.TableStatisticsDiscovery;
20import org.onosproject.net.flow.FlowRuleService;
21import org.onosproject.net.flow.FlowEntry;
22import org.onosproject.net.flow.TableId;
23import org.onosproject.net.flow.IndexTableId;
24import org.onosproject.net.flow.TableStatisticsEntry;
25import org.onosproject.net.flow.DefaultTableStatisticsEntry;
26import org.onosproject.net.pi.model.PiPipelineModel;
27import org.onosproject.net.pi.model.PiPipelineInterpreter;
28import org.onosproject.net.pi.model.PiTableId;
29import org.onosproject.net.pi.model.PiTableModel;
30
31import java.util.List;
32import java.util.Collections;
33import java.util.Map;
34import java.util.HashMap;
35import java.util.Iterator;
36import java.util.ArrayList;
37
38import static com.google.common.collect.Lists.newArrayList;
39
40/**
41 * Implementation of behaviour TableStatisticsDiscovery for P4Runtime.
42 */
43public class P4RuntimeTableStatisticsDiscovery extends AbstractP4RuntimeHandlerBehaviour
44 implements TableStatisticsDiscovery {
45
46 @Override
47 public List<TableStatisticsEntry> getTableStatistics() {
48 if (!setupBehaviour()) {
49 return Collections.emptyList();
50 }
51 FlowRuleService flowService = handler().get(FlowRuleService.class);
52 PiPipelineInterpreter interpreter = getInterpreter();
53 PiPipelineModel model = pipeconf.pipelineModel();
54 List<TableStatisticsEntry> tableStatsList;
55
56 List<FlowEntry> rules = newArrayList(flowService.getFlowEntries(deviceId));
57 Map<PiTableId, Integer> piTableFlowCount = piFlowRuleCounting(model, interpreter, rules);
58 Map<PiTableId, Long> piTableMatchCount = piMatchedCounting(model, interpreter, rules);
59 tableStatsList = generatePiFlowTableStatistics(piTableFlowCount, piTableMatchCount, model, deviceId);
60
61 return tableStatsList;
62 }
63
64 /**
65 * Returns the number of added flows in each table.
66 *
67 * @param model pipeline model
68 * @param interpreter pipeline interpreter
69 * @param rules flow rules in this device
70 * @return hashmap containing matched packet counting for each table
71 */
72 private Map<PiTableId, Integer> piFlowRuleCounting(PiPipelineModel model, PiPipelineInterpreter interpreter,
73 List<FlowEntry> rules) {
74 Map<PiTableId, Integer> piTableFlowCount = new HashMap<>();
75 for (PiTableModel tableModel : model.tables()) {
76 piTableFlowCount.put(tableModel.id(), 0);
77 }
78 for (FlowEntry f : rules) {
79 if (f.state() == FlowEntry.FlowEntryState.ADDED) {
80 PiTableId piTableId = getPiTableId(f, interpreter);
81 if (piTableId != null) {
82 piTableFlowCount.put(piTableId, piTableFlowCount.get(piTableId) + 1);
83 }
84 }
85 }
86 return piTableFlowCount;
87 }
88
89 /**
90 * Returns the number of matched packets for each table.
91 *
92 * @param model pipeline model
93 * @param interpreter pipeline interpreter
94 * @param rules flow rules in this device
95 * @return hashmap containing flow rule counting for each table
96 */
97 private Map<PiTableId, Long> piMatchedCounting(PiPipelineModel model, PiPipelineInterpreter interpreter,
98 List<FlowEntry> rules) {
99 Map<PiTableId, Long> piTableMatchCount = new HashMap<>();
100 for (PiTableModel tableModel : model.tables()) {
101 piTableMatchCount.put(tableModel.id(), (long) 0);
102 }
103 for (FlowEntry f : rules) {
104 if (f.state() == FlowEntry.FlowEntryState.ADDED) {
105 PiTableId piTableId = getPiTableId(f, interpreter);
106 if (piTableId != null) {
107 piTableMatchCount.put(piTableId, piTableMatchCount.get(piTableId) + f.packets());
108 }
109 }
110 }
111 return piTableMatchCount;
112 }
113
114 /**
115 * Returns the PiTableId of the pipeline independent table that contains the flow rule. If null is returned, it
116 * means that the given flow rule's table ID is index table ID without a mapping with a pipeline independent table
117 * ID.
118 *
119 * @param flowEntry flow rule
120 * @param interpreter pipeline interpreter
121 * @return PiTableId of the table containing input FlowEntry or null
122 */
123 private PiTableId getPiTableId(FlowEntry flowEntry, PiPipelineInterpreter interpreter) {
124 return flowEntry.table().type() == TableId.Type.PIPELINE_INDEPENDENT ? (PiTableId) flowEntry.table() :
125 interpreter.mapFlowRuleTableId(((IndexTableId) flowEntry.table()).id()).orElse(null);
126 }
127
128 /**
129 * Returns the list of table statistics for P4 switch.
130 *
131 * @param piTableFlowCount hashmap containing the number of flow rules for each table
132 * @param piTableMatchCount hashmap containing the number of matched packets for each table
133 * @param model pipeline model
134 * @param deviceId device ID
135 * @return list of table statistics for P4 switch
136 */
137 private List<TableStatisticsEntry> generatePiFlowTableStatistics(Map<PiTableId, Integer> piTableFlowCount,
138 Map<PiTableId, Long> piTableMatchCount,
139 PiPipelineModel model, DeviceId deviceId) {
140 List<TableStatisticsEntry> tableStatsList;
141 Iterator it = piTableFlowCount.entrySet().iterator();
142 tableStatsList = new ArrayList<>();
143 while (it.hasNext()) {
144 Map.Entry pair = (Map.Entry) it.next();
145 TableStatisticsEntry tableStat = DefaultTableStatisticsEntry.builder()
146 .withDeviceId(deviceId)
147 .withTableId((PiTableId) pair.getKey())
148 .withActiveFlowEntries(piTableFlowCount.get(pair.getKey()))
149 .withPacketsMatchedCount(piTableMatchCount.get(pair.getKey()))
150 .withMaxSize(model.table((PiTableId) pair.getKey()).get().maxSize()).build();
151 tableStatsList.add(tableStat);
152 it.remove();
153 }
154 return tableStatsList;
155 }
156}