First commit
Change-Id: Iab8dca19bca1ef367b1cced4b345554fd32154df
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4e68904
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.iml
+target
+p4c-out
+src/main/resources/p4c-out
\ No newline at end of file
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..3241765
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.opencord.org
+port=29418
+project=fabric-tofino.git
+defaultremote=origin
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..da88f63
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,82 @@
+PROFILES ?= all
+ONOS_HOST ?= localhost
+
+mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
+curr_dir := $(patsubst %/,%,$(dir $(mkfile_path)))
+curr_dir_sha := $(shell echo -n "$(curr_dir)" | shasum | cut -c1-7)
+
+mvn_image := maven:3.6.1-jdk-11-slim
+mvn_container := mvn-build-${curr_dir_sha}
+
+onos_url := http://${ONOS_HOST}:8181/onos
+onos_curl := curl --fail -sSL --user onos:rocks --noproxy localhost
+
+pipeconf_app_name := org.opencord.fabric-tofino
+pipeconf_app_version := 2.2.1-SNAPSHOT
+
+tofino_compile := ./src/main/p4/tofino-compile.sh
+
+.PHONY: pipeconf
+
+build: clean $(PROFILES) pipeconf
+
+all: fabric fabric-bng fabric-spgw fabric-int fabric-spgw-int
+
+fabric:
+ @${tofino_compile} fabric ""
+
+fabric-simple:
+ @${tofino_compile} fabric-simple "-DWITH_SIMPLE_NEXT"
+
+fabric-bng:
+ @${tofino_compile} fabric-bng "-DWITH_BNG -DWITH_DOUBLE_VLAN_TERMINATION -DWITHOUT_XCONNECT"
+
+fabric-int:
+ @${tofino_compile} fabric-int "-DWITH_INT_SOURCE -DWITH_INT_TRANSIT"
+
+fabric-spgw:
+ @${tofino_compile} fabric-spgw "-DWITH_SPGW"
+
+fabric-spgw-int:
+ @${tofino_compile} fabric-spgw-int "-DWITH_SPGW -DWITH_INT_SOURCE -DWITH_INT_TRANSIT"
+
+# Reuse the same container to persist mvn repo cache.
+_create_mvn_container:
+ @if ! docker container ls -a --format '{{.Names}}' | grep -q ${mvn_container} ; then \
+ docker create -v ${curr_dir}:/mvn-src -w /mvn-src --name ${mvn_container} ${mvn_image} mvn clean package verify; \
+ fi
+
+_mvn_package:
+ $(info *** Building ONOS app...)
+ @mkdir -p target
+ @docker start -a -i ${mvn_container}
+
+pipeconf: _create_mvn_container _mvn_package
+ $(info *** ONOS pipeconf .oar package created succesfully)
+ @ls -1 ${curr_dir}/target/*.oar
+
+pipeconf-install:
+ $(info *** Installing and activating pipeconf app in ONOS at ${ONOS_HOST}...)
+ ${onos_curl} -X POST -HContent-Type:application/octet-stream \
+ '${onos_url}/v1/applications?activate=true' \
+ --data-binary @target/fabric-tofino-${pipeconf_app_version}.oar
+ @echo
+
+pipeconf-uninstall:
+ $(info *** Uninstalling pipeconf app from ONOS (if present) at ${ONOS_HOST}...)
+ -${onos_curl} -X DELETE ${onos_url}/v1/applications/${pipeconf_app_name}
+ @echo
+
+netcfg:
+ $(info *** Pushing tofino-netcfg.json to ONOS at ${ONOS_HOST}...)
+ ${onos_curl} -X POST -H 'Content-Type:application/json' \
+ ${onos_url}/v1/network/configuration -d@./tofino-netcfg.json
+ @echo
+
+clean:
+ -rm -rf src/main/resources/p4c-out
+
+deep-clean: clean
+ -rm -rf target
+ -rm -rf p4c-out
+ -docker rm ${mvn_container} > /dev/null 2>&1
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..27f2161
--- /dev/null
+++ b/README.md
@@ -0,0 +1,242 @@
+# ONOS Fabric Pipeconf for Tofino
+
+This repository contains instructions and scripts to compile and use
+`fabric.p4` on Intel/Barefoot Tofino-enabled switches.
+
+[fabric.p4][fabric.p4] is a P4 program distributed as part of ONOS,
+designed to work with [Trellis](trellis), a set
+of SDN applications running on top of ONOS to provide the control plane for an
+IP fabric based on MPLS segment-routing.
+
+To use ONOS to control a Tofino-enabled switch, you will need to run the
+[Stratum][stratum] agent on the switch.
+
+## Requirements
+
+* Barefoot SDE >= 8.9 (with the P4_16 compiler for Tofino)
+* ONOS >= 2.2.1
+* Docker (to run the build scripts without worrying about dependencies)
+* cURL (to interact with the ONOS REST APIs)
+
+## Steps to build Tofino-enabled fabric.p4 pipeconfs
+
+ONOS uses "pipeconfs" to deploy and manage a given P4 program on a device.
+Pipeconfs are distrubuted as ONOS applications, hence using the `.oar`
+packaging. The following steps provide instructions on how to generate an oar
+package that includes a compiled version of `fabric.p4` that works on Tofino.
+
+* `src/main/java`: contains Java code that implements the ONOS app responsible
+ of registering the Tofino-enabled pipeconfs in ONOS;
+* `src/main/p4`: contains code to compile fabric.p4 for Tofino.
+
+To learn more about pipeconfs and how ONOS supports P4-programmable devices:
+<https://github.com/opennetworkinglab/ngsdn-tutorial>
+
+### 1 - Obtain fabric.p4 sources from ONOS
+
+`fabric.p4` is distributed as part of ONOS. We recommend using the
+`onos-2.2` branch, which is an LTS branch.
+
+```bash
+git clone -b onos-2.2 https://github.com/opennetworkinglab/onos
+```
+
+Set the `ONOS_ROOT` env variable to the location where ONOS was cloned:
+
+```bash
+export ONOS_ROOT=$PWD/onos
+```
+
+### 2 - Build Tofino-enabled fabric pipeconf
+
+To build `fabric.p4` using the Barefoot compiler and to create the pipeconf
+`.oar` package:
+
+```bash
+cd fabric-tofino # this repo
+make build PROFILES=all
+```
+
+#### Fabric profiles
+
+The above command will build the `fabric.p4` profiles specified in the
+`PROFILES` argument. Possible values are:
+
+| Profile name | Description |
+| ------------------------|----------------------------------------------------|
+| `fabric` | Basic profile |
+| `fabric-bng` | With BNG user plane support |
+| `fabric-spgw` | With SPGW user plane support |
+| `fabric-int` | With INT (spec v0.5) source and transit |
+| `fabric-spgw-int` | WITH SPGW and INT support |
+
+Check the `Makefile` for other profiles.
+
+To build all profiles: `PROFILES=all`.
+
+To build a subset of the available profiles: `PROFILES="fabric fabric-bng"`
+
+The P4 compiler outputs to include in the `.oar` package (such as `tofino.bin`,
+`context.json`, and `p4info.txt`) will be placed under
+`src/main/resources/p4c-out`.
+
+When done, the pipeconf `.oar` package can be found in
+`target/fabric-tofino-<VERSION>.oar`
+
+#### Using containerized version of the Barefoot SDE / p4c compilers
+
+The previous command expects the `bf-p4c` compiler to be installed locally. As an
+alternative, the build script supports using a Docker-based distribution of the
+Barefoot SDE / p4c compilers. To do so, simply set the `SDE_DOCKER_IMG`
+make argument (or environment variable) to a Docker image that can be downloaded
+via `docker pull`, for example:
+
+```bash
+make build SDE_DOCKER_IMG=my-docker-repo/bf-sde:9.0.0 PROFILES=all
+```
+
+The build script will use `docker run` to invoke the `bf-p4c` command inside the
+given image. For this reason, the script expects a Docker image that has the
+whole Barefoot SDE installed in it or just the p4c package. In both cases, the
+`bf-p4c` executable should be on `PATH`. We do not provide such image, but one
+can be easily generated by executing the SDE install instructions inside a
+Dockerfile.
+
+## Steps to use the Tofino-enabled fabric pipeconf with ONOS
+
+### 1 - Get and run ONOS
+
+The minimum required ONOS version that works with this pipeconf is 2.2.1.
+
+You can either build from sources (using the `onos-2.2` or `master` branch), or
+run one the released versions:
+<https://wiki.onosproject.org/display/ONOS/Downloads>
+
+Pre-built ONOS Docker images are available here:
+<https://hub.docker.com/r/onosproject/onos/tags>
+
+For more information on how to get and run ONOS:
+<https://wiki.onosproject.org/display/ONOS/Guides>
+
+### 2 - Start Stratum on your switch
+
+For instructions on how to install and run Stratum on Tofino-enabled switches:
+<https://github.com/stratum/stratum/tree/master/stratum/hal/bin/barefoot>
+
+### 3 - Install pipeconf app in ONOS
+
+To install the pipeconf app built in the previous step, assuming ONOS is
+running on the local machine:
+
+```bash
+make pipeconf-install ONOS_HOST=localhost
+```
+
+Use the `ONOS_HOST` argument to specify the hostname/IP address of the machine
+where ONOS is running.
+
+This command is a wrapper to a `curl` command that uses the ONOS REST API to
+upload and activate the `.oar` package previously built.
+
+You should see the ONOS log updating with messages notifying the registration of
+new Tofino-specific pipeconfs in the system, depending on the `fabric.p4`
+profiles compiled before and the Barefoot SDE/p4c version used:
+
+```
+New pipeconf registered: org.opencord.fabric.tofino.mavericks_sde_9_0_0 (fingerprint=...)
+New pipeconf registered: org.opencord.fabric.tofino.montara_sde_9_0_0 (fingerprint=...)
+New pipeconf registered: org.opencord.fabric-bng.tofino.mavericks_sde_9_0_0 (fingerprint=...)
+New pipeconf registered: org.opencord.fabric-bng.tofino.montara_sde_9_0_0 (fingerprint=...)
+...
+```
+
+**NOTE: it might take up to one minute for the pipeconfs to be registered.
+This is currently a bug and will be fixed soon.**
+
+To check all pipeconfs registered in the system, use the ONOS CLI:
+
+```
+onos> pipeconfs
+```
+
+### 4 - Connect ONOS to a Stratum switch
+
+Activate the Barefoot drivers in ONOS:
+
+```
+onos> app activate org.onosproject.drivers.barefoot
+```
+
+This command will register a new driver named `stratum-tofino`. As the name
+suggests, this driver allows ONOS to control Tofino-enabled Stratum switches.
+
+For ONOS to be able to discover your switch, you need to push a JSON file,
+usually referred to as the "netcfg" file. We provide an example of such
+`tofino-netcfg.json` file in this repository. Make sure to modify the following
+values:
+
+* `managementAddress` is expected to contain a valid URI with host and port of
+ the Stratum gRPC server running on the switch;
+* The `device_id` URI query parameter is the P4Runtime-internal `device_id`,
+ also known as the Stratum "Node ID". Usually, you can leave this value set to
+ `1`;
+* Use the `pipeconf` field to specify which pipeconf/fabric profile to deploy on
+ the switch.
+
+Push the `tofino-netcfg.json` to ONOS using the command:
+
+```
+make netcfg ONOS_HOST=localhost
+```
+
+Like before, this command is a wrapper to a `curl` command that uses the ONOS
+REST API to push the `tofino-netcfg.json` file.
+
+Check the ONOS log for potential errors.
+
+## Using Trellis with Stratum+Tofino switches
+
+Check the official Trellis documentation here:
+<https://docs.trellisfabric.org>
+
+In the "Device Configuration" section:
+<https://docs.trellisfabric.org/configuration/device-config.html>
+
+make sure to replace the `basic` JSON node for OpenFlow devices with the one
+provided in `tofino-netcfg.json`, for example:
+
+```json
+{
+ "devices" : {
+ "device:leaf-1" : {
+ "segmentrouting" : {
+ "ipv4NodeSid" : 101,
+ "ipv4Loopback" : "192.168.0.201",
+ "ipv6NodeSid" : 111,
+ "ipv6Loopback" : "2000::c0a8:0201",
+ "routerMac" : "00:00:00:00:02:01",
+ "isEdgeRouter" : true,
+ "adjacencySids" : []
+ },
+ "basic": {
+ "managementAddress": "grpc://10.0.0.1:28000?device_id=1",
+ "driver": "stratum-tofino",
+ "pipeconf": "org.opencord.fabric.tofino.montara_sde_9_0_0"
+ }
+ }
+ }
+}
+```
+
+## Support
+
+To report issues when compiling `fabric.p4` for Tofino (i.e., compiler errors),
+please contact Intel/Barefoot support.
+
+To get help with ONOS and the fabric pipeconf, please contact
+<brigade-p4@onosproject.org> (this is a public mailing list, please beware of
+not discussing information under Intel/Barefoot NDA)
+
+[stratum]: https://github.com/stratum/stratum
+[trellis]: https://www.opennetworking.org/trellis
+[fabric.p4]: https://github.com/opennetworkinglab/onos/tree/master/pipelines/fabric/impl/src/main/resources
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..d377ec6
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2019 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-dependencies</artifactId>
+ <version>2.2.1-b3</version>
+ </parent>
+
+ <groupId>org.opencord</groupId>
+ <artifactId>fabric-tofino</artifactId>
+ <version>2.2.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <description>Pipeconf to use Trellis with Tofino-based targets</description>
+ <url>http://www.opencord.org</url>
+
+ <properties>
+ <onos.app.name>org.opencord.fabric-tofino</onos.app.name>
+ <onos.app.title>Tofino-enabled Fabric Pipeconf</onos.app.title>
+ <onos.app.origin>http://www.opencord.org</onos.app.origin>
+ <onos.app.category>Pipeline</onos.app.category>
+ <onos.app.url>http://www.opencord.org</onos.app.url>
+ <onos.app.readme>
+ Provides pipeconfs based on fabric.p4 to use Trellis with Barefoot
+ Tofino-based switches.
+ </onos.app.readme>
+ <onos.app.requires>
+ org.onosproject.pipelines.fabric
+ </onos.app.requires>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${onos.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-osgi</artifactId>
+ <version>${onos.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-pipelines-fabric-api</artifactId>
+ <version>${onos.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/src/main/java/org/opencord/fabric/tofino/PipeconfLoader.java b/src/main/java/org/opencord/fabric/tofino/PipeconfLoader.java
new file mode 100644
index 0000000..f6b60e9
--- /dev/null
+++ b/src/main/java/org/opencord/fabric/tofino/PipeconfLoader.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2019-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.opencord.fabric.tofino;
+
+import org.onosproject.core.CoreService;
+import org.onosproject.net.pi.model.DefaultPiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconf.ExtensionType;
+import org.onosproject.net.pi.model.PiPipeconfId;
+import org.onosproject.net.pi.service.PiPipeconfService;
+import org.onosproject.pipelines.fabric.FabricPipeconfService;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.wiring.BundleWiring;
+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.io.File;
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static java.lang.String.format;
+import static org.osgi.framework.wiring.BundleWiring.LISTRESOURCES_RECURSE;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Component responsible of registering Tofino-specific versions
+ * of the fabric pipeconf at app activation.
+ */
+@Component(immediate = true)
+public class PipeconfLoader {
+
+ private static final String APP_NAME = "org.opencord.fabric-tofino";
+
+ private static Logger log = getLogger(PipeconfLoader.class);
+
+ private static final String BASE_PIPECONF_ID = "org.opencord";
+ private static final String P4C_OUT_PATH = "/p4c-out";
+ // p4c-out/<profile>/<platform>
+ private static final String P4C_RES_BASE_PATH = P4C_OUT_PATH + "/%s/%s/%s/";
+ private static final String SEP = File.separator;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ private PiPipeconfService pipeconfService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ private FabricPipeconfService fabricPipeconfService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ private CoreService coreService;
+
+ private Collection<PiPipeconf> pipeconfs;
+
+ private static final String TOFINO = "tofino";
+ private static final String P4INFO_TXT = "p4info.txt";
+ private static final String CPU_PORT_TXT = "cpu_port.txt";
+ private static final String TOFINO_BIN = "pipe/tofino.bin";
+ private static final String TOFINO_CTX_JSON = "pipe/context.json";
+
+
+ @Activate
+ public void activate() {
+ coreService.registerApplication(APP_NAME);
+ // Registers all pipeconf at component activation.
+ pipeconfs = buildAllPipeconfs();
+ pipeconfs.forEach(pipeconfService::register);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ pipeconfs.stream()
+ .map(PiPipeconf::id)
+ .forEach(pipeconfService::unregister);
+ pipeconfs = null;
+ log.info("Stopped");
+ }
+
+ private Collection<PiPipeconf> buildAllPipeconfs() {
+ return FrameworkUtil
+ .getBundle(this.getClass())
+ .adapt(BundleWiring.class)
+ // List all resource files in /p4c-out
+ .listResources(P4C_OUT_PATH, "*", LISTRESOURCES_RECURSE)
+ .stream()
+ // Filter only directories
+ .filter(name -> name.endsWith(SEP))
+ // Derive profile, target, and platform and build pipeconf.
+ .map(this::buildPipeconfFromPath)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
+ private PiPipeconf buildPipeconfFromPath(String path) {
+ String[] pieces = path.split(SEP);
+ // We expect a path of 4 elements, e.g.
+ // p4c-out/<profile>/<target>/<platform>
+ if (pieces.length != 4) {
+ return null;
+ }
+ String profile = pieces[1];
+ String target = pieces[2];
+ String platform = pieces[3];
+
+ if (TOFINO.equals(target)) {
+ try {
+ return tofinoPipeconf(profile, platform);
+ } catch (FileNotFoundException e) {
+ log.warn("Unable to build pipeconf at {} because file is missing: {}",
+ path, e.getMessage());
+ return null;
+ }
+ }
+
+ log.warn("Unknown target '{}', skipping pipeconf build at '{}'...",
+ target, path);
+ return null;
+ }
+
+ private PiPipeconf tofinoPipeconf(String profile, String platform)
+ throws FileNotFoundException {
+ final URL tofinoBinUrl = this.getClass().getResource(format(
+ P4C_RES_BASE_PATH + TOFINO_BIN, profile, TOFINO, platform));
+ final URL contextJsonUrl = this.getClass().getResource(format(
+ P4C_RES_BASE_PATH + TOFINO_CTX_JSON, profile, TOFINO, platform));
+ final URL p4InfoUrl = this.getClass().getResource(format(
+ P4C_RES_BASE_PATH + P4INFO_TXT, profile, TOFINO, platform));
+ final URL cpuPortUrl = this.getClass().getResource(format(
+ P4C_RES_BASE_PATH + CPU_PORT_TXT, profile, TOFINO, platform));
+
+ checkFileExists(tofinoBinUrl, TOFINO_BIN);
+ checkFileExists(contextJsonUrl, TOFINO_CTX_JSON);
+ checkFileExists(p4InfoUrl, P4INFO_TXT);
+ checkFileExists(cpuPortUrl, CPU_PORT_TXT);
+
+ final DefaultPiPipeconf.Builder builder = DefaultPiPipeconf.builder()
+ .withId(new PiPipeconfId(format(
+ "%s.%s.tofino.%s", BASE_PIPECONF_ID, profile, platform)))
+ .addExtension(ExtensionType.TOFINO_BIN, tofinoBinUrl)
+ .addExtension(ExtensionType.TOFINO_CONTEXT_JSON, contextJsonUrl);
+
+ return fabricPipeconfService.buildFabricPipeconf(
+ builder, profile, p4InfoUrl, cpuPortUrl);
+ }
+
+ private void checkFileExists(URL url, String name)
+ throws FileNotFoundException {
+ if (url == null) {
+ throw new FileNotFoundException(name);
+ }
+ }
+}
diff --git a/src/main/java/org/opencord/fabric/tofino/package-info.java b/src/main/java/org/opencord/fabric/tofino/package-info.java
new file mode 100644
index 0000000..2e69823
--- /dev/null
+++ b/src/main/java/org/opencord/fabric/tofino/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2019-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.
+ */
+
+/**
+ * Fabric-tofino pipeconf loader app.
+ */
+package org.opencord.fabric.tofino;
\ No newline at end of file
diff --git a/src/main/p4/fabric-tofino.p4 b/src/main/p4/fabric-tofino.p4
new file mode 100755
index 0000000..7b81449
--- /dev/null
+++ b/src/main/p4/fabric-tofino.p4
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019-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.
+ */
+
+#define _PKT_OUT_HDR_ANNOT @not_extracted_in_egress
+
+#define _BOOL bit<1>
+#define _TRUE 1w1
+#define _FALSE 1w0
+
+#ifdef WITH_INT_TRANSIT
+#define _PRE_INGRESS fabric_metadata.int_meta.ig_tstamp = (bit<32>) standard_metadata.ingress_global_timestamp;
+#define _PRE_EGRESS fabric_metadata.int_meta.eg_tstamp = (bit<32>) standard_metadata.egress_global_timestamp;
+#endif // WITH_INT_TRANSIT
+
+#define _INT_INIT_METADATA \
+ hdr.int_switch_id.switch_id = switch_id;\
+ hdr.int_port_ids.ingress_port_id = (bit<16>) smeta.ingress_port;\
+ hdr.int_port_ids.egress_port_id = (bit<16>) smeta.egress_port;\
+ hdr.int_ingress_tstamp.ingress_tstamp = fmeta.int_meta.ig_tstamp;\
+ hdr.int_egress_tstamp.egress_tstamp = fmeta.int_meta.eg_tstamp;\
+ hdr.int_hop_latency.hop_latency = (bit<32>) smeta.egress_global_timestamp - (bit<32>) smeta.ingress_global_timestamp;\
+ hdr.int_q_occupancy.q_id = 8w0;\
+ hdr.int_q_occupancy.q_occupancy = (bit<24>) smeta.deq_qdepth;\
+ hdr.int_q_congestion.q_id = 8w0;\
+ hdr.int_q_congestion.q_congestion = 24w0;\
+ hdr.int_egress_tx_util.egress_port_tx_util = 32w0;\
+
+#define _INT_METADATA_ACTIONS \
+ action int_set_header_0() { hdr.int_switch_id.setValid(); }\
+ action int_set_header_1() { hdr.int_port_ids.setValid(); }\
+ action int_set_header_2() { hdr.int_hop_latency.setValid(); }\
+ action int_set_header_3() { hdr.int_q_occupancy.setValid(); }\
+ action int_set_header_4() { hdr.int_ingress_tstamp.setValid(); }\
+ action int_set_header_5() { hdr.int_egress_tstamp.setValid(); }\
+ action int_set_header_6() { hdr.int_q_congestion.setValid(); }\
+ action int_set_header_7() { hdr.int_egress_tx_util.setValid(); }\
+
+#define __TABLE_SIZE__
+#define BNG_MAX_SUBSC 1024
+#define BNG_MAX_NET_PER_SUBSC 4
+#define BNG_MAX_SUBSC_NET BNG_MAX_NET_PER_SUBSC * BNG_MAX_SUBSC
+#ifdef WITH_BNG
+ #define PORT_VLAN_TABLE_SIZE BNG_MAX_SUBSC + 2048
+#else
+ #define PORT_VLAN_TABLE_SIZE 2048
+#endif // WITH_BNG
+#define FWD_CLASSIFIER_TABLE_SIZE 128
+#define BRIDGING_TABLE_SIZE 2048
+#define MPLS_TABLE_SIZE 2048
+#ifdef WITH_BNG
+ #define ROUTING_V4_TABLE_SIZE BNG_MAX_SUBSC_NET + 1024
+#else
+ #define ROUTING_V4_TABLE_SIZE 30000
+#endif // WITH_BNG
+#define ACL_TABLE_SIZE 2048
+// Depends on number of unique next_id expected
+#define NEXT_VLAN_TABLE_SIZE 2048
+#define XCONNECT_NEXT_TABLE_SIZE 4096
+#define SIMPLE_NEXT_TABLE_SIZE 2048
+#define HASHED_NEXT_TABLE_SIZE 2048
+// Max size of ECMP groups
+#define HASHED_SELECTOR_MAX_GROUP_SIZE 16
+// Ideally HASHED_NEXT_TABLE_SIZE * HASHED_SELECTOR_MAX_GROUP_SIZE
+#define HASHED_ACT_PROFILE_SIZE 32w32768
+#define MULTICAST_NEXT_TABLE_SIZE 2048
+#define EGRESS_VLAN_TABLE_SIZE 2048
+
+#define _ROUTING_V4_TABLE_ANNOT @alpm(1)
+
+#include "fabric.p4"
diff --git a/src/main/p4/tofino-compile.sh b/src/main/p4/tofino-compile.sh
new file mode 100755
index 0000000..cab4c0c
--- /dev/null
+++ b/src/main/p4/tofino-compile.sh
@@ -0,0 +1,82 @@
+#!/usr/bin/env bash
+# Copyright 2019-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.
+
+MAVERICKS_CPU_PORT=320
+MONTARA_CPU_PORT=192
+
+if [ -z "$ONOS_ROOT" ]; then
+ echo "Error: ONOS_ROOT is not set"
+ exit 1
+fi
+
+P4_SRC_DIR=${ONOS_ROOT}/pipelines/fabric/impl/src/main/resources
+
+if [ ! -d "${P4_SRC_DIR}" ]; then
+ echo "Error: unable to locate fabric P4 sources at ${P4_SRC_DIR}"
+fi
+
+set -e
+
+PROFILE=$1
+OTHER_PP_FLAGS=$2
+
+# PWD is the directory where this script is called from (should be the root of
+# this repo).
+P4C_OUT=${PWD}/p4c-out/${PROFILE}
+
+# DIR is this file directory.
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+# Where the compiler output should be placed to be included in the pipeconf.
+DEST_DIR=${DIR}/../resources/p4c-out/${PROFILE}/tofino
+
+# If SDE_DOCKER_IMG env is set, use containerized version of the compiler
+if [ -z "${SDE_DOCKER_IMG}" ]; then
+ P4C_CMD="bf-p4c"
+else
+ P4C_CMD="docker run --rm -v ${P4C_OUT}:${P4C_OUT} -v ${P4_SRC_DIR}:${P4_SRC_DIR} -v ${DIR}:${DIR} -w ${DIR} ${SDE_DOCKER_IMG} bf-p4c"
+fi
+
+SDE_VER=$( ${P4C_CMD} --version | cut -d' ' -f2 )
+
+# shellcheck disable=SC2086
+function do_p4c() {
+ pltf="$1_sde_${SDE_VER//./_}"
+ cpu_port=$2
+ echo "*** Compiling profile '${PROFILE}' for ${pltf} platform..."
+ echo "*** Output in ${P4C_OUT}/${pltf}"
+ pp_flags="-DCPU_PORT=${cpu_port}"
+ mkdir -p ${P4C_OUT}/${pltf}
+ (
+ set -x
+ $P4C_CMD --arch v1model -g \
+ -o ${P4C_OUT}/${pltf} -I ${P4_SRC_DIR} \
+ ${pp_flags} ${OTHER_PP_FLAGS} \
+ --p4runtime-files ${P4C_OUT}/${pltf}/p4info.txt \
+ ${DIR}/fabric-tofino.p4
+ )
+
+ # Copy only the relevant files to the pipeconf resources
+ mkdir -p ${DEST_DIR}/${pltf}/pipe
+ cp ${P4C_OUT}/${pltf}/p4info.txt ${DEST_DIR}/${pltf}
+ cp ${P4C_OUT}/${pltf}/pipe/context.json ${DEST_DIR}/${pltf}/pipe
+ cp ${P4C_OUT}/${pltf}/pipe/tofino.bin ${DEST_DIR}/${pltf}/pipe
+ echo "${cpu_port}" > ${DEST_DIR}/${pltf}/cpu_port.txt
+
+ echo
+}
+
+do_p4c "mavericks" ${MAVERICKS_CPU_PORT}
+do_p4c "montara" ${MONTARA_CPU_PORT}
diff --git a/tofino-netcfg.json b/tofino-netcfg.json
new file mode 100644
index 0000000..b521fdb
--- /dev/null
+++ b/tofino-netcfg.json
@@ -0,0 +1,11 @@
+{
+ "devices": {
+ "device:my-tofino-switch": {
+ "basic": {
+ "managementAddress": "grpc://10.0.0.1:28000?device_id=1",
+ "driver": "stratum-tofino",
+ "pipeconf": "org.opencord.fabric.tofino.montara_sde_9_0_0"
+ }
+ }
+ }
+}
\ No newline at end of file