blob: bfcdd869d4f0dcf2a6762752055efe4c641df955 [file] [log] [blame]
Carmelo Casconeb045ddc2017-09-01 01:26:35 +02001/*
2 * Copyright 2017-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 */
16
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070017package org.onosproject.pipelines.basic;
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020018
19import com.google.common.collect.Maps;
20import com.google.common.collect.Sets;
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070021import org.onosproject.net.DeviceId;
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020022import org.onosproject.net.device.DefaultPortStatistics;
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070023import org.onosproject.net.device.DeviceService;
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020024import org.onosproject.net.device.PortStatistics;
25import org.onosproject.net.device.PortStatisticsDiscovery;
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070026import org.onosproject.net.driver.AbstractHandlerBehaviour;
Carmelo Cascone87892e22017-11-13 16:01:29 -080027import org.onosproject.net.pi.model.PiCounterId;
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070028import org.onosproject.net.pi.model.PiPipeconf;
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020029import org.onosproject.net.pi.runtime.PiCounterCellData;
30import org.onosproject.net.pi.runtime.PiCounterCellId;
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070031import org.onosproject.net.pi.runtime.PiPipeconfService;
32import org.onosproject.p4runtime.api.P4RuntimeClient;
33import org.onosproject.p4runtime.api.P4RuntimeController;
34import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020036
37import java.util.Collection;
38import java.util.Collections;
39import java.util.Map;
40import java.util.Set;
41import java.util.concurrent.ExecutionException;
42import java.util.stream.Collectors;
43
Carmelo Cascone87892e22017-11-13 16:01:29 -080044import static org.onosproject.net.pi.model.PiCounterType.INDIRECT;
45import static org.onosproject.pipelines.basic.BasicConstants.CNT_EGRESS_PORT_COUNTER_ID;
46import static org.onosproject.pipelines.basic.BasicConstants.CNT_INGRESS_PORT_COUNTER_ID;
Carmelo Cascone7f75be42017-09-07 14:37:02 +020047
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020048/**
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070049 * Implementation of the PortStatisticsBehaviour for basic.p4.
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020050 */
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070051public class PortStatisticsDiscoveryImpl extends AbstractHandlerBehaviour implements PortStatisticsDiscovery {
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020052
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070053 protected final Logger log = LoggerFactory.getLogger(getClass());
54
Carmelo Casconecb0a49c2017-10-03 14:32:23 +020055 /**
Carmelo Cascone2b057522017-10-04 14:35:29 +020056 * Returns the ID of the ingress port counter.
Carmelo Casconecb0a49c2017-10-03 14:32:23 +020057 *
Carmelo Cascone2b057522017-10-04 14:35:29 +020058 * @return counter ID
Carmelo Casconecb0a49c2017-10-03 14:32:23 +020059 */
Carmelo Cascone2b057522017-10-04 14:35:29 +020060 public PiCounterId ingressCounterId() {
Carmelo Cascone87892e22017-11-13 16:01:29 -080061 return CNT_INGRESS_PORT_COUNTER_ID;
Carmelo Cascone2b057522017-10-04 14:35:29 +020062 }
63
64 /**
65 * Returns the ID of the egress port counter.
66 *
67 * @return counter ID
68 */
69 public PiCounterId egressCounterId() {
Carmelo Cascone87892e22017-11-13 16:01:29 -080070 return CNT_EGRESS_PORT_COUNTER_ID;
Carmelo Casconecb0a49c2017-10-03 14:32:23 +020071 }
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020072
73 @Override
74 public Collection<PortStatistics> discoverPortStatistics() {
75
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070076 DeviceService deviceService = this.handler().get(DeviceService.class);
77 DeviceId deviceId = this.data().deviceId();
78
79 PiPipeconfService piPipeconfService = handler().get(PiPipeconfService.class);
80 if (!piPipeconfService.ofDevice(deviceId).isPresent() ||
81 !piPipeconfService.getPipeconf(piPipeconfService.ofDevice(deviceId).get()).isPresent()) {
82 log.warn("Unable to get the pipeconf of {}, aborting operation", deviceId);
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020083 return Collections.emptyList();
84 }
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070085 PiPipeconf pipeconf = piPipeconfService.getPipeconf(piPipeconfService.ofDevice(deviceId).get()).get();
86
87 P4RuntimeController controller = handler().get(P4RuntimeController.class);
88 if (!controller.hasClient(deviceId)) {
89 log.warn("Unable to find client for {}, aborting operation", deviceId);
90 return Collections.emptyList();
91 }
92 P4RuntimeClient client = controller.getClient(deviceId);
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020093
94 Map<Long, DefaultPortStatistics.Builder> portStatBuilders = Maps.newHashMap();
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020095 deviceService.getPorts(deviceId)
96 .forEach(p -> portStatBuilders.put(p.number().toLong(),
97 DefaultPortStatistics.builder()
Carmelo Cascone7f75be42017-09-07 14:37:02 +020098 .setPort(p.number())
Carmelo Casconeb045ddc2017-09-01 01:26:35 +020099 .setDeviceId(deviceId)));
100
101 Set<PiCounterCellId> counterCellIds = Sets.newHashSet();
102 portStatBuilders.keySet().forEach(p -> {
103 // Counter cell/index = port number.
Carmelo Cascone87892e22017-11-13 16:01:29 -0800104 counterCellIds.add(PiCounterCellId.ofIndirect(ingressCounterId(), p));
105 counterCellIds.add(PiCounterCellId.ofIndirect(egressCounterId(), p));
Carmelo Casconeb045ddc2017-09-01 01:26:35 +0200106 });
107
108 Collection<PiCounterCellData> counterEntryResponse;
109 try {
110 counterEntryResponse = client.readCounterCells(counterCellIds, pipeconf).get();
111 } catch (InterruptedException | ExecutionException e) {
112 log.warn("Exception while reading port counters from {}: {}", deviceId, e.toString());
113 log.debug("", e);
114 return Collections.emptyList();
115 }
116
Carmelo Cascone7f75be42017-09-07 14:37:02 +0200117 counterEntryResponse.forEach(counterData -> {
Carmelo Cascone87892e22017-11-13 16:01:29 -0800118 if (counterData.cellId().counterType() != INDIRECT) {
119 log.warn("Invalid counter data type {}, skipping", counterData.cellId().counterType());
Carmelo Casconeb045ddc2017-09-01 01:26:35 +0200120 return;
121 }
Carmelo Cascone87892e22017-11-13 16:01:29 -0800122 PiCounterCellId indCellId = counterData.cellId();
Carmelo Cascone7f75be42017-09-07 14:37:02 +0200123 if (!portStatBuilders.containsKey(indCellId.index())) {
124 log.warn("Unrecognized counter index {}, skipping", counterData);
125 return;
126 }
127 DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(indCellId.index());
Carmelo Cascone2b057522017-10-04 14:35:29 +0200128 if (counterData.cellId().counterId().equals(ingressCounterId())) {
Carmelo Cascone7f75be42017-09-07 14:37:02 +0200129 statsBuilder.setPacketsReceived(counterData.packets());
130 statsBuilder.setBytesReceived(counterData.bytes());
Carmelo Cascone2b057522017-10-04 14:35:29 +0200131 } else if (counterData.cellId().counterId().equals(egressCounterId())) {
Carmelo Cascone7f75be42017-09-07 14:37:02 +0200132 statsBuilder.setPacketsSent(counterData.packets());
133 statsBuilder.setBytesSent(counterData.bytes());
Carmelo Casconeb045ddc2017-09-01 01:26:35 +0200134 } else {
Carmelo Cascone7f75be42017-09-07 14:37:02 +0200135 log.warn("Unrecognized counter ID {}, skipping", counterData);
Carmelo Casconeb045ddc2017-09-01 01:26:35 +0200136 }
137 });
138
139 return portStatBuilders
140 .values()
141 .stream()
142 .map(DefaultPortStatistics.Builder::build)
143 .collect(Collectors.toList());
144 }
145}