mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-12-10 03:41:28 +01:00
Merge branch 'master' into dev-karaf-4.2.1
Change-Id: I86b9d80581cd76a7c20e05201023090f9692d1ab
This commit is contained in:
commit
db57f1c326
15
apps/inbandtelemetry/BUILD
Normal file
15
apps/inbandtelemetry/BUILD
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
BUNDLES = [
|
||||||
|
"//apps/inbandtelemetry/api:onos-apps-inbandtelemetry-api",
|
||||||
|
"//apps/inbandtelemetry/impl:onos-apps-inbandtelemetry-impl",
|
||||||
|
"//apps/inbandtelemetry/app:onos-apps-inbandtelemetry-app",
|
||||||
|
]
|
||||||
|
|
||||||
|
onos_app(
|
||||||
|
app_name = "org.onosproject.inbandtelemetry",
|
||||||
|
category = "Monitoring",
|
||||||
|
description = "Provides managements of INT-capable devices. Specifies flows to enable INT and" +
|
||||||
|
"types of metadata to collect. Sets up INT-related information.",
|
||||||
|
included_bundles = BUNDLES,
|
||||||
|
title = "P4 In-band Network Telemetry Service",
|
||||||
|
url = "http://onosproject.org",
|
||||||
|
)
|
||||||
@ -30,7 +30,7 @@ public final class IntConfig {
|
|||||||
/**
|
/**
|
||||||
* Represents a type of telemetry spec to collect in the dataplane.
|
* Represents a type of telemetry spec to collect in the dataplane.
|
||||||
*/
|
*/
|
||||||
enum TelemetrySpec {
|
public enum TelemetrySpec {
|
||||||
/**
|
/**
|
||||||
* Embeds telemetry metadata according to the INT specification.
|
* Embeds telemetry metadata according to the INT specification.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -16,18 +16,64 @@
|
|||||||
package org.onosproject.inbandtelemetry.api;
|
package org.onosproject.inbandtelemetry.api;
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
import com.google.common.annotations.Beta;
|
||||||
|
import org.onosproject.net.PortNumber;
|
||||||
import org.onosproject.net.driver.HandlerBehaviour;
|
import org.onosproject.net.driver.HandlerBehaviour;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
/**
|
||||||
|
* Abstraction of a device implementing In-band Network Telemetry (INT)
|
||||||
|
* capabilities.
|
||||||
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public interface IntProgrammable extends HandlerBehaviour {
|
public interface IntProgrammable extends HandlerBehaviour {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the pipeline, by installing required flow rules
|
* INT functionalities that a device can implement.
|
||||||
* not relevant to specific watchlist, report and event.
|
|
||||||
*/
|
*/
|
||||||
void init();
|
enum IntFunctionality {
|
||||||
|
/**
|
||||||
|
* Source functionality.
|
||||||
|
*/
|
||||||
|
SOURCE,
|
||||||
|
/**
|
||||||
|
* Sink functionality.
|
||||||
|
*/
|
||||||
|
SINK,
|
||||||
|
/**
|
||||||
|
* Transit functionality.
|
||||||
|
*/
|
||||||
|
TRANSIT
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the pipeline, by installing required flow rules not relevant
|
||||||
|
* to specific watchlist, report and event. Returns true if the operation
|
||||||
|
* was successful, false otherwise.
|
||||||
|
*
|
||||||
|
* @return true if successful, false otherwise
|
||||||
|
*/
|
||||||
|
boolean init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the given port as an INT source port. Packets received via
|
||||||
|
* this port can be modified to add the INT header, if a corresponding INT
|
||||||
|
* objective is matched. Returns true if the operation was successful, false
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* @param port port
|
||||||
|
* @return true if successful, false otherwise
|
||||||
|
*/
|
||||||
|
boolean setSourcePort(PortNumber port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the given port as an INT sink port. Packets forwarded via this
|
||||||
|
* port will be stripped of the INT header and a corresponding INT report
|
||||||
|
* will be generated. Returns true if the operation was successful, false
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* @param port port
|
||||||
|
* @return true if successful, false otherwise
|
||||||
|
*/
|
||||||
|
boolean setSinkPort(PortNumber port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a given IntObjective to the device.
|
* Adds a given IntObjective to the device.
|
||||||
@ -35,7 +81,7 @@ public interface IntProgrammable extends HandlerBehaviour {
|
|||||||
* @param obj an IntObjective
|
* @param obj an IntObjective
|
||||||
* @return true if the objective is successfully added; false otherwise.
|
* @return true if the objective is successfully added; false otherwise.
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> addIntObjective(IntObjective obj);
|
boolean addIntObjective(IntObjective obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a given IntObjective entry from the device.
|
* Removes a given IntObjective entry from the device.
|
||||||
@ -43,7 +89,7 @@ public interface IntProgrammable extends HandlerBehaviour {
|
|||||||
* @param obj an IntObjective
|
* @param obj an IntObjective
|
||||||
* @return true if the objective is successfully removed; false otherwise.
|
* @return true if the objective is successfully removed; false otherwise.
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> removeIntObjective(IntObjective obj);
|
boolean removeIntObjective(IntObjective obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up report-related configuration.
|
* Set up report-related configuration.
|
||||||
@ -51,7 +97,20 @@ public interface IntProgrammable extends HandlerBehaviour {
|
|||||||
* @param config a configuration regarding to the collector
|
* @param config a configuration regarding to the collector
|
||||||
* @return true if the objective is successfully added; false otherwise.
|
* @return true if the objective is successfully added; false otherwise.
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> setupIntConfig(IntConfig config);
|
boolean setupIntConfig(IntConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up any INT-related configuration from the device.
|
||||||
|
*/
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this device supports the given INT functionality.
|
||||||
|
*
|
||||||
|
* @param functionality INt functionality
|
||||||
|
* @return true if functionality is supported, false otherwise
|
||||||
|
*/
|
||||||
|
boolean supportsFunctionality(IntFunctionality functionality);
|
||||||
|
|
||||||
//TODO: [ONOS-7616] Design IntEvent and related APIs
|
//TODO: [ONOS-7616] Design IntEvent and related APIs
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,13 +43,13 @@ public interface IntService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the INT functionalities in all INT-capable devices.
|
* Starts the INT functionality in all INT-capable devices.
|
||||||
* This will include populating tables to process INT packets.
|
* This will include populating tables to process INT packets.
|
||||||
*/
|
*/
|
||||||
void startInt();
|
void startInt();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the INT functionalities in specified set of INT transit devices.
|
* Starts the INT functionality in specified set of INT transit devices.
|
||||||
* <p>
|
* <p>
|
||||||
* Note: this is an experimental API, which can be either changed or removed.
|
* Note: this is an experimental API, which can be either changed or removed.
|
||||||
*
|
*
|
||||||
@ -116,4 +116,4 @@ public interface IntService {
|
|||||||
Map<IntIntentId, IntIntent> getIntIntents();
|
Map<IntIntentId, IntIntent> getIntIntents();
|
||||||
|
|
||||||
//TODO: [ONOS-7616] Design IntEvent and related APIs
|
//TODO: [ONOS-7616] Design IntEvent and related APIs
|
||||||
}
|
}
|
||||||
|
|||||||
11
apps/inbandtelemetry/app/BUILD
Normal file
11
apps/inbandtelemetry/app/BUILD
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
COMPILE_DEPS = CORE_DEPS + KRYO + JACKSON + [
|
||||||
|
"//core/store/serializers:onos-core-serializers",
|
||||||
|
"//apps/inbandtelemetry/api:onos-apps-inbandtelemetry-api",
|
||||||
|
]
|
||||||
|
|
||||||
|
TEST_DEPS = TEST_REST
|
||||||
|
|
||||||
|
osgi_jar_with_tests(
|
||||||
|
test_deps = TEST_DEPS,
|
||||||
|
deps = COMPILE_DEPS,
|
||||||
|
)
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015-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.inbandtelemetry.app;
|
|
||||||
|
|
||||||
import org.osgi.service.component.annotations.Activate;
|
|
||||||
import org.osgi.service.component.annotations.Deactivate;
|
|
||||||
import org.osgi.service.component.annotations.Reference;
|
|
||||||
import org.osgi.service.component.annotations.Component;
|
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
|
||||||
import org.onosproject.core.CoreService;
|
|
||||||
import org.onosproject.inbandtelemetry.api.IntService;
|
|
||||||
import org.onosproject.net.host.HostService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Component(immediate = true)
|
|
||||||
public class IntControl {
|
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
|
||||||
// private ApplicationId appId;
|
|
||||||
// private static final int collectorPort = 1234;
|
|
||||||
// private static final IpAddress collectorIp = IpAddress.valueOf("10.0.0.3");
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
protected CoreService coreService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
protected IntService intService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
protected HostService hostService;
|
|
||||||
|
|
||||||
@Activate
|
|
||||||
protected void activate() {
|
|
||||||
coreService.registerApplication("org.onosproject.inbandtelemetry.app");
|
|
||||||
log.info("Started");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deactivate
|
|
||||||
protected void deactivate() {
|
|
||||||
log.info("Stopped");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -58,6 +58,10 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ov-int-app-main input {
|
||||||
|
padding: 4px;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.light #ov-int-app-main .int-app-config-button {
|
.light #ov-int-app-main .int-app-config-button {
|
||||||
color: white;
|
color: white;
|
||||||
@ -68,8 +72,25 @@
|
|||||||
background-color: #aaa;
|
background-color: #aaa;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#ov-int-app-main hr {
|
||||||
|
border: 0;
|
||||||
|
height: 1px;
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
|
||||||
#ov-int-app-main h2 {
|
#ov-int-app-main h2 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
margin: 15px 0px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ov-int-app-main h3 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ov-int-app-main h4 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
/* #ov-int-app-main .table-body{
|
/* #ov-int-app-main .table-body{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|||||||
@ -1,62 +1,128 @@
|
|||||||
<!-- partial HTML -->
|
<!-- partial HTML -->
|
||||||
<div id="ov-int-app-main">
|
<div id="ov-int-app-main">
|
||||||
<div class="config-panel">
|
<div class="tabular-header">
|
||||||
<div>
|
<h2 style="font-weight: bold">In-band Network Telemetry (INT) Control
|
||||||
Collector IP
|
Application</h2>
|
||||||
<input type="text" required pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}$" ng-model="collectorIp">
|
</div>
|
||||||
|
|
||||||
Collector Port
|
|
||||||
<input type="text" required pattern="^[0-9]{0,5}$" ng-model="collectorPort">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="config-button-panel">
|
|
||||||
<div class = "int-app-config-button" ng-click="sendIntConfigString()">
|
|
||||||
Deploy
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr>
|
<hr>
|
||||||
<div class="input-panel">
|
|
||||||
<div>
|
|
||||||
Src Address
|
|
||||||
<input type="text" required pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$" ng-model="ip4SrcPrefix">
|
|
||||||
|
|
||||||
Dst Address
|
<div class="tabular-header">
|
||||||
<input type="text" required pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$" ng-model="ip4DstPrefix">
|
<h2>
|
||||||
|
INT Collector Configuration
|
||||||
Src Port
|
</h2>
|
||||||
<input type="text" required pattern="^[0-9]{0,5}$" ng-model="l4SrcPort">
|
<div class="config-panel">
|
||||||
|
<h3>
|
||||||
Dst Port
|
Collector IPv4 address and UDP port
|
||||||
<input type="text" required pattern="^[0-9]{0,5}$" ng-model="l4DstPort">
|
</h3>
|
||||||
|
<div>
|
||||||
Protocol
|
<input type="text" required
|
||||||
<select name="protocol" ng-model="protocol">
|
pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
|
||||||
<option selected disabled hidden style="display: none" value=''></option>
|
ng-model="collectorIp" placeholder="IPv4 address">
|
||||||
<option value="TCP">TCP</option>
|
:
|
||||||
<option value="UDP">UDP</option>
|
<input type="text" required pattern="^[0-9]{0,5}$"
|
||||||
</select>
|
ng-model="collectorPort" placeholder="port">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="config-button-panel">
|
||||||
<input type="checkbox" ng-model= "metaSwId">Switch Id
|
<div class="int-app-config-button" ng-click="sendIntConfigString()">
|
||||||
<input type="checkbox" ng-model= "metaPortId">Port Id
|
Apply Configuration
|
||||||
<input type="checkbox" ng-model= "metaHopLatency">Hop Latency
|
</div>
|
||||||
<input type="checkbox" ng-model= "metaQOccupancy">Queue Occupancy
|
|
||||||
<input type="checkbox" ng-model= "metaIngressTstamp">Ingress Timestamp
|
|
||||||
<input type="checkbox" ng-model= "metaEgressTstamp">Egress Timestamp
|
|
||||||
<!--<input type="checkbox" ng-model= "metaQCongestion">Queue Congestion Status-->
|
|
||||||
<input type="checkbox" ng-model= "metaEgressTx">Egress Port Tx Utilization
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="button-panel">
|
<hr>
|
||||||
<div class = "int-app-button" ng-click="sendIntIntentString()">
|
|
||||||
Deploy
|
<div class="tabular-header">
|
||||||
|
<h2>
|
||||||
|
INT Watchlist Rules
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="input-panel">
|
||||||
|
<h3>
|
||||||
|
Create New Watchlist Rule
|
||||||
|
</h3>
|
||||||
|
<div>
|
||||||
|
<label>
|
||||||
|
<input placeholder="Source IP address" type="text"
|
||||||
|
required
|
||||||
|
pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$"
|
||||||
|
ng-model="ip4SrcPrefix">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input placeholder="Dest IP address" type="text"
|
||||||
|
required
|
||||||
|
pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$"
|
||||||
|
ng-model="ip4DstPrefix">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input placeholder="Source port" type="text" required
|
||||||
|
pattern="^[0-9]{0,5}$"
|
||||||
|
ng-model="l4SrcPort">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input placeholder="Dest port" type="text" required
|
||||||
|
pattern="^[0-9]{0,5}$"
|
||||||
|
ng-model="l4DstPort">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Protocol
|
||||||
|
<select name="protocol" ng-model="protocol">
|
||||||
|
<option selected disabled hidden
|
||||||
|
style="display: none" value=''></option>
|
||||||
|
<option value="TCP">TCP</option>
|
||||||
|
<option value="UDP">UDP</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaSwId">
|
||||||
|
Switch ID
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaPortId">
|
||||||
|
Port IDs
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaHopLatency">
|
||||||
|
Hop Latency
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaQOccupancy">
|
||||||
|
Queue Occupancy
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaIngressTstamp">
|
||||||
|
Ingress Timestamp
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaEgressTstamp">
|
||||||
|
Egress Timestamp
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaQCongestion">
|
||||||
|
Queue Congestion Status
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" ng-model="metaEgressTx">
|
||||||
|
Egress Port Tx Utilization
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-panel">
|
||||||
|
<div class="int-app-button" ng-click="sendIntIntentString()">
|
||||||
|
Apply Watchlist Rule
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||||
<div class='int-app-main-intents'>
|
<div class='int-app-main-intents'>
|
||||||
<div class="tabular-header">
|
<div class="tabular-header">
|
||||||
<h2>Installed INT Intents ({{tableData.length}} total)</h2>
|
<h2>Installed Watchlist Rules ({{tableData.length}} total)</h2>
|
||||||
<div class="ctrl-btns">
|
<div class="ctrl-btns">
|
||||||
<div class="refresh" ng-class="{active: autoRefresh}"
|
<div class="refresh" ng-class="{active: autoRefresh}"
|
||||||
icon icon-id="refresh" icon-size="36"
|
icon icon-id="refresh" icon-size="36"
|
||||||
@ -77,13 +143,13 @@
|
|||||||
<div class="table-header" onos-sortable-header>
|
<div class="table-header" onos-sortable-header>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td colId="id" sortable>ID </td>
|
<td colId="id" sortable>ID</td>
|
||||||
<td colId="srcAddr" sortable>Src Address </td>
|
<td colId="srcAddr" sortable>Src Address</td>
|
||||||
<td colId="dstAddr" sortable>Dst Address </td>
|
<td colId="dstAddr" sortable>Dst Address</td>
|
||||||
<td colId="srcPort" sortable>Src Port </td>
|
<td colId="srcPort" sortable>Src Port</td>
|
||||||
<td colId="dstPort" sortable>Dst Port </td>
|
<td colId="dstPort" sortable>Dst Port</td>
|
||||||
<td colId="protocol" sortable>Protocol </td>
|
<td colId="protocol" sortable>Protocol</td>
|
||||||
<td colId="metadata" sortable>Metadata </td>
|
<td colId="metadata" sortable>Metadata</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
12
apps/inbandtelemetry/impl/BUILD
Normal file
12
apps/inbandtelemetry/impl/BUILD
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
COMPILE_DEPS = CORE_DEPS + KRYO + [
|
||||||
|
"//core/store/serializers:onos-core-serializers",
|
||||||
|
"//pipelines/basic:onos-pipelines-basic",
|
||||||
|
"//apps/inbandtelemetry/api:onos-apps-inbandtelemetry-api",
|
||||||
|
]
|
||||||
|
|
||||||
|
TEST_DEPS = TEST_ADAPTERS
|
||||||
|
|
||||||
|
osgi_jar_with_tests(
|
||||||
|
test_deps = TEST_DEPS,
|
||||||
|
deps = COMPILE_DEPS,
|
||||||
|
)
|
||||||
@ -1,262 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015-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.inbandtelemetry.impl;
|
|
||||||
|
|
||||||
import org.onlab.util.KryoNamespace;
|
|
||||||
import org.onosproject.core.ApplicationId;
|
|
||||||
import org.onosproject.core.CoreService;
|
|
||||||
import org.onosproject.inbandtelemetry.api.IntConfig;
|
|
||||||
import org.onosproject.inbandtelemetry.api.IntIntent;
|
|
||||||
import org.onosproject.inbandtelemetry.api.IntIntentId;
|
|
||||||
import org.onosproject.inbandtelemetry.api.IntObjective;
|
|
||||||
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
|
||||||
import org.onosproject.inbandtelemetry.api.IntService;
|
|
||||||
import org.onosproject.net.Device;
|
|
||||||
import org.onosproject.net.DeviceId;
|
|
||||||
import org.onosproject.net.device.DeviceService;
|
|
||||||
import org.onosproject.net.flow.FlowRuleService;
|
|
||||||
import org.onosproject.net.host.HostEvent;
|
|
||||||
import org.onosproject.net.host.HostListener;
|
|
||||||
import org.onosproject.net.host.HostService;
|
|
||||||
import org.onosproject.store.serializers.KryoNamespaces;
|
|
||||||
import org.onosproject.store.service.AtomicIdGenerator;
|
|
||||||
import org.onosproject.store.service.ConsistentMap;
|
|
||||||
import org.onosproject.store.service.Serializer;
|
|
||||||
import org.onosproject.store.service.StorageService;
|
|
||||||
import org.osgi.service.component.annotations.Activate;
|
|
||||||
import org.osgi.service.component.annotations.Component;
|
|
||||||
import org.osgi.service.component.annotations.Deactivate;
|
|
||||||
import org.osgi.service.component.annotations.Reference;
|
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of IntService, for controlling INT-capable pipelines.
|
|
||||||
*/
|
|
||||||
@Component(immediate = true, service = IntService.class)
|
|
||||||
public class IntManager implements IntService {
|
|
||||||
private final String appName = "org.onosproject.inbandtelemetry";
|
|
||||||
private ApplicationId appId;
|
|
||||||
private final Logger log = getLogger(getClass());
|
|
||||||
private ConsistentMap<IntIntentId, IntIntent> intentConsistentMap;
|
|
||||||
private ConsistentMap<DeviceId, IntDeviceRole> deviceRoleConsistentMap;
|
|
||||||
private IntConfig cfg;
|
|
||||||
private AtomicIdGenerator intentIds;
|
|
||||||
|
|
||||||
private InternalHostListener hostListener = new InternalHostListener();
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private CoreService coreService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private DeviceService deviceService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private StorageService storageService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private HostService hostService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private FlowRuleService flowRuleService;
|
|
||||||
|
|
||||||
@Activate
|
|
||||||
public void activate() {
|
|
||||||
appId = coreService.registerApplication(appName);
|
|
||||||
|
|
||||||
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
|
|
||||||
.register(KryoNamespaces.API)
|
|
||||||
.register(IntIntent.class)
|
|
||||||
.register(IntIntentId.class)
|
|
||||||
.register(IntDeviceRole.class)
|
|
||||||
.register(IntIntent.IntHeaderType.class)
|
|
||||||
.register(IntIntent.IntMetadataType.class)
|
|
||||||
.register(IntIntent.IntReportType.class)
|
|
||||||
.register(IntIntent.TelemetryMode.class);
|
|
||||||
|
|
||||||
intentConsistentMap = storageService.<IntIntentId, IntIntent>consistentMapBuilder()
|
|
||||||
.withSerializer(Serializer.using(serializer.build()))
|
|
||||||
.withName("int-intents")
|
|
||||||
.withApplicationId(appId)
|
|
||||||
.withPurgeOnUninstall()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
deviceRoleConsistentMap = storageService.<DeviceId, IntDeviceRole>consistentMapBuilder()
|
|
||||||
.withSerializer(Serializer.using(serializer.build()))
|
|
||||||
.withName("int-device-roles")
|
|
||||||
.withApplicationId(appId)
|
|
||||||
.withPurgeOnUninstall()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Assign IntDeviceRole to each device
|
|
||||||
deviceService.getAvailableDevices().forEach(device ->
|
|
||||||
deviceRoleConsistentMap.put(device.id(),
|
|
||||||
hostService.getConnectedHosts(device.id()).isEmpty() ?
|
|
||||||
IntDeviceRole.TRANSIT :
|
|
||||||
IntDeviceRole.SOURCE_SINK)
|
|
||||||
);
|
|
||||||
hostService.addListener(hostListener);
|
|
||||||
intentIds = storageService.getAtomicIdGenerator("int-intent-id-generator");
|
|
||||||
startInt();
|
|
||||||
log.info("Started", appId.id());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deactivate
|
|
||||||
public void deactivate() {
|
|
||||||
hostService.removeListener(hostListener);
|
|
||||||
log.info("Deactivated");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startInt() {
|
|
||||||
deviceService.getAvailableDevices().forEach(device -> {
|
|
||||||
if (device.is(IntProgrammable.class)) {
|
|
||||||
IntProgrammable intDevice = device.as(IntProgrammable.class);
|
|
||||||
intDevice.init();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startInt(Set<DeviceId> deviceIds) {
|
|
||||||
deviceIds.forEach(deviceId -> {
|
|
||||||
Device device = deviceService.getDevice(deviceId);
|
|
||||||
if (device.is(IntProgrammable.class) &&
|
|
||||||
getIntRole(deviceId) == IntDeviceRole.TRANSIT) {
|
|
||||||
IntProgrammable intDevice = device.as(IntProgrammable.class);
|
|
||||||
intDevice.init();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopInt() {
|
|
||||||
flowRuleService.removeFlowRulesById(appId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopInt(Set<DeviceId> deviceIds) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConfig(IntConfig cfg) {
|
|
||||||
this.cfg = cfg;
|
|
||||||
deviceService.getAvailableDevices().forEach(device -> {
|
|
||||||
if (device.is(IntProgrammable.class)) {
|
|
||||||
IntProgrammable intDevice = device.as(IntProgrammable.class);
|
|
||||||
intDevice.setupIntConfig(cfg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IntConfig getConfig() {
|
|
||||||
return cfg;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IntIntentId installIntIntent(IntIntent intent) {
|
|
||||||
Integer intentId = (int) intentIds.nextId();
|
|
||||||
IntIntentId intIntentId = IntIntentId.valueOf(intentId);
|
|
||||||
intentConsistentMap.put(intIntentId, intent);
|
|
||||||
|
|
||||||
// Convert IntIntent into an IntObjective
|
|
||||||
IntObjective obj = new IntObjective.Builder()
|
|
||||||
.withSelector(intent.selector())
|
|
||||||
.withMetadataTypes(intent.metadataTypes())
|
|
||||||
.withHeaderType(intent.headerType())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Install IntObjective on each INT source device
|
|
||||||
deviceService.getAvailableDevices().forEach(device -> {
|
|
||||||
if (device.is(IntProgrammable.class)
|
|
||||||
&& deviceRoleConsistentMap.get(device.id()).value() == IntDeviceRole.SOURCE_SINK) {
|
|
||||||
IntProgrammable intDevice = device.as(IntProgrammable.class);
|
|
||||||
intDevice.addIntObjective(obj);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return intIntentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeIntIntent(IntIntentId intentId) {
|
|
||||||
IntIntent intent = intentConsistentMap.remove(intentId).value();
|
|
||||||
|
|
||||||
// Convert IntIntent into an IntObjective
|
|
||||||
IntObjective obj = new IntObjective.Builder()
|
|
||||||
.withSelector(intent.selector())
|
|
||||||
.withMetadataTypes(intent.metadataTypes())
|
|
||||||
.withHeaderType(intent.headerType())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Remove IntObjective on each INT source device
|
|
||||||
deviceService.getAvailableDevices().forEach(device -> {
|
|
||||||
if (device.is(IntProgrammable.class)
|
|
||||||
&& deviceRoleConsistentMap.get(device.id()).value() == IntDeviceRole.SOURCE_SINK) {
|
|
||||||
IntProgrammable intDevice = device.as(IntProgrammable.class);
|
|
||||||
intDevice.removeIntObjective(obj);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IntIntent getIntIntent(IntIntentId intentId) {
|
|
||||||
return Optional.ofNullable(intentConsistentMap.get(intentId).value()).orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<IntIntentId, IntIntent> getIntIntents() {
|
|
||||||
return intentConsistentMap.asJavaMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IntDeviceRole getIntRole(DeviceId deviceId) {
|
|
||||||
return deviceRoleConsistentMap.get(deviceId).value();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setIntRole(DeviceId deviceId, IntDeviceRole role) {
|
|
||||||
deviceRoleConsistentMap.put(deviceId, role);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class InternalHostListener implements HostListener {
|
|
||||||
@Override
|
|
||||||
public void event(HostEvent event) {
|
|
||||||
DeviceId deviceId = event.subject().location().deviceId();
|
|
||||||
if (!deviceService.getDevice(deviceId).is(IntProgrammable.class)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (event.type()) {
|
|
||||||
case HOST_ADDED:
|
|
||||||
// When a host is attached to the switch, we can configure it
|
|
||||||
// to work as SOURCE_SINK switch.
|
|
||||||
if (deviceRoleConsistentMap.getOrDefault(deviceId, IntDeviceRole.TRANSIT).value()
|
|
||||||
!= IntDeviceRole.SOURCE_SINK) {
|
|
||||||
setIntRole(deviceId, IntDeviceRole.SOURCE_SINK);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,525 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-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.inbandtelemetry.impl;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.util.concurrent.Striped;
|
||||||
|
import org.onlab.util.KryoNamespace;
|
||||||
|
import org.onlab.util.SharedScheduledExecutors;
|
||||||
|
import org.onosproject.core.ApplicationId;
|
||||||
|
import org.onosproject.core.CoreService;
|
||||||
|
import org.onosproject.inbandtelemetry.api.IntConfig;
|
||||||
|
import org.onosproject.inbandtelemetry.api.IntIntent;
|
||||||
|
import org.onosproject.inbandtelemetry.api.IntIntentId;
|
||||||
|
import org.onosproject.inbandtelemetry.api.IntObjective;
|
||||||
|
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
||||||
|
import org.onosproject.inbandtelemetry.api.IntService;
|
||||||
|
import org.onosproject.mastership.MastershipService;
|
||||||
|
import org.onosproject.net.ConnectPoint;
|
||||||
|
import org.onosproject.net.Device;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.MastershipRole;
|
||||||
|
import org.onosproject.net.PortNumber;
|
||||||
|
import org.onosproject.net.device.DeviceEvent;
|
||||||
|
import org.onosproject.net.device.DeviceListener;
|
||||||
|
import org.onosproject.net.device.DeviceService;
|
||||||
|
import org.onosproject.net.host.HostEvent;
|
||||||
|
import org.onosproject.net.host.HostListener;
|
||||||
|
import org.onosproject.net.host.HostService;
|
||||||
|
import org.onosproject.store.serializers.KryoNamespaces;
|
||||||
|
import org.onosproject.store.service.AtomicIdGenerator;
|
||||||
|
import org.onosproject.store.service.AtomicValue;
|
||||||
|
import org.onosproject.store.service.AtomicValueEvent;
|
||||||
|
import org.onosproject.store.service.AtomicValueEventListener;
|
||||||
|
import org.onosproject.store.service.ConsistentMap;
|
||||||
|
import org.onosproject.store.service.MapEvent;
|
||||||
|
import org.onosproject.store.service.MapEventListener;
|
||||||
|
import org.onosproject.store.service.Serializer;
|
||||||
|
import org.onosproject.store.service.StorageService;
|
||||||
|
import org.onosproject.store.service.Versioned;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Deactivate;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple implementation of IntService, for controlling INT-capable pipelines.
|
||||||
|
* <p>
|
||||||
|
* All INT intents are converted to an equivalent INT objective and applied to
|
||||||
|
* all SOURCE_SINK devices. A device is deemed SOURCE_SINK if it has at least
|
||||||
|
* one host attached.
|
||||||
|
* <p>
|
||||||
|
* The implementation listens for different types of events and when required it
|
||||||
|
* configures a device by cleaning-up any previous state and applying the new
|
||||||
|
* one.
|
||||||
|
*/
|
||||||
|
@Component(immediate = true, service = IntService.class)
|
||||||
|
public class SimpleIntManager implements IntService {
|
||||||
|
|
||||||
|
private final Logger log = getLogger(getClass());
|
||||||
|
|
||||||
|
private static final int CONFIG_EVENT_DELAY = 5; // Seconds.
|
||||||
|
|
||||||
|
private static final String APP_NAME = "org.onosproject.inbandtelemetry";
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
|
private CoreService coreService;
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
|
private StorageService storageService;
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
|
private MastershipService mastershipService;
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
|
private HostService hostService;
|
||||||
|
|
||||||
|
private final Striped<Lock> deviceLocks = Striped.lock(10);
|
||||||
|
|
||||||
|
private final ConcurrentMap<DeviceId, ScheduledFuture<?>> scheduledDeviceTasks = Maps.newConcurrentMap();
|
||||||
|
|
||||||
|
// Distributed state.
|
||||||
|
private ConsistentMap<IntIntentId, IntIntent> intentMap;
|
||||||
|
private ConsistentMap<DeviceId, Long> devicesToConfigure;
|
||||||
|
private AtomicValue<IntConfig> intConfig;
|
||||||
|
private AtomicValue<Boolean> intStarted;
|
||||||
|
private AtomicIdGenerator intentIds;
|
||||||
|
|
||||||
|
// Event listeners.
|
||||||
|
private final InternalHostListener hostListener = new InternalHostListener();
|
||||||
|
private final InternalDeviceListener deviceListener = new InternalDeviceListener();
|
||||||
|
private final InternalIntentMapListener intentMapListener = new InternalIntentMapListener();
|
||||||
|
private final InternalIntConfigListener intConfigListener = new InternalIntConfigListener();
|
||||||
|
private final InternalIntStartedListener intStartedListener = new InternalIntStartedListener();
|
||||||
|
private final InternalDeviceToConfigureListener devicesToConfigureListener =
|
||||||
|
new InternalDeviceToConfigureListener();
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public void activate() {
|
||||||
|
|
||||||
|
final ApplicationId appId = coreService.registerApplication(APP_NAME);
|
||||||
|
|
||||||
|
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
|
||||||
|
.register(KryoNamespaces.API)
|
||||||
|
.register(IntIntent.class)
|
||||||
|
.register(IntIntentId.class)
|
||||||
|
.register(IntDeviceRole.class)
|
||||||
|
.register(IntIntent.IntHeaderType.class)
|
||||||
|
.register(IntIntent.IntMetadataType.class)
|
||||||
|
.register(IntIntent.IntReportType.class)
|
||||||
|
.register(IntIntent.TelemetryMode.class)
|
||||||
|
.register(IntConfig.class)
|
||||||
|
.register(IntConfig.TelemetrySpec.class);
|
||||||
|
|
||||||
|
devicesToConfigure = storageService.<DeviceId, Long>consistentMapBuilder()
|
||||||
|
.withSerializer(Serializer.using(serializer.build()))
|
||||||
|
.withName("onos-int-devices-to-configure")
|
||||||
|
.withApplicationId(appId)
|
||||||
|
.withPurgeOnUninstall()
|
||||||
|
.build();
|
||||||
|
devicesToConfigure.addListener(devicesToConfigureListener);
|
||||||
|
|
||||||
|
intentMap = storageService.<IntIntentId, IntIntent>consistentMapBuilder()
|
||||||
|
.withSerializer(Serializer.using(serializer.build()))
|
||||||
|
.withName("onos-int-intents")
|
||||||
|
.withApplicationId(appId)
|
||||||
|
.withPurgeOnUninstall()
|
||||||
|
.build();
|
||||||
|
intentMap.addListener(intentMapListener);
|
||||||
|
|
||||||
|
intStarted = storageService.<Boolean>atomicValueBuilder()
|
||||||
|
.withSerializer(Serializer.using(serializer.build()))
|
||||||
|
.withName("onos-int-started")
|
||||||
|
.withApplicationId(appId)
|
||||||
|
.build()
|
||||||
|
.asAtomicValue();
|
||||||
|
intStarted.addListener(intStartedListener);
|
||||||
|
|
||||||
|
intConfig = storageService.<IntConfig>atomicValueBuilder()
|
||||||
|
.withSerializer(Serializer.using(serializer.build()))
|
||||||
|
.withName("onos-int-config")
|
||||||
|
.withApplicationId(appId)
|
||||||
|
.build()
|
||||||
|
.asAtomicValue();
|
||||||
|
intConfig.addListener(intConfigListener);
|
||||||
|
|
||||||
|
intentIds = storageService.getAtomicIdGenerator("int-intent-id-generator");
|
||||||
|
|
||||||
|
// Bootstrap config for already existing devices.
|
||||||
|
triggerAllDeviceConfigure();
|
||||||
|
|
||||||
|
hostService.addListener(hostListener);
|
||||||
|
deviceService.addListener(deviceListener);
|
||||||
|
|
||||||
|
startInt();
|
||||||
|
log.info("Started", appId.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deactivate
|
||||||
|
public void deactivate() {
|
||||||
|
deviceService.removeListener(deviceListener);
|
||||||
|
hostService.removeListener(hostListener);
|
||||||
|
intentIds = null;
|
||||||
|
intConfig.removeListener(intConfigListener);
|
||||||
|
intConfig = null;
|
||||||
|
intStarted.removeListener(intStartedListener);
|
||||||
|
intStarted = null;
|
||||||
|
intentMap.removeListener(intentMapListener);
|
||||||
|
intentMap = null;
|
||||||
|
devicesToConfigure.removeListener(devicesToConfigureListener);
|
||||||
|
devicesToConfigure.destroy();
|
||||||
|
devicesToConfigure = null;
|
||||||
|
// Cancel tasks (if any).
|
||||||
|
scheduledDeviceTasks.values().forEach(f -> {
|
||||||
|
f.cancel(true);
|
||||||
|
if (!f.isDone()) {
|
||||||
|
try {
|
||||||
|
f.get(1, TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
|
// Don't care, we are terminating the service anyways.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Clean up INT rules from existing devices.
|
||||||
|
deviceService.getDevices().forEach(d -> cleanupDevice(d.id()));
|
||||||
|
log.info("Deactivated");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startInt() {
|
||||||
|
// Atomic value event will trigger device configure.
|
||||||
|
intStarted.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startInt(Set<DeviceId> deviceIds) {
|
||||||
|
log.warn("Starting INT for a subset of devices is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopInt() {
|
||||||
|
// Atomic value event will trigger device configure.
|
||||||
|
intStarted.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopInt(Set<DeviceId> deviceIds) {
|
||||||
|
log.warn("Stopping INT for a subset of devices is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConfig(IntConfig cfg) {
|
||||||
|
checkNotNull(cfg);
|
||||||
|
// Atomic value event will trigger device configure.
|
||||||
|
intConfig.set(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntConfig getConfig() {
|
||||||
|
return intConfig.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntIntentId installIntIntent(IntIntent intent) {
|
||||||
|
checkNotNull(intent);
|
||||||
|
final Integer intentId = (int) intentIds.nextId();
|
||||||
|
final IntIntentId intIntentId = IntIntentId.valueOf(intentId);
|
||||||
|
// Intent map event will trigger device configure.
|
||||||
|
intentMap.put(intIntentId, intent);
|
||||||
|
return intIntentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeIntIntent(IntIntentId intentId) {
|
||||||
|
checkNotNull(intentId);
|
||||||
|
// Intent map event will trigger device configure.
|
||||||
|
intentMap.remove(intentId).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntIntent getIntIntent(IntIntentId intentId) {
|
||||||
|
return Optional.ofNullable(intentMap.get(intentId).value()).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<IntIntentId, IntIntent> getIntIntents() {
|
||||||
|
return intentMap.asJavaMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isConfigTaskValid(DeviceId deviceId, long creationTime) {
|
||||||
|
Versioned<?> versioned = devicesToConfigure.get(deviceId);
|
||||||
|
return versioned != null && versioned.creationTime() == creationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isIntStarted() {
|
||||||
|
return intStarted.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNotIntConfigured() {
|
||||||
|
return intConfig.get() == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isIntProgrammable(DeviceId deviceId) {
|
||||||
|
final Device device = deviceService.getDevice(deviceId);
|
||||||
|
return device != null && device.is(IntProgrammable.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerDeviceConfigure(DeviceId deviceId) {
|
||||||
|
if (isIntProgrammable(deviceId)) {
|
||||||
|
devicesToConfigure.put(deviceId, System.nanoTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerAllDeviceConfigure() {
|
||||||
|
deviceService.getDevices().forEach(d -> triggerDeviceConfigure(d.id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configDeviceTask(DeviceId deviceId, long creationTime) {
|
||||||
|
if (isConfigTaskValid(deviceId, creationTime)) {
|
||||||
|
// Task outdated.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!deviceService.isAvailable(deviceId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final MastershipRole role = mastershipService.requestRoleForSync(deviceId);
|
||||||
|
if (!role.equals(MastershipRole.MASTER)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deviceLocks.get(deviceId).lock();
|
||||||
|
try {
|
||||||
|
// Clean up first.
|
||||||
|
cleanupDevice(deviceId);
|
||||||
|
if (!configDevice(deviceId)) {
|
||||||
|
// Clean up if fails.
|
||||||
|
cleanupDevice(deviceId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
devicesToConfigure.remove(deviceId);
|
||||||
|
} finally {
|
||||||
|
deviceLocks.get(deviceId).unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanupDevice(DeviceId deviceId) {
|
||||||
|
final Device device = deviceService.getDevice(deviceId);
|
||||||
|
if (device == null || !device.is(IntProgrammable.class)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
device.as(IntProgrammable.class).cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean configDevice(DeviceId deviceId) {
|
||||||
|
// Returns true if config was successful, false if not and a clean up is
|
||||||
|
// needed.
|
||||||
|
final Device device = deviceService.getDevice(deviceId);
|
||||||
|
if (device == null || !device.is(IntProgrammable.class)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotIntConfigured()) {
|
||||||
|
log.warn("Missing INT config, aborting programming of INT device {}", deviceId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean isEdge = !hostService.getConnectedHosts(deviceId).isEmpty();
|
||||||
|
final IntDeviceRole intDeviceRole = isEdge
|
||||||
|
? IntDeviceRole.SOURCE_SINK
|
||||||
|
: IntDeviceRole.TRANSIT;
|
||||||
|
|
||||||
|
log.info("Started programming of INT device {} with role {}...",
|
||||||
|
deviceId, intDeviceRole);
|
||||||
|
|
||||||
|
final IntProgrammable intProg = device.as(IntProgrammable.class);
|
||||||
|
|
||||||
|
if (!isIntStarted()) {
|
||||||
|
// Leave device with no INT configuration.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!intProg.init()) {
|
||||||
|
log.warn("Unable to init INT pipeline on {}", deviceId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intDeviceRole != IntDeviceRole.SOURCE_SINK) {
|
||||||
|
// Stop here, no more configuration needed for transit devices.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intProg.supportsFunctionality(IntProgrammable.IntFunctionality.SINK)) {
|
||||||
|
if (!intProg.setupIntConfig(intConfig.get())) {
|
||||||
|
log.warn("Unable to apply INT report config on {}", deviceId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port configuration.
|
||||||
|
final Set<PortNumber> hostPorts = deviceService.getPorts(deviceId)
|
||||||
|
.stream()
|
||||||
|
.map(port -> new ConnectPoint(deviceId, port.number()))
|
||||||
|
.filter(cp -> !hostService.getConnectedHosts(cp).isEmpty())
|
||||||
|
.map(ConnectPoint::port)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
for (PortNumber port : hostPorts) {
|
||||||
|
if (intProg.supportsFunctionality(IntProgrammable.IntFunctionality.SOURCE)) {
|
||||||
|
log.info("Setting port {}/{} as INT source port...", deviceId, port);
|
||||||
|
if (!intProg.setSourcePort(port)) {
|
||||||
|
log.warn("Unable to set INT source port {} on {}", port, deviceId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (intProg.supportsFunctionality(IntProgrammable.IntFunctionality.SINK)) {
|
||||||
|
log.info("Setting port {}/{} as INT sink port...", deviceId, port);
|
||||||
|
if (!intProg.setSinkPort(port)) {
|
||||||
|
log.warn("Unable to set INT sink port {} on {}", port, deviceId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!intProg.supportsFunctionality(IntProgrammable.IntFunctionality.SOURCE)) {
|
||||||
|
// Stop here, no more configuration needed for sink devices.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply intents.
|
||||||
|
// This is a trivial implementation where we simply get the
|
||||||
|
// corresponding INT objective from an intent and we apply to all source
|
||||||
|
// device.
|
||||||
|
final Collection<IntObjective> objectives = intentMap.values().stream()
|
||||||
|
.map(v -> getIntObjective(v.value()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
int appliedCount = 0;
|
||||||
|
for (IntObjective objective : objectives) {
|
||||||
|
if (intProg.addIntObjective(objective)) {
|
||||||
|
appliedCount = appliedCount + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Completed programming of {}, applied {} INT objectives of {} total",
|
||||||
|
deviceId, appliedCount, objectives.size());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntObjective getIntObjective(IntIntent intent) {
|
||||||
|
return new IntObjective.Builder()
|
||||||
|
.withSelector(intent.selector())
|
||||||
|
.withMetadataTypes(intent.metadataTypes())
|
||||||
|
.withHeaderType(intent.headerType())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Event listeners which trigger device configuration. */
|
||||||
|
|
||||||
|
private class InternalHostListener implements HostListener {
|
||||||
|
@Override
|
||||||
|
public void event(HostEvent event) {
|
||||||
|
final DeviceId deviceId = event.subject().location().deviceId();
|
||||||
|
triggerDeviceConfigure(deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InternalDeviceListener implements DeviceListener {
|
||||||
|
@Override
|
||||||
|
public void event(DeviceEvent event) {
|
||||||
|
switch (event.type()) {
|
||||||
|
case DEVICE_ADDED:
|
||||||
|
case DEVICE_UPDATED:
|
||||||
|
case DEVICE_REMOVED:
|
||||||
|
case DEVICE_SUSPENDED:
|
||||||
|
case DEVICE_AVAILABILITY_CHANGED:
|
||||||
|
case PORT_ADDED:
|
||||||
|
case PORT_UPDATED:
|
||||||
|
case PORT_REMOVED:
|
||||||
|
triggerDeviceConfigure(event.subject().id());
|
||||||
|
return;
|
||||||
|
case PORT_STATS_UPDATED:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
log.warn("Unknown device event type {}", event.type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InternalIntentMapListener
|
||||||
|
implements MapEventListener<IntIntentId, IntIntent> {
|
||||||
|
@Override
|
||||||
|
public void event(MapEvent<IntIntentId, IntIntent> event) {
|
||||||
|
triggerAllDeviceConfigure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InternalIntConfigListener
|
||||||
|
implements AtomicValueEventListener<IntConfig> {
|
||||||
|
@Override
|
||||||
|
public void event(AtomicValueEvent<IntConfig> event) {
|
||||||
|
triggerAllDeviceConfigure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InternalIntStartedListener
|
||||||
|
implements AtomicValueEventListener<Boolean> {
|
||||||
|
@Override
|
||||||
|
public void event(AtomicValueEvent<Boolean> event) {
|
||||||
|
triggerAllDeviceConfigure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InternalDeviceToConfigureListener
|
||||||
|
implements MapEventListener<DeviceId, Long> {
|
||||||
|
@Override
|
||||||
|
public void event(MapEvent<DeviceId, Long> event) {
|
||||||
|
if (event.type().equals(MapEvent.Type.REMOVE) ||
|
||||||
|
event.newValue() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Schedule task in the future. Wait for events for this device to
|
||||||
|
// stabilize.
|
||||||
|
final DeviceId deviceId = event.key();
|
||||||
|
final long creationTime = event.newValue().creationTime();
|
||||||
|
ScheduledFuture<?> newTask = SharedScheduledExecutors.newTimeout(
|
||||||
|
() -> configDeviceTask(deviceId, creationTime),
|
||||||
|
CONFIG_EVENT_DELAY, TimeUnit.SECONDS);
|
||||||
|
ScheduledFuture<?> oldTask = scheduledDeviceTasks.put(deviceId, newTask);
|
||||||
|
if (oldTask != null) {
|
||||||
|
oldTask.cancel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -124,7 +124,6 @@ public final class DefaultPrometheusTelemetryConfig implements PrometheusTelemet
|
|||||||
@Override
|
@Override
|
||||||
public PrometheusTelemetryConfig build() {
|
public PrometheusTelemetryConfig build() {
|
||||||
checkNotNull(address, "Prometheus exporter binding address cannot be null");
|
checkNotNull(address, "Prometheus exporter binding address cannot be null");
|
||||||
checkNotNull(configMap, "Config map cannot be null");
|
|
||||||
return new DefaultPrometheusTelemetryConfig(address, port, configMap);
|
return new DefaultPrometheusTelemetryConfig(address, port, configMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ public abstract class AbstractAnnotated implements Annotated {
|
|||||||
*/
|
*/
|
||||||
protected AbstractAnnotated(Annotations... annotations) {
|
protected AbstractAnnotated(Annotations... annotations) {
|
||||||
checkArgument(annotations.length <= 1, "Only one set of annotations is expected");
|
checkArgument(annotations.length <= 1, "Only one set of annotations is expected");
|
||||||
this.annotations = annotations.length == 1 ? annotations[0] : EMPTY;
|
this.annotations = annotations.length == 0 || annotations[0] == null ? EMPTY : annotations[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -100,6 +100,14 @@ public interface PiPipeconf {
|
|||||||
/**
|
/**
|
||||||
* Barefoot's Tofino context JSON.
|
* Barefoot's Tofino context JSON.
|
||||||
*/
|
*/
|
||||||
TOFINO_CONTEXT_JSON
|
TOFINO_CONTEXT_JSON,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU port file in UTF 8 encoding.
|
||||||
|
*/
|
||||||
|
// TODO: consider a better way to get the CPU port in the interpreter
|
||||||
|
// (see FabricInterpreter.java mapLogicalPortNumber). Perhaps using
|
||||||
|
// pipeconf annotations?
|
||||||
|
CPU_PORT_TXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,6 +125,18 @@ public interface PiPipelineInterpreter extends HandlerBehaviour {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given table allows for mutable default actions, this method
|
||||||
|
* returns an action instance to be used when ONOS tries to remove a
|
||||||
|
* different default action previously set.
|
||||||
|
*
|
||||||
|
* @param tableId table ID
|
||||||
|
* @return optional default action
|
||||||
|
*/
|
||||||
|
default Optional<PiAction> getOriginalDefaultAction(PiTableId tableId) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that an error was encountered while executing the interpreter.
|
* Signals that an error was encountered while executing the interpreter.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -42,8 +42,9 @@ public interface PiTableModel {
|
|||||||
PiTableType tableType();
|
PiTableType tableType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the model of the action profile that implements this table. Meaningful if this table is of type {@link
|
* Returns the model of the action profile that implements this table.
|
||||||
* PiTableType#INDIRECT}, otherwise returns null.
|
* Meaningful if this table is of type {@link PiTableType#INDIRECT},
|
||||||
|
* otherwise returns null.
|
||||||
*
|
*
|
||||||
* @return action profile ID
|
* @return action profile ID
|
||||||
*/
|
*/
|
||||||
@ -92,16 +93,19 @@ public interface PiTableModel {
|
|||||||
Collection<PiActionModel> actions();
|
Collection<PiActionModel> actions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the model of the default action associated with this table, if any.
|
* Returns the model of the constant default action associated with this
|
||||||
|
* table, if any.
|
||||||
*
|
*
|
||||||
* @return optional default action model
|
* @return optional default action model
|
||||||
*/
|
*/
|
||||||
Optional<PiActionModel> defaultAction();
|
Optional<PiActionModel> constDefaultAction();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the default action has mutable parameters that can be changed at runtime, false otherwise.
|
* Returns true if the default action has mutable parameters that can be
|
||||||
|
* changed at runtime, false otherwise.
|
||||||
*
|
*
|
||||||
* @return true if the default action has mutable parameters, false otherwise
|
* @return true if the default action has mutable parameters, false
|
||||||
|
* otherwise
|
||||||
*/
|
*/
|
||||||
boolean hasDefaultMutableParams();
|
boolean hasDefaultMutableParams();
|
||||||
|
|
||||||
@ -114,8 +118,8 @@ public interface PiTableModel {
|
|||||||
boolean isConstantTable();
|
boolean isConstantTable();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the action model associated with the given ID, if present. If not present, it means that this table does
|
* Returns the action model associated with the given ID, if present. If not
|
||||||
* not support such an action.
|
* present, it means that this table does not support such an action.
|
||||||
*
|
*
|
||||||
* @param actionId action ID
|
* @param actionId action ID
|
||||||
* @return optional action model
|
* @return optional action model
|
||||||
@ -123,8 +127,9 @@ public interface PiTableModel {
|
|||||||
Optional<PiActionModel> action(PiActionId actionId);
|
Optional<PiActionModel> action(PiActionId actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the match field model associated with the given ID, if present. If not present, it means that this table
|
* Returns the match field model associated with the given ID, if present.
|
||||||
* does not support such a match field.
|
* If not present, it means that this table does not support such a match
|
||||||
|
* field.
|
||||||
*
|
*
|
||||||
* @param matchFieldId match field ID
|
* @param matchFieldId match field ID
|
||||||
* @return optional match field model
|
* @return optional match field model
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.google.common.annotations.Beta;
|
|||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.pi.model.PiActionProfileId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global identifier of a PI action group applied to a device, uniquely defined
|
* Global identifier of a PI action group applied to a device, uniquely defined
|
||||||
@ -28,8 +29,13 @@ import org.onosproject.net.DeviceId;
|
|||||||
@Beta
|
@Beta
|
||||||
public final class PiActionGroupHandle extends PiHandle<PiActionGroup> {
|
public final class PiActionGroupHandle extends PiHandle<PiActionGroup> {
|
||||||
|
|
||||||
|
private final PiActionProfileId actionProfileId;
|
||||||
|
private final PiActionGroupId groupId;
|
||||||
|
|
||||||
private PiActionGroupHandle(DeviceId deviceId, PiActionGroup group) {
|
private PiActionGroupHandle(DeviceId deviceId, PiActionGroup group) {
|
||||||
super(deviceId, group);
|
super(deviceId);
|
||||||
|
actionProfileId = group.actionProfileId();
|
||||||
|
groupId = group.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,11 +50,16 @@ public final class PiActionGroupHandle extends PiHandle<PiActionGroup> {
|
|||||||
return new PiActionGroupHandle(deviceId, group);
|
return new PiActionGroupHandle(deviceId, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PiEntityType entityType() {
|
||||||
|
return PiEntityType.GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(deviceId(),
|
return Objects.hashCode(deviceId(),
|
||||||
piEntity().actionProfileId(),
|
actionProfileId,
|
||||||
piEntity().id());
|
groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -61,17 +72,17 @@ public final class PiActionGroupHandle extends PiHandle<PiActionGroup> {
|
|||||||
}
|
}
|
||||||
PiActionGroupHandle that = (PiActionGroupHandle) o;
|
PiActionGroupHandle that = (PiActionGroupHandle) o;
|
||||||
return Objects.equal(deviceId(), that.deviceId()) &&
|
return Objects.equal(deviceId(), that.deviceId()) &&
|
||||||
Objects.equal(piEntity().actionProfileId(),
|
Objects.equal(actionProfileId,
|
||||||
that.piEntity().actionProfileId()) &&
|
that.actionProfileId) &&
|
||||||
Objects.equal(piEntity().id(), that.piEntity().id());
|
Objects.equal(groupId, that.groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
.add("deviceId", deviceId())
|
.add("deviceId", deviceId())
|
||||||
.add("actionProfileId", piEntity().actionProfileId())
|
.add("actionProfileId", actionProfileId)
|
||||||
.add("groupId", piEntity().id())
|
.add("groupId", groupId)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ package org.onosproject.net.pi.runtime;
|
|||||||
import com.google.common.annotations.Beta;
|
import com.google.common.annotations.Beta;
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import org.onosproject.net.pi.model.PiActionProfileId;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -28,11 +29,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
@Beta
|
@Beta
|
||||||
public final class PiActionGroupMember implements PiEntity {
|
public final class PiActionGroupMember implements PiEntity {
|
||||||
|
|
||||||
|
private final PiActionProfileId actionProfileId;
|
||||||
private final PiActionGroupMemberId id;
|
private final PiActionGroupMemberId id;
|
||||||
private final PiAction action;
|
private final PiAction action;
|
||||||
|
// FIXME: in P4Runtime weight is an attribute of the member reference in a
|
||||||
|
// group. Either remove it from this class or define the containing group
|
||||||
|
// ID.
|
||||||
private final int weight;
|
private final int weight;
|
||||||
|
|
||||||
private PiActionGroupMember(PiActionGroupMemberId id, PiAction action, int weight) {
|
private PiActionGroupMember(
|
||||||
|
PiActionProfileId actionProfileId, PiActionGroupMemberId id,
|
||||||
|
PiAction action, int weight) {
|
||||||
|
this.actionProfileId = actionProfileId;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
@ -47,6 +55,15 @@ public final class PiActionGroupMember implements PiEntity {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the identifier of the action profile.
|
||||||
|
*
|
||||||
|
* @return action profile identifier
|
||||||
|
*/
|
||||||
|
public PiActionProfileId actionProfile() {
|
||||||
|
return actionProfileId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the action associated to this member.
|
* Returns the action associated to this member.
|
||||||
*
|
*
|
||||||
@ -80,18 +97,20 @@ public final class PiActionGroupMember implements PiEntity {
|
|||||||
}
|
}
|
||||||
PiActionGroupMember that = (PiActionGroupMember) o;
|
PiActionGroupMember that = (PiActionGroupMember) o;
|
||||||
return weight == that.weight &&
|
return weight == that.weight &&
|
||||||
|
Objects.equal(actionProfileId, that.actionProfileId) &&
|
||||||
Objects.equal(id, that.id) &&
|
Objects.equal(id, that.id) &&
|
||||||
Objects.equal(action, that.action);
|
Objects.equal(action, that.action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(id, action, weight);
|
return Objects.hashCode(actionProfileId, id, action, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
|
.add("actionProfile", actionProfileId)
|
||||||
.add("id", id)
|
.add("id", id)
|
||||||
.add("action", action)
|
.add("action", action)
|
||||||
.add("weight", weight)
|
.add("weight", weight)
|
||||||
@ -112,6 +131,7 @@ public final class PiActionGroupMember implements PiEntity {
|
|||||||
*/
|
*/
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
|
|
||||||
|
private PiActionProfileId actionProfileId;
|
||||||
private PiActionGroupMemberId id;
|
private PiActionGroupMemberId id;
|
||||||
private PiAction action;
|
private PiAction action;
|
||||||
private int weight;
|
private int weight;
|
||||||
@ -120,6 +140,17 @@ public final class PiActionGroupMember implements PiEntity {
|
|||||||
// Hides constructor.
|
// Hides constructor.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the action profile identifier of this member.
|
||||||
|
*
|
||||||
|
* @param actionProfileId action profile identifier
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder forActionProfile(PiActionProfileId actionProfileId) {
|
||||||
|
this.actionProfileId = actionProfileId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the identifier of this member.
|
* Sets the identifier of this member.
|
||||||
*
|
*
|
||||||
@ -161,9 +192,10 @@ public final class PiActionGroupMember implements PiEntity {
|
|||||||
* @return action group member
|
* @return action group member
|
||||||
*/
|
*/
|
||||||
public PiActionGroupMember build() {
|
public PiActionGroupMember build() {
|
||||||
|
checkNotNull(actionProfileId);
|
||||||
checkNotNull(id);
|
checkNotNull(id);
|
||||||
checkNotNull(action);
|
checkNotNull(action);
|
||||||
return new PiActionGroupMember(id, action, weight);
|
return new PiActionGroupMember(actionProfileId, id, action, weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* 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.base.MoreObjects;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.pi.model.PiActionProfileId;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global identifier of a PI action profile group member, uniquely defined by a
|
||||||
|
* device ID, action profile ID, and member ID.
|
||||||
|
*/
|
||||||
|
public final class PiActionGroupMemberHandle extends PiHandle<PiActionGroupMember> {
|
||||||
|
|
||||||
|
private final PiActionGroupMemberId memberId;
|
||||||
|
private final PiActionProfileId actionProfileId;
|
||||||
|
|
||||||
|
private PiActionGroupMemberHandle(DeviceId deviceId,
|
||||||
|
PiActionProfileId actionProfileId,
|
||||||
|
PiActionGroupMemberId memberId) {
|
||||||
|
super(deviceId);
|
||||||
|
this.actionProfileId = actionProfileId;
|
||||||
|
this.memberId = memberId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new handle for the given device ID, action profile ID, and
|
||||||
|
* member ID.
|
||||||
|
*
|
||||||
|
* @param deviceId device ID
|
||||||
|
* @param actionProfileId action profile ID
|
||||||
|
* @param memberId member ID
|
||||||
|
* @return action profile group member handle
|
||||||
|
*/
|
||||||
|
public static PiActionGroupMemberHandle of(
|
||||||
|
DeviceId deviceId,
|
||||||
|
PiActionProfileId actionProfileId,
|
||||||
|
PiActionGroupMemberId memberId) {
|
||||||
|
return new PiActionGroupMemberHandle(
|
||||||
|
deviceId, actionProfileId, memberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new handle for the given device ID, and action profile group
|
||||||
|
* member instance.
|
||||||
|
*
|
||||||
|
* @param deviceId device ID
|
||||||
|
* @param member member instance
|
||||||
|
* @return action profile group member handle
|
||||||
|
*/
|
||||||
|
public static PiActionGroupMemberHandle of(
|
||||||
|
DeviceId deviceId,
|
||||||
|
PiActionGroupMember member) {
|
||||||
|
checkNotNull(member);
|
||||||
|
return new PiActionGroupMemberHandle(
|
||||||
|
deviceId, member.actionProfile(), member.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the member ID of this handle.
|
||||||
|
*
|
||||||
|
* @return member ID
|
||||||
|
*/
|
||||||
|
public PiActionGroupMemberId memberId() {
|
||||||
|
return memberId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the action profile ID of this handle.
|
||||||
|
*
|
||||||
|
* @return action profile ID
|
||||||
|
*/
|
||||||
|
public PiActionProfileId actionProfileId() {
|
||||||
|
return actionProfileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PiEntityType entityType() {
|
||||||
|
return PiEntityType.GROUP_MEMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(deviceId(), actionProfileId, memberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final PiActionGroupMemberHandle other = (PiActionGroupMemberHandle) obj;
|
||||||
|
return Objects.equal(this.deviceId(), other.deviceId())
|
||||||
|
&& Objects.equal(this.actionProfileId, other.actionProfileId)
|
||||||
|
&& Objects.equal(this.memberId, other.memberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MoreObjects.toStringHelper(this)
|
||||||
|
.add("deviceId", deviceId())
|
||||||
|
.add("actionProfileId", actionProfileId)
|
||||||
|
.add("memberId", memberId)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -29,11 +29,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
public abstract class PiHandle<E extends PiEntity> {
|
public abstract class PiHandle<E extends PiEntity> {
|
||||||
|
|
||||||
private final DeviceId deviceId;
|
private final DeviceId deviceId;
|
||||||
private final E piEntity;
|
|
||||||
|
|
||||||
protected PiHandle(DeviceId deviceId, E piEntity) {
|
protected PiHandle(DeviceId deviceId) {
|
||||||
this.deviceId = checkNotNull(deviceId);
|
this.deviceId = checkNotNull(deviceId);
|
||||||
this.piEntity = checkNotNull(piEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,18 +48,7 @@ public abstract class PiHandle<E extends PiEntity> {
|
|||||||
*
|
*
|
||||||
* @return PI entity type
|
* @return PI entity type
|
||||||
*/
|
*/
|
||||||
public final PiEntityType entityType() {
|
public abstract PiEntityType entityType();
|
||||||
return piEntity.piEntityType();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The entity to which this handle is associated.
|
|
||||||
*
|
|
||||||
* @return PI entity
|
|
||||||
*/
|
|
||||||
public final E piEntity() {
|
|
||||||
return piEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract int hashCode();
|
public abstract int hashCode();
|
||||||
|
|||||||
@ -21,33 +21,56 @@ import com.google.common.base.MoreObjects;
|
|||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global identifier of a PI meter cell configuration applied to a device, uniquely defined
|
* Global identifier of a PI meter cell configuration applied to a device,
|
||||||
* by a device ID and meter cell ID.
|
* uniquely defined by a device ID and meter cell ID.
|
||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public final class PiMeterHandle extends PiHandle<PiMeterCellConfig> {
|
public final class PiMeterHandle extends PiHandle<PiMeterCellConfig> {
|
||||||
|
|
||||||
private PiMeterHandle(DeviceId deviceId, PiMeterCellConfig meterCellConfig) {
|
private final PiMeterCellId cellId;
|
||||||
super(deviceId, meterCellConfig);
|
|
||||||
|
private PiMeterHandle(DeviceId deviceId, PiMeterCellId meterCellId) {
|
||||||
|
super(deviceId);
|
||||||
|
this.cellId = meterCellId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new handle for the given device ID and PI meter cell configuration.
|
* Creates a new handle for the given device ID and PI meter cell ID.
|
||||||
*
|
*
|
||||||
* @param deviceId device ID
|
* @param deviceId device ID
|
||||||
|
* @param meterCellId meter cell ID
|
||||||
|
* @return PI meter handle
|
||||||
|
*/
|
||||||
|
public static PiMeterHandle of(DeviceId deviceId,
|
||||||
|
PiMeterCellId meterCellId) {
|
||||||
|
return new PiMeterHandle(deviceId, meterCellId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new handle for the given device ID and PI meter cell
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* @param deviceId device ID
|
||||||
* @param meterCellConfig meter config
|
* @param meterCellConfig meter config
|
||||||
* @return PI meter handle
|
* @return PI meter handle
|
||||||
*/
|
*/
|
||||||
public static PiMeterHandle of(DeviceId deviceId,
|
public static PiMeterHandle of(DeviceId deviceId,
|
||||||
PiMeterCellConfig meterCellConfig) {
|
PiMeterCellConfig meterCellConfig) {
|
||||||
return new PiMeterHandle(deviceId, meterCellConfig);
|
checkNotNull(meterCellConfig);
|
||||||
|
return new PiMeterHandle(deviceId, meterCellConfig.cellId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PiEntityType entityType() {
|
||||||
|
return PiEntityType.METER_CELL_CONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(deviceId(),
|
return Objects.hashCode(deviceId(), cellId);
|
||||||
piEntity().cellId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,15 +83,14 @@ public final class PiMeterHandle extends PiHandle<PiMeterCellConfig> {
|
|||||||
}
|
}
|
||||||
PiMeterHandle that = (PiMeterHandle) o;
|
PiMeterHandle that = (PiMeterHandle) o;
|
||||||
return Objects.equal(deviceId(), that.deviceId()) &&
|
return Objects.equal(deviceId(), that.deviceId()) &&
|
||||||
Objects.equal(piEntity().cellId(),
|
Objects.equal(cellId, that.cellId);
|
||||||
that.piEntity().cellId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
.add("deviceId", deviceId())
|
.add("deviceId", deviceId())
|
||||||
.add("meterCellId", piEntity().cellId())
|
.add("meterCellId", cellId)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,8 @@ import com.google.common.base.MoreObjects;
|
|||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global identifier of a PI multicast group entry applied to the packet
|
* Global identifier of a PI multicast group entry applied to the packet
|
||||||
* replication engine of a device, uniquely defined by a device ID, and group
|
* replication engine of a device, uniquely defined by a device ID, and group
|
||||||
@ -29,8 +31,23 @@ import org.onosproject.net.DeviceId;
|
|||||||
@Beta
|
@Beta
|
||||||
public final class PiMulticastGroupEntryHandle extends PiHandle<PiMulticastGroupEntry> {
|
public final class PiMulticastGroupEntryHandle extends PiHandle<PiMulticastGroupEntry> {
|
||||||
|
|
||||||
private PiMulticastGroupEntryHandle(DeviceId deviceId, PiMulticastGroupEntry entry) {
|
private final long groupId;
|
||||||
super(deviceId, entry);
|
|
||||||
|
private PiMulticastGroupEntryHandle(DeviceId deviceId, long groupId) {
|
||||||
|
super(deviceId);
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new handle for the given device ID and PI multicast group ID.
|
||||||
|
*
|
||||||
|
* @param deviceId device ID
|
||||||
|
* @param groupId multicast group ID
|
||||||
|
* @return PI multicast group entry handle
|
||||||
|
*/
|
||||||
|
public static PiMulticastGroupEntryHandle of(DeviceId deviceId,
|
||||||
|
long groupId) {
|
||||||
|
return new PiMulticastGroupEntryHandle(deviceId, groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,12 +60,18 @@ public final class PiMulticastGroupEntryHandle extends PiHandle<PiMulticastGroup
|
|||||||
*/
|
*/
|
||||||
public static PiMulticastGroupEntryHandle of(DeviceId deviceId,
|
public static PiMulticastGroupEntryHandle of(DeviceId deviceId,
|
||||||
PiMulticastGroupEntry entry) {
|
PiMulticastGroupEntry entry) {
|
||||||
return new PiMulticastGroupEntryHandle(deviceId, entry);
|
checkNotNull(entry);
|
||||||
|
return new PiMulticastGroupEntryHandle(deviceId, entry.groupId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PiEntityType entityType() {
|
||||||
|
return PiEntityType.PRE_MULTICAST_GROUP_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(deviceId(), piEntity().groupId());
|
return Objects.hashCode(deviceId(), groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -61,14 +84,14 @@ public final class PiMulticastGroupEntryHandle extends PiHandle<PiMulticastGroup
|
|||||||
}
|
}
|
||||||
PiMulticastGroupEntryHandle that = (PiMulticastGroupEntryHandle) o;
|
PiMulticastGroupEntryHandle that = (PiMulticastGroupEntryHandle) o;
|
||||||
return Objects.equal(deviceId(), that.deviceId()) &&
|
return Objects.equal(deviceId(), that.deviceId()) &&
|
||||||
Objects.equal(piEntity().groupId(), that.piEntity().groupId());
|
Objects.equal(groupId, that.groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
.add("deviceId", deviceId())
|
.add("deviceId", deviceId())
|
||||||
.add("groupId", piEntity().groupId())
|
.add("groupId", groupId)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,15 +38,18 @@ public final class PiTableEntry implements PiEntity {
|
|||||||
private final PiTableId tableId;
|
private final PiTableId tableId;
|
||||||
private final PiMatchKey matchKey;
|
private final PiMatchKey matchKey;
|
||||||
private final PiTableAction tableAction;
|
private final PiTableAction tableAction;
|
||||||
|
private final boolean isDefaultAction;
|
||||||
private final long cookie;
|
private final long cookie;
|
||||||
private final int priority;
|
private final int priority;
|
||||||
private final double timeout;
|
private final double timeout;
|
||||||
|
|
||||||
private PiTableEntry(PiTableId tableId, PiMatchKey matchKey,
|
private PiTableEntry(PiTableId tableId, PiMatchKey matchKey,
|
||||||
PiTableAction tableAction, long cookie, int priority, double timeout) {
|
PiTableAction tableAction, boolean isDefaultAction,
|
||||||
|
long cookie, int priority, double timeout) {
|
||||||
this.tableId = tableId;
|
this.tableId = tableId;
|
||||||
this.matchKey = matchKey;
|
this.matchKey = matchKey;
|
||||||
this.tableAction = tableAction;
|
this.tableAction = tableAction;
|
||||||
|
this.isDefaultAction = isDefaultAction;
|
||||||
this.cookie = cookie;
|
this.cookie = cookie;
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
@ -63,6 +66,9 @@ public final class PiTableEntry implements PiEntity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the match key of this table entry.
|
* Returns the match key of this table entry.
|
||||||
|
* <p>
|
||||||
|
* If {@link #isDefaultAction()} is {@code true} this method returns the
|
||||||
|
* empty match key ({@link PiMatchKey#EMPTY}).
|
||||||
*
|
*
|
||||||
* @return match key
|
* @return match key
|
||||||
*/
|
*/
|
||||||
@ -79,6 +85,16 @@ public final class PiTableEntry implements PiEntity {
|
|||||||
return tableAction;
|
return tableAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this table entry contains the default action for this
|
||||||
|
* table, a.k.a. table-miss entry, false otherwise.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isDefaultAction() {
|
||||||
|
return isDefaultAction;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cookie of this table entry.
|
* Returns the cookie of this table entry.
|
||||||
*
|
*
|
||||||
@ -89,8 +105,8 @@ public final class PiTableEntry implements PiEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the priority of this table entry, if present. If the priority value is not present, then this table entry
|
* Returns the priority of this table entry, if present. If the priority
|
||||||
* has no explicit priority.
|
* value is not present, then this table entry has no explicit priority.
|
||||||
*
|
*
|
||||||
* @return optional priority
|
* @return optional priority
|
||||||
*/
|
*/
|
||||||
@ -99,8 +115,9 @@ public final class PiTableEntry implements PiEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the timeout in seconds of this table entry, if present. If the timeout value is not present, then this
|
* Returns the timeout in seconds of this table entry, if present. If the
|
||||||
* table entry is meant to be permanent.
|
* timeout value is not present, then this table entry is meant to be
|
||||||
|
* permanent.
|
||||||
*
|
*
|
||||||
* @return optional timeout value in seconds
|
* @return optional timeout value in seconds
|
||||||
*/
|
*/
|
||||||
@ -118,28 +135,46 @@ public final class PiTableEntry implements PiEntity {
|
|||||||
}
|
}
|
||||||
PiTableEntry that = (PiTableEntry) o;
|
PiTableEntry that = (PiTableEntry) o;
|
||||||
return priority == that.priority &&
|
return priority == that.priority &&
|
||||||
|
cookie == that.cookie &&
|
||||||
Double.compare(that.timeout, timeout) == 0 &&
|
Double.compare(that.timeout, timeout) == 0 &&
|
||||||
Objects.equal(tableId, that.tableId) &&
|
Objects.equal(tableId, that.tableId) &&
|
||||||
Objects.equal(matchKey, that.matchKey) &&
|
Objects.equal(matchKey, that.matchKey) &&
|
||||||
|
Objects.equal(isDefaultAction, that.isDefaultAction) &&
|
||||||
Objects.equal(tableAction, that.tableAction);
|
Objects.equal(tableAction, that.tableAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(tableId, matchKey, tableAction, priority, timeout);
|
return Objects.hashCode(tableId, matchKey, isDefaultAction, tableAction,
|
||||||
|
priority, cookie, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
.add("tableId", tableId)
|
.add("tableId", tableId)
|
||||||
.add("matchKey", matchKey)
|
.add("matchKey", isDefaultAction ? "DEFAULT-ACTION" : matchKey)
|
||||||
.add("tableAction", tableAction)
|
.add("tableAction", tableActionToString(tableAction))
|
||||||
.add("priority", priority == NO_PRIORITY ? "N/A" : String.valueOf(priority))
|
.add("priority", priority == NO_PRIORITY ? "N/A" : String.valueOf(priority))
|
||||||
.add("timeout", timeout == NO_TIMEOUT ? "PERMANENT" : String.valueOf(timeout))
|
.add("timeout", timeout == NO_TIMEOUT ? "PERMANENT" : String.valueOf(timeout))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String tableActionToString(PiTableAction tableAction) {
|
||||||
|
if (tableAction == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
switch (tableAction.type()) {
|
||||||
|
case ACTION_GROUP_ID:
|
||||||
|
return "GROUP:" + ((PiActionGroupId) tableAction).id();
|
||||||
|
case GROUP_MEMBER_ID:
|
||||||
|
return "GROUP_MEMBER:" + ((PiActionGroupMemberId) tableAction).id();
|
||||||
|
case ACTION:
|
||||||
|
default:
|
||||||
|
return tableAction.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a table entry builder.
|
* Returns a table entry builder.
|
||||||
*
|
*
|
||||||
@ -244,7 +279,9 @@ public final class PiTableEntry implements PiEntity {
|
|||||||
public PiTableEntry build() {
|
public PiTableEntry build() {
|
||||||
checkNotNull(tableId);
|
checkNotNull(tableId);
|
||||||
checkNotNull(matchKey);
|
checkNotNull(matchKey);
|
||||||
return new PiTableEntry(tableId, matchKey, tableAction, cookie, priority, timeout);
|
final boolean isDefaultAction = matchKey.equals(PiMatchKey.EMPTY);
|
||||||
|
return new PiTableEntry(tableId, matchKey, tableAction,
|
||||||
|
isDefaultAction, cookie, priority, timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,9 @@ import com.google.common.annotations.Beta;
|
|||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.pi.model.PiTableId;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global identifier of a PI table entry applied on a device, uniquely defined
|
* Global identifier of a PI table entry applied on a device, uniquely defined
|
||||||
@ -28,8 +31,28 @@ import org.onosproject.net.DeviceId;
|
|||||||
@Beta
|
@Beta
|
||||||
public final class PiTableEntryHandle extends PiHandle<PiTableEntry> {
|
public final class PiTableEntryHandle extends PiHandle<PiTableEntry> {
|
||||||
|
|
||||||
private PiTableEntryHandle(DeviceId deviceId, PiTableEntry entry) {
|
private final PiTableId tableId;
|
||||||
super(deviceId, entry);
|
private final PiMatchKey matchKey;
|
||||||
|
|
||||||
|
private PiTableEntryHandle(DeviceId deviceId, PiTableId tableId, PiMatchKey matchKey) {
|
||||||
|
super(deviceId);
|
||||||
|
this.tableId = tableId;
|
||||||
|
this.matchKey = matchKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new handle for the given device ID, PI table ID, and match
|
||||||
|
* key.
|
||||||
|
*
|
||||||
|
* @param deviceId device ID
|
||||||
|
* @param tableId table ID
|
||||||
|
* @param matchKey match key
|
||||||
|
* @return PI table entry handle
|
||||||
|
*/
|
||||||
|
public static PiTableEntryHandle of(DeviceId deviceId, PiTableId tableId, PiMatchKey matchKey) {
|
||||||
|
checkNotNull(tableId);
|
||||||
|
checkNotNull(matchKey);
|
||||||
|
return new PiTableEntryHandle(deviceId, tableId, matchKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,14 +63,18 @@ public final class PiTableEntryHandle extends PiHandle<PiTableEntry> {
|
|||||||
* @return PI table entry handle
|
* @return PI table entry handle
|
||||||
*/
|
*/
|
||||||
public static PiTableEntryHandle of(DeviceId deviceId, PiTableEntry entry) {
|
public static PiTableEntryHandle of(DeviceId deviceId, PiTableEntry entry) {
|
||||||
return new PiTableEntryHandle(deviceId, entry);
|
checkNotNull(entry);
|
||||||
|
return PiTableEntryHandle.of(deviceId, entry.table(), entry.matchKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PiEntityType entityType() {
|
||||||
|
return PiEntityType.TABLE_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(deviceId(),
|
return Objects.hashCode(deviceId(), tableId, matchKey);
|
||||||
piEntity().table(),
|
|
||||||
piEntity().matchKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,18 +87,16 @@ public final class PiTableEntryHandle extends PiHandle<PiTableEntry> {
|
|||||||
}
|
}
|
||||||
final PiTableEntryHandle other = (PiTableEntryHandle) obj;
|
final PiTableEntryHandle other = (PiTableEntryHandle) obj;
|
||||||
return Objects.equal(this.deviceId(), other.deviceId())
|
return Objects.equal(this.deviceId(), other.deviceId())
|
||||||
&& Objects.equal(this.piEntity().table(),
|
&& Objects.equal(this.tableId, other.tableId)
|
||||||
other.piEntity().table())
|
&& Objects.equal(this.matchKey, other.matchKey);
|
||||||
&& Objects.equal(this.piEntity().matchKey(),
|
|
||||||
other.piEntity().matchKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
.add("deviceId", deviceId())
|
.add("deviceId", deviceId())
|
||||||
.add("tableId", piEntity().table())
|
.add("tableId", tableId)
|
||||||
.add("matchKey", piEntity().matchKey())
|
.add("matchKey", matchKey)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ import java.util.Set;
|
|||||||
public interface PiPipeconfMappingStore extends Store<PiPipeconfDeviceMappingEvent, PiPipeconfMappingStoreDelegate> {
|
public interface PiPipeconfMappingStore extends Store<PiPipeconfDeviceMappingEvent, PiPipeconfMappingStoreDelegate> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the id of the pipeconf deployed on a given device.
|
* Retrieves the id of the pipeconf associated to a given device.
|
||||||
*
|
*
|
||||||
* @param deviceId device identifier
|
* @param deviceId device identifier
|
||||||
* @return PiPipeconfId
|
* @return PiPipeconfId
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.google.common.testing.EqualsTester;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.onosproject.net.pi.model.PiActionId;
|
import org.onosproject.net.pi.model.PiActionId;
|
||||||
import org.onosproject.net.pi.model.PiActionParamId;
|
import org.onosproject.net.pi.model.PiActionParamId;
|
||||||
|
import org.onosproject.net.pi.model.PiActionProfileId;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
@ -34,26 +35,37 @@ import static org.onosproject.net.pi.runtime.PiConstantsTest.MOD_NW_DST;
|
|||||||
*/
|
*/
|
||||||
public class PiActionGroupMemberTest {
|
public class PiActionGroupMemberTest {
|
||||||
|
|
||||||
|
private final PiActionProfileId actionProfileId1 = PiActionProfileId.of("foo");
|
||||||
|
private final PiActionProfileId actionProfileId2 = PiActionProfileId.of("bar");
|
||||||
private final PiActionGroupMemberId piActionGroupMemberId = PiActionGroupMemberId.of(10);
|
private final PiActionGroupMemberId piActionGroupMemberId = PiActionGroupMemberId.of(10);
|
||||||
private final PiAction piAction = PiAction.builder().withId(PiActionId.of(MOD_NW_DST))
|
private final PiAction piAction = PiAction.builder().withId(PiActionId.of(MOD_NW_DST))
|
||||||
.withParameter(new PiActionParam(PiActionParamId.of(DST_ADDR), copyFrom(0x0a010101)))
|
.withParameter(new PiActionParam(PiActionParamId.of(DST_ADDR), copyFrom(0x0a010101)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final PiActionGroupMember piActionGroupMember1 = PiActionGroupMember.builder()
|
private final PiActionGroupMember piActionGroupMember1 = PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(actionProfileId1)
|
||||||
.withId(piActionGroupMemberId)
|
.withId(piActionGroupMemberId)
|
||||||
.withAction(piAction)
|
.withAction(piAction)
|
||||||
.withWeight(10)
|
.withWeight(10)
|
||||||
.build();
|
.build();
|
||||||
private final PiActionGroupMember sameAsPiActionGroupMember1 = PiActionGroupMember.builder()
|
private final PiActionGroupMember sameAsPiActionGroupMember1 = PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(actionProfileId1)
|
||||||
.withId(piActionGroupMemberId)
|
.withId(piActionGroupMemberId)
|
||||||
.withAction(piAction)
|
.withAction(piAction)
|
||||||
.withWeight(10)
|
.withWeight(10)
|
||||||
.build();
|
.build();
|
||||||
private final PiActionGroupMember piActionGroupMember2 = PiActionGroupMember.builder()
|
private final PiActionGroupMember piActionGroupMember2 = PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(actionProfileId1)
|
||||||
.withId(piActionGroupMemberId)
|
.withId(piActionGroupMemberId)
|
||||||
.withAction(piAction)
|
.withAction(piAction)
|
||||||
.withWeight(20)
|
.withWeight(20)
|
||||||
.build();
|
.build();
|
||||||
|
private final PiActionGroupMember piActionGroupMember1ForOtherProfile = PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(actionProfileId2)
|
||||||
|
.withId(piActionGroupMemberId)
|
||||||
|
.withAction(piAction)
|
||||||
|
.withWeight(10)
|
||||||
|
.build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that the PiActionGroupMember class is immutable.
|
* Checks that the PiActionGroupMember class is immutable.
|
||||||
@ -73,6 +85,7 @@ public class PiActionGroupMemberTest {
|
|||||||
new EqualsTester()
|
new EqualsTester()
|
||||||
.addEqualityGroup(piActionGroupMember1, sameAsPiActionGroupMember1)
|
.addEqualityGroup(piActionGroupMember1, sameAsPiActionGroupMember1)
|
||||||
.addEqualityGroup(piActionGroupMember2)
|
.addEqualityGroup(piActionGroupMember2)
|
||||||
|
.addEqualityGroup(piActionGroupMember1ForOtherProfile)
|
||||||
.testEquals();
|
.testEquals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,6 +45,7 @@ public class PiActionGroupTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final PiActionGroupMember piActionGroupMember = PiActionGroupMember.builder()
|
private final PiActionGroupMember piActionGroupMember = PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(ACTION_PROF_ID)
|
||||||
.withId(piActionGroupMemberId)
|
.withId(piActionGroupMemberId)
|
||||||
.withAction(piAction)
|
.withAction(piAction)
|
||||||
.withWeight(10)
|
.withWeight(10)
|
||||||
|
|||||||
@ -119,21 +119,14 @@ public class DriverManager implements DriverService {
|
|||||||
|
|
||||||
Driver driver;
|
Driver driver;
|
||||||
|
|
||||||
// Primary source of driver configuration is the network config.
|
// Special processing for devices with pipeconf.
|
||||||
if (pipeconfService.ofDevice(deviceId).isPresent()) {
|
if (pipeconfService.ofDevice(deviceId).isPresent()) {
|
||||||
// Device has pipeconf associated, look for merged driver.
|
// No fallback for pipeconf merged drivers. Returns null if driver
|
||||||
// Implementation of PiPipeconfService is expected to look for a
|
// does not exist.
|
||||||
// base driver in network config.
|
return getPipeconfMergedDriver(deviceId);
|
||||||
PiPipeconfId pipeconfId = pipeconfService.ofDevice(deviceId).get();
|
|
||||||
String mergedDriver = pipeconfService.getMergedDriver(deviceId, pipeconfId);
|
|
||||||
driver = mergedDriver != null ? lookupDriver(mergedDriver) : null;
|
|
||||||
if (driver != null) {
|
|
||||||
return driver;
|
|
||||||
} else {
|
|
||||||
log.error("Merged driver for {} with pipeconf {} not found, falling back.",
|
|
||||||
deviceId, pipeconfId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Primary source of driver configuration is the network config.
|
||||||
BasicDeviceConfig cfg = networkConfigService.getConfig(deviceId, BasicDeviceConfig.class);
|
BasicDeviceConfig cfg = networkConfigService.getConfig(deviceId, BasicDeviceConfig.class);
|
||||||
driver = lookupDriver(cfg != null ? cfg.driver() : null);
|
driver = lookupDriver(cfg != null ? cfg.driver() : null);
|
||||||
if (driver != null) {
|
if (driver != null) {
|
||||||
@ -154,6 +147,28 @@ public class DriverManager implements DriverService {
|
|||||||
NO_DRIVER);
|
NO_DRIVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Driver getPipeconfMergedDriver(DeviceId deviceId) {
|
||||||
|
PiPipeconfId pipeconfId = pipeconfService.ofDevice(deviceId).orElse(null);
|
||||||
|
if (pipeconfId == null) {
|
||||||
|
log.warn("Missing pipeconf for {}, cannot produce a pipeconf merged driver",
|
||||||
|
deviceId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String mergedDriverName = pipeconfService.getMergedDriver(deviceId, pipeconfId);
|
||||||
|
if (mergedDriverName == null) {
|
||||||
|
log.warn("Unable to get pipeconf merged driver for {} and {}",
|
||||||
|
deviceId, pipeconfId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return getDriver(mergedDriverName);
|
||||||
|
} catch (ItemNotFoundException e) {
|
||||||
|
log.warn("Specified pipeconf merged driver {} for {} not found",
|
||||||
|
mergedDriverName, deviceId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Driver lookupDriver(String driverName) {
|
private Driver lookupDriver(String driverName) {
|
||||||
if (driverName != null) {
|
if (driverName != null) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -116,6 +116,7 @@ final class PiGroupTranslatorImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
piActionGroupBuilder.addMember(PiActionGroupMember.builder()
|
piActionGroupBuilder.addMember(PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(groupKey.actionProfileId())
|
||||||
.withId(PiActionGroupMemberId.of(memberId))
|
.withId(PiActionGroupMemberId.of(memberId))
|
||||||
.withAction((PiAction) tableAction)
|
.withAction((PiAction) tableAction)
|
||||||
.withWeight(bucket.weight())
|
.withWeight(bucket.weight())
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.Striped;
|
import com.google.common.util.concurrent.Striped;
|
||||||
import org.onlab.util.ItemNotFoundException;
|
import org.onlab.util.ItemNotFoundException;
|
||||||
|
import org.onlab.util.SharedExecutors;
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.config.ConfigFactory;
|
import org.onosproject.net.config.ConfigFactory;
|
||||||
import org.onosproject.net.config.NetworkConfigRegistry;
|
import org.onosproject.net.config.NetworkConfigRegistry;
|
||||||
@ -54,6 +55,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
@ -73,6 +75,8 @@ public class PiPipeconfManager implements PiPipeconfService {
|
|||||||
private static final String MERGED_DRIVER_SEPARATOR = ":";
|
private static final String MERGED_DRIVER_SEPARATOR = ":";
|
||||||
private static final String CFG_SCHEME = "piPipeconf";
|
private static final String CFG_SCHEME = "piPipeconf";
|
||||||
|
|
||||||
|
private static final int MISSING_DRIVER_WATCHDOG_INTERVAL = 5; // Seconds.
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
protected NetworkConfigRegistry cfgService;
|
protected NetworkConfigRegistry cfgService;
|
||||||
|
|
||||||
@ -109,6 +113,13 @@ public class PiPipeconfManager implements PiPipeconfService {
|
|||||||
cfgService.registerConfigFactory(configFactory);
|
cfgService.registerConfigFactory(configFactory);
|
||||||
driverAdminService.addListener(driverListener);
|
driverAdminService.addListener(driverListener);
|
||||||
checkMissingMergedDrivers();
|
checkMissingMergedDrivers();
|
||||||
|
if (!missingMergedDrivers.isEmpty()) {
|
||||||
|
// Missing drivers should be created upon detecting registration
|
||||||
|
// events of a new pipeconf or a base driver. If, for any reason, we
|
||||||
|
// miss such event, here's a watchdog task.
|
||||||
|
SharedExecutors.getPoolThreadExecutor()
|
||||||
|
.execute(this::missingDriversWatchdogTask);
|
||||||
|
}
|
||||||
log.info("Started");
|
log.info("Started");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +143,7 @@ public class PiPipeconfManager implements PiPipeconfService {
|
|||||||
}
|
}
|
||||||
pipeconfs.put(pipeconf.id(), pipeconf);
|
pipeconfs.put(pipeconf.id(), pipeconf);
|
||||||
log.info("New pipeconf registered: {}", pipeconf.id());
|
log.info("New pipeconf registered: {}", pipeconf.id());
|
||||||
executor.execute(() -> mergeAll(pipeconf.id()));
|
executor.execute(() -> attemptMergeAll(pipeconf.id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -304,64 +315,102 @@ public class PiPipeconfManager implements PiPipeconfService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkMissingMergedDrivers() {
|
private boolean driverExists(String name) {
|
||||||
cfgService.getSubjects(DeviceId.class, BasicDeviceConfig.class).stream()
|
return getDriver(name) != null;
|
||||||
.map(d -> cfgService.getConfig(d, BasicDeviceConfig.class))
|
|
||||||
.map(BasicDeviceConfig::driver)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.filter(d -> getDriver(d) == null)
|
|
||||||
.forEach(driverName -> {
|
|
||||||
final String baseDriverName = getBaseDriverNameFromMerged(driverName);
|
|
||||||
final PiPipeconfId pipeconfId = getPipeconfIdFromMerged(driverName);
|
|
||||||
if (baseDriverName == null || pipeconfId == null) {
|
|
||||||
// Not a merged driver.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.info("Detected missing merged driver: {}", driverName);
|
|
||||||
missingMergedDrivers.add(driverName);
|
|
||||||
// Attempt building the driver now if all pieces are present.
|
|
||||||
// If not, either a driver or pipeconf event will re-trigger
|
|
||||||
// the merge process.
|
|
||||||
if (getDriver(baseDriverName) != null
|
|
||||||
&& pipeconfs.containsKey(pipeconfId)) {
|
|
||||||
mergedDriverName(baseDriverName, pipeconfId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mergeAll(String baseDriverName) {
|
private void checkMissingMergedDriver(DeviceId deviceId) {
|
||||||
|
final PiPipeconfId pipeconfId = pipeconfMappingStore.getPipeconfId(deviceId);
|
||||||
|
final BasicDeviceConfig cfg = cfgService.getConfig(deviceId, BasicDeviceConfig.class);
|
||||||
|
|
||||||
|
if (pipeconfId == null) {
|
||||||
|
// No pipeconf associated.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg == null || cfg.driver() == null) {
|
||||||
|
log.warn("Missing basic device config or driver key in netcfg for " +
|
||||||
|
"{}, which is odd since it has a " +
|
||||||
|
"pipeconf associated ({})",
|
||||||
|
deviceId, pipeconfId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String baseDriverName = cfg.driver();
|
||||||
|
final String mergedDriverName = mergedDriverName(baseDriverName, pipeconfId);
|
||||||
|
|
||||||
|
if (driverExists(mergedDriverName) ||
|
||||||
|
missingMergedDrivers.contains(mergedDriverName)) {
|
||||||
|
// Not missing, or already aware of it missing.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Detected missing merged driver: {}", mergedDriverName);
|
||||||
|
missingMergedDrivers.add(mergedDriverName);
|
||||||
|
// Attempt building the driver now if all pieces are present.
|
||||||
|
// If not, either a driver or pipeconf event will re-trigger
|
||||||
|
// the process.
|
||||||
|
attemptDriverMerge(mergedDriverName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attemptDriverMerge(String mergedDriverName) {
|
||||||
|
final String baseDriverName = getBaseDriverNameFromMerged(mergedDriverName);
|
||||||
|
final PiPipeconfId pipeconfId = getPipeconfIdFromMerged(mergedDriverName);
|
||||||
|
if (driverExists(baseDriverName) && pipeconfs.containsKey(pipeconfId)) {
|
||||||
|
doMergeDriver(baseDriverName, pipeconfId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void missingDriversWatchdogTask() {
|
||||||
|
while (true) {
|
||||||
|
// Most probably all missing drivers will be created before the
|
||||||
|
// watchdog interval, so wait before starting...
|
||||||
|
try {
|
||||||
|
TimeUnit.SECONDS.sleep(MISSING_DRIVER_WATCHDOG_INTERVAL);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.warn("Interrupted! There are still {} missing merged drivers",
|
||||||
|
missingMergedDrivers.size());
|
||||||
|
}
|
||||||
|
if (missingMergedDrivers.isEmpty()) {
|
||||||
|
log.info("There are no more missing merged drivers!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("Detected {} missing merged drivers, attempt merge...",
|
||||||
|
missingMergedDrivers.size());
|
||||||
|
missingMergedDrivers.forEach(this::attemptDriverMerge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMissingMergedDrivers() {
|
||||||
|
cfgService.getSubjects(DeviceId.class, BasicDeviceConfig.class)
|
||||||
|
.forEach(this::checkMissingMergedDriver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attemptMergeAll(String baseDriverName) {
|
||||||
missingMergedDrivers.stream()
|
missingMergedDrivers.stream()
|
||||||
.filter(driverName -> {
|
.filter(missingDriver -> {
|
||||||
final String xx = getBaseDriverNameFromMerged(driverName);
|
// Filter missing merged drivers using this base driver.
|
||||||
|
final String xx = getBaseDriverNameFromMerged(missingDriver);
|
||||||
return xx != null && xx.equals(baseDriverName);
|
return xx != null && xx.equals(baseDriverName);
|
||||||
})
|
})
|
||||||
.forEach(driverName -> {
|
.forEach(this::attemptDriverMerge);
|
||||||
final PiPipeconfId pipeconfId = getPipeconfIdFromMerged(driverName);
|
|
||||||
if (pipeconfs.containsKey(pipeconfId)) {
|
|
||||||
doMergeDriver(baseDriverName, pipeconfId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mergeAll(PiPipeconfId pipeconfId) {
|
private void attemptMergeAll(PiPipeconfId pipeconfId) {
|
||||||
missingMergedDrivers.stream()
|
missingMergedDrivers.stream()
|
||||||
.filter(driverName -> {
|
.filter(missingDriver -> {
|
||||||
final PiPipeconfId xx = getPipeconfIdFromMerged(driverName);
|
// Filter missing merged drivers using this pipeconf.
|
||||||
|
final PiPipeconfId xx = getPipeconfIdFromMerged(missingDriver);
|
||||||
return xx != null && xx.equals(pipeconfId);
|
return xx != null && xx.equals(pipeconfId);
|
||||||
})
|
})
|
||||||
.forEach(driverName -> {
|
.forEach(this::attemptDriverMerge);
|
||||||
final String baseDriverName = getBaseDriverNameFromMerged(driverName);
|
|
||||||
if (getDriver(baseDriverName) != null) {
|
|
||||||
doMergeDriver(baseDriverName, pipeconfId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InternalDriverListener implements DriverListener {
|
private class InternalDriverListener implements DriverListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void event(DriverEvent event) {
|
public void event(DriverEvent event) {
|
||||||
executor.execute(() -> mergeAll(event.subject().name()));
|
executor.execute(() -> attemptMergeAll(event.subject().name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -109,6 +109,7 @@ public class PiGroupTranslatorImplTest {
|
|||||||
.withId(ACT_SET_EGRESS_PORT_WCMP_ID)
|
.withId(ACT_SET_EGRESS_PORT_WCMP_ID)
|
||||||
.withParameter(param).build();
|
.withParameter(param).build();
|
||||||
return PiActionGroupMember.builder()
|
return PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(ACT_PRF_WCMP_SELECTOR_ID)
|
||||||
.withAction(piAction)
|
.withAction(piAction)
|
||||||
.withId(PiActionGroupMemberId.of(BASE_MEM_ID + portNum))
|
.withId(PiActionGroupMemberId.of(BASE_MEM_ID + portNum))
|
||||||
.withWeight(DEFAULT_MEMBER_WEIGHT)
|
.withWeight(DEFAULT_MEMBER_WEIGHT)
|
||||||
|
|||||||
@ -45,7 +45,12 @@ public class DistributedPiTranslationStoreTest {
|
|||||||
};
|
};
|
||||||
private static final PiEntity PI_ENTITY = () -> PiEntityType.TABLE_ENTRY;
|
private static final PiEntity PI_ENTITY = () -> PiEntityType.TABLE_ENTRY;
|
||||||
private static final PiHandle<PiEntity> PI_HANDLE =
|
private static final PiHandle<PiEntity> PI_HANDLE =
|
||||||
new PiHandle<PiEntity>(DeviceId.NONE, PI_ENTITY) {
|
new PiHandle<PiEntity>(DeviceId.NONE) {
|
||||||
|
@Override
|
||||||
|
public PiEntityType entityType() {
|
||||||
|
return PI_ENTITY.piEntityType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return HANDLE_HASH;
|
return HANDLE_HASH;
|
||||||
|
|||||||
@ -157,13 +157,13 @@ public class AtomixClusterStore extends AbstractStore<ClusterEvent, ClusterStore
|
|||||||
private ControllerNode toControllerNode(Member member) {
|
private ControllerNode toControllerNode(Member member) {
|
||||||
return new DefaultControllerNode(
|
return new DefaultControllerNode(
|
||||||
NodeId.nodeId(member.id().id()),
|
NodeId.nodeId(member.id().id()),
|
||||||
IpAddress.valueOf(member.address().address()),
|
member.address().host(),
|
||||||
member.address().port());
|
member.address().port());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ControllerNode getLocalNode() {
|
public ControllerNode getLocalNode() {
|
||||||
return toControllerNode(membershipService.getLocalMember());
|
return localNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -109,10 +109,6 @@ import org.onosproject.net.flow.StatTriggerFlag;
|
|||||||
import org.onosproject.net.flow.StoredFlowEntry;
|
import org.onosproject.net.flow.StoredFlowEntry;
|
||||||
import org.onosproject.net.flow.TableId;
|
import org.onosproject.net.flow.TableId;
|
||||||
import org.onosproject.net.flow.TableStatisticsEntry;
|
import org.onosproject.net.flow.TableStatisticsEntry;
|
||||||
import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
|
|
||||||
import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
|
|
||||||
import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
|
|
||||||
import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
|
|
||||||
import org.onosproject.net.flow.criteria.ArpHaCriterion;
|
import org.onosproject.net.flow.criteria.ArpHaCriterion;
|
||||||
import org.onosproject.net.flow.criteria.ArpOpCriterion;
|
import org.onosproject.net.flow.criteria.ArpOpCriterion;
|
||||||
import org.onosproject.net.flow.criteria.ArpPaCriterion;
|
import org.onosproject.net.flow.criteria.ArpPaCriterion;
|
||||||
@ -157,6 +153,10 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction;
|
|||||||
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
|
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
|
||||||
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
|
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
|
||||||
import org.onosproject.net.flow.instructions.PiInstruction;
|
import org.onosproject.net.flow.instructions.PiInstruction;
|
||||||
|
import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
|
||||||
|
import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
|
||||||
|
import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
|
||||||
|
import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
|
||||||
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
|
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
|
||||||
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
|
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
|
||||||
import org.onosproject.net.flowobjective.DefaultNextObjective;
|
import org.onosproject.net.flowobjective.DefaultNextObjective;
|
||||||
@ -227,6 +227,7 @@ import org.onosproject.net.pi.runtime.PiActionGroup;
|
|||||||
import org.onosproject.net.pi.runtime.PiActionGroupHandle;
|
import org.onosproject.net.pi.runtime.PiActionGroupHandle;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupId;
|
import org.onosproject.net.pi.runtime.PiActionGroupId;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMemberHandle;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
|
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
|
||||||
import org.onosproject.net.pi.runtime.PiActionParam;
|
import org.onosproject.net.pi.runtime.PiActionParam;
|
||||||
import org.onosproject.net.pi.runtime.PiControlMetadata;
|
import org.onosproject.net.pi.runtime.PiControlMetadata;
|
||||||
@ -242,12 +243,12 @@ import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
|
|||||||
import org.onosproject.net.pi.runtime.PiMatchKey;
|
import org.onosproject.net.pi.runtime.PiMatchKey;
|
||||||
import org.onosproject.net.pi.runtime.PiMeterCellId;
|
import org.onosproject.net.pi.runtime.PiMeterCellId;
|
||||||
import org.onosproject.net.pi.runtime.PiPacketOperation;
|
import org.onosproject.net.pi.runtime.PiPacketOperation;
|
||||||
import org.onosproject.net.pi.service.PiPipeconfConfig;
|
|
||||||
import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
|
import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
|
||||||
import org.onosproject.net.pi.runtime.PiTableAction;
|
import org.onosproject.net.pi.runtime.PiTableAction;
|
||||||
import org.onosproject.net.pi.runtime.PiTableEntry;
|
import org.onosproject.net.pi.runtime.PiTableEntry;
|
||||||
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
|
|
||||||
import org.onosproject.net.pi.runtime.PiTableEntryHandle;
|
import org.onosproject.net.pi.runtime.PiTableEntryHandle;
|
||||||
|
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
|
||||||
|
import org.onosproject.net.pi.service.PiPipeconfConfig;
|
||||||
import org.onosproject.net.pi.service.PiTranslatable;
|
import org.onosproject.net.pi.service.PiTranslatable;
|
||||||
import org.onosproject.net.pi.service.PiTranslatedEntity;
|
import org.onosproject.net.pi.service.PiTranslatedEntity;
|
||||||
import org.onosproject.net.provider.ProviderId;
|
import org.onosproject.net.provider.ProviderId;
|
||||||
@ -687,6 +688,7 @@ public final class KryoNamespaces {
|
|||||||
PiActionGroupHandle.class,
|
PiActionGroupHandle.class,
|
||||||
PiActionGroupId.class,
|
PiActionGroupId.class,
|
||||||
PiActionGroupMember.class,
|
PiActionGroupMember.class,
|
||||||
|
PiActionGroupMemberHandle.class,
|
||||||
PiActionGroupMemberId.class,
|
PiActionGroupMemberId.class,
|
||||||
PiActionParam.class,
|
PiActionParam.class,
|
||||||
PiControlMetadata.class,
|
PiControlMetadata.class,
|
||||||
|
|||||||
@ -1,43 +1,44 @@
|
|||||||
GRPC_VER = '1.3.1'
|
# Buck build of P4-related modules is no longer supported, please use Bazel
|
||||||
|
# GRPC_VER = '1.3.1'
|
||||||
COMPILE_DEPS = [
|
#
|
||||||
'//lib:CORE_DEPS',
|
# COMPILE_DEPS = [
|
||||||
'//lib:minimal-json',
|
# '//lib:CORE_DEPS',
|
||||||
'//lib:KRYO',
|
# '//lib:minimal-json',
|
||||||
'//lib:JACKSON',
|
# '//lib:KRYO',
|
||||||
'//lib:libthrift',
|
# '//lib:JACKSON',
|
||||||
'//protocols/p4runtime/api:onos-protocols-p4runtime-api',
|
# '//lib:libthrift',
|
||||||
'//protocols/p4runtime/model:onos-protocols-p4runtime-model',
|
# '//protocols/p4runtime/api:onos-protocols-p4runtime-api',
|
||||||
'//protocols/bmv2/thrift-api:onos-protocols-bmv2-thrift-api',
|
# '//protocols/p4runtime/model:onos-protocols-p4runtime-model',
|
||||||
'//drivers/p4runtime:onos-drivers-p4runtime',
|
# '//protocols/bmv2/thrift-api:onos-protocols-bmv2-thrift-api',
|
||||||
'//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
|
# '//drivers/p4runtime:onos-drivers-p4runtime',
|
||||||
'//lib:grpc-netty-' + GRPC_VER,
|
# '//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
|
||||||
'//pipelines/basic:onos-pipelines-basic',
|
# '//lib:grpc-netty-' + GRPC_VER,
|
||||||
'//core/store/serializers:onos-core-serializers',
|
# '//pipelines/basic:onos-pipelines-basic',
|
||||||
]
|
# '//core/store/serializers:onos-core-serializers',
|
||||||
|
# ]
|
||||||
BUNDLES = [
|
#
|
||||||
':onos-drivers-bmv2',
|
# BUNDLES = [
|
||||||
'//lib:libthrift',
|
# ':onos-drivers-bmv2',
|
||||||
'//protocols/bmv2/thrift-api:onos-protocols-bmv2-thrift-api',
|
# '//lib:libthrift',
|
||||||
]
|
# '//protocols/bmv2/thrift-api:onos-protocols-bmv2-thrift-api',
|
||||||
|
# ]
|
||||||
osgi_jar(
|
#
|
||||||
deps = COMPILE_DEPS,
|
# osgi_jar(
|
||||||
resources_root = 'src/main/resources',
|
# deps = COMPILE_DEPS,
|
||||||
resources = glob(['src/main/resources/**']),
|
# resources_root = 'src/main/resources',
|
||||||
)
|
# resources = glob(['src/main/resources/**']),
|
||||||
|
# )
|
||||||
onos_app (
|
#
|
||||||
app_name = 'org.onosproject.drivers.bmv2',
|
# onos_app (
|
||||||
title = 'BMv2 Drivers',
|
# app_name = 'org.onosproject.drivers.bmv2',
|
||||||
category = 'Drivers',
|
# title = 'BMv2 Drivers',
|
||||||
url = 'http://onosproject.org',
|
# category = 'Drivers',
|
||||||
description = 'Adds support for BMv2 P4 devices.',
|
# url = 'http://onosproject.org',
|
||||||
included_bundles = BUNDLES,
|
# description = 'Adds support for BMv2 P4 devices.',
|
||||||
required_apps = [
|
# included_bundles = BUNDLES,
|
||||||
'org.onosproject.drivers.p4runtime',
|
# required_apps = [
|
||||||
'org.onosproject.drivers.gnmi',
|
# 'org.onosproject.drivers.p4runtime',
|
||||||
'org.onosproject.pipelines.basic',
|
# 'org.onosproject.drivers.gnmi',
|
||||||
],
|
# 'org.onosproject.pipelines.basic',
|
||||||
)
|
# ],
|
||||||
|
# )
|
||||||
|
|||||||
@ -430,7 +430,11 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
|
|||||||
Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
|
Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
|
||||||
Criterion innerVlan = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
|
Criterion innerVlan = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
|
||||||
Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
|
Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
|
||||||
Criterion bullshit = Criteria.matchMetadata(output.port().toLong());
|
|
||||||
|
long cvid = ((VlanIdCriterion) innerVlan).vlanId().toShort();
|
||||||
|
long outPort = output.port().toLong() & 0x0FFFFFFFFL;
|
||||||
|
|
||||||
|
Criterion metadata = Criteria.matchMetadata((cvid << 32) | outPort);
|
||||||
|
|
||||||
if (outerVlan == null || innerVlan == null || inport == null) {
|
if (outerVlan == null || innerVlan == null || inport == null) {
|
||||||
log.error("Forwarding objective is underspecified: {}", fwd);
|
log.error("Forwarding objective is underspecified: {}", fwd);
|
||||||
@ -445,7 +449,7 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
|
|||||||
.forDevice(deviceId)
|
.forDevice(deviceId)
|
||||||
.makePermanent()
|
.makePermanent()
|
||||||
.withPriority(fwd.priority())
|
.withPriority(fwd.priority())
|
||||||
.withSelector(buildSelector(inport, outerVlan, bullshit))
|
.withSelector(buildSelector(inport, outerVlan, metadata))
|
||||||
.withTreatment(buildTreatment(popAndRewrite.getLeft(),
|
.withTreatment(buildTreatment(popAndRewrite.getLeft(),
|
||||||
Instructions.transition(QQ_TABLE)));
|
Instructions.transition(QQ_TABLE)));
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,436 @@
|
|||||||
|
/*
|
||||||
|
* 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.drivers.p4runtime;
|
||||||
|
|
||||||
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.util.concurrent.Striped;
|
||||||
|
import org.onlab.util.SharedExecutors;
|
||||||
|
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeActionProfileMemberMirror;
|
||||||
|
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeGroupMirror;
|
||||||
|
import org.onosproject.drivers.p4runtime.mirror.TimedEntry;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.group.DefaultGroup;
|
||||||
|
import org.onosproject.net.group.DefaultGroupDescription;
|
||||||
|
import org.onosproject.net.group.Group;
|
||||||
|
import org.onosproject.net.group.GroupDescription;
|
||||||
|
import org.onosproject.net.group.GroupOperation;
|
||||||
|
import org.onosproject.net.group.GroupOperations;
|
||||||
|
import org.onosproject.net.group.GroupProgrammable;
|
||||||
|
import org.onosproject.net.group.GroupStore;
|
||||||
|
import org.onosproject.net.pi.model.PiActionId;
|
||||||
|
import org.onosproject.net.pi.model.PiActionProfileId;
|
||||||
|
import org.onosproject.net.pi.model.PiActionProfileModel;
|
||||||
|
import org.onosproject.net.pi.runtime.PiAction;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroup;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupHandle;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMemberHandle;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
|
||||||
|
import org.onosproject.net.pi.service.PiGroupTranslator;
|
||||||
|
import org.onosproject.net.pi.service.PiTranslatedEntity;
|
||||||
|
import org.onosproject.net.pi.service.PiTranslationException;
|
||||||
|
import org.onosproject.p4runtime.api.P4RuntimeClient;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.DELETE;
|
||||||
|
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.INSERT;
|
||||||
|
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.MODIFY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of GroupProgrammable to handle action profile groups in
|
||||||
|
* P4Runtime.
|
||||||
|
*/
|
||||||
|
public class P4RuntimeActionGroupProgrammable
|
||||||
|
extends AbstractP4RuntimeHandlerBehaviour
|
||||||
|
implements GroupProgrammable {
|
||||||
|
|
||||||
|
// If true, we avoid querying the device and return what's already known by
|
||||||
|
// the ONOS store.
|
||||||
|
private static final String READ_ACTION_GROUPS_FROM_MIRROR = "actionGroupReadFromMirror";
|
||||||
|
private static final boolean DEFAULT_READ_ACTION_GROUPS_FROM_MIRROR = false;
|
||||||
|
|
||||||
|
protected GroupStore groupStore;
|
||||||
|
private P4RuntimeGroupMirror groupMirror;
|
||||||
|
private P4RuntimeActionProfileMemberMirror memberMirror;
|
||||||
|
private PiGroupTranslator groupTranslator;
|
||||||
|
|
||||||
|
// Needed to synchronize operations over the same group.
|
||||||
|
private static final Striped<Lock> STRIPED_LOCKS = Striped.lock(30);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean setupBehaviour() {
|
||||||
|
if (!super.setupBehaviour()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
groupMirror = this.handler().get(P4RuntimeGroupMirror.class);
|
||||||
|
memberMirror = this.handler().get(P4RuntimeActionProfileMemberMirror.class);
|
||||||
|
groupStore = handler().get(GroupStore.class);
|
||||||
|
groupTranslator = piTranslationService.groupTranslator();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performGroupOperation(DeviceId deviceId,
|
||||||
|
GroupOperations groupOps) {
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
groupOps.operations().stream()
|
||||||
|
.filter(op -> !op.groupType().equals(GroupDescription.Type.ALL))
|
||||||
|
.forEach(op -> {
|
||||||
|
// ONOS-7785 We need app cookie (action profile id) from the group
|
||||||
|
Group groupOnStore = groupStore.getGroup(deviceId, op.groupId());
|
||||||
|
GroupDescription groupDesc = new DefaultGroupDescription(
|
||||||
|
deviceId, op.groupType(), op.buckets(), groupOnStore.appCookie(),
|
||||||
|
op.groupId().id(), groupOnStore.appId());
|
||||||
|
DefaultGroup groupToApply = new DefaultGroup(op.groupId(), groupDesc);
|
||||||
|
processGroupOperation(groupToApply, op.opType());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Group> getGroups() {
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return getActionGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Group> getActionGroups() {
|
||||||
|
|
||||||
|
if (driverBoolProperty(READ_ACTION_GROUPS_FROM_MIRROR,
|
||||||
|
DEFAULT_READ_ACTION_GROUPS_FROM_MIRROR)) {
|
||||||
|
return getActionGroupsFromMirror();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Collection<PiActionProfileId> actionProfileIds = pipeconf.pipelineModel()
|
||||||
|
.actionProfiles()
|
||||||
|
.stream()
|
||||||
|
.map(PiActionProfileModel::id)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
final List<PiActionGroup> groupsOnDevice = actionProfileIds.stream()
|
||||||
|
.flatMap(this::streamGroupsFromDevice)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
final Set<PiActionGroupMemberHandle> membersOnDevice = actionProfileIds
|
||||||
|
.stream()
|
||||||
|
.flatMap(actProfId -> getMembersFromDevice(actProfId)
|
||||||
|
.stream()
|
||||||
|
.map(memberId -> PiActionGroupMemberHandle.of(
|
||||||
|
deviceId, actProfId, memberId)))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
if (groupsOnDevice.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync mirrors.
|
||||||
|
syncGroupMirror(groupsOnDevice);
|
||||||
|
syncMemberMirror(membersOnDevice);
|
||||||
|
|
||||||
|
final List<Group> result = Lists.newArrayList();
|
||||||
|
final List<PiActionGroup> inconsistentGroups = Lists.newArrayList();
|
||||||
|
final List<PiActionGroup> validGroups = Lists.newArrayList();
|
||||||
|
|
||||||
|
for (PiActionGroup piGroup : groupsOnDevice) {
|
||||||
|
final Group pdGroup = forgeGroupEntry(piGroup);
|
||||||
|
if (pdGroup == null) {
|
||||||
|
// Entry is on device but unknown to translation service or
|
||||||
|
// device mirror. Inconsistent. Mark for removal.
|
||||||
|
inconsistentGroups.add(piGroup);
|
||||||
|
} else {
|
||||||
|
validGroups.add(piGroup);
|
||||||
|
result.add(pdGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger clean up of inconsistent groups and members. This will also
|
||||||
|
// remove all members that are not used by any group, and update the
|
||||||
|
// mirror accordingly.
|
||||||
|
final Set<PiActionGroupMemberHandle> membersToKeep = validGroups.stream()
|
||||||
|
.flatMap(g -> g.members().stream())
|
||||||
|
.map(m -> PiActionGroupMemberHandle.of(deviceId, m))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
final Set<PiActionGroupMemberHandle> inconsistentMembers = Sets.difference(
|
||||||
|
membersOnDevice, membersToKeep);
|
||||||
|
SharedExecutors.getSingleThreadExecutor().execute(
|
||||||
|
() -> cleanUpInconsistentGroupsAndMembers(
|
||||||
|
inconsistentGroups, inconsistentMembers));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncGroupMirror(Collection<PiActionGroup> groups) {
|
||||||
|
Map<PiActionGroupHandle, PiActionGroup> handleMap = Maps.newHashMap();
|
||||||
|
groups.forEach(g -> handleMap.put(PiActionGroupHandle.of(deviceId, g), g));
|
||||||
|
groupMirror.sync(deviceId, handleMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncMemberMirror(Collection<PiActionGroupMemberHandle> memberHandles) {
|
||||||
|
Map<PiActionGroupMemberHandle, PiActionGroupMember> handleMap = Maps.newHashMap();
|
||||||
|
memberHandles.forEach(handle -> handleMap.put(
|
||||||
|
handle, dummyMember(handle.actionProfileId(), handle.memberId())));
|
||||||
|
memberMirror.sync(deviceId, handleMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Group> getActionGroupsFromMirror() {
|
||||||
|
return groupMirror.getAll(deviceId).stream()
|
||||||
|
.map(TimedEntry::entry)
|
||||||
|
.map(this::forgeGroupEntry)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanUpInconsistentGroupsAndMembers(Collection<PiActionGroup> groupsToRemove,
|
||||||
|
Collection<PiActionGroupMemberHandle> membersToRemove) {
|
||||||
|
if (!groupsToRemove.isEmpty()) {
|
||||||
|
log.warn("Found {} inconsistent action profile groups on {}, removing them...",
|
||||||
|
groupsToRemove.size(), deviceId);
|
||||||
|
groupsToRemove.forEach(piGroup -> {
|
||||||
|
log.debug(piGroup.toString());
|
||||||
|
processGroup(piGroup, null, Operation.REMOVE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!membersToRemove.isEmpty()) {
|
||||||
|
log.warn("Found {} inconsistent action profile members on {}, removing them...",
|
||||||
|
membersToRemove.size(), deviceId);
|
||||||
|
// FIXME: implement client call to remove members from multiple
|
||||||
|
// action profiles in one shot.
|
||||||
|
final ListMultimap<PiActionProfileId, PiActionGroupMemberId>
|
||||||
|
membersByActProfId = ArrayListMultimap.create();
|
||||||
|
membersToRemove.forEach(m -> membersByActProfId.put(
|
||||||
|
m.actionProfileId(), m.memberId()));
|
||||||
|
membersByActProfId.keySet().forEach(actProfId -> {
|
||||||
|
List<PiActionGroupMemberId> removedMembers = getFutureWithDeadline(
|
||||||
|
client.removeActionProfileMembers(
|
||||||
|
actProfId, membersByActProfId.get(actProfId), pipeconf),
|
||||||
|
"cleaning up action profile members", Collections.emptyList());
|
||||||
|
// Update member mirror.
|
||||||
|
removedMembers.stream()
|
||||||
|
.map(id -> PiActionGroupMemberHandle.of(deviceId, actProfId, id))
|
||||||
|
.forEach(memberMirror::remove);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<PiActionGroup> streamGroupsFromDevice(PiActionProfileId actProfId) {
|
||||||
|
// TODO: implement P4Runtime client call to read all groups with one call
|
||||||
|
// Good if pipeline has multiple action profiles.
|
||||||
|
final Collection<PiActionGroup> groups = getFutureWithDeadline(
|
||||||
|
client.dumpGroups(actProfId, pipeconf),
|
||||||
|
"dumping groups", Collections.emptyList());
|
||||||
|
return groups.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PiActionGroupMemberId> getMembersFromDevice(PiActionProfileId actProfId) {
|
||||||
|
// TODO: implement P4Runtime client call to read all members with one call
|
||||||
|
// Good if pipeline has multiple action profiles.
|
||||||
|
return getFutureWithDeadline(
|
||||||
|
client.dumpActionProfileMemberIds(actProfId, pipeconf),
|
||||||
|
"dumping action profile ids", Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Group forgeGroupEntry(PiActionGroup piGroup) {
|
||||||
|
final PiActionGroupHandle handle = PiActionGroupHandle.of(deviceId, piGroup);
|
||||||
|
final Optional<PiTranslatedEntity<Group, PiActionGroup>>
|
||||||
|
translatedEntity = groupTranslator.lookup(handle);
|
||||||
|
final TimedEntry<PiActionGroup> timedEntry = groupMirror.get(handle);
|
||||||
|
// Is entry consistent with our state?
|
||||||
|
if (!translatedEntity.isPresent()) {
|
||||||
|
log.warn("Group handle not found in translation store: {}", handle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!translatedEntity.get().translated().equals(piGroup)) {
|
||||||
|
log.warn("Group obtained from device {} is different from the one in" +
|
||||||
|
"translation store: device={}, store={}",
|
||||||
|
deviceId, piGroup, translatedEntity.get().translated());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (timedEntry == null) {
|
||||||
|
log.warn("Group handle not found in device mirror: {}", handle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return addedGroup(translatedEntity.get().original(), timedEntry.lifeSec());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Group addedGroup(Group original, long life) {
|
||||||
|
final DefaultGroup forgedGroup = new DefaultGroup(original.id(), original);
|
||||||
|
forgedGroup.setState(Group.GroupState.ADDED);
|
||||||
|
forgedGroup.setLife(life);
|
||||||
|
return forgedGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processGroupOperation(Group pdGroup, GroupOperation.Type opType) {
|
||||||
|
final PiActionGroup piGroup;
|
||||||
|
try {
|
||||||
|
piGroup = groupTranslator.translate(pdGroup, pipeconf);
|
||||||
|
} catch (PiTranslationException e) {
|
||||||
|
log.warn("Unable to translate group, aborting {} operation: {} [{}]",
|
||||||
|
opType, e.getMessage(), pdGroup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Operation operation = opType.equals(GroupOperation.Type.DELETE)
|
||||||
|
? Operation.REMOVE : Operation.APPLY;
|
||||||
|
processGroup(piGroup, pdGroup, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processGroup(PiActionGroup groupToApply,
|
||||||
|
Group pdGroup,
|
||||||
|
Operation operation) {
|
||||||
|
final PiActionGroupHandle handle = PiActionGroupHandle.of(deviceId, groupToApply);
|
||||||
|
STRIPED_LOCKS.get(handle).lock();
|
||||||
|
try {
|
||||||
|
switch (operation) {
|
||||||
|
case APPLY:
|
||||||
|
if (applyGroupWithMembersOrNothing(groupToApply, handle)) {
|
||||||
|
groupTranslator.learn(handle, new PiTranslatedEntity<>(
|
||||||
|
pdGroup, groupToApply, handle));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case REMOVE:
|
||||||
|
if (deleteGroup(groupToApply, handle)) {
|
||||||
|
groupTranslator.forget(handle);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
log.error("Unknwon group operation type {}, cannot process group", operation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
STRIPED_LOCKS.get(handle).unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean applyGroupWithMembersOrNothing(PiActionGroup group, PiActionGroupHandle handle) {
|
||||||
|
// First apply members, then group, if fails, delete members.
|
||||||
|
if (!applyAllMembersOrNothing(group.members())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!applyGroup(group, handle)) {
|
||||||
|
deleteMembers(group.members());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean applyGroup(PiActionGroup group, PiActionGroupHandle handle) {
|
||||||
|
final P4RuntimeClient.WriteOperationType opType =
|
||||||
|
groupMirror.get(handle) == null ? INSERT : MODIFY;
|
||||||
|
final boolean success = getFutureWithDeadline(
|
||||||
|
client.writeActionGroup(group, opType, pipeconf),
|
||||||
|
"performing action profile group " + opType, false);
|
||||||
|
if (success) {
|
||||||
|
groupMirror.put(handle, group);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean deleteGroup(PiActionGroup group, PiActionGroupHandle handle) {
|
||||||
|
final boolean success = getFutureWithDeadline(
|
||||||
|
client.writeActionGroup(group, DELETE, pipeconf),
|
||||||
|
"performing action profile group " + DELETE, false);
|
||||||
|
if (success) {
|
||||||
|
groupMirror.remove(handle);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean applyAllMembersOrNothing(Collection<PiActionGroupMember> members) {
|
||||||
|
Collection<PiActionGroupMember> appliedMembers = applyMembers(members);
|
||||||
|
if (appliedMembers.size() == members.size()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
deleteMembers(appliedMembers);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<PiActionGroupMember> applyMembers(
|
||||||
|
Collection<PiActionGroupMember> members) {
|
||||||
|
return members.stream()
|
||||||
|
.filter(this::applyMember)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean applyMember(PiActionGroupMember member) {
|
||||||
|
// If exists, modify, otherwise insert
|
||||||
|
final PiActionGroupMemberHandle handle = PiActionGroupMemberHandle.of(
|
||||||
|
deviceId, member);
|
||||||
|
final P4RuntimeClient.WriteOperationType opType =
|
||||||
|
memberMirror.get(handle) == null ? INSERT : MODIFY;
|
||||||
|
final boolean success = getFutureWithDeadline(
|
||||||
|
client.writeActionGroupMembers(Collections.singletonList(member),
|
||||||
|
opType, pipeconf),
|
||||||
|
"performing action profile member " + opType, false);
|
||||||
|
if (success) {
|
||||||
|
memberMirror.put(handle, dummyMember(member.actionProfile(), member.id()));
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteMembers(Collection<PiActionGroupMember> members) {
|
||||||
|
members.forEach(this::deleteMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteMember(PiActionGroupMember member) {
|
||||||
|
final PiActionGroupMemberHandle handle = PiActionGroupMemberHandle.of(
|
||||||
|
deviceId, member);
|
||||||
|
final boolean success = getFutureWithDeadline(
|
||||||
|
client.writeActionGroupMembers(Collections.singletonList(member),
|
||||||
|
DELETE, pipeconf),
|
||||||
|
"performing action profile member " + DELETE, false);
|
||||||
|
if (success) {
|
||||||
|
memberMirror.remove(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: this is nasty, we have to rely on a dummy member of the mirror
|
||||||
|
// because the PiActionGroupMember abstraction is broken, since it includes
|
||||||
|
// attributes that are not part of a P4Runtime member, e.g. weight.
|
||||||
|
// We should remove weight from the class, and have client methods that
|
||||||
|
// return the full PiActionGroupMember, not just the IDs. Also the naming
|
||||||
|
// "ActionGroupMember" is wrong since it makes believe that members can
|
||||||
|
// exists only inside a group, which is not true.
|
||||||
|
private PiActionGroupMember dummyMember(
|
||||||
|
PiActionProfileId actionProfileId, PiActionGroupMemberId memberId) {
|
||||||
|
return PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(actionProfileId)
|
||||||
|
.withId(memberId)
|
||||||
|
.withAction(PiAction.builder()
|
||||||
|
.withId(PiActionId.of("dummy"))
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Operation {
|
||||||
|
APPLY, REMOVE
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,6 +18,7 @@ package org.onosproject.drivers.p4runtime;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.util.concurrent.Striped;
|
import com.google.common.util.concurrent.Striped;
|
||||||
import org.onlab.util.SharedExecutors;
|
import org.onlab.util.SharedExecutors;
|
||||||
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeTableMirror;
|
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeTableMirror;
|
||||||
@ -26,8 +27,10 @@ import org.onosproject.net.flow.DefaultFlowEntry;
|
|||||||
import org.onosproject.net.flow.FlowEntry;
|
import org.onosproject.net.flow.FlowEntry;
|
||||||
import org.onosproject.net.flow.FlowRule;
|
import org.onosproject.net.flow.FlowRule;
|
||||||
import org.onosproject.net.flow.FlowRuleProgrammable;
|
import org.onosproject.net.flow.FlowRuleProgrammable;
|
||||||
|
import org.onosproject.net.pi.model.PiPipelineInterpreter;
|
||||||
import org.onosproject.net.pi.model.PiPipelineModel;
|
import org.onosproject.net.pi.model.PiPipelineModel;
|
||||||
import org.onosproject.net.pi.model.PiTableId;
|
import org.onosproject.net.pi.model.PiTableId;
|
||||||
|
import org.onosproject.net.pi.model.PiTableModel;
|
||||||
import org.onosproject.net.pi.runtime.PiCounterCellData;
|
import org.onosproject.net.pi.runtime.PiCounterCellData;
|
||||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
|
import org.onosproject.net.pi.runtime.PiCounterCellId;
|
||||||
import org.onosproject.net.pi.runtime.PiTableEntry;
|
import org.onosproject.net.pi.runtime.PiTableEntry;
|
||||||
@ -41,11 +44,13 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static com.google.common.collect.Lists.newArrayList;
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
import static org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable.Operation.APPLY;
|
import static org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable.Operation.APPLY;
|
||||||
@ -90,6 +95,12 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
// FIXME: set to true as soon as the feature is implemented in P4Runtime.
|
// FIXME: set to true as soon as the feature is implemented in P4Runtime.
|
||||||
private static final boolean DEFAULT_READ_ALL_DIRECT_COUNTERS = false;
|
private static final boolean DEFAULT_READ_ALL_DIRECT_COUNTERS = false;
|
||||||
|
|
||||||
|
// For default entries, P4Runtime mandates that only MODIFY messages are
|
||||||
|
// allowed. If true, treats default entries as normal table entries,
|
||||||
|
// e.g. inserting them first.
|
||||||
|
private static final String TABLE_DEFAULT_AS_ENTRY = "tableDefaultAsEntry";
|
||||||
|
private static final boolean DEFAULT_TABLE_DEFAULT_AS_ENTRY = false;
|
||||||
|
|
||||||
// Needed to synchronize operations over the same table entry.
|
// Needed to synchronize operations over the same table entry.
|
||||||
private static final Striped<Lock> ENTRY_LOCKS = Striped.lock(30);
|
private static final Striped<Lock> ENTRY_LOCKS = Striped.lock(30);
|
||||||
|
|
||||||
@ -124,37 +135,40 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
final ImmutableList.Builder<FlowEntry> result = ImmutableList.builder();
|
final ImmutableList.Builder<FlowEntry> result = ImmutableList.builder();
|
||||||
final List<PiTableEntry> inconsistentEntries = Lists.newArrayList();
|
final List<PiTableEntry> inconsistentEntries = Lists.newArrayList();
|
||||||
|
|
||||||
// Read table entries.
|
// Read table entries, including default ones.
|
||||||
// TODO: ONOS-7596 read counters with table entries
|
final Collection<PiTableEntry> deviceEntries = Stream.concat(
|
||||||
final Collection<PiTableEntry> installedEntries = getFutureWithDeadline(
|
streamEntries(), streamDefaultEntries())
|
||||||
client.dumpAllTables(pipeconf), "dumping all tables",
|
// Ignore entries from constant tables.
|
||||||
Collections.emptyList())
|
|
||||||
// Filter out entries from constant table.
|
|
||||||
.stream()
|
|
||||||
.filter(e -> !tableIsConstant(e.table()))
|
.filter(e -> !tableIsConstant(e.table()))
|
||||||
|
// Device implementation might return duplicate entries. For
|
||||||
|
// example if reading only default ones is not supported and
|
||||||
|
// non-default entries are returned, by using distinct() we are
|
||||||
|
// robust against that possibility.
|
||||||
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (installedEntries.isEmpty()) {
|
if (deviceEntries.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read table direct counters (if any).
|
// Synchronize mirror with the device state.
|
||||||
|
syncMirror(deviceEntries);
|
||||||
|
// TODO: ONOS-7596 read counters with table entries
|
||||||
final Map<PiTableEntry, PiCounterCellData> counterCellMap =
|
final Map<PiTableEntry, PiCounterCellData> counterCellMap =
|
||||||
readEntryCounters(installedEntries);
|
readEntryCounters(deviceEntries);
|
||||||
|
|
||||||
// Forge flow entries with counter values.
|
// Forge flow entries with counter values.
|
||||||
for (PiTableEntry installedEntry : installedEntries) {
|
for (PiTableEntry entry : deviceEntries) {
|
||||||
|
|
||||||
final FlowEntry flowEntry = forgeFlowEntry(
|
final FlowEntry flowEntry = forgeFlowEntry(
|
||||||
installedEntry, counterCellMap.get(installedEntry));
|
entry, counterCellMap.get(entry));
|
||||||
|
|
||||||
if (flowEntry == null) {
|
if (flowEntry == null) {
|
||||||
// Entry is on device but unknown to translation service or
|
// Entry is on device but unknown to translation service or
|
||||||
// device mirror. Inconsistent. Mark for removal.
|
// device mirror. Inconsistent. Mark for removal.
|
||||||
// TODO: make this behaviour configurable
|
// TODO: make this behaviour configurable
|
||||||
// In some cases it's fine for the device to have rules
|
// In some cases it's fine for the device to have rules
|
||||||
// that were not installed by us.
|
// that were not installed by us, e.g. original default entry.
|
||||||
inconsistentEntries.add(installedEntry);
|
if (!isOriginalDefaultEntry(entry)) {
|
||||||
|
inconsistentEntries.add(entry);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result.add(flowEntry);
|
result.add(flowEntry);
|
||||||
}
|
}
|
||||||
@ -169,6 +183,34 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
return result.build();
|
return result.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Stream<PiTableEntry> streamEntries() {
|
||||||
|
return getFutureWithDeadline(
|
||||||
|
client.dumpAllTables(pipeconf), "dumping all tables",
|
||||||
|
Collections.emptyList())
|
||||||
|
.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<PiTableEntry> streamDefaultEntries() {
|
||||||
|
// Ignore tables with constant default action.
|
||||||
|
final Set<PiTableId> defaultTables = pipelineModel.tables()
|
||||||
|
.stream()
|
||||||
|
.filter(table -> !table.constDefaultAction().isPresent())
|
||||||
|
.map(PiTableModel::id)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
return defaultTables.isEmpty() ? Stream.empty()
|
||||||
|
: getFutureWithDeadline(
|
||||||
|
client.dumpTables(defaultTables, true, pipeconf),
|
||||||
|
"dumping default table entries",
|
||||||
|
Collections.emptyList())
|
||||||
|
.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncMirror(Collection<PiTableEntry> entries) {
|
||||||
|
Map<PiTableEntryHandle, PiTableEntry> handleMap = Maps.newHashMap();
|
||||||
|
entries.forEach(e -> handleMap.put(PiTableEntryHandle.of(deviceId, e), e));
|
||||||
|
tableMirror.sync(deviceId, handleMap);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
|
public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
|
||||||
return processFlowRules(rules, APPLY);
|
return processFlowRules(rules, APPLY);
|
||||||
@ -188,12 +230,17 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
final TimedEntry<PiTableEntry> timedEntry = tableMirror.get(handle);
|
final TimedEntry<PiTableEntry> timedEntry = tableMirror.get(handle);
|
||||||
|
|
||||||
if (!translatedEntity.isPresent()) {
|
if (!translatedEntity.isPresent()) {
|
||||||
log.debug("Handle not found in store: {}", handle);
|
log.warn("Table entry handle not found in translation store: {}", handle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!translatedEntity.get().translated().equals(entry)) {
|
||||||
|
log.warn("Table entry obtained from device {} is different from " +
|
||||||
|
"one in in translation store: device={}, store={}",
|
||||||
|
deviceId, entry, translatedEntity.get().translated());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timedEntry == null) {
|
if (timedEntry == null) {
|
||||||
log.debug("Handle not found in device mirror: {}", handle);
|
log.warn("Table entry handle not found in device mirror: {}", handle);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,23 +258,29 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
return tableMirror.getAll(deviceId).stream()
|
return tableMirror.getAll(deviceId).stream()
|
||||||
.map(timedEntry -> forgeFlowEntry(
|
.map(timedEntry -> forgeFlowEntry(
|
||||||
timedEntry.entry(), null))
|
timedEntry.entry(), null))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanUpInconsistentEntries(Collection<PiTableEntry> piEntries) {
|
private void cleanUpInconsistentEntries(Collection<PiTableEntry> piEntries) {
|
||||||
log.warn("Found {} entries from {} not on translation store, removing them...",
|
log.warn("Found {} inconsistent table entries on {}, removing them...",
|
||||||
piEntries.size(), deviceId);
|
piEntries.size(), deviceId);
|
||||||
piEntries.forEach(entry -> {
|
piEntries.forEach(entry -> {
|
||||||
log.debug(entry.toString());
|
log.debug(entry.toString());
|
||||||
applyEntry(PiTableEntryHandle.of(deviceId, entry),
|
final PiTableEntryHandle handle = PiTableEntryHandle.of(deviceId, entry);
|
||||||
entry, null, REMOVE);
|
ENTRY_LOCKS.get(handle).lock();
|
||||||
|
try {
|
||||||
|
applyEntry(handle, entry, null, REMOVE);
|
||||||
|
} finally {
|
||||||
|
ENTRY_LOCKS.get(handle).unlock();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<FlowRule> processFlowRules(Collection<FlowRule> rules,
|
private Collection<FlowRule> processFlowRules(Collection<FlowRule> rules,
|
||||||
Operation driverOperation) {
|
Operation driverOperation) {
|
||||||
|
|
||||||
if (!setupBehaviour()) {
|
if (!setupBehaviour() || rules.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,43 +323,66 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
* Applies the given entry to the device, and returns true if the operation
|
* Applies the given entry to the device, and returns true if the operation
|
||||||
* was successful, false otherwise.
|
* was successful, false otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean applyEntry(PiTableEntryHandle handle,
|
private boolean applyEntry(final PiTableEntryHandle handle,
|
||||||
PiTableEntry piEntryToApply,
|
PiTableEntry piEntryToApply,
|
||||||
FlowRule ruleToApply,
|
final FlowRule ruleToApply,
|
||||||
Operation driverOperation) {
|
final Operation driverOperation) {
|
||||||
// Depending on the driver operation, and if a matching rule exists on
|
// Depending on the driver operation, and if a matching rule exists on
|
||||||
// the device, decide which P4 Runtime write operation to perform for
|
// the device, decide which P4 Runtime write operation to perform for
|
||||||
// this entry.
|
// this entry.
|
||||||
final TimedEntry<PiTableEntry> piEntryOnDevice = tableMirror.get(handle);
|
final TimedEntry<PiTableEntry> piEntryOnDevice = tableMirror.get(handle);
|
||||||
final WriteOperationType p4Operation;
|
final WriteOperationType p4Operation;
|
||||||
|
final WriteOperationType storeOperation;
|
||||||
|
|
||||||
|
final boolean defaultAsEntry = driverBoolProperty(
|
||||||
|
TABLE_DEFAULT_AS_ENTRY, DEFAULT_TABLE_DEFAULT_AS_ENTRY);
|
||||||
|
final boolean ignoreSameEntryUpdate = driverBoolProperty(
|
||||||
|
IGNORE_SAME_ENTRY_UPDATE, DEFAULT_IGNORE_SAME_ENTRY_UPDATE);
|
||||||
|
final boolean deleteBeforeUpdate = driverBoolProperty(
|
||||||
|
DELETE_BEFORE_UPDATE, DEFAULT_DELETE_BEFORE_UPDATE);
|
||||||
if (driverOperation == APPLY) {
|
if (driverOperation == APPLY) {
|
||||||
if (piEntryOnDevice == null) {
|
if (piEntryOnDevice == null) {
|
||||||
// Entry is first-timer.
|
// Entry is first-timer, INSERT or MODIFY if default action.
|
||||||
p4Operation = INSERT;
|
p4Operation = !piEntryToApply.isDefaultAction() || defaultAsEntry
|
||||||
|
? INSERT : MODIFY;
|
||||||
|
storeOperation = p4Operation;
|
||||||
} else {
|
} else {
|
||||||
if (driverBoolProperty(IGNORE_SAME_ENTRY_UPDATE,
|
if (ignoreSameEntryUpdate &&
|
||||||
DEFAULT_IGNORE_SAME_ENTRY_UPDATE)
|
piEntryToApply.action().equals(piEntryOnDevice.entry().action())) {
|
||||||
&& piEntryToApply.action().equals(piEntryOnDevice.entry().action())) {
|
|
||||||
log.debug("Ignoring re-apply of existing entry: {}", piEntryToApply);
|
log.debug("Ignoring re-apply of existing entry: {}", piEntryToApply);
|
||||||
p4Operation = null;
|
p4Operation = null;
|
||||||
} else if (driverBoolProperty(DELETE_BEFORE_UPDATE,
|
} else if (deleteBeforeUpdate && !piEntryToApply.isDefaultAction()) {
|
||||||
DEFAULT_DELETE_BEFORE_UPDATE)) {
|
|
||||||
// Some devices return error when updating existing
|
// Some devices return error when updating existing
|
||||||
// entries. If requested, remove entry before
|
// entries. If requested, remove entry before
|
||||||
// re-inserting the modified one.
|
// re-inserting the modified one, except the default action
|
||||||
|
// entry, that cannot be removed.
|
||||||
applyEntry(handle, piEntryOnDevice.entry(), null, REMOVE);
|
applyEntry(handle, piEntryOnDevice.entry(), null, REMOVE);
|
||||||
p4Operation = INSERT;
|
p4Operation = INSERT;
|
||||||
} else {
|
} else {
|
||||||
p4Operation = MODIFY;
|
p4Operation = MODIFY;
|
||||||
}
|
}
|
||||||
|
storeOperation = p4Operation;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p4Operation = DELETE;
|
if (piEntryToApply.isDefaultAction()) {
|
||||||
|
// Cannot remove default action. Instead we should use the
|
||||||
|
// original defined by the interpreter (if any).
|
||||||
|
piEntryToApply = getOriginalDefaultEntry(piEntryToApply.table());
|
||||||
|
if (piEntryToApply == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p4Operation = MODIFY;
|
||||||
|
} else {
|
||||||
|
p4Operation = DELETE;
|
||||||
|
}
|
||||||
|
// Still want to delete the default entry from the mirror and
|
||||||
|
// translation store.
|
||||||
|
storeOperation = DELETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p4Operation != null) {
|
if (p4Operation != null) {
|
||||||
if (writeEntry(piEntryToApply, p4Operation)) {
|
if (writeEntry(piEntryToApply, p4Operation)) {
|
||||||
updateStores(handle, piEntryToApply, ruleToApply, p4Operation);
|
updateStores(handle, piEntryToApply, ruleToApply, storeOperation);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -317,6 +393,34 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PiTableEntry getOriginalDefaultEntry(PiTableId tableId) {
|
||||||
|
final PiPipelineInterpreter interpreter = getInterpreter();
|
||||||
|
if (interpreter == null) {
|
||||||
|
log.warn("Missing interpreter for {}, cannot get default action",
|
||||||
|
deviceId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!interpreter.getOriginalDefaultAction(tableId).isPresent()) {
|
||||||
|
log.warn("Interpreter of {} doesn't define a default action for " +
|
||||||
|
"table {}, cannot produce default action entry",
|
||||||
|
deviceId, tableId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return PiTableEntry.builder()
|
||||||
|
.forTable(tableId)
|
||||||
|
.withAction(interpreter.getOriginalDefaultAction(tableId).get())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOriginalDefaultEntry(PiTableEntry entry) {
|
||||||
|
if (!entry.isDefaultAction()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final PiTableEntry originalDefaultEntry = getOriginalDefaultEntry(entry.table());
|
||||||
|
return originalDefaultEntry != null &&
|
||||||
|
originalDefaultEntry.action().equals(entry.action());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a write operation on the device.
|
* Performs a write operation on the device.
|
||||||
*/
|
*/
|
||||||
@ -324,17 +428,9 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
WriteOperationType p4Operation) {
|
WriteOperationType p4Operation) {
|
||||||
final CompletableFuture<Boolean> future = client.writeTableEntries(
|
final CompletableFuture<Boolean> future = client.writeTableEntries(
|
||||||
newArrayList(entry), p4Operation, pipeconf);
|
newArrayList(entry), p4Operation, pipeconf);
|
||||||
final Boolean success = getFutureWithDeadline(
|
// If false, errors logged by internal calls.
|
||||||
future, "performing table " + p4Operation.name(), null);
|
return getFutureWithDeadline(
|
||||||
if (success == null) {
|
future, "performing table " + p4Operation.name(), false);
|
||||||
// Error logged by getFutureWithDeadline();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
log.warn("Unable to {} table entry in {}: {}",
|
|
||||||
p4Operation.name(), deviceId, entry);
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStores(PiTableEntryHandle handle,
|
private void updateStores(PiTableEntryHandle handle,
|
||||||
@ -373,6 +469,8 @@ public class P4RuntimeFlowRuleProgrammable
|
|||||||
cellDatas = Collections.emptyList();
|
cellDatas = Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
Set<PiCounterCellId> cellIds = tableEntries.stream()
|
Set<PiCounterCellId> cellIds = tableEntries.stream()
|
||||||
|
// Ignore counter for default entry.
|
||||||
|
.filter(e -> !e.isDefaultAction())
|
||||||
.filter(e -> tableHasCounter(e.table()))
|
.filter(e -> tableHasCounter(e.table()))
|
||||||
.map(PiCounterCellId::ofDirect)
|
.map(PiCounterCellId::ofDirect)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|||||||
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -17,418 +17,93 @@
|
|||||||
package org.onosproject.drivers.p4runtime;
|
package org.onosproject.drivers.p4runtime;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.util.concurrent.Striped;
|
|
||||||
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeGroupMirror;
|
|
||||||
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeMulticastGroupMirror;
|
|
||||||
import org.onosproject.drivers.p4runtime.mirror.TimedEntry;
|
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.group.DefaultGroup;
|
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||||
import org.onosproject.net.group.DefaultGroupDescription;
|
|
||||||
import org.onosproject.net.group.Group;
|
import org.onosproject.net.group.Group;
|
||||||
import org.onosproject.net.group.GroupDescription;
|
import org.onosproject.net.group.GroupDescription;
|
||||||
import org.onosproject.net.group.GroupOperation;
|
import org.onosproject.net.group.GroupOperation;
|
||||||
import org.onosproject.net.group.GroupOperations;
|
import org.onosproject.net.group.GroupOperations;
|
||||||
import org.onosproject.net.group.GroupProgrammable;
|
import org.onosproject.net.group.GroupProgrammable;
|
||||||
import org.onosproject.net.group.GroupStore;
|
|
||||||
import org.onosproject.net.pi.model.PiActionProfileId;
|
|
||||||
import org.onosproject.net.pi.model.PiActionProfileModel;
|
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroup;
|
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupHandle;
|
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
|
||||||
import org.onosproject.net.pi.runtime.PiMulticastGroupEntry;
|
|
||||||
import org.onosproject.net.pi.runtime.PiMulticastGroupEntryHandle;
|
|
||||||
import org.onosproject.net.pi.service.PiGroupTranslator;
|
|
||||||
import org.onosproject.net.pi.service.PiMulticastGroupTranslator;
|
|
||||||
import org.onosproject.net.pi.service.PiTranslatedEntity;
|
|
||||||
import org.onosproject.net.pi.service.PiTranslationException;
|
|
||||||
import org.onosproject.p4runtime.api.P4RuntimeClient;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Objects;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.DELETE;
|
|
||||||
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.INSERT;
|
|
||||||
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.MODIFY;
|
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the group programmable behaviour for P4Runtime.
|
* Implementation of GroupProgrammable for P4Runtime devices that uses two
|
||||||
* <p>
|
* different implementation of the same behavior to handle both action profile
|
||||||
* This implementation distinguishes between ALL groups, and other types. ALL
|
* groups and multicast groups.
|
||||||
* groups are handled via PRE multicast group programming, while other types are
|
|
||||||
* handled via action profile group programming.
|
|
||||||
*/
|
*/
|
||||||
public class P4RuntimeGroupProgrammable
|
public class P4RuntimeGroupProgrammable
|
||||||
extends AbstractP4RuntimeHandlerBehaviour
|
extends AbstractHandlerBehaviour implements GroupProgrammable {
|
||||||
implements GroupProgrammable {
|
|
||||||
|
|
||||||
private static final String ACT_GRP_MEMS_STR = "action group members";
|
private final Logger log = getLogger(this.getClass());
|
||||||
private static final String DELETE_STR = "delete";
|
|
||||||
private static final String ACT_GRP_STR = "action group";
|
|
||||||
private static final String INSERT_STR = "insert";
|
|
||||||
private static final String MODIFY_STR = "modify";
|
|
||||||
|
|
||||||
private static final Logger log = getLogger(P4RuntimeGroupProgrammable.class);
|
private void doPerformGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
|
||||||
|
// TODO: fix GroupProgrammable API, passing the device ID is ambiguous
|
||||||
// If true, we ignore re-installing groups that are already known in the
|
checkArgument(deviceId.equals(data().deviceId()),
|
||||||
// device mirror.
|
"passed deviceId must be the same assigned to this behavior");
|
||||||
private static final String CHECK_MIRROR_BEFORE_UPDATE = "checkMirrorBeforeUpdate";
|
final List<GroupOperation> actionGroups = Lists.newArrayList();
|
||||||
private static final boolean DEFAULT_CHECK_MIRROR_BEFORE_UPDATE = true;
|
final List<GroupOperation> multicastGroups = Lists.newArrayList();
|
||||||
|
groupOps.operations().forEach(op -> {
|
||||||
// If true, we avoid querying the device and return what's already known by
|
if (op.groupType().equals(GroupDescription.Type.ALL)) {
|
||||||
// the ONOS store.
|
multicastGroups.add(op);
|
||||||
private static final String IGNORE_DEVICE_WHEN_GET = "ignoreDeviceWhenGet";
|
} else {
|
||||||
private static final boolean DEFAULT_IGNORE_DEVICE_WHEN_GET = false;
|
actionGroups.add(op);
|
||||||
|
}
|
||||||
protected GroupStore groupStore;
|
});
|
||||||
private P4RuntimeGroupMirror groupMirror;
|
if (!actionGroups.isEmpty()) {
|
||||||
private PiGroupTranslator groupTranslator;
|
actionProgrammable().performGroupOperation(
|
||||||
private P4RuntimeMulticastGroupMirror mcGroupMirror;
|
deviceId, new GroupOperations(actionGroups));
|
||||||
private PiMulticastGroupTranslator mcGroupTranslator;
|
|
||||||
|
|
||||||
// Needed to synchronize operations over the same group.
|
|
||||||
private static final Striped<Lock> STRIPED_LOCKS = Striped.lock(30);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean setupBehaviour() {
|
|
||||||
if (!super.setupBehaviour()) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
groupMirror = this.handler().get(P4RuntimeGroupMirror.class);
|
if (!multicastGroups.isEmpty()) {
|
||||||
mcGroupMirror = this.handler().get(P4RuntimeMulticastGroupMirror.class);
|
multicastProgrammable().performGroupOperation(
|
||||||
groupStore = handler().get(GroupStore.class);
|
deviceId, new GroupOperations(multicastGroups));
|
||||||
groupTranslator = piTranslationService.groupTranslator();
|
}
|
||||||
mcGroupTranslator = piTranslationService.multicastGroupTranslator();
|
}
|
||||||
return true;
|
|
||||||
|
private Collection<Group> doGetGroups() {
|
||||||
|
return new ImmutableList.Builder<Group>()
|
||||||
|
.addAll(actionProgrammable().getGroups())
|
||||||
|
.addAll(multicastProgrammable().getGroups())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private P4RuntimeActionGroupProgrammable actionProgrammable() {
|
||||||
|
P4RuntimeActionGroupProgrammable prog = new P4RuntimeActionGroupProgrammable();
|
||||||
|
prog.setData(data());
|
||||||
|
prog.setHandler(handler());
|
||||||
|
return prog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private P4RuntimeMulticastGroupProgrammable multicastProgrammable() {
|
||||||
|
P4RuntimeMulticastGroupProgrammable prog = new P4RuntimeMulticastGroupProgrammable();
|
||||||
|
prog.setData(data());
|
||||||
|
prog.setHandler(handler());
|
||||||
|
return prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void performGroupOperation(DeviceId deviceId,
|
public void performGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
|
||||||
GroupOperations groupOps) {
|
try {
|
||||||
if (!setupBehaviour()) {
|
doPerformGroupOperation(deviceId, groupOps);
|
||||||
return;
|
} catch (Throwable ex) {
|
||||||
|
log.error("Unhandled exception on performGroupOperation", ex);
|
||||||
}
|
}
|
||||||
groupOps.operations().forEach(op -> {
|
|
||||||
// ONOS-7785 We need app cookie (action profile id) from the group
|
|
||||||
Group groupOnStore = groupStore.getGroup(deviceId, op.groupId());
|
|
||||||
GroupDescription groupDesc = new DefaultGroupDescription(deviceId,
|
|
||||||
op.groupType(),
|
|
||||||
op.buckets(),
|
|
||||||
groupOnStore.appCookie(),
|
|
||||||
op.groupId().id(),
|
|
||||||
groupOnStore.appId());
|
|
||||||
DefaultGroup groupToApply = new DefaultGroup(op.groupId(), groupDesc);
|
|
||||||
if (op.groupType().equals(GroupDescription.Type.ALL)) {
|
|
||||||
processMcGroupOp(deviceId, groupToApply, op.opType());
|
|
||||||
} else {
|
|
||||||
|
|
||||||
processGroupOp(deviceId, groupToApply, op.opType());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Group> getGroups() {
|
public Collection<Group> getGroups() {
|
||||||
if (!setupBehaviour()) {
|
try {
|
||||||
|
return doGetGroups();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
log.error("Unhandled exception on getGroups", ex);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
final ImmutableList.Builder<Group> groups = ImmutableList.builder();
|
|
||||||
|
|
||||||
if (!driverBoolProperty(IGNORE_DEVICE_WHEN_GET, DEFAULT_IGNORE_DEVICE_WHEN_GET)) {
|
|
||||||
groups.addAll(pipeconf.pipelineModel().actionProfiles().stream()
|
|
||||||
.map(PiActionProfileModel::id)
|
|
||||||
.flatMap(this::streamGroupsFromDevice)
|
|
||||||
.iterator());
|
|
||||||
// FIXME: enable reading MC groups from device once reading from
|
|
||||||
// PRE is supported in PI
|
|
||||||
// groups.addAll(getMcGroupsFromDevice());
|
|
||||||
} else {
|
|
||||||
groups.addAll(groupMirror.getAll(deviceId).stream()
|
|
||||||
.map(TimedEntry::entry)
|
|
||||||
.map(this::forgeGroupEntry)
|
|
||||||
.iterator());
|
|
||||||
}
|
|
||||||
// FIXME: same as before..
|
|
||||||
groups.addAll(mcGroupMirror.getAll(deviceId).stream()
|
|
||||||
.map(TimedEntry::entry)
|
|
||||||
.map(this::forgeMcGroupEntry)
|
|
||||||
.iterator());
|
|
||||||
|
|
||||||
return groups.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processGroupOp(DeviceId deviceId, Group pdGroup, GroupOperation.Type opType) {
|
|
||||||
final PiActionGroup piGroup;
|
|
||||||
try {
|
|
||||||
piGroup = groupTranslator.translate(pdGroup, pipeconf);
|
|
||||||
} catch (PiTranslationException e) {
|
|
||||||
log.warn("Unable to translate group, aborting {} operation: {} [{}]",
|
|
||||||
opType, e.getMessage(), pdGroup);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final PiActionGroupHandle handle = PiActionGroupHandle.of(deviceId, piGroup);
|
|
||||||
|
|
||||||
final PiActionGroup groupOnDevice = groupMirror.get(handle) == null
|
|
||||||
? null
|
|
||||||
: groupMirror.get(handle).entry();
|
|
||||||
|
|
||||||
final Lock lock = STRIPED_LOCKS.get(handle);
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
processPiGroup(handle, piGroup,
|
|
||||||
groupOnDevice, pdGroup, opType);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processMcGroupOp(DeviceId deviceId, Group pdGroup, GroupOperation.Type opType) {
|
|
||||||
final PiMulticastGroupEntry mcGroup;
|
|
||||||
try {
|
|
||||||
mcGroup = mcGroupTranslator.translate(pdGroup, pipeconf);
|
|
||||||
} catch (PiTranslationException e) {
|
|
||||||
log.warn("Unable to translate multicast group, aborting {} operation: {} [{}]",
|
|
||||||
opType, e.getMessage(), pdGroup);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final PiMulticastGroupEntryHandle handle = PiMulticastGroupEntryHandle.of(
|
|
||||||
deviceId, mcGroup);
|
|
||||||
final PiMulticastGroupEntry groupOnDevice = mcGroupMirror.get(handle) == null
|
|
||||||
? null
|
|
||||||
: mcGroupMirror.get(handle).entry();
|
|
||||||
final Lock lock = STRIPED_LOCKS.get(handle);
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
processMcGroup(handle, mcGroup,
|
|
||||||
groupOnDevice, pdGroup, opType);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processPiGroup(PiActionGroupHandle handle,
|
|
||||||
PiActionGroup groupToApply,
|
|
||||||
PiActionGroup groupOnDevice,
|
|
||||||
Group pdGroup, GroupOperation.Type operationType) {
|
|
||||||
if (operationType == GroupOperation.Type.ADD) {
|
|
||||||
if (groupOnDevice != null) {
|
|
||||||
log.warn("Unable to add group {} since group already on device {}",
|
|
||||||
groupToApply.id(), deviceId);
|
|
||||||
log.debug("To apply: {}", groupToApply);
|
|
||||||
log.debug("On device: {}", groupOnDevice);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writeGroupToDevice(groupToApply)) {
|
|
||||||
groupMirror.put(handle, groupToApply);
|
|
||||||
groupTranslator.learn(handle, new PiTranslatedEntity<>(
|
|
||||||
pdGroup, groupToApply, handle));
|
|
||||||
}
|
|
||||||
} else if (operationType == GroupOperation.Type.MODIFY) {
|
|
||||||
if (groupOnDevice == null) {
|
|
||||||
log.warn("Group {} does not exists on device {}, can not modify it",
|
|
||||||
groupToApply.id(), deviceId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE, DEFAULT_CHECK_MIRROR_BEFORE_UPDATE)
|
|
||||||
&& groupOnDevice.equals(groupToApply)) {
|
|
||||||
// Group on device has the same members, ignore operation.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (modifyGroupFromDevice(groupToApply, groupOnDevice)) {
|
|
||||||
groupMirror.put(handle, groupToApply);
|
|
||||||
groupTranslator.learn(handle,
|
|
||||||
new PiTranslatedEntity<>(pdGroup, groupToApply, handle));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (groupOnDevice == null) {
|
|
||||||
log.warn("Unable to remove group {} from device {} since it does" +
|
|
||||||
"not exists on device.", groupToApply.id(), deviceId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (deleteGroupFromDevice(groupOnDevice)) {
|
|
||||||
groupMirror.remove(handle);
|
|
||||||
groupTranslator.forget(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processMcGroup(PiMulticastGroupEntryHandle handle,
|
|
||||||
PiMulticastGroupEntry groupToApply,
|
|
||||||
PiMulticastGroupEntry groupOnDevice,
|
|
||||||
Group pdGroup, GroupOperation.Type opType) {
|
|
||||||
if (opType == GroupOperation.Type.DELETE) {
|
|
||||||
if (writeMcGroupOnDevice(groupToApply, DELETE)) {
|
|
||||||
mcGroupMirror.remove(handle);
|
|
||||||
mcGroupTranslator.forget(handle);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final P4RuntimeClient.WriteOperationType p4OpType =
|
|
||||||
opType == GroupOperation.Type.ADD ? INSERT : MODIFY;
|
|
||||||
|
|
||||||
if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE,
|
|
||||||
DEFAULT_CHECK_MIRROR_BEFORE_UPDATE)
|
|
||||||
&& p4OpType == MODIFY
|
|
||||||
&& groupOnDevice != null
|
|
||||||
&& groupOnDevice.equals(groupToApply)) {
|
|
||||||
// Ignore.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writeMcGroupOnDevice(groupToApply, p4OpType)) {
|
|
||||||
mcGroupMirror.put(handle, groupToApply);
|
|
||||||
mcGroupTranslator.learn(handle, new PiTranslatedEntity<>(
|
|
||||||
pdGroup, groupToApply, handle));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean writeMcGroupOnDevice(PiMulticastGroupEntry group, P4RuntimeClient.WriteOperationType opType) {
|
|
||||||
return getFutureWithDeadline(
|
|
||||||
client.writePreMulticastGroupEntries(
|
|
||||||
Collections.singleton(group), opType),
|
|
||||||
"performing multicast group " + opType, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean modifyGroupFromDevice(PiActionGroup groupToApply, PiActionGroup groupOnDevice) {
|
|
||||||
PiActionProfileId groupProfileId = groupToApply.actionProfileId();
|
|
||||||
Collection<PiActionGroupMember> membersToRemove = Sets.newHashSet(groupOnDevice.members());
|
|
||||||
membersToRemove.removeAll(groupToApply.members());
|
|
||||||
Collection<PiActionGroupMember> membersToAdd = Sets.newHashSet(groupToApply.members());
|
|
||||||
membersToAdd.removeAll(groupOnDevice.members());
|
|
||||||
|
|
||||||
if (!membersToAdd.isEmpty() &&
|
|
||||||
!completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, INSERT, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, INSERT_STR)) {
|
|
||||||
// remove what we added
|
|
||||||
completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, DELETE, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, INSERT_STR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!completeFuture(client.writeActionGroup(groupToApply, MODIFY, pipeconf),
|
|
||||||
ACT_GRP_STR, MODIFY_STR)) {
|
|
||||||
// recover group information
|
|
||||||
completeFuture(client.writeActionGroup(groupOnDevice, MODIFY, pipeconf),
|
|
||||||
ACT_GRP_STR, MODIFY_STR);
|
|
||||||
// remove what we added
|
|
||||||
completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, DELETE, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, INSERT_STR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!membersToRemove.isEmpty() &&
|
|
||||||
!completeFuture(client.writeActionGroupMembers(groupProfileId, membersToRemove, DELETE, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, DELETE_STR)) {
|
|
||||||
// add what we removed
|
|
||||||
completeFuture(client.writeActionGroupMembers(groupProfileId, membersToRemove, INSERT, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, DELETE_STR);
|
|
||||||
// recover group information
|
|
||||||
completeFuture(client.writeActionGroup(groupOnDevice, MODIFY, pipeconf),
|
|
||||||
ACT_GRP_STR, MODIFY_STR);
|
|
||||||
// remove what we added
|
|
||||||
completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, DELETE, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, INSERT_STR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean writeGroupToDevice(PiActionGroup groupToApply) {
|
|
||||||
// First insert members, then group.
|
|
||||||
// The operation is deemed successful if both operations are successful.
|
|
||||||
// FIXME: add transactional semantics, i.e. remove members if group fails.
|
|
||||||
final boolean membersSuccess = completeFuture(
|
|
||||||
client.writeActionGroupMembers(groupToApply.actionProfileId(),
|
|
||||||
groupToApply.members(),
|
|
||||||
INSERT, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, INSERT_STR);
|
|
||||||
return membersSuccess && completeFuture(
|
|
||||||
client.writeActionGroup(groupToApply, INSERT, pipeconf),
|
|
||||||
ACT_GRP_STR, INSERT_STR);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean deleteGroupFromDevice(PiActionGroup piActionGroup) {
|
|
||||||
// First delete group, then members.
|
|
||||||
// The operation is deemed successful if both operations are successful.
|
|
||||||
final boolean groupSuccess = completeFuture(
|
|
||||||
client.writeActionGroup(piActionGroup, DELETE, pipeconf),
|
|
||||||
ACT_GRP_STR, DELETE_STR);
|
|
||||||
return groupSuccess && completeFuture(
|
|
||||||
client.writeActionGroupMembers(piActionGroup.actionProfileId(),
|
|
||||||
piActionGroup.members(),
|
|
||||||
DELETE, pipeconf),
|
|
||||||
ACT_GRP_MEMS_STR, DELETE_STR);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean completeFuture(CompletableFuture<Boolean> completableFuture,
|
|
||||||
String topic, String action) {
|
|
||||||
return getFutureWithDeadline(
|
|
||||||
completableFuture, format("performing %s %s", action, topic), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream<Group> streamGroupsFromDevice(PiActionProfileId actProfId) {
|
|
||||||
// Read PI groups and return original PD one.
|
|
||||||
Collection<PiActionGroup> groups = getFutureWithDeadline(
|
|
||||||
client.dumpGroups(actProfId, pipeconf),
|
|
||||||
"dumping groups", Collections.emptyList());
|
|
||||||
return groups.stream()
|
|
||||||
.map(this::forgeGroupEntry)
|
|
||||||
.filter(Objects::nonNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Collection<Group> getMcGroupsFromDevice() {
|
|
||||||
Collection<PiMulticastGroupEntry> groups = getFutureWithDeadline(
|
|
||||||
client.readAllMulticastGroupEntries(),
|
|
||||||
"dumping multicast groups", Collections.emptyList());
|
|
||||||
return groups.stream()
|
|
||||||
.map(this::forgeMcGroupEntry)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Group forgeGroupEntry(PiActionGroup piGroup) {
|
|
||||||
final PiActionGroupHandle handle = PiActionGroupHandle.of(deviceId, piGroup);
|
|
||||||
if (!groupTranslator.lookup(handle).isPresent()) {
|
|
||||||
log.warn("Missing PI group from translation store: {} - {}:{}",
|
|
||||||
pipeconf.id(), piGroup.actionProfileId(),
|
|
||||||
piGroup.id());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final long life = groupMirror.get(handle) != null
|
|
||||||
? groupMirror.get(handle).lifeSec() : 0;
|
|
||||||
final Group original = groupTranslator.lookup(handle).get().original();
|
|
||||||
return addedGroup(original, life);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Group forgeMcGroupEntry(PiMulticastGroupEntry mcGroup) {
|
|
||||||
final PiMulticastGroupEntryHandle handle = PiMulticastGroupEntryHandle.of(
|
|
||||||
deviceId, mcGroup);
|
|
||||||
if (!mcGroupTranslator.lookup(handle).isPresent()) {
|
|
||||||
log.warn("Missing PI multicast group {} from translation store",
|
|
||||||
mcGroup.groupId());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final long life = mcGroupMirror.get(handle) != null
|
|
||||||
? mcGroupMirror.get(handle).lifeSec() : 0;
|
|
||||||
final Group original = mcGroupTranslator.lookup(handle).get().original();
|
|
||||||
return addedGroup(original, life);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Group addedGroup(Group original, long life) {
|
|
||||||
final DefaultGroup forgedGroup = new DefaultGroup(original.id(), original);
|
|
||||||
forgedGroup.setState(Group.GroupState.ADDED);
|
|
||||||
forgedGroup.setLife(life);
|
|
||||||
return forgedGroup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* 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.drivers.p4runtime;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.util.concurrent.Striped;
|
||||||
|
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeMulticastGroupMirror;
|
||||||
|
import org.onosproject.drivers.p4runtime.mirror.TimedEntry;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.group.DefaultGroup;
|
||||||
|
import org.onosproject.net.group.Group;
|
||||||
|
import org.onosproject.net.group.GroupDescription;
|
||||||
|
import org.onosproject.net.group.GroupOperation;
|
||||||
|
import org.onosproject.net.group.GroupOperations;
|
||||||
|
import org.onosproject.net.group.GroupProgrammable;
|
||||||
|
import org.onosproject.net.group.GroupStore;
|
||||||
|
import org.onosproject.net.pi.runtime.PiMulticastGroupEntry;
|
||||||
|
import org.onosproject.net.pi.runtime.PiMulticastGroupEntryHandle;
|
||||||
|
import org.onosproject.net.pi.service.PiMulticastGroupTranslator;
|
||||||
|
import org.onosproject.net.pi.service.PiTranslatedEntity;
|
||||||
|
import org.onosproject.net.pi.service.PiTranslationException;
|
||||||
|
import org.onosproject.p4runtime.api.P4RuntimeClient;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.DELETE;
|
||||||
|
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.INSERT;
|
||||||
|
import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.MODIFY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of GroupProgrammable to handle multicast groups in P4Runtime.
|
||||||
|
*/
|
||||||
|
public class P4RuntimeMulticastGroupProgrammable
|
||||||
|
extends AbstractP4RuntimeHandlerBehaviour implements GroupProgrammable {
|
||||||
|
|
||||||
|
// Needed to synchronize operations over the same group.
|
||||||
|
private static final Striped<Lock> STRIPED_LOCKS = Striped.lock(30);
|
||||||
|
|
||||||
|
private GroupStore groupStore;
|
||||||
|
private P4RuntimeMulticastGroupMirror mcGroupMirror;
|
||||||
|
private PiMulticastGroupTranslator mcGroupTranslator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean setupBehaviour() {
|
||||||
|
if (!super.setupBehaviour()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mcGroupMirror = this.handler().get(P4RuntimeMulticastGroupMirror.class);
|
||||||
|
groupStore = handler().get(GroupStore.class);
|
||||||
|
mcGroupTranslator = piTranslationService.multicastGroupTranslator();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
groupOps.operations().stream()
|
||||||
|
.filter(op -> op.groupType().equals(GroupDescription.Type.ALL))
|
||||||
|
.forEach(op -> {
|
||||||
|
final Group group = groupStore.getGroup(deviceId, op.groupId());
|
||||||
|
processMcGroupOp(group, op.opType());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Group> getGroups() {
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return ImmutableList.copyOf(getMcGroups());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Group> getMcGroups() {
|
||||||
|
// TODO: missing support for reading multicast groups is ready in PI/Stratum.
|
||||||
|
return getMcGroupsFromMirror();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Group> getMcGroupsFromMirror() {
|
||||||
|
return mcGroupMirror.getAll(deviceId).stream()
|
||||||
|
.map(TimedEntry::entry)
|
||||||
|
.map(this::forgeMcGroupEntry)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMcGroupOp(Group pdGroup, GroupOperation.Type opType) {
|
||||||
|
final PiMulticastGroupEntry mcGroup;
|
||||||
|
try {
|
||||||
|
mcGroup = mcGroupTranslator.translate(pdGroup, pipeconf);
|
||||||
|
} catch (PiTranslationException e) {
|
||||||
|
log.warn("Unable to translate multicast group, aborting {} operation: {} [{}]",
|
||||||
|
opType, e.getMessage(), pdGroup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final PiMulticastGroupEntryHandle handle = PiMulticastGroupEntryHandle.of(
|
||||||
|
deviceId, mcGroup);
|
||||||
|
final PiMulticastGroupEntry groupOnDevice = mcGroupMirror.get(handle) == null
|
||||||
|
? null
|
||||||
|
: mcGroupMirror.get(handle).entry();
|
||||||
|
final Lock lock = STRIPED_LOCKS.get(handle);
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
processMcGroup(handle, mcGroup,
|
||||||
|
groupOnDevice, pdGroup, opType);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMcGroup(PiMulticastGroupEntryHandle handle,
|
||||||
|
PiMulticastGroupEntry groupToApply,
|
||||||
|
PiMulticastGroupEntry groupOnDevice,
|
||||||
|
Group pdGroup, GroupOperation.Type opType) {
|
||||||
|
switch (opType) {
|
||||||
|
case ADD:
|
||||||
|
robustMcGroupAdd(handle, groupToApply, pdGroup);
|
||||||
|
return;
|
||||||
|
case MODIFY:
|
||||||
|
// Since reading multicast groups is not supported yet on
|
||||||
|
// PI/Stratum, we cannot trust groupOnDevic) as we don't have a
|
||||||
|
// mechanism to enforce consistency of the mirror with the
|
||||||
|
// device state.
|
||||||
|
// if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE,
|
||||||
|
// DEFAULT_CHECK_MIRROR_BEFORE_UPDATE)
|
||||||
|
// && p4OpType == MODIFY
|
||||||
|
// && groupOnDevice != null
|
||||||
|
// && groupOnDevice.equals(groupToApply)) {
|
||||||
|
// // Ignore.
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
robustMcGroupModify(handle, groupToApply, pdGroup);
|
||||||
|
return;
|
||||||
|
case DELETE:
|
||||||
|
mcGroupApply(handle, groupToApply, pdGroup, DELETE);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
log.error("Unknown group operation type {}, " +
|
||||||
|
"cannot process multicast group", opType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeMcGroupOnDevice(PiMulticastGroupEntry group, P4RuntimeClient.WriteOperationType opType) {
|
||||||
|
return getFutureWithDeadline(
|
||||||
|
client.writePreMulticastGroupEntries(
|
||||||
|
Collections.singletonList(group), opType),
|
||||||
|
"performing multicast group " + opType, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean mcGroupApply(PiMulticastGroupEntryHandle handle,
|
||||||
|
PiMulticastGroupEntry piGroup,
|
||||||
|
Group pdGroup,
|
||||||
|
P4RuntimeClient.WriteOperationType opType) {
|
||||||
|
switch (opType) {
|
||||||
|
case DELETE:
|
||||||
|
if (writeMcGroupOnDevice(piGroup, DELETE)) {
|
||||||
|
mcGroupMirror.remove(handle);
|
||||||
|
mcGroupTranslator.forget(handle);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case INSERT:
|
||||||
|
case MODIFY:
|
||||||
|
if (writeMcGroupOnDevice(piGroup, opType)) {
|
||||||
|
mcGroupMirror.put(handle, piGroup);
|
||||||
|
mcGroupTranslator.learn(handle, new PiTranslatedEntity<>(
|
||||||
|
pdGroup, piGroup, handle));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.warn("Unknown operation type {}, cannot apply group", opType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void robustMcGroupAdd(PiMulticastGroupEntryHandle handle,
|
||||||
|
PiMulticastGroupEntry piGroup,
|
||||||
|
Group pdGroup) {
|
||||||
|
if (mcGroupApply(handle, piGroup, pdGroup, INSERT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Try to delete (perhaps it already exists) and re-add...
|
||||||
|
mcGroupApply(handle, piGroup, pdGroup, DELETE);
|
||||||
|
mcGroupApply(handle, piGroup, pdGroup, INSERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void robustMcGroupModify(PiMulticastGroupEntryHandle handle,
|
||||||
|
PiMulticastGroupEntry piGroup,
|
||||||
|
Group pdGroup) {
|
||||||
|
if (mcGroupApply(handle, piGroup, pdGroup, MODIFY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Not sure for which reason it cannot be modified, so try to delete and insert instead...
|
||||||
|
mcGroupApply(handle, piGroup, pdGroup, DELETE);
|
||||||
|
mcGroupApply(handle, piGroup, pdGroup, INSERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Group forgeMcGroupEntry(PiMulticastGroupEntry mcGroup) {
|
||||||
|
final PiMulticastGroupEntryHandle handle = PiMulticastGroupEntryHandle.of(
|
||||||
|
deviceId, mcGroup);
|
||||||
|
final Optional<PiTranslatedEntity<Group, PiMulticastGroupEntry>>
|
||||||
|
translatedEntity = mcGroupTranslator.lookup(handle);
|
||||||
|
final TimedEntry<PiMulticastGroupEntry> timedEntry = mcGroupMirror.get(handle);
|
||||||
|
// Is entry consistent with our state?
|
||||||
|
if (!translatedEntity.isPresent()) {
|
||||||
|
log.warn("Multicast group handle not found in translation store: {}", handle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (timedEntry == null) {
|
||||||
|
log.warn("Multicast group handle not found in device mirror: {}", handle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return addedGroup(translatedEntity.get().original(), timedEntry.lifeSec());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Group addedGroup(Group original, long life) {
|
||||||
|
final DefaultGroup forgedGroup = new DefaultGroup(original.id(), original);
|
||||||
|
forgedGroup.setState(Group.GroupState.ADDED);
|
||||||
|
forgedGroup.setLife(life);
|
||||||
|
return forgedGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -17,15 +17,21 @@
|
|||||||
package org.onosproject.drivers.p4runtime.mirror;
|
package org.onosproject.drivers.p4runtime.mirror;
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
import com.google.common.annotations.Beta;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import org.osgi.service.component.annotations.Activate;
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Deactivate;
|
import org.osgi.service.component.annotations.Deactivate;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
|
|
||||||
import org.onlab.util.KryoNamespace;
|
import org.onlab.util.KryoNamespace;
|
||||||
|
import org.onlab.util.SharedExecutors;
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.pi.runtime.PiEntity;
|
import org.onosproject.net.pi.runtime.PiEntity;
|
||||||
import org.onosproject.net.pi.runtime.PiHandle;
|
import org.onosproject.net.pi.runtime.PiHandle;
|
||||||
|
import org.onosproject.net.pi.service.PiPipeconfWatchdogEvent;
|
||||||
|
import org.onosproject.net.pi.service.PiPipeconfWatchdogListener;
|
||||||
|
import org.onosproject.net.pi.service.PiPipeconfWatchdogService;
|
||||||
import org.onosproject.store.service.EventuallyConsistentMap;
|
import org.onosproject.store.service.EventuallyConsistentMap;
|
||||||
import org.onosproject.store.service.StorageService;
|
import org.onosproject.store.service.StorageService;
|
||||||
import org.onosproject.store.service.WallClockTimestamp;
|
import org.onosproject.store.service.WallClockTimestamp;
|
||||||
@ -33,9 +39,12 @@ import org.slf4j.Logger;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.onosproject.net.pi.service.PiPipeconfWatchdogService.PipelineStatus.READY;
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,8 +65,14 @@ public abstract class AbstractDistributedP4RuntimeMirror
|
|||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
private StorageService storageService;
|
private StorageService storageService;
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
|
private PiPipeconfWatchdogService pipeconfWatchdogService;
|
||||||
|
|
||||||
private EventuallyConsistentMap<H, TimedEntry<E>> mirrorMap;
|
private EventuallyConsistentMap<H, TimedEntry<E>> mirrorMap;
|
||||||
|
|
||||||
|
private final PiPipeconfWatchdogListener pipeconfListener =
|
||||||
|
new InternalPipeconfWatchdogListener();
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public void activate() {
|
public void activate() {
|
||||||
mirrorMap = storageService
|
mirrorMap = storageService
|
||||||
@ -66,6 +81,7 @@ public abstract class AbstractDistributedP4RuntimeMirror
|
|||||||
.withSerializer(storeSerializer())
|
.withSerializer(storeSerializer())
|
||||||
.withTimestampProvider((k, v) -> new WallClockTimestamp())
|
.withTimestampProvider((k, v) -> new WallClockTimestamp())
|
||||||
.build();
|
.build();
|
||||||
|
pipeconfWatchdogService.addListener(pipeconfListener);
|
||||||
log.info("Started");
|
log.info("Started");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +91,7 @@ public abstract class AbstractDistributedP4RuntimeMirror
|
|||||||
|
|
||||||
@Deactivate
|
@Deactivate
|
||||||
public void deactivate() {
|
public void deactivate() {
|
||||||
|
pipeconfWatchdogService.removeListener(pipeconfListener);
|
||||||
mirrorMap.destroy();
|
mirrorMap.destroy();
|
||||||
mirrorMap = null;
|
mirrorMap = null;
|
||||||
log.info("Stopped");
|
log.info("Stopped");
|
||||||
@ -99,6 +116,14 @@ public abstract class AbstractDistributedP4RuntimeMirror
|
|||||||
public void put(H handle, E entry) {
|
public void put(H handle, E entry) {
|
||||||
checkNotNull(handle);
|
checkNotNull(handle);
|
||||||
checkNotNull(entry);
|
checkNotNull(entry);
|
||||||
|
final PiPipeconfWatchdogService.PipelineStatus status =
|
||||||
|
pipeconfWatchdogService.getStatus(handle.deviceId());
|
||||||
|
if (!status.equals(READY)) {
|
||||||
|
log.info("Ignoring device mirror update because pipeline " +
|
||||||
|
"status of {} is {}: {}",
|
||||||
|
handle.deviceId(), status, entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
final long now = new WallClockTimestamp().unixTimestamp();
|
final long now = new WallClockTimestamp().unixTimestamp();
|
||||||
final TimedEntry<E> timedEntry = new TimedEntry<>(now, entry);
|
final TimedEntry<E> timedEntry = new TimedEntry<>(now, entry);
|
||||||
mirrorMap.put(handle, timedEntry);
|
mirrorMap.put(handle, timedEntry);
|
||||||
@ -110,4 +135,77 @@ public abstract class AbstractDistributedP4RuntimeMirror
|
|||||||
mirrorMap.remove(handle);
|
mirrorMap.remove(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sync(DeviceId deviceId, Map<H, E> deviceState) {
|
||||||
|
checkNotNull(deviceId);
|
||||||
|
final Map<H, E> localState = getMirrorMapForDevice(deviceId);
|
||||||
|
|
||||||
|
final AtomicInteger removeCount = new AtomicInteger(0);
|
||||||
|
final AtomicInteger updateCount = new AtomicInteger(0);
|
||||||
|
final AtomicInteger addCount = new AtomicInteger(0);
|
||||||
|
// Add missing entries.
|
||||||
|
deviceState.keySet().stream()
|
||||||
|
.filter(deviceHandle -> !localState.containsKey(deviceHandle))
|
||||||
|
.forEach(deviceHandle -> {
|
||||||
|
final E entryToAdd = deviceState.get(deviceHandle);
|
||||||
|
log.debug("Adding mirror entry for {}: {}",
|
||||||
|
deviceId, entryToAdd);
|
||||||
|
put(deviceHandle, entryToAdd);
|
||||||
|
addCount.incrementAndGet();
|
||||||
|
});
|
||||||
|
// Update or remove local entries.
|
||||||
|
localState.keySet().forEach(localHandle -> {
|
||||||
|
final E localEntry = localState.get(localHandle);
|
||||||
|
final E deviceEntry = deviceState.get(localHandle);
|
||||||
|
if (deviceEntry == null) {
|
||||||
|
log.debug("Removing mirror entry for {}: {}", deviceId, localEntry);
|
||||||
|
remove(localHandle);
|
||||||
|
removeCount.incrementAndGet();
|
||||||
|
} else if (!deviceEntry.equals(localEntry)) {
|
||||||
|
log.debug("Updating mirror entry for {}: {}-->{}",
|
||||||
|
deviceId, localEntry, deviceEntry);
|
||||||
|
put(localHandle, deviceEntry);
|
||||||
|
updateCount.incrementAndGet();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (removeCount.get() + updateCount.get() + addCount.get() > 0) {
|
||||||
|
log.info("Synchronized mirror entries for {}: {} removed, {} updated, {} added",
|
||||||
|
deviceId, removeCount, updateCount, addCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<H> getHandlesForDevice(DeviceId deviceId) {
|
||||||
|
return mirrorMap.keySet().stream()
|
||||||
|
.filter(h -> h.deviceId().equals(deviceId))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<H, E> getMirrorMapForDevice(DeviceId deviceId) {
|
||||||
|
final Map<H, E> deviceMap = Maps.newHashMap();
|
||||||
|
mirrorMap.entrySet().stream()
|
||||||
|
.filter(e -> e.getKey().deviceId().equals(deviceId))
|
||||||
|
.forEach(e -> deviceMap.put(e.getKey(), e.getValue().entry()));
|
||||||
|
return deviceMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeAll(DeviceId deviceId) {
|
||||||
|
checkNotNull(deviceId);
|
||||||
|
Collection<H> handles = getHandlesForDevice(deviceId);
|
||||||
|
handles.forEach(mirrorMap::remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InternalPipeconfWatchdogListener implements PiPipeconfWatchdogListener {
|
||||||
|
@Override
|
||||||
|
public void event(PiPipeconfWatchdogEvent event) {
|
||||||
|
log.debug("Flushing mirror for {}, pipeline status is {}",
|
||||||
|
event.subject(), event.type());
|
||||||
|
SharedExecutors.getPoolThreadExecutor().execute(
|
||||||
|
() -> removeAll(event.subject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRelevant(PiPipeconfWatchdogEvent event) {
|
||||||
|
return event.type().equals(PiPipeconfWatchdogEvent.Type.PIPELINE_UNKNOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* 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.drivers.p4runtime.mirror;
|
||||||
|
|
||||||
|
import org.onlab.util.KryoNamespace;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMemberHandle;
|
||||||
|
import org.onosproject.store.serializers.KryoNamespaces;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distributed implementation of a P4Runtime action profile member mirror.
|
||||||
|
*/
|
||||||
|
@Component(immediate = true, service = AbstractDistributedP4RuntimeMirror.class)
|
||||||
|
public class DistributedP4RuntimeActionProfileMemberMirror
|
||||||
|
extends AbstractDistributedP4RuntimeMirror
|
||||||
|
<PiActionGroupMemberHandle, PiActionGroupMember>
|
||||||
|
implements P4RuntimeActionProfileMemberMirror {
|
||||||
|
|
||||||
|
private static final String DIST_MAP_NAME = "onos-p4runtime-act-prof-member-mirror";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String mapName() {
|
||||||
|
return DIST_MAP_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
KryoNamespace storeSerializer() {
|
||||||
|
return KryoNamespace.newBuilder()
|
||||||
|
.register(KryoNamespaces.API)
|
||||||
|
.register(TimedEntry.class)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-present Open Networking Foundation
|
* Copyright 2018-present Open Networking Foundation
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -14,7 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package org.onosproject.drivers.p4runtime.mirror;
|
||||||
|
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMemberHandle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IntService sample application.
|
* Mirror of action profile members installed on a P4Runtime device.
|
||||||
*/
|
*/
|
||||||
package org.onosproject.inbandtelemetry.app;
|
public interface P4RuntimeActionProfileMemberMirror
|
||||||
|
extends P4RuntimeMirror<PiActionGroupMemberHandle, PiActionGroupMember> {
|
||||||
|
}
|
||||||
@ -22,6 +22,7 @@ import org.onosproject.net.pi.runtime.PiEntity;
|
|||||||
import org.onosproject.net.pi.runtime.PiHandle;
|
import org.onosproject.net.pi.runtime.PiHandle;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to keep track of the device state for a given class of PI entities.
|
* Service to keep track of the device state for a given class of PI entities.
|
||||||
@ -71,4 +72,12 @@ public interface P4RuntimeMirror
|
|||||||
* @param handle handle
|
* @param handle handle
|
||||||
*/
|
*/
|
||||||
void remove(H handle);
|
void remove(H handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronizes the state of the given device ID with the given handle map.
|
||||||
|
*
|
||||||
|
* @param deviceId device ID
|
||||||
|
* @param handleMap handle map
|
||||||
|
*/
|
||||||
|
void sync(DeviceId deviceId, Map<H, E> handleMap);
|
||||||
}
|
}
|
||||||
|
|||||||
84
lib/BUCK
84
lib/BUCK
@ -1,8 +1,12 @@
|
|||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
|
<<<<<<< HEAD
|
||||||
# ***** This file was auto-generated at Tue, 18 Sep 2018 20:31:36 GMT. Do not edit this file manually. *****
|
# ***** This file was auto-generated at Tue, 18 Sep 2018 20:31:36 GMT. Do not edit this file manually. *****
|
||||||
=======
|
=======
|
||||||
# ***** This file was auto-generated at Thu, 27 Sep 2018 15:25:26 GMT. Do not edit this file manually. *****
|
# ***** This file was auto-generated at Thu, 27 Sep 2018 15:25:26 GMT. Do not edit this file manually. *****
|
||||||
>>>>>>> origin/master
|
>>>>>>> origin/master
|
||||||
|
=======
|
||||||
|
# ***** This file was auto-generated at Fri, 5 Oct 2018 20:40:12 GMT. Do not edit this file manually. *****
|
||||||
|
>>>>>>> master
|
||||||
# ***** Use onos-lib-gen *****
|
# ***** Use onos-lib-gen *****
|
||||||
|
|
||||||
pass_thru_pom(
|
pass_thru_pom(
|
||||||
@ -246,82 +250,82 @@ remote_jar (
|
|||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix',
|
name = 'atomix',
|
||||||
out = 'atomix-3.0.5.jar',
|
out = 'atomix-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix:jar:3.0.6',
|
||||||
sha1 = '758df25aed743d625930654d2e589cc0084efdbc',
|
sha1 = 'a8c1401b9f5d3757c8cfa2b7905d928825507cf8',
|
||||||
maven_coords = 'io.atomix:atomix:3.0.5',
|
maven_coords = 'io.atomix:atomix:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix-cluster',
|
name = 'atomix-cluster',
|
||||||
out = 'atomix-cluster-3.0.5.jar',
|
out = 'atomix-cluster-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix-cluster:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix-cluster:jar:3.0.6',
|
||||||
sha1 = '3ac50436eaf47fa5ba7553b37628aea7fa8b8deb',
|
sha1 = '8d91e0caf5c2739476826b32bdcf21afc32bf433',
|
||||||
maven_coords = 'io.atomix:atomix-cluster:3.0.5',
|
maven_coords = 'io.atomix:atomix-cluster:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix-gossip',
|
name = 'atomix-gossip',
|
||||||
out = 'atomix-gossip-3.0.5.jar',
|
out = 'atomix-gossip-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix-gossip:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix-gossip:jar:3.0.6',
|
||||||
sha1 = '63c365b00b0164aa067e55febca9a4df253e8ab2',
|
sha1 = '5db475ea2702fabfb8eb19079bc07979bc706c17',
|
||||||
maven_coords = 'io.atomix:atomix-gossip:3.0.5',
|
maven_coords = 'io.atomix:atomix-gossip:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix-primary-backup',
|
name = 'atomix-primary-backup',
|
||||||
out = 'atomix-primary-backup-3.0.5.jar',
|
out = 'atomix-primary-backup-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix-primary-backup:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix-primary-backup:jar:3.0.6',
|
||||||
sha1 = 'f444f8f733457182a096786dd2b6a4369d1feebc',
|
sha1 = 'af3a4475a54a83fe8eafd58925c04db608eec150',
|
||||||
maven_coords = 'io.atomix:atomix-primary-backup:3.0.5',
|
maven_coords = 'io.atomix:atomix-primary-backup:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix-primitive',
|
name = 'atomix-primitive',
|
||||||
out = 'atomix-primitive-3.0.5.jar',
|
out = 'atomix-primitive-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix-primitive:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix-primitive:jar:3.0.6',
|
||||||
sha1 = 'e383b171c202df84af7e8510034714bc52831115',
|
sha1 = 'bb65acf0dd5e805ffc27f0f768e2fe5310d83a71',
|
||||||
maven_coords = 'io.atomix:atomix-primitive:3.0.5',
|
maven_coords = 'io.atomix:atomix-primitive:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix-raft',
|
name = 'atomix-raft',
|
||||||
out = 'atomix-raft-3.0.5.jar',
|
out = 'atomix-raft-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix-raft:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix-raft:jar:3.0.6',
|
||||||
sha1 = '0e7345cd475adb6e1f5af8ec48fd6faeb1261f84',
|
sha1 = 'f3497269b021f8794ba26296f6779977fd213f0e',
|
||||||
maven_coords = 'io.atomix:atomix-raft:3.0.5',
|
maven_coords = 'io.atomix:atomix-raft:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix-storage',
|
name = 'atomix-storage',
|
||||||
out = 'atomix-storage-3.0.5.jar',
|
out = 'atomix-storage-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix-storage:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix-storage:jar:3.0.6',
|
||||||
sha1 = '2967037f437ce85c191795baeb65535d76b027fe',
|
sha1 = '0cebbfd8932c7ed27d173d9f3487687317905f5d',
|
||||||
maven_coords = 'io.atomix:atomix-storage:3.0.5',
|
maven_coords = 'io.atomix:atomix-storage:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'atomix-utils',
|
name = 'atomix-utils',
|
||||||
out = 'atomix-utils-3.0.5.jar',
|
out = 'atomix-utils-3.0.6.jar',
|
||||||
url = 'mvn:io.atomix:atomix-utils:jar:3.0.5',
|
url = 'mvn:io.atomix:atomix-utils:jar:3.0.6',
|
||||||
sha1 = '63afb65deccb9631b8017d6aa779b337f920cef0',
|
sha1 = 'd99e63b9df25b59baea5c2fedbd6ad9dab6de59f',
|
||||||
maven_coords = 'io.atomix:atomix-utils:3.0.5',
|
maven_coords = 'io.atomix:atomix-utils:3.0.6',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'classgraph',
|
name = 'classgraph',
|
||||||
out = 'classgraph-4.0.6.jar',
|
out = 'classgraph-4.2.3.jar',
|
||||||
url = 'mvn:io.github.classgraph:classgraph:jar:4.0.6',
|
url = 'mvn:io.github.classgraph:classgraph:jar:4.2.3',
|
||||||
sha1 = '7fe1e7464ffd40c7333b8bbf53c4d73a7cbd7b4c',
|
sha1 = '5c9bfb002097a6cf6c7134821954e24326db3a7b',
|
||||||
maven_coords = 'io.github.classgraph:classgraph:4.0.6',
|
maven_coords = 'io.github.classgraph:classgraph:4.2.3',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1477,10 +1481,10 @@ remote_jar (
|
|||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'libthrift',
|
name = 'libthrift',
|
||||||
out = 'libthrift-0.9.3.jar',
|
out = 'libthrift-0.11.0.jar',
|
||||||
url = 'mvn:org.apache.thrift:libthrift:jar:0.9.3',
|
url = 'mvn:org.apache.thrift:libthrift:jar:0.11.0',
|
||||||
sha1 = '8625e8f9b6f49b881fa5fd143172c2833df1ce47',
|
sha1 = '4f4f1c1fbbae63258625dea71007fa41bee7edb3',
|
||||||
maven_coords = 'org.apache.thrift:libthrift:0.9.3',
|
maven_coords = 'org.apache.thrift:libthrift:0.11.0',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -148,7 +148,7 @@
|
|||||||
"atomix-raft": "mvn:io.atomix:atomix-raft:3.0.5",
|
"atomix-raft": "mvn:io.atomix:atomix-raft:3.0.5",
|
||||||
"atomix-storage": "mvn:io.atomix:atomix-storage:3.0.5",
|
"atomix-storage": "mvn:io.atomix:atomix-storage:3.0.5",
|
||||||
"atomix-utils": "mvn:io.atomix:atomix-utils:3.0.5",
|
"atomix-utils": "mvn:io.atomix:atomix-utils:3.0.5",
|
||||||
"classgraph": "mvn:io.github.classgraph:classgraph:4.0.6",
|
"classgraph": "mvn:io.github.classgraph:classgraph:4.2.3",
|
||||||
"commons-codec": "mvn:commons-codec:commons-codec:1.10",
|
"commons-codec": "mvn:commons-codec:commons-codec:1.10",
|
||||||
"commons-cli": "mvn:commons-cli:commons-cli:1.3",
|
"commons-cli": "mvn:commons-cli:commons-cli:1.3",
|
||||||
"commons-collections": "mvn:commons-collections:commons-collections:3.2.2",
|
"commons-collections": "mvn:commons-collections:commons-collections:3.2.2",
|
||||||
@ -285,7 +285,7 @@
|
|||||||
"apache-karaf": "http://repo1.maven.org/maven2/org/onosproject/apache-karaf-offline/4.2.1-base/apache-karaf-offline-4.2.1-base.tar.gz",
|
"apache-karaf": "http://repo1.maven.org/maven2/org/onosproject/apache-karaf-offline/4.2.1-base/apache-karaf-offline-4.2.1-base.tar.gz",
|
||||||
"bndlib": "mvn:biz.aQute.bnd:biz.aQute.bndlib:jar:4.0.0",
|
"bndlib": "mvn:biz.aQute.bnd:biz.aQute.bndlib:jar:4.0.0",
|
||||||
"bndexe": "mvn:biz.aQute.bnd:biz.aQute.bnd:4.0.0",
|
"bndexe": "mvn:biz.aQute.bnd:biz.aQute.bnd:4.0.0",
|
||||||
"libthrift": "mvn:org.apache.thrift:libthrift:0.9.3",
|
"libthrift": "mvn:org.apache.thrift:libthrift:0.11.0",
|
||||||
"qdox": "mvn:com.thoughtworks.qdox:qdox:2.0-M3",
|
"qdox": "mvn:com.thoughtworks.qdox:qdox:2.0-M3",
|
||||||
"snmp-core": "mvn:org.onosproject:snmp-core:1.3-20161021.1",
|
"snmp-core": "mvn:org.onosproject:snmp-core:1.3-20161021.1",
|
||||||
"mibs-net-snmp": "mvn:org.onosproject:mibbler-mibs-net-snmp:1.0-20151221.1",
|
"mibs-net-snmp": "mvn:org.onosproject:mibbler-mibs-net-snmp:1.0-20151221.1",
|
||||||
|
|||||||
@ -249,6 +249,7 @@ ONOS_APPS = [
|
|||||||
"//apps/layout:onos-apps-layout-oar",
|
"//apps/layout:onos-apps-layout-oar",
|
||||||
"//apps/imr:onos-apps-imr-oar",
|
"//apps/imr:onos-apps-imr-oar",
|
||||||
"//apps/nodemetrics:onos-apps-nodemetrics-oar",
|
"//apps/nodemetrics:onos-apps-nodemetrics-oar",
|
||||||
|
"//apps/inbandtelemetry:onos-apps-inbandtelemetry-oar",
|
||||||
# "//web/gui2:onos-web-gui2-oar",
|
# "//web/gui2:onos-web-gui2-oar",
|
||||||
"//apps/workflow:onos-apps-workflow-oar",
|
"//apps/workflow:onos-apps-workflow-oar",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -20,24 +20,21 @@ import com.google.common.collect.Sets;
|
|||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
import org.onlab.util.ImmutableByteSequence;
|
import org.onlab.util.ImmutableByteSequence;
|
||||||
import org.onlab.util.SharedExecutors;
|
|
||||||
import org.onosproject.core.ApplicationId;
|
import org.onosproject.core.ApplicationId;
|
||||||
import org.onosproject.core.CoreService;
|
import org.onosproject.core.CoreService;
|
||||||
import org.onosproject.inbandtelemetry.api.IntConfig;
|
import org.onosproject.inbandtelemetry.api.IntConfig;
|
||||||
import org.onosproject.inbandtelemetry.api.IntIntent;
|
import org.onosproject.inbandtelemetry.api.IntIntent;
|
||||||
import org.onosproject.inbandtelemetry.api.IntObjective;
|
import org.onosproject.inbandtelemetry.api.IntObjective;
|
||||||
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
||||||
import org.onosproject.net.ConnectPoint;
|
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.Port;
|
|
||||||
import org.onosproject.net.PortNumber;
|
import org.onosproject.net.PortNumber;
|
||||||
import org.onosproject.net.device.DeviceService;
|
|
||||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||||
import org.onosproject.net.flow.DefaultFlowRule;
|
import org.onosproject.net.flow.DefaultFlowRule;
|
||||||
import org.onosproject.net.flow.DefaultTrafficSelector;
|
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||||
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||||
import org.onosproject.net.flow.FlowRule;
|
import org.onosproject.net.flow.FlowRule;
|
||||||
import org.onosproject.net.flow.FlowRuleService;
|
import org.onosproject.net.flow.FlowRuleService;
|
||||||
|
import org.onosproject.net.flow.TableId;
|
||||||
import org.onosproject.net.flow.TrafficSelector;
|
import org.onosproject.net.flow.TrafficSelector;
|
||||||
import org.onosproject.net.flow.TrafficTreatment;
|
import org.onosproject.net.flow.TrafficTreatment;
|
||||||
import org.onosproject.net.flow.criteria.Criterion;
|
import org.onosproject.net.flow.criteria.Criterion;
|
||||||
@ -45,7 +42,6 @@ import org.onosproject.net.flow.criteria.IPCriterion;
|
|||||||
import org.onosproject.net.flow.criteria.PiCriterion;
|
import org.onosproject.net.flow.criteria.PiCriterion;
|
||||||
import org.onosproject.net.flow.criteria.TcpPortCriterion;
|
import org.onosproject.net.flow.criteria.TcpPortCriterion;
|
||||||
import org.onosproject.net.flow.criteria.UdpPortCriterion;
|
import org.onosproject.net.flow.criteria.UdpPortCriterion;
|
||||||
import org.onosproject.net.host.HostService;
|
|
||||||
import org.onosproject.net.pi.model.PiActionId;
|
import org.onosproject.net.pi.model.PiActionId;
|
||||||
import org.onosproject.net.pi.model.PiMatchFieldId;
|
import org.onosproject.net.pi.model.PiMatchFieldId;
|
||||||
import org.onosproject.net.pi.model.PiTableId;
|
import org.onosproject.net.pi.model.PiTableId;
|
||||||
@ -53,11 +49,9 @@ import org.onosproject.net.pi.runtime.PiAction;
|
|||||||
import org.onosproject.net.pi.runtime.PiActionParam;
|
import org.onosproject.net.pi.runtime.PiActionParam;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
@ -79,15 +73,18 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
Criterion.Type.TCP_SRC, Criterion.Type.TCP_DST,
|
Criterion.Type.TCP_SRC, Criterion.Type.TCP_DST,
|
||||||
Criterion.Type.IP_PROTO);
|
Criterion.Type.IP_PROTO);
|
||||||
|
|
||||||
|
private static final Set<PiTableId> TABLES_TO_CLEANUP = Sets.newHashSet(
|
||||||
|
IntConstants.TBL_INT_INSERT_ID,
|
||||||
|
IntConstants.TBL_INT_INST_0003_ID,
|
||||||
|
IntConstants.TBL_INT_INST_0407_ID,
|
||||||
|
IntConstants.TBL_SET_SOURCE_ID,
|
||||||
|
IntConstants.TBL_SET_SINK_ID,
|
||||||
|
IntConstants.TBL_INT_SOURCE_ID,
|
||||||
|
IntConstants.TBL_GENERATE_REPORT_ID);
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
private FlowRuleService flowRuleService;
|
private FlowRuleService flowRuleService;
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private DeviceService deviceService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private HostService hostService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
private CoreService coreService;
|
private CoreService coreService;
|
||||||
|
|
||||||
@ -134,23 +131,16 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public boolean init() {
|
||||||
deviceId = this.data().deviceId();
|
deviceId = this.data().deviceId();
|
||||||
flowRuleService = handler().get(FlowRuleService.class);
|
flowRuleService = handler().get(FlowRuleService.class);
|
||||||
deviceService = handler().get(DeviceService.class);
|
|
||||||
hostService = handler().get(HostService.class);
|
|
||||||
coreService = handler().get(CoreService.class);
|
coreService = handler().get(CoreService.class);
|
||||||
appId = coreService.getAppId(PIPELINE_APP_NAME);
|
appId = coreService.getAppId(PIPELINE_APP_NAME);
|
||||||
if (appId == null) {
|
if (appId == null) {
|
||||||
log.warn("Application ID is null. Cannot initialize INT-pipeline.");
|
log.warn("Application ID is null. Cannot initialize INT-pipeline.");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<PortNumber> hostPorts = deviceService.getPorts(deviceId).stream().filter(port ->
|
|
||||||
hostService.getConnectedHosts(new ConnectPoint(deviceId, port.number())).size() > 0
|
|
||||||
).map(Port::number).collect(Collectors.toSet());
|
|
||||||
List<FlowRule> flowRules = new ArrayList<>();
|
|
||||||
|
|
||||||
// process_int_transit.tb_int_insert
|
// process_int_transit.tb_int_insert
|
||||||
PiActionParam transitIdParam = new PiActionParam(
|
PiActionParam transitIdParam = new PiActionParam(
|
||||||
IntConstants.ACT_PRM_SWITCH_ID,
|
IntConstants.ACT_PRM_SWITCH_ID,
|
||||||
@ -173,58 +163,8 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
.forDevice(deviceId)
|
.forDevice(deviceId)
|
||||||
.forTable(IntConstants.TBL_INT_INSERT_ID)
|
.forTable(IntConstants.TBL_INT_INSERT_ID)
|
||||||
.build();
|
.build();
|
||||||
flowRules.add(transitFlowRule);
|
|
||||||
|
|
||||||
for (PortNumber portNumber: hostPorts) {
|
flowRuleService.applyFlowRules(transitFlowRule);
|
||||||
// process_set_source_sink.tb_set_source for each host-facing port
|
|
||||||
PiCriterion ingressCriterion = PiCriterion.builder()
|
|
||||||
.matchExact(BasicConstants.HDR_IN_PORT_ID, portNumber.toLong())
|
|
||||||
.build();
|
|
||||||
TrafficSelector srcSelector = DefaultTrafficSelector.builder()
|
|
||||||
.matchPi(ingressCriterion)
|
|
||||||
.build();
|
|
||||||
PiAction setSourceAct = PiAction.builder()
|
|
||||||
.withId(IntConstants.ACT_INT_SET_SOURCE_ID)
|
|
||||||
.build();
|
|
||||||
TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
|
|
||||||
.piTableAction(setSourceAct)
|
|
||||||
.build();
|
|
||||||
FlowRule srcFlowRule = DefaultFlowRule.builder()
|
|
||||||
.withSelector(srcSelector)
|
|
||||||
.withTreatment(srcTreatment)
|
|
||||||
.fromApp(appId)
|
|
||||||
.withPriority(DEFAULT_PRIORITY)
|
|
||||||
.makePermanent()
|
|
||||||
.forDevice(deviceId)
|
|
||||||
.forTable(IntConstants.TBL_SET_SOURCE_ID)
|
|
||||||
.build();
|
|
||||||
flowRules.add(srcFlowRule);
|
|
||||||
|
|
||||||
// process_set_source_sink.tb_set_sink
|
|
||||||
PiCriterion egressCriterion = PiCriterion.builder()
|
|
||||||
.matchExact(IntConstants.HDR_OUT_PORT_ID, portNumber.toLong())
|
|
||||||
.build();
|
|
||||||
TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
|
|
||||||
.matchPi(egressCriterion)
|
|
||||||
.build();
|
|
||||||
PiAction setSinkAct = PiAction.builder()
|
|
||||||
.withId(IntConstants.ACT_INT_SET_SINK_ID)
|
|
||||||
.build();
|
|
||||||
TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
|
|
||||||
.piTableAction(setSinkAct)
|
|
||||||
.build();
|
|
||||||
FlowRule sinkFlowRule = DefaultFlowRule.builder()
|
|
||||||
.withSelector(sinkSelector)
|
|
||||||
.withTreatment(sinkTreatment)
|
|
||||||
.fromApp(appId)
|
|
||||||
.withPriority(DEFAULT_PRIORITY)
|
|
||||||
.makePermanent()
|
|
||||||
.forDevice(deviceId)
|
|
||||||
.forTable(IntConstants.TBL_SET_SINK_ID)
|
|
||||||
.build();
|
|
||||||
flowRules.add(sinkFlowRule);
|
|
||||||
}
|
|
||||||
flowRules.forEach(flowRule -> flowRuleService.applyFlowRules(flowRule));
|
|
||||||
|
|
||||||
// Populate tb_int_inst_0003 table
|
// Populate tb_int_inst_0003 table
|
||||||
INST_0003_ACTION_MAP.forEach((matchValue, actionId) ->
|
INST_0003_ACTION_MAP.forEach((matchValue, actionId) ->
|
||||||
@ -240,32 +180,103 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
matchValue,
|
matchValue,
|
||||||
actionId,
|
actionId,
|
||||||
appId));
|
appId));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> addIntObjective(IntObjective obj) {
|
public boolean setSourcePort(PortNumber port) {
|
||||||
|
// process_set_source_sink.tb_set_source for each host-facing port
|
||||||
|
PiCriterion ingressCriterion = PiCriterion.builder()
|
||||||
|
.matchExact(BasicConstants.HDR_IN_PORT_ID, port.toLong())
|
||||||
|
.build();
|
||||||
|
TrafficSelector srcSelector = DefaultTrafficSelector.builder()
|
||||||
|
.matchPi(ingressCriterion)
|
||||||
|
.build();
|
||||||
|
PiAction setSourceAct = PiAction.builder()
|
||||||
|
.withId(IntConstants.ACT_INT_SET_SOURCE_ID)
|
||||||
|
.build();
|
||||||
|
TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
|
||||||
|
.piTableAction(setSourceAct)
|
||||||
|
.build();
|
||||||
|
FlowRule srcFlowRule = DefaultFlowRule.builder()
|
||||||
|
.withSelector(srcSelector)
|
||||||
|
.withTreatment(srcTreatment)
|
||||||
|
.fromApp(appId)
|
||||||
|
.withPriority(DEFAULT_PRIORITY)
|
||||||
|
.makePermanent()
|
||||||
|
.forDevice(deviceId)
|
||||||
|
.forTable(IntConstants.TBL_SET_SOURCE_ID)
|
||||||
|
.build();
|
||||||
|
flowRuleService.applyFlowRules(srcFlowRule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setSinkPort(PortNumber port) {
|
||||||
|
// process_set_source_sink.tb_set_sink
|
||||||
|
PiCriterion egressCriterion = PiCriterion.builder()
|
||||||
|
.matchExact(IntConstants.HDR_OUT_PORT_ID, port.toLong())
|
||||||
|
.build();
|
||||||
|
TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
|
||||||
|
.matchPi(egressCriterion)
|
||||||
|
.build();
|
||||||
|
PiAction setSinkAct = PiAction.builder()
|
||||||
|
.withId(IntConstants.ACT_INT_SET_SINK_ID)
|
||||||
|
.build();
|
||||||
|
TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
|
||||||
|
.piTableAction(setSinkAct)
|
||||||
|
.build();
|
||||||
|
FlowRule sinkFlowRule = DefaultFlowRule.builder()
|
||||||
|
.withSelector(sinkSelector)
|
||||||
|
.withTreatment(sinkTreatment)
|
||||||
|
.fromApp(appId)
|
||||||
|
.withPriority(DEFAULT_PRIORITY)
|
||||||
|
.makePermanent()
|
||||||
|
.forDevice(deviceId)
|
||||||
|
.forTable(IntConstants.TBL_SET_SINK_ID)
|
||||||
|
.build();
|
||||||
|
flowRuleService.applyFlowRules(sinkFlowRule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addIntObjective(IntObjective obj) {
|
||||||
// TODO: support different types of watchlist other than flow watchlist
|
// TODO: support different types of watchlist other than flow watchlist
|
||||||
|
|
||||||
return CompletableFuture.supplyAsync(
|
return processIntObjective(obj, true);
|
||||||
() -> processIntObjective(obj, true),
|
|
||||||
SharedExecutors.getPoolThreadExecutor()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> removeIntObjective(IntObjective obj) {
|
public boolean removeIntObjective(IntObjective obj) {
|
||||||
return CompletableFuture.supplyAsync(
|
return processIntObjective(obj, false);
|
||||||
() -> processIntObjective(obj, false),
|
|
||||||
SharedExecutors.getPoolThreadExecutor()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> setupIntConfig(IntConfig config) {
|
public boolean setupIntConfig(IntConfig config) {
|
||||||
return CompletableFuture.supplyAsync(
|
return setupIntReportInternal(config);
|
||||||
() -> setupIntReportInternal(config),
|
}
|
||||||
SharedExecutors.getPoolThreadExecutor()
|
|
||||||
);
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
|
StreamSupport.stream(flowRuleService.getFlowEntries(
|
||||||
|
data().deviceId()).spliterator(), false)
|
||||||
|
.filter(f -> f.table().type() == TableId.Type.PIPELINE_INDEPENDENT)
|
||||||
|
.filter(f -> TABLES_TO_CLEANUP.contains((PiTableId) f.table()))
|
||||||
|
.forEach(flowRuleService::removeFlowRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsFunctionality(IntFunctionality functionality) {
|
||||||
|
switch (functionality) {
|
||||||
|
case SOURCE:
|
||||||
|
case SINK:
|
||||||
|
case TRANSIT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
log.warn("Unknown functionality {}", functionality);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateInstTableEntry(PiTableId tableId, PiMatchFieldId matchFieldId,
|
private void populateInstTableEntry(PiTableId tableId, PiMatchFieldId matchFieldId,
|
||||||
@ -419,12 +430,12 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a subset of Criterion from given selector,
|
* Returns a subset of Criterion from given selector, which is unsupported
|
||||||
* which is unsupported by this INT pipeline.
|
* by this INT pipeline.
|
||||||
*
|
*
|
||||||
* @param selector a traffic selector
|
* @param selector a traffic selector
|
||||||
* @return a subset of Criterion from given selector, unsupported by this INT pipeline,
|
* @return a subset of Criterion from given selector, unsupported by this
|
||||||
* empty if all criteria are supported.
|
* INT pipeline, empty if all criteria are supported.
|
||||||
*/
|
*/
|
||||||
private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
|
private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
|
||||||
return selector.criteria().stream()
|
return selector.criteria().stream()
|
||||||
|
|||||||
@ -6,6 +6,7 @@ COMPILE_DEPS = [
|
|||||||
'//pipelines/basic:onos-pipelines-basic',
|
'//pipelines/basic:onos-pipelines-basic',
|
||||||
'//core/store/serializers:onos-core-serializers',
|
'//core/store/serializers:onos-core-serializers',
|
||||||
'//apps/inbandtelemetry/api:onos-apps-inbandtelemetry-api',
|
'//apps/inbandtelemetry/api:onos-apps-inbandtelemetry-api',
|
||||||
|
'//providers/general/device:onos-providers-general-device',
|
||||||
]
|
]
|
||||||
|
|
||||||
TEST_DEPS = [
|
TEST_DEPS = [
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
COMPILE_DEPS = CORE_DEPS + KRYO + [
|
COMPILE_DEPS = CORE_DEPS + KRYO + [
|
||||||
"//protocols/p4runtime/model:onos-protocols-p4runtime-model",
|
"//protocols/p4runtime/model:onos-protocols-p4runtime-model",
|
||||||
"//protocols/p4runtime/api:onos-protocols-p4runtime-api",
|
"//protocols/p4runtime/api:onos-protocols-p4runtime-api",
|
||||||
|
"//providers/general/device:onos-providers-general-device",
|
||||||
"//pipelines/basic:onos-pipelines-basic",
|
"//pipelines/basic:onos-pipelines-basic",
|
||||||
"//core/store/serializers:onos-core-serializers",
|
"//core/store/serializers:onos-core-serializers",
|
||||||
"//apps/inbandtelemetry/api:onos-apps-inbandtelemetry-api",
|
"//apps/inbandtelemetry/api:onos-apps-inbandtelemetry-api",
|
||||||
|
|||||||
@ -45,6 +45,8 @@ public final class FabricConstants {
|
|||||||
PiMatchFieldId.of("hdr.vlan_tag.is_valid");
|
PiMatchFieldId.of("hdr.vlan_tag.is_valid");
|
||||||
public static final PiMatchFieldId HDR_ICMP_ICMP_CODE =
|
public static final PiMatchFieldId HDR_ICMP_ICMP_CODE =
|
||||||
PiMatchFieldId.of("hdr.icmp.icmp_code");
|
PiMatchFieldId.of("hdr.icmp.icmp_code");
|
||||||
|
public static final PiMatchFieldId HDR_INT_HEADER_IS_VALID =
|
||||||
|
PiMatchFieldId.of("hdr.int_header.is_valid");
|
||||||
public static final PiMatchFieldId HDR_ETHERNET_SRC_ADDR =
|
public static final PiMatchFieldId HDR_ETHERNET_SRC_ADDR =
|
||||||
PiMatchFieldId.of("hdr.ethernet.src_addr");
|
PiMatchFieldId.of("hdr.ethernet.src_addr");
|
||||||
public static final PiMatchFieldId HDR_ICMP_ICMP_TYPE =
|
public static final PiMatchFieldId HDR_ICMP_ICMP_TYPE =
|
||||||
@ -82,36 +84,36 @@ public final class FabricConstants {
|
|||||||
PiTableId.of("FabricIngress.forwarding.acl");
|
PiTableId.of("FabricIngress.forwarding.acl");
|
||||||
public static final PiTableId FABRIC_INGRESS_NEXT_HASHED =
|
public static final PiTableId FABRIC_INGRESS_NEXT_HASHED =
|
||||||
PiTableId.of("FabricIngress.next.hashed");
|
PiTableId.of("FabricIngress.next.hashed");
|
||||||
|
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_TB_INT_SOURCE =
|
||||||
|
PiTableId.of("FabricEgress.process_int_main.process_int_source.tb_int_source");
|
||||||
public static final PiTableId FABRIC_INGRESS_FORWARDING_MPLS =
|
public static final PiTableId FABRIC_INGRESS_FORWARDING_MPLS =
|
||||||
PiTableId.of("FabricIngress.forwarding.mpls");
|
PiTableId.of("FabricIngress.forwarding.mpls");
|
||||||
public static final PiTableId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SINK =
|
public static final PiTableId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SINK =
|
||||||
PiTableId.of("FabricIngress.process_set_source_sink.tb_set_sink");
|
PiTableId.of("FabricIngress.process_set_source_sink.tb_set_sink");
|
||||||
public static final PiTableId FABRIC_INGRESS_FORWARDING_ROUTING_V4 =
|
public static final PiTableId FABRIC_INGRESS_FORWARDING_ROUTING_V4 =
|
||||||
PiTableId.of("FabricIngress.forwarding.routing_v4");
|
PiTableId.of("FabricIngress.forwarding.routing_v4");
|
||||||
|
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INST_0407 =
|
||||||
|
PiTableId.of("FabricEgress.process_int_main.process_int_transit.tb_int_inst_0407");
|
||||||
|
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INSERT =
|
||||||
|
PiTableId.of("FabricEgress.process_int_main.process_int_transit.tb_int_insert");
|
||||||
public static final PiTableId FABRIC_INGRESS_NEXT_SIMPLE =
|
public static final PiTableId FABRIC_INGRESS_NEXT_SIMPLE =
|
||||||
PiTableId.of("FabricIngress.next.simple");
|
PiTableId.of("FabricIngress.next.simple");
|
||||||
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_SOURCE_TB_INT_SOURCE =
|
|
||||||
PiTableId.of("FabricEgress.process_int_source.tb_int_source");
|
|
||||||
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_TRANSIT_TB_INT_INST_0003 =
|
|
||||||
PiTableId.of("FabricEgress.process_int_transit.tb_int_inst_0003");
|
|
||||||
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_TRANSIT_TB_INT_INSERT =
|
|
||||||
PiTableId.of("FabricEgress.process_int_transit.tb_int_insert");
|
|
||||||
public static final PiTableId FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER =
|
public static final PiTableId FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER =
|
||||||
PiTableId.of("FabricIngress.filtering.fwd_classifier");
|
PiTableId.of("FabricIngress.filtering.fwd_classifier");
|
||||||
public static final PiTableId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SOURCE =
|
public static final PiTableId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SOURCE =
|
||||||
PiTableId.of("FabricIngress.process_set_source_sink.tb_set_source");
|
PiTableId.of("FabricIngress.process_set_source_sink.tb_set_source");
|
||||||
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_REPORT_TB_GENERATE_REPORT =
|
|
||||||
PiTableId.of("FabricEgress.process_int_report.tb_generate_report");
|
|
||||||
public static final PiTableId FABRIC_INGRESS_FORWARDING_BRIDGING =
|
public static final PiTableId FABRIC_INGRESS_FORWARDING_BRIDGING =
|
||||||
PiTableId.of("FabricIngress.forwarding.bridging");
|
PiTableId.of("FabricIngress.forwarding.bridging");
|
||||||
public static final PiTableId FABRIC_INGRESS_SPGW_INGRESS_S1U_FILTER_TABLE =
|
public static final PiTableId FABRIC_INGRESS_SPGW_INGRESS_S1U_FILTER_TABLE =
|
||||||
PiTableId.of("FabricIngress.spgw_ingress.s1u_filter_table");
|
PiTableId.of("FabricIngress.spgw_ingress.s1u_filter_table");
|
||||||
|
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INST_0003 =
|
||||||
|
PiTableId.of("FabricEgress.process_int_main.process_int_transit.tb_int_inst_0003");
|
||||||
public static final PiTableId FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN =
|
public static final PiTableId FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN =
|
||||||
PiTableId.of("FabricIngress.filtering.ingress_port_vlan");
|
PiTableId.of("FabricIngress.filtering.ingress_port_vlan");
|
||||||
|
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_TB_GENERATE_REPORT =
|
||||||
|
PiTableId.of("FabricEgress.process_int_main.process_int_report.tb_generate_report");
|
||||||
public static final PiTableId FABRIC_INGRESS_SPGW_INGRESS_DL_SESS_LOOKUP =
|
public static final PiTableId FABRIC_INGRESS_SPGW_INGRESS_DL_SESS_LOOKUP =
|
||||||
PiTableId.of("FabricIngress.spgw_ingress.dl_sess_lookup");
|
PiTableId.of("FabricIngress.spgw_ingress.dl_sess_lookup");
|
||||||
public static final PiTableId FABRIC_EGRESS_PROCESS_INT_TRANSIT_TB_INT_INST_0407 =
|
|
||||||
PiTableId.of("FabricEgress.process_int_transit.tb_int_inst_0407");
|
|
||||||
public static final PiTableId FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN =
|
public static final PiTableId FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN =
|
||||||
PiTableId.of("FabricEgress.egress_next.egress_vlan");
|
PiTableId.of("FabricEgress.egress_next.egress_vlan");
|
||||||
public static final PiTableId FABRIC_INGRESS_NEXT_MULTICAST =
|
public static final PiTableId FABRIC_INGRESS_NEXT_MULTICAST =
|
||||||
@ -140,22 +142,16 @@ public final class FabricConstants {
|
|||||||
PiCounterId.of("FabricIngress.forwarding.routing_v4_counter");
|
PiCounterId.of("FabricIngress.forwarding.routing_v4_counter");
|
||||||
public static final PiCounterId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_COUNTER_SET_SOURCE =
|
public static final PiCounterId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_COUNTER_SET_SOURCE =
|
||||||
PiCounterId.of("FabricIngress.process_set_source_sink.counter_set_source");
|
PiCounterId.of("FabricIngress.process_set_source_sink.counter_set_source");
|
||||||
public static final PiCounterId FABRIC_EGRESS_PROCESS_INT_TRANSIT_COUNTER_INT_INST_0407 =
|
public static final PiCounterId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_COUNTER_INT_SOURCE =
|
||||||
PiCounterId.of("FabricEgress.process_int_transit.counter_int_inst_0407");
|
PiCounterId.of("FabricEgress.process_int_main.process_int_source.counter_int_source");
|
||||||
public static final PiCounterId FABRIC_INGRESS_SPGW_INGRESS_UE_COUNTER =
|
public static final PiCounterId FABRIC_INGRESS_SPGW_INGRESS_UE_COUNTER =
|
||||||
PiCounterId.of("FabricIngress.spgw_ingress.ue_counter");
|
PiCounterId.of("FabricIngress.spgw_ingress.ue_counter");
|
||||||
public static final PiCounterId FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN_COUNTER =
|
|
||||||
PiCounterId.of("FabricEgress.egress_next.egress_vlan_counter");
|
|
||||||
public static final PiCounterId FABRIC_INGRESS_NEXT_SIMPLE_COUNTER =
|
public static final PiCounterId FABRIC_INGRESS_NEXT_SIMPLE_COUNTER =
|
||||||
PiCounterId.of("FabricIngress.next.simple_counter");
|
PiCounterId.of("FabricIngress.next.simple_counter");
|
||||||
public static final PiCounterId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_COUNTER_SET_SINK =
|
public static final PiCounterId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_COUNTER_SET_SINK =
|
||||||
PiCounterId.of("FabricIngress.process_set_source_sink.counter_set_sink");
|
PiCounterId.of("FabricIngress.process_set_source_sink.counter_set_sink");
|
||||||
public static final PiCounterId FABRIC_EGRESS_PROCESS_INT_TRANSIT_COUNTER_INT_INSERT =
|
public static final PiCounterId FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN_COUNTER =
|
||||||
PiCounterId.of("FabricEgress.process_int_transit.counter_int_insert");
|
PiCounterId.of("FabricEgress.egress_next.egress_vlan_counter");
|
||||||
public static final PiCounterId FABRIC_EGRESS_PROCESS_INT_SOURCE_COUNTER_INT_SOURCE =
|
|
||||||
PiCounterId.of("FabricEgress.process_int_source.counter_int_source");
|
|
||||||
public static final PiCounterId FABRIC_EGRESS_PROCESS_INT_TRANSIT_COUNTER_INT_INST_0003 =
|
|
||||||
PiCounterId.of("FabricEgress.process_int_transit.counter_int_inst_0003");
|
|
||||||
public static final PiCounterId FABRIC_INGRESS_FORWARDING_ROUTING_V6_COUNTER =
|
public static final PiCounterId FABRIC_INGRESS_FORWARDING_ROUTING_V6_COUNTER =
|
||||||
PiCounterId.of("FabricIngress.forwarding.routing_v6_counter");
|
PiCounterId.of("FabricIngress.forwarding.routing_v6_counter");
|
||||||
public static final PiCounterId FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN_COUNTER =
|
public static final PiCounterId FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN_COUNTER =
|
||||||
@ -165,145 +161,129 @@ public final class FabricConstants {
|
|||||||
public static final PiCounterId FABRIC_INGRESS_NEXT_HASHED_COUNTER =
|
public static final PiCounterId FABRIC_INGRESS_NEXT_HASHED_COUNTER =
|
||||||
PiCounterId.of("FabricIngress.next.hashed_counter");
|
PiCounterId.of("FabricIngress.next.hashed_counter");
|
||||||
// Action IDs
|
// Action IDs
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I14 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i14");
|
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_PUNT_TO_CPU =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_PUNT_TO_CPU =
|
||||||
PiActionId.of("FabricIngress.forwarding.punt_to_cpu");
|
PiActionId.of("FabricIngress.forwarding.punt_to_cpu");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I12 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I5 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i12");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i5");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I13 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i13");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I10 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i10");
|
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_MPLS_ROUTING_V6_SIMPLE =
|
public static final PiActionId FABRIC_INGRESS_NEXT_MPLS_ROUTING_V6_SIMPLE =
|
||||||
PiActionId.of("FabricIngress.next.mpls_routing_v6_simple");
|
PiActionId.of("FabricIngress.next.mpls_routing_v6_simple");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I12 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i12");
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_NOP_ROUTING_V4 =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_NOP_ROUTING_V4 =
|
||||||
PiActionId.of("FabricIngress.forwarding.nop_routing_v4");
|
PiActionId.of("FabricIngress.forwarding.nop_routing_v4");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_UPDATE_TOTAL_HOP_CNT =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I10 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_update_total_hop_cnt");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i10");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I11 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i11");
|
||||||
public static final PiActionId FABRIC_INGRESS_FILTERING_NOP_INGRESS_PORT_VLAN =
|
public static final PiActionId FABRIC_INGRESS_FILTERING_NOP_INGRESS_PORT_VLAN =
|
||||||
PiActionId.of("FabricIngress.filtering.nop_ingress_port_vlan");
|
PiActionId.of("FabricIngress.filtering.nop_ingress_port_vlan");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I14 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I14 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i14");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i14");
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING =
|
||||||
PiActionId.of("FabricIngress.forwarding.set_next_id_bridging");
|
PiActionId.of("FabricIngress.forwarding.set_next_id_bridging");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I15 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_INT_SOURCE_DSCP =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i15");
|
PiActionId.of("FabricEgress.process_int_main.process_int_source.int_source_dscp");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I2 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I0 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i2");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i0");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I5 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INIT_METADATA =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i5");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.init_metadata");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I4 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I14 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i4");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i14");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_SINK_INT_SINK =
|
public static final PiActionId FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN =
|
||||||
PiActionId.of("FabricEgress.process_int_sink.int_sink");
|
PiActionId.of("FabricEgress.egress_next.pop_vlan");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I3 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I4 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i3");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i4");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I13 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I2 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i13");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i2");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I7 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i7");
|
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_SET_VLAN =
|
public static final PiActionId FABRIC_INGRESS_NEXT_SET_VLAN =
|
||||||
PiActionId.of("FabricIngress.next.set_vlan");
|
PiActionId.of("FabricIngress.next.set_vlan");
|
||||||
public static final PiActionId FABRIC_EGRESS_PKT_IO_EGRESS_POP_VLAN =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I4 =
|
||||||
PiActionId.of("FabricEgress.pkt_io_egress.pop_vlan");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i4");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I8 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i8");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I9 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i9");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_SPGW_EGRESS_GTPU_ENCAP =
|
public static final PiActionId FABRIC_EGRESS_SPGW_EGRESS_GTPU_ENCAP =
|
||||||
PiActionId.of("FabricEgress.spgw_egress.gtpu_encap");
|
PiActionId.of("FabricEgress.spgw_egress.gtpu_encap");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I4 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I12 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i4");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i12");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I5 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I13 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i5");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i13");
|
||||||
public static final PiActionId FABRIC_INGRESS_FILTERING_SET_VLAN =
|
public static final PiActionId FABRIC_INGRESS_FILTERING_SET_VLAN =
|
||||||
PiActionId.of("FabricIngress.filtering.set_vlan");
|
PiActionId.of("FabricIngress.filtering.set_vlan");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I11 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I11 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i11");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i11");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I0 =
|
public static final PiActionId FABRIC_EGRESS_PKT_IO_EGRESS_POP_VLAN =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i0");
|
PiActionId.of("FabricEgress.pkt_io_egress.pop_vlan");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I1 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i1");
|
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_L3_ROUTING_SIMPLE =
|
public static final PiActionId FABRIC_INGRESS_NEXT_L3_ROUTING_SIMPLE =
|
||||||
PiActionId.of("FabricIngress.next.l3_routing_simple");
|
PiActionId.of("FabricIngress.next.l3_routing_simple");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I3 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I15 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i3");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i15");
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_SET_MCAST_GROUP =
|
public static final PiActionId FABRIC_INGRESS_NEXT_SET_MCAST_GROUP =
|
||||||
PiActionId.of("FabricIngress.next.set_mcast_group");
|
PiActionId.of("FabricIngress.next.set_mcast_group");
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V4 =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V4 =
|
||||||
PiActionId.of("FabricIngress.forwarding.set_next_id_routing_v4");
|
PiActionId.of("FabricIngress.forwarding.set_next_id_routing_v4");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_OUTER_ENCAP_INT_UPDATE_UDP =
|
|
||||||
PiActionId.of("FabricEgress.process_int_outer_encap.int_update_udp");
|
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V6 =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V6 =
|
||||||
PiActionId.of("FabricIngress.forwarding.set_next_id_routing_v6");
|
PiActionId.of("FabricIngress.forwarding.set_next_id_routing_v6");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I13 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i13");
|
||||||
public static final PiActionId FABRIC_INGRESS_SPGW_INGRESS_SET_DL_SESS_INFO =
|
public static final PiActionId FABRIC_INGRESS_SPGW_INGRESS_SET_DL_SESS_INFO =
|
||||||
PiActionId.of("FabricIngress.spgw_ingress.set_dl_sess_info");
|
PiActionId.of("FabricIngress.spgw_ingress.set_dl_sess_info");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I7 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i7");
|
||||||
public static final PiActionId FABRIC_INGRESS_FILTERING_PUSH_INTERNAL_VLAN =
|
public static final PiActionId FABRIC_INGRESS_FILTERING_PUSH_INTERNAL_VLAN =
|
||||||
PiActionId.of("FabricIngress.filtering.push_internal_vlan");
|
PiActionId.of("FabricIngress.filtering.push_internal_vlan");
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_CLONE_TO_CPU =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_CLONE_TO_CPU =
|
||||||
PiActionId.of("FabricIngress.forwarding.clone_to_cpu");
|
PiActionId.of("FabricIngress.forwarding.clone_to_cpu");
|
||||||
public static final PiActionId FABRIC_INGRESS_SPGW_INGRESS_GTPU_DECAP =
|
public static final PiActionId FABRIC_INGRESS_SPGW_INGRESS_GTPU_DECAP =
|
||||||
PiActionId.of("FabricIngress.spgw_ingress.gtpu_decap");
|
PiActionId.of("FabricIngress.spgw_ingress.gtpu_decap");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I15 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i15");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I12 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i12");
|
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT =
|
||||||
PiActionId.of("FabricIngress.forwarding.pop_mpls_and_next");
|
PiActionId.of("FabricIngress.forwarding.pop_mpls_and_next");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I10 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i10");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I11 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i11");
|
|
||||||
public static final PiActionId DROP_NOW = PiActionId.of("drop_now");
|
public static final PiActionId DROP_NOW = PiActionId.of("drop_now");
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_L3_ROUTING_HASHED =
|
public static final PiActionId FABRIC_INGRESS_NEXT_L3_ROUTING_HASHED =
|
||||||
PiActionId.of("FabricIngress.next.l3_routing_hashed");
|
PiActionId.of("FabricIngress.next.l3_routing_hashed");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_SOURCE_INT_SOURCE_DSCP =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I10 =
|
||||||
PiActionId.of("FabricEgress.process_int_source.int_source_dscp");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i10");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_REPORT_DO_REPORT_ENCAPSULATION =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I8 =
|
||||||
PiActionId.of("FabricEgress.process_int_report.do_report_encapsulation");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i8");
|
||||||
public static final PiActionId FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I0 =
|
||||||
PiActionId.of("FabricEgress.egress_next.pop_vlan");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i0");
|
||||||
public static final PiActionId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SINK =
|
public static final PiActionId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SINK =
|
||||||
PiActionId.of("FabricIngress.process_set_source_sink.int_set_sink");
|
PiActionId.of("FabricIngress.process_set_source_sink.int_set_sink");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_OUTER_ENCAP_INT_UPDATE_SHIM =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SINK_INT_SINK =
|
||||||
PiActionId.of("FabricEgress.process_int_outer_encap.int_update_shim");
|
PiActionId.of("FabricEgress.process_int_main.process_int_sink.int_sink");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I1 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i1");
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_MPLS_ROUTING_V4_HASHED =
|
public static final PiActionId FABRIC_INGRESS_NEXT_MPLS_ROUTING_V4_HASHED =
|
||||||
PiActionId.of("FabricIngress.next.mpls_routing_v4_hashed");
|
PiActionId.of("FabricIngress.next.mpls_routing_v4_hashed");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I1 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i1");
|
||||||
public static final PiActionId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SOURCE =
|
public static final PiActionId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SOURCE =
|
||||||
PiActionId.of("FabricIngress.process_set_source_sink.int_set_source");
|
PiActionId.of("FabricIngress.process_set_source_sink.int_set_source");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I3 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i3");
|
||||||
public static final PiActionId NOP = PiActionId.of("nop");
|
public static final PiActionId NOP = PiActionId.of("nop");
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_DROP =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_DROP =
|
||||||
PiActionId.of("FabricIngress.forwarding.drop");
|
PiActionId.of("FabricIngress.forwarding.drop");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I6 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i6");
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE =
|
public static final PiActionId FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE =
|
||||||
PiActionId.of("FabricIngress.next.output_simple");
|
PiActionId.of("FabricIngress.next.output_simple");
|
||||||
public static final PiActionId FABRIC_INGRESS_FILTERING_DROP =
|
public static final PiActionId FABRIC_INGRESS_FILTERING_DROP =
|
||||||
PiActionId.of("FabricIngress.filtering.drop");
|
PiActionId.of("FabricIngress.filtering.drop");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_OUTER_ENCAP_INT_UPDATE_IPV4 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SINK_RESTORE_HEADER =
|
||||||
PiActionId.of("FabricEgress.process_int_outer_encap.int_update_ipv4");
|
PiActionId.of("FabricEgress.process_int_main.process_int_sink.restore_header");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I8 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I9 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i8");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i9");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I9 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i9");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_SINK_RESTORE_HEADER =
|
|
||||||
PiActionId.of("FabricEgress.process_int_sink.restore_header");
|
|
||||||
public static final PiActionId FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE =
|
public static final PiActionId FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE =
|
||||||
PiActionId.of("FabricIngress.filtering.set_forwarding_type");
|
PiActionId.of("FabricIngress.filtering.set_forwarding_type");
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_SET_VLAN_OUTPUT =
|
public static final PiActionId FABRIC_INGRESS_NEXT_SET_VLAN_OUTPUT =
|
||||||
PiActionId.of("FabricIngress.next.set_vlan_output");
|
PiActionId.of("FabricIngress.next.set_vlan_output");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I6 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_DO_REPORT_ENCAPSULATION =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i6");
|
PiActionId.of("FabricEgress.process_int_main.process_int_report.do_report_encapsulation");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I7 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i7");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I0 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i0");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I1 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i1");
|
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I2 =
|
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0003_i2");
|
|
||||||
public static final PiActionId NO_ACTION = PiActionId.of("NoAction");
|
public static final PiActionId NO_ACTION = PiActionId.of("NoAction");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_TRANSIT =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I8 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_transit");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i8");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I9 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i9");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I15 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i15");
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_MPLS_ROUTING_V4_SIMPLE =
|
public static final PiActionId FABRIC_INGRESS_NEXT_MPLS_ROUTING_V4_SIMPLE =
|
||||||
PiActionId.of("FabricIngress.next.mpls_routing_v4_simple");
|
PiActionId.of("FabricIngress.next.mpls_routing_v4_simple");
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_NOP_ACL =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_NOP_ACL =
|
||||||
@ -312,10 +292,18 @@ public final class FabricConstants {
|
|||||||
PiActionId.of("FabricIngress.next.mpls_routing_v6_hashed");
|
PiActionId.of("FabricIngress.next.mpls_routing_v6_hashed");
|
||||||
public static final PiActionId FABRIC_INGRESS_NEXT_L3_ROUTING_VLAN =
|
public static final PiActionId FABRIC_INGRESS_NEXT_L3_ROUTING_VLAN =
|
||||||
PiActionId.of("FabricIngress.next.l3_routing_vlan");
|
PiActionId.of("FabricIngress.next.l3_routing_vlan");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I2 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i2");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I3 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i3");
|
||||||
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ACL =
|
public static final PiActionId FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ACL =
|
||||||
PiActionId.of("FabricIngress.forwarding.set_next_id_acl");
|
PiActionId.of("FabricIngress.forwarding.set_next_id_acl");
|
||||||
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I6 =
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I5 =
|
||||||
PiActionId.of("FabricEgress.process_int_transit.int_set_header_0407_i6");
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i5");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I6 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i6");
|
||||||
|
public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I7 =
|
||||||
|
PiActionId.of("FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i7");
|
||||||
// Action Param IDs
|
// Action Param IDs
|
||||||
public static final PiActionParamId DMAC = PiActionParamId.of("dmac");
|
public static final PiActionParamId DMAC = PiActionParamId.of("dmac");
|
||||||
public static final PiActionParamId MON_IP = PiActionParamId.of("mon_ip");
|
public static final PiActionParamId MON_IP = PiActionParamId.of("mon_ip");
|
||||||
|
|||||||
@ -36,12 +36,20 @@ import org.onosproject.net.packet.DefaultInboundPacket;
|
|||||||
import org.onosproject.net.packet.InboundPacket;
|
import org.onosproject.net.packet.InboundPacket;
|
||||||
import org.onosproject.net.packet.OutboundPacket;
|
import org.onosproject.net.packet.OutboundPacket;
|
||||||
import org.onosproject.net.pi.model.PiMatchFieldId;
|
import org.onosproject.net.pi.model.PiMatchFieldId;
|
||||||
|
import org.onosproject.net.pi.model.PiPipeconf;
|
||||||
|
import org.onosproject.net.pi.model.PiPipeconfId;
|
||||||
import org.onosproject.net.pi.model.PiPipelineInterpreter;
|
import org.onosproject.net.pi.model.PiPipelineInterpreter;
|
||||||
import org.onosproject.net.pi.model.PiTableId;
|
import org.onosproject.net.pi.model.PiTableId;
|
||||||
import org.onosproject.net.pi.runtime.PiAction;
|
import org.onosproject.net.pi.runtime.PiAction;
|
||||||
import org.onosproject.net.pi.runtime.PiControlMetadata;
|
import org.onosproject.net.pi.runtime.PiControlMetadata;
|
||||||
import org.onosproject.net.pi.runtime.PiPacketOperation;
|
import org.onosproject.net.pi.runtime.PiPacketOperation;
|
||||||
|
import org.onosproject.net.pi.service.PiPipeconfService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -51,9 +59,12 @@ import java.util.Set;
|
|||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
import static org.onlab.util.ImmutableByteSequence.copyFrom;
|
import static org.onlab.util.ImmutableByteSequence.copyFrom;
|
||||||
|
import static org.onosproject.net.PortNumber.CONTROLLER;
|
||||||
import static org.onosproject.net.PortNumber.FLOOD;
|
import static org.onosproject.net.PortNumber.FLOOD;
|
||||||
import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
|
import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
|
||||||
import static org.onosproject.net.pi.model.PiPacketOperationType.PACKET_OUT;
|
import static org.onosproject.net.pi.model.PiPacketOperationType.PACKET_OUT;
|
||||||
|
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.CPU_PORT_TXT;
|
||||||
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interpreter for fabric pipeline.
|
* Interpreter for fabric pipeline.
|
||||||
@ -61,6 +72,8 @@ import static org.onosproject.net.pi.model.PiPacketOperationType.PACKET_OUT;
|
|||||||
public class FabricInterpreter extends AbstractHandlerBehaviour
|
public class FabricInterpreter extends AbstractHandlerBehaviour
|
||||||
implements PiPipelineInterpreter {
|
implements PiPipelineInterpreter {
|
||||||
|
|
||||||
|
private final Logger log = getLogger(getClass());
|
||||||
|
|
||||||
public static final int PORT_BITWIDTH = 9;
|
public static final int PORT_BITWIDTH = 9;
|
||||||
|
|
||||||
private static final ImmutableBiMap<Integer, PiTableId> TABLE_ID_MAP =
|
private static final ImmutableBiMap<Integer, PiTableId> TABLE_ID_MAP =
|
||||||
@ -134,6 +147,14 @@ public class FabricInterpreter extends AbstractHandlerBehaviour
|
|||||||
.put(FabricConstants.HDR_ICMP_ICMP_CODE, Criterion.Type.ICMPV6_CODE)
|
.put(FabricConstants.HDR_ICMP_ICMP_CODE, Criterion.Type.ICMPV6_CODE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
private static final PiAction NOACTION = PiAction.builder().withId(
|
||||||
|
FabricConstants.NO_ACTION).build();
|
||||||
|
|
||||||
|
private static final ImmutableMap<PiTableId, PiAction> DEFAULT_ACTIONS =
|
||||||
|
ImmutableMap.<PiTableId, PiAction>builder()
|
||||||
|
.put(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4, NOACTION)
|
||||||
|
.build();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PiMatchFieldId> mapCriterionType(Criterion.Type type) {
|
public Optional<PiMatchFieldId> mapCriterionType(Criterion.Type type) {
|
||||||
return Optional.ofNullable(CRITERION_MAP.get(type));
|
return Optional.ofNullable(CRITERION_MAP.get(type));
|
||||||
@ -262,4 +283,60 @@ public class FabricInterpreter extends AbstractHandlerBehaviour
|
|||||||
FabricConstants.INGRESS_PORT, deviceId, packetIn));
|
FabricConstants.INGRESS_PORT, deviceId, packetIn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<PiAction> getOriginalDefaultAction(PiTableId tableId) {
|
||||||
|
return Optional.ofNullable(DEFAULT_ACTIONS.get(tableId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> mapLogicalPortNumber(PortNumber port) {
|
||||||
|
if (!port.equals(CONTROLLER)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
// This is probably brittle, but needed to dynamically get the CPU port
|
||||||
|
// for different platforms.
|
||||||
|
final DeviceId deviceId = data().deviceId();
|
||||||
|
final PiPipeconfService pipeconfService = handler().get(
|
||||||
|
PiPipeconfService.class);
|
||||||
|
final PiPipeconfId pipeconfId = pipeconfService
|
||||||
|
.ofDevice(deviceId).orElse(null);
|
||||||
|
if (pipeconfId == null ||
|
||||||
|
!pipeconfService.getPipeconf(pipeconfId).isPresent()) {
|
||||||
|
log.error("Unable to get pipeconf of {} - BUG?");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
final PiPipeconf pipeconf = pipeconfService.getPipeconf(pipeconfId).get();
|
||||||
|
if (!pipeconf.extension(CPU_PORT_TXT).isPresent()) {
|
||||||
|
log.error("Missing {} extension from pipeconf {}",
|
||||||
|
CPU_PORT_TXT, pipeconfId);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(
|
||||||
|
readCpuPort(pipeconf.extension(CPU_PORT_TXT).get(),
|
||||||
|
pipeconfId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer readCpuPort(InputStream stream, PiPipeconfId pipeconfId) {
|
||||||
|
try {
|
||||||
|
final BufferedReader buff = new BufferedReader(
|
||||||
|
new InputStreamReader(stream));
|
||||||
|
final String str = buff.readLine();
|
||||||
|
buff.close();
|
||||||
|
if (str == null) {
|
||||||
|
log.error("Empty CPU port file for {}", pipeconfId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(str);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.error("Invalid CPU port for {}: {}", pipeconfId, str);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Unable to read CPU port file of {}: {}",
|
||||||
|
pipeconfId, e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,29 +15,26 @@
|
|||||||
*/
|
*/
|
||||||
package org.onosproject.pipelines.fabric;
|
package org.onosproject.pipelines.fabric;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableBiMap;
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
import org.onlab.util.ImmutableByteSequence;
|
|
||||||
import org.onlab.util.SharedExecutors;
|
|
||||||
import org.onosproject.core.ApplicationId;
|
import org.onosproject.core.ApplicationId;
|
||||||
import org.onosproject.core.CoreService;
|
import org.onosproject.core.CoreService;
|
||||||
import org.onosproject.inbandtelemetry.api.IntConfig;
|
import org.onosproject.inbandtelemetry.api.IntConfig;
|
||||||
import org.onosproject.inbandtelemetry.api.IntIntent;
|
import org.onosproject.inbandtelemetry.api.IntIntent;
|
||||||
import org.onosproject.inbandtelemetry.api.IntObjective;
|
import org.onosproject.inbandtelemetry.api.IntObjective;
|
||||||
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
||||||
import org.onosproject.net.ConnectPoint;
|
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.Port;
|
|
||||||
import org.onosproject.net.PortNumber;
|
import org.onosproject.net.PortNumber;
|
||||||
import org.onosproject.net.device.DeviceService;
|
import org.onosproject.net.config.NetworkConfigService;
|
||||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||||
import org.onosproject.net.flow.DefaultFlowRule;
|
import org.onosproject.net.flow.DefaultFlowRule;
|
||||||
import org.onosproject.net.flow.DefaultTrafficSelector;
|
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||||
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||||
import org.onosproject.net.flow.FlowRule;
|
import org.onosproject.net.flow.FlowRule;
|
||||||
import org.onosproject.net.flow.FlowRuleService;
|
import org.onosproject.net.flow.FlowRuleService;
|
||||||
|
import org.onosproject.net.flow.TableId;
|
||||||
import org.onosproject.net.flow.TrafficSelector;
|
import org.onosproject.net.flow.TrafficSelector;
|
||||||
import org.onosproject.net.flow.TrafficTreatment;
|
import org.onosproject.net.flow.TrafficTreatment;
|
||||||
import org.onosproject.net.flow.criteria.Criterion;
|
import org.onosproject.net.flow.criteria.Criterion;
|
||||||
@ -45,32 +42,32 @@ import org.onosproject.net.flow.criteria.IPCriterion;
|
|||||||
import org.onosproject.net.flow.criteria.PiCriterion;
|
import org.onosproject.net.flow.criteria.PiCriterion;
|
||||||
import org.onosproject.net.flow.criteria.TcpPortCriterion;
|
import org.onosproject.net.flow.criteria.TcpPortCriterion;
|
||||||
import org.onosproject.net.flow.criteria.UdpPortCriterion;
|
import org.onosproject.net.flow.criteria.UdpPortCriterion;
|
||||||
import org.onosproject.net.host.HostService;
|
|
||||||
import org.onosproject.net.pi.model.PiActionId;
|
|
||||||
import org.onosproject.net.pi.model.PiMatchFieldId;
|
|
||||||
import org.onosproject.net.pi.model.PiTableId;
|
import org.onosproject.net.pi.model.PiTableId;
|
||||||
import org.onosproject.net.pi.runtime.PiAction;
|
import org.onosproject.net.pi.runtime.PiAction;
|
||||||
import org.onosproject.net.pi.runtime.PiActionParam;
|
import org.onosproject.net.pi.runtime.PiActionParam;
|
||||||
|
import org.onosproject.provider.general.device.api.GeneralProviderDeviceConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import static org.onlab.util.ImmutableByteSequence.copyFrom;
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of INT programmable behavior for fabric.p4. Currently supports
|
||||||
|
* only SOURCE and TRANSIT functionalities.
|
||||||
|
*/
|
||||||
public class IntProgrammableImpl extends AbstractHandlerBehaviour implements IntProgrammable {
|
public class IntProgrammableImpl extends AbstractHandlerBehaviour implements IntProgrammable {
|
||||||
|
|
||||||
|
private final Logger log = getLogger(getClass());
|
||||||
|
|
||||||
// TODO: change this value to the value of diameter of a network.
|
// TODO: change this value to the value of diameter of a network.
|
||||||
|
private static final int DEFAULT_PRIORITY = 10000;
|
||||||
private static final int MAXHOP = 64;
|
private static final int MAXHOP = 64;
|
||||||
private static final int PORTMASK = 0xffff;
|
private static final int PORTMASK = 0xffff;
|
||||||
private static final int IDLE_TIMEOUT = 100;
|
|
||||||
private static final int PKT_INSTANCE_TYPE_INGRESS_CLONE = 1;
|
private static final int PKT_INSTANCE_TYPE_INGRESS_CLONE = 1;
|
||||||
// Application name of the pipeline which adds this implementation to the pipeconf
|
|
||||||
private static final String PIPELINE_APP_NAME = "org.onosproject.pipelines.fabric";
|
|
||||||
private final Logger log = getLogger(getClass());
|
|
||||||
private ApplicationId appId;
|
|
||||||
|
|
||||||
private static final Set<Criterion.Type> SUPPORTED_CRITERION = Sets.newHashSet(
|
private static final Set<Criterion.Type> SUPPORTED_CRITERION = Sets.newHashSet(
|
||||||
Criterion.Type.IPV4_DST, Criterion.Type.IPV4_SRC,
|
Criterion.Type.IPV4_DST, Criterion.Type.IPV4_SRC,
|
||||||
@ -78,247 +75,225 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
Criterion.Type.TCP_SRC, Criterion.Type.TCP_DST,
|
Criterion.Type.TCP_SRC, Criterion.Type.TCP_DST,
|
||||||
Criterion.Type.IP_PROTO);
|
Criterion.Type.IP_PROTO);
|
||||||
|
|
||||||
|
private static final Set<PiTableId> TABLES_TO_CLEANUP = Sets.newHashSet(
|
||||||
|
FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INSERT,
|
||||||
|
FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SOURCE,
|
||||||
|
FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SINK,
|
||||||
|
FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_TB_INT_SOURCE,
|
||||||
|
FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_TB_GENERATE_REPORT
|
||||||
|
);
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
private FlowRuleService flowRuleService;
|
private FlowRuleService flowRuleService;
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private DeviceService deviceService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private HostService hostService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
|
||||||
private CoreService coreService;
|
private CoreService coreService;
|
||||||
|
private NetworkConfigService cfgService;
|
||||||
private DeviceId deviceId;
|
private DeviceId deviceId;
|
||||||
private static final int DEFAULT_PRIORITY = 10000;
|
private ApplicationId appId;
|
||||||
private static final ImmutableBiMap<Integer, PiActionId> INST_0003_ACTION_MAP =
|
|
||||||
ImmutableBiMap.<Integer, PiActionId>builder()
|
|
||||||
.put(0, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I0)
|
|
||||||
.put(1, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I1)
|
|
||||||
.put(2, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I2)
|
|
||||||
.put(3, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I3)
|
|
||||||
.put(4, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I4)
|
|
||||||
.put(5, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I5)
|
|
||||||
.put(6, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I6)
|
|
||||||
.put(7, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I7)
|
|
||||||
.put(8, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I8)
|
|
||||||
.put(9, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I9)
|
|
||||||
.put(10, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I10)
|
|
||||||
.put(11, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I11)
|
|
||||||
.put(12, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I12)
|
|
||||||
.put(13, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I13)
|
|
||||||
.put(14, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I14)
|
|
||||||
.put(15, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I15)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private static final ImmutableBiMap<Integer, PiActionId> INST_0407_ACTION_MAP =
|
private boolean setupBehaviour() {
|
||||||
ImmutableBiMap.<Integer, PiActionId>builder()
|
|
||||||
.put(0, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I0)
|
|
||||||
.put(1, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I1)
|
|
||||||
.put(2, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I2)
|
|
||||||
.put(3, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I3)
|
|
||||||
.put(4, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I4)
|
|
||||||
.put(5, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I5)
|
|
||||||
.put(6, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I6)
|
|
||||||
.put(7, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I7)
|
|
||||||
.put(8, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I8)
|
|
||||||
.put(9, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I9)
|
|
||||||
.put(10, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I10)
|
|
||||||
.put(11, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I11)
|
|
||||||
.put(12, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I12)
|
|
||||||
.put(13, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I13)
|
|
||||||
.put(14, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I14)
|
|
||||||
.put(15, FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I15)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() {
|
|
||||||
deviceId = this.data().deviceId();
|
deviceId = this.data().deviceId();
|
||||||
flowRuleService = handler().get(FlowRuleService.class);
|
flowRuleService = handler().get(FlowRuleService.class);
|
||||||
deviceService = handler().get(DeviceService.class);
|
|
||||||
hostService = handler().get(HostService.class);
|
|
||||||
coreService = handler().get(CoreService.class);
|
coreService = handler().get(CoreService.class);
|
||||||
appId = coreService.getAppId(PIPELINE_APP_NAME);
|
cfgService = handler().get(NetworkConfigService.class);
|
||||||
|
appId = coreService.getAppId(PipeconfLoader.PIPELINE_APP_NAME);
|
||||||
if (appId == null) {
|
if (appId == null) {
|
||||||
log.warn("Application ID is null. Cannot initialize INT-pipeline.");
|
log.warn("Application ID is null. Cannot initialize behaviour.");
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean init() {
|
||||||
|
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<PortNumber> hostPorts = deviceService.getPorts(deviceId).stream().filter(port ->
|
final GeneralProviderDeviceConfig cfg = cfgService.getConfig(
|
||||||
hostService.getConnectedHosts(
|
deviceId, GeneralProviderDeviceConfig.class);
|
||||||
new ConnectPoint(deviceId, port.number())).size() > 0
|
if (cfg == null) {
|
||||||
).map(Port::number).collect(Collectors.toSet());
|
log.warn("Missing GeneralProviderDevice config for {}", deviceId);
|
||||||
List<FlowRule> flowRules = new ArrayList<>();
|
return false;
|
||||||
|
}
|
||||||
|
final String switchId = cfg.protocolsInfo().containsKey("int") ?
|
||||||
|
cfg.protocolsInfo().get("int").configValues().get("switchId")
|
||||||
|
: null;
|
||||||
|
if (switchId == null || switchId.isEmpty()) {
|
||||||
|
log.warn("Missing INT device config for {}", deviceId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PiActionParam transitIdParam;
|
||||||
|
try {
|
||||||
|
transitIdParam = new PiActionParam(
|
||||||
|
FabricConstants.SWITCH_ID,
|
||||||
|
// FIXME set switch ID from netcfg
|
||||||
|
copyFrom(Integer.parseInt(switchId)));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.warn("Invalid INT switch ID for {}: {}", deviceId, switchId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// process_int_transit.tb_int_insert
|
|
||||||
PiActionParam transitIdParam = new PiActionParam(
|
|
||||||
FabricConstants.SWITCH_ID,
|
|
||||||
ImmutableByteSequence.copyFrom(
|
|
||||||
Integer.parseInt(deviceId.toString().substring(
|
|
||||||
deviceId.toString().length() - 2))));
|
|
||||||
PiAction transitAction = PiAction.builder()
|
PiAction transitAction = PiAction.builder()
|
||||||
.withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_INT_TRANSIT)
|
.withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INIT_METADATA)
|
||||||
.withParameter(transitIdParam)
|
.withParameter(transitIdParam)
|
||||||
.build();
|
.build();
|
||||||
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
|
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
|
||||||
.piTableAction(transitAction)
|
.piTableAction(transitAction)
|
||||||
.build();
|
.build();
|
||||||
|
TrafficSelector selector = DefaultTrafficSelector.builder()
|
||||||
|
.matchPi(PiCriterion.builder().matchExact(
|
||||||
|
FabricConstants.HDR_INT_HEADER_IS_VALID, (byte) 0x01)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
FlowRule transitFlowRule = DefaultFlowRule.builder()
|
FlowRule transitFlowRule = DefaultFlowRule.builder()
|
||||||
|
.withSelector(selector)
|
||||||
.withTreatment(treatment)
|
.withTreatment(treatment)
|
||||||
.fromApp(appId)
|
.fromApp(appId)
|
||||||
.withPriority(DEFAULT_PRIORITY)
|
.withPriority(DEFAULT_PRIORITY)
|
||||||
.makePermanent()
|
.makePermanent()
|
||||||
.forDevice(deviceId)
|
.forDevice(deviceId)
|
||||||
.forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_TB_INT_INSERT)
|
.forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INSERT)
|
||||||
.build();
|
.build();
|
||||||
flowRules.add(transitFlowRule);
|
|
||||||
|
|
||||||
for (PortNumber portNumber: hostPorts) {
|
flowRuleService.applyFlowRules(transitFlowRule);
|
||||||
// process_set_source_sink.tb_set_source for each host-facing port
|
return true;
|
||||||
PiCriterion ingressCriterion = PiCriterion.builder()
|
}
|
||||||
.matchExact(FabricConstants.STANDARD_METADATA_INGRESS_PORT, portNumber.toLong())
|
|
||||||
.build();
|
|
||||||
TrafficSelector srcSelector = DefaultTrafficSelector.builder()
|
|
||||||
.matchPi(ingressCriterion)
|
|
||||||
.build();
|
|
||||||
PiAction setSourceAct = PiAction.builder()
|
|
||||||
.withId(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SOURCE)
|
|
||||||
.build();
|
|
||||||
TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
|
|
||||||
.piTableAction(setSourceAct)
|
|
||||||
.build();
|
|
||||||
FlowRule srcFlowRule = DefaultFlowRule.builder()
|
|
||||||
.withSelector(srcSelector)
|
|
||||||
.withTreatment(srcTreatment)
|
|
||||||
.fromApp(appId)
|
|
||||||
.withPriority(DEFAULT_PRIORITY)
|
|
||||||
.makePermanent()
|
|
||||||
.forDevice(deviceId)
|
|
||||||
.forTable(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SOURCE)
|
|
||||||
.build();
|
|
||||||
flowRules.add(srcFlowRule);
|
|
||||||
|
|
||||||
// process_set_source_sink.tb_set_sink
|
@Override
|
||||||
PiCriterion egressCriterion = PiCriterion.builder()
|
public boolean setSourcePort(PortNumber port) {
|
||||||
.matchExact(FabricConstants.STANDARD_METADATA_EGRESS_PORT, portNumber.toLong())
|
|
||||||
.build();
|
if (!setupBehaviour()) {
|
||||||
TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
|
return false;
|
||||||
.matchPi(egressCriterion)
|
|
||||||
.build();
|
|
||||||
PiAction setSinkAct = PiAction.builder()
|
|
||||||
.withId(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SINK)
|
|
||||||
.build();
|
|
||||||
TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
|
|
||||||
.piTableAction(setSinkAct)
|
|
||||||
.build();
|
|
||||||
FlowRule sinkFlowRule = DefaultFlowRule.builder()
|
|
||||||
.withSelector(sinkSelector)
|
|
||||||
.withTreatment(sinkTreatment)
|
|
||||||
.fromApp(appId)
|
|
||||||
.withPriority(DEFAULT_PRIORITY)
|
|
||||||
.makePermanent()
|
|
||||||
.forDevice(deviceId)
|
|
||||||
.forTable(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SINK)
|
|
||||||
.build();
|
|
||||||
flowRules.add(sinkFlowRule);
|
|
||||||
}
|
}
|
||||||
flowRules.forEach(flowRule -> flowRuleService.applyFlowRules(flowRule));
|
|
||||||
|
|
||||||
// Populate tb_int_inst_0003 table
|
PiCriterion ingressCriterion = PiCriterion.builder()
|
||||||
INST_0003_ACTION_MAP.forEach((matchValue, actionId) ->
|
.matchExact(FabricConstants.STANDARD_METADATA_INGRESS_PORT, port.toLong())
|
||||||
populateInstTableEntry(FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_TB_INT_INST_0003,
|
|
||||||
FabricConstants.HDR_INT_HEADER_INSTRUCTION_MASK_0003,
|
|
||||||
matchValue,
|
|
||||||
actionId,
|
|
||||||
appId));
|
|
||||||
// Populate tb_int_inst_0407 table
|
|
||||||
INST_0407_ACTION_MAP.forEach((matchValue, actionId) ->
|
|
||||||
populateInstTableEntry(FabricConstants.FABRIC_EGRESS_PROCESS_INT_TRANSIT_TB_INT_INST_0407,
|
|
||||||
FabricConstants.HDR_INT_HEADER_INSTRUCTION_MASK_0407,
|
|
||||||
matchValue,
|
|
||||||
actionId,
|
|
||||||
appId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Boolean> addIntObjective(IntObjective obj) {
|
|
||||||
// TODO: support different types of watchlist other than flow watchlist
|
|
||||||
|
|
||||||
return CompletableFuture.supplyAsync(
|
|
||||||
() -> processIntObjective(obj, true),
|
|
||||||
SharedExecutors.getPoolThreadExecutor()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Boolean> removeIntObjective(IntObjective obj) {
|
|
||||||
return CompletableFuture.supplyAsync(
|
|
||||||
() -> processIntObjective(obj, false),
|
|
||||||
SharedExecutors.getPoolThreadExecutor()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Boolean> setupIntConfig(IntConfig config) {
|
|
||||||
return CompletableFuture.supplyAsync(
|
|
||||||
() -> setupIntReportInternal(config),
|
|
||||||
SharedExecutors.getPoolThreadExecutor()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateInstTableEntry(PiTableId tableId, PiMatchFieldId matchFieldId,
|
|
||||||
int matchValue, PiActionId actionId, ApplicationId appId) {
|
|
||||||
PiCriterion instCriterion = PiCriterion.builder()
|
|
||||||
.matchExact(matchFieldId, matchValue)
|
|
||||||
.build();
|
.build();
|
||||||
TrafficSelector instSelector = DefaultTrafficSelector.builder()
|
TrafficSelector srcSelector = DefaultTrafficSelector.builder()
|
||||||
.matchPi(instCriterion)
|
.matchPi(ingressCriterion)
|
||||||
.build();
|
.build();
|
||||||
PiAction instAction = PiAction.builder()
|
PiAction setSourceAct = PiAction.builder()
|
||||||
.withId(actionId)
|
.withId(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SOURCE)
|
||||||
.build();
|
.build();
|
||||||
TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
|
TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
|
||||||
.piTableAction(instAction)
|
.piTableAction(setSourceAct)
|
||||||
.build();
|
.build();
|
||||||
|
FlowRule srcFlowRule = DefaultFlowRule.builder()
|
||||||
FlowRule instFlowRule = DefaultFlowRule.builder()
|
.withSelector(srcSelector)
|
||||||
.withSelector(instSelector)
|
.withTreatment(srcTreatment)
|
||||||
.withTreatment(instTreatment)
|
.fromApp(appId)
|
||||||
.withPriority(DEFAULT_PRIORITY)
|
.withPriority(DEFAULT_PRIORITY)
|
||||||
.makePermanent()
|
.makePermanent()
|
||||||
.forDevice(deviceId)
|
.forDevice(deviceId)
|
||||||
.forTable(tableId)
|
.forTable(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SOURCE)
|
||||||
.fromApp(appId)
|
|
||||||
.build();
|
.build();
|
||||||
|
flowRuleService.applyFlowRules(srcFlowRule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
flowRuleService.applyFlowRules(instFlowRule);
|
@Override
|
||||||
|
public boolean setSinkPort(PortNumber port) {
|
||||||
|
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PiCriterion egressCriterion = PiCriterion.builder()
|
||||||
|
.matchExact(FabricConstants.STANDARD_METADATA_EGRESS_PORT, port.toLong())
|
||||||
|
.build();
|
||||||
|
TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
|
||||||
|
.matchPi(egressCriterion)
|
||||||
|
.build();
|
||||||
|
PiAction setSinkAct = PiAction.builder()
|
||||||
|
.withId(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SINK)
|
||||||
|
.build();
|
||||||
|
TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
|
||||||
|
.piTableAction(setSinkAct)
|
||||||
|
.build();
|
||||||
|
FlowRule sinkFlowRule = DefaultFlowRule.builder()
|
||||||
|
.withSelector(sinkSelector)
|
||||||
|
.withTreatment(sinkTreatment)
|
||||||
|
.fromApp(appId)
|
||||||
|
.withPriority(DEFAULT_PRIORITY)
|
||||||
|
.makePermanent()
|
||||||
|
.forDevice(deviceId)
|
||||||
|
.forTable(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SINK)
|
||||||
|
.build();
|
||||||
|
flowRuleService.applyFlowRules(sinkFlowRule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addIntObjective(IntObjective obj) {
|
||||||
|
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return processIntObjective(obj, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeIntObjective(IntObjective obj) {
|
||||||
|
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return processIntObjective(obj, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setupIntConfig(IntConfig config) {
|
||||||
|
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setupIntReportInternal(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
|
|
||||||
|
if (!setupBehaviour()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamSupport.stream(flowRuleService.getFlowEntries(
|
||||||
|
data().deviceId()).spliterator(), false)
|
||||||
|
.filter(f -> f.table().type() == TableId.Type.PIPELINE_INDEPENDENT)
|
||||||
|
.filter(f -> TABLES_TO_CLEANUP.contains((PiTableId) f.table()))
|
||||||
|
.forEach(flowRuleService::removeFlowRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsFunctionality(IntFunctionality functionality) {
|
||||||
|
// Sink not fully supported yet.
|
||||||
|
return functionality == IntFunctionality.SOURCE || functionality == IntFunctionality.TRANSIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FlowRule buildWatchlistEntry(IntObjective obj) {
|
private FlowRule buildWatchlistEntry(IntObjective obj) {
|
||||||
coreService = handler().get(CoreService.class);
|
|
||||||
appId = coreService.getAppId(PIPELINE_APP_NAME);
|
|
||||||
if (appId == null) {
|
|
||||||
log.warn("Application ID is null. Cannot initialize INT-pipeline.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int instructionBitmap = buildInstructionBitmap(obj.metadataTypes());
|
int instructionBitmap = buildInstructionBitmap(obj.metadataTypes());
|
||||||
PiActionParam maxHopParam = new PiActionParam(
|
PiActionParam maxHopParam = new PiActionParam(
|
||||||
FabricConstants.MAX_HOP,
|
FabricConstants.MAX_HOP,
|
||||||
ImmutableByteSequence.copyFrom(MAXHOP));
|
copyFrom(MAXHOP));
|
||||||
PiActionParam instCntParam = new PiActionParam(
|
PiActionParam instCntParam = new PiActionParam(
|
||||||
FabricConstants.INS_CNT,
|
FabricConstants.INS_CNT,
|
||||||
ImmutableByteSequence.copyFrom(Integer.bitCount(instructionBitmap)));
|
copyFrom(Integer.bitCount(instructionBitmap)));
|
||||||
PiActionParam inst0003Param = new PiActionParam(
|
PiActionParam inst0003Param = new PiActionParam(
|
||||||
FabricConstants.INS_MASK0003,
|
FabricConstants.INS_MASK0003,
|
||||||
ImmutableByteSequence.copyFrom((instructionBitmap >> 12) & 0xF));
|
copyFrom((instructionBitmap >> 12) & 0xF));
|
||||||
PiActionParam inst0407Param = new PiActionParam(
|
PiActionParam inst0407Param = new PiActionParam(
|
||||||
FabricConstants.INS_MASK0407,
|
FabricConstants.INS_MASK0407,
|
||||||
ImmutableByteSequence.copyFrom((instructionBitmap >> 8) & 0xF));
|
copyFrom((instructionBitmap >> 8) & 0xF));
|
||||||
|
|
||||||
PiAction intSourceAction = PiAction.builder()
|
PiAction intSourceAction = PiAction.builder()
|
||||||
.withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_SOURCE_INT_SOURCE_DSCP)
|
.withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_INT_SOURCE_DSCP)
|
||||||
.withParameter(maxHopParam)
|
.withParameter(maxHopParam)
|
||||||
.withParameter(instCntParam)
|
.withParameter(instCntParam)
|
||||||
.withParameter(inst0003Param)
|
.withParameter(inst0003Param)
|
||||||
@ -372,13 +347,13 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
return DefaultFlowRule.builder()
|
return DefaultFlowRule.builder()
|
||||||
.forDevice(this.data().deviceId())
|
.forDevice(deviceId)
|
||||||
.withSelector(sBuilder.build())
|
.withSelector(sBuilder.build())
|
||||||
.withTreatment(instTreatment)
|
.withTreatment(instTreatment)
|
||||||
.withPriority(DEFAULT_PRIORITY)
|
.withPriority(DEFAULT_PRIORITY)
|
||||||
.forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_SOURCE_TB_INT_SOURCE)
|
.forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_TB_INT_SOURCE)
|
||||||
.fromApp(appId)
|
.fromApp(appId)
|
||||||
.withIdleTimeout(IDLE_TIMEOUT)
|
.makePermanent()
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,12 +394,12 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a subset of Criterion from given selector,
|
* Returns a subset of Criterion from given selector, which is unsupported
|
||||||
* which is unsupported by this INT pipeline.
|
* by this INT pipeline.
|
||||||
*
|
*
|
||||||
* @param selector a traffic selector
|
* @param selector a traffic selector
|
||||||
* @return a subset of Criterion from given selector, unsupported by this INT pipeline,
|
* @return a subset of Criterion from given selector, unsupported by this
|
||||||
* empty if all criteria are supported.
|
* INT pipeline, empty if all criteria are supported.
|
||||||
*/
|
*/
|
||||||
private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
|
private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
|
||||||
return selector.criteria().stream()
|
return selector.criteria().stream()
|
||||||
@ -433,11 +408,9 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean processIntObjective(IntObjective obj, boolean install) {
|
private boolean processIntObjective(IntObjective obj, boolean install) {
|
||||||
flowRuleService = handler().get(FlowRuleService.class);
|
|
||||||
deviceId = this.data().deviceId();
|
|
||||||
if (install && !unsupportedSelectors(obj.selector()).isEmpty()) {
|
if (install && !unsupportedSelectors(obj.selector()).isEmpty()) {
|
||||||
log.warn("Device {} does not support criteria {} for INT.",
|
log.warn("Criteria {} not supported by {} for INT watchlist",
|
||||||
deviceId, unsupportedSelectors(obj.selector()));
|
unsupportedSelectors(obj.selector()), deviceId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,44 +432,42 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean setupIntReportInternal(IntConfig cfg) {
|
private boolean setupIntReportInternal(IntConfig cfg) {
|
||||||
flowRuleService = handler().get(FlowRuleService.class);
|
// Report not fully supported yet.
|
||||||
|
return true;
|
||||||
FlowRule reportRule = buildReportEntry(cfg, PKT_INSTANCE_TYPE_INGRESS_CLONE);
|
// FlowRule reportRule = buildReportEntry(cfg, PKT_INSTANCE_TYPE_INGRESS_CLONE);
|
||||||
if (reportRule != null) {
|
// if (reportRule != null) {
|
||||||
flowRuleService.applyFlowRules(reportRule);
|
// flowRuleService.applyFlowRules(reportRule);
|
||||||
log.info("Report entry {} has been added to {}", reportRule, this.data().deviceId());
|
// log.info("Report entry {} has been added to {}", reportRule, this.data().deviceId());
|
||||||
return true;
|
// return true;
|
||||||
} else {
|
// } else {
|
||||||
log.warn("Failed to add report entry on {}", this.data().deviceId());
|
// log.warn("Failed to add report entry on {}", this.data().deviceId());
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private FlowRule buildReportEntry(IntConfig cfg, int type) {
|
private FlowRule buildReportEntry(IntConfig cfg, int type) {
|
||||||
coreService = handler().get(CoreService.class);
|
|
||||||
appId = coreService.getAppId(PIPELINE_APP_NAME);
|
if (!setupBehaviour()) {
|
||||||
if (appId == null) {
|
|
||||||
log.warn("Application ID is null. Cannot build report entry.");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
PiActionParam srcMacParam = new PiActionParam(
|
PiActionParam srcMacParam = new PiActionParam(
|
||||||
FabricConstants.SRC_MAC,
|
FabricConstants.SRC_MAC,
|
||||||
ImmutableByteSequence.copyFrom(cfg.sinkMac().toBytes()));
|
copyFrom(cfg.sinkMac().toBytes()));
|
||||||
PiActionParam nextHopMacParam = new PiActionParam(
|
PiActionParam nextHopMacParam = new PiActionParam(
|
||||||
FabricConstants.MON_MAC,
|
FabricConstants.MON_MAC,
|
||||||
ImmutableByteSequence.copyFrom(cfg.collectorNextHopMac().toBytes()));
|
copyFrom(cfg.collectorNextHopMac().toBytes()));
|
||||||
PiActionParam srcIpParam = new PiActionParam(
|
PiActionParam srcIpParam = new PiActionParam(
|
||||||
FabricConstants.SRC_IP,
|
FabricConstants.SRC_IP,
|
||||||
ImmutableByteSequence.copyFrom(cfg.sinkIp().toOctets()));
|
copyFrom(cfg.sinkIp().toOctets()));
|
||||||
PiActionParam monIpParam = new PiActionParam(
|
PiActionParam monIpParam = new PiActionParam(
|
||||||
FabricConstants.MON_IP,
|
FabricConstants.MON_IP,
|
||||||
ImmutableByteSequence.copyFrom(cfg.collectorIp().toOctets()));
|
copyFrom(cfg.collectorIp().toOctets()));
|
||||||
PiActionParam monPortParam = new PiActionParam(
|
PiActionParam monPortParam = new PiActionParam(
|
||||||
FabricConstants.MON_PORT,
|
FabricConstants.MON_PORT,
|
||||||
ImmutableByteSequence.copyFrom(cfg.collectorPort().toInt()));
|
copyFrom(cfg.collectorPort().toInt()));
|
||||||
PiAction reportAction = PiAction.builder()
|
PiAction reportAction = PiAction.builder()
|
||||||
.withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_REPORT_DO_REPORT_ENCAPSULATION)
|
.withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_DO_REPORT_ENCAPSULATION)
|
||||||
.withParameter(srcMacParam)
|
.withParameter(srcMacParam)
|
||||||
.withParameter(nextHopMacParam)
|
.withParameter(nextHopMacParam)
|
||||||
.withParameter(srcIpParam)
|
.withParameter(srcIpParam)
|
||||||
@ -513,7 +484,7 @@ public class IntProgrammableImpl extends AbstractHandlerBehaviour implements Int
|
|||||||
.withPriority(DEFAULT_PRIORITY)
|
.withPriority(DEFAULT_PRIORITY)
|
||||||
.makePermanent()
|
.makePermanent()
|
||||||
.forDevice(this.data().deviceId())
|
.forDevice(this.data().deviceId())
|
||||||
.forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_REPORT_TB_GENERATE_REPORT)
|
.forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_TB_GENERATE_REPORT)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import org.osgi.service.component.annotations.Reference;
|
|||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
import org.onosproject.core.CoreService;
|
import org.onosproject.core.CoreService;
|
||||||
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
import org.onosproject.inbandtelemetry.api.IntProgrammable;
|
||||||
import org.onosproject.net.PortNumber;
|
|
||||||
import org.onosproject.net.behaviour.Pipeliner;
|
import org.onosproject.net.behaviour.Pipeliner;
|
||||||
import org.onosproject.net.device.PortStatisticsDiscovery;
|
import org.onosproject.net.device.PortStatisticsDiscovery;
|
||||||
import org.onosproject.net.pi.model.DefaultPiPipeconf;
|
import org.onosproject.net.pi.model.DefaultPiPipeconf;
|
||||||
@ -44,7 +43,6 @@ import java.io.FileNotFoundException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
@ -64,12 +62,11 @@ public class PipeconfLoader {
|
|||||||
|
|
||||||
private static Logger log = getLogger(PipeconfLoader.class);
|
private static Logger log = getLogger(PipeconfLoader.class);
|
||||||
|
|
||||||
|
static final String PIPELINE_APP_NAME = "org.onosproject.pipelines.fabric";
|
||||||
|
|
||||||
private static final String BASE_PIPECONF_ID = "org.onosproject.pipelines";
|
private static final String BASE_PIPECONF_ID = "org.onosproject.pipelines";
|
||||||
|
|
||||||
private static final String P4C_OUT_PATH = "/p4c-out";
|
private static final String P4C_OUT_PATH = "/p4c-out";
|
||||||
|
|
||||||
private static final String PIPELINE_APP_NAME = "org.onosproject.pipelines.fabric";
|
|
||||||
|
|
||||||
// profile/target/platform
|
// profile/target/platform
|
||||||
private static final String P4C_RES_BASE_PATH = P4C_OUT_PATH + "/%s/%s/%s/";
|
private static final String P4C_RES_BASE_PATH = P4C_OUT_PATH + "/%s/%s/%s/";
|
||||||
|
|
||||||
@ -79,13 +76,12 @@ public class PipeconfLoader {
|
|||||||
private static final String DEFAULT_PLATFORM = "default";
|
private static final String DEFAULT_PLATFORM = "default";
|
||||||
private static final String BMV2_JSON = "bmv2.json";
|
private static final String BMV2_JSON = "bmv2.json";
|
||||||
private static final String P4INFO_TXT = "p4info.txt";
|
private static final String P4INFO_TXT = "p4info.txt";
|
||||||
|
private static final String CPU_PORT_TXT = "cpu_port.txt";
|
||||||
private static final String TOFINO_BIN = "tofino.bin";
|
private static final String TOFINO_BIN = "tofino.bin";
|
||||||
private static final String TOFINO_CTX_JSON = "context.json";
|
private static final String TOFINO_CTX_JSON = "context.json";
|
||||||
private static final String INT_PROFILE_SUFFIX = "-int";
|
private static final String INT_PROFILE_SUFFIX = "-int";
|
||||||
private static final String FULL_PROFILE_SUFFIX = "-full";
|
private static final String FULL_PROFILE_SUFFIX = "-full";
|
||||||
|
|
||||||
private static final int BMV2_CPU_PORT = 255;
|
|
||||||
|
|
||||||
private static final Collection<PiPipeconf> PIPECONFS = buildAllPipeconf();
|
private static final Collection<PiPipeconf> PIPECONFS = buildAllPipeconf();
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||||
@ -131,45 +127,58 @@ public class PipeconfLoader {
|
|||||||
String profile = pieces[1];
|
String profile = pieces[1];
|
||||||
String target = pieces[2];
|
String target = pieces[2];
|
||||||
String platform = pieces[3];
|
String platform = pieces[3];
|
||||||
|
final DefaultPiPipeconf.Builder pipeconfBuilder;
|
||||||
try {
|
try {
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case BMV2:
|
case BMV2:
|
||||||
return buildBmv2Pipeconf(profile, platform);
|
pipeconfBuilder = bmv2Pipeconf(profile, platform);
|
||||||
|
break;
|
||||||
case TOFINO:
|
case TOFINO:
|
||||||
return buildTofinoPipeconf(profile, platform);
|
pipeconfBuilder = tofinoPipeconf(profile, platform);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log.warn("Unknown target '{}', skipping pipeconf build...",
|
log.warn("Unknown target '{}', skipping pipeconf build...",
|
||||||
target);
|
target);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
log.warn("Unable to build pipeconf at {} because one or more p4c outputs are missing",
|
log.warn("Unable to build pipeconf at {} because file is missing: {}",
|
||||||
path);
|
path, e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// Add IntProgrammable behaviour for INT-enabled profiles.
|
||||||
|
if (profile.endsWith(INT_PROFILE_SUFFIX) || profile.endsWith(FULL_PROFILE_SUFFIX)) {
|
||||||
|
pipeconfBuilder.addBehaviour(IntProgrammable.class, IntProgrammableImpl.class);
|
||||||
|
}
|
||||||
|
return pipeconfBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PiPipeconf buildBmv2Pipeconf(String profile, String platform)
|
private static DefaultPiPipeconf.Builder bmv2Pipeconf(
|
||||||
|
String profile, String platform)
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
final URL bmv2JsonUrl = PipeconfLoader.class.getResource(format(
|
final URL bmv2JsonUrl = PipeconfLoader.class.getResource(format(
|
||||||
P4C_RES_BASE_PATH + BMV2_JSON, profile, BMV2, platform));
|
P4C_RES_BASE_PATH + BMV2_JSON, profile, BMV2, platform));
|
||||||
final URL p4InfoUrl = PipeconfLoader.class.getResource(format(
|
final URL p4InfoUrl = PipeconfLoader.class.getResource(format(
|
||||||
P4C_RES_BASE_PATH + P4INFO_TXT, profile, BMV2, platform));
|
P4C_RES_BASE_PATH + P4INFO_TXT, profile, BMV2, platform));
|
||||||
if (bmv2JsonUrl == null || p4InfoUrl == null) {
|
final URL cpuPortUrl = PipeconfLoader.class.getResource(format(
|
||||||
throw new FileNotFoundException();
|
P4C_RES_BASE_PATH + CPU_PORT_TXT, profile, BMV2, platform));
|
||||||
|
if (bmv2JsonUrl == null) {
|
||||||
|
throw new FileNotFoundException(BMV2_JSON);
|
||||||
}
|
}
|
||||||
|
if (p4InfoUrl == null) {
|
||||||
DefaultPiPipeconf.Builder builder = basePipeconfBuilder(
|
throw new FileNotFoundException(P4INFO_TXT);
|
||||||
profile, platform, p4InfoUrl, Bmv2FabricInterpreter.class)
|
}
|
||||||
|
if (cpuPortUrl == null) {
|
||||||
|
throw new FileNotFoundException(CPU_PORT_TXT);
|
||||||
|
}
|
||||||
|
return basePipeconfBuilder(profile, platform, p4InfoUrl, cpuPortUrl)
|
||||||
|
.addBehaviour(PortStatisticsDiscovery.class,
|
||||||
|
FabricPortStatisticsDiscovery.class)
|
||||||
.addExtension(ExtensionType.BMV2_JSON, bmv2JsonUrl);
|
.addExtension(ExtensionType.BMV2_JSON, bmv2JsonUrl);
|
||||||
// Add IntProgrammable behaviour for INT-enabled profiles.
|
|
||||||
if (profile.endsWith(INT_PROFILE_SUFFIX) || profile.endsWith(FULL_PROFILE_SUFFIX)) {
|
|
||||||
builder.addBehaviour(IntProgrammable.class, IntProgrammableImpl.class);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PiPipeconf buildTofinoPipeconf(String profile, String platform)
|
private static DefaultPiPipeconf.Builder tofinoPipeconf(
|
||||||
|
String profile, String platform)
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
final URL tofinoBinUrl = PipeconfLoader.class.getResource(format(
|
final URL tofinoBinUrl = PipeconfLoader.class.getResource(format(
|
||||||
P4C_RES_BASE_PATH + TOFINO_BIN, profile, TOFINO, platform));
|
P4C_RES_BASE_PATH + TOFINO_BIN, profile, TOFINO, platform));
|
||||||
@ -177,19 +186,27 @@ public class PipeconfLoader {
|
|||||||
P4C_RES_BASE_PATH + TOFINO_CTX_JSON, profile, TOFINO, platform));
|
P4C_RES_BASE_PATH + TOFINO_CTX_JSON, profile, TOFINO, platform));
|
||||||
final URL p4InfoUrl = PipeconfLoader.class.getResource(format(
|
final URL p4InfoUrl = PipeconfLoader.class.getResource(format(
|
||||||
P4C_RES_BASE_PATH + P4INFO_TXT, profile, TOFINO, platform));
|
P4C_RES_BASE_PATH + P4INFO_TXT, profile, TOFINO, platform));
|
||||||
if (tofinoBinUrl == null || contextJsonUrl == null || p4InfoUrl == null) {
|
final URL cpuPortUrl = PipeconfLoader.class.getResource(format(
|
||||||
throw new FileNotFoundException();
|
P4C_RES_BASE_PATH + CPU_PORT_TXT, profile, TOFINO, platform));
|
||||||
|
if (tofinoBinUrl == null) {
|
||||||
|
throw new FileNotFoundException(TOFINO_BIN);
|
||||||
}
|
}
|
||||||
return basePipeconfBuilder(
|
if (contextJsonUrl == null) {
|
||||||
profile, platform, p4InfoUrl, FabricInterpreter.class)
|
throw new FileNotFoundException(TOFINO_CTX_JSON);
|
||||||
|
}
|
||||||
|
if (p4InfoUrl == null) {
|
||||||
|
throw new FileNotFoundException(P4INFO_TXT);
|
||||||
|
}
|
||||||
|
if (cpuPortUrl == null) {
|
||||||
|
throw new FileNotFoundException(CPU_PORT_TXT);
|
||||||
|
}
|
||||||
|
return basePipeconfBuilder(profile, platform, p4InfoUrl, cpuPortUrl)
|
||||||
.addExtension(ExtensionType.TOFINO_BIN, tofinoBinUrl)
|
.addExtension(ExtensionType.TOFINO_BIN, tofinoBinUrl)
|
||||||
.addExtension(ExtensionType.TOFINO_CONTEXT_JSON, contextJsonUrl)
|
.addExtension(ExtensionType.TOFINO_CONTEXT_JSON, contextJsonUrl);
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DefaultPiPipeconf.Builder basePipeconfBuilder(
|
private static DefaultPiPipeconf.Builder basePipeconfBuilder(
|
||||||
String profile, String platform, URL p4InfoUrl,
|
String profile, String platform, URL p4InfoUrl, URL cpuPortUrl) {
|
||||||
Class<? extends FabricInterpreter> interpreterClass) {
|
|
||||||
final String pipeconfId = platform.equals(DEFAULT_PLATFORM)
|
final String pipeconfId = platform.equals(DEFAULT_PLATFORM)
|
||||||
// Omit platform if default, e.g. with BMv2 pipeconf
|
// Omit platform if default, e.g. with BMv2 pipeconf
|
||||||
? format("%s.%s", BASE_PIPECONF_ID, profile)
|
? format("%s.%s", BASE_PIPECONF_ID, profile)
|
||||||
@ -199,12 +216,11 @@ public class PipeconfLoader {
|
|||||||
.withId(new PiPipeconfId(pipeconfId))
|
.withId(new PiPipeconfId(pipeconfId))
|
||||||
.withPipelineModel(model)
|
.withPipelineModel(model)
|
||||||
.addBehaviour(PiPipelineInterpreter.class,
|
.addBehaviour(PiPipelineInterpreter.class,
|
||||||
interpreterClass)
|
FabricInterpreter.class)
|
||||||
.addBehaviour(Pipeliner.class,
|
.addBehaviour(Pipeliner.class,
|
||||||
FabricPipeliner.class)
|
FabricPipeliner.class)
|
||||||
.addBehaviour(PortStatisticsDiscovery.class,
|
.addExtension(ExtensionType.P4_INFO_TEXT, p4InfoUrl)
|
||||||
FabricPortStatisticsDiscovery.class)
|
.addExtension(ExtensionType.CPU_PORT_TXT, cpuPortUrl);
|
||||||
.addExtension(ExtensionType.P4_INFO_TEXT, p4InfoUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PiPipelineModel parseP4Info(URL p4InfoUrl) {
|
private static PiPipelineModel parseP4Info(URL p4InfoUrl) {
|
||||||
@ -214,16 +230,4 @@ public class PipeconfLoader {
|
|||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: define interpreters with logical port mapping for Tofino platforms.
|
|
||||||
public static class Bmv2FabricInterpreter extends FabricInterpreter {
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> mapLogicalPortNumber(PortNumber port) {
|
|
||||||
if (port.equals(PortNumber.CONTROLLER)) {
|
|
||||||
return Optional.of(BMV2_CPU_PORT);
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
all: fabric fabric-spgw fabric-int fabric-full constants
|
all: fabric fabric-spgw fabric-int fabric-spgw-int fabric-full constants
|
||||||
|
|
||||||
fabric:
|
fabric:
|
||||||
@./bmv2-compile.sh "fabric" ""
|
@./bmv2-compile.sh "fabric" ""
|
||||||
@ -7,10 +7,14 @@ fabric-spgw:
|
|||||||
@./bmv2-compile.sh "fabric-spgw" "-DWITH_SPGW"
|
@./bmv2-compile.sh "fabric-spgw" "-DWITH_SPGW"
|
||||||
|
|
||||||
fabric-int:
|
fabric-int:
|
||||||
@./bmv2-compile.sh "fabric-int" "-DWITH_INT"
|
@./bmv2-compile.sh "fabric-int" "-DWITH_INT_SOURCE -DWITH_INT_TRANSIT"
|
||||||
|
|
||||||
|
fabric-spgw-int:
|
||||||
|
@./bmv2-compile.sh "fabric-spgw-int" "-DWITH_SPGW -DWITH_INT_SOURCE -DWITH_INT_TRANSIT"
|
||||||
|
|
||||||
fabric-full:
|
fabric-full:
|
||||||
@./bmv2-compile.sh "fabric-full" "-DWITH_MULTICAST -DWITH_IPV6 -DWITH_SPGW -DWITH_INT"
|
@./bmv2-compile.sh "fabric-full" "-DWITH_MULTICAST -DWITH_IPV6 -DWITH_SPGW \
|
||||||
|
-DWITH_INT_SOURCE -DWITH_INT_TRANSIT -DWITH_INT_SINK"
|
||||||
|
|
||||||
constants:
|
constants:
|
||||||
onos-gen-p4-constants \
|
onos-gen-p4-constants \
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
BMV2_CPU_PORT="255"
|
BMV2_CPU_PORT="255"
|
||||||
BMV2_PP_FLAGS="-DTARGET_BMV2 -DCPU_PORT=${BMV2_CPU_PORT}"
|
BMV2_PP_FLAGS="-DTARGET_BMV2 -DCPU_PORT=${BMV2_CPU_PORT} -DWITH_PORT_COUNTER"
|
||||||
|
|
||||||
PROFILE=$1
|
PROFILE=$1
|
||||||
OTHER_PP_FLAGS=$2
|
OTHER_PP_FLAGS=$2
|
||||||
@ -18,3 +18,5 @@ p4c-bm2-ss --arch v1model \
|
|||||||
--p4runtime-file ${OUT_DIR}/p4info.txt \
|
--p4runtime-file ${OUT_DIR}/p4info.txt \
|
||||||
--p4runtime-format text \
|
--p4runtime-format text \
|
||||||
fabric.p4
|
fabric.p4
|
||||||
|
|
||||||
|
echo ${BMV2_CPU_PORT} > ${OUT_DIR}/cpu_port.txt
|
||||||
|
|||||||
@ -21,20 +21,20 @@
|
|||||||
#include "include/control/forwarding.p4"
|
#include "include/control/forwarding.p4"
|
||||||
#include "include/control/next.p4"
|
#include "include/control/next.p4"
|
||||||
#include "include/control/packetio.p4"
|
#include "include/control/packetio.p4"
|
||||||
#include "include/control/port_counter.p4"
|
|
||||||
#include "include/header.p4"
|
#include "include/header.p4"
|
||||||
#include "include/checksum.p4"
|
#include "include/checksum.p4"
|
||||||
#include "include/parser.p4"
|
#include "include/parser.p4"
|
||||||
|
|
||||||
|
#ifdef WITH_PORT_COUNTER
|
||||||
|
#include "include/control/port_counter.p4"
|
||||||
|
#endif // WITH_PORT_COUNTER
|
||||||
|
|
||||||
#ifdef WITH_SPGW
|
#ifdef WITH_SPGW
|
||||||
#include "include/spgw.p4"
|
#include "include/spgw.p4"
|
||||||
#endif // WITH_SPGW
|
#endif // WITH_SPGW
|
||||||
|
|
||||||
#ifdef WITH_INT
|
#ifdef WITH_INT
|
||||||
#include "include/int_source.p4"
|
#include "include/int/int_main.p4"
|
||||||
#include "include/int_transit.p4"
|
|
||||||
#include "include/int_sink.p4"
|
|
||||||
#include "include/int_report.p4"
|
|
||||||
#endif // WITH_INT
|
#endif // WITH_INT
|
||||||
|
|
||||||
control FabricIngress (
|
control FabricIngress (
|
||||||
@ -45,9 +45,12 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
Filtering() filtering;
|
Filtering() filtering;
|
||||||
Forwarding() forwarding;
|
Forwarding() forwarding;
|
||||||
Next() next;
|
Next() next;
|
||||||
|
#ifdef WITH_PORT_COUNTER
|
||||||
PortCountersControl() port_counters_control;
|
PortCountersControl() port_counters_control;
|
||||||
|
#endif // WITH_PORT_COUNTER
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
|
_PRE_INGRESS
|
||||||
#ifdef WITH_SPGW
|
#ifdef WITH_SPGW
|
||||||
spgw_normalizer.apply(hdr.gtpu.isValid(), hdr.gtpu_ipv4, hdr.gtpu_udp,
|
spgw_normalizer.apply(hdr.gtpu.isValid(), hdr.gtpu_ipv4, hdr.gtpu_udp,
|
||||||
hdr.ipv4, hdr.udp, hdr.inner_ipv4, hdr.inner_udp);
|
hdr.ipv4, hdr.udp, hdr.inner_ipv4, hdr.inner_udp);
|
||||||
@ -64,15 +67,12 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
filtering.apply(hdr, fabric_metadata, standard_metadata);
|
filtering.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
forwarding.apply(hdr, fabric_metadata, standard_metadata);
|
forwarding.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
next.apply(hdr, fabric_metadata, standard_metadata);
|
next.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
|
#ifdef WITH_PORT_COUNTER
|
||||||
|
// FIXME: we're not counting pkts punted to cpu or forwarded via multicast groups.
|
||||||
port_counters_control.apply(hdr, fabric_metadata, standard_metadata);
|
port_counters_control.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
#ifdef WITH_INT
|
#endif // WITH_PORT_COUNTER
|
||||||
|
#if defined(WITH_INT_SOURCE) || defined(WITH_INT_SINK)
|
||||||
process_set_source_sink.apply(hdr, fabric_metadata, standard_metadata);
|
process_set_source_sink.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
if(fabric_metadata.int_meta.sink == 1) {
|
|
||||||
// clone packet for Telemetry Report
|
|
||||||
#ifdef __TARGET_BMV2__
|
|
||||||
clone(CloneType.I2E, REPORT_MIRROR_SESSION_ID);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,6 +84,7 @@ control FabricEgress (inout parsed_headers_t hdr,
|
|||||||
EgressNextControl() egress_next;
|
EgressNextControl() egress_next;
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
|
_PRE_EGRESS
|
||||||
pkt_io_egress.apply(hdr, fabric_metadata, standard_metadata);
|
pkt_io_egress.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
egress_next.apply(hdr, fabric_metadata, standard_metadata);
|
egress_next.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
#ifdef WITH_SPGW
|
#ifdef WITH_SPGW
|
||||||
@ -91,26 +92,7 @@ control FabricEgress (inout parsed_headers_t hdr,
|
|||||||
fabric_metadata.spgw, standard_metadata);
|
fabric_metadata.spgw, standard_metadata);
|
||||||
#endif // WITH_SPGW
|
#endif // WITH_SPGW
|
||||||
#ifdef WITH_INT
|
#ifdef WITH_INT
|
||||||
if (standard_metadata.ingress_port != CPU_PORT &&
|
process_int_main.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
standard_metadata.egress_port != CPU_PORT &&
|
|
||||||
(hdr.udp.isValid() || hdr.tcp.isValid())) {
|
|
||||||
if (fabric_metadata.int_meta.source == 1) {
|
|
||||||
process_int_source.apply(hdr, fabric_metadata, standard_metadata);
|
|
||||||
}
|
|
||||||
if(hdr.int_header.isValid()) {
|
|
||||||
process_int_transit.apply(hdr, fabric_metadata, standard_metadata);
|
|
||||||
// update underlay header based on INT information inserted
|
|
||||||
process_int_outer_encap.apply(hdr, fabric_metadata, standard_metadata);
|
|
||||||
if (standard_metadata.instance_type == PKT_INSTANCE_TYPE_INGRESS_CLONE) {
|
|
||||||
/* send int report */
|
|
||||||
process_int_report.apply(hdr, fabric_metadata, standard_metadata);
|
|
||||||
}
|
|
||||||
if (fabric_metadata.int_meta.sink == 1) {
|
|
||||||
// int sink
|
|
||||||
process_int_sink.apply(hdr, fabric_metadata, standard_metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
standard_metadata.egress_spec = hdr.packet_out.egress_port;
|
standard_metadata.egress_spec = hdr.packet_out.egress_port;
|
||||||
hdr.packet_out.setInvalid();
|
hdr.packet_out.setInvalid();
|
||||||
fabric_metadata.is_controller_packet_out = _TRUE;
|
fabric_metadata.is_controller_packet_out = _TRUE;
|
||||||
|
// No need for ingress processing, straight to egress.
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,7 +42,7 @@ control PacketIoEgress(
|
|||||||
}
|
}
|
||||||
apply {
|
apply {
|
||||||
if (fabric_metadata.is_controller_packet_out == _TRUE) {
|
if (fabric_metadata.is_controller_packet_out == _TRUE) {
|
||||||
// No need to process through the rest of the pipeline.
|
// Transmit right away.
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
if (standard_metadata.egress_port == CPU_PORT) {
|
if (standard_metadata.egress_port == CPU_PORT) {
|
||||||
|
|||||||
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
#define MAX_PORTS 511
|
#define MAX_PORTS 511
|
||||||
|
|
||||||
|
#if defined(WITH_INT_SOURCE) || defined(WITH_INT_TRANSIT) || defined(WITH_INT_SINK)
|
||||||
|
#define WITH_INT
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _BOOL
|
#ifndef _BOOL
|
||||||
#define _BOOL bool
|
#define _BOOL bool
|
||||||
#endif
|
#endif
|
||||||
@ -33,6 +37,14 @@
|
|||||||
#define _PKT_OUT_HDR_ANNOT
|
#define _PKT_OUT_HDR_ANNOT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _PRE_INGRESS
|
||||||
|
#define _PRE_INGRESS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _PRE_EGRESS
|
||||||
|
#define _PRE_EGRESS
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef IP_VER_LENGTH
|
#ifndef IP_VER_LENGTH
|
||||||
#define IP_VER_LENGTH 4
|
#define IP_VER_LENGTH 4
|
||||||
#endif
|
#endif
|
||||||
@ -68,8 +80,6 @@ typedef bit<9> port_num_t;
|
|||||||
typedef bit<48> mac_addr_t;
|
typedef bit<48> mac_addr_t;
|
||||||
typedef bit<16> group_id_t;
|
typedef bit<16> group_id_t;
|
||||||
typedef bit<12> vlan_id_t;
|
typedef bit<12> vlan_id_t;
|
||||||
typedef bit<48> timestamp_t;
|
|
||||||
typedef bit<32> switch_id_t;
|
|
||||||
typedef bit<32> ipv4_addr_t;
|
typedef bit<32> ipv4_addr_t;
|
||||||
typedef bit<16> l4_port_t;
|
typedef bit<16> l4_port_t;
|
||||||
|
|
||||||
@ -124,7 +134,10 @@ const pcc_gate_status_t PCC_GATE_CLOSED = 1w1;
|
|||||||
/* indicate INT at LSB of DSCP */
|
/* indicate INT at LSB of DSCP */
|
||||||
const bit<6> INT_DSCP = 0x1;
|
const bit<6> INT_DSCP = 0x1;
|
||||||
|
|
||||||
const bit<8> INT_HEADER_LEN_WORD = 4;
|
// Length of the whole INT header,
|
||||||
|
// including shim and tail, excluding metadata stack.
|
||||||
|
const bit<8> INT_HEADER_LEN_WORDS = 4;
|
||||||
|
const bit<16> INT_HEADER_LEN_BYTES = 16;
|
||||||
|
|
||||||
const bit<8> CPU_MIRROR_SESSION_ID = 250;
|
const bit<8> CPU_MIRROR_SESSION_ID = 250;
|
||||||
const bit<32> REPORT_MIRROR_SESSION_ID = 500;
|
const bit<32> REPORT_MIRROR_SESSION_ID = 500;
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#define __HEADER__
|
#define __HEADER__
|
||||||
|
|
||||||
#include "define.p4"
|
#include "define.p4"
|
||||||
|
#include "int/int_header.p4"
|
||||||
|
|
||||||
@controller_header("packet_in")
|
@controller_header("packet_in")
|
||||||
header packet_in_header_t {
|
header packet_in_header_t {
|
||||||
@ -147,122 +148,6 @@ struct spgw_meta_t {
|
|||||||
}
|
}
|
||||||
#endif // WITH_SPGW
|
#endif // WITH_SPGW
|
||||||
|
|
||||||
#ifdef WITH_INT
|
|
||||||
// Report Telemetry Headers
|
|
||||||
header report_fixed_header_t {
|
|
||||||
bit<4> ver;
|
|
||||||
bit<4> nproto;
|
|
||||||
bit<1> d;
|
|
||||||
bit<1> q;
|
|
||||||
bit<1> f;
|
|
||||||
bit<15> rsvd;
|
|
||||||
bit<6> hw_id;
|
|
||||||
bit<32> seq_no;
|
|
||||||
bit<32> ingress_tstamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Telemetry drop report header
|
|
||||||
header drop_report_header_t {
|
|
||||||
bit<32> switch_id;
|
|
||||||
bit<16> ingress_port_id;
|
|
||||||
bit<16> egress_port_id;
|
|
||||||
bit<8> queue_id;
|
|
||||||
bit<8> drop_reason;
|
|
||||||
bit<16> pad;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch Local Report Header
|
|
||||||
header local_report_header_t {
|
|
||||||
bit<32> switch_id;
|
|
||||||
bit<16> ingress_port_id;
|
|
||||||
bit<16> egress_port_id;
|
|
||||||
bit<8> queue_id;
|
|
||||||
bit<24> queue_occupancy;
|
|
||||||
bit<32> egress_tstamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
header_union local_report_t {
|
|
||||||
drop_report_header_t drop_report_header;
|
|
||||||
local_report_header_t local_report_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
// INT headers
|
|
||||||
header int_header_t {
|
|
||||||
bit<2> ver;
|
|
||||||
bit<2> rep;
|
|
||||||
bit<1> c;
|
|
||||||
bit<1> e;
|
|
||||||
bit<5> rsvd1;
|
|
||||||
bit<5> ins_cnt;
|
|
||||||
bit<8> max_hop_cnt;
|
|
||||||
bit<8> total_hop_cnt;
|
|
||||||
bit<4> instruction_mask_0003; /* split the bits for lookup */
|
|
||||||
bit<4> instruction_mask_0407;
|
|
||||||
bit<4> instruction_mask_0811;
|
|
||||||
bit<4> instruction_mask_1215;
|
|
||||||
bit<16> rsvd2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// INT meta-value headers - different header for each value type
|
|
||||||
header int_switch_id_t {
|
|
||||||
bit<32> switch_id;
|
|
||||||
}
|
|
||||||
header int_port_ids_t {
|
|
||||||
bit<16> ingress_port_id;
|
|
||||||
bit<16> egress_port_id;
|
|
||||||
}
|
|
||||||
header int_hop_latency_t {
|
|
||||||
bit<32> hop_latency;
|
|
||||||
}
|
|
||||||
header int_q_occupancy_t {
|
|
||||||
bit<8> q_id;
|
|
||||||
bit<24> q_occupancy;
|
|
||||||
}
|
|
||||||
header int_ingress_tstamp_t {
|
|
||||||
bit<32> ingress_tstamp;
|
|
||||||
}
|
|
||||||
header int_egress_tstamp_t {
|
|
||||||
bit<32> egress_tstamp;
|
|
||||||
}
|
|
||||||
header int_q_congestion_t {
|
|
||||||
bit<8> q_id;
|
|
||||||
bit<24> q_congestion;
|
|
||||||
}
|
|
||||||
header int_egress_port_tx_util_t {
|
|
||||||
bit<32> egress_port_tx_util;
|
|
||||||
}
|
|
||||||
|
|
||||||
header int_data_t {
|
|
||||||
// Maximum int metadata stack size in bits:
|
|
||||||
// (0xFF -4) * 32 (excluding INT shim header, tail header and INT header)
|
|
||||||
varbit<8032> data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* INT shim header for TCP/UDP */
|
|
||||||
header intl4_shim_t {
|
|
||||||
bit<8> int_type;
|
|
||||||
bit<8> rsvd1;
|
|
||||||
bit<8> len;
|
|
||||||
bit<8> rsvd2;
|
|
||||||
}
|
|
||||||
/* INT tail header for TCP/UDP */
|
|
||||||
header intl4_tail_t {
|
|
||||||
bit<8> next_proto;
|
|
||||||
bit<16> dest_port;
|
|
||||||
bit<8> dscp;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct int_metadata_t {
|
|
||||||
switch_id_t switch_id;
|
|
||||||
bit<16> insert_byte_cnt;
|
|
||||||
bit<1> source;
|
|
||||||
bit<1> sink;
|
|
||||||
bit<8> mirror_id;
|
|
||||||
bit<16> flow_id;
|
|
||||||
bit<8> metadata_len;
|
|
||||||
}
|
|
||||||
#endif // WITH_INT
|
|
||||||
|
|
||||||
//Custom metadata definition
|
//Custom metadata definition
|
||||||
struct fabric_metadata_t {
|
struct fabric_metadata_t {
|
||||||
fwd_type_t fwd_type;
|
fwd_type_t fwd_type;
|
||||||
@ -279,7 +164,6 @@ struct fabric_metadata_t {
|
|||||||
#endif // WITH_SPGW
|
#endif // WITH_SPGW
|
||||||
#ifdef WITH_INT
|
#ifdef WITH_INT
|
||||||
int_metadata_t int_meta;
|
int_metadata_t int_meta;
|
||||||
bool compute_checksum;
|
|
||||||
#endif // WITH_INT
|
#endif // WITH_INT
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,18 +188,19 @@ struct parsed_headers_t {
|
|||||||
icmp_t icmp;
|
icmp_t icmp;
|
||||||
packet_out_header_t packet_out;
|
packet_out_header_t packet_out;
|
||||||
packet_in_header_t packet_in;
|
packet_in_header_t packet_in;
|
||||||
#ifdef WITH_INT
|
#ifdef WITH_INT_SINK
|
||||||
// INT Report Encapsulation
|
// INT Report encap
|
||||||
ethernet_t report_ethernet;
|
ethernet_t report_ethernet;
|
||||||
ipv4_t report_ipv4;
|
ipv4_t report_ipv4;
|
||||||
udp_t report_udp;
|
udp_t report_udp;
|
||||||
// INT Report Headers
|
// INT Report header (support only fixed)
|
||||||
report_fixed_header_t report_fixed_header;
|
report_fixed_header_t report_fixed_header;
|
||||||
local_report_t report_local;
|
// local_report_t report_local;
|
||||||
|
#endif // WITH_INT_SINK
|
||||||
|
#ifdef WITH_INT
|
||||||
// INT specific headers
|
// INT specific headers
|
||||||
intl4_shim_t intl4_shim;
|
intl4_shim_t intl4_shim;
|
||||||
int_header_t int_header;
|
int_header_t int_header;
|
||||||
int_data_t int_data;
|
|
||||||
int_switch_id_t int_switch_id;
|
int_switch_id_t int_switch_id;
|
||||||
int_port_ids_t int_port_ids;
|
int_port_ids_t int_port_ids;
|
||||||
int_hop_latency_t int_hop_latency;
|
int_hop_latency_t int_hop_latency;
|
||||||
@ -324,6 +209,7 @@ struct parsed_headers_t {
|
|||||||
int_egress_tstamp_t int_egress_tstamp;
|
int_egress_tstamp_t int_egress_tstamp;
|
||||||
int_q_congestion_t int_q_congestion;
|
int_q_congestion_t int_q_congestion;
|
||||||
int_egress_port_tx_util_t int_egress_tx_util;
|
int_egress_port_tx_util_t int_egress_tx_util;
|
||||||
|
int_data_t int_data;
|
||||||
intl4_tail_t intl4_tail;
|
intl4_tail_t intl4_tail;
|
||||||
#endif //WITH_INT
|
#endif //WITH_INT
|
||||||
}
|
}
|
||||||
|
|||||||
143
pipelines/fabric/src/main/resources/include/int/int_header.p4
Normal file
143
pipelines/fabric/src/main/resources/include/int/int_header.p4
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __INT_HEADER__
|
||||||
|
#define __INT_HEADER__
|
||||||
|
|
||||||
|
#include "../define.p4"
|
||||||
|
|
||||||
|
struct int_metadata_t {
|
||||||
|
_BOOL source;
|
||||||
|
_BOOL transit;
|
||||||
|
_BOOL sink;
|
||||||
|
bit<32> switch_id;
|
||||||
|
bit<8> new_words;
|
||||||
|
bit<16> new_bytes;
|
||||||
|
bit<32> ig_tstamp;
|
||||||
|
bit<32> eg_tstamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INT headers - 8 bytes
|
||||||
|
header int_header_t {
|
||||||
|
bit<2> ver;
|
||||||
|
bit<2> rep;
|
||||||
|
bit<1> c;
|
||||||
|
bit<1> e;
|
||||||
|
bit<5> rsvd1;
|
||||||
|
bit<5> ins_cnt;
|
||||||
|
bit<8> max_hop_cnt;
|
||||||
|
bit<8> total_hop_cnt;
|
||||||
|
bit<4> instruction_mask_0003; /* split the bits for lookup */
|
||||||
|
bit<4> instruction_mask_0407;
|
||||||
|
bit<4> instruction_mask_0811;
|
||||||
|
bit<4> instruction_mask_1215;
|
||||||
|
bit<16> rsvd2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INT shim header for TCP/UDP - 4 bytes
|
||||||
|
header intl4_shim_t {
|
||||||
|
bit<8> int_type;
|
||||||
|
bit<8> rsvd1;
|
||||||
|
bit<8> len_words; // 4-byte words.
|
||||||
|
bit<8> rsvd2;
|
||||||
|
}
|
||||||
|
// INT tail header for TCP/UDP - 4 bytes
|
||||||
|
header intl4_tail_t {
|
||||||
|
bit<8> next_proto;
|
||||||
|
bit<16> dest_port;
|
||||||
|
bit<2> padding;
|
||||||
|
bit<6> dscp;
|
||||||
|
}
|
||||||
|
|
||||||
|
header int_data_t {
|
||||||
|
// Maximum int metadata stack size in bits:
|
||||||
|
// (0xFF -4) * 32 (excluding INT shim header, tail header and INT header)
|
||||||
|
varbit<8032> data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_INT_TRANSIT
|
||||||
|
// INT meta-value headers - 4 bytes each
|
||||||
|
// Different header for each value type
|
||||||
|
header int_switch_id_t {
|
||||||
|
bit<32> switch_id;
|
||||||
|
}
|
||||||
|
header int_port_ids_t {
|
||||||
|
bit<16> ingress_port_id;
|
||||||
|
bit<16> egress_port_id;
|
||||||
|
}
|
||||||
|
header int_hop_latency_t {
|
||||||
|
bit<32> hop_latency;
|
||||||
|
}
|
||||||
|
header int_q_occupancy_t {
|
||||||
|
bit<8> q_id;
|
||||||
|
bit<24> q_occupancy;
|
||||||
|
}
|
||||||
|
header int_ingress_tstamp_t {
|
||||||
|
bit<32> ingress_tstamp;
|
||||||
|
}
|
||||||
|
header int_egress_tstamp_t {
|
||||||
|
bit<32> egress_tstamp;
|
||||||
|
}
|
||||||
|
header int_q_congestion_t {
|
||||||
|
bit<8> q_id;
|
||||||
|
bit<24> q_congestion;
|
||||||
|
}
|
||||||
|
header int_egress_port_tx_util_t {
|
||||||
|
bit<32> egress_port_tx_util;
|
||||||
|
}
|
||||||
|
#endif // WITH_INT_TRANSIT
|
||||||
|
|
||||||
|
#ifdef WITH_INT_SINK
|
||||||
|
// Report Telemetry Headers
|
||||||
|
header report_fixed_header_t {
|
||||||
|
bit<4> ver;
|
||||||
|
bit<4> nproto;
|
||||||
|
bit<1> d;
|
||||||
|
bit<1> q;
|
||||||
|
bit<1> f;
|
||||||
|
bit<15> rsvd;
|
||||||
|
bit<6> hw_id;
|
||||||
|
bit<32> seq_no;
|
||||||
|
bit<32> ingress_tstamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Telemetry drop report header
|
||||||
|
header drop_report_header_t {
|
||||||
|
bit<32> switch_id;
|
||||||
|
bit<16> ingress_port_id;
|
||||||
|
bit<16> egress_port_id;
|
||||||
|
bit<8> queue_id;
|
||||||
|
bit<8> drop_reason;
|
||||||
|
bit<16> pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch Local Report Header
|
||||||
|
header local_report_header_t {
|
||||||
|
bit<32> switch_id;
|
||||||
|
bit<16> ingress_port_id;
|
||||||
|
bit<16> egress_port_id;
|
||||||
|
bit<8> queue_id;
|
||||||
|
bit<24> queue_occupancy;
|
||||||
|
bit<32> egress_tstamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
header_union local_report_t {
|
||||||
|
drop_report_header_t drop_report_header;
|
||||||
|
local_report_header_t local_report_header;
|
||||||
|
}
|
||||||
|
#endif // WITH_INT_SINK
|
||||||
|
|
||||||
|
#endif
|
||||||
124
pipelines/fabric/src/main/resources/include/int/int_main.p4
Normal file
124
pipelines/fabric/src/main/resources/include/int/int_main.p4
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -*- P4_16 -*- */
|
||||||
|
#ifndef __INT_MAIN__
|
||||||
|
#define __INT_MAIN__
|
||||||
|
|
||||||
|
#ifdef WITH_INT_SOURCE
|
||||||
|
#include "int_source.p4"
|
||||||
|
#endif // WITH_INT_SOURCE
|
||||||
|
|
||||||
|
#ifdef WITH_INT_TRANSIT
|
||||||
|
#include "int_transit.p4"
|
||||||
|
#endif // WITH_INT_TRANSIT
|
||||||
|
|
||||||
|
#ifdef WITH_INT_SINK
|
||||||
|
#include "int_sink.p4"
|
||||||
|
#include "int_report.p4"
|
||||||
|
#endif // WITH_INT_SINK
|
||||||
|
|
||||||
|
control process_set_source_sink (
|
||||||
|
inout parsed_headers_t hdr,
|
||||||
|
inout fabric_metadata_t fabric_metadata,
|
||||||
|
inout standard_metadata_t standard_metadata) {
|
||||||
|
|
||||||
|
direct_counter(CounterType.packets_and_bytes) counter_set_source;
|
||||||
|
|
||||||
|
action int_set_source () {
|
||||||
|
fabric_metadata.int_meta.source = _TRUE;
|
||||||
|
counter_set_source.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
table tb_set_source {
|
||||||
|
key = {
|
||||||
|
standard_metadata.ingress_port: exact;
|
||||||
|
}
|
||||||
|
actions = {
|
||||||
|
int_set_source;
|
||||||
|
}
|
||||||
|
counters = counter_set_source;
|
||||||
|
size = MAX_PORTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_INT_SINK
|
||||||
|
direct_counter(CounterType.packets_and_bytes) counter_set_sink;
|
||||||
|
|
||||||
|
action int_set_sink () {
|
||||||
|
fabric_metadata.int_meta.sink = _TRUE;
|
||||||
|
counter_set_sink.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
table tb_set_sink {
|
||||||
|
key = {
|
||||||
|
standard_metadata.egress_spec: exact;
|
||||||
|
}
|
||||||
|
actions = {
|
||||||
|
int_set_sink;
|
||||||
|
}
|
||||||
|
counters = counter_set_sink;
|
||||||
|
size = MAX_PORTS;
|
||||||
|
}
|
||||||
|
#endif // WITH_INT_SINK
|
||||||
|
|
||||||
|
apply {
|
||||||
|
tb_set_source.apply();
|
||||||
|
|
||||||
|
#ifdef WITH_INT_SINK
|
||||||
|
tb_set_sink.apply();
|
||||||
|
if(fabric_metadata.int_meta.sink == _TRUE) {
|
||||||
|
// FIXME: this works only on BMv2
|
||||||
|
#ifdef __TARGET_BMV2__
|
||||||
|
clone(CloneType.I2E, REPORT_MIRROR_SESSION_ID);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // WITH_INT_SINK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
control process_int_main (
|
||||||
|
inout parsed_headers_t hdr,
|
||||||
|
inout fabric_metadata_t fabric_metadata,
|
||||||
|
inout standard_metadata_t standard_metadata) {
|
||||||
|
|
||||||
|
apply {
|
||||||
|
if (standard_metadata.ingress_port != CPU_PORT &&
|
||||||
|
standard_metadata.egress_port != CPU_PORT &&
|
||||||
|
(hdr.udp.isValid() || hdr.tcp.isValid())) {
|
||||||
|
#ifdef WITH_INT_SOURCE
|
||||||
|
if (fabric_metadata.int_meta.source == _TRUE) {
|
||||||
|
process_int_source.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
|
}
|
||||||
|
#endif // WITH_INT_SOURCE
|
||||||
|
if(hdr.int_header.isValid()) {
|
||||||
|
#ifdef WITH_INT_TRANSIT
|
||||||
|
process_int_transit.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
|
#endif // WITH_INT_TRANSIT
|
||||||
|
#ifdef WITH_INT_SINK
|
||||||
|
if (standard_metadata.instance_type == PKT_INSTANCE_TYPE_INGRESS_CLONE) {
|
||||||
|
/* send int report */
|
||||||
|
process_int_report.apply(hdr, fabric_metadata, standard_metadata);
|
||||||
|
}
|
||||||
|
if (fabric_metadata.int_meta.sink == _TRUE) {
|
||||||
|
// int sink
|
||||||
|
process_int_sink.apply(hdr, fabric_metadata);
|
||||||
|
}
|
||||||
|
#endif // WITH_INT_SINK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -40,8 +40,7 @@ control process_int_report (
|
|||||||
// TODO how save a variable and increment
|
// TODO how save a variable and increment
|
||||||
hdr.report_fixed_header.seq_no = 0;
|
hdr.report_fixed_header.seq_no = 0;
|
||||||
//TODO how to get timestamp from ingress ns
|
//TODO how to get timestamp from ingress ns
|
||||||
hdr.report_fixed_header.ingress_tstamp =
|
hdr.report_fixed_header.ingress_tstamp = (bit<32>) standard_metadata.enq_timestamp;
|
||||||
(bit<32>) standard_metadata.enq_timestamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
action do_report_encapsulation(mac_addr_t src_mac, mac_addr_t mon_mac, ipv4_addr_t src_ip,
|
action do_report_encapsulation(mac_addr_t src_mac, mac_addr_t mon_mac, ipv4_addr_t src_ip,
|
||||||
@ -77,7 +76,6 @@ control process_int_report (
|
|||||||
hdr.report_udp.len = (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_FIXED_HEADER_LEN +
|
hdr.report_udp.len = (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_FIXED_HEADER_LEN +
|
||||||
(bit<16>) ETH_HEADER_LEN + hdr.ipv4.total_len;
|
(bit<16>) ETH_HEADER_LEN + hdr.ipv4.total_len;
|
||||||
|
|
||||||
fabric_metadata.compute_checksum = true;
|
|
||||||
add_report_fixed_header();
|
add_report_fixed_header();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,17 +20,18 @@
|
|||||||
|
|
||||||
control process_int_sink (
|
control process_int_sink (
|
||||||
inout parsed_headers_t hdr,
|
inout parsed_headers_t hdr,
|
||||||
inout fabric_metadata_t fabric_metadata,
|
inout fabric_metadata_t fabric_metadata) {
|
||||||
inout standard_metadata_t standard_metadata) {
|
|
||||||
action restore_header () {
|
action restore_header () {
|
||||||
hdr.udp.dst_port = hdr.intl4_tail.dest_port;
|
hdr.udp.dst_port = hdr.intl4_tail.dest_port;
|
||||||
hdr.ipv4.dscp = (bit<6>)hdr.intl4_tail.dscp;
|
hdr.ipv4.dscp = hdr.intl4_tail.dscp;
|
||||||
}
|
}
|
||||||
|
|
||||||
action int_sink() {
|
action int_sink() {
|
||||||
// restore length fields of IPv4 header and UDP header
|
// restore length fields of IPv4 header and UDP header
|
||||||
hdr.ipv4.total_len = hdr.ipv4.total_len - (bit<16>)(hdr.intl4_shim.len << 2);
|
bit<16> len_bytes = (bit<16>) (hdr.intl4_shim.len_words << 5w2);
|
||||||
hdr.udp.len = hdr.udp.len - (bit<16>)(hdr.intl4_shim.len << 2);
|
hdr.ipv4.total_len = hdr.ipv4.total_len - len_bytes;
|
||||||
|
hdr.udp.len = hdr.udp.len - len_bytes;
|
||||||
// remove all the INT information from the packet
|
// remove all the INT information from the packet
|
||||||
hdr.int_header.setInvalid();
|
hdr.int_header.setInvalid();
|
||||||
hdr.int_data.setInvalid();
|
hdr.int_data.setInvalid();
|
||||||
@ -51,4 +52,4 @@ control process_int_sink (
|
|||||||
int_sink();
|
int_sink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -27,13 +27,12 @@ control process_int_source (
|
|||||||
direct_counter(CounterType.packets_and_bytes) counter_int_source;
|
direct_counter(CounterType.packets_and_bytes) counter_int_source;
|
||||||
|
|
||||||
action int_source(bit<8> max_hop, bit<5> ins_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
|
action int_source(bit<8> max_hop, bit<5> ins_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
|
||||||
// insert INT shim header
|
// Insert INT shim header.
|
||||||
hdr.intl4_shim.setValid();
|
hdr.intl4_shim.setValid();
|
||||||
// int_type: Hop-by-hop type (1) , destination type (2)
|
// int_type: Hop-by-hop type (1) , destination type (2)
|
||||||
hdr.intl4_shim.int_type = 1;
|
hdr.intl4_shim.int_type = 1;
|
||||||
hdr.intl4_shim.len = INT_HEADER_LEN_WORD;
|
hdr.intl4_shim.len_words = INT_HEADER_LEN_WORDS;
|
||||||
|
// Insert INT header.
|
||||||
// insert INT header
|
|
||||||
hdr.int_header.setValid();
|
hdr.int_header.setValid();
|
||||||
hdr.int_header.ver = 0;
|
hdr.int_header.ver = 0;
|
||||||
hdr.int_header.rep = 0;
|
hdr.int_header.rep = 0;
|
||||||
@ -47,20 +46,20 @@ control process_int_source (
|
|||||||
hdr.int_header.instruction_mask_0407 = ins_mask0407;
|
hdr.int_header.instruction_mask_0407 = ins_mask0407;
|
||||||
hdr.int_header.instruction_mask_0811 = 0; // not supported
|
hdr.int_header.instruction_mask_0811 = 0; // not supported
|
||||||
hdr.int_header.instruction_mask_1215 = 0; // not supported
|
hdr.int_header.instruction_mask_1215 = 0; // not supported
|
||||||
|
// Insert INT tail header.
|
||||||
// insert INT tail header
|
|
||||||
hdr.intl4_tail.setValid();
|
hdr.intl4_tail.setValid();
|
||||||
hdr.intl4_tail.next_proto = hdr.ipv4.protocol;
|
hdr.intl4_tail.next_proto = hdr.ipv4.protocol;
|
||||||
hdr.intl4_tail.dest_port = fabric_metadata.l4_dst_port;
|
hdr.intl4_tail.dest_port = fabric_metadata.l4_dst_port;
|
||||||
hdr.intl4_tail.dscp = (bit<8>) hdr.ipv4.dscp;
|
hdr.intl4_tail.dscp = hdr.ipv4.dscp;
|
||||||
|
// Update IP and UDP (if not valid we don't care) lens (in bytes).
|
||||||
// add the header len (8 bytes) to total len
|
hdr.ipv4.total_len = hdr.ipv4.total_len + INT_HEADER_LEN_BYTES;
|
||||||
hdr.ipv4.total_len = hdr.ipv4.total_len + 16;
|
hdr.udp.len = hdr.udp.len + INT_HEADER_LEN_BYTES;
|
||||||
hdr.udp.len = hdr.udp.len + 16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
action int_source_dscp(bit<8> max_hop, bit<5> ins_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
|
action int_source_dscp(bit<8> max_hop, bit<5> ins_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
|
||||||
int_source(max_hop, ins_cnt, ins_mask0003, ins_mask0407);
|
int_source(max_hop, ins_cnt, ins_mask0003, ins_mask0407);
|
||||||
hdr.ipv4.dscp = INT_DSCP;
|
hdr.ipv4.dscp = INT_DSCP;
|
||||||
|
counter_int_source.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
table tb_int_source {
|
table tb_int_source {
|
||||||
@ -74,54 +73,10 @@ control process_int_source (
|
|||||||
int_source_dscp;
|
int_source_dscp;
|
||||||
}
|
}
|
||||||
counters = counter_int_source;
|
counters = counter_int_source;
|
||||||
size = 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
tb_int_source.apply();
|
tb_int_source.apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
control process_set_source_sink (
|
|
||||||
inout parsed_headers_t hdr,
|
|
||||||
inout fabric_metadata_t fabric_metadata,
|
|
||||||
inout standard_metadata_t standard_metadata) {
|
|
||||||
|
|
||||||
direct_counter(CounterType.packets_and_bytes) counter_set_source;
|
|
||||||
direct_counter(CounterType.packets_and_bytes) counter_set_sink;
|
|
||||||
|
|
||||||
action int_set_source () {
|
|
||||||
fabric_metadata.int_meta.source = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
action int_set_sink () {
|
|
||||||
fabric_metadata.int_meta.sink = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
table tb_set_source {
|
|
||||||
key = {
|
|
||||||
standard_metadata.ingress_port: exact;
|
|
||||||
}
|
|
||||||
actions = {
|
|
||||||
int_set_source;
|
|
||||||
}
|
|
||||||
counters = counter_set_source;
|
|
||||||
size = 256;
|
|
||||||
}
|
|
||||||
table tb_set_sink {
|
|
||||||
key = {
|
|
||||||
standard_metadata.egress_spec: exact;
|
|
||||||
}
|
|
||||||
actions = {
|
|
||||||
int_set_sink;
|
|
||||||
}
|
|
||||||
counters = counter_set_sink;
|
|
||||||
size = 256;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply {
|
|
||||||
tb_set_source.apply();
|
|
||||||
tb_set_sink.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
@ -19,221 +19,270 @@
|
|||||||
#define __INT_TRANSIT__
|
#define __INT_TRANSIT__
|
||||||
control process_int_transit (
|
control process_int_transit (
|
||||||
inout parsed_headers_t hdr,
|
inout parsed_headers_t hdr,
|
||||||
inout fabric_metadata_t fabric_metadata,
|
inout fabric_metadata_t fmeta,
|
||||||
inout standard_metadata_t standard_metadata) {
|
inout standard_metadata_t smeta) {
|
||||||
|
|
||||||
direct_counter(CounterType.packets_and_bytes) counter_int_insert;
|
action init_metadata(bit<32> switch_id) {
|
||||||
direct_counter(CounterType.packets_and_bytes) counter_int_inst_0003;
|
fmeta.int_meta.transit = _TRUE;
|
||||||
direct_counter(CounterType.packets_and_bytes) counter_int_inst_0407;
|
#ifdef _INT_INIT_METADATA
|
||||||
|
// Allow other targets to initialize INT metadata in their own way.
|
||||||
action int_update_total_hop_cnt() {
|
_INT_INIT_METADATA
|
||||||
hdr.int_header.total_hop_cnt = hdr.int_header.total_hop_cnt + 1;
|
#else
|
||||||
|
fmeta.int_meta.switch_id = switch_id;
|
||||||
|
#endif // _INT_INIT_METADATA
|
||||||
}
|
}
|
||||||
|
|
||||||
action int_transit(switch_id_t switch_id) {
|
#ifdef _INT_METADATA_ACTIONS
|
||||||
fabric_metadata.int_meta.switch_id = switch_id;
|
_INT_METADATA_ACTIONS
|
||||||
fabric_metadata.int_meta.insert_byte_cnt = (bit<16>) hdr.int_header.ins_cnt << 2;
|
#else
|
||||||
}
|
// Switch ID.
|
||||||
|
action int_set_header_0() {
|
||||||
/* Instr Bit 0 */
|
|
||||||
action int_set_header_0() { //switch_id
|
|
||||||
hdr.int_switch_id.setValid();
|
hdr.int_switch_id.setValid();
|
||||||
hdr.int_switch_id.switch_id = fabric_metadata.int_meta.switch_id;
|
hdr.int_switch_id.switch_id = fmeta.int_meta.switch_id;
|
||||||
}
|
}
|
||||||
action int_set_header_1() { //port_ids
|
// Port IDs.
|
||||||
|
action int_set_header_1() {
|
||||||
hdr.int_port_ids.setValid();
|
hdr.int_port_ids.setValid();
|
||||||
hdr.int_port_ids.ingress_port_id =
|
hdr.int_port_ids.ingress_port_id = (bit<16>) smeta.ingress_port;
|
||||||
(bit<16>) standard_metadata.ingress_port;
|
hdr.int_port_ids.egress_port_id = (bit<16>) smeta.egress_port;
|
||||||
hdr.int_port_ids.egress_port_id =
|
|
||||||
(bit<16>) standard_metadata.egress_port;
|
|
||||||
}
|
}
|
||||||
action int_set_header_2() { //hop_latency
|
// Hop latency.
|
||||||
|
action int_set_header_2() {
|
||||||
hdr.int_hop_latency.setValid();
|
hdr.int_hop_latency.setValid();
|
||||||
hdr.int_hop_latency.hop_latency =
|
hdr.int_hop_latency.hop_latency = (bit<32>) smeta.deq_timedelta;
|
||||||
(bit<32>) standard_metadata.deq_timedelta;
|
|
||||||
}
|
}
|
||||||
action int_set_header_3() { //q_occupancy
|
// Queue occupancy.
|
||||||
// TODO: Support egress queue ID
|
action int_set_header_3() {
|
||||||
hdr.int_q_occupancy.setValid();
|
hdr.int_q_occupancy.setValid();
|
||||||
hdr.int_q_occupancy.q_id =
|
// TODO: support queues in BMv2. ATM we assume only one.
|
||||||
0;
|
hdr.int_q_occupancy.q_id = 8w0;
|
||||||
// (bit<8>) standard_metadata.egress_qid;
|
hdr.int_q_occupancy.q_occupancy = (bit<24>) smeta.deq_qdepth;
|
||||||
hdr.int_q_occupancy.q_occupancy =
|
|
||||||
(bit<24>) standard_metadata.deq_qdepth;
|
|
||||||
}
|
}
|
||||||
action int_set_header_4() { //ingress_tstamp
|
// Ingress timestamp.
|
||||||
|
action int_set_header_4() {
|
||||||
hdr.int_ingress_tstamp.setValid();
|
hdr.int_ingress_tstamp.setValid();
|
||||||
hdr.int_ingress_tstamp.ingress_tstamp =
|
hdr.int_ingress_tstamp.ingress_tstamp = (bit<32>) smeta.enq_timestamp;
|
||||||
(bit<32>) standard_metadata.enq_timestamp;
|
|
||||||
}
|
}
|
||||||
action int_set_header_5() { //egress_timestamp
|
// Egress timestamp.
|
||||||
|
action int_set_header_5() {
|
||||||
hdr.int_egress_tstamp.setValid();
|
hdr.int_egress_tstamp.setValid();
|
||||||
hdr.int_egress_tstamp.egress_tstamp =
|
hdr.int_egress_tstamp.egress_tstamp = (bit<32>) smeta.enq_timestamp + (bit<32>) smeta.deq_timedelta;
|
||||||
(bit<32>) standard_metadata.enq_timestamp +
|
|
||||||
(bit<32>) standard_metadata.deq_timedelta;
|
|
||||||
}
|
}
|
||||||
action int_set_header_6() { //q_congestion
|
// Queue congestion.
|
||||||
// TODO: implement queue congestion support in BMv2
|
action int_set_header_6() {
|
||||||
// TODO: update egress queue ID
|
|
||||||
hdr.int_q_congestion.setValid();
|
hdr.int_q_congestion.setValid();
|
||||||
hdr.int_q_congestion.q_id =
|
// TODO: support queue congestion.
|
||||||
0;
|
hdr.int_q_congestion.q_id = 8w0;
|
||||||
// (bit<8>) standard_metadata.egress_qid;
|
hdr.int_q_congestion.q_congestion = 24w0;
|
||||||
hdr.int_q_congestion.q_congestion =
|
|
||||||
// (bit<24>) queueing_metadata.deq_congestion;
|
|
||||||
0;
|
|
||||||
}
|
}
|
||||||
action int_set_header_7() { //egress_port_tx_utilization
|
// Egress port utilization.
|
||||||
// TODO: implement tx utilization support in BMv2
|
action int_set_header_7() {
|
||||||
hdr.int_egress_tx_util.setValid();
|
hdr.int_egress_tx_util.setValid();
|
||||||
hdr.int_egress_tx_util.egress_port_tx_util =
|
// TODO: implement tx utilization support in BMv2.
|
||||||
// (bit<32>) queueing_metadata.tx_utilization;
|
hdr.int_egress_tx_util.egress_port_tx_util = 32w0;
|
||||||
0;
|
}
|
||||||
|
#endif // _INT_METADATA_ACTIONS
|
||||||
|
|
||||||
|
// Actions to keep track of the new metadata added.
|
||||||
|
action add_1() {
|
||||||
|
fmeta.int_meta.new_words = fmeta.int_meta.new_words + 1;
|
||||||
|
fmeta.int_meta.new_bytes = fmeta.int_meta.new_bytes + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* action function for bits 0-3 combinations, 0 is msb, 3 is lsb */
|
action add_2() {
|
||||||
/* Each bit set indicates that corresponding INT header should be added */
|
fmeta.int_meta.new_words = fmeta.int_meta.new_words + 2;
|
||||||
|
fmeta.int_meta.new_bytes = fmeta.int_meta.new_bytes + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
action add_3() {
|
||||||
|
fmeta.int_meta.new_words = fmeta.int_meta.new_words + 3;
|
||||||
|
fmeta.int_meta.new_bytes = fmeta.int_meta.new_bytes + 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
action add_4() {
|
||||||
|
fmeta.int_meta.new_words = fmeta.int_meta.new_words + 4;
|
||||||
|
fmeta.int_meta.new_bytes = fmeta.int_meta.new_bytes + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action function for bits 0-3 combinations, 0 is msb, 3 is lsb.
|
||||||
|
// Each bit set indicates that corresponding INT header should be added.
|
||||||
action int_set_header_0003_i0() {
|
action int_set_header_0003_i0() {
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i1() {
|
action int_set_header_0003_i1() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i2() {
|
action int_set_header_0003_i2() {
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i3() {
|
action int_set_header_0003_i3() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i4() {
|
action int_set_header_0003_i4() {
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i5() {
|
action int_set_header_0003_i5() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i6() {
|
action int_set_header_0003_i6() {
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i7() {
|
action int_set_header_0003_i7() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i8() {
|
action int_set_header_0003_i8() {
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i9() {
|
action int_set_header_0003_i9() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i10() {
|
action int_set_header_0003_i10() {
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i11() {
|
action int_set_header_0003_i11() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i12() {
|
action int_set_header_0003_i12() {
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i13() {
|
action int_set_header_0003_i13() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i14() {
|
action int_set_header_0003_i14() {
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0003_i15() {
|
action int_set_header_0003_i15() {
|
||||||
int_set_header_3();
|
int_set_header_3();
|
||||||
int_set_header_2();
|
int_set_header_2();
|
||||||
int_set_header_1();
|
int_set_header_1();
|
||||||
int_set_header_0();
|
int_set_header_0();
|
||||||
|
add_4();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* action function for bits 4-7 combinations, 4 is msb, 7 is lsb */
|
// Action function for bits 4-7 combinations, 4 is msb, 7 is lsb.
|
||||||
action int_set_header_0407_i0() {
|
action int_set_header_0407_i0() {
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i1() {
|
action int_set_header_0407_i1() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i2() {
|
action int_set_header_0407_i2() {
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i3() {
|
action int_set_header_0407_i3() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i4() {
|
action int_set_header_0407_i4() {
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i5() {
|
action int_set_header_0407_i5() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i6() {
|
action int_set_header_0407_i6() {
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i7() {
|
action int_set_header_0407_i7() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i8() {
|
action int_set_header_0407_i8() {
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_1();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i9() {
|
action int_set_header_0407_i9() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i10() {
|
action int_set_header_0407_i10() {
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i11() {
|
action int_set_header_0407_i11() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i12() {
|
action int_set_header_0407_i12() {
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_2();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i13() {
|
action int_set_header_0407_i13() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i14() {
|
action int_set_header_0407_i14() {
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_3();
|
||||||
}
|
}
|
||||||
action int_set_header_0407_i15() {
|
action int_set_header_0407_i15() {
|
||||||
int_set_header_7();
|
int_set_header_7();
|
||||||
int_set_header_6();
|
int_set_header_6();
|
||||||
int_set_header_5();
|
int_set_header_5();
|
||||||
int_set_header_4();
|
int_set_header_4();
|
||||||
|
add_4();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default action used to set switch ID.
|
||||||
table tb_int_insert {
|
table tb_int_insert {
|
||||||
key = {}
|
// We don't really need a key here, however we add a dummy one as a
|
||||||
actions = {
|
// workaround to ONOS inability to properly support default actions.
|
||||||
int_transit;
|
key = {
|
||||||
|
hdr.int_header.isValid(): exact @name("hdr.int_header.is_valid");
|
||||||
}
|
}
|
||||||
counters = counter_int_insert;
|
actions = {
|
||||||
size = 2;
|
init_metadata;
|
||||||
|
@defaultonly nop;
|
||||||
|
}
|
||||||
|
const default_action = nop;
|
||||||
|
size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Table to process instruction bits 0-3 */
|
// Table to process instruction bits 0-3.
|
||||||
table tb_int_inst_0003 {
|
table tb_int_inst_0003 {
|
||||||
key = {
|
key = {
|
||||||
hdr.int_header.instruction_mask_0003 : exact;
|
hdr.int_header.instruction_mask_0003 : exact;
|
||||||
@ -256,11 +305,28 @@ control process_int_transit (
|
|||||||
int_set_header_0003_i14;
|
int_set_header_0003_i14;
|
||||||
int_set_header_0003_i15;
|
int_set_header_0003_i15;
|
||||||
}
|
}
|
||||||
counters = counter_int_inst_0003;
|
|
||||||
size = 16;
|
size = 16;
|
||||||
|
const entries = {
|
||||||
|
(0x0) : int_set_header_0003_i0();
|
||||||
|
(0x1) : int_set_header_0003_i1();
|
||||||
|
(0x2) : int_set_header_0003_i2();
|
||||||
|
(0x3) : int_set_header_0003_i3();
|
||||||
|
(0x4) : int_set_header_0003_i4();
|
||||||
|
(0x5) : int_set_header_0003_i5();
|
||||||
|
(0x6) : int_set_header_0003_i6();
|
||||||
|
(0x7) : int_set_header_0003_i7();
|
||||||
|
(0x8) : int_set_header_0003_i8();
|
||||||
|
(0x9) : int_set_header_0003_i9();
|
||||||
|
(0xA) : int_set_header_0003_i10();
|
||||||
|
(0xB) : int_set_header_0003_i11();
|
||||||
|
(0xC) : int_set_header_0003_i12();
|
||||||
|
(0xD) : int_set_header_0003_i13();
|
||||||
|
(0xE) : int_set_header_0003_i14();
|
||||||
|
(0xF) : int_set_header_0003_i15();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Table to process instruction bits 4-7 */
|
// Table to process instruction bits 4-7.
|
||||||
table tb_int_inst_0407 {
|
table tb_int_inst_0407 {
|
||||||
key = {
|
key = {
|
||||||
hdr.int_header.instruction_mask_0407 : exact;
|
hdr.int_header.instruction_mask_0407 : exact;
|
||||||
@ -283,42 +349,45 @@ control process_int_transit (
|
|||||||
int_set_header_0407_i14;
|
int_set_header_0407_i14;
|
||||||
int_set_header_0407_i15;
|
int_set_header_0407_i15;
|
||||||
}
|
}
|
||||||
counters = counter_int_inst_0407;
|
|
||||||
size = 16;
|
size = 16;
|
||||||
|
const entries = {
|
||||||
|
(0x0) : int_set_header_0407_i0();
|
||||||
|
(0x1) : int_set_header_0407_i1();
|
||||||
|
(0x2) : int_set_header_0407_i2();
|
||||||
|
(0x3) : int_set_header_0407_i3();
|
||||||
|
(0x4) : int_set_header_0407_i4();
|
||||||
|
(0x5) : int_set_header_0407_i5();
|
||||||
|
(0x6) : int_set_header_0407_i6();
|
||||||
|
(0x7) : int_set_header_0407_i7();
|
||||||
|
(0x8) : int_set_header_0407_i8();
|
||||||
|
(0x9) : int_set_header_0407_i9();
|
||||||
|
(0xA) : int_set_header_0407_i10();
|
||||||
|
(0xB) : int_set_header_0407_i11();
|
||||||
|
(0xC) : int_set_header_0407_i12();
|
||||||
|
(0xD) : int_set_header_0407_i13();
|
||||||
|
(0xE) : int_set_header_0407_i14();
|
||||||
|
(0xF) : int_set_header_0407_i15();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
tb_int_insert.apply();
|
tb_int_insert.apply();
|
||||||
|
if (fmeta.int_meta.transit == _FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
tb_int_inst_0003.apply();
|
tb_int_inst_0003.apply();
|
||||||
tb_int_inst_0407.apply();
|
tb_int_inst_0407.apply();
|
||||||
int_update_total_hop_cnt();
|
// Increment hop cnt
|
||||||
}
|
hdr.int_header.total_hop_cnt = hdr.int_header.total_hop_cnt + 1;
|
||||||
}
|
// Update headers lengths.
|
||||||
|
|
||||||
control process_int_outer_encap (
|
|
||||||
inout parsed_headers_t hdr,
|
|
||||||
inout fabric_metadata_t fabric_metadata,
|
|
||||||
inout standard_metadata_t standard_metadata) {
|
|
||||||
|
|
||||||
action int_update_ipv4() {
|
|
||||||
hdr.ipv4.total_len = hdr.ipv4.total_len + fabric_metadata.int_meta.insert_byte_cnt;
|
|
||||||
}
|
|
||||||
action int_update_udp() {
|
|
||||||
hdr.udp.len = hdr.udp.len + fabric_metadata.int_meta.insert_byte_cnt;
|
|
||||||
}
|
|
||||||
action int_update_shim() {
|
|
||||||
hdr.intl4_shim.len = hdr.intl4_shim.len + (bit<8>)hdr.int_header.ins_cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply {
|
|
||||||
if (hdr.ipv4.isValid()) {
|
if (hdr.ipv4.isValid()) {
|
||||||
int_update_ipv4();
|
hdr.ipv4.total_len = hdr.ipv4.total_len + fmeta.int_meta.new_bytes;
|
||||||
}
|
}
|
||||||
if (hdr.udp.isValid()) {
|
if (hdr.udp.isValid()) {
|
||||||
int_update_udp();
|
hdr.udp.len = hdr.udp.len + fmeta.int_meta.new_bytes;
|
||||||
}
|
}
|
||||||
if (hdr.intl4_shim.isValid()) {
|
if (hdr.intl4_shim.isValid()) {
|
||||||
int_update_shim();
|
hdr.intl4_shim.len_words = hdr.intl4_shim.len_words + fmeta.int_meta.new_words;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,6 +25,8 @@ out parsed_headers_t hdr,
|
|||||||
inout fabric_metadata_t fabric_metadata,
|
inout fabric_metadata_t fabric_metadata,
|
||||||
inout standard_metadata_t standard_metadata) {
|
inout standard_metadata_t standard_metadata) {
|
||||||
|
|
||||||
|
bit<6> last_ipv4_dscp = 0;
|
||||||
|
|
||||||
state start {
|
state start {
|
||||||
transition select(standard_metadata.ingress_port) {
|
transition select(standard_metadata.ingress_port) {
|
||||||
CPU_PORT: parse_packet_out;
|
CPU_PORT: parse_packet_out;
|
||||||
@ -82,6 +84,7 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
state parse_ipv4 {
|
state parse_ipv4 {
|
||||||
packet.extract(hdr.ipv4);
|
packet.extract(hdr.ipv4);
|
||||||
fabric_metadata.ip_proto = hdr.ipv4.protocol;
|
fabric_metadata.ip_proto = hdr.ipv4.protocol;
|
||||||
|
last_ipv4_dscp = hdr.ipv4.dscp;
|
||||||
//Need header verification?
|
//Need header verification?
|
||||||
transition select(hdr.ipv4.protocol) {
|
transition select(hdr.ipv4.protocol) {
|
||||||
PROTO_TCP: parse_tcp;
|
PROTO_TCP: parse_tcp;
|
||||||
@ -114,10 +117,7 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
fabric_metadata.l4_src_port = hdr.tcp.src_port;
|
fabric_metadata.l4_src_port = hdr.tcp.src_port;
|
||||||
fabric_metadata.l4_dst_port = hdr.tcp.dst_port;
|
fabric_metadata.l4_dst_port = hdr.tcp.dst_port;
|
||||||
#ifdef WITH_INT
|
#ifdef WITH_INT
|
||||||
transition select(hdr.ipv4.isValid() && ((hdr.ipv4.dscp & INT_DSCP) == INT_DSCP)) {
|
transition parse_int;
|
||||||
true: parse_intl4_shim;
|
|
||||||
default: accept;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
transition accept;
|
transition accept;
|
||||||
#endif // WITH_INT
|
#endif // WITH_INT
|
||||||
@ -127,19 +127,16 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
packet.extract(hdr.udp);
|
packet.extract(hdr.udp);
|
||||||
fabric_metadata.l4_src_port = hdr.udp.src_port;
|
fabric_metadata.l4_src_port = hdr.udp.src_port;
|
||||||
fabric_metadata.l4_dst_port = hdr.udp.dst_port;
|
fabric_metadata.l4_dst_port = hdr.udp.dst_port;
|
||||||
#ifdef WITH_SPGW
|
|
||||||
transition select(hdr.udp.dst_port) {
|
transition select(hdr.udp.dst_port) {
|
||||||
|
#ifdef WITH_SPGW
|
||||||
UDP_PORT_GTPU: parse_gtpu;
|
UDP_PORT_GTPU: parse_gtpu;
|
||||||
default: accept;
|
#endif // WITH_SPGW
|
||||||
}
|
#ifdef WITH_INT
|
||||||
#elif WITH_INT
|
default: parse_int;
|
||||||
transition select(hdr.ipv4.isValid() && (hdr.ipv4.dscp & INT_DSCP) == INT_DSCP) {
|
|
||||||
true: parse_intl4_shim;
|
|
||||||
default: accept;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
transition accept;
|
default: accept;
|
||||||
#endif // WITH_SPGW, WITH_INT
|
#endif // WITH_INT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state parse_icmp {
|
state parse_icmp {
|
||||||
@ -147,36 +144,6 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
transition accept;
|
transition accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_INT
|
|
||||||
state parse_intl4_shim {
|
|
||||||
packet.extract(hdr.intl4_shim);
|
|
||||||
transition parse_int_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
state parse_int_header {
|
|
||||||
packet.extract(hdr.int_header);
|
|
||||||
// If there is no INT metadata but the INT header (and corresponding shim header
|
|
||||||
// and tail header) exists, default value of length field in shim header
|
|
||||||
// should be INT_HEADER_LEN_WORD.
|
|
||||||
fabric_metadata.int_meta.metadata_len = hdr.intl4_shim.len - INT_HEADER_LEN_WORD;
|
|
||||||
transition select (fabric_metadata.int_meta.metadata_len) {
|
|
||||||
0: parse_intl4_tail;
|
|
||||||
default: parse_int_data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state parse_int_data {
|
|
||||||
// Parse INT metadata, not INT header, INT shim header and INT tail header
|
|
||||||
packet.extract(hdr.int_data, (bit<32>) ((hdr.intl4_shim.len - INT_HEADER_LEN_WORD) << 5));
|
|
||||||
transition parse_intl4_tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
state parse_intl4_tail {
|
|
||||||
packet.extract(hdr.intl4_tail);
|
|
||||||
transition accept;
|
|
||||||
}
|
|
||||||
#endif // WITH_INT
|
|
||||||
|
|
||||||
#ifdef WITH_SPGW
|
#ifdef WITH_SPGW
|
||||||
state parse_gtpu {
|
state parse_gtpu {
|
||||||
transition select(hdr.ipv4.dst_addr[31:32-S1U_SGW_PREFIX_LEN]) {
|
transition select(hdr.ipv4.dst_addr[31:32-S1U_SGW_PREFIX_LEN]) {
|
||||||
@ -196,6 +163,7 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
|
|
||||||
state parse_inner_ipv4 {
|
state parse_inner_ipv4 {
|
||||||
packet.extract(hdr.inner_ipv4);
|
packet.extract(hdr.inner_ipv4);
|
||||||
|
last_ipv4_dscp = hdr.inner_ipv4.dscp;
|
||||||
transition select(hdr.inner_ipv4.protocol) {
|
transition select(hdr.inner_ipv4.protocol) {
|
||||||
PROTO_TCP: parse_tcp;
|
PROTO_TCP: parse_tcp;
|
||||||
PROTO_UDP: parse_inner_udp;
|
PROTO_UDP: parse_inner_udp;
|
||||||
@ -209,26 +177,63 @@ inout standard_metadata_t standard_metadata) {
|
|||||||
fabric_metadata.l4_src_port = hdr.inner_udp.src_port;
|
fabric_metadata.l4_src_port = hdr.inner_udp.src_port;
|
||||||
fabric_metadata.l4_dst_port = hdr.inner_udp.dst_port;
|
fabric_metadata.l4_dst_port = hdr.inner_udp.dst_port;
|
||||||
#ifdef WITH_INT
|
#ifdef WITH_INT
|
||||||
transition select(hdr.ipv4.isValid() && (hdr.ipv4.dscp & INT_DSCP) == INT_DSCP) {
|
transition parse_int;
|
||||||
true: parse_intl4_shim;
|
|
||||||
default: accept;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
transition accept;
|
transition accept;
|
||||||
#endif // WITH_INT
|
#endif // WITH_INT
|
||||||
}
|
}
|
||||||
#endif // WITH_SPGW
|
#endif // WITH_SPGW
|
||||||
|
|
||||||
|
#ifdef WITH_INT
|
||||||
|
state parse_int {
|
||||||
|
transition select(last_ipv4_dscp) {
|
||||||
|
INT_DSCP &&& INT_DSCP: parse_intl4_shim;
|
||||||
|
default: accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state parse_intl4_shim {
|
||||||
|
packet.extract(hdr.intl4_shim);
|
||||||
|
transition parse_int_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
state parse_int_header {
|
||||||
|
packet.extract(hdr.int_header);
|
||||||
|
// If there is no INT metadata but the INT header (plus shim and tail)
|
||||||
|
// exists, default value of length field in shim header should be
|
||||||
|
// INT_HEADER_LEN_WORDS.
|
||||||
|
transition select (hdr.intl4_shim.len_words) {
|
||||||
|
INT_HEADER_LEN_WORDS: parse_intl4_tail;
|
||||||
|
default: parse_int_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state parse_int_data {
|
||||||
|
#ifdef WITH_INT_SINK
|
||||||
|
// Parse INT metadata stack, but not tail
|
||||||
|
packet.extract(hdr.int_data, (bit<32>) (hdr.intl4_shim.len_words - INT_HEADER_LEN_WORDS) << 5);
|
||||||
|
transition parse_intl4_tail;
|
||||||
|
#else // not interested in INT data
|
||||||
|
transition accept;
|
||||||
|
#endif // WITH_INT_SINK
|
||||||
|
}
|
||||||
|
|
||||||
|
state parse_intl4_tail {
|
||||||
|
packet.extract(hdr.intl4_tail);
|
||||||
|
transition accept;
|
||||||
|
}
|
||||||
|
#endif // WITH_INT
|
||||||
}
|
}
|
||||||
|
|
||||||
control FabricDeparser(packet_out packet, in parsed_headers_t hdr) {
|
control FabricDeparser(packet_out packet, in parsed_headers_t hdr) {
|
||||||
apply {
|
apply {
|
||||||
packet.emit(hdr.packet_in);
|
packet.emit(hdr.packet_in);
|
||||||
#ifdef WITH_INT
|
#ifdef WITH_INT_SINK
|
||||||
packet.emit(hdr.report_ethernet);
|
packet.emit(hdr.report_ethernet);
|
||||||
packet.emit(hdr.report_ipv4);
|
packet.emit(hdr.report_ipv4);
|
||||||
packet.emit(hdr.report_udp);
|
packet.emit(hdr.report_udp);
|
||||||
packet.emit(hdr.report_fixed_header);
|
packet.emit(hdr.report_fixed_header);
|
||||||
#endif // WITH_INT
|
#endif // WITH_INT_SINK
|
||||||
packet.emit(hdr.ethernet);
|
packet.emit(hdr.ethernet);
|
||||||
packet.emit(hdr.vlan_tag);
|
packet.emit(hdr.vlan_tag);
|
||||||
packet.emit(hdr.mpls);
|
packet.emit(hdr.mpls);
|
||||||
@ -248,6 +253,7 @@ control FabricDeparser(packet_out packet, in parsed_headers_t hdr) {
|
|||||||
#ifdef WITH_INT
|
#ifdef WITH_INT
|
||||||
packet.emit(hdr.intl4_shim);
|
packet.emit(hdr.intl4_shim);
|
||||||
packet.emit(hdr.int_header);
|
packet.emit(hdr.int_header);
|
||||||
|
#ifdef WITH_INT_TRANSIT
|
||||||
packet.emit(hdr.int_switch_id);
|
packet.emit(hdr.int_switch_id);
|
||||||
packet.emit(hdr.int_port_ids);
|
packet.emit(hdr.int_port_ids);
|
||||||
packet.emit(hdr.int_hop_latency);
|
packet.emit(hdr.int_hop_latency);
|
||||||
@ -256,6 +262,7 @@ control FabricDeparser(packet_out packet, in parsed_headers_t hdr) {
|
|||||||
packet.emit(hdr.int_egress_tstamp);
|
packet.emit(hdr.int_egress_tstamp);
|
||||||
packet.emit(hdr.int_q_congestion);
|
packet.emit(hdr.int_q_congestion);
|
||||||
packet.emit(hdr.int_egress_tx_util);
|
packet.emit(hdr.int_egress_tx_util);
|
||||||
|
#endif // WITH_INT_TRANSIT
|
||||||
packet.emit(hdr.int_data);
|
packet.emit(hdr.int_data);
|
||||||
packet.emit(hdr.intl4_tail);
|
packet.emit(hdr.intl4_tail);
|
||||||
#endif // WITH_INT
|
#endif // WITH_INT
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
|||||||
|
255
|
||||||
@ -59,7 +59,7 @@ tables {
|
|||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318787614
|
direct_resource_ids: 318787614
|
||||||
size: 256
|
size: 511
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
@ -82,7 +82,7 @@ tables {
|
|||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318770551
|
direct_resource_ids: 318770551
|
||||||
size: 256
|
size: 511
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
@ -473,8 +473,8 @@ tables {
|
|||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33566961
|
id: 33612258
|
||||||
name: "FabricEgress.process_int_source.tb_int_source"
|
name: "FabricEgress.process_int_main.process_int_source.tb_int_source"
|
||||||
alias: "tb_int_source"
|
alias: "tb_int_source"
|
||||||
}
|
}
|
||||||
match_fields {
|
match_fields {
|
||||||
@ -502,37 +502,43 @@ tables {
|
|||||||
match_type: TERNARY
|
match_type: TERNARY
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16807851
|
id: 16785857
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16800567
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318776637
|
direct_resource_ids: 318800047
|
||||||
size: 1024
|
size: 1024
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33602084
|
id: 33599867
|
||||||
name: "FabricEgress.process_int_transit.tb_int_insert"
|
name: "FabricEgress.process_int_main.process_int_transit.tb_int_insert"
|
||||||
alias: "tb_int_insert"
|
alias: "tb_int_insert"
|
||||||
}
|
}
|
||||||
action_refs {
|
match_fields {
|
||||||
id: 16806530
|
id: 1
|
||||||
|
name: "hdr.int_header.is_valid"
|
||||||
|
bitwidth: 1
|
||||||
|
match_type: EXACT
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16780783
|
||||||
|
}
|
||||||
|
action_refs {
|
||||||
|
id: 16819938
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318794595
|
const_default_action_id: 16819938
|
||||||
size: 2
|
size: 1
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33561642
|
id: 33569467
|
||||||
name: "FabricEgress.process_int_transit.tb_int_inst_0003"
|
name: "FabricEgress.process_int_main.process_int_transit.tb_int_inst_0003"
|
||||||
alias: "tb_int_inst_0003"
|
alias: "tb_int_inst_0003"
|
||||||
}
|
}
|
||||||
match_fields {
|
match_fields {
|
||||||
@ -542,65 +548,65 @@ tables {
|
|||||||
match_type: EXACT
|
match_type: EXACT
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16788439
|
id: 16809886
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16792702
|
id: 16783130
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16834796
|
id: 16809096
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16815381
|
id: 16834117
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16824457
|
id: 16825314
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16796364
|
id: 16811436
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16806322
|
id: 16802199
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16819063
|
id: 16796779
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16828306
|
id: 16787676
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16799786
|
id: 16825351
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16796975
|
id: 16793999
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16801652
|
id: 16786714
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16778440
|
id: 16814203
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16790887
|
id: 16807054
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16783849
|
id: 16800064
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16837726
|
id: 16792997
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16800567
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318777781
|
|
||||||
size: 16
|
size: 16
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
|
is_const_table: true
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33571998
|
id: 33595914
|
||||||
name: "FabricEgress.process_int_transit.tb_int_inst_0407"
|
name: "FabricEgress.process_int_main.process_int_transit.tb_int_inst_0407"
|
||||||
alias: "tb_int_inst_0407"
|
alias: "tb_int_inst_0407"
|
||||||
}
|
}
|
||||||
match_fields {
|
match_fields {
|
||||||
@ -610,69 +616,69 @@ tables {
|
|||||||
match_type: EXACT
|
match_type: EXACT
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16839298
|
id: 16819022
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16837018
|
id: 16804144
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16827414
|
id: 16829117
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16786021
|
id: 16797781
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16785131
|
id: 16813543
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16808652
|
id: 16824974
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16799296
|
id: 16815362
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16780668
|
id: 16835399
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16805625
|
id: 16834505
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16778495
|
id: 16811493
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16784981
|
id: 16825476
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16806353
|
id: 16799777
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16802140
|
id: 16829592
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16827601
|
id: 16805877
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16820295
|
id: 16780182
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16810955
|
id: 16799476
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16800567
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318818305
|
|
||||||
size: 16
|
size: 16
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
|
is_const_table: true
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33607792
|
id: 33618104
|
||||||
name: "FabricEgress.process_int_report.tb_generate_report"
|
name: "FabricEgress.process_int_main.process_int_report.tb_generate_report"
|
||||||
alias: "tb_generate_report"
|
alias: "tb_generate_report"
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16814383
|
id: 16788620
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16800567
|
||||||
@ -1160,8 +1166,8 @@ actions {
|
|||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16807851
|
id: 16785857
|
||||||
name: "FabricEgress.process_int_source.int_source_dscp"
|
name: "FabricEgress.process_int_main.process_int_source.int_source_dscp"
|
||||||
alias: "int_source_dscp"
|
alias: "int_source_dscp"
|
||||||
}
|
}
|
||||||
params {
|
params {
|
||||||
@ -1187,16 +1193,9 @@ actions {
|
|||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16806280
|
id: 16780783
|
||||||
name: "FabricEgress.process_int_transit.int_update_total_hop_cnt"
|
name: "FabricEgress.process_int_main.process_int_transit.init_metadata"
|
||||||
alias: "int_update_total_hop_cnt"
|
alias: "init_metadata"
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16806530
|
|
||||||
name: "FabricEgress.process_int_transit.int_transit"
|
|
||||||
alias: "int_transit"
|
|
||||||
}
|
}
|
||||||
params {
|
params {
|
||||||
id: 1
|
id: 1
|
||||||
@ -1206,253 +1205,232 @@ actions {
|
|||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16788439
|
id: 16809886
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i0"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i0"
|
||||||
alias: "int_set_header_0003_i0"
|
alias: "int_set_header_0003_i0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16792702
|
id: 16783130
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i1"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i1"
|
||||||
alias: "int_set_header_0003_i1"
|
alias: "int_set_header_0003_i1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16834796
|
id: 16809096
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i2"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i2"
|
||||||
alias: "int_set_header_0003_i2"
|
alias: "int_set_header_0003_i2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16815381
|
id: 16834117
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i3"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i3"
|
||||||
alias: "int_set_header_0003_i3"
|
alias: "int_set_header_0003_i3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16824457
|
id: 16825314
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i4"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i4"
|
||||||
alias: "int_set_header_0003_i4"
|
alias: "int_set_header_0003_i4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16796364
|
id: 16811436
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i5"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i5"
|
||||||
alias: "int_set_header_0003_i5"
|
alias: "int_set_header_0003_i5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16806322
|
id: 16802199
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i6"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i6"
|
||||||
alias: "int_set_header_0003_i6"
|
alias: "int_set_header_0003_i6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16819063
|
id: 16796779
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i7"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i7"
|
||||||
alias: "int_set_header_0003_i7"
|
alias: "int_set_header_0003_i7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16828306
|
id: 16787676
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i8"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i8"
|
||||||
alias: "int_set_header_0003_i8"
|
alias: "int_set_header_0003_i8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16799786
|
id: 16825351
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i9"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i9"
|
||||||
alias: "int_set_header_0003_i9"
|
alias: "int_set_header_0003_i9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16796975
|
id: 16793999
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i10"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i10"
|
||||||
alias: "int_set_header_0003_i10"
|
alias: "int_set_header_0003_i10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16801652
|
id: 16786714
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i11"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i11"
|
||||||
alias: "int_set_header_0003_i11"
|
alias: "int_set_header_0003_i11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16778440
|
id: 16814203
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i12"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i12"
|
||||||
alias: "int_set_header_0003_i12"
|
alias: "int_set_header_0003_i12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16790887
|
id: 16807054
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i13"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i13"
|
||||||
alias: "int_set_header_0003_i13"
|
alias: "int_set_header_0003_i13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16783849
|
id: 16800064
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i14"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i14"
|
||||||
alias: "int_set_header_0003_i14"
|
alias: "int_set_header_0003_i14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16837726
|
id: 16792997
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i15"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i15"
|
||||||
alias: "int_set_header_0003_i15"
|
alias: "int_set_header_0003_i15"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16839298
|
id: 16819022
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i0"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i0"
|
||||||
alias: "int_set_header_0407_i0"
|
alias: "int_set_header_0407_i0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16837018
|
id: 16804144
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i1"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i1"
|
||||||
alias: "int_set_header_0407_i1"
|
alias: "int_set_header_0407_i1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16827414
|
id: 16829117
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i2"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i2"
|
||||||
alias: "int_set_header_0407_i2"
|
alias: "int_set_header_0407_i2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16786021
|
id: 16797781
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i3"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i3"
|
||||||
alias: "int_set_header_0407_i3"
|
alias: "int_set_header_0407_i3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16785131
|
id: 16813543
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i4"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i4"
|
||||||
alias: "int_set_header_0407_i4"
|
alias: "int_set_header_0407_i4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16808652
|
id: 16824974
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i5"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i5"
|
||||||
alias: "int_set_header_0407_i5"
|
alias: "int_set_header_0407_i5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16799296
|
id: 16815362
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i6"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i6"
|
||||||
alias: "int_set_header_0407_i6"
|
alias: "int_set_header_0407_i6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16780668
|
id: 16835399
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i7"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i7"
|
||||||
alias: "int_set_header_0407_i7"
|
alias: "int_set_header_0407_i7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16805625
|
id: 16834505
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i8"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i8"
|
||||||
alias: "int_set_header_0407_i8"
|
alias: "int_set_header_0407_i8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16778495
|
id: 16811493
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i9"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i9"
|
||||||
alias: "int_set_header_0407_i9"
|
alias: "int_set_header_0407_i9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16784981
|
id: 16825476
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i10"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i10"
|
||||||
alias: "int_set_header_0407_i10"
|
alias: "int_set_header_0407_i10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16806353
|
id: 16799777
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i11"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i11"
|
||||||
alias: "int_set_header_0407_i11"
|
alias: "int_set_header_0407_i11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16802140
|
id: 16829592
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i12"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i12"
|
||||||
alias: "int_set_header_0407_i12"
|
alias: "int_set_header_0407_i12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16827601
|
id: 16805877
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i13"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i13"
|
||||||
alias: "int_set_header_0407_i13"
|
alias: "int_set_header_0407_i13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16820295
|
id: 16780182
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i14"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i14"
|
||||||
alias: "int_set_header_0407_i14"
|
alias: "int_set_header_0407_i14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16810955
|
id: 16799476
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i15"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i15"
|
||||||
alias: "int_set_header_0407_i15"
|
alias: "int_set_header_0407_i15"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16816602
|
id: 16788620
|
||||||
name: "FabricEgress.process_int_outer_encap.int_update_ipv4"
|
name: "FabricEgress.process_int_main.process_int_report.do_report_encapsulation"
|
||||||
alias: "int_update_ipv4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16829666
|
|
||||||
name: "FabricEgress.process_int_outer_encap.int_update_udp"
|
|
||||||
alias: "int_update_udp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16826978
|
|
||||||
name: "FabricEgress.process_int_outer_encap.int_update_shim"
|
|
||||||
alias: "int_update_shim"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16814383
|
|
||||||
name: "FabricEgress.process_int_report.do_report_encapsulation"
|
|
||||||
alias: "do_report_encapsulation"
|
alias: "do_report_encapsulation"
|
||||||
}
|
}
|
||||||
params {
|
params {
|
||||||
@ -1483,15 +1461,15 @@ actions {
|
|||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16810741
|
id: 16816369
|
||||||
name: "FabricEgress.process_int_sink.restore_header"
|
name: "FabricEgress.process_int_main.process_int_sink.restore_header"
|
||||||
alias: "restore_header"
|
alias: "restore_header"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16787662
|
id: 16834566
|
||||||
name: "FabricEgress.process_int_sink.int_sink"
|
name: "FabricEgress.process_int_main.process_int_sink.int_sink"
|
||||||
alias: "int_sink"
|
alias: "int_sink"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1697,47 +1675,14 @@ direct_counters {
|
|||||||
}
|
}
|
||||||
direct_counters {
|
direct_counters {
|
||||||
preamble {
|
preamble {
|
||||||
id: 318776637
|
id: 318800047
|
||||||
name: "FabricEgress.process_int_source.counter_int_source"
|
name: "FabricEgress.process_int_main.process_int_source.counter_int_source"
|
||||||
alias: "counter_int_source"
|
alias: "counter_int_source"
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
unit: BOTH
|
unit: BOTH
|
||||||
}
|
}
|
||||||
direct_table_id: 33566961
|
direct_table_id: 33612258
|
||||||
}
|
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 318794595
|
|
||||||
name: "FabricEgress.process_int_transit.counter_int_insert"
|
|
||||||
alias: "counter_int_insert"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: BOTH
|
|
||||||
}
|
|
||||||
direct_table_id: 33602084
|
|
||||||
}
|
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 318777781
|
|
||||||
name: "FabricEgress.process_int_transit.counter_int_inst_0003"
|
|
||||||
alias: "counter_int_inst_0003"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: BOTH
|
|
||||||
}
|
|
||||||
direct_table_id: 33561642
|
|
||||||
}
|
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 318818305
|
|
||||||
name: "FabricEgress.process_int_transit.counter_int_inst_0407"
|
|
||||||
alias: "counter_int_inst_0407"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: BOTH
|
|
||||||
}
|
|
||||||
direct_table_id: 33571998
|
|
||||||
}
|
}
|
||||||
direct_counters {
|
direct_counters {
|
||||||
preamble {
|
preamble {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
|||||||
|
255
|
||||||
@ -18,30 +18,7 @@ tables {
|
|||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318787614
|
direct_resource_ids: 318787614
|
||||||
size: 256
|
size: 511
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
|
||||||
}
|
|
||||||
tables {
|
|
||||||
preamble {
|
|
||||||
id: 33561619
|
|
||||||
name: "FabricIngress.process_set_source_sink.tb_set_sink"
|
|
||||||
alias: "tb_set_sink"
|
|
||||||
}
|
|
||||||
match_fields {
|
|
||||||
id: 1
|
|
||||||
name: "standard_metadata.egress_spec"
|
|
||||||
bitwidth: 9
|
|
||||||
match_type: EXACT
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16788951
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16800567
|
|
||||||
annotations: "@defaultonly()"
|
|
||||||
}
|
|
||||||
direct_resource_ids: 318770551
|
|
||||||
size: 256
|
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
@ -409,8 +386,8 @@ tables {
|
|||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33566961
|
id: 33612258
|
||||||
name: "FabricEgress.process_int_source.tb_int_source"
|
name: "FabricEgress.process_int_main.process_int_source.tb_int_source"
|
||||||
alias: "tb_int_source"
|
alias: "tb_int_source"
|
||||||
}
|
}
|
||||||
match_fields {
|
match_fields {
|
||||||
@ -438,37 +415,43 @@ tables {
|
|||||||
match_type: TERNARY
|
match_type: TERNARY
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16807851
|
id: 16785857
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16800567
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318776637
|
direct_resource_ids: 318800047
|
||||||
size: 1024
|
size: 1024
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33602084
|
id: 33599867
|
||||||
name: "FabricEgress.process_int_transit.tb_int_insert"
|
name: "FabricEgress.process_int_main.process_int_transit.tb_int_insert"
|
||||||
alias: "tb_int_insert"
|
alias: "tb_int_insert"
|
||||||
}
|
}
|
||||||
action_refs {
|
match_fields {
|
||||||
id: 16806530
|
id: 1
|
||||||
|
name: "hdr.int_header.is_valid"
|
||||||
|
bitwidth: 1
|
||||||
|
match_type: EXACT
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16780783
|
||||||
|
}
|
||||||
|
action_refs {
|
||||||
|
id: 16819938
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318794595
|
const_default_action_id: 16819938
|
||||||
size: 2
|
size: 1
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33561642
|
id: 33569467
|
||||||
name: "FabricEgress.process_int_transit.tb_int_inst_0003"
|
name: "FabricEgress.process_int_main.process_int_transit.tb_int_inst_0003"
|
||||||
alias: "tb_int_inst_0003"
|
alias: "tb_int_inst_0003"
|
||||||
}
|
}
|
||||||
match_fields {
|
match_fields {
|
||||||
@ -478,65 +461,65 @@ tables {
|
|||||||
match_type: EXACT
|
match_type: EXACT
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16788439
|
id: 16809886
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16792702
|
id: 16783130
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16834796
|
id: 16809096
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16815381
|
id: 16834117
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16824457
|
id: 16825314
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16796364
|
id: 16811436
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16806322
|
id: 16802199
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16819063
|
id: 16796779
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16828306
|
id: 16787676
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16799786
|
id: 16825351
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16796975
|
id: 16793999
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16801652
|
id: 16786714
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16778440
|
id: 16814203
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16790887
|
id: 16807054
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16783849
|
id: 16800064
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16837726
|
id: 16792997
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16800567
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318777781
|
|
||||||
size: 16
|
size: 16
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
|
is_const_table: true
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
id: 33571998
|
id: 33595914
|
||||||
name: "FabricEgress.process_int_transit.tb_int_inst_0407"
|
name: "FabricEgress.process_int_main.process_int_transit.tb_int_inst_0407"
|
||||||
alias: "tb_int_inst_0407"
|
alias: "tb_int_inst_0407"
|
||||||
}
|
}
|
||||||
match_fields {
|
match_fields {
|
||||||
@ -546,76 +529,60 @@ tables {
|
|||||||
match_type: EXACT
|
match_type: EXACT
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16839298
|
id: 16819022
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16837018
|
id: 16804144
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16827414
|
id: 16829117
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16786021
|
id: 16797781
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16785131
|
id: 16813543
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16808652
|
id: 16824974
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16799296
|
id: 16815362
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16780668
|
id: 16835399
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16805625
|
id: 16834505
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16778495
|
id: 16811493
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16784981
|
id: 16825476
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16806353
|
id: 16799777
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16802140
|
id: 16829592
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16827601
|
id: 16805877
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16820295
|
id: 16780182
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16810955
|
id: 16799476
|
||||||
}
|
}
|
||||||
action_refs {
|
action_refs {
|
||||||
id: 16800567
|
id: 16800567
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
direct_resource_ids: 318818305
|
|
||||||
size: 16
|
size: 16
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
idle_timeout_behavior: NO_TIMEOUT
|
||||||
}
|
is_const_table: true
|
||||||
tables {
|
|
||||||
preamble {
|
|
||||||
id: 33607792
|
|
||||||
name: "FabricEgress.process_int_report.tb_generate_report"
|
|
||||||
alias: "tb_generate_report"
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16814383
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16800567
|
|
||||||
annotations: "@defaultonly()"
|
|
||||||
}
|
|
||||||
size: 1024
|
|
||||||
idle_timeout_behavior: NO_TIMEOUT
|
|
||||||
}
|
}
|
||||||
tables {
|
tables {
|
||||||
preamble {
|
preamble {
|
||||||
@ -667,13 +634,6 @@ actions {
|
|||||||
alias: "int_set_source"
|
alias: "int_set_source"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16788951
|
|
||||||
name: "FabricIngress.process_set_source_sink.int_set_sink"
|
|
||||||
alias: "int_set_sink"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16798734
|
id: 16798734
|
||||||
@ -1048,8 +1008,8 @@ actions {
|
|||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16807851
|
id: 16785857
|
||||||
name: "FabricEgress.process_int_source.int_source_dscp"
|
name: "FabricEgress.process_int_main.process_int_source.int_source_dscp"
|
||||||
alias: "int_source_dscp"
|
alias: "int_source_dscp"
|
||||||
}
|
}
|
||||||
params {
|
params {
|
||||||
@ -1075,16 +1035,9 @@ actions {
|
|||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16806280
|
id: 16780783
|
||||||
name: "FabricEgress.process_int_transit.int_update_total_hop_cnt"
|
name: "FabricEgress.process_int_main.process_int_transit.init_metadata"
|
||||||
alias: "int_update_total_hop_cnt"
|
alias: "init_metadata"
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16806530
|
|
||||||
name: "FabricEgress.process_int_transit.int_transit"
|
|
||||||
alias: "int_transit"
|
|
||||||
}
|
}
|
||||||
params {
|
params {
|
||||||
id: 1
|
id: 1
|
||||||
@ -1094,295 +1047,228 @@ actions {
|
|||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16788439
|
id: 16809886
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i0"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i0"
|
||||||
alias: "int_set_header_0003_i0"
|
alias: "int_set_header_0003_i0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16792702
|
id: 16783130
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i1"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i1"
|
||||||
alias: "int_set_header_0003_i1"
|
alias: "int_set_header_0003_i1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16834796
|
id: 16809096
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i2"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i2"
|
||||||
alias: "int_set_header_0003_i2"
|
alias: "int_set_header_0003_i2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16815381
|
id: 16834117
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i3"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i3"
|
||||||
alias: "int_set_header_0003_i3"
|
alias: "int_set_header_0003_i3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16824457
|
id: 16825314
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i4"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i4"
|
||||||
alias: "int_set_header_0003_i4"
|
alias: "int_set_header_0003_i4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16796364
|
id: 16811436
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i5"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i5"
|
||||||
alias: "int_set_header_0003_i5"
|
alias: "int_set_header_0003_i5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16806322
|
id: 16802199
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i6"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i6"
|
||||||
alias: "int_set_header_0003_i6"
|
alias: "int_set_header_0003_i6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16819063
|
id: 16796779
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i7"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i7"
|
||||||
alias: "int_set_header_0003_i7"
|
alias: "int_set_header_0003_i7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16828306
|
id: 16787676
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i8"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i8"
|
||||||
alias: "int_set_header_0003_i8"
|
alias: "int_set_header_0003_i8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16799786
|
id: 16825351
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i9"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i9"
|
||||||
alias: "int_set_header_0003_i9"
|
alias: "int_set_header_0003_i9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16796975
|
id: 16793999
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i10"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i10"
|
||||||
alias: "int_set_header_0003_i10"
|
alias: "int_set_header_0003_i10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16801652
|
id: 16786714
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i11"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i11"
|
||||||
alias: "int_set_header_0003_i11"
|
alias: "int_set_header_0003_i11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16778440
|
id: 16814203
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i12"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i12"
|
||||||
alias: "int_set_header_0003_i12"
|
alias: "int_set_header_0003_i12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16790887
|
id: 16807054
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i13"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i13"
|
||||||
alias: "int_set_header_0003_i13"
|
alias: "int_set_header_0003_i13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16783849
|
id: 16800064
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i14"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i14"
|
||||||
alias: "int_set_header_0003_i14"
|
alias: "int_set_header_0003_i14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16837726
|
id: 16792997
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0003_i15"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0003_i15"
|
||||||
alias: "int_set_header_0003_i15"
|
alias: "int_set_header_0003_i15"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16839298
|
id: 16819022
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i0"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i0"
|
||||||
alias: "int_set_header_0407_i0"
|
alias: "int_set_header_0407_i0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16837018
|
id: 16804144
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i1"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i1"
|
||||||
alias: "int_set_header_0407_i1"
|
alias: "int_set_header_0407_i1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16827414
|
id: 16829117
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i2"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i2"
|
||||||
alias: "int_set_header_0407_i2"
|
alias: "int_set_header_0407_i2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16786021
|
id: 16797781
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i3"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i3"
|
||||||
alias: "int_set_header_0407_i3"
|
alias: "int_set_header_0407_i3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16785131
|
id: 16813543
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i4"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i4"
|
||||||
alias: "int_set_header_0407_i4"
|
alias: "int_set_header_0407_i4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16808652
|
id: 16824974
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i5"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i5"
|
||||||
alias: "int_set_header_0407_i5"
|
alias: "int_set_header_0407_i5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16799296
|
id: 16815362
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i6"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i6"
|
||||||
alias: "int_set_header_0407_i6"
|
alias: "int_set_header_0407_i6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16780668
|
id: 16835399
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i7"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i7"
|
||||||
alias: "int_set_header_0407_i7"
|
alias: "int_set_header_0407_i7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16805625
|
id: 16834505
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i8"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i8"
|
||||||
alias: "int_set_header_0407_i8"
|
alias: "int_set_header_0407_i8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16778495
|
id: 16811493
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i9"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i9"
|
||||||
alias: "int_set_header_0407_i9"
|
alias: "int_set_header_0407_i9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16784981
|
id: 16825476
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i10"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i10"
|
||||||
alias: "int_set_header_0407_i10"
|
alias: "int_set_header_0407_i10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16806353
|
id: 16799777
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i11"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i11"
|
||||||
alias: "int_set_header_0407_i11"
|
alias: "int_set_header_0407_i11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16802140
|
id: 16829592
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i12"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i12"
|
||||||
alias: "int_set_header_0407_i12"
|
alias: "int_set_header_0407_i12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16827601
|
id: 16805877
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i13"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i13"
|
||||||
alias: "int_set_header_0407_i13"
|
alias: "int_set_header_0407_i13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16820295
|
id: 16780182
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i14"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i14"
|
||||||
alias: "int_set_header_0407_i14"
|
alias: "int_set_header_0407_i14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16810955
|
id: 16799476
|
||||||
name: "FabricEgress.process_int_transit.int_set_header_0407_i15"
|
name: "FabricEgress.process_int_main.process_int_transit.int_set_header_0407_i15"
|
||||||
alias: "int_set_header_0407_i15"
|
alias: "int_set_header_0407_i15"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16816602
|
|
||||||
name: "FabricEgress.process_int_outer_encap.int_update_ipv4"
|
|
||||||
alias: "int_update_ipv4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16829666
|
|
||||||
name: "FabricEgress.process_int_outer_encap.int_update_udp"
|
|
||||||
alias: "int_update_udp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16826978
|
|
||||||
name: "FabricEgress.process_int_outer_encap.int_update_shim"
|
|
||||||
alias: "int_update_shim"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16814383
|
|
||||||
name: "FabricEgress.process_int_report.do_report_encapsulation"
|
|
||||||
alias: "do_report_encapsulation"
|
|
||||||
}
|
|
||||||
params {
|
|
||||||
id: 1
|
|
||||||
name: "src_mac"
|
|
||||||
bitwidth: 48
|
|
||||||
}
|
|
||||||
params {
|
|
||||||
id: 2
|
|
||||||
name: "mon_mac"
|
|
||||||
bitwidth: 48
|
|
||||||
}
|
|
||||||
params {
|
|
||||||
id: 3
|
|
||||||
name: "src_ip"
|
|
||||||
bitwidth: 32
|
|
||||||
}
|
|
||||||
params {
|
|
||||||
id: 4
|
|
||||||
name: "mon_ip"
|
|
||||||
bitwidth: 32
|
|
||||||
}
|
|
||||||
params {
|
|
||||||
id: 5
|
|
||||||
name: "mon_port"
|
|
||||||
bitwidth: 16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16810741
|
|
||||||
name: "FabricEgress.process_int_sink.restore_header"
|
|
||||||
alias: "restore_header"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16787662
|
|
||||||
name: "FabricEgress.process_int_sink.int_sink"
|
|
||||||
alias: "int_sink"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
actions {
|
||||||
preamble {
|
preamble {
|
||||||
id: 16801047
|
id: 16801047
|
||||||
@ -1440,17 +1326,6 @@ direct_counters {
|
|||||||
}
|
}
|
||||||
direct_table_id: 33581620
|
direct_table_id: 33581620
|
||||||
}
|
}
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 318770551
|
|
||||||
name: "FabricIngress.process_set_source_sink.counter_set_sink"
|
|
||||||
alias: "counter_set_sink"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: BOTH
|
|
||||||
}
|
|
||||||
direct_table_id: 33561619
|
|
||||||
}
|
|
||||||
direct_counters {
|
direct_counters {
|
||||||
preamble {
|
preamble {
|
||||||
id: 318815501
|
id: 318815501
|
||||||
@ -1563,47 +1438,14 @@ direct_counters {
|
|||||||
}
|
}
|
||||||
direct_counters {
|
direct_counters {
|
||||||
preamble {
|
preamble {
|
||||||
id: 318776637
|
id: 318800047
|
||||||
name: "FabricEgress.process_int_source.counter_int_source"
|
name: "FabricEgress.process_int_main.process_int_source.counter_int_source"
|
||||||
alias: "counter_int_source"
|
alias: "counter_int_source"
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
unit: BOTH
|
unit: BOTH
|
||||||
}
|
}
|
||||||
direct_table_id: 33566961
|
direct_table_id: 33612258
|
||||||
}
|
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 318794595
|
|
||||||
name: "FabricEgress.process_int_transit.counter_int_insert"
|
|
||||||
alias: "counter_int_insert"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: BOTH
|
|
||||||
}
|
|
||||||
direct_table_id: 33602084
|
|
||||||
}
|
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 318777781
|
|
||||||
name: "FabricEgress.process_int_transit.counter_int_inst_0003"
|
|
||||||
alias: "counter_int_inst_0003"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: BOTH
|
|
||||||
}
|
|
||||||
direct_table_id: 33561642
|
|
||||||
}
|
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 318818305
|
|
||||||
name: "FabricEgress.process_int_transit.counter_int_inst_0407"
|
|
||||||
alias: "counter_int_inst_0407"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: BOTH
|
|
||||||
}
|
|
||||||
direct_table_id: 33571998
|
|
||||||
}
|
}
|
||||||
direct_counters {
|
direct_counters {
|
||||||
preamble {
|
preamble {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
|||||||
|
255
|
||||||
File diff suppressed because it is too large
Load Diff
@ -930,7 +930,7 @@
|
|||||||
"id" : 0,
|
"id" : 0,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/parser.p4",
|
"filename" : "include/parser.p4",
|
||||||
"line" : 223,
|
"line" : 228,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "FabricDeparser"
|
"source_fragment" : "FabricDeparser"
|
||||||
},
|
},
|
||||||
@ -1578,7 +1578,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 89,
|
"line" : 91,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8100; ..."
|
"source_fragment" : "0x8100; ..."
|
||||||
}
|
}
|
||||||
@ -2211,7 +2211,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -2287,7 +2287,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -2402,7 +2402,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -2478,7 +2478,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -2770,7 +2770,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -2846,7 +2846,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -2961,7 +2961,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -3037,7 +3037,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -3155,7 +3155,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "fabric.p4",
|
"filename" : "fabric.p4",
|
||||||
"line" : 52,
|
"line" : 54,
|
||||||
"column" : 50,
|
"column" : 50,
|
||||||
"source_fragment" : "hdr.gtpu_ipv4"
|
"source_fragment" : "hdr.gtpu_ipv4"
|
||||||
}
|
}
|
||||||
@ -3170,7 +3170,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "fabric.p4",
|
"filename" : "fabric.p4",
|
||||||
"line" : 52,
|
"line" : 54,
|
||||||
"column" : 65,
|
"column" : 65,
|
||||||
"source_fragment" : "hdr.gtpu_udp"
|
"source_fragment" : "hdr.gtpu_udp"
|
||||||
}
|
}
|
||||||
@ -3461,7 +3461,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 119,
|
"line" : 121,
|
||||||
"column" : 36,
|
"column" : 36,
|
||||||
"source_fragment" : "2w1; ..."
|
"source_fragment" : "2w1; ..."
|
||||||
}
|
}
|
||||||
@ -3547,7 +3547,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 120,
|
"line" : 122,
|
||||||
"column" : 38,
|
"column" : 38,
|
||||||
"source_fragment" : "2w2; ..."
|
"source_fragment" : "2w2; ..."
|
||||||
}
|
}
|
||||||
@ -3573,7 +3573,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 118,
|
"line" : 120,
|
||||||
"column" : 37,
|
"column" : 37,
|
||||||
"source_fragment" : "2w0; ..."
|
"source_fragment" : "2w0; ..."
|
||||||
}
|
}
|
||||||
@ -3744,7 +3744,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 109,
|
"line" : 111,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "7; ..."
|
"source_fragment" : "7; ..."
|
||||||
}
|
}
|
||||||
@ -3770,7 +3770,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 92,
|
"line" : 94,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x0800; ..."
|
"source_fragment" : "0x0800; ..."
|
||||||
}
|
}
|
||||||
@ -4301,7 +4301,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 101,
|
"line" : 103,
|
||||||
"column" : 28,
|
"column" : 28,
|
||||||
"source_fragment" : "5; ..."
|
"source_fragment" : "5; ..."
|
||||||
}
|
}
|
||||||
@ -4457,7 +4457,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 114,
|
"line" : 116,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -4476,7 +4476,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 98,
|
"line" : 100,
|
||||||
"column" : 25,
|
"column" : 25,
|
||||||
"source_fragment" : "17; ..."
|
"source_fragment" : "17; ..."
|
||||||
}
|
}
|
||||||
@ -4859,7 +4859,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 39,
|
"line" : 40,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "hdr.ethernet.ether_type = hdr.vlan_tag.ether_type"
|
"source_fragment" : "hdr.ethernet.ether_type = hdr.vlan_tag.ether_type"
|
||||||
}
|
}
|
||||||
@ -4874,7 +4874,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 40,
|
"line" : 41,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "hdr.vlan_tag.setInvalid()"
|
"source_fragment" : "hdr.vlan_tag.setInvalid()"
|
||||||
}
|
}
|
||||||
@ -4937,7 +4937,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 56,
|
"line" : 57,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "hdr.packet_in.setValid()"
|
"source_fragment" : "hdr.packet_in.setValid()"
|
||||||
}
|
}
|
||||||
@ -4956,7 +4956,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 57,
|
"line" : 58,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "hdr.packet_in.ingress_port = standard_metadata.ingress_port"
|
"source_fragment" : "hdr.packet_in.ingress_port = standard_metadata.ingress_port"
|
||||||
}
|
}
|
||||||
@ -6799,7 +6799,7 @@
|
|||||||
"id" : 1,
|
"id" : 1,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "fabric.p4",
|
"filename" : "fabric.p4",
|
||||||
"line" : 80,
|
"line" : 79,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "FabricEgress"
|
"source_fragment" : "FabricEgress"
|
||||||
},
|
},
|
||||||
@ -6971,7 +6971,7 @@
|
|||||||
"id" : 20,
|
"id" : 20,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 43,
|
"line" : 44,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "fabric_metadata.is_controller_packet_out == true"
|
"source_fragment" : "fabric_metadata.is_controller_packet_out == true"
|
||||||
},
|
},
|
||||||
@ -7004,7 +7004,7 @@
|
|||||||
"id" : 21,
|
"id" : 21,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 47,
|
"line" : 48,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "standard_metadata.egress_port == 255"
|
"source_fragment" : "standard_metadata.egress_port == 255"
|
||||||
},
|
},
|
||||||
@ -7030,7 +7030,7 @@
|
|||||||
"id" : 22,
|
"id" : 22,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 48,
|
"line" : 49,
|
||||||
"column" : 16,
|
"column" : 16,
|
||||||
"source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in == true"
|
"source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in == true"
|
||||||
},
|
},
|
||||||
@ -7080,7 +7080,7 @@
|
|||||||
"id" : 23,
|
"id" : 23,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 51,
|
"line" : 52,
|
||||||
"column" : 16,
|
"column" : 16,
|
||||||
"source_fragment" : "fabric_metadata.is_multicast == true && ..."
|
"source_fragment" : "fabric_metadata.is_multicast == true && ..."
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
255
|
||||||
@ -634,7 +634,12 @@
|
|||||||
"next_state" : null
|
"next_state" : null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"transition_key" : []
|
"transition_key" : [
|
||||||
|
{
|
||||||
|
"type" : "field",
|
||||||
|
"value" : ["udp", "dst_port"]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name" : "parse_icmp",
|
"name" : "parse_icmp",
|
||||||
@ -669,7 +674,7 @@
|
|||||||
"id" : 0,
|
"id" : 0,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/parser.p4",
|
"filename" : "include/parser.p4",
|
||||||
"line" : 223,
|
"line" : 228,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "FabricDeparser"
|
"source_fragment" : "FabricDeparser"
|
||||||
},
|
},
|
||||||
@ -1082,7 +1087,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 89,
|
"line" : 91,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8100; ..."
|
"source_fragment" : "0x8100; ..."
|
||||||
}
|
}
|
||||||
@ -1715,7 +1720,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -1791,7 +1796,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -1906,7 +1911,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -1982,7 +1987,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -2274,7 +2279,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -2350,7 +2355,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -2465,7 +2470,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 90,
|
"line" : 92,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x8847; ..."
|
"source_fragment" : "0x8847; ..."
|
||||||
}
|
}
|
||||||
@ -2541,7 +2546,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 113,
|
"line" : 115,
|
||||||
"column" : 32,
|
"column" : 32,
|
||||||
"source_fragment" : "64; ..."
|
"source_fragment" : "64; ..."
|
||||||
}
|
}
|
||||||
@ -2757,7 +2762,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 109,
|
"line" : 111,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "7; ..."
|
"source_fragment" : "7; ..."
|
||||||
}
|
}
|
||||||
@ -2783,7 +2788,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/../define.p4",
|
"filename" : "include/control/../define.p4",
|
||||||
"line" : 92,
|
"line" : 94,
|
||||||
"column" : 31,
|
"column" : 31,
|
||||||
"source_fragment" : "0x0800; ..."
|
"source_fragment" : "0x0800; ..."
|
||||||
}
|
}
|
||||||
@ -3280,7 +3285,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 39,
|
"line" : 40,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "hdr.ethernet.ether_type = hdr.vlan_tag.ether_type"
|
"source_fragment" : "hdr.ethernet.ether_type = hdr.vlan_tag.ether_type"
|
||||||
}
|
}
|
||||||
@ -3295,7 +3300,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 40,
|
"line" : 41,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "hdr.vlan_tag.setInvalid()"
|
"source_fragment" : "hdr.vlan_tag.setInvalid()"
|
||||||
}
|
}
|
||||||
@ -3358,7 +3363,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 56,
|
"line" : 57,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "hdr.packet_in.setValid()"
|
"source_fragment" : "hdr.packet_in.setValid()"
|
||||||
}
|
}
|
||||||
@ -3377,7 +3382,7 @@
|
|||||||
],
|
],
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 57,
|
"line" : 58,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "hdr.packet_in.ingress_port = standard_metadata.ingress_port"
|
"source_fragment" : "hdr.packet_in.ingress_port = standard_metadata.ingress_port"
|
||||||
}
|
}
|
||||||
@ -4607,7 +4612,7 @@
|
|||||||
"id" : 1,
|
"id" : 1,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "fabric.p4",
|
"filename" : "fabric.p4",
|
||||||
"line" : 80,
|
"line" : 79,
|
||||||
"column" : 8,
|
"column" : 8,
|
||||||
"source_fragment" : "FabricEgress"
|
"source_fragment" : "FabricEgress"
|
||||||
},
|
},
|
||||||
@ -4756,7 +4761,7 @@
|
|||||||
"id" : 13,
|
"id" : 13,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 43,
|
"line" : 44,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "fabric_metadata.is_controller_packet_out == true"
|
"source_fragment" : "fabric_metadata.is_controller_packet_out == true"
|
||||||
},
|
},
|
||||||
@ -4789,7 +4794,7 @@
|
|||||||
"id" : 14,
|
"id" : 14,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 47,
|
"line" : 48,
|
||||||
"column" : 12,
|
"column" : 12,
|
||||||
"source_fragment" : "standard_metadata.egress_port == 255"
|
"source_fragment" : "standard_metadata.egress_port == 255"
|
||||||
},
|
},
|
||||||
@ -4815,7 +4820,7 @@
|
|||||||
"id" : 15,
|
"id" : 15,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 48,
|
"line" : 49,
|
||||||
"column" : 16,
|
"column" : 16,
|
||||||
"source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in == true"
|
"source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in == true"
|
||||||
},
|
},
|
||||||
@ -4865,7 +4870,7 @@
|
|||||||
"id" : 16,
|
"id" : 16,
|
||||||
"source_info" : {
|
"source_info" : {
|
||||||
"filename" : "include/control/packetio.p4",
|
"filename" : "include/control/packetio.p4",
|
||||||
"line" : 51,
|
"line" : 52,
|
||||||
"column" : 16,
|
"column" : 16,
|
||||||
"source_fragment" : "fabric_metadata.is_multicast == true && ..."
|
"source_fragment" : "fabric_metadata.is_multicast == true && ..."
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
255
|
||||||
@ -24,6 +24,7 @@ import org.onosproject.net.pi.model.PiPipeconf;
|
|||||||
import org.onosproject.net.pi.model.PiTableId;
|
import org.onosproject.net.pi.model.PiTableId;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroup;
|
import org.onosproject.net.pi.runtime.PiActionGroup;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
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.PiCounterCellData;
|
||||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
|
import org.onosproject.net.pi.runtime.PiCounterCellId;
|
||||||
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
|
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
|
||||||
@ -33,7 +34,7 @@ import org.onosproject.net.pi.runtime.PiPacketOperation;
|
|||||||
import org.onosproject.net.pi.runtime.PiTableEntry;
|
import org.onosproject.net.pi.runtime.PiTableEntry;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Collection;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@ -132,27 +133,31 @@ public interface P4RuntimeClient {
|
|||||||
* @return true if the operation was successful, false otherwise.
|
* @return true if the operation was successful, false otherwise.
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> writeTableEntries(
|
CompletableFuture<Boolean> writeTableEntries(
|
||||||
Collection<PiTableEntry> entries, WriteOperationType opType,
|
List<PiTableEntry> entries, WriteOperationType opType,
|
||||||
PiPipeconf pipeconf);
|
PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps all entries currently installed in the given table, for the given
|
* Dumps all entries currently installed in the given tables, for the given
|
||||||
* pipeconf.
|
* pipeconf. If defaultEntries is set to true only the default action
|
||||||
|
* entries will be returned, otherwise non-default entries will be
|
||||||
|
* considered.
|
||||||
*
|
*
|
||||||
* @param tableId table identifier
|
* @param tableIds table identifiers
|
||||||
* @param pipeconf pipeconf currently deployed on the device
|
* @param defaultEntries true to read default entries, false for
|
||||||
* @return completable future of a collection of table entries
|
* non-default
|
||||||
|
* @param pipeconf pipeconf currently deployed on the device
|
||||||
|
* @return completable future of a list of table entries
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiTableEntry>> dumpTable(
|
CompletableFuture<List<PiTableEntry>> dumpTables(
|
||||||
PiTableId tableId, PiPipeconf pipeconf);
|
Set<PiTableId> tableIds, boolean defaultEntries, PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps entries from all tables, for the given pipeconf.
|
* Dumps entries from all tables, for the given pipeconf.
|
||||||
*
|
*
|
||||||
* @param pipeconf pipeconf currently deployed on the device
|
* @param pipeconf pipeconf currently deployed on the device
|
||||||
* @return completable future of a collection of table entries
|
* @return completable future of a list of table entries
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiTableEntry>> dumpAllTables(PiPipeconf pipeconf);
|
CompletableFuture<List<PiTableEntry>> dumpAllTables(PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a packet-out operation for the given pipeconf.
|
* Executes a packet-out operation for the given pipeconf.
|
||||||
@ -171,34 +176,33 @@ public interface P4RuntimeClient {
|
|||||||
*
|
*
|
||||||
* @param counterIds counter identifiers
|
* @param counterIds counter identifiers
|
||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of counter data
|
* @return list of counter data
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiCounterCellData>> readAllCounterCells(
|
CompletableFuture<List<PiCounterCellData>> readAllCounterCells(
|
||||||
Set<PiCounterId> counterIds, PiPipeconf pipeconf);
|
Set<PiCounterId> counterIds, PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a collection of counter data corresponding to the given set of
|
* Returns a list of counter data corresponding to the given set of counter
|
||||||
* counter cell identifiers, for the given pipeconf.
|
* cell identifiers, for the given pipeconf.
|
||||||
*
|
*
|
||||||
* @param cellIds set of counter cell identifiers
|
* @param cellIds set of counter cell identifiers
|
||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of counter data
|
* @return list of counter data
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiCounterCellData>> readCounterCells(
|
CompletableFuture<List<PiCounterCellData>> readCounterCells(
|
||||||
Set<PiCounterCellId> cellIds, PiPipeconf pipeconf);
|
Set<PiCounterCellId> cellIds, PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the given write operation for the given action group members and
|
* Performs the given write operation for the given action group members and
|
||||||
* pipeconf.
|
* pipeconf.
|
||||||
*
|
*
|
||||||
* @param profileId action group profile ID
|
* @param members action group members
|
||||||
* @param members action group members
|
* @param opType write operation type
|
||||||
* @param opType write operation type
|
* @param pipeconf the pipeconf currently deployed on the device
|
||||||
* @param pipeconf the pipeconf currently deployed on the device
|
|
||||||
* @return true if the operation was successful, false otherwise
|
* @return true if the operation was successful, false otherwise
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> writeActionGroupMembers(
|
CompletableFuture<Boolean> writeActionGroupMembers(
|
||||||
PiActionProfileId profileId, Collection<PiActionGroupMember> members,
|
List<PiActionGroupMember> members,
|
||||||
WriteOperationType opType, PiPipeconf pipeconf);
|
WriteOperationType opType, PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,31 +222,55 @@ public interface P4RuntimeClient {
|
|||||||
*
|
*
|
||||||
* @param actionProfileId the action profile id
|
* @param actionProfileId the action profile id
|
||||||
* @param pipeconf the pipeconf currently deployed on the device
|
* @param pipeconf the pipeconf currently deployed on the device
|
||||||
* @return completable future of a collection of groups
|
* @return completable future of a list of groups
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiActionGroup>> dumpGroups(
|
CompletableFuture<List<PiActionGroup>> dumpGroups(
|
||||||
PiActionProfileId actionProfileId, PiPipeconf pipeconf);
|
PiActionProfileId actionProfileId, PiPipeconf pipeconf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dumps all action profile member IDs for a given action profile.
|
||||||
|
*
|
||||||
|
* @param actionProfileId action profile ID
|
||||||
|
* @param pipeconf pipeconf
|
||||||
|
* @return future of list of action profile member ID
|
||||||
|
*/
|
||||||
|
CompletableFuture<List<PiActionGroupMemberId>> dumpActionProfileMemberIds(
|
||||||
|
PiActionProfileId actionProfileId, PiPipeconf pipeconf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given members from the given action profile. Returns the list
|
||||||
|
* of successfully removed members.
|
||||||
|
*
|
||||||
|
* @param actionProfileId action profile ID
|
||||||
|
* @param memberIds member IDs
|
||||||
|
* @param pipeconf pipeconf
|
||||||
|
* @return list of member IDs that were successfully removed from the device
|
||||||
|
*/
|
||||||
|
CompletableFuture<List<PiActionGroupMemberId>> removeActionProfileMembers(
|
||||||
|
PiActionProfileId actionProfileId,
|
||||||
|
List<PiActionGroupMemberId> memberIds,
|
||||||
|
PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the configuration of all meter cells for the given set of meter
|
* Returns the configuration of all meter cells for the given set of meter
|
||||||
* identifiers and pipeconf.
|
* identifiers and pipeconf.
|
||||||
*
|
*
|
||||||
* @param meterIds meter identifiers
|
* @param meterIds meter identifiers
|
||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of meter configurations
|
* @return list of meter configurations
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiMeterCellConfig>> readAllMeterCells(
|
CompletableFuture<List<PiMeterCellConfig>> readAllMeterCells(
|
||||||
Set<PiMeterId> meterIds, PiPipeconf pipeconf);
|
Set<PiMeterId> meterIds, PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a collection of meter configurations corresponding to the given
|
* Returns a list of meter configurations corresponding to the given set of
|
||||||
* set of meter cell identifiers, for the given pipeconf.
|
* meter cell identifiers, for the given pipeconf.
|
||||||
*
|
*
|
||||||
* @param cellIds set of meter cell identifiers
|
* @param cellIds set of meter cell identifiers
|
||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of meter configrations
|
* @return list of meter configrations
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiMeterCellConfig>> readMeterCells(
|
CompletableFuture<List<PiMeterCellConfig>> readMeterCells(
|
||||||
Set<PiMeterCellId> cellIds, PiPipeconf pipeconf);
|
Set<PiMeterCellId> cellIds, PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -254,7 +282,7 @@ public interface P4RuntimeClient {
|
|||||||
* @return true if the operation was successful, false otherwise.
|
* @return true if the operation was successful, false otherwise.
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> writeMeterCells(
|
CompletableFuture<Boolean> writeMeterCells(
|
||||||
Collection<PiMeterCellConfig> cellConfigs, PiPipeconf pipeconf);
|
List<PiMeterCellConfig> cellConfigs, PiPipeconf pipeconf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the given write operation for the given PI multicast groups
|
* Performs the given write operation for the given PI multicast groups
|
||||||
@ -265,7 +293,7 @@ public interface P4RuntimeClient {
|
|||||||
* @return true if the operation was successful, false otherwise
|
* @return true if the operation was successful, false otherwise
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> writePreMulticastGroupEntries(
|
CompletableFuture<Boolean> writePreMulticastGroupEntries(
|
||||||
Collection<PiMulticastGroupEntry> entries,
|
List<PiMulticastGroupEntry> entries,
|
||||||
WriteOperationType opType);
|
WriteOperationType opType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -273,5 +301,5 @@ public interface P4RuntimeClient {
|
|||||||
*
|
*
|
||||||
* @return multicast groups
|
* @return multicast groups
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Collection<PiMulticastGroupEntry>> readAllMulticastGroupEntries();
|
CompletableFuture<List<PiMulticastGroupEntry>> readAllMulticastGroupEntries();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,10 +21,10 @@ import org.onosproject.net.pi.model.PiActionProfileId;
|
|||||||
import org.onosproject.net.pi.model.PiPipeconf;
|
import org.onosproject.net.pi.model.PiPipeconf;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroup;
|
import org.onosproject.net.pi.runtime.PiActionGroup;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupId;
|
import org.onosproject.net.pi.runtime.PiActionGroupId;
|
||||||
|
import p4.config.v1.P4InfoOuterClass;
|
||||||
import p4.v1.P4RuntimeOuterClass.ActionProfileGroup;
|
import p4.v1.P4RuntimeOuterClass.ActionProfileGroup;
|
||||||
import p4.v1.P4RuntimeOuterClass.ActionProfileGroup.Member;
|
import p4.v1.P4RuntimeOuterClass.ActionProfileGroup.Member;
|
||||||
import p4.v1.P4RuntimeOuterClass.ActionProfileMember;
|
import p4.v1.P4RuntimeOuterClass.ActionProfileMember;
|
||||||
import p4.config.v1.P4InfoOuterClass;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -36,6 +36,8 @@ import static java.lang.String.format;
|
|||||||
*/
|
*/
|
||||||
final class ActionProfileGroupEncoder {
|
final class ActionProfileGroupEncoder {
|
||||||
|
|
||||||
|
private static final int GROUP_SIZE_ADDITIONAL_MEMBERS = 10;
|
||||||
|
|
||||||
private ActionProfileGroupEncoder() {
|
private ActionProfileGroupEncoder() {
|
||||||
// hide default constructor
|
// hide default constructor
|
||||||
}
|
}
|
||||||
@ -44,10 +46,12 @@ final class ActionProfileGroupEncoder {
|
|||||||
* Encode a PI action group to a action profile group.
|
* Encode a PI action group to a action profile group.
|
||||||
*
|
*
|
||||||
* @param piActionGroup the action profile group
|
* @param piActionGroup the action profile group
|
||||||
* @param pipeconf the pipeconf
|
* @param pipeconf the pipeconf
|
||||||
* @return a action profile group encoded from PI action group
|
* @return a action profile group encoded from PI action group
|
||||||
* @throws P4InfoBrowser.NotFoundException if can't find action profile from P4Info browser
|
* @throws P4InfoBrowser.NotFoundException if can't find action profile from
|
||||||
* @throws EncodeException if can't find P4Info from pipeconf
|
* P4Info browser
|
||||||
|
* @throws EncodeException if can't find P4Info from
|
||||||
|
* pipeconf
|
||||||
*/
|
*/
|
||||||
static ActionProfileGroup encode(PiActionGroup piActionGroup, PiPipeconf pipeconf)
|
static ActionProfileGroup encode(PiActionGroup piActionGroup, PiPipeconf pipeconf)
|
||||||
throws P4InfoBrowser.NotFoundException, EncodeException {
|
throws P4InfoBrowser.NotFoundException, EncodeException {
|
||||||
@ -62,8 +66,8 @@ final class ActionProfileGroupEncoder {
|
|||||||
.getByName(piActionProfileId.id());
|
.getByName(piActionProfileId.id());
|
||||||
int actionProfileId = actionProfile.getPreamble().getId();
|
int actionProfileId = actionProfile.getPreamble().getId();
|
||||||
ActionProfileGroup.Builder actionProfileGroupBuilder = ActionProfileGroup.newBuilder()
|
ActionProfileGroup.Builder actionProfileGroupBuilder = ActionProfileGroup.newBuilder()
|
||||||
.setGroupId(piActionGroup.id().id())
|
.setGroupId(piActionGroup.id().id())
|
||||||
.setActionProfileId(actionProfileId);
|
.setActionProfileId(actionProfileId);
|
||||||
|
|
||||||
piActionGroup.members().forEach(m -> {
|
piActionGroup.members().forEach(m -> {
|
||||||
// TODO: currently we don't set "watch" field of member
|
// TODO: currently we don't set "watch" field of member
|
||||||
@ -74,20 +78,31 @@ final class ActionProfileGroupEncoder {
|
|||||||
actionProfileGroupBuilder.addMembers(member);
|
actionProfileGroupBuilder.addMembers(member);
|
||||||
});
|
});
|
||||||
|
|
||||||
actionProfileGroupBuilder.setMaxSize(piActionGroup.members().size());
|
// FIXME: ONOS-7797 Make this configurable, or find a different way of
|
||||||
|
// supporting group modify. In P4Runtime, group size cannot be modified
|
||||||
|
// once the group is created. To allow adding members to an existing
|
||||||
|
// group we set max_size to support an additional number of members
|
||||||
|
// other than the one already defined in the PI group. Clearly, this
|
||||||
|
// will break if we try to add more than GROUP_SIZE_ADDITIONAL_MEMBERS
|
||||||
|
// to the same group.
|
||||||
|
actionProfileGroupBuilder.setMaxSize(
|
||||||
|
piActionGroup.members().size() + GROUP_SIZE_ADDITIONAL_MEMBERS);
|
||||||
|
|
||||||
return actionProfileGroupBuilder.build();
|
return actionProfileGroupBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode an action profile group with members information to a PI action group.
|
* Decode an action profile group with members information to a PI action
|
||||||
|
* group.
|
||||||
*
|
*
|
||||||
* @param actionProfileGroup the action profile group
|
* @param actionProfileGroup the action profile group
|
||||||
* @param members members of the action profile group
|
* @param members members of the action profile group
|
||||||
* @param pipeconf the pipeconf
|
* @param pipeconf the pipeconf
|
||||||
* @return decoded PI action group
|
* @return decoded PI action group
|
||||||
* @throws P4InfoBrowser.NotFoundException if can't find action profile from P4Info browser
|
* @throws P4InfoBrowser.NotFoundException if can't find action profile from
|
||||||
* @throws EncodeException if can't find P4Info from pipeconf
|
* P4Info browser
|
||||||
|
* @throws EncodeException if can't find P4Info from
|
||||||
|
* pipeconf
|
||||||
*/
|
*/
|
||||||
static PiActionGroup decode(ActionProfileGroup actionProfileGroup,
|
static PiActionGroup decode(ActionProfileGroup actionProfileGroup,
|
||||||
Collection<ActionProfileMember> members,
|
Collection<ActionProfileMember> members,
|
||||||
|
|||||||
@ -39,16 +39,14 @@ final class ActionProfileMemberEncoder {
|
|||||||
/**
|
/**
|
||||||
* Encode a PiActionGroupMember to a ActionProfileMember.
|
* Encode a PiActionGroupMember to a ActionProfileMember.
|
||||||
*
|
*
|
||||||
* @param profileId the PI action group profile ID of members
|
* @param member the member to encode
|
||||||
* @param member the member to encode
|
* @param pipeconf the pipeconf, as encode spec
|
||||||
* @param pipeconf the pipeconf, as encode spec
|
|
||||||
* @return encoded member
|
* @return encoded member
|
||||||
* @throws P4InfoBrowser.NotFoundException can't find action profile from
|
* @throws P4InfoBrowser.NotFoundException can't find action profile from
|
||||||
* P4Info browser
|
* P4Info browser
|
||||||
* @throws EncodeException can't find P4Info from pipeconf
|
* @throws EncodeException can't find P4Info from pipeconf
|
||||||
*/
|
*/
|
||||||
static ActionProfileMember encode(PiActionProfileId profileId,
|
static ActionProfileMember encode(PiActionGroupMember member,
|
||||||
PiActionGroupMember member,
|
|
||||||
PiPipeconf pipeconf)
|
PiPipeconf pipeconf)
|
||||||
throws P4InfoBrowser.NotFoundException, EncodeException {
|
throws P4InfoBrowser.NotFoundException, EncodeException {
|
||||||
|
|
||||||
@ -66,7 +64,7 @@ final class ActionProfileMemberEncoder {
|
|||||||
|
|
||||||
// action profile id
|
// action profile id
|
||||||
P4InfoOuterClass.ActionProfile actionProfile =
|
P4InfoOuterClass.ActionProfile actionProfile =
|
||||||
browser.actionProfiles().getByName(profileId.id());
|
browser.actionProfiles().getByName(member.actionProfile().id());
|
||||||
|
|
||||||
int actionProfileId = actionProfile.getPreamble().getId();
|
int actionProfileId = actionProfile.getPreamble().getId();
|
||||||
actionProfileMemberBuilder.setActionProfileId(actionProfileId);
|
actionProfileMemberBuilder.setActionProfileId(actionProfileId);
|
||||||
@ -95,11 +93,19 @@ final class ActionProfileMemberEncoder {
|
|||||||
PiPipeconf pipeconf)
|
PiPipeconf pipeconf)
|
||||||
throws P4InfoBrowser.NotFoundException, EncodeException {
|
throws P4InfoBrowser.NotFoundException, EncodeException {
|
||||||
P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
|
||||||
if (browser == null) {
|
if (browser == null) {
|
||||||
throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
|
throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
|
||||||
}
|
}
|
||||||
return PiActionGroupMember.builder().withId(PiActionGroupMemberId.of(member.getMemberId()))
|
|
||||||
|
final PiActionProfileId actionProfileId = PiActionProfileId.of(
|
||||||
|
browser.actionProfiles()
|
||||||
|
.getById(member.getActionProfileId())
|
||||||
|
.getPreamble()
|
||||||
|
.getName());
|
||||||
|
|
||||||
|
return PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(actionProfileId)
|
||||||
|
.withId(PiActionGroupMemberId.of(member.getMemberId()))
|
||||||
.withWeight(weight)
|
.withWeight(weight)
|
||||||
.withAction(decodeActionMsg(member.getAction(), browser))
|
.withAction(decodeActionMsg(member.getAction(), browser))
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@ -30,8 +30,8 @@ import p4.v1.P4RuntimeOuterClass.CounterEntry;
|
|||||||
import p4.v1.P4RuntimeOuterClass.DirectCounterEntry;
|
import p4.v1.P4RuntimeOuterClass.DirectCounterEntry;
|
||||||
import p4.v1.P4RuntimeOuterClass.Entity;
|
import p4.v1.P4RuntimeOuterClass.Entity;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ final class CounterEntryCodec {
|
|||||||
* @return collection of entity messages describing both counter or direct
|
* @return collection of entity messages describing both counter or direct
|
||||||
* counter entries
|
* counter entries
|
||||||
*/
|
*/
|
||||||
static Collection<Entity> encodePiCounterCellIds(Collection<PiCounterCellId> cellIds,
|
static List<Entity> encodePiCounterCellIds(List<PiCounterCellId> cellIds,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
|
|
||||||
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
@ -100,7 +100,7 @@ final class CounterEntryCodec {
|
|||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of entity messages
|
* @return collection of entity messages
|
||||||
*/
|
*/
|
||||||
static Collection<Entity> readAllCellsEntities(Collection<PiCounterId> counterIds,
|
static List<Entity> readAllCellsEntities(List<PiCounterId> counterIds,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
|
||||||
@ -135,8 +135,8 @@ final class CounterEntryCodec {
|
|||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of PI counter cell data
|
* @return collection of PI counter cell data
|
||||||
*/
|
*/
|
||||||
static Collection<PiCounterCellData> decodeCounterEntities(Collection<Entity> entities,
|
static List<PiCounterCellData> decodeCounterEntities(List<Entity> entities,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
|
|
||||||
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
|
||||||
|
|||||||
@ -31,8 +31,8 @@ import p4.v1.P4RuntimeOuterClass.Entity;
|
|||||||
import p4.v1.P4RuntimeOuterClass.MeterConfig;
|
import p4.v1.P4RuntimeOuterClass.MeterConfig;
|
||||||
import p4.v1.P4RuntimeOuterClass.MeterEntry;
|
import p4.v1.P4RuntimeOuterClass.MeterEntry;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ final class MeterEntryCodec {
|
|||||||
* @return collection of entity messages describing both meter or direct
|
* @return collection of entity messages describing both meter or direct
|
||||||
* meter entries
|
* meter entries
|
||||||
*/
|
*/
|
||||||
static Collection<Entity> encodePiMeterCellConfigs(Collection<PiMeterCellConfig> cellConfigs,
|
static List<Entity> encodePiMeterCellConfigs(List<PiMeterCellConfig> cellConfigs,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ final class MeterEntryCodec {
|
|||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of entity messages
|
* @return collection of entity messages
|
||||||
*/
|
*/
|
||||||
static Collection<Entity> readAllCellsEntities(Collection<PiMeterId> meterIds,
|
static List<Entity> readAllCellsEntities(List<PiMeterId> meterIds,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
|
||||||
@ -136,8 +136,8 @@ final class MeterEntryCodec {
|
|||||||
* @param pipeconf pipeconf
|
* @param pipeconf pipeconf
|
||||||
* @return collection of PI meter cell data
|
* @return collection of PI meter cell data
|
||||||
*/
|
*/
|
||||||
static Collection<PiMeterCellConfig> decodeMeterEntities(Collection<Entity> entities,
|
static List<PiMeterCellConfig> decodeMeterEntities(List<Entity> entities,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
|
||||||
if (browser == null) {
|
if (browser == null) {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.google.common.collect.HashMultimap;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import io.grpc.Context;
|
import io.grpc.Context;
|
||||||
@ -30,7 +31,6 @@ import io.grpc.StatusRuntimeException;
|
|||||||
import io.grpc.protobuf.lite.ProtoLiteUtils;
|
import io.grpc.protobuf.lite.ProtoLiteUtils;
|
||||||
import io.grpc.stub.ClientCallStreamObserver;
|
import io.grpc.stub.ClientCallStreamObserver;
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.onlab.osgi.DefaultServiceDirectory;
|
import org.onlab.osgi.DefaultServiceDirectory;
|
||||||
import org.onlab.util.SharedExecutors;
|
import org.onlab.util.SharedExecutors;
|
||||||
import org.onlab.util.Tools;
|
import org.onlab.util.Tools;
|
||||||
@ -42,9 +42,9 @@ import org.onosproject.net.pi.model.PiPipeconf;
|
|||||||
import org.onosproject.net.pi.model.PiTableId;
|
import org.onosproject.net.pi.model.PiTableId;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroup;
|
import org.onosproject.net.pi.runtime.PiActionGroup;
|
||||||
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
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.PiCounterCellData;
|
||||||
import org.onosproject.net.pi.runtime.PiCounterCellId;
|
import org.onosproject.net.pi.runtime.PiCounterCellId;
|
||||||
import org.onosproject.net.pi.runtime.PiEntity;
|
|
||||||
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
|
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
|
||||||
import org.onosproject.net.pi.runtime.PiMeterCellId;
|
import org.onosproject.net.pi.runtime.PiMeterCellId;
|
||||||
import org.onosproject.net.pi.runtime.PiMulticastGroupEntry;
|
import org.onosproject.net.pi.runtime.PiMulticastGroupEntry;
|
||||||
@ -80,7 +80,6 @@ import p4.v1.P4RuntimeOuterClass.WriteRequest;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -101,6 +100,7 @@ import java.util.stream.StreamSupport;
|
|||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
import static org.onlab.util.Tools.groupedThreads;
|
import static org.onlab.util.Tools.groupedThreads;
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
import static p4.v1.P4RuntimeOuterClass.Entity.EntityCase.ACTION_PROFILE_GROUP;
|
import static p4.v1.P4RuntimeOuterClass.Entity.EntityCase.ACTION_PROFILE_GROUP;
|
||||||
@ -257,20 +257,22 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> writeTableEntries(Collection<PiTableEntry> piTableEntries,
|
public CompletableFuture<Boolean> writeTableEntries(List<PiTableEntry> piTableEntries,
|
||||||
WriteOperationType opType, PiPipeconf pipeconf) {
|
WriteOperationType opType, PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doWriteTableEntries(piTableEntries, opType, pipeconf),
|
return supplyInContext(() -> doWriteTableEntries(piTableEntries, opType, pipeconf),
|
||||||
"writeTableEntries-" + opType.name());
|
"writeTableEntries-" + opType.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiTableEntry>> dumpTable(PiTableId piTableId, PiPipeconf pipeconf) {
|
public CompletableFuture<List<PiTableEntry>> dumpTables(
|
||||||
return supplyInContext(() -> doDumpTable(piTableId, pipeconf), "dumpTable-" + piTableId);
|
Set<PiTableId> piTableIds, boolean defaultEntries, PiPipeconf pipeconf) {
|
||||||
|
return supplyInContext(() -> doDumpTables(piTableIds, defaultEntries, pipeconf),
|
||||||
|
"dumpTables-" + piTableIds.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiTableEntry>> dumpAllTables(PiPipeconf pipeconf) {
|
public CompletableFuture<List<PiTableEntry>> dumpAllTables(PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doDumpTable(null, pipeconf), "dumpAllTables");
|
return supplyInContext(() -> doDumpTables(null, false, pipeconf), "dumpAllTables");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -279,25 +281,24 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiCounterCellData>> readCounterCells(Set<PiCounterCellId> cellIds,
|
public CompletableFuture<List<PiCounterCellData>> readCounterCells(Set<PiCounterCellId> cellIds,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doReadCounterCells(cellIds, pipeconf),
|
return supplyInContext(() -> doReadCounterCells(Lists.newArrayList(cellIds), pipeconf),
|
||||||
"readCounterCells-" + cellIds.hashCode());
|
"readCounterCells-" + cellIds.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiCounterCellData>> readAllCounterCells(Set<PiCounterId> counterIds,
|
public CompletableFuture<List<PiCounterCellData>> readAllCounterCells(Set<PiCounterId> counterIds,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doReadAllCounterCells(counterIds, pipeconf),
|
return supplyInContext(() -> doReadAllCounterCells(Lists.newArrayList(counterIds), pipeconf),
|
||||||
"readAllCounterCells-" + counterIds.hashCode());
|
"readAllCounterCells-" + counterIds.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> writeActionGroupMembers(PiActionProfileId profileId,
|
public CompletableFuture<Boolean> writeActionGroupMembers(List<PiActionGroupMember> members,
|
||||||
Collection<PiActionGroupMember> members,
|
|
||||||
WriteOperationType opType,
|
WriteOperationType opType,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doWriteActionGroupMembers(profileId, members, opType, pipeconf),
|
return supplyInContext(() -> doWriteActionGroupMembers(members, opType, pipeconf),
|
||||||
"writeActionGroupMembers-" + opType.name());
|
"writeActionGroupMembers-" + opType.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,14 +312,31 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiActionGroup>> dumpGroups(PiActionProfileId actionProfileId,
|
public CompletableFuture<List<PiActionGroup>> dumpGroups(PiActionProfileId actionProfileId,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doDumpGroups(actionProfileId, pipeconf),
|
return supplyInContext(() -> doDumpGroups(actionProfileId, pipeconf),
|
||||||
"dumpGroups-" + actionProfileId.id());
|
"dumpGroups-" + actionProfileId.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> writeMeterCells(Collection<PiMeterCellConfig> cellIds, PiPipeconf pipeconf) {
|
public CompletableFuture<List<PiActionGroupMemberId>> dumpActionProfileMemberIds(
|
||||||
|
PiActionProfileId actionProfileId, PiPipeconf pipeconf) {
|
||||||
|
return supplyInContext(() -> doDumpActionProfileMemberIds(actionProfileId, pipeconf),
|
||||||
|
"dumpActionProfileMemberIds-" + actionProfileId.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<PiActionGroupMemberId>> removeActionProfileMembers(
|
||||||
|
PiActionProfileId actionProfileId,
|
||||||
|
List<PiActionGroupMemberId> memberIds,
|
||||||
|
PiPipeconf pipeconf) {
|
||||||
|
return supplyInContext(
|
||||||
|
() -> doRemoveActionProfileMembers(actionProfileId, memberIds, pipeconf),
|
||||||
|
"cleanupActionProfileMembers-" + actionProfileId.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Boolean> writeMeterCells(List<PiMeterCellConfig> cellIds, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
return supplyInContext(() -> doWriteMeterCells(cellIds, pipeconf),
|
return supplyInContext(() -> doWriteMeterCells(cellIds, pipeconf),
|
||||||
"writeMeterCells");
|
"writeMeterCells");
|
||||||
@ -326,29 +344,29 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> writePreMulticastGroupEntries(
|
public CompletableFuture<Boolean> writePreMulticastGroupEntries(
|
||||||
Collection<PiMulticastGroupEntry> entries,
|
List<PiMulticastGroupEntry> entries,
|
||||||
WriteOperationType opType) {
|
WriteOperationType opType) {
|
||||||
return supplyInContext(() -> doWriteMulticastGroupEntries(entries, opType),
|
return supplyInContext(() -> doWriteMulticastGroupEntries(entries, opType),
|
||||||
"writePreMulticastGroupEntries");
|
"writePreMulticastGroupEntries");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiMulticastGroupEntry>> readAllMulticastGroupEntries() {
|
public CompletableFuture<List<PiMulticastGroupEntry>> readAllMulticastGroupEntries() {
|
||||||
return supplyInContext(this::doReadAllMulticastGroupEntries,
|
return supplyInContext(this::doReadAllMulticastGroupEntries,
|
||||||
"readAllMulticastGroupEntries");
|
"readAllMulticastGroupEntries");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiMeterCellConfig>> readMeterCells(Set<PiMeterCellId> cellIds,
|
public CompletableFuture<List<PiMeterCellConfig>> readMeterCells(Set<PiMeterCellId> cellIds,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doReadMeterCells(cellIds, pipeconf),
|
return supplyInContext(() -> doReadMeterCells(Lists.newArrayList(cellIds), pipeconf),
|
||||||
"readMeterCells-" + cellIds.hashCode());
|
"readMeterCells-" + cellIds.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Collection<PiMeterCellConfig>> readAllMeterCells(Set<PiMeterId> meterIds,
|
public CompletableFuture<List<PiMeterCellConfig>> readAllMeterCells(Set<PiMeterId> meterIds,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
return supplyInContext(() -> doReadAllMeterCells(meterIds, pipeconf),
|
return supplyInContext(() -> doReadAllMeterCells(Lists.newArrayList(meterIds), pipeconf),
|
||||||
"readAllMeterCells-" + meterIds.hashCode());
|
"readAllMeterCells-" + meterIds.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,13 +506,13 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doWriteTableEntries(Collection<PiTableEntry> piTableEntries, WriteOperationType opType,
|
private boolean doWriteTableEntries(List<PiTableEntry> piTableEntries, WriteOperationType opType,
|
||||||
PiPipeconf pipeconf) {
|
PiPipeconf pipeconf) {
|
||||||
if (piTableEntries.size() == 0) {
|
if (piTableEntries.size() == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<Update> updateMsgs;
|
List<Update> updateMsgs;
|
||||||
try {
|
try {
|
||||||
updateMsgs = TableEntryEncoder.encode(piTableEntries, pipeconf)
|
updateMsgs = TableEntryEncoder.encode(piTableEntries, pipeconf)
|
||||||
.stream()
|
.stream()
|
||||||
@ -515,43 +533,53 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return write(updateMsgs, piTableEntries, opType, "table entry");
|
return write(updateMsgs, piTableEntries, opType, "table entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiTableEntry> doDumpTable(PiTableId piTableId, PiPipeconf pipeconf) {
|
private List<PiTableEntry> doDumpTables(
|
||||||
|
Set<PiTableId> piTableIds, boolean defaultEntries, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
log.debug("Dumping table {} from {} (pipeconf {})...", piTableId, deviceId, pipeconf.id());
|
log.debug("Dumping tables {} from {} (pipeconf {})...",
|
||||||
|
piTableIds, deviceId, pipeconf.id());
|
||||||
|
|
||||||
int tableId;
|
Set<Integer> tableIds = Sets.newHashSet();
|
||||||
if (piTableId == null) {
|
if (piTableIds == null) {
|
||||||
// Dump all tables.
|
// Dump all tables.
|
||||||
tableId = 0;
|
tableIds.add(0);
|
||||||
} else {
|
} else {
|
||||||
P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
if (browser == null) {
|
if (browser == null) {
|
||||||
log.warn("Unable to get a P4Info browser for pipeconf {}", pipeconf);
|
log.warn("Unable to get a P4Info browser for pipeconf {}", pipeconf);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
try {
|
piTableIds.forEach(piTableId -> {
|
||||||
tableId = browser.tables().getByName(piTableId.id()).getPreamble().getId();
|
try {
|
||||||
} catch (P4InfoBrowser.NotFoundException e) {
|
tableIds.add(browser.tables().getByName(piTableId.id()).getPreamble().getId());
|
||||||
log.warn("Unable to dump table: {}", e.getMessage());
|
} catch (P4InfoBrowser.NotFoundException e) {
|
||||||
return Collections.emptyList();
|
log.warn("Unable to dump table {}: {}", piTableId, e.getMessage());
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadRequest requestMsg = ReadRequest.newBuilder()
|
if (tableIds.isEmpty()) {
|
||||||
.setDeviceId(p4DeviceId)
|
return Collections.emptyList();
|
||||||
.addEntities(Entity.newBuilder()
|
}
|
||||||
.setTableEntry(TableEntry.newBuilder()
|
|
||||||
.setTableId(tableId)
|
ReadRequest.Builder requestMsgBuilder = ReadRequest.newBuilder()
|
||||||
.build())
|
.setDeviceId(p4DeviceId);
|
||||||
.build())
|
tableIds.forEach(tableId -> requestMsgBuilder.addEntities(
|
||||||
.build();
|
Entity.newBuilder()
|
||||||
|
.setTableEntry(
|
||||||
|
TableEntry.newBuilder()
|
||||||
|
.setTableId(tableId)
|
||||||
|
.setIsDefaultAction(defaultEntries)
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
|
||||||
Iterator<ReadResponse> responses;
|
Iterator<ReadResponse> responses;
|
||||||
try {
|
try {
|
||||||
responses = blockingStub.read(requestMsg);
|
responses = blockingStub.read(requestMsgBuilder.build());
|
||||||
} catch (StatusRuntimeException e) {
|
} catch (StatusRuntimeException e) {
|
||||||
checkGrpcException(e);
|
checkGrpcException(e);
|
||||||
log.warn("Unable to dump table {} from {}: {}", piTableId, deviceId, e.getMessage());
|
log.warn("Unable to dump tables from {}: {}", deviceId, e.getMessage());
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,7 +592,8 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
.map(Entity::getTableEntry)
|
.map(Entity::getTableEntry)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
log.debug("Retrieved {} entries from table {} on {}...", tableEntryMsgs.size(), piTableId, deviceId);
|
log.debug("Retrieved {} entries from {} tables on {}...",
|
||||||
|
tableEntryMsgs.size(), tableIds.size(), deviceId);
|
||||||
|
|
||||||
return TableEntryEncoder.decode(tableEntryMsgs, pipeconf);
|
return TableEntryEncoder.decode(tableEntryMsgs, pipeconf);
|
||||||
}
|
}
|
||||||
@ -633,22 +662,22 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
isClientMaster.set(isMaster);
|
isClientMaster.set(isMaster);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiCounterCellData> doReadAllCounterCells(
|
private List<PiCounterCellData> doReadAllCounterCells(
|
||||||
Collection<PiCounterId> counterIds, PiPipeconf pipeconf) {
|
List<PiCounterId> counterIds, PiPipeconf pipeconf) {
|
||||||
return doReadCounterEntities(
|
return doReadCounterEntities(
|
||||||
CounterEntryCodec.readAllCellsEntities(counterIds, pipeconf),
|
CounterEntryCodec.readAllCellsEntities(counterIds, pipeconf),
|
||||||
pipeconf);
|
pipeconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiCounterCellData> doReadCounterCells(
|
private List<PiCounterCellData> doReadCounterCells(
|
||||||
Collection<PiCounterCellId> cellIds, PiPipeconf pipeconf) {
|
List<PiCounterCellId> cellIds, PiPipeconf pipeconf) {
|
||||||
return doReadCounterEntities(
|
return doReadCounterEntities(
|
||||||
CounterEntryCodec.encodePiCounterCellIds(cellIds, pipeconf),
|
CounterEntryCodec.encodePiCounterCellIds(cellIds, pipeconf),
|
||||||
pipeconf);
|
pipeconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiCounterCellData> doReadCounterEntities(
|
private List<PiCounterCellData> doReadCounterEntities(
|
||||||
Collection<Entity> counterEntities, PiPipeconf pipeconf) {
|
List<Entity> counterEntities, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
if (counterEntities.size() == 0) {
|
if (counterEntities.size() == 0) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@ -676,13 +705,13 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return CounterEntryCodec.decodeCounterEntities(entities, pipeconf);
|
return CounterEntryCodec.decodeCounterEntities(entities, pipeconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doWriteActionGroupMembers(PiActionProfileId profileId, Collection<PiActionGroupMember> members,
|
private boolean doWriteActionGroupMembers(List<PiActionGroupMember> members,
|
||||||
WriteOperationType opType, PiPipeconf pipeconf) {
|
WriteOperationType opType, PiPipeconf pipeconf) {
|
||||||
final Collection<ActionProfileMember> actionProfileMembers = Lists.newArrayList();
|
final List<ActionProfileMember> actionProfileMembers = Lists.newArrayList();
|
||||||
|
|
||||||
for (PiActionGroupMember member : members) {
|
for (PiActionGroupMember member : members) {
|
||||||
try {
|
try {
|
||||||
actionProfileMembers.add(ActionProfileMemberEncoder.encode(profileId, member, pipeconf));
|
actionProfileMembers.add(ActionProfileMemberEncoder.encode(member, pipeconf));
|
||||||
} catch (EncodeException | P4InfoBrowser.NotFoundException e) {
|
} catch (EncodeException | P4InfoBrowser.NotFoundException e) {
|
||||||
log.warn("Unable to encode group member, aborting {} operation: {} [{}]",
|
log.warn("Unable to encode group member, aborting {} operation: {} [{}]",
|
||||||
opType.name(), e.getMessage(), member.toString());
|
opType.name(), e.getMessage(), member.toString());
|
||||||
@ -690,7 +719,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Collection<Update> updateMsgs = actionProfileMembers.stream()
|
final List<Update> updateMsgs = actionProfileMembers.stream()
|
||||||
.map(actionProfileMember ->
|
.map(actionProfileMember ->
|
||||||
Update.newBuilder()
|
Update.newBuilder()
|
||||||
.setEntity(Entity.newBuilder()
|
.setEntity(Entity.newBuilder()
|
||||||
@ -708,14 +737,14 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return write(updateMsgs, members, opType, "group member");
|
return write(updateMsgs, members, opType, "group member");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiActionGroup> doDumpGroups(PiActionProfileId piActionProfileId, PiPipeconf pipeconf) {
|
private List<PiActionGroup> doDumpGroups(PiActionProfileId piActionProfileId, PiPipeconf pipeconf) {
|
||||||
log.debug("Dumping groups from action profile {} from {} (pipeconf {})...",
|
log.debug("Dumping groups from action profile {} from {} (pipeconf {})...",
|
||||||
piActionProfileId.id(), deviceId, pipeconf.id());
|
piActionProfileId.id(), deviceId, pipeconf.id());
|
||||||
|
|
||||||
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
if (browser == null) {
|
if (browser == null) {
|
||||||
log.warn("Unable to get a P4Info browser for pipeconf {}, aborting dump action profile", pipeconf);
|
log.warn("Unable to get a P4Info browser for pipeconf {}, aborting dump action profile", pipeconf);
|
||||||
return Collections.emptySet();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
final int actionProfileId;
|
final int actionProfileId;
|
||||||
@ -727,7 +756,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
.getId();
|
.getId();
|
||||||
} catch (P4InfoBrowser.NotFoundException e) {
|
} catch (P4InfoBrowser.NotFoundException e) {
|
||||||
log.warn("Unable to dump groups: {}", e.getMessage());
|
log.warn("Unable to dump groups: {}", e.getMessage());
|
||||||
return Collections.emptySet();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare read request to read all groups from the given action profile.
|
// Prepare read request to read all groups from the given action profile.
|
||||||
@ -748,7 +777,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
} catch (StatusRuntimeException e) {
|
} catch (StatusRuntimeException e) {
|
||||||
checkGrpcException(e);
|
checkGrpcException(e);
|
||||||
log.warn("Unable to dump action profile {} from {}: {}", piActionProfileId, deviceId, e.getMessage());
|
log.warn("Unable to dump action profile {} from {}: {}", piActionProfileId, deviceId, e.getMessage());
|
||||||
return Collections.emptySet();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ActionProfileGroup> groupMsgs = Tools.stream(() -> groupResponses)
|
final List<ActionProfileGroup> groupMsgs = Tools.stream(() -> groupResponses)
|
||||||
@ -833,6 +862,104 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<PiActionGroupMemberId> doDumpActionProfileMemberIds(
|
||||||
|
PiActionProfileId actionProfileId, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
if (browser == null) {
|
||||||
|
log.warn("Unable to get a P4Info browser for pipeconf {}, " +
|
||||||
|
"aborting cleanup of action profile members",
|
||||||
|
pipeconf);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int p4ActProfId;
|
||||||
|
try {
|
||||||
|
p4ActProfId = browser
|
||||||
|
.actionProfiles()
|
||||||
|
.getByName(actionProfileId.id())
|
||||||
|
.getPreamble()
|
||||||
|
.getId();
|
||||||
|
} catch (P4InfoBrowser.NotFoundException e) {
|
||||||
|
log.warn("Unable to cleanup action profile members: {}", e.getMessage());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ReadRequest memberRequestMsg = ReadRequest.newBuilder()
|
||||||
|
.setDeviceId(p4DeviceId)
|
||||||
|
.addEntities(Entity.newBuilder().setActionProfileMember(
|
||||||
|
ActionProfileMember.newBuilder()
|
||||||
|
.setActionProfileId(p4ActProfId)
|
||||||
|
.build()).build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Read members.
|
||||||
|
final Iterator<ReadResponse> memberResponses;
|
||||||
|
try {
|
||||||
|
memberResponses = blockingStub.read(memberRequestMsg);
|
||||||
|
} catch (StatusRuntimeException e) {
|
||||||
|
checkGrpcException(e);
|
||||||
|
log.warn("Unable to read members of action profile {} from {}: {}",
|
||||||
|
actionProfileId, deviceId, e.getMessage());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Tools.stream(() -> memberResponses)
|
||||||
|
.map(ReadResponse::getEntitiesList)
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.filter(e -> e.getEntityCase() == ACTION_PROFILE_MEMBER)
|
||||||
|
.map(Entity::getActionProfileMember)
|
||||||
|
// Perhaps not needed, but better to double check to avoid
|
||||||
|
// removing members of other groups.
|
||||||
|
.filter(m -> m.getActionProfileId() == p4ActProfId)
|
||||||
|
.map(ActionProfileMember::getMemberId)
|
||||||
|
.map(PiActionGroupMemberId::of)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PiActionGroupMemberId> doRemoveActionProfileMembers(
|
||||||
|
PiActionProfileId actionProfileId,
|
||||||
|
List<PiActionGroupMemberId> memberIds,
|
||||||
|
PiPipeconf pipeconf) {
|
||||||
|
|
||||||
|
if (memberIds.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
if (browser == null) {
|
||||||
|
log.warn("Unable to get a P4Info browser for pipeconf {}, " +
|
||||||
|
"aborting cleanup of action profile members",
|
||||||
|
pipeconf);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int p4ActProfId;
|
||||||
|
try {
|
||||||
|
p4ActProfId = browser.actionProfiles()
|
||||||
|
.getByName(actionProfileId.id()).getPreamble().getId();
|
||||||
|
} catch (P4InfoBrowser.NotFoundException e) {
|
||||||
|
log.warn("Unable to cleanup action profile members: {}", e.getMessage());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Update> updateMsgs = memberIds.stream()
|
||||||
|
.map(m -> ActionProfileMember.newBuilder()
|
||||||
|
.setActionProfileId(p4ActProfId)
|
||||||
|
.setMemberId(m.id()).build())
|
||||||
|
.map(m -> Entity.newBuilder().setActionProfileMember(m).build())
|
||||||
|
.map(e -> Update.newBuilder().setEntity(e)
|
||||||
|
.setType(Update.Type.DELETE).build())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
log.debug("Removing {} members of action profile '{}'...",
|
||||||
|
memberIds.size(), actionProfileId);
|
||||||
|
|
||||||
|
return writeAndReturnSuccessEntities(
|
||||||
|
updateMsgs, memberIds, WriteOperationType.DELETE,
|
||||||
|
"action profile members");
|
||||||
|
}
|
||||||
|
|
||||||
private boolean doWriteActionGroup(PiActionGroup group, WriteOperationType opType, PiPipeconf pipeconf) {
|
private boolean doWriteActionGroup(PiActionGroup group, WriteOperationType opType, PiPipeconf pipeconf) {
|
||||||
final ActionProfileGroup actionProfileGroup;
|
final ActionProfileGroup actionProfileGroup;
|
||||||
try {
|
try {
|
||||||
@ -849,20 +976,20 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
.setType(UPDATE_TYPES.get(opType))
|
.setType(UPDATE_TYPES.get(opType))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return write(Collections.singleton(updateMsg), Collections.singleton(group),
|
return write(singletonList(updateMsg), singletonList(group),
|
||||||
opType, "group");
|
opType, "group");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiMeterCellConfig> doReadAllMeterCells(
|
private List<PiMeterCellConfig> doReadAllMeterCells(
|
||||||
Collection<PiMeterId> meterIds, PiPipeconf pipeconf) {
|
List<PiMeterId> meterIds, PiPipeconf pipeconf) {
|
||||||
return doReadMeterEntities(MeterEntryCodec.readAllCellsEntities(
|
return doReadMeterEntities(MeterEntryCodec.readAllCellsEntities(
|
||||||
meterIds, pipeconf), pipeconf);
|
meterIds, pipeconf), pipeconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiMeterCellConfig> doReadMeterCells(
|
private List<PiMeterCellConfig> doReadMeterCells(
|
||||||
Collection<PiMeterCellId> cellIds, PiPipeconf pipeconf) {
|
List<PiMeterCellId> cellIds, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
final Collection<PiMeterCellConfig> piMeterCellConfigs = cellIds.stream()
|
final List<PiMeterCellConfig> piMeterCellConfigs = cellIds.stream()
|
||||||
.map(cellId -> PiMeterCellConfig.builder()
|
.map(cellId -> PiMeterCellConfig.builder()
|
||||||
.withMeterCellId(cellId)
|
.withMeterCellId(cellId)
|
||||||
.build())
|
.build())
|
||||||
@ -872,8 +999,8 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
piMeterCellConfigs, pipeconf), pipeconf);
|
piMeterCellConfigs, pipeconf), pipeconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiMeterCellConfig> doReadMeterEntities(
|
private List<PiMeterCellConfig> doReadMeterEntities(
|
||||||
Collection<Entity> entitiesToRead, PiPipeconf pipeconf) {
|
List<Entity> entitiesToRead, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
if (entitiesToRead.size() == 0) {
|
if (entitiesToRead.size() == 0) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@ -903,9 +1030,9 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return MeterEntryCodec.decodeMeterEntities(responseEntities, pipeconf);
|
return MeterEntryCodec.decodeMeterEntities(responseEntities, pipeconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doWriteMeterCells(Collection<PiMeterCellConfig> cellConfigs, PiPipeconf pipeconf) {
|
private boolean doWriteMeterCells(List<PiMeterCellConfig> cellConfigs, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
Collection<Update> updateMsgs = MeterEntryCodec.encodePiMeterCellConfigs(cellConfigs, pipeconf)
|
List<Update> updateMsgs = MeterEntryCodec.encodePiMeterCellConfigs(cellConfigs, pipeconf)
|
||||||
.stream()
|
.stream()
|
||||||
.map(meterEntryMsg ->
|
.map(meterEntryMsg ->
|
||||||
Update.newBuilder()
|
Update.newBuilder()
|
||||||
@ -922,7 +1049,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean doWriteMulticastGroupEntries(
|
private boolean doWriteMulticastGroupEntries(
|
||||||
Collection<PiMulticastGroupEntry> entries,
|
List<PiMulticastGroupEntry> entries,
|
||||||
WriteOperationType opType) {
|
WriteOperationType opType) {
|
||||||
|
|
||||||
final List<Update> updateMsgs = entries.stream()
|
final List<Update> updateMsgs = entries.stream()
|
||||||
@ -941,7 +1068,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return write(updateMsgs, entries, opType, "multicast group entry");
|
return write(updateMsgs, entries, opType, "multicast group entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PiMulticastGroupEntry> doReadAllMulticastGroupEntries() {
|
private List<PiMulticastGroupEntry> doReadAllMulticastGroupEntries() {
|
||||||
|
|
||||||
final Entity entity = Entity.newBuilder()
|
final Entity entity = Entity.newBuilder()
|
||||||
.setPacketReplicationEngineEntry(
|
.setPacketReplicationEngineEntry(
|
||||||
@ -985,18 +1112,24 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return mcEntries;
|
return mcEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <E extends PiEntity> boolean write(Collection<Update> updates,
|
private <T> boolean write(List<Update> updates,
|
||||||
Collection<E> writeEntities,
|
List<T> writeEntities,
|
||||||
WriteOperationType opType,
|
WriteOperationType opType,
|
||||||
String entryType) {
|
String entryType) {
|
||||||
try {
|
// True if all entities were successfully written.
|
||||||
|
return writeAndReturnSuccessEntities(updates, writeEntities, opType,
|
||||||
|
entryType).size() == writeEntities.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> List<T> writeAndReturnSuccessEntities(
|
||||||
|
List<Update> updates, List<T> writeEntities,
|
||||||
|
WriteOperationType opType, String entryType) {
|
||||||
|
try {
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
blockingStub.write(writeRequest(updates));
|
blockingStub.write(writeRequest(updates));
|
||||||
return true;
|
return writeEntities;
|
||||||
} catch (StatusRuntimeException e) {
|
} catch (StatusRuntimeException e) {
|
||||||
checkAndLogWriteErrors(writeEntities, e, opType, entryType);
|
return checkAndLogWriteErrors(writeEntities, e, opType, entryType);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,8 +1156,9 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <E extends PiEntity> void checkAndLogWriteErrors(
|
// Returns the collection of succesfully write entities.
|
||||||
Collection<E> writeEntities, StatusRuntimeException ex,
|
private <T> List<T> checkAndLogWriteErrors(
|
||||||
|
List<T> writeEntities, StatusRuntimeException ex,
|
||||||
WriteOperationType opType, String entryType) {
|
WriteOperationType opType, String entryType) {
|
||||||
|
|
||||||
checkGrpcException(ex);
|
checkGrpcException(ex);
|
||||||
@ -1034,33 +1168,35 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
if (errors.isEmpty()) {
|
if (errors.isEmpty()) {
|
||||||
final String description = ex.getStatus().getDescription();
|
final String description = ex.getStatus().getDescription();
|
||||||
log.warn("Unable to {} {} {}(s) on {}: {}",
|
log.warn("Unable to {} {} {}(s) on {}: {}",
|
||||||
opType.name(), writeEntities.size(), entryType, deviceId,
|
opType.name(), writeEntities.size(), entryType, deviceId,
|
||||||
ex.getStatus().getCode().name(),
|
ex.getStatus().getCode().name(),
|
||||||
description == null ? "" : " - " + description);
|
description == null ? "" : " - " + description);
|
||||||
return;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: we are assuming entities is an ordered collection, e.g. a list,
|
|
||||||
// and that errors are reported in the same order as the corresponding
|
|
||||||
// written entity. Write RPC methods should be refactored to accept an
|
|
||||||
// ordered list of entities, instead of a collection.
|
|
||||||
if (errors.size() == writeEntities.size()) {
|
if (errors.size() == writeEntities.size()) {
|
||||||
Iterator<E> entityIterator = writeEntities.iterator();
|
List<T> okEntities = Lists.newArrayList();
|
||||||
errors.stream()
|
Iterator<T> entityIterator = writeEntities.iterator();
|
||||||
.map(e -> ImmutablePair.of(e, entityIterator.next()))
|
for (P4RuntimeOuterClass.Error error : errors) {
|
||||||
.filter(p -> p.left.getCanonicalCode() != Status.OK.getCode().value())
|
T entity = entityIterator.next();
|
||||||
.forEach(p -> log.warn("Unable to {} {} on {}: {} [{}]",
|
if (error.getCanonicalCode() != Status.OK.getCode().value()) {
|
||||||
opType.name(), entryType, deviceId,
|
log.warn("Unable to {} {} on {}: {} [{}]",
|
||||||
parseP4Error(p.getLeft()),
|
opType.name(), entryType, deviceId,
|
||||||
p.getRight().toString()));
|
parseP4Error(error), entity.toString());
|
||||||
|
} else {
|
||||||
|
okEntities.add(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return okEntities;
|
||||||
} else {
|
} else {
|
||||||
log.warn("Unable to reconcile error details to updates " +
|
log.warn("Unable to reconcile error details to updates " +
|
||||||
"(sent {} updates, but device returned {} errors)",
|
"(sent {} updates, but device returned {} errors)",
|
||||||
entryType, writeEntities.size(), errors.size());
|
entryType, writeEntities.size(), errors.size());
|
||||||
errors.stream()
|
errors.stream()
|
||||||
.filter(err -> err.getCanonicalCode() != Status.OK.getCode().value())
|
.filter(err -> err.getCanonicalCode() != Status.OK.getCode().value())
|
||||||
.forEach(err -> log.warn("Unable to {} {} (unknown): {}",
|
.forEach(err -> log.warn("Unable to {} {} (unknown): {}",
|
||||||
opType.name(), entryType, parseP4Error(err)));
|
opType.name(), entryType, parseP4Error(err)));
|
||||||
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1085,7 +1221,6 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
})
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parseP4Error(P4RuntimeOuterClass.Error err) {
|
private String parseP4Error(P4RuntimeOuterClass.Error err) {
|
||||||
|
|||||||
@ -59,6 +59,10 @@ public class P4RuntimeControllerImpl
|
|||||||
extends AbstractListenerManager<P4RuntimeEvent, P4RuntimeEventListener>
|
extends AbstractListenerManager<P4RuntimeEvent, P4RuntimeEventListener>
|
||||||
implements P4RuntimeController {
|
implements P4RuntimeController {
|
||||||
|
|
||||||
|
// Getting the pipeline config from the device can take tens of MBs.
|
||||||
|
private static final int MAX_INBOUND_MSG_SIZE = 256; // Megabytes.
|
||||||
|
private static final int MEGABYTES = 1024 * 1024;
|
||||||
|
|
||||||
private final Logger log = getLogger(getClass());
|
private final Logger log = getLogger(getClass());
|
||||||
|
|
||||||
private final Map<DeviceId, ClientKey> clientKeys = Maps.newHashMap();
|
private final Map<DeviceId, ClientKey> clientKeys = Maps.newHashMap();
|
||||||
@ -119,7 +123,7 @@ public class P4RuntimeControllerImpl
|
|||||||
final ClientKey existingKey = clientKeys.get(deviceId);
|
final ClientKey existingKey = clientKeys.get(deviceId);
|
||||||
if (clientKey.equals(existingKey)) {
|
if (clientKey.equals(existingKey)) {
|
||||||
log.debug("Not creating client for {} as it already exists (server={}:{}, p4DeviceId={})...",
|
log.debug("Not creating client for {} as it already exists (server={}:{}, p4DeviceId={})...",
|
||||||
deviceId, serverAddr, serverPort, p4DeviceId);
|
deviceId, serverAddr, serverPort, p4DeviceId);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
log.info("Requested client for {} with new " +
|
log.info("Requested client for {} with new " +
|
||||||
@ -139,7 +143,8 @@ public class P4RuntimeControllerImpl
|
|||||||
|
|
||||||
ManagedChannelBuilder channelBuilder = NettyChannelBuilder
|
ManagedChannelBuilder channelBuilder = NettyChannelBuilder
|
||||||
.forAddress(serverAddr, serverPort)
|
.forAddress(serverAddr, serverPort)
|
||||||
.usePlaintext(true);
|
.maxInboundMessageSize(MAX_INBOUND_MSG_SIZE * MEGABYTES)
|
||||||
|
.usePlaintext();
|
||||||
|
|
||||||
ManagedChannel channel;
|
ManagedChannel channel;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -38,11 +38,11 @@ import org.onosproject.net.pi.runtime.PiTableAction;
|
|||||||
import org.onosproject.net.pi.runtime.PiTableEntry;
|
import org.onosproject.net.pi.runtime.PiTableEntry;
|
||||||
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
|
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
import p4.config.v1.P4InfoOuterClass;
|
||||||
import p4.v1.P4RuntimeOuterClass.Action;
|
import p4.v1.P4RuntimeOuterClass.Action;
|
||||||
import p4.v1.P4RuntimeOuterClass.FieldMatch;
|
import p4.v1.P4RuntimeOuterClass.FieldMatch;
|
||||||
import p4.v1.P4RuntimeOuterClass.TableAction;
|
import p4.v1.P4RuntimeOuterClass.TableAction;
|
||||||
import p4.v1.P4RuntimeOuterClass.TableEntry;
|
import p4.v1.P4RuntimeOuterClass.TableEntry;
|
||||||
import p4.config.v1.P4InfoOuterClass;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -82,7 +82,7 @@ final class TableEntryEncoder {
|
|||||||
* @return collection of P4Runtime table entry protobuf messages
|
* @return collection of P4Runtime table entry protobuf messages
|
||||||
* @throws EncodeException if a PI table entry cannot be encoded
|
* @throws EncodeException if a PI table entry cannot be encoded
|
||||||
*/
|
*/
|
||||||
static Collection<TableEntry> encode(Collection<PiTableEntry> piTableEntries,
|
static List<TableEntry> encode(List<PiTableEntry> piTableEntries,
|
||||||
PiPipeconf pipeconf)
|
PiPipeconf pipeconf)
|
||||||
throws EncodeException {
|
throws EncodeException {
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ final class TableEntryEncoder {
|
|||||||
* @param pipeconf PI pipeconf
|
* @param pipeconf PI pipeconf
|
||||||
* @return collection of PI table entry objects
|
* @return collection of PI table entry objects
|
||||||
*/
|
*/
|
||||||
static Collection<PiTableEntry> decode(Collection<TableEntry> tableEntryMsgs, PiPipeconf pipeconf) {
|
static List<PiTableEntry> decode(List<TableEntry> tableEntryMsgs, PiPipeconf pipeconf) {
|
||||||
|
|
||||||
P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
|
||||||
|
|
||||||
@ -263,7 +263,9 @@ final class TableEntryEncoder {
|
|||||||
piTableEntryBuilder.forTable(PiTableId.of(tableInfo.getPreamble().getName()));
|
piTableEntryBuilder.forTable(PiTableId.of(tableInfo.getPreamble().getName()));
|
||||||
|
|
||||||
// Priority.
|
// Priority.
|
||||||
piTableEntryBuilder.withPriority(tableEntryMsg.getPriority());
|
if (tableEntryMsg.getPriority() > 0) {
|
||||||
|
piTableEntryBuilder.withPriority(tableEntryMsg.getPriority());
|
||||||
|
}
|
||||||
|
|
||||||
// Controller metadata (cookie)
|
// Controller metadata (cookie)
|
||||||
piTableEntryBuilder.withCookie(tableEntryMsg.getControllerMetadata());
|
piTableEntryBuilder.withCookie(tableEntryMsg.getControllerMetadata());
|
||||||
@ -373,7 +375,7 @@ final class TableEntryEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PiMatchKey decodeFieldMatchMsgs(Collection<FieldMatch> fieldMatchs, P4InfoOuterClass.Table tableInfo,
|
private static PiMatchKey decodeFieldMatchMsgs(List<FieldMatch> fieldMatchs, P4InfoOuterClass.Table tableInfo,
|
||||||
P4InfoBrowser browser)
|
P4InfoBrowser browser)
|
||||||
throws P4InfoBrowser.NotFoundException, EncodeException {
|
throws P4InfoBrowser.NotFoundException, EncodeException {
|
||||||
// Match key for field matches.
|
// Match key for field matches.
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
package org.onosproject.p4runtime.ctl;
|
package org.onosproject.p4runtime.ctl;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
@ -84,8 +83,8 @@ public class P4RuntimeGroupTest {
|
|||||||
private static final PiActionParamId PORT_PARAM_ID = PiActionParamId.of("port");
|
private static final PiActionParamId PORT_PARAM_ID = PiActionParamId.of("port");
|
||||||
private static final int BASE_MEM_ID = 65535;
|
private static final int BASE_MEM_ID = 65535;
|
||||||
private static final List<Integer> MEMBER_IDS = ImmutableList.of(65536, 65537, 65538);
|
private static final List<Integer> MEMBER_IDS = ImmutableList.of(65536, 65537, 65538);
|
||||||
private static final Collection<PiActionGroupMember> GROUP_MEMBERS =
|
private static final List<PiActionGroupMember> GROUP_MEMBERS =
|
||||||
ImmutableSet.of(
|
Lists.newArrayList(
|
||||||
outputMember((short) 1),
|
outputMember((short) 1),
|
||||||
outputMember((short) 2),
|
outputMember((short) 2),
|
||||||
outputMember((short) 3)
|
outputMember((short) 3)
|
||||||
@ -116,6 +115,7 @@ public class P4RuntimeGroupTest {
|
|||||||
.withParameter(param).build();
|
.withParameter(param).build();
|
||||||
|
|
||||||
return PiActionGroupMember.builder()
|
return PiActionGroupMember.builder()
|
||||||
|
.forActionProfile(ACT_PROF_ID)
|
||||||
.withAction(piAction)
|
.withAction(piAction)
|
||||||
.withId(PiActionGroupMemberId.of(BASE_MEM_ID + portNum))
|
.withId(PiActionGroupMemberId.of(BASE_MEM_ID + portNum))
|
||||||
.withWeight(DEFAULT_MEMBER_WEIGHT)
|
.withWeight(DEFAULT_MEMBER_WEIGHT)
|
||||||
@ -139,7 +139,6 @@ public class P4RuntimeGroupTest {
|
|||||||
grpcServer = builder.build().start();
|
grpcServer = builder.build().start();
|
||||||
grpcChannel = InProcessChannelBuilder.forName(GRPC_SERVER_NAME)
|
grpcChannel = InProcessChannelBuilder.forName(GRPC_SERVER_NAME)
|
||||||
.directExecutor()
|
.directExecutor()
|
||||||
.usePlaintext(true)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +190,7 @@ public class P4RuntimeGroupTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testInsertPiActionMembers() throws Exception {
|
public void testInsertPiActionMembers() throws Exception {
|
||||||
CompletableFuture<Void> complete = p4RuntimeServerImpl.expectRequests(1);
|
CompletableFuture<Void> complete = p4RuntimeServerImpl.expectRequests(1);
|
||||||
client.writeActionGroupMembers(ACT_PROF_ID, GROUP_MEMBERS, INSERT, PIPECONF);
|
client.writeActionGroupMembers(GROUP_MEMBERS, INSERT, PIPECONF);
|
||||||
complete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
|
complete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
|
||||||
WriteRequest result = p4RuntimeServerImpl.getWriteReqs().get(0);
|
WriteRequest result = p4RuntimeServerImpl.getWriteReqs().get(0);
|
||||||
assertEquals(1, result.getDeviceId());
|
assertEquals(1, result.getDeviceId());
|
||||||
@ -246,6 +245,7 @@ public class P4RuntimeGroupTest {
|
|||||||
|
|
||||||
ActionProfileMember actProfMember =
|
ActionProfileMember actProfMember =
|
||||||
ActionProfileMember.newBuilder()
|
ActionProfileMember.newBuilder()
|
||||||
|
.setActionProfileId(P4_INFO_ACT_PROF_ID)
|
||||||
.setMemberId(id)
|
.setMemberId(id)
|
||||||
.setAction(action)
|
.setAction(action)
|
||||||
.build();
|
.build();
|
||||||
@ -260,13 +260,14 @@ public class P4RuntimeGroupTest {
|
|||||||
|
|
||||||
responses.add(ReadResponse.newBuilder()
|
responses.add(ReadResponse.newBuilder()
|
||||||
.addAllEntities(members.stream()
|
.addAllEntities(members.stream()
|
||||||
.map(m -> Entity.newBuilder().setActionProfileMember(m).build())
|
.map(m -> Entity.newBuilder()
|
||||||
|
.setActionProfileMember(m).build())
|
||||||
.collect(Collectors.toList()))
|
.collect(Collectors.toList()))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
p4RuntimeServerImpl.willReturnReadResult(responses);
|
p4RuntimeServerImpl.willReturnReadResult(responses);
|
||||||
CompletableFuture<Void> complete = p4RuntimeServerImpl.expectRequests(2);
|
CompletableFuture<Void> complete = p4RuntimeServerImpl.expectRequests(2);
|
||||||
CompletableFuture<Collection<PiActionGroup>> groupsComplete = client.dumpGroups(ACT_PROF_ID, PIPECONF);
|
CompletableFuture<List<PiActionGroup>> groupsComplete = client.dumpGroups(ACT_PROF_ID, PIPECONF);
|
||||||
complete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
|
complete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
|
||||||
|
|
||||||
Collection<PiActionGroup> groups = groupsComplete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
|
Collection<PiActionGroup> groups = groupsComplete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
|
||||||
|
|||||||
@ -48,7 +48,7 @@ final class P4TableModel implements PiTableModel {
|
|||||||
private final boolean supportAging;
|
private final boolean supportAging;
|
||||||
private final ImmutableMap<PiMatchFieldId, PiMatchFieldModel> matchFields;
|
private final ImmutableMap<PiMatchFieldId, PiMatchFieldModel> matchFields;
|
||||||
private final ImmutableMap<PiActionId, PiActionModel> actions;
|
private final ImmutableMap<PiActionId, PiActionModel> actions;
|
||||||
private final PiActionModel defaultAction;
|
private final PiActionModel constDefaultAction;
|
||||||
private final boolean hasDefaultMutableParams;
|
private final boolean hasDefaultMutableParams;
|
||||||
private final boolean isConstTable;
|
private final boolean isConstTable;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ final class P4TableModel implements PiTableModel {
|
|||||||
ImmutableMap<PiMeterId, PiMeterModel> meters, boolean supportAging,
|
ImmutableMap<PiMeterId, PiMeterModel> meters, boolean supportAging,
|
||||||
ImmutableMap<PiMatchFieldId, PiMatchFieldModel> matchFields,
|
ImmutableMap<PiMatchFieldId, PiMatchFieldModel> matchFields,
|
||||||
ImmutableMap<PiActionId, PiActionModel> actions,
|
ImmutableMap<PiActionId, PiActionModel> actions,
|
||||||
PiActionModel defaultAction, boolean hasDefaultMutableParams,
|
PiActionModel constDefaultAction, boolean hasDefaultMutableParams,
|
||||||
boolean isConstTable) {
|
boolean isConstTable) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.tableType = tableType;
|
this.tableType = tableType;
|
||||||
@ -69,7 +69,7 @@ final class P4TableModel implements PiTableModel {
|
|||||||
this.supportAging = supportAging;
|
this.supportAging = supportAging;
|
||||||
this.matchFields = matchFields;
|
this.matchFields = matchFields;
|
||||||
this.actions = actions;
|
this.actions = actions;
|
||||||
this.defaultAction = defaultAction;
|
this.constDefaultAction = constDefaultAction;
|
||||||
this.hasDefaultMutableParams = hasDefaultMutableParams;
|
this.hasDefaultMutableParams = hasDefaultMutableParams;
|
||||||
this.isConstTable = isConstTable;
|
this.isConstTable = isConstTable;
|
||||||
}
|
}
|
||||||
@ -120,8 +120,8 @@ final class P4TableModel implements PiTableModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PiActionModel> defaultAction() {
|
public Optional<PiActionModel> constDefaultAction() {
|
||||||
return Optional.ofNullable(defaultAction);
|
return Optional.ofNullable(constDefaultAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -148,7 +148,7 @@ final class P4TableModel implements PiTableModel {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(id, tableType, actionProfile, maxSize, counters,
|
return Objects.hash(id, tableType, actionProfile, maxSize, counters,
|
||||||
meters, supportAging, matchFields, actions,
|
meters, supportAging, matchFields, actions,
|
||||||
defaultAction, hasDefaultMutableParams);
|
constDefaultAction, hasDefaultMutableParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -169,7 +169,7 @@ final class P4TableModel implements PiTableModel {
|
|||||||
&& Objects.equals(this.supportAging, other.supportAging)
|
&& Objects.equals(this.supportAging, other.supportAging)
|
||||||
&& Objects.equals(this.matchFields, other.matchFields)
|
&& Objects.equals(this.matchFields, other.matchFields)
|
||||||
&& Objects.equals(this.actions, other.actions)
|
&& Objects.equals(this.actions, other.actions)
|
||||||
&& Objects.equals(this.defaultAction, other.defaultAction)
|
&& Objects.equals(this.constDefaultAction, other.constDefaultAction)
|
||||||
&& Objects.equals(this.hasDefaultMutableParams, other.hasDefaultMutableParams);
|
&& Objects.equals(this.hasDefaultMutableParams, other.hasDefaultMutableParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -193,7 +193,7 @@ public class P4InfoParserTest {
|
|||||||
wcmpTableModel.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(
|
wcmpTableModel.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(
|
||||||
setEgressPortAction, noAction));
|
setEgressPortAction, noAction));
|
||||||
|
|
||||||
PiActionModel table0DefaultAction = table0Model.defaultAction().orElse(null);
|
PiActionModel table0DefaultAction = table0Model.constDefaultAction().orElse(null);
|
||||||
|
|
||||||
new EqualsTester().addEqualityGroup(table0DefaultAction, dropAction).testEquals();
|
new EqualsTester().addEqualityGroup(table0DefaultAction, dropAction).testEquals();
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# ***** This file was auto-generated at Thu, 4 Oct 2018 21:19:54 GMT. Do not edit this file manually. *****
|
# ***** This file was auto-generated at Tue, 9 Oct 2018 17:26:45 GMT. Do not edit this file manually. *****
|
||||||
# ***** Use onos-lib-gen *****
|
# ***** Use onos-lib-gen *****
|
||||||
|
|
||||||
load("//tools/build/bazel:variables.bzl", "ONOS_GROUP_ID", "ONOS_VERSION")
|
load("//tools/build/bazel:variables.bzl", "ONOS_GROUP_ID", "ONOS_VERSION")
|
||||||
@ -205,9 +205,9 @@ def generated_maven_jars():
|
|||||||
if "classgraph" not in native.existing_rules():
|
if "classgraph" not in native.existing_rules():
|
||||||
java_import_external(
|
java_import_external(
|
||||||
name = "classgraph",
|
name = "classgraph",
|
||||||
jar_sha256 = "b88663a3c775262afad6450d4670fc7c6afa64f4933db0d75e94d66f14230ef7",
|
jar_sha256 = "92a75236a6a30993895916b7eea4011c54d3182c9fa6734e8c23b30cc9500023",
|
||||||
licenses = ["notice"],
|
licenses = ["notice"],
|
||||||
jar_urls = ["http://repo1.maven.org/maven2/io/github/classgraph/classgraph/4.0.6/classgraph-4.0.6.jar"], )
|
jar_urls = ["http://repo1.maven.org/maven2/io/github/classgraph/classgraph/4.2.3/classgraph-4.2.3.jar"], )
|
||||||
if "commons_codec" not in native.existing_rules():
|
if "commons_codec" not in native.existing_rules():
|
||||||
java_import_external(
|
java_import_external(
|
||||||
name = "commons_codec",
|
name = "commons_codec",
|
||||||
@ -1003,9 +1003,9 @@ def generated_maven_jars():
|
|||||||
if "libthrift" not in native.existing_rules():
|
if "libthrift" not in native.existing_rules():
|
||||||
java_import_external(
|
java_import_external(
|
||||||
name = "libthrift",
|
name = "libthrift",
|
||||||
jar_sha256 = "bca5e8cdee1e0fbf563de7d41c452385e7bed69723fa28225a9ce718a8ee3419",
|
jar_sha256 = "65f1d191c3c97ec79e6d82e75f8af9d5265f4fbb605df4efc5614c222109cf36",
|
||||||
licenses = ["notice"],
|
licenses = ["notice"],
|
||||||
jar_urls = ["http://repo1.maven.org/maven2/org/apache/thrift/libthrift/0.9.3/libthrift-0.9.3.jar"], )
|
jar_urls = ["http://repo1.maven.org/maven2/org/apache/thrift/libthrift/0.11.0/libthrift-0.11.0.jar"], )
|
||||||
if "qdox" not in native.existing_rules():
|
if "qdox" not in native.existing_rules():
|
||||||
java_import_external(
|
java_import_external(
|
||||||
name = "qdox",
|
name = "qdox",
|
||||||
@ -1402,7 +1402,7 @@ artifact_map["@atomix_primitive//:atomix_primitive"] = "mvn:io.atomix:atomix-pri
|
|||||||
artifact_map["@atomix_raft//:atomix_raft"] = "mvn:io.atomix:atomix-raft:jar:3.0.5"
|
artifact_map["@atomix_raft//:atomix_raft"] = "mvn:io.atomix:atomix-raft:jar:3.0.5"
|
||||||
artifact_map["@atomix_storage//:atomix_storage"] = "mvn:io.atomix:atomix-storage:jar:3.0.5"
|
artifact_map["@atomix_storage//:atomix_storage"] = "mvn:io.atomix:atomix-storage:jar:3.0.5"
|
||||||
artifact_map["@atomix_utils//:atomix_utils"] = "mvn:io.atomix:atomix-utils:jar:3.0.5"
|
artifact_map["@atomix_utils//:atomix_utils"] = "mvn:io.atomix:atomix-utils:jar:3.0.5"
|
||||||
artifact_map["@classgraph//:classgraph"] = "mvn:io.github.classgraph:classgraph:jar:4.0.6"
|
artifact_map["@classgraph//:classgraph"] = "mvn:io.github.classgraph:classgraph:jar:4.2.3"
|
||||||
artifact_map["@commons_codec//:commons_codec"] = "mvn:commons-codec:commons-codec:jar:1.10"
|
artifact_map["@commons_codec//:commons_codec"] = "mvn:commons-codec:commons-codec:jar:1.10"
|
||||||
artifact_map["@commons_cli//:commons_cli"] = "mvn:commons-cli:commons-cli:jar:1.3"
|
artifact_map["@commons_cli//:commons_cli"] = "mvn:commons-cli:commons-cli:jar:1.3"
|
||||||
artifact_map["@commons_collections//:commons_collections"] = "mvn:commons-collections:commons-collections:jar:3.2.2"
|
artifact_map["@commons_collections//:commons_collections"] = "mvn:commons-collections:commons-collections:jar:3.2.2"
|
||||||
@ -1535,7 +1535,7 @@ artifact_map["@checkstyle//:checkstyle"] = "mvn:com.puppycrawl.tools:checkstyle:
|
|||||||
artifact_map["@apache_karaf//:apache_karaf"] = "http://repo1.maven.org/maven2/org/onosproject/apache-karaf-offline/4.2.1-base/apache-karaf-offline-4.2.1-base.tar.gz"
|
artifact_map["@apache_karaf//:apache_karaf"] = "http://repo1.maven.org/maven2/org/onosproject/apache-karaf-offline/4.2.1-base/apache-karaf-offline-4.2.1-base.tar.gz"
|
||||||
artifact_map["@bndlib//:bndlib"] = "mvn:biz.aQute.bnd:biz.aQute.bndlib:jar:4.0.0"
|
artifact_map["@bndlib//:bndlib"] = "mvn:biz.aQute.bnd:biz.aQute.bndlib:jar:4.0.0"
|
||||||
artifact_map["@bndexe//:bndexe"] = "mvn:biz.aQute.bnd:biz.aQute.bnd:jar:4.0.0"
|
artifact_map["@bndexe//:bndexe"] = "mvn:biz.aQute.bnd:biz.aQute.bnd:jar:4.0.0"
|
||||||
artifact_map["@libthrift//:libthrift"] = "mvn:org.apache.thrift:libthrift:jar:0.9.3"
|
artifact_map["@libthrift//:libthrift"] = "mvn:org.apache.thrift:libthrift:jar:0.11.0"
|
||||||
artifact_map["@qdox//:qdox"] = "mvn:com.thoughtworks.qdox:qdox:jar:NON-OSGI:2.0-M3"
|
artifact_map["@qdox//:qdox"] = "mvn:com.thoughtworks.qdox:qdox:jar:NON-OSGI:2.0-M3"
|
||||||
artifact_map["@snmp_core//:snmp_core"] = "mvn:org.onosproject:snmp-core:jar:1.3-20161021.1"
|
artifact_map["@snmp_core//:snmp_core"] = "mvn:org.onosproject:snmp-core:jar:1.3-20161021.1"
|
||||||
artifact_map["@mibs_net_snmp//:mibs_net_snmp"] = "mvn:org.onosproject:mibbler-mibs-net-snmp:jar:1.0-20151221.1"
|
artifact_map["@mibs_net_snmp//:mibs_net_snmp"] = "mvn:org.onosproject:mibbler-mibs-net-snmp:jar:1.0-20151221.1"
|
||||||
|
|||||||
@ -47,7 +47,7 @@ ssh -tt $remote "
|
|||||||
[ -f $ATOMIX_INSTALL_DIR/bin/atomix-agent ] && echo \"Atomix is already installed\" && exit 1
|
[ -f $ATOMIX_INSTALL_DIR/bin/atomix-agent ] && echo \"Atomix is already installed\" && exit 1
|
||||||
|
|
||||||
sudo mkdir -p $ATOMIX_INSTALL_DIR && sudo chown ${ONOS_USER}:${ONOS_GROUP} $ATOMIX_INSTALL_DIR
|
sudo mkdir -p $ATOMIX_INSTALL_DIR && sudo chown ${ONOS_USER}:${ONOS_GROUP} $ATOMIX_INSTALL_DIR
|
||||||
sudo wget -O $ATOMIX_INSTALL_DIR/atomix-dist.tar.gz https://oss.sonatype.org/content/repositories/releases/io/atomix/atomix-dist/3.0.5/atomix-dist-3.0.5.tar.gz
|
sudo wget -O $ATOMIX_INSTALL_DIR/atomix-dist.tar.gz https://oss.sonatype.org/content/repositories/releases/io/atomix/atomix-dist/3.0.6/atomix-dist-3.0.6.tar.gz
|
||||||
tar -xvf $ATOMIX_INSTALL_DIR/atomix-dist.tar.gz -C $ATOMIX_INSTALL_DIR
|
tar -xvf $ATOMIX_INSTALL_DIR/atomix-dist.tar.gz -C $ATOMIX_INSTALL_DIR
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user