mirror of
				https://github.com/opennetworkinglab/onos.git
				synced 2025-11-04 10:11:16 +01:00 
			
		
		
		
	[ONOS-7596] Support reading table entries with counter data in P4Runtime
Change-Id: I85bacb1697a6c881dd69ba74a2162c73ec0b8aee
This commit is contained in:
		
							parent
							
								
									a25251cdf5
								
							
						
					
					
						commit
						7632e150e1
					
				@ -26,7 +26,7 @@ import org.onosproject.net.device.PortStatisticsDiscovery;
 | 
			
		||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
 | 
			
		||||
import org.onosproject.net.pi.model.PiCounterId;
 | 
			
		||||
import org.onosproject.net.pi.model.PiPipeconf;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCell;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
 | 
			
		||||
import org.onosproject.net.pi.service.PiPipeconfService;
 | 
			
		||||
import org.onosproject.p4runtime.api.P4RuntimeClient;
 | 
			
		||||
@ -95,7 +95,7 @@ public final class PortStatisticsDiscoveryImpl extends AbstractHandlerBehaviour
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Query the device.
 | 
			
		||||
        Collection<PiCounterCellData> counterEntryResponse;
 | 
			
		||||
        Collection<PiCounterCell> counterEntryResponse;
 | 
			
		||||
        try {
 | 
			
		||||
            counterEntryResponse = client.readCounterCells(counterCellIds, pipeconf).get();
 | 
			
		||||
        } catch (InterruptedException | ExecutionException e) {
 | 
			
		||||
@ -105,24 +105,24 @@ public final class PortStatisticsDiscoveryImpl extends AbstractHandlerBehaviour
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Process response.
 | 
			
		||||
        counterEntryResponse.forEach(counterData -> {
 | 
			
		||||
            if (counterData.cellId().counterType() != INDIRECT) {
 | 
			
		||||
                log.warn("Invalid counter data type {}, skipping", counterData.cellId().counterType());
 | 
			
		||||
        counterEntryResponse.forEach(counterCell -> {
 | 
			
		||||
            if (counterCell.cellId().counterType() != INDIRECT) {
 | 
			
		||||
                log.warn("Invalid counter data type {}, skipping", counterCell.cellId().counterType());
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (!portStatBuilders.containsKey(counterData.cellId().index())) {
 | 
			
		||||
                log.warn("Unrecognized counter index {}, skipping", counterData);
 | 
			
		||||
            if (!portStatBuilders.containsKey(counterCell.cellId().index())) {
 | 
			
		||||
                log.warn("Unrecognized counter index {}, skipping", counterCell);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(counterData.cellId().index());
 | 
			
		||||
            if (counterData.cellId().counterId().equals(INGRESS_COUNTER_ID)) {
 | 
			
		||||
                statsBuilder.setPacketsReceived(counterData.packets());
 | 
			
		||||
                statsBuilder.setBytesReceived(counterData.bytes());
 | 
			
		||||
            } else if (counterData.cellId().counterId().equals(EGRESS_COUNTER_ID)) {
 | 
			
		||||
                statsBuilder.setPacketsSent(counterData.packets());
 | 
			
		||||
                statsBuilder.setBytesSent(counterData.bytes());
 | 
			
		||||
            DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(counterCell.cellId().index());
 | 
			
		||||
            if (counterCell.cellId().counterId().equals(INGRESS_COUNTER_ID)) {
 | 
			
		||||
                statsBuilder.setPacketsReceived(counterCell.data().packets());
 | 
			
		||||
                statsBuilder.setBytesReceived(counterCell.data().bytes());
 | 
			
		||||
            } else if (counterCell.cellId().counterId().equals(EGRESS_COUNTER_ID)) {
 | 
			
		||||
                statsBuilder.setPacketsSent(counterCell.data().packets());
 | 
			
		||||
                statsBuilder.setBytesSent(counterCell.data().bytes());
 | 
			
		||||
            } else {
 | 
			
		||||
                log.warn("Unrecognized counter ID {}, skipping", counterData);
 | 
			
		||||
                log.warn("Unrecognized counter ID {}, skipping", counterCell);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,98 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2017-present Open Networking Foundation
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.onosproject.net.pi.runtime;
 | 
			
		||||
 | 
			
		||||
import com.google.common.annotations.Beta;
 | 
			
		||||
import com.google.common.base.MoreObjects;
 | 
			
		||||
import com.google.common.base.Objects;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Counter cell of a protocol-independent pipeline.
 | 
			
		||||
 */
 | 
			
		||||
@Beta
 | 
			
		||||
public final class PiCounterCell {
 | 
			
		||||
 | 
			
		||||
    private final PiCounterCellId cellId;
 | 
			
		||||
    private final PiCounterCellData counterData;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new counter cell for the given cell identifier and counter cell data.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cellId  counter cell identifier
 | 
			
		||||
     * @param piCounterCellData  counter cell data
 | 
			
		||||
     */
 | 
			
		||||
    public PiCounterCell(PiCounterCellId cellId, PiCounterCellData piCounterCellData) {
 | 
			
		||||
        this.cellId = cellId;
 | 
			
		||||
        this.counterData = piCounterCellData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new counter cell for the given cell identifier, number of packets and bytes.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cellId  counter cell identifier
 | 
			
		||||
     * @param packets  number of packets
 | 
			
		||||
     * @param bytes  number of bytes
 | 
			
		||||
     */
 | 
			
		||||
    public PiCounterCell(PiCounterCellId cellId, long packets, long bytes) {
 | 
			
		||||
        this.cellId = cellId;
 | 
			
		||||
        this.counterData = new PiCounterCellData(packets, bytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the cell identifier.
 | 
			
		||||
     *
 | 
			
		||||
     * @return cell identifier
 | 
			
		||||
     */
 | 
			
		||||
    public PiCounterCellId cellId() {
 | 
			
		||||
        return cellId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the data contained by this cell.
 | 
			
		||||
     *
 | 
			
		||||
     * @return counter cell data
 | 
			
		||||
     */
 | 
			
		||||
    public PiCounterCellData data() {
 | 
			
		||||
        return counterData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals(Object o) {
 | 
			
		||||
        if (this == o) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (!(o instanceof PiCounterCell)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        PiCounterCell that = (PiCounterCell) o;
 | 
			
		||||
        return Objects.equal(cellId, that.cellId) &&
 | 
			
		||||
                Objects.equal(counterData, that.counterData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int hashCode() {
 | 
			
		||||
        return Objects.hashCode(cellId, counterData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        return MoreObjects.toStringHelper(this)
 | 
			
		||||
                .add("cellId", cellId)
 | 
			
		||||
                .add("counterData", counterData)
 | 
			
		||||
                .toString();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2017-present Open Networking Foundation
 | 
			
		||||
 * Copyright 2018-present Open Networking Foundation
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
@ -23,37 +23,26 @@ import com.google.common.base.Objects;
 | 
			
		||||
/**
 | 
			
		||||
 * Data of a counter cell of a protocol-independent pipeline.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Beta
 | 
			
		||||
public final class PiCounterCellData {
 | 
			
		||||
 | 
			
		||||
    private final PiCounterCellId cellId;
 | 
			
		||||
    private final long packets;
 | 
			
		||||
    private final long bytes;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new counter cell data for the given cell identifier, number of packets and bytes.
 | 
			
		||||
     * Creates a new counter cell data for the given number of packets and bytes.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cellId  counter cell identifier
 | 
			
		||||
     * @param packets  number of packets
 | 
			
		||||
     * @param bytes  number of bytes
 | 
			
		||||
     */
 | 
			
		||||
    public PiCounterCellData(PiCounterCellId cellId, long packets, long bytes) {
 | 
			
		||||
        this.cellId = cellId;
 | 
			
		||||
    public PiCounterCellData(long packets, long bytes) {
 | 
			
		||||
        this.packets = packets;
 | 
			
		||||
        this.bytes = bytes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the cell identifier.
 | 
			
		||||
     *
 | 
			
		||||
     * @return cell identifier
 | 
			
		||||
     */
 | 
			
		||||
    public PiCounterCellId cellId() {
 | 
			
		||||
        return cellId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the packet count value contained by this cell.
 | 
			
		||||
     * Returns the packet count value contained by this counter data.
 | 
			
		||||
     *
 | 
			
		||||
     * @return number of packets
 | 
			
		||||
     */
 | 
			
		||||
@ -62,7 +51,7 @@ public final class PiCounterCellData {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the byte count value contained by this cell.
 | 
			
		||||
     * Returns the byte count value contained by this counter data.
 | 
			
		||||
     *
 | 
			
		||||
     * @return number of bytes
 | 
			
		||||
     */
 | 
			
		||||
@ -80,19 +69,17 @@ public final class PiCounterCellData {
 | 
			
		||||
        }
 | 
			
		||||
        PiCounterCellData that = (PiCounterCellData) o;
 | 
			
		||||
        return packets == that.packets &&
 | 
			
		||||
                bytes == that.bytes &&
 | 
			
		||||
                Objects.equal(cellId, that.cellId);
 | 
			
		||||
                bytes == that.bytes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int hashCode() {
 | 
			
		||||
        return Objects.hashCode(cellId, packets, bytes);
 | 
			
		||||
        return Objects.hashCode(packets, bytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        return MoreObjects.toStringHelper(this)
 | 
			
		||||
                .add("cellId", cellId)
 | 
			
		||||
                .add("packets", packets)
 | 
			
		||||
                .add("bytes", bytes)
 | 
			
		||||
                .toString();
 | 
			
		||||
 | 
			
		||||
@ -42,10 +42,11 @@ public final class PiTableEntry implements PiEntity {
 | 
			
		||||
    private final long cookie;
 | 
			
		||||
    private final int priority;
 | 
			
		||||
    private final double timeout;
 | 
			
		||||
    private final PiCounterCellData counterData;
 | 
			
		||||
 | 
			
		||||
    private PiTableEntry(PiTableId tableId, PiMatchKey matchKey,
 | 
			
		||||
                         PiTableAction tableAction, boolean isDefaultAction,
 | 
			
		||||
                         long cookie, int priority, double timeout) {
 | 
			
		||||
                         long cookie, int priority, double timeout, PiCounterCellData data) {
 | 
			
		||||
        this.tableId = tableId;
 | 
			
		||||
        this.matchKey = matchKey;
 | 
			
		||||
        this.tableAction = tableAction;
 | 
			
		||||
@ -53,6 +54,7 @@ public final class PiTableEntry implements PiEntity {
 | 
			
		||||
        this.cookie = cookie;
 | 
			
		||||
        this.priority = priority;
 | 
			
		||||
        this.timeout = timeout;
 | 
			
		||||
        this.counterData = data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -125,6 +127,18 @@ public final class PiTableEntry implements PiEntity {
 | 
			
		||||
        return timeout == NO_TIMEOUT ? Optional.empty() : Optional.of(timeout);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the data of the counter cell associated with this table entry.
 | 
			
		||||
     * This method is meaningful only if the table entry was read from the
 | 
			
		||||
     * infrastructure device and the table has direct counters, otherwise
 | 
			
		||||
     * returns null.
 | 
			
		||||
     *
 | 
			
		||||
     * @return counter cell data
 | 
			
		||||
     */
 | 
			
		||||
    public PiCounterCellData counter() {
 | 
			
		||||
        return counterData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals(Object o) {
 | 
			
		||||
        if (this == o) {
 | 
			
		||||
@ -197,6 +211,7 @@ public final class PiTableEntry implements PiEntity {
 | 
			
		||||
        private long cookie = 0;
 | 
			
		||||
        private int priority = NO_PRIORITY;
 | 
			
		||||
        private double timeout = NO_TIMEOUT;
 | 
			
		||||
        private PiCounterCellData counterData;
 | 
			
		||||
 | 
			
		||||
        private Builder() {
 | 
			
		||||
            // Hides constructor.
 | 
			
		||||
@ -271,6 +286,17 @@ public final class PiTableEntry implements PiEntity {
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Sets the counter cell data of this table entry.
 | 
			
		||||
         *
 | 
			
		||||
         * @param data counter cell data
 | 
			
		||||
         * @return this
 | 
			
		||||
         */
 | 
			
		||||
        public Builder withCounterCellData(PiCounterCellData data) {
 | 
			
		||||
            this.counterData = checkNotNull(data, "Counter cell data cannot be null");
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Builds the table entry.
 | 
			
		||||
         *
 | 
			
		||||
@ -281,7 +307,7 @@ public final class PiTableEntry implements PiEntity {
 | 
			
		||||
            checkNotNull(matchKey);
 | 
			
		||||
            final boolean isDefaultAction = matchKey.equals(PiMatchKey.EMPTY);
 | 
			
		||||
            return new PiTableEntry(tableId, matchKey, tableAction,
 | 
			
		||||
                                    isDefaultAction, cookie, priority, timeout);
 | 
			
		||||
                                    isDefaultAction, cookie, priority, timeout, counterData);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2017-present Open Networking Foundation
 | 
			
		||||
 * Copyright 2018-present Open Networking Foundation
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
@ -18,48 +18,25 @@ package org.onosproject.net.pi.runtime;
 | 
			
		||||
 | 
			
		||||
import com.google.common.testing.EqualsTester;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.onosproject.net.pi.model.PiActionId;
 | 
			
		||||
import org.onosproject.net.pi.model.PiTableId;
 | 
			
		||||
 | 
			
		||||
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
 | 
			
		||||
import static org.onosproject.net.pi.runtime.PiConstantsTest.DROP;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Unit tests for PiCounterCellData class.
 | 
			
		||||
 * Unit tests for PiCounterData class.
 | 
			
		||||
 */
 | 
			
		||||
public class PiCounterCellDataTest {
 | 
			
		||||
 | 
			
		||||
    private static final PiTableEntry PI_TABLE_ENTRY_1 = PiTableEntry.builder()
 | 
			
		||||
            .forTable(PiTableId.of("T10"))
 | 
			
		||||
            .withCookie(0xac)
 | 
			
		||||
            .withPriority(10)
 | 
			
		||||
            .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
 | 
			
		||||
            .withTimeout(100)
 | 
			
		||||
            .build();
 | 
			
		||||
    private static final PiTableEntry PI_TABLE_ENTRY_2 = PiTableEntry.builder()
 | 
			
		||||
            .forTable(PiTableId.of("T20"))
 | 
			
		||||
            .withCookie(0xac)
 | 
			
		||||
            .withPriority(10)
 | 
			
		||||
            .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
 | 
			
		||||
            .withTimeout(1000)
 | 
			
		||||
            .build();
 | 
			
		||||
 | 
			
		||||
    private static final PiCounterCellId PI_COUNTER_CELL_ID_1 =
 | 
			
		||||
            PiCounterCellId.ofDirect(PI_TABLE_ENTRY_1);
 | 
			
		||||
    private static final PiCounterCellId PI_COUNTER_CELL_ID_2 =
 | 
			
		||||
            PiCounterCellId.ofDirect(PI_TABLE_ENTRY_2);
 | 
			
		||||
 | 
			
		||||
    private static final long PACKETS_1 = 10;
 | 
			
		||||
    private static final long PACKETS_2 = 20;
 | 
			
		||||
    private static final long BYTES_1 = 100;
 | 
			
		||||
    private static final long BYTES_2 = 200;
 | 
			
		||||
 | 
			
		||||
    private static final PiCounterCellData PI_COUNTER_CELL_DATA_1 =
 | 
			
		||||
            new PiCounterCellData(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
 | 
			
		||||
    private static final PiCounterCellData SAME_AS_PI_COUNTER_CELL_DATA_1 =
 | 
			
		||||
            new PiCounterCellData(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
 | 
			
		||||
    private static final PiCounterCellData PI_COUNTER_CELL_DATA_2 =
 | 
			
		||||
            new PiCounterCellData(PI_COUNTER_CELL_ID_2, PACKETS_2, BYTES_2);
 | 
			
		||||
    private static final PiCounterCellData PI_COUNTER_DATA_1 =
 | 
			
		||||
            new PiCounterCellData(PACKETS_1, BYTES_1);
 | 
			
		||||
    private static final PiCounterCellData SAME_AS_PI_COUNTER_DATA_1 =
 | 
			
		||||
            new PiCounterCellData(PACKETS_1, BYTES_1);
 | 
			
		||||
    private static final PiCounterCellData PI_COUNTER_DATA_2 =
 | 
			
		||||
            new PiCounterCellData(PACKETS_2, BYTES_2);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks that the PiCounterCellData class is immutable.
 | 
			
		||||
@ -75,8 +52,8 @@ public class PiCounterCellDataTest {
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testEquals() {
 | 
			
		||||
        new EqualsTester()
 | 
			
		||||
                .addEqualityGroup(PI_COUNTER_CELL_DATA_1, SAME_AS_PI_COUNTER_CELL_DATA_1)
 | 
			
		||||
                .addEqualityGroup(PI_COUNTER_CELL_DATA_2)
 | 
			
		||||
                .addEqualityGroup(PI_COUNTER_DATA_1, SAME_AS_PI_COUNTER_DATA_1)
 | 
			
		||||
                .addEqualityGroup(PI_COUNTER_DATA_2)
 | 
			
		||||
                .testEquals();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,82 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2017-present Open Networking Foundation
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.onosproject.net.pi.runtime;
 | 
			
		||||
 | 
			
		||||
import com.google.common.testing.EqualsTester;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.onosproject.net.pi.model.PiActionId;
 | 
			
		||||
import org.onosproject.net.pi.model.PiTableId;
 | 
			
		||||
 | 
			
		||||
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
 | 
			
		||||
import static org.onosproject.net.pi.runtime.PiConstantsTest.DROP;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Unit tests for PiCounterCell class.
 | 
			
		||||
 */
 | 
			
		||||
public class PiCounterCellTest {
 | 
			
		||||
 | 
			
		||||
    private static final PiTableEntry PI_TABLE_ENTRY_1 = PiTableEntry.builder()
 | 
			
		||||
            .forTable(PiTableId.of("T10"))
 | 
			
		||||
            .withCookie(0xac)
 | 
			
		||||
            .withPriority(10)
 | 
			
		||||
            .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
 | 
			
		||||
            .withTimeout(100)
 | 
			
		||||
            .build();
 | 
			
		||||
    private static final PiTableEntry PI_TABLE_ENTRY_2 = PiTableEntry.builder()
 | 
			
		||||
            .forTable(PiTableId.of("T20"))
 | 
			
		||||
            .withCookie(0xac)
 | 
			
		||||
            .withPriority(10)
 | 
			
		||||
            .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
 | 
			
		||||
            .withTimeout(1000)
 | 
			
		||||
            .build();
 | 
			
		||||
 | 
			
		||||
    private static final PiCounterCellId PI_COUNTER_CELL_ID_1 =
 | 
			
		||||
            PiCounterCellId.ofDirect(PI_TABLE_ENTRY_1);
 | 
			
		||||
    private static final PiCounterCellId PI_COUNTER_CELL_ID_2 =
 | 
			
		||||
            PiCounterCellId.ofDirect(PI_TABLE_ENTRY_2);
 | 
			
		||||
 | 
			
		||||
    private static final long PACKETS_1 = 10;
 | 
			
		||||
    private static final long PACKETS_2 = 20;
 | 
			
		||||
    private static final long BYTES_1 = 100;
 | 
			
		||||
    private static final long BYTES_2 = 200;
 | 
			
		||||
 | 
			
		||||
    private static final PiCounterCell PI_COUNTER_CELL_1 =
 | 
			
		||||
            new PiCounterCell(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
 | 
			
		||||
    private static final PiCounterCell SAME_AS_PI_COUNTER_CELL_1 =
 | 
			
		||||
            new PiCounterCell(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
 | 
			
		||||
    private static final PiCounterCell PI_COUNTER_CELL_2 =
 | 
			
		||||
            new PiCounterCell(PI_COUNTER_CELL_ID_2, PACKETS_2, BYTES_2);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks that the PiCounterCell class is immutable.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testImmutability() {
 | 
			
		||||
        assertThatClassIsImmutable(PiCounterCell.class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks the operation of equals(), hashCode() and toString() methods.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testEquals() {
 | 
			
		||||
        new EqualsTester()
 | 
			
		||||
                .addEqualityGroup(PI_COUNTER_CELL_1, SAME_AS_PI_COUNTER_CELL_1)
 | 
			
		||||
                .addEqualityGroup(PI_COUNTER_CELL_2)
 | 
			
		||||
                .testEquals();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -231,6 +231,7 @@ import org.onosproject.net.pi.runtime.PiActionGroupMemberHandle;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionParam;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiControlMetadata;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCell;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiEntity;
 | 
			
		||||
@ -692,6 +693,7 @@ public final class KryoNamespaces {
 | 
			
		||||
                    PiActionGroupMemberId.class,
 | 
			
		||||
                    PiActionParam.class,
 | 
			
		||||
                    PiControlMetadata.class,
 | 
			
		||||
                    PiCounterCell.class,
 | 
			
		||||
                    PiCounterCellData.class,
 | 
			
		||||
                    PiCounterCellId.class,
 | 
			
		||||
                    PiEntity.class,
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@ import org.onosproject.net.pi.model.PiPipelineInterpreter;
 | 
			
		||||
import org.onosproject.net.pi.model.PiPipelineModel;
 | 
			
		||||
import org.onosproject.net.pi.model.PiTableId;
 | 
			
		||||
import org.onosproject.net.pi.model.PiTableModel;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCell;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiTableEntry;
 | 
			
		||||
@ -89,11 +90,11 @@ public class P4RuntimeFlowRuleProgrammable
 | 
			
		||||
    private static final String SUPPORT_TABLE_COUNTERS = "supportTableCounters";
 | 
			
		||||
    private static final boolean DEFAULT_SUPPORT_TABLE_COUNTERS = true;
 | 
			
		||||
 | 
			
		||||
    // If true, we read all direct counters of a table with one request.
 | 
			
		||||
    // Otherwise, we send as many requests as the number of table entries.
 | 
			
		||||
    private static final String READ_ALL_DIRECT_COUNTERS = "tableReadAllDirectCounters";
 | 
			
		||||
    // FIXME: set to true as soon as the feature is implemented in P4Runtime.
 | 
			
		||||
    private static final boolean DEFAULT_READ_ALL_DIRECT_COUNTERS = false;
 | 
			
		||||
    // If true, assumes that the device returns table entry message populated
 | 
			
		||||
    // with direct counter values. If false, we issue a second P4Runtime request
 | 
			
		||||
    // to read the direct counter values.
 | 
			
		||||
    private static final String READ_COUNTERS_WITH_TABLE_ENTRIES = "tableReadCountersWithTableEntries";
 | 
			
		||||
    private static final boolean DEFAULT_READ_COUNTERS_WITH_TABLE_ENTRIES = true;
 | 
			
		||||
 | 
			
		||||
    // For default entries, P4Runtime mandates that only MODIFY messages are
 | 
			
		||||
    // allowed. If true, treats default entries as normal table entries,
 | 
			
		||||
@ -153,7 +154,6 @@ public class P4RuntimeFlowRuleProgrammable
 | 
			
		||||
 | 
			
		||||
        // Synchronize mirror with the device state.
 | 
			
		||||
        syncMirror(deviceEntries);
 | 
			
		||||
        // TODO: ONOS-7596 read counters with table entries
 | 
			
		||||
        final Map<PiTableEntry, PiCounterCellData> counterCellMap =
 | 
			
		||||
                readEntryCounters(deviceEntries);
 | 
			
		||||
        // Forge flow entries with counter values.
 | 
			
		||||
@ -461,25 +461,22 @@ public class P4RuntimeFlowRuleProgrammable
 | 
			
		||||
            return Collections.emptyMap();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Collection<PiCounterCellData> cellDatas;
 | 
			
		||||
 | 
			
		||||
        if (driverBoolProperty(READ_ALL_DIRECT_COUNTERS,
 | 
			
		||||
                               DEFAULT_READ_ALL_DIRECT_COUNTERS)) {
 | 
			
		||||
            // FIXME: read counters when dumping table entries ONOS-7596
 | 
			
		||||
            cellDatas = Collections.emptyList();
 | 
			
		||||
        if (driverBoolProperty(READ_COUNTERS_WITH_TABLE_ENTRIES,
 | 
			
		||||
                               DEFAULT_READ_COUNTERS_WITH_TABLE_ENTRIES)) {
 | 
			
		||||
            return tableEntries.stream().collect(Collectors.toMap(c -> c, PiTableEntry::counter));
 | 
			
		||||
        } else {
 | 
			
		||||
            Collection<PiCounterCell> cells;
 | 
			
		||||
            Set<PiCounterCellId> cellIds = tableEntries.stream()
 | 
			
		||||
                    // Ignore counter for default entry.
 | 
			
		||||
                    .filter(e -> !e.isDefaultAction())
 | 
			
		||||
                    .filter(e -> tableHasCounter(e.table()))
 | 
			
		||||
                    .map(PiCounterCellId::ofDirect)
 | 
			
		||||
                    .collect(Collectors.toSet());
 | 
			
		||||
            cellDatas = getFutureWithDeadline(client.readCounterCells(cellIds, pipeconf),
 | 
			
		||||
            cells = getFutureWithDeadline(client.readCounterCells(cellIds, pipeconf),
 | 
			
		||||
                                              "reading table counters", Collections.emptyList());
 | 
			
		||||
            return cells.stream()
 | 
			
		||||
                    .collect(Collectors.toMap(c -> c.cellId().tableEntry(), PiCounterCell::data));
 | 
			
		||||
        }
 | 
			
		||||
        return cellDatas.stream()
 | 
			
		||||
                .collect(Collectors.toMap(c -> c.cellId().tableEntry(), c -> c));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean tableHasCounter(PiTableId tableId) {
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ import org.onosproject.net.device.PortStatisticsDiscovery;
 | 
			
		||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
 | 
			
		||||
import org.onosproject.net.pi.model.PiCounterId;
 | 
			
		||||
import org.onosproject.net.pi.model.PiPipeconf;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCell;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
 | 
			
		||||
import org.onosproject.net.pi.service.PiPipeconfService;
 | 
			
		||||
import org.onosproject.p4runtime.api.P4RuntimeClient;
 | 
			
		||||
@ -112,7 +112,7 @@ public class PortStatisticsDiscoveryImpl extends AbstractHandlerBehaviour implem
 | 
			
		||||
            counterCellIds.add(PiCounterCellId.ofIndirect(egressCounterId(), p));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Collection<PiCounterCellData> counterEntryResponse;
 | 
			
		||||
        Collection<PiCounterCell> counterEntryResponse;
 | 
			
		||||
        try {
 | 
			
		||||
            counterEntryResponse = client.readCounterCells(counterCellIds, pipeconf).get();
 | 
			
		||||
        } catch (InterruptedException | ExecutionException e) {
 | 
			
		||||
@ -121,25 +121,25 @@ public class PortStatisticsDiscoveryImpl extends AbstractHandlerBehaviour implem
 | 
			
		||||
            return Collections.emptyList();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        counterEntryResponse.forEach(counterData -> {
 | 
			
		||||
            if (counterData.cellId().counterType() != INDIRECT) {
 | 
			
		||||
                log.warn("Invalid counter data type {}, skipping", counterData.cellId().counterType());
 | 
			
		||||
        counterEntryResponse.forEach(counterCell -> {
 | 
			
		||||
            if (counterCell.cellId().counterType() != INDIRECT) {
 | 
			
		||||
                log.warn("Invalid counter data type {}, skipping", counterCell.cellId().counterType());
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            PiCounterCellId indCellId = counterData.cellId();
 | 
			
		||||
            PiCounterCellId indCellId = counterCell.cellId();
 | 
			
		||||
            if (!portStatBuilders.containsKey(indCellId.index())) {
 | 
			
		||||
                log.warn("Unrecognized counter index {}, skipping", counterData);
 | 
			
		||||
                log.warn("Unrecognized counter index {}, skipping", counterCell);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(indCellId.index());
 | 
			
		||||
            if (counterData.cellId().counterId().equals(ingressCounterId())) {
 | 
			
		||||
                statsBuilder.setPacketsReceived(counterData.packets());
 | 
			
		||||
                statsBuilder.setBytesReceived(counterData.bytes());
 | 
			
		||||
            } else if (counterData.cellId().counterId().equals(egressCounterId())) {
 | 
			
		||||
                statsBuilder.setPacketsSent(counterData.packets());
 | 
			
		||||
                statsBuilder.setBytesSent(counterData.bytes());
 | 
			
		||||
            if (counterCell.cellId().counterId().equals(ingressCounterId())) {
 | 
			
		||||
                statsBuilder.setPacketsReceived(counterCell.data().packets());
 | 
			
		||||
                statsBuilder.setBytesReceived(counterCell.data().bytes());
 | 
			
		||||
            } else if (counterCell.cellId().counterId().equals(egressCounterId())) {
 | 
			
		||||
                statsBuilder.setPacketsSent(counterCell.data().packets());
 | 
			
		||||
                statsBuilder.setBytesSent(counterCell.data().bytes());
 | 
			
		||||
            } else {
 | 
			
		||||
                log.warn("Unrecognized counter ID {}, skipping", counterData);
 | 
			
		||||
                log.warn("Unrecognized counter ID {}, skipping", counterCell);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ import org.onosproject.net.pi.model.PiTableId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroup;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupMember;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCell;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiMeterCellId;
 | 
			
		||||
@ -178,7 +178,7 @@ public interface P4RuntimeClient {
 | 
			
		||||
     * @param pipeconf   pipeconf
 | 
			
		||||
     * @return list of counter data
 | 
			
		||||
     */
 | 
			
		||||
    CompletableFuture<List<PiCounterCellData>> readAllCounterCells(
 | 
			
		||||
    CompletableFuture<List<PiCounterCell>> readAllCounterCells(
 | 
			
		||||
            Set<PiCounterId> counterIds, PiPipeconf pipeconf);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -189,7 +189,7 @@ public interface P4RuntimeClient {
 | 
			
		||||
     * @param pipeconf pipeconf
 | 
			
		||||
     * @return list of counter data
 | 
			
		||||
     */
 | 
			
		||||
    CompletableFuture<List<PiCounterCellData>> readCounterCells(
 | 
			
		||||
    CompletableFuture<List<PiCounterCell>> readCounterCells(
 | 
			
		||||
            Set<PiCounterCellId> cellIds, PiPipeconf pipeconf);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@ import org.onosproject.net.pi.model.PiCounterId;
 | 
			
		||||
import org.onosproject.net.pi.model.PiCounterType;
 | 
			
		||||
import org.onosproject.net.pi.model.PiPipeconf;
 | 
			
		||||
import org.onosproject.net.pi.model.PiTableId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCell;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiTableEntry;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
@ -135,7 +135,7 @@ final class CounterEntryCodec {
 | 
			
		||||
     * @param pipeconf pipeconf
 | 
			
		||||
     * @return collection of PI counter cell data
 | 
			
		||||
     */
 | 
			
		||||
    static List<PiCounterCellData> decodeCounterEntities(List<Entity> entities,
 | 
			
		||||
    static List<PiCounterCell> decodeCounterEntities(List<Entity> entities,
 | 
			
		||||
                                                     PiPipeconf pipeconf) {
 | 
			
		||||
 | 
			
		||||
        final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
 | 
			
		||||
@ -248,7 +248,7 @@ final class CounterEntryCodec {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static PiCounterCellData decodeCounterEntity(Entity entity,
 | 
			
		||||
    private static PiCounterCell decodeCounterEntity(Entity entity,
 | 
			
		||||
                                                     PiPipeconf pipeconf,
 | 
			
		||||
                                                     P4InfoBrowser browser)
 | 
			
		||||
            throws EncodeException, P4InfoBrowser.NotFoundException {
 | 
			
		||||
@ -276,7 +276,7 @@ final class CounterEntryCodec {
 | 
			
		||||
                    entity.getEntityCase().name()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return new PiCounterCellData(piCellId,
 | 
			
		||||
        return new PiCounterCell(piCellId,
 | 
			
		||||
                                 counterData.getPacketCount(),
 | 
			
		||||
                                 counterData.getByteCount());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ import org.onosproject.net.pi.model.PiTableId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroup;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupMember;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCell;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiMeterCellId;
 | 
			
		||||
@ -281,14 +281,14 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CompletableFuture<List<PiCounterCellData>> readCounterCells(Set<PiCounterCellId> cellIds,
 | 
			
		||||
    public CompletableFuture<List<PiCounterCell>> readCounterCells(Set<PiCounterCellId> cellIds,
 | 
			
		||||
                                                                   PiPipeconf pipeconf) {
 | 
			
		||||
        return supplyInContext(() -> doReadCounterCells(Lists.newArrayList(cellIds), pipeconf),
 | 
			
		||||
                               "readCounterCells-" + cellIds.hashCode());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CompletableFuture<List<PiCounterCellData>> readAllCounterCells(Set<PiCounterId> counterIds,
 | 
			
		||||
    public CompletableFuture<List<PiCounterCell>> readAllCounterCells(Set<PiCounterId> counterIds,
 | 
			
		||||
                                                                      PiPipeconf pipeconf) {
 | 
			
		||||
        return supplyInContext(() -> doReadAllCounterCells(Lists.newArrayList(counterIds), pipeconf),
 | 
			
		||||
                               "readAllCounterCells-" + counterIds.hashCode());
 | 
			
		||||
@ -559,6 +559,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
 | 
			
		||||
                                TableEntry.newBuilder()
 | 
			
		||||
                                        .setTableId(tableId)
 | 
			
		||||
                                        .setIsDefaultAction(defaultEntries)
 | 
			
		||||
                                        .setCounterData(P4RuntimeOuterClass.CounterData.getDefaultInstance())
 | 
			
		||||
                                        .build())
 | 
			
		||||
                        .build())
 | 
			
		||||
                .build());
 | 
			
		||||
@ -651,21 +652,21 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
 | 
			
		||||
        isClientMaster.set(isMaster);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<PiCounterCellData> doReadAllCounterCells(
 | 
			
		||||
    private List<PiCounterCell> doReadAllCounterCells(
 | 
			
		||||
            List<PiCounterId> counterIds, PiPipeconf pipeconf) {
 | 
			
		||||
        return doReadCounterEntities(
 | 
			
		||||
                CounterEntryCodec.readAllCellsEntities(counterIds, pipeconf),
 | 
			
		||||
                pipeconf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<PiCounterCellData> doReadCounterCells(
 | 
			
		||||
    private List<PiCounterCell> doReadCounterCells(
 | 
			
		||||
            List<PiCounterCellId> cellIds, PiPipeconf pipeconf) {
 | 
			
		||||
        return doReadCounterEntities(
 | 
			
		||||
                CounterEntryCodec.encodePiCounterCellIds(cellIds, pipeconf),
 | 
			
		||||
                pipeconf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<PiCounterCellData> doReadCounterEntities(
 | 
			
		||||
    private List<PiCounterCell> doReadCounterEntities(
 | 
			
		||||
            List<Entity> counterEntities, PiPipeconf pipeconf) {
 | 
			
		||||
 | 
			
		||||
        if (counterEntities.size() == 0) {
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,7 @@ import org.onosproject.net.pi.runtime.PiAction;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionParam;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiExactFieldMatch;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiFieldMatch;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
 | 
			
		||||
@ -40,6 +41,7 @@ import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import p4.config.v1.P4InfoOuterClass;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.Action;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.CounterData;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.FieldMatch;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.TableAction;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.TableEntry;
 | 
			
		||||
@ -249,6 +251,11 @@ final class TableEntryEncoder {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Counter.
 | 
			
		||||
        if (piTableEntry.counter() != null) {
 | 
			
		||||
            tableEntryMsgBuilder.setCounterData(encodeCounter(piTableEntry.counter()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return tableEntryMsgBuilder.build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -281,6 +288,9 @@ final class TableEntryEncoder {
 | 
			
		||||
        // Match key for field matches.
 | 
			
		||||
        piTableEntryBuilder.withMatchKey(decodeFieldMatchMsgs(tableEntryMsg.getMatchList(), tableInfo, browser));
 | 
			
		||||
 | 
			
		||||
        // Counter.
 | 
			
		||||
        piTableEntryBuilder.withCounterCellData(decodeCounter(tableEntryMsg.getCounterData()));
 | 
			
		||||
 | 
			
		||||
        return piTableEntryBuilder.build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -505,4 +515,13 @@ final class TableEntryEncoder {
 | 
			
		||||
        }
 | 
			
		||||
        return PiAction.builder().withId(id).withParameters(params).build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static CounterData encodeCounter(PiCounterCellData piCounterCellData) {
 | 
			
		||||
        return CounterData.newBuilder().setPacketCount(piCounterCellData.packets())
 | 
			
		||||
                .setByteCount(piCounterCellData.bytes()).build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static PiCounterCellData decodeCounter(CounterData counterData) {
 | 
			
		||||
        return new PiCounterCellData(counterData.getPacketCount(), counterData.getByteCount());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -32,11 +32,13 @@ import org.onosproject.net.pi.model.PiTableId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiAction;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionGroupId;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiActionParam;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiExactFieldMatch;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiMatchKey;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiTableEntry;
 | 
			
		||||
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.Action;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.CounterData;
 | 
			
		||||
import p4.v1.P4RuntimeOuterClass.TableEntry;
 | 
			
		||||
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
@ -72,6 +74,9 @@ public class TableEntryEncoderTest {
 | 
			
		||||
    private static final String ETHER_TYPE = "etherType";
 | 
			
		||||
    private static final String ECMP_GROUP_ID = "ecmp_group_id";
 | 
			
		||||
 | 
			
		||||
    private static final long PACKETS = 10;
 | 
			
		||||
    private static final long BYTES = 100;
 | 
			
		||||
 | 
			
		||||
    private final Random rand = new Random();
 | 
			
		||||
    private final URL p4InfoUrl = this.getClass().getResource("/test.p4info");
 | 
			
		||||
 | 
			
		||||
@ -94,6 +99,7 @@ public class TableEntryEncoderTest {
 | 
			
		||||
    private final PiActionId outActionId = PiActionId.of(SET_EGRESS_PORT);
 | 
			
		||||
    private final PiTableId tableId = PiTableId.of(TABLE_0);
 | 
			
		||||
    private final PiTableId ecmpTableId = PiTableId.of(TABLE_ECMP);
 | 
			
		||||
    private final PiCounterCellData counterCellData = new PiCounterCellData(PACKETS, BYTES);
 | 
			
		||||
 | 
			
		||||
    private final PiTableEntry piTableEntry = PiTableEntry
 | 
			
		||||
            .builder()
 | 
			
		||||
@ -111,6 +117,7 @@ public class TableEntryEncoderTest {
 | 
			
		||||
                                .build())
 | 
			
		||||
            .withPriority(1)
 | 
			
		||||
            .withCookie(2)
 | 
			
		||||
            .withCounterCellData(counterCellData)
 | 
			
		||||
            .build();
 | 
			
		||||
 | 
			
		||||
    private final PiTableEntry piTableEntryWithoutAction = PiTableEntry
 | 
			
		||||
@ -124,6 +131,7 @@ public class TableEntryEncoderTest {
 | 
			
		||||
                                  .build())
 | 
			
		||||
            .withPriority(1)
 | 
			
		||||
            .withCookie(2)
 | 
			
		||||
            .withCounterCellData(counterCellData)
 | 
			
		||||
            .build();
 | 
			
		||||
 | 
			
		||||
    private final PiTableEntry piTableEntryWithGroupAction = PiTableEntry
 | 
			
		||||
@ -135,6 +143,7 @@ public class TableEntryEncoderTest {
 | 
			
		||||
            .withAction(PiActionGroupId.of(1))
 | 
			
		||||
            .withPriority(1)
 | 
			
		||||
            .withCookie(2)
 | 
			
		||||
            .withCounterCellData(counterCellData)
 | 
			
		||||
            .build();
 | 
			
		||||
 | 
			
		||||
    public TableEntryEncoderTest() throws ImmutableByteSequence.ByteSequenceTrimException {
 | 
			
		||||
@ -198,6 +207,12 @@ public class TableEntryEncoderTest {
 | 
			
		||||
        byte[] encodedActionParam = actionMsg.getParams(0).getValue().toByteArray();
 | 
			
		||||
        assertThat(encodedActionParam, is(portValue.asArray()));
 | 
			
		||||
 | 
			
		||||
        // Counter
 | 
			
		||||
        CounterData counterData = tableEntryMsg.getCounterData();
 | 
			
		||||
        PiCounterCellData encodedCounterData = new PiCounterCellData(counterData.getPacketCount(),
 | 
			
		||||
                                                                     counterData.getByteCount());
 | 
			
		||||
        assertThat(encodedCounterData, is(counterCellData));
 | 
			
		||||
 | 
			
		||||
        // TODO: improve, assert other field match types (ternary, LPM)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -257,6 +272,12 @@ public class TableEntryEncoderTest {
 | 
			
		||||
        // no action
 | 
			
		||||
        assertThat(tableEntryMsg.hasAction(), is(false));
 | 
			
		||||
 | 
			
		||||
        // Counter
 | 
			
		||||
        CounterData counterData = tableEntryMsg.getCounterData();
 | 
			
		||||
        PiCounterCellData encodedCounterData = new PiCounterCellData(counterData.getPacketCount(),
 | 
			
		||||
                                                                     counterData.getByteCount());
 | 
			
		||||
        assertThat(encodedCounterData, is(counterCellData));
 | 
			
		||||
 | 
			
		||||
        // TODO: improve, assert other field match types (ternary, LPM)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user