├── .dockerignore ├── .github └── workflows │ ├── ci.yml │ └── publish.yaml ├── .gitignore ├── .gitmodules ├── Doxyfile ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── docker ├── base.Dockerfile ├── builder.Dockerfile └── run.Dockerfile ├── docs ├── 20181018_Introduction to the Transponder Abstraction Interface.pdf ├── 20191018_TAI Deep Dive.pdf ├── 20191018_TAI Demo - Voyager.pdf ├── 20191018_TAI Licensing and Governance.pdf ├── 20191018_TAI_Workshop_Fujitsu_3.pdf ├── 20210616_0_TAI_workshop.pdf ├── 20210616_1_background_history.pdf ├── 20210616_2_attribute_enhancement.pdf ├── 20210616_4_nec-tai-workshop-jun-16-17-2021.pdf ├── 20211105_TAI.pdf ├── TAI-MUX.pdf ├── attributes.md └── objects.md ├── inc ├── tai.h ├── taihostif.h ├── taimeta.h ├── taimetadatatypes.h ├── taimodule.h ├── tainetworkif.h ├── taistatus.h └── taitypes.h ├── logo └── logo.png ├── meta ├── .gitignore ├── Makefile ├── README.md ├── cJSON.c ├── cJSON.h ├── sample │ ├── Makefile │ └── custom.h ├── taimetadatalogger.h ├── taimetadatautils.c ├── taimetadatautils.h ├── taiserialize.c ├── taiserialize.h └── test │ ├── .gitignore │ ├── Makefile │ └── test.c ├── stub ├── .gitignore ├── Makefile ├── README.md └── stub_tai.c ├── tests ├── .gitignore ├── Makefile ├── config.json ├── test.c └── test_base.py └── tools ├── framework ├── README.md ├── config.hpp ├── examples │ ├── .gitignore │ ├── basic │ │ ├── Makefile │ │ ├── basic.cpp │ │ ├── basic.hpp │ │ └── custom │ │ │ ├── module.h │ │ │ └── netif.h │ └── stub │ │ ├── Makefile │ │ ├── stub.cpp │ │ └── stub.hpp ├── fsm.hpp ├── make │ └── lib.mk ├── object.hpp ├── platform.hpp └── tai.cpp ├── lib ├── README.md ├── attribute.cpp ├── attribute.hpp ├── capability.hpp ├── exception.hpp ├── logger.hpp └── test │ ├── .gitignore │ ├── Makefile │ └── test.cpp ├── meta-generator ├── .gitignore ├── setup.cfg ├── setup.py └── tai_meta_generator │ ├── __init__.py │ └── main.py └── taish ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── client ├── .gitignore ├── Makefile └── taish │ ├── __init__.py │ ├── cli.py │ └── main.py ├── config └── sample.json ├── include └── taigrpc.hpp ├── lib └── server.cpp ├── proto └── taish │ └── taish.proto ├── requirements.txt ├── server ├── json.hpp └── main.cpp └── setup.py /.dockerignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/.dockerignore -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - 12 | name: Checkout 13 | uses: actions/checkout@v2 14 | - 15 | name: Set up Docker Buildx 16 | uses: docker/setup-buildx-action@v1 17 | with: 18 | driver: docker-container 19 | driver-opts: | 20 | image=moby/buildkit:master 21 | network=host 22 | - 23 | name: Set up QEMU 24 | uses: docker/setup-qemu-action@v1 25 | - 26 | name: Set up local container registry 27 | run: docker run -d -p 5000:5000 registry 28 | - 29 | name: Build builder 30 | uses: docker/build-push-action@v2 31 | with: 32 | context: . 33 | platforms: linux/amd64,linux/arm64 34 | file: ./docker/builder.Dockerfile 35 | tags: | 36 | localhost:5000/tai-builder:${{ github.sha }} 37 | push: true 38 | cache-from: type=registry,ref=docker.io/microsonic/tai-builder:latest 39 | cache-to: type=inline 40 | - 41 | name: Build container 42 | uses: docker/build-push-action@v2 43 | with: 44 | context: . 45 | build-args: | 46 | TAI_DOCKER_BUILDER_IMAGE=localhost:5000/tai-builder:${{ github.sha }} 47 | platforms: linux/amd64,linux/arm64 48 | file: ./docker/run.Dockerfile 49 | tags: | 50 | localhost:5000/tai:${{ github.sha }} 51 | push: true 52 | cache-from: type=registry,ref=docker.io/microsonic/tai:latest 53 | cache-to: type=inline 54 | - 55 | name: Run test 56 | run: make ci 57 | env: 58 | TAI_DOCKER_CMD_IMAGE: localhost:5000/tai-builder:${{ github.sha }} 59 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | jobs: 8 | job: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - 12 | name: Checkout 13 | uses: actions/checkout@v2 14 | - run: | 15 | import os 16 | ref = os.environ['GITHUB_REF'] 17 | branch = ref[11:] 18 | with open(os.environ['GITHUB_ENV'], "a") as f: 19 | tag = "latest" if branch == "master" else branch 20 | f.write(f"DOCKER_IMAGE_TAG={tag}\n") 21 | shell: python 22 | - 23 | name: Set up Docker Buildx 24 | uses: docker/setup-buildx-action@v1 25 | - 26 | name: Set up QEMU 27 | uses: docker/setup-qemu-action@v1 28 | - 29 | name: Login to GitHub Container Registry 30 | uses: docker/login-action@v1 31 | with: 32 | username: ${{ secrets.DOCKER_USER }} 33 | password: ${{ secrets.DOCKER_PASSWORD }} 34 | - 35 | name: Build builder 36 | uses: docker/build-push-action@v2 37 | with: 38 | context: . 39 | platforms: linux/amd64,linux/arm64 40 | file: ./docker/builder.Dockerfile 41 | tags: | 42 | docker.io/microsonic/tai-builder:${{ env.DOCKER_IMAGE_TAG }} 43 | push: true 44 | cache-from: type=registry,ref=docker.io/microsonic/tai-builder:latest 45 | cache-to: type=inline 46 | - 47 | name: Build container 48 | uses: docker/build-push-action@v2 49 | with: 50 | context: . 51 | build-args: | 52 | TAI_DOCKER_BUILDER_IMAGE=docker.io/microsonic/tai-builder:${{ env.DOCKER_IMAGE_TAG }} 53 | platforms: linux/amd64,linux/arm64 54 | file: ./docker/run.Dockerfile 55 | tags: | 56 | docker.io/microsonic/tai:${{ env.DOCKER_IMAGE_TAG }} 57 | push: true 58 | cache-from: type=registry,ref=docker.io/microsonic/tai:latest 59 | cache-to: type=inline 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | doc 2 | *.o 3 | *.d 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/.gitmodules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Telecom Infra Project 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: doc stub test docker meta 2 | 3 | TAI_DOCKER_CMD ?= bash 4 | TAI_DOCKER_IMAGE ?= tai 5 | TAI_DOCKER_BUILDER_IMAGE ?= tai-builder 6 | TAI_DOCKER_CMD_IMAGE ?= $(TAI_DOCKER_BUILDER_IMAGE) 7 | TAI_DOCKER_MOUNT ?= "$(PWD):/data" 8 | TAI_DOCKER_WORKDIR ?= "/data" 9 | TAI_DOCKER_RUN_OPTION ?= -it --rm 10 | 11 | all: meta stub 12 | 13 | meta: 14 | $(MAKE) -C ./meta 15 | 16 | doc: 17 | doxygen Doxyfile 18 | 19 | stub: 20 | $(MAKE) -C ./stub 21 | 22 | test: 23 | TAI_TEST_TARGET=$(abspath ./stub/libtai.so) $(MAKE) -C ./tests c 24 | $(MAKE) -C ./tests 25 | 26 | cmd: 27 | docker run $(TAI_DOCKER_RUN_OPTION) -v $(TAI_DOCKER_MOUNT) -w $(TAI_DOCKER_WORKDIR) $(TAI_DOCKER_CMD_IMAGE) $(TAI_DOCKER_CMD) 28 | 29 | image: 30 | DOCKER_BUILDKIT=1 docker build $(TAI_DOCKER_BUILD_OPTION) --build-arg TAI_DOCKER_BUILDER_IMAGE=$(TAI_DOCKER_BUILDER_IMAGE) \ 31 | -f docker/run.Dockerfile \ 32 | -t $(TAI_DOCKER_IMAGE) . 33 | 34 | builder: 35 | DOCKER_BUILDKIT=1 docker build $(TAI_DOCKER_BUILD_OPTION) -f docker/builder.Dockerfile \ 36 | -t $(TAI_DOCKER_BUILDER_IMAGE) . 37 | 38 | bash: 39 | $(MAKE) cmd 40 | 41 | ci: 42 | TAI_DOCKER_RUN_OPTION='--rm' TAI_DOCKER_CMD="make test" $(MAKE) cmd 43 | 44 | clean: 45 | $(MAKE) -C ./meta clean 46 | $(MAKE) -C ./stub clean 47 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This source code includes following software 2 | 3 | - SAI : licensed by Microsoft under the Apache License, Version 2.0 4 | - cJSON : licensed by Dave Gamble and cJSON contributors under MIT License 5 | - JSON for Modern C++ : licensed by Niels Lohmann under MIT License 6 | -------------------------------------------------------------------------------- /docker/base.Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1.2 2 | FROM ubuntu:20.04 3 | 4 | ARG http_proxy 5 | ARG https_proxy 6 | 7 | ARG TARGETARCH 8 | 9 | RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -qy libgrpc++-dev g++ protobuf-compiler-grpc make pkg-config python3 python3-pip curl python3-distutils libclang1-6.0 doxygen git 10 | 11 | RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 10 12 | RUN update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 10 13 | RUN --mount=type=cache,target=/root/.cache,sharing=private pip install grpcio grpcio-tools prompt_toolkit tabulate 14 | -------------------------------------------------------------------------------- /docker/builder.Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1.2 2 | FROM python:bullseye 3 | 4 | ARG http_proxy 5 | ARG https_proxy 6 | 7 | ARG TARGETARCH 8 | 9 | RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -qy libgrpc++-dev protobuf-compiler-grpc 10 | 11 | RUN `([ $TARGETARCH = arm64 ] && echo /usr/lib/aarch64-linux-gnu > /tmp/lib ) || ([ $TARGETARCH = amd64 ] && echo /usr/lib/x86_64-linux-gnu > /tmp/lib )` 12 | 13 | RUN --mount=type=bind,source=tools/meta-generator,target=/root,rw cd /root && pip install . 14 | RUN --mount=type=bind,target=/root,rw cd /root && make -C meta && cp meta/libmetatai.so `cat /tmp/lib` && cp meta/tai*.h /usr/local/include/ 15 | RUN --mount=type=bind,target=/root,rw cd /root && make -C tools/framework/examples/basic && cp tools/framework/examples/basic/libtai-basic.so `cat /tmp/lib`/ 16 | RUN cd `cat /tmp/lib` && ln -s libtai-basic.so libtai.so 17 | RUN --mount=type=bind,target=/root,rw cd /root && make -C tools/taish && cp tools/taish/taish_server /usr/local/bin/ 18 | RUN --mount=type=bind,target=/root,rw cd /root && make -C tools/taish python && cp tools/taish/dist/*.whl /tmp/ 19 | -------------------------------------------------------------------------------- /docker/run.Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1.2 2 | ARG TAI_DOCKER_BUILDER_IMAGE=tai-builder:latest 3 | 4 | FROM ${TAI_DOCKER_BUILDER_IMAGE} as builder 5 | 6 | FROM python:slim-bullseye 7 | 8 | ARG http_proxy 9 | ARG https_proxy 10 | 11 | RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache 12 | RUN --mount=type=cache,target=/var/cache/apt,sharing=private --mount=type=cache,target=/var/lib/apt,sharing=private \ 13 | apt update && DEBIAN_FRONTEND=noninteractive apt install -qy --no-install-recommends libgrpc++1 14 | 15 | RUN --mount=type=bind,source=/tmp,target=/tmp,from=builder python -m pip install /tmp/*.whl 16 | RUN --mount=type=bind,target=/tmp,from=builder cp /tmp/`cat /tmp/tmp/lib`/libtai-basic.so `cat /tmp/tmp/lib` 17 | RUN --mount=type=bind,source=/tmp,target=/tmp,from=builder cd `cat /tmp/lib` && ln -s libtai-basic.so libtai.so 18 | 19 | RUN --mount=type=bind,target=/tmp,from=builder cp /tmp/`cat /tmp/tmp/lib`/libmetatai.so `cat /tmp/tmp/lib` 20 | RUN --mount=type=bind,target=/tmp,from=builder cp /tmp/usr/local/bin/taish_server /usr/local/bin/ 21 | -------------------------------------------------------------------------------- /docs/20181018_Introduction to the Transponder Abstraction Interface.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20181018_Introduction to the Transponder Abstraction Interface.pdf -------------------------------------------------------------------------------- /docs/20191018_TAI Deep Dive.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20191018_TAI Deep Dive.pdf -------------------------------------------------------------------------------- /docs/20191018_TAI Demo - Voyager.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20191018_TAI Demo - Voyager.pdf -------------------------------------------------------------------------------- /docs/20191018_TAI Licensing and Governance.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20191018_TAI Licensing and Governance.pdf -------------------------------------------------------------------------------- /docs/20191018_TAI_Workshop_Fujitsu_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20191018_TAI_Workshop_Fujitsu_3.pdf -------------------------------------------------------------------------------- /docs/20210616_0_TAI_workshop.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20210616_0_TAI_workshop.pdf -------------------------------------------------------------------------------- /docs/20210616_1_background_history.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20210616_1_background_history.pdf -------------------------------------------------------------------------------- /docs/20210616_2_attribute_enhancement.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20210616_2_attribute_enhancement.pdf -------------------------------------------------------------------------------- /docs/20210616_4_nec-tai-workshop-jun-16-17-2021.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20210616_4_nec-tai-workshop-jun-16-17-2021.pdf -------------------------------------------------------------------------------- /docs/20211105_TAI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/20211105_TAI.pdf -------------------------------------------------------------------------------- /docs/TAI-MUX.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/docs/TAI-MUX.pdf -------------------------------------------------------------------------------- /docs/attributes.md: -------------------------------------------------------------------------------- 1 | ## TAI attribute 2 | 3 | TAI attribute belongs to one of the TAI object. 4 | In TAI, hardware control is done by setting/getting an attribute of TAI object. 5 | 6 | Currently, three kinds of TAI object are defined, which are 7 | module, network interface and host interface. 8 | 9 | `tai_attribute_t` which is defined like below in `taitypes.h` represents the TAI attribute. 10 | 11 | ```c 12 | typedef struct _tai_attribute_t 13 | { 14 | tai_attr_id_t id; 15 | tai_attribute_value_t value; 16 | } tai_attribute_t; 17 | ``` 18 | 19 | `id` field is an identifier of the attribute. `value` fields contains the value of the attribute. 20 | `tai_attribute_value_t` is defined as an union and can contain various type of value. 21 | 22 | Each TAI object defines its attributes as an enum value. For example, TAI module has `tai_module_attr_t` 23 | defined in `taimodule.h`. Each enum value represents a TAI attribute and can be assigned to `id` field of `tai_attribute_t`. Every enum value must have doxygen style comment to describe the attribute. 24 | 25 | The comment must include `@type` tag and `@flags` tag. 26 | 27 | `@type` tag describes the value type of the attribute. It must be one of the TAI value type which `tai_attribute_value_t` contains or an enum type which is already defined. 28 | 29 | `@flag` tag describes what kind of operation is allowed for the attribute. Supported values are defined in `meta/taimetadatatypes.h` `tai_attr_flags_t`. 30 | 31 | For example, `TAI_MODULE_ATTR_LOCATION` is defined like below in `taimodule.h` 32 | 33 | ```c 34 | /** 35 | * @brief The location of the module 36 | * 37 | * Used (and required) in the tai_create_module_fn call. This allows the 38 | * adapter to uniquely identify the module. This could be a PCI address, 39 | * slot identifier, or other value that allows the adapter to determine 40 | * which optical module is being initialized. 41 | * 42 | * @type #tai_char_list_t 43 | * @flags MANDATORY_ON_CREATE | CREATE_ONLY 44 | */ 45 | TAI_MODULE_ATTR_LOCATION = TAI_MODULE_ATTR_START, 46 | ``` 47 | 48 | The type of the attribute is `tai_char_list_t` which can be accessed via `charlist` field of `tai_attribute_value_t`. 49 | 50 | The flags of the attribute are `MANDATORY_ON_CREATE` and `CREATE_ONLY` which means the attribute must be specified when creating TAI module object and can only be specified at the creation ( it can't be set to other value after the creation ). 51 | 52 | TAI meta library uses these information to provide allocation/serialization methods. 53 | 54 | Some TAI attribute values need allocation before calling set/get TAI API. For example, `tai_char_list_t` is defined like blow in `taitypes.h` and needs allocation for `list`. 55 | 56 | ```c 57 | typedef struct _tai_char_list_t 58 | { 59 | uint32_t count; 60 | char *list; 61 | } tai_char_list_t; 62 | ``` 63 | 64 | In TAI, it is caller's responsibility to allocate enough memory for the TAI API operations and de-allocation after the use. 65 | 66 | If allocated memory is not enough, TAI API must return `TAI_STATUS_BUFFER_OVERFLOW` error code with putting the required size in the value structure. 67 | 68 | If you're TAI application is written in C, it is recommended to use TAI meta library `tai_metadata_alloc_attr_value` and `tai_metadata_free_attr_value` for the memory management. 69 | If it is written in C++, it is recommended to use `tai::Attribute` class which is defined in `tools/lib/attribute.hpp`. 70 | -------------------------------------------------------------------------------- /docs/objects.md: -------------------------------------------------------------------------------- 1 | ## Example Platform 2 | 3 | - Facebook Voyager 4 | - Fixed 4 optical line ports 5 | - 2 Acacia AC400 (Dual Channel Module) 6 | - Edgecore Cassini 7 | - 8 plug-in-unit(PIU) slots 8 | - 3 types of PIU 9 | 1. CFP2ACO PIU 10 | 2. CFP2DCO PIU 11 | 3. QSFP28 PIU ( out of scope for TAI ) 12 | 13 | ## module, network-interface, host-interface relationship 14 | 15 | | | module | network interface | host interface 16 | |---------------------|--------|-------------------------------------------------|---- 17 | | AC400 | 1 | 2 = ( 1 Tunable Laser + 1 Channel of DSP ) * 2 | 4 18 | | Cassini CFP2ACO PIU | 1 | 1 = CFP2ACO + DSP | 2 19 | | Cassini CFP2DCO PIU | 1 | 1 = CFP2DCO | 2 20 | -------------------------------------------------------------------------------- /inc/tai.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tai.h 3 | * @brief This module defines an entry point into Transponder Abstraction 4 | * Interface (TAI) 5 | * 6 | * @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc. 7 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 8 | * @copyright Copyright (c) 2017 Cumulus Networks, Inc. 9 | * All rights reserved. 10 | * 11 | * This source code is licensed under the BSD-style license found in the 12 | * LICENSE file in the root directory of this source tree. 13 | * 14 | * This source code includes software licensed by Microsoft under the 15 | * Apache License, Version 2.0 16 | * 17 | */ 18 | 19 | #if !defined (__TAI_H_) 20 | #define __TAI_H_ 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #include "taihostif.h" 27 | #include "taimodule.h" 28 | #include "tainetworkif.h" 29 | #include "taistatus.h" 30 | #include "taitypes.h" 31 | #include "taimeta.h" 32 | 33 | /** 34 | * @defgroup TAI TAI - Entry point specific API definitions. 35 | * 36 | * @{ 37 | */ 38 | 39 | /** 40 | * @brief Defined API sets have assigned IDs. 41 | * 42 | * If specific API method table changes in any way (method signature, number of 43 | * methods), a new ID needs to be created (e.g. HOSTIF2) and old API still may 44 | * need to be supported for compatibility with older adapter hosts. 45 | */ 46 | typedef enum _tai_api_t 47 | { 48 | TAI_API_UNSPECIFIED, /**< unspecified API */ 49 | TAI_API_MODULE, /**< #tai_module_api_t */ 50 | TAI_API_HOSTIF, /**< #tai_host_interface_api_t */ 51 | TAI_API_NETWORKIF, /**< #tai_network_interface_api_t */ 52 | TAI_API_META , /**< #tai_meta_api_t */ 53 | TAI_API_MAX /**< total number of APIs */ 54 | } tai_api_t; 55 | 56 | /** 57 | * @brief Defines the logging level. 58 | */ 59 | typedef enum _tai_log_level_t 60 | { 61 | TAI_LOG_LEVEL_DEBUG, /**< Debug logging level */ 62 | TAI_LOG_LEVEL_INFO, /**< Info logging level */ 63 | TAI_LOG_LEVEL_NOTICE, /**< Notice logging level */ 64 | TAI_LOG_LEVEL_WARN, /**< Warning logging level */ 65 | TAI_LOG_LEVEL_ERROR, /**< Error logging level */ 66 | TAI_LOG_LEVEL_CRITICAL, /**< Critical logging level */ 67 | TAI_LOG_LEVEL_MAX /**< Number of logging levels */ 68 | } tai_log_level_t; 69 | 70 | /** 71 | * @brief Log level function definition. 72 | * 73 | * User can specify his own function that will be called when message log level 74 | * will be greater or equal to #tai_log_level_t. 75 | * 76 | * @param[in] log_level Log level 77 | * @param[in] file Source file 78 | * @param[in] line Line number in file 79 | * @param[in] function Function name 80 | * @param[in] format Format of logging 81 | * @param[in] ... Variable parameters 82 | */ 83 | typedef void (*tai_log_fn)( 84 | _In_ tai_log_level_t log_level, 85 | _In_ const char *file, 86 | _In_ int line, 87 | _In_ const char *function, 88 | _In_ const char *format, 89 | _In_ ...); 90 | 91 | /** 92 | * @brief Module I/O handler 93 | */ 94 | typedef struct _tai_module_io_handler_t { 95 | void* context; 96 | int (*read)(void* context, uint32_t addr, uint32_t* value); 97 | int (*write)(void* context, uint32_t addr, uint32_t value); 98 | int (*close)(void* context); 99 | } tai_module_io_handler_t; 100 | 101 | /** 102 | * @brief The adapter calls this function, whose address is provided by the 103 | * adapter host, whenever there is a change in an optical module's 104 | * presence. This function will be called once for each module present 105 | * toward the end of the tai_api_initialze function, and then whenever 106 | * there is a change. The adapter host should be ready to accept calls to 107 | * this function at any time after invoking the tai_api_initialize 108 | * function. Because this function may be called in different contexts 109 | * (such as interrupt context or from a different thread/process) the 110 | * adapter host must not invoke other TAI interfaces directly from this 111 | * function. 112 | */ 113 | typedef void (*tai_module_presence_event_fn)( 114 | _In_ bool present, 115 | _In_ char * module_location); 116 | 117 | /** 118 | * @brief A callback to get module I/O handler 119 | */ 120 | typedef int (*tai_get_module_io_handler_fn)( 121 | _In_ const char * module_location, 122 | _Out_ tai_module_io_handler_t * handler); 123 | 124 | /** 125 | * @brief Method table that contains function pointers for services exposed by 126 | * the adapter host for the adapter. This is currently a single service: module 127 | * presence, which is called whenever a module is inserted or removed. 128 | */ 129 | typedef struct _tai_service_method_table_t 130 | { 131 | /** 132 | * @brief Notification of module insertion/removal 133 | * When NULL, TAI adapter won't do module detection. 134 | */ 135 | tai_module_presence_event_fn module_presence; 136 | 137 | /** 138 | * @brief get module I/O handler 139 | * When NULL, the default handler will be used 140 | */ 141 | tai_get_module_io_handler_fn get_module_io_handler; 142 | 143 | } tai_service_method_table_t; 144 | 145 | /** 146 | * @brief Adapter module initialization call 147 | * 148 | * This is NOT for SDK initialization. This function allows the adapter to 149 | * initialize any data/control structures that may be necessary during 150 | * subsequent TAI operations. 151 | * 152 | * @param[in] flags Reserved for future use, must be zero 153 | * @param[in] services Methods table with services provided by adapter host 154 | * 155 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 156 | */ 157 | tai_status_t tai_api_initialize( 158 | _In_ uint64_t flags, 159 | _In_ const tai_service_method_table_t *services); 160 | 161 | /** 162 | * @brief Retrieve a pointer to the C-style method table for desired TAI 163 | * functionality as specified by the given tai_api_id. 164 | * 165 | * @param[in] tai_api_id The API ID whose method table is being retrieved. 166 | * @param[out] api_method_table Caller allocated method table. The table must 167 | * remain valid until the tai_api_uninitialize() is called. 168 | * 169 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 170 | */ 171 | tai_status_t tai_api_query( 172 | _In_ tai_api_t tai_api_id, 173 | _Out_ void** api_method_table); 174 | 175 | /** 176 | * @brief Uninitialize adapter module. TAI functionalities, 177 | * retrieved via tai_api_query() cannot be used after this call. 178 | * 179 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 180 | */ 181 | tai_status_t tai_api_uninitialize(void); 182 | 183 | /** 184 | * @brief Set log level for TAI API module 185 | * 186 | * The default log level is #TAI_LOG_LEVEL_WARN. 187 | * 188 | * @param[in] tai_api_id The API ID whose logging level is being set 189 | * @param[in] log_level Log level 190 | * @param[in] log_fn Log callback (when null, the default log handler is used) 191 | * 192 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 193 | */ 194 | tai_status_t tai_log_set( 195 | _In_ tai_api_t tai_api_id, 196 | _In_ tai_log_level_t log_level, 197 | _In_ tai_log_fn); 198 | 199 | /** 200 | * @brief Query TAI object type. 201 | * 202 | * @param[in] tai_object_id Object id 203 | * 204 | * @return #TAI_OBJECT_TYPE_NULL when tai_object_id is not valid. 205 | * Otherwise, return a valid TAI object type TAI_OBJECT_TYPE_XXX. 206 | */ 207 | tai_object_type_t tai_object_type_query( 208 | _In_ tai_object_id_t tai_object_id); 209 | 210 | /** 211 | * @brief Query TAI module id. 212 | * 213 | * @param[in] tai_object_id Object id 214 | * 215 | * @return #TAI_NULL_OBJECT_ID when tai_object_id is not valid. 216 | * Otherwise, return a valid TAI_OBJECT_TYPE_MODULE object on which provided 217 | * object id belongs. If valid module id object is provided as input parameter 218 | * it should return itself. 219 | */ 220 | tai_object_id_t tai_module_id_query( 221 | _In_ tai_object_id_t tai_object_id); 222 | 223 | /** 224 | * @brief Generate dump file. The dump file may include TAI state information 225 | * and vendor SDK information. 226 | * 227 | * @param[in] dump_file_name Full path for dump file 228 | * 229 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 230 | */ 231 | tai_status_t tai_dbg_generate_dump( 232 | _In_ const char *dump_file_name); 233 | 234 | #ifdef __cplusplus 235 | } 236 | #endif 237 | 238 | /** 239 | * @} 240 | */ 241 | #endif /** __TAI_H_ */ 242 | -------------------------------------------------------------------------------- /inc/taihostif.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taihostif.h 3 | * @brief This module defines the host interface for the Transponder 4 | * Abstraction Interface (TAI) 5 | * 6 | * @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc. 7 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 8 | * @copyright Copyright (c) 2017 Cumulus Networks, Inc. 9 | * All rights reserved. 10 | * 11 | * This source code is licensed under the BSD-style license found in the 12 | * LICENSE file in the root directory of this source tree. 13 | * 14 | */ 15 | 16 | #if !defined (__TAIHOSTIF_H_) 17 | #define __TAIHOSTIF_H_ 18 | 19 | #include 20 | 21 | /** 22 | * @defgroup TAIHOSTIF TAI - Host Interface specific API definitions 23 | * 24 | * @{ 25 | */ 26 | 27 | /** @brief A bitmap of lane faults */ 28 | typedef enum _tai_host_interface_lane_fault_t 29 | { 30 | TAI_HOST_INTERFACE_LANE_FAULT_LOSS_OF_LOCK, 31 | TAI_HOST_INTERFACE_LANE_FAULT_TX_FIFO_ERR 32 | } tai_host_interface_lane_fault_t; 33 | 34 | /** @brief The transmit alignment status */ 35 | typedef enum _tai_host_interface_tx_align_status_t 36 | { 37 | TAI_HOST_INTERFACE_TX_ALIGN_STATUS_CDR_LOCK_FAULT, 38 | TAI_HOST_INTERFACE_TX_ALIGN_STATUS_LOSS, 39 | TAI_HOST_INTERFACE_TX_ALIGN_STATUS_OUT, 40 | TAI_HOST_INTERFACE_TX_ALIGN_STATUS_DESKEW_LOCK 41 | } tai_host_interface_tx_align_status_t; 42 | 43 | /** @brief The host interface signal rate */ 44 | typedef enum _tai_host_interface_signal_rate_t 45 | { 46 | TAI_HOST_INTERFACE_SIGNAL_RATE_UNKNOWN, 47 | TAI_HOST_INTERFACE_SIGNAL_RATE_100_GBE, 48 | TAI_HOST_INTERFACE_SIGNAL_RATE_200_GBE, 49 | TAI_HOST_INTERFACE_SIGNAL_RATE_400_GBE, 50 | TAI_HOST_INTERFACE_SIGNAL_RATE_OTU4, 51 | TAI_HOST_INTERFACE_SIGNAL_RATE_MAX 52 | } tai_host_interface_signal_rate_t; 53 | 54 | /** @brief The host interface FEC type */ 55 | typedef enum _tai_host_interface_fec_type_t 56 | { 57 | TAI_HOST_INTERFACE_FEC_TYPE_NONE, /**< No FEC */ 58 | TAI_HOST_INTERFACE_FEC_TYPE_RS, /**< RS-FEC */ 59 | TAI_HOST_INTERFACE_FEC_TYPE_FC, /**< FC-FEC */ 60 | } tai_host_interface_fec_type_t; 61 | 62 | /** @brief The loopback types */ 63 | typedef enum _tai_host_interface_loopback_type_t 64 | { 65 | TAI_HOST_INTERFACE_LOOPBACK_TYPE_NONE, 66 | TAI_HOST_INTERFACE_LOOPBACK_TYPE_SHALLOW, 67 | TAI_HOST_INTERFACE_LOOPBACK_TYPE_DEEP, 68 | TAI_HOST_INTERFACE_LOOPBACK_TYPE_MAX 69 | } tai_host_interface_loopback_type_t; 70 | 71 | /** @brief The PCS alarm */ 72 | typedef enum _tai_host_interface_pcs_alarm_t 73 | { 74 | TAI_HOST_INTERFACE_PCS_ALARM_LOSS_OF_SIGNAL, 75 | TAI_HOST_INTERFACE_PCS_ALARM_LOSS_OF_FRAME, 76 | TAI_HOST_INTERFACE_PCS_ALARM_ILLEGAL_ALIGNMENT_MARKER, 77 | TAI_HOST_INTERFACE_PCS_ALARM_REMOTE_FAULT, 78 | TAI_HOST_INTERFACE_PCS_ALARM_LOCAL_FAULT, 79 | TAI_HOST_INTERFACE_PCS_ALARM_HI_BER, 80 | TAI_HOST_INTERFACE_PCS_ALARM_BIP_ERROR, 81 | TAI_HOST_INTERFACE_PCS_ALARM_DESKEW_ERROR, 82 | } tai_host_interface_pcs_alarm_t; 83 | 84 | /** 85 | * @brief Host interface Attribute Ids 86 | */ 87 | typedef enum _tai_host_interface_attr_t 88 | { 89 | /** 90 | * @brief Start of attributes 91 | */ 92 | TAI_HOST_INTERFACE_ATTR_START, 93 | 94 | /** 95 | * @brief The location of the host interface 96 | * 97 | * Used (and required) in the tai_create_host_interface_fn call. This allows 98 | * the adapter to uniquely identify the host interface on a module. 99 | * 100 | * @type #tai_uint32_t 101 | * @flags MANDATORY_ON_CREATE | CREATE_ONLY 102 | */ 103 | TAI_HOST_INTERFACE_ATTR_INDEX = TAI_HOST_INTERFACE_ATTR_START, 104 | 105 | /** 106 | * @brief Host lane fault status 107 | * 108 | * A list of lane fault status 109 | * 110 | * @type #tai_attr_value_list_t #tai_s32_list_t #tai_host_interface_lane_fault_t 111 | * @flags READ_ONLY 112 | */ 113 | TAI_HOST_INTERFACE_ATTR_LANE_FAULT, 114 | 115 | /** 116 | * @brief TX Alignment Status 117 | * 118 | * @type #tai_s32_list_t #tai_host_interface_tx_align_status_t 119 | * @flags READ_ONLY 120 | */ 121 | TAI_HOST_INTERFACE_ATTR_TX_ALIGN_STATUS, 122 | 123 | /** 124 | * @brief signal rate 125 | * 126 | * @type #tai_host_interface_signal_rate_t 127 | * @flags CREATE_AND_SET 128 | * @default vendor-specific 129 | */ 130 | TAI_HOST_INTERFACE_ATTR_SIGNAL_RATE, 131 | 132 | /** 133 | * @brief FEC type 134 | * 135 | * @type #tai_host_interface_fec_type_t 136 | * @flags CREATE_AND_SET 137 | * @default TAI_HOST_INTERFACE_FEC_TYPE_NONE 138 | */ 139 | TAI_HOST_INTERFACE_ATTR_FEC_TYPE, 140 | 141 | /** 142 | * @brief Loopback type 143 | * 144 | * @type #tai_host_interface_loopback_type_t 145 | * @flags CREATE_AND_SET 146 | * @default TAI_HOST_INTERFACE_LOOPBACK_TYPE_NONE 147 | */ 148 | TAI_HOST_INTERFACE_ATTR_LOOPBACK_TYPE, 149 | 150 | /** 151 | * @type #tai_uint32_t 152 | * @flags READ_ONLY | CLEARABLE 153 | */ 154 | TAI_HOST_INTERFACE_ATTR_ETHERNET_IN_OCTETS, 155 | 156 | /** 157 | * @type #tai_uint32_t 158 | * @flags READ_ONLY | CLEARABLE 159 | */ 160 | TAI_HOST_INTERFACE_ATTR_ETHERNET_IN_PACKETS, 161 | 162 | /** 163 | * @type #tai_uint32_t 164 | * @flags READ_ONLY | CLEARABLE 165 | */ 166 | TAI_HOST_INTERFACE_ATTR_ETHERNET_IN_FCS_ERRORS, 167 | 168 | /** 169 | * @type #tai_uint32_t 170 | * @flags READ_ONLY | CLEARABLE 171 | */ 172 | TAI_HOST_INTERFACE_ATTR_ETHERNET_IN_MAC_ERRORS, 173 | 174 | /** 175 | * @type #tai_uint32_t 176 | * @flags READ_ONLY | CLEARABLE 177 | */ 178 | TAI_HOST_INTERFACE_ATTR_ETHERNET_OUT_OCTETS, 179 | 180 | /** 181 | * @type #tai_uint32_t 182 | * @flags READ_ONLY | CLEARABLE 183 | */ 184 | TAI_HOST_INTERFACE_ATTR_ETHERNET_OUT_PACKETS, 185 | 186 | /** 187 | * @type #tai_uint32_t 188 | * @flags READ_ONLY | CLEARABLE 189 | */ 190 | TAI_HOST_INTERFACE_ATTR_ETHERNET_OUT_FCS_ERRORS, 191 | 192 | /** 193 | * @type #tai_uint32_t 194 | * @flags READ_ONLY | CLEARABLE 195 | */ 196 | TAI_HOST_INTERFACE_ATTR_ETHERNET_OUT_MAC_ERRORS, 197 | 198 | /** 199 | * @brief TX Ethernet PCS Alarm 200 | * 201 | * @type #tai_s32_list_t #tai_host_interface_pcs_alarm_t 202 | * @flags READ_ONLY 203 | */ 204 | TAI_HOST_INTERFACE_ATTR_TX_PCS_ALARM, 205 | 206 | /** 207 | * @brief RX Ethernet PCS Alarm 208 | * 209 | * @type #tai_s32_list_t #tai_host_interface_pcs_alarm_t 210 | * @flags READ_ONLY 211 | */ 212 | TAI_HOST_INTERFACE_ATTR_RX_PCS_ALARM, 213 | 214 | /** 215 | * @brief Host interface generic notification 216 | * 217 | * @type #tai_notification_handler_t 218 | * @flags CREATE_AND_SET 219 | * @default NULL 220 | */ 221 | TAI_HOST_INTERFACE_ATTR_NOTIFY, 222 | 223 | /** 224 | * @brief End of attributes 225 | */ 226 | TAI_HOST_INTERFACE_ATTR_END, 227 | 228 | /** Custom range base value */ 229 | TAI_HOST_INTERFACE_ATTR_CUSTOM_RANGE_START = 0x10000000, 230 | 231 | /** Custom range for the AC400 adapter */ 232 | TAI_HOST_INTERFACE_ATTR_CUSTOM_AC400_START = TAI_HOST_INTERFACE_ATTR_CUSTOM_RANGE_START, 233 | TAI_HOST_INTERFACE_ATTR_CUSTOM_AC400_END = TAI_HOST_INTERFACE_ATTR_CUSTOM_AC400_START + 0xFFFF, 234 | 235 | /** Custom range for the NLD0670APB/TRB100 adapter */ 236 | TAI_HOST_INTERFACE_ATTR_CUSTOM_NLD0670_TRB100_START, 237 | TAI_HOST_INTERFACE_ATTR_CUSTOM_NLD0670_TRB100_END = TAI_HOST_INTERFACE_ATTR_CUSTOM_NLD0670_TRB100_START + 0xFFFF, 238 | 239 | /** Custom range for TAI mux */ 240 | TAI_HOST_INTERFACE_ATTR_CUSTOM_MUX_START, 241 | TAI_HOST_INTERFACE_ATTR_CUSTOM_MUX_END = TAI_HOST_INTERFACE_ATTR_CUSTOM_MUX_START + 0xFFFF, 242 | 243 | /** End of custom range base */ 244 | TAI_HOST_INTERFACE_ATTR_CUSTOM_RANGE_END 245 | 246 | } tai_host_interface_attr_t; 247 | 248 | /** 249 | * @brief Create host interface 250 | * 251 | * @param[out] host_interface_id Host interface id 252 | * @param[in] module_id Module ID containing the host interface 253 | * @param[in] attr_count Number of attributes 254 | * @param[in] attr_list Array of attributes 255 | * 256 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 257 | */ 258 | typedef tai_status_t (*tai_create_host_interface_fn)( 259 | _Out_ tai_object_id_t *host_interface_id, 260 | _In_ tai_object_id_t module_id, 261 | _In_ uint32_t attr_count, 262 | _In_ const tai_attribute_t *attr_list); 263 | 264 | /** 265 | * @brief Remove host interface 266 | * 267 | * @param[in] host_interface_id Host interface id 268 | * 269 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 270 | */ 271 | typedef tai_status_t (*tai_remove_host_interface_fn)( 272 | _In_ tai_object_id_t host_interface_id); 273 | 274 | /** 275 | * @brief Set host interface attribute value. 276 | * 277 | * @param[in] host_interface_id Host interface id 278 | * @param[in] attr Attribute 279 | * 280 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 281 | */ 282 | typedef tai_status_t (*tai_set_host_interface_attribute_fn)( 283 | _In_ tai_object_id_t host_interface_id, 284 | _In_ const tai_attribute_t *attr); 285 | 286 | /** 287 | * @brief Set multiple host interface attribute values 288 | * 289 | * @param[in] host_interface_id Host interface id 290 | * @param[in] attr_count Number of attributes 291 | * @param[in] attr_list Array of attributes 292 | * 293 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 294 | */ 295 | typedef tai_status_t (*tai_set_host_interface_attributes_fn)( 296 | _In_ tai_object_id_t host_interface_id, 297 | _In_ uint32_t attr_count, 298 | _In_ const tai_attribute_t *attr_list); 299 | 300 | /** 301 | * @brief Get host interface attribute 302 | * 303 | * @param[in] host_interface_id Host interface id 304 | * @param[inout] attr Attribute 305 | * 306 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 307 | */ 308 | typedef tai_status_t (*tai_get_host_interface_attribute_fn)( 309 | _In_ tai_object_id_t host_interface_id, 310 | _Inout_ tai_attribute_t *attr); 311 | 312 | /** 313 | * @brief Get multiple host interface attribute values 314 | * 315 | * @param[in] host_interface_id Host interface id 316 | * @param[in] attr_count Number of attributes 317 | * @param[inout] attr_list Array of attributes 318 | * 319 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 320 | */ 321 | typedef tai_status_t (*tai_get_host_interface_attributes_fn)( 322 | _In_ tai_object_id_t host_interface_id, 323 | _In_ uint32_t attr_count, 324 | _Inout_ tai_attribute_t *attr_list); 325 | 326 | /** 327 | * @brief Clear host interface attribute 328 | * 329 | * @param[in] host_interface_id Host interface id 330 | * @param[in] attr_id Attribute 331 | * 332 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 333 | */ 334 | typedef tai_status_t (*tai_clear_host_interface_attribute_fn)( 335 | _In_ tai_object_id_t host_interface_id, 336 | _In_ tai_attr_id_t attr_id); 337 | 338 | /** 339 | * @brief Clear multiple host interface attribute values 340 | * 341 | * @param[in] host_interface_id Host interface id 342 | * @param[in] attr_id_count Number of attribute ids 343 | * @param[in] attr_id_list Array of attribute ids 344 | * 345 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 346 | */ 347 | typedef tai_status_t (*tai_clear_host_interface_attributes_fn)( 348 | _In_ tai_object_id_t host_interface_id, 349 | _In_ uint32_t attr_id_count, 350 | _In_ tai_attr_id_t *attr_id); 351 | 352 | /** 353 | * @brief Get host interface capability 354 | * 355 | * @param[in] host_interface_id Host interface id 356 | * @param[inout] attr Attribute capability 357 | * 358 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 359 | */ 360 | typedef tai_status_t (*tai_get_host_interface_capability_fn)( 361 | _In_ tai_object_id_t host_interface_id, 362 | _Inout_ tai_attribute_capability_t *cap); 363 | 364 | /** 365 | * @brief Get multiple host interface capabilities 366 | * 367 | * @param[in] host_interface_id Host Interface id 368 | * @param[in] count Number of capabilities 369 | * @param[inout] list Attribute capabilities 370 | * 371 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 372 | */ 373 | typedef tai_status_t (*tai_get_host_interface_capabilities_fn)( 374 | _In_ tai_object_id_t host_interface_id, 375 | _In_ uint32_t count, 376 | _Inout_ tai_attribute_capability_t *list); 377 | 378 | /** 379 | * @brief Host interface methods table retrieved with tai_api_query() 380 | */ 381 | typedef struct _tai_host_interface_api_t 382 | { 383 | tai_create_host_interface_fn create_host_interface; 384 | tai_remove_host_interface_fn remove_host_interface; 385 | tai_set_host_interface_attribute_fn set_host_interface_attribute; 386 | tai_set_host_interface_attributes_fn set_host_interface_attributes; 387 | tai_get_host_interface_attribute_fn get_host_interface_attribute; 388 | tai_get_host_interface_attributes_fn get_host_interface_attributes; 389 | tai_clear_host_interface_attribute_fn clear_host_interface_attribute; 390 | tai_clear_host_interface_attributes_fn clear_host_interface_attributes; 391 | tai_get_host_interface_capability_fn get_host_interface_capability; 392 | tai_get_host_interface_capabilities_fn get_host_interface_capabilities; 393 | 394 | } tai_host_interface_api_t; 395 | 396 | /** 397 | * @} 398 | */ 399 | #endif /** __TAIHOSTIF_H_ */ 400 | -------------------------------------------------------------------------------- /inc/taimeta.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taimeta.h 3 | * @brief This module defines the meta interface for the Transponder 4 | * Abstraction Interface (TAI) 5 | * 6 | * @copyright Copyright (c) 2021 Nippon Telegraph and Telephone Corporation 7 | * All rights reserved. 8 | * 9 | * This source code is licensed under the BSD-style license found in the 10 | * LICENSE file in the root directory of this source tree. 11 | * 12 | */ 13 | 14 | #if !defined (__TAIMETA_H_) 15 | #define __TAIMETA_H_ 16 | 17 | #include 18 | #include 19 | 20 | /** 21 | * @defgroup TAIMETA TAI - Meta specific API definitions 22 | * 23 | * @{ 24 | */ 25 | 26 | /** 27 | * @brief List metadata of the given oid object 28 | * 29 | * Passing TAI_NULL_OBJECT_ID to oid and TAI_OBJECT_TYPE_NULL to object_type 30 | * returns all metadata which this TAI library has. 31 | * 32 | * @param[in] key Metadata key 33 | * @param[out] count Number of metadata 34 | * @param[out] list Array of metadata 35 | * 36 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 37 | */ 38 | typedef tai_status_t (*tai_meta_list_metadata_fn)( 39 | _In_ const tai_metadata_key_t *const key, 40 | _Out_ uint32_t *count, 41 | _Out_ const tai_attr_metadata_t * const **list); 42 | 43 | /** 44 | * @brief Get attribute metadata of the given oid object 45 | * 46 | * @param[in] key Metadata key 47 | * @param[in] attr_id Attribute Id 48 | * 49 | * @return Pointer to attribute metadata or NULL in case of failure 50 | */ 51 | typedef const tai_attr_metadata_t* (*tai_meta_get_attr_metadata_fn)( 52 | _In_ const tai_metadata_key_t *const key, 53 | _In_ tai_attr_id_t attr_id); 54 | 55 | /** 56 | * @brief Get object info of the given oid object 57 | * 58 | * @param[in] key Metadata key 59 | * 60 | * @return Pointer to object metadata or NULL in case of failure 61 | */ 62 | typedef const tai_object_type_info_t* (*tai_meta_get_object_info_fn)( 63 | _In_ const tai_metadata_key_t *const key); 64 | 65 | /** 66 | * @brief Meta methods table retrieved with tai_api_query() 67 | */ 68 | typedef struct _tai_meta_api_t 69 | { 70 | tai_meta_list_metadata_fn list_metadata; 71 | tai_meta_get_attr_metadata_fn get_attr_metadata; 72 | tai_meta_get_object_info_fn get_object_info; 73 | } tai_meta_api_t; 74 | 75 | /** 76 | * @} 77 | */ 78 | 79 | 80 | #endif /** __TAIMETA_H_ */ 81 | -------------------------------------------------------------------------------- /inc/taimodule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taimodule.h 3 | * @brief This module defines the TAI Module interface 4 | * @details A "module" in this context refers to an optical module. The 5 | * #tai_create_module_fn causes a new module to be allocated and 6 | * initialized, including the SDK which controls that module. 7 | * 8 | * @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc. 9 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 10 | * @copyright Copyright (c) 2017 Cumulus Networks, Inc. 11 | * All rights reserved. 12 | * 13 | * This source code is licensed under the BSD-style license found in the 14 | * LICENSE file in the root directory of this source tree. 15 | * 16 | */ 17 | 18 | #if !defined (__TAIMODULE_H_) 19 | #define __TAIMODULE_H_ 20 | 21 | #include 22 | 23 | /** 24 | * @defgroup TAIMODULE TAI - Module specific API definitions 25 | * 26 | * @{ 27 | */ 28 | 29 | /** 30 | * @brief Maximum Number of Modules 31 | */ 32 | #define TAI_MAX_MODULES 32 33 | 34 | /** 35 | * @brief Maximum Hardware ID Length 36 | */ 37 | #define TAI_MAX_HARDWARE_ID_LEN 255 38 | 39 | /** 40 | * @brief Maximum Firmware Path Name Length 41 | */ 42 | #define TAI_MAX_FIRMWARE_PATH_NAME_LEN PATH_MAX 43 | 44 | /** 45 | * @brief Operational states of the module 46 | */ 47 | typedef enum _tai_module_oper_status_t 48 | { 49 | TAI_MODULE_OPER_STATUS_UNKNOWN, /**< Unknown */ 50 | TAI_MODULE_OPER_STATUS_INITIALIZE, /**< Initialize */ 51 | TAI_MODULE_OPER_STATUS_READY, /**< Ready */ 52 | TAI_MODULE_OPER_STATUS_MAX, /**< Number of states */ 53 | } tai_module_oper_status_t; 54 | 55 | /** 56 | * @brief Admin states of the module 57 | */ 58 | typedef enum _tai_module_admin_status_t 59 | { 60 | TAI_MODULE_ADMIN_STATUS_UNKNOWN, /**< Unknown */ 61 | TAI_MODULE_ADMIN_STATUS_DOWN, /**< Down */ 62 | TAI_MODULE_ADMIN_STATUS_UP, /**< Up */ 63 | TAI_MODULE_ADMIN_STATUS_MAX, /**< Number of states */ 64 | } tai_module_admin_status_t; 65 | 66 | /** 67 | * @brief Module shutdown request callback. 68 | * 69 | * Adapter DLL may request a shutdown due to an unrecoverable failure 70 | * or a maintenance operation 71 | * 72 | * @param[in] module_id Module Id 73 | */ 74 | typedef void (*tai_module_shutdown_request_notification_fn)( 75 | _In_ tai_object_id_t module_id); 76 | 77 | /** 78 | * @brief Module operational state change notification 79 | * 80 | * @param[in] module_id Module Id 81 | * @param[in] module_oper_status New module operational state 82 | */ 83 | typedef void (*tai_module_state_change_notification_fn)( 84 | _In_ tai_object_id_t module_id, 85 | _In_ tai_module_oper_status_t module_oper_status); 86 | 87 | /** 88 | * @brief Attribute Id in tai_set_module_attribute() and 89 | * tai_get_module_attribute() calls. 90 | */ 91 | typedef enum _tai_module_attr_t 92 | { 93 | /** 94 | * @brief Start of attributes 95 | */ 96 | TAI_MODULE_ATTR_START, 97 | 98 | /** 99 | * @brief The location of the module 100 | * 101 | * Used (and required) in the tai_create_module_fn call. This allows the 102 | * adapter to uniquely identify the module. This could be a PCI address, 103 | * slot identifier, or other value that allows the adapter to determine 104 | * which optical module is being initialized. 105 | * 106 | * @type #tai_char_list_t 107 | * @flags MANDATORY_ON_CREATE | CREATE_ONLY 108 | */ 109 | TAI_MODULE_ATTR_LOCATION = TAI_MODULE_ATTR_START, 110 | 111 | /** 112 | * @brief The module vendor's name 113 | * 114 | * If the module is composed of several components, this attribute 115 | * contains the vendor name of all components with '/' used as 116 | * the delimiter 117 | * 118 | * @type #tai_char_list_t 119 | * @flags READ_ONLY 120 | */ 121 | TAI_MODULE_ATTR_VENDOR_NAME, 122 | 123 | /** 124 | * @brief The module vendor's part number 125 | * 126 | * If the module is composed of several components, this attribute 127 | * contains the part number of all components with '/' used as 128 | * the delimiter 129 | * 130 | * @type #tai_char_list_t 131 | * @flags READ_ONLY 132 | */ 133 | TAI_MODULE_ATTR_VENDOR_PART_NUMBER, 134 | 135 | /** 136 | * @brief The module vendor's serial number 137 | * 138 | * If there are several serial number exists inside the module, '/' is 139 | * used as the delimiter 140 | * 141 | * @type #tai_char_list_t 142 | * @flags READ_ONLY 143 | */ 144 | TAI_MODULE_ATTR_VENDOR_SERIAL_NUMBER, 145 | 146 | /** 147 | * @brief The module firmware version 148 | * 149 | * If there are several firmware exists inside the module, '/' is used 150 | * as the delimiter 151 | * 152 | * @type #tai_char_list_t 153 | * @flags READ_ONLY 154 | */ 155 | TAI_MODULE_ATTR_FIRMWARE_VERSION, 156 | 157 | /** 158 | * @brief The operational state of the module 159 | * 160 | * @type #tai_module_oper_status_t 161 | * @flags READ_ONLY 162 | */ 163 | TAI_MODULE_ATTR_OPER_STATUS, 164 | 165 | /** 166 | * @brief The internal temperature of the module 167 | * 168 | * @type #tai_float_t 169 | * @flags READ_ONLY 170 | */ 171 | TAI_MODULE_ATTR_TEMP, 172 | 173 | /** 174 | * @brief The power supply voltage 175 | * 176 | * @type #tai_float_t 177 | * @flags READ_ONLY 178 | */ 179 | TAI_MODULE_ATTR_POWER, 180 | 181 | /** 182 | * @brief The number of host interfaces on the module 183 | * 184 | * @type #tai_uint32_t 185 | * @flags READ_ONLY 186 | */ 187 | TAI_MODULE_ATTR_NUM_HOST_INTERFACES, 188 | 189 | /** 190 | * @brief The number of network interfaces on the module 191 | * 192 | * @type #tai_uint32_t 193 | * @flags READ_ONLY 194 | */ 195 | TAI_MODULE_ATTR_NUM_NETWORK_INTERFACES, 196 | 197 | /** 198 | * @brief The admin state of the module 199 | * 200 | * @type #tai_module_admin_status_t 201 | * @flags CREATE_AND_SET 202 | * @default TAI_MODULE_ADMIN_STATUS_UP 203 | */ 204 | TAI_MODULE_ATTR_ADMIN_STATUS, 205 | 206 | /** 207 | * @brief Tributary mapping of netif and hostif 208 | * 209 | * The key is netif oid and the value is a list of hostif oids 210 | * corresponds to the netif. This attribute can be changed automatically 211 | * by setting some netif attributes (e.g TAI_NETWORK_INTERFACE_ATTR_MODULATION_FORMAT ) 212 | * 213 | * @type #tai_object_map_list_t 214 | * @flags CREATE_AND_SET 215 | * @defaults empty-list 216 | */ 217 | TAI_MODULE_ATTR_TRIBUTARY_MAPPING, 218 | 219 | /** 220 | * @brief Module shutdown request callback. 221 | * 222 | * @type tai_pointer_t tai_module_shutdown_request_notification_fn 223 | * @flags CREATE_AND_SET 224 | * @default NULL 225 | */ 226 | TAI_MODULE_ATTR_MODULE_SHUTDOWN_REQUEST_NOTIFY, 227 | 228 | /** 229 | * @brief Module operational state change notification 230 | * 231 | * @type tai_pointer_t tai_module_state_change_notification_fn 232 | * @flags CREATE_AND_SET 233 | * @default NULL 234 | */ 235 | TAI_MODULE_ATTR_MODULE_STATE_CHANGE_NOTIFY, 236 | 237 | /** 238 | * @brief Module generic notification 239 | * 240 | * @type #tai_notification_handler_t 241 | * @flags CREATE_AND_SET 242 | * @default NULL 243 | */ 244 | TAI_MODULE_ATTR_NOTIFY, 245 | 246 | /** 247 | * @brief End of attributes 248 | */ 249 | TAI_MODULE_ATTR_END, 250 | 251 | /** Custom range base value */ 252 | TAI_MODULE_ATTR_CUSTOM_RANGE_START = 0x10000000, 253 | 254 | /** Custom range for the AC400 adapter */ 255 | TAI_MODULE_ATTR_CUSTOM_AC400_START = TAI_MODULE_ATTR_CUSTOM_RANGE_START, 256 | TAI_MODULE_ATTR_CUSTOM_AC400_END = TAI_MODULE_ATTR_CUSTOM_AC400_START + 0xFFFF, 257 | 258 | /** Custom range for the NLD0670APB/TRB100 adapter */ 259 | TAI_MODULE_ATTR_CUSTOM_NLD0670_TRB100_START, 260 | TAI_MODULE_ATTR_CUSTOM_NLD0670_TRB100_END = TAI_MODULE_ATTR_CUSTOM_NLD0670_TRB100_START + 0xFFFF, 261 | 262 | /** Custom range for TAI mux */ 263 | TAI_MODULE_ATTR_CUSTOM_MUX_START, 264 | TAI_MODULE_ATTR_CUSTOM_MUX_END = TAI_MODULE_ATTR_CUSTOM_MUX_START + 0xFFFF, 265 | 266 | /** End of custom range base */ 267 | TAI_MODULE_ATTR_CUSTOM_RANGE_END 268 | 269 | } tai_module_attr_t; 270 | 271 | /** 272 | * @brief Create module 273 | * 274 | * SDK initialization/connect to SDK. After the call the capability attributes 275 | * should be ready for retrieval via tai_get_module_attribute(). Returned Module 276 | * Object id should be used in subsequent TAI function calls in order to 277 | * identify the module. 278 | * 279 | * @param[out] module_id The Module Object ID 280 | * @param[in] attr_count Number of attributes 281 | * @param[in] attr_list Array of attributes to set during initialization 282 | * 283 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 284 | */ 285 | typedef tai_status_t (*tai_create_module_fn)( 286 | _Out_ tai_object_id_t *module_id, 287 | _In_ uint32_t attr_count, 288 | _In_ const tai_attribute_t *attr_list); 289 | 290 | /** 291 | * @brief Remove/disconnect Module 292 | * 293 | * Release all resources associated with a currently created module 294 | * 295 | * @param[in] module_id The Module id 296 | * 297 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 298 | */ 299 | typedef tai_status_t (*tai_remove_module_fn)( 300 | _In_ tai_object_id_t module_id); 301 | 302 | /** 303 | * @brief Set module attribute value 304 | * 305 | * @param[in] module_id Module id 306 | * @param[in] attr Module attribute 307 | * 308 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 309 | */ 310 | typedef tai_status_t (*tai_set_module_attribute_fn)( 311 | _In_ tai_object_id_t module_id, 312 | _In_ const tai_attribute_t *attr); 313 | 314 | /** 315 | * @brief Set multiple module attribute values 316 | * 317 | * @param[in] module_id Module id 318 | * @param[in] attr_count Number of attributes 319 | * @param[in] attr_list Array of module attributes 320 | * 321 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 322 | */ 323 | typedef tai_status_t (*tai_set_module_attributes_fn)( 324 | _In_ tai_object_id_t module_id, 325 | _In_ uint32_t attr_count, 326 | _In_ const tai_attribute_t *attr_list); 327 | 328 | /** 329 | * @brief Get module attribute value 330 | * 331 | * @param[in] module_id Module id 332 | * @param[inout] attr Module attribute 333 | * 334 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 335 | */ 336 | typedef tai_status_t (*tai_get_module_attribute_fn)( 337 | _In_ tai_object_id_t module_id, 338 | _Inout_ tai_attribute_t *attr); 339 | 340 | /** 341 | * @brief Get multiple module attribute values 342 | * 343 | * @param[in] module_id Module id 344 | * @param[in] attr_count Number of attributes 345 | * @param[inout] attr_list Array of module attributes 346 | * 347 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 348 | */ 349 | typedef tai_status_t (*tai_get_module_attributes_fn)( 350 | _In_ tai_object_id_t module_id, 351 | _In_ uint32_t attr_count, 352 | _Inout_ tai_attribute_t *attr_list); 353 | 354 | /** 355 | * @brief Get module capability 356 | * 357 | * @param[in] module_id Module id 358 | * @param[inout] cap Attribute capability 359 | * 360 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 361 | */ 362 | typedef tai_status_t (*tai_get_module_capability_fn)( 363 | _In_ tai_object_id_t module_id, 364 | _Inout_ tai_attribute_capability_t *cap); 365 | 366 | /** 367 | * @brief Get multiple module capabilities 368 | * 369 | * @param[in] module_id Module id 370 | * @param[in] count Number of capabilities 371 | * @param[inout] list Attribute capabilities 372 | * 373 | * @return #TAI_STATUS_SUCCESS on success, failure status code on error 374 | */ 375 | typedef tai_status_t (*tai_get_module_capabilities_fn)( 376 | _In_ tai_object_id_t module_id, 377 | _In_ uint32_t count, 378 | _Inout_ tai_attribute_capability_t *list); 379 | 380 | /** 381 | * @brief Module method table retrieved with tai_api_query() 382 | */ 383 | typedef struct _tai_module_api_t 384 | { 385 | tai_create_module_fn create_module; 386 | tai_remove_module_fn remove_module; 387 | tai_set_module_attribute_fn set_module_attribute; 388 | tai_set_module_attributes_fn set_module_attributes; 389 | tai_get_module_attribute_fn get_module_attribute; 390 | tai_get_module_attributes_fn get_module_attributes; 391 | tai_get_module_capability_fn get_module_capability; 392 | tai_get_module_capabilities_fn get_module_capabilities; 393 | 394 | } tai_module_api_t; 395 | 396 | /** 397 | * @} 398 | */ 399 | #endif /** __TAIMODULE_H_ */ 400 | -------------------------------------------------------------------------------- /inc/taistatus.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taistatus.h 3 | * @brief This module defines TAI Status codes 4 | * Interface (TAI) 5 | * 6 | * @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc. 7 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 8 | * @copyright Copyright (c) 2017 Cumulus Networks, Inc. 9 | * All rights reserved. 10 | * 11 | * This source code is licensed under the BSD-style license found in the 12 | * LICENSE file in the root directory of this source tree. 13 | * 14 | * This source code includes software licensed by Microsoft under the 15 | * Apache License, Version 2.0 16 | * 17 | */ 18 | 19 | #if !defined (__TAISTATUS_H_) 20 | #define __TAISTATUS_H_ 21 | 22 | /** 23 | * @defgroup TAISTATUS TAI - Status codes definitions 24 | * 25 | * @{ 26 | */ 27 | 28 | #ifdef _WIN32 29 | 30 | #define TAI_STATUS_CODE(_S_) ((tai_status_t)(_S_)) 31 | 32 | #else 33 | 34 | /** 35 | * @brief Any mapping schema from _S_ to error codes convenient on *nix can be used. 36 | */ 37 | #define TAI_STATUS_CODE(_S_) (-(_S_)) 38 | 39 | #endif 40 | 41 | /** 42 | * @brief Status success 43 | */ 44 | #define TAI_STATUS_SUCCESS 0x00000000L 45 | 46 | /** 47 | * @brief General failure 48 | */ 49 | #define TAI_STATUS_FAILURE TAI_STATUS_CODE(0x00000001L) 50 | 51 | /** 52 | * @brief The request is not supported 53 | */ 54 | #define TAI_STATUS_NOT_SUPPORTED TAI_STATUS_CODE(0x00000002L) 55 | 56 | /** 57 | * @brief Not enough memory to complete the operation 58 | */ 59 | #define TAI_STATUS_NO_MEMORY TAI_STATUS_CODE(0x00000003L) 60 | 61 | /** 62 | * @brief Insufficient system resources exist to complete the operation 63 | */ 64 | #define TAI_STATUS_INSUFFICIENT_RESOURCES TAI_STATUS_CODE(0x00000004L) 65 | 66 | /** 67 | * @brief An invalid parameter was passed to a function 68 | */ 69 | #define TAI_STATUS_INVALID_PARAMETER TAI_STATUS_CODE(0x00000005L) 70 | 71 | /** 72 | * @brief An item already exists. For example, create a route which already 73 | * exists. 74 | */ 75 | #define TAI_STATUS_ITEM_ALREADY_EXISTS TAI_STATUS_CODE(0x00000006L) 76 | 77 | /** 78 | * @brief An item was not found. For example, remove a route which does not 79 | * exist. 80 | */ 81 | #define TAI_STATUS_ITEM_NOT_FOUND TAI_STATUS_CODE(0x00000007L) 82 | 83 | /** 84 | * @brief The data was too large to fit into the specified buffer. 85 | */ 86 | #define TAI_STATUS_BUFFER_OVERFLOW TAI_STATUS_CODE(0x00000008L) 87 | 88 | /** 89 | * @brief Invalid port number 90 | */ 91 | #define TAI_STATUS_INVALID_PORT_NUMBER TAI_STATUS_CODE(0x00000009L) 92 | 93 | /** 94 | * @brief Invalid port member 95 | */ 96 | #define TAI_STATUS_INVALID_PORT_MEMBER TAI_STATUS_CODE(0x0000000AL) 97 | 98 | /** 99 | * @brief Object is uninitialized 100 | */ 101 | #define TAI_STATUS_UNINITIALIZED TAI_STATUS_CODE(0x0000000CL) 102 | 103 | /** 104 | * @brief Table is full 105 | */ 106 | #define TAI_STATUS_TABLE_FULL TAI_STATUS_CODE(0x0000000DL) 107 | 108 | /** 109 | * @brief Mandatory attribute is missing 110 | */ 111 | #define TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING TAI_STATUS_CODE(0x0000000EL) 112 | 113 | /** 114 | * @brief Function is not implemented 115 | */ 116 | #define TAI_STATUS_NOT_IMPLEMENTED TAI_STATUS_CODE(0x0000000FL) 117 | 118 | /** 119 | * @brief Address not found 120 | */ 121 | #define TAI_STATUS_ADDR_NOT_FOUND TAI_STATUS_CODE(0x00000010L) 122 | 123 | /** 124 | * @brief TAI Object is in use 125 | */ 126 | #define TAI_STATUS_OBJECT_IN_USE TAI_STATUS_CODE(0x00000011L) 127 | 128 | /** 129 | * @brief Invalid TAI Object type passed to a function. 130 | * 131 | * If the object id is passed as an attribute value in list, then 132 | * #TAI_STATUS_INVALID_ATTR_VALUE_0 status code should be used. 133 | */ 134 | #define TAI_STATUS_INVALID_OBJECT_TYPE TAI_STATUS_CODE(0x00000012L) 135 | 136 | /** 137 | * @brief Invalid TAI Object ID passed to a function. 138 | * 139 | * Return #TAI_STATUS_INVALID_OBJECT_TYPE when the object type is invalid, 140 | * otherwise return this #TAI_STATUS_INVALID_OBJECT_ID. This can happen if the 141 | * object id is already deleted. 142 | */ 143 | #define TAI_STATUS_INVALID_OBJECT_ID TAI_STATUS_CODE(0x00000013L) 144 | 145 | /** 146 | * @brief The NV storage used is either invalid or corrupt. (rv for 147 | * initialize_module()) 148 | */ 149 | #define TAI_STATUS_INVALID_NV_STORAGE TAI_STATUS_CODE(0x00000014L) 150 | 151 | /** 152 | * @brief The NV storage is full. (rv for shutdown_module()) 153 | */ 154 | #define TAI_STATUS_NV_STORAGE_FULL TAI_STATUS_CODE(0x00000015L) 155 | 156 | /** 157 | * @brief Version mismatch in case of Inservice upgrade (rv for 158 | * initialize_module()) 159 | */ 160 | #define TAI_STATUS_SW_UPGRADE_VERSION_MISMATCH TAI_STATUS_CODE(0x00000016L) 161 | 162 | /** 163 | * @brief Operation not executed 164 | */ 165 | #define TAI_STATUS_NOT_EXECUTED TAI_STATUS_CODE(0x00000017L) 166 | 167 | /** 168 | * @brief Attribute is invalid 169 | * 170 | * Range from 0x00010000L to 0x0001FFFFL. 171 | * 172 | * Return this when the property attached to the attribute does not match 173 | * the API call. 174 | * 175 | * For example: 176 | * - When a READ_ONLY attribute is passed set_attribute or create call 177 | * - When a CREATE_ONLY attribute is passed to set_attribute call 178 | * 179 | * The offset from #TAI_STATUS_INVALID_ATTRIBUTE_0 is the array index of 180 | * the attribute list passed to the TAI API call. 181 | */ 182 | #define TAI_STATUS_INVALID_ATTRIBUTE_0 TAI_STATUS_CODE(0x00010000L) 183 | 184 | /** 185 | * @brief End of invalid attribute range 186 | */ 187 | #define TAI_STATUS_INVALID_ATTRIBUTE_MAX TAI_STATUS_CODE(0x0001FFFFL) 188 | 189 | /** 190 | * @brief Invalid attribute value 191 | * 192 | * Range from 0x00020000L to 0x0002FFFFL. 193 | */ 194 | #define TAI_STATUS_INVALID_ATTR_VALUE_0 TAI_STATUS_CODE(0x00020000L) 195 | 196 | /** 197 | * @brief End of invalid attribute value range 198 | */ 199 | #define TAI_STATUS_INVALID_ATTR_VALUE_MAX TAI_STATUS_CODE(0x0002FFFFL) 200 | 201 | /** 202 | * @brief Attribute is not implemented 203 | * 204 | * Range from 0x00030000L to 0x003FFFFL. 205 | * 206 | * Return this when the attribute is supported but not implemented on 207 | * the platform. 208 | */ 209 | #define TAI_STATUS_ATTR_NOT_IMPLEMENTED_0 TAI_STATUS_CODE(0x00030000L) 210 | 211 | /** 212 | * @brief End of not implemented range 213 | */ 214 | #define TAI_STATUS_ATTR_NOT_IMPLEMENTED_MAX TAI_STATUS_CODE(0x0003FFFFL) 215 | 216 | /** 217 | * @brief Attribute is unknown 218 | * 219 | * Range from 0x00040000L to 0x004FFFFL. 220 | * 221 | * Return this when the attribute is undefined, e.g., the attribute id 222 | * is out of range. 223 | */ 224 | #define TAI_STATUS_UNKNOWN_ATTRIBUTE_0 TAI_STATUS_CODE(0x00040000L) 225 | 226 | /** 227 | * @brief End of unknown attribute range 228 | */ 229 | #define TAI_STATUS_UNKNOWN_ATTRIBUTE_MAX TAI_STATUS_CODE(0x0004FFFFL) 230 | 231 | /** 232 | * @brief Attribute is not supported 233 | * 234 | * Range from 0x00050000L to 0x005FFFFL. 235 | * 236 | * Return this when the platform does not have the capability to support 237 | * this attribute. 238 | */ 239 | #define TAI_STATUS_ATTR_NOT_SUPPORTED_0 TAI_STATUS_CODE(0x00050000L) 240 | 241 | /** 242 | * @brief End of attribute not supported range 243 | */ 244 | #define TAI_STATUS_ATTR_NOT_SUPPORTED_MAX TAI_STATUS_CODE(0x0005FFFFL) 245 | 246 | /* 247 | * Macros to check if attribute related error is within the specified range 248 | */ 249 | 250 | /** 251 | * @brief Is invalid attribute helper 252 | */ 253 | #define TAI_STATUS_IS_INVALID_ATTRIBUTE(x) (((x) & (~0xFFFF)) == TAI_STATUS_INVALID_ATTRIBUTE_0) 254 | 255 | /** 256 | * @brief Is invalid attribute value helper 257 | */ 258 | #define TAI_STATUS_IS_INVALID_ATTR_VALUE(x) (((x) & (~0xFFFF)) == TAI_STATUS_INVALID_ATTR_VALUE_0) 259 | 260 | /** 261 | * @brief Is attribute not implemented helper 262 | */ 263 | #define TAI_STATUS_IS_ATTR_NOT_IMPLEMENTED(x) (((x) & (~0xFFFF)) == TAI_STATUS_ATTR_NOT_IMPLEMENTED_0) 264 | 265 | /** 266 | * @brief Is unknown attribute helper 267 | */ 268 | #define TAI_STATUS_IS_UNKNOWN_ATTRIBUTE(x) (((x) & (~0xFFFF)) == TAI_STATUS_INVALID_ATTRIBUTE_0) 269 | 270 | /** 271 | * @brief Is attribute not supported helper 272 | */ 273 | #define TAI_STATUS_IS_ATTR_NOT_SUPPORTED(x) (((x) & (~0xFFFF)) == TAI_STATUS_ATTR_NOT_SUPPORTED_0) 274 | 275 | /** 276 | * @} 277 | */ 278 | #endif /** __TAISTATUS_H_ */ 279 | -------------------------------------------------------------------------------- /inc/taitypes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taitypes.h 3 | * @brief This module defines TAI portable types 4 | * 5 | * @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc. 6 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 7 | * @copyright Copyright (c) 2017 Cumulus Networks, Inc. 8 | * All rights reserved. 9 | * 10 | * This source code is licensed under the BSD-style license found in the 11 | * LICENSE file in the root directory of this source tree. 12 | * 13 | * This source code includes software licensed by Microsoft under the 14 | * Apache License, Version 2.0 15 | * 16 | */ 17 | 18 | #if !defined (__TAITYPES_H_) 19 | #define __TAITYPES_H_ 20 | 21 | /** 22 | * @defgroup TAITYPES TAI - Types definitions 23 | * 24 | * @{ 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | typedef int32_t tai_status_t; 32 | typedef uint32_t tai_module_profile_id_t; 33 | typedef uint32_t tai_attr_id_t; 34 | 35 | #define _In_ 36 | #define _Out_ 37 | #define _Inout_ 38 | #define _In_reads_z_(_LEN_) 39 | #define _In_reads_opt_z_(_LEN_) 40 | 41 | /* 42 | * New common definitions 43 | */ 44 | 45 | typedef uint64_t tai_uint64_t; 46 | typedef int64_t tai_int64_t; 47 | typedef uint32_t tai_uint32_t; 48 | typedef int32_t tai_int32_t; 49 | typedef uint16_t tai_uint16_t; 50 | typedef int16_t tai_int16_t; 51 | typedef uint8_t tai_uint8_t; 52 | typedef int8_t tai_int8_t; 53 | typedef size_t tai_size_t; 54 | typedef float tai_float_t; 55 | typedef uint64_t tai_object_id_t; 56 | typedef void *tai_pointer_t; 57 | 58 | /** 59 | * @def TAI_NULL_OBJECT_ID 60 | * TAI NULL object ID 61 | */ 62 | #define TAI_NULL_OBJECT_ID 0L 63 | 64 | /** 65 | * @brief Defines a list of TAI object ids used as TAI attribute value. 66 | * 67 | * In set attribute function call, the count member defines the number of 68 | * objects. 69 | * 70 | * In get attribute function call, the function call returns a list of objects 71 | * to the caller in the list member. The caller is responsible for allocating 72 | * the buffer for the list member and set the count member to the size of 73 | * allocated object list. If the size is large enough to accommodate the list of 74 | * object id, the callee will then fill the list member and set the count member 75 | * to the actual number of objects. If the list size is not large enough, the 76 | * callee will set the count member to the actual number of object id and return 77 | * #TAI_STATUS_BUFFER_OVERFLOW. Once the caller gets such return code, it should 78 | * use the returned count member to re-allocate list and retry. 79 | */ 80 | typedef struct _tai_object_list_t 81 | { 82 | uint32_t count; 83 | tai_object_id_t *list; 84 | } tai_object_list_t; 85 | 86 | typedef struct _tai_object_map_t 87 | { 88 | tai_object_id_t key; 89 | tai_object_list_t value; 90 | } tai_object_map_t; 91 | 92 | /** 93 | * @brief TAI common API type 94 | */ 95 | typedef enum _tai_common_api_t 96 | { 97 | TAI_COMMON_API_CREATE = 0, 98 | TAI_COMMON_API_REMOVE = 1, 99 | TAI_COMMON_API_SET = 2, 100 | TAI_COMMON_API_GET = 3, 101 | TAI_COMMON_API_BULK_CREATE = 4, 102 | TAI_COMMON_API_BULK_REMOVE = 5, 103 | TAI_COMMON_API_BULK_SET = 6, 104 | TAI_COMMON_API_BULK_GET = 7, 105 | TAI_COMMON_API_MAX = 8, 106 | } tai_common_api_t; 107 | 108 | /** 109 | * @brief TAI object type 110 | */ 111 | typedef enum _tai_object_type_t 112 | { 113 | TAI_OBJECT_TYPE_NULL = 0, /**< invalid object type */ 114 | TAI_OBJECT_TYPE_MODULE = 1, 115 | TAI_OBJECT_TYPE_HOSTIF = 2, 116 | TAI_OBJECT_TYPE_NETWORKIF = 3, 117 | TAI_OBJECT_TYPE_MAX = 4, 118 | } tai_object_type_t; 119 | 120 | typedef struct _tai_char_list_t 121 | { 122 | uint32_t count; 123 | char *list; 124 | } tai_char_list_t; 125 | 126 | typedef struct _tai_u8_list_t 127 | { 128 | uint32_t count; 129 | uint8_t *list; 130 | } tai_u8_list_t; 131 | 132 | typedef struct _tai_s8_list_t 133 | { 134 | uint32_t count; 135 | int8_t *list; 136 | } tai_s8_list_t; 137 | 138 | typedef struct _tai_u16_list_t 139 | { 140 | uint32_t count; 141 | uint16_t *list; 142 | } tai_u16_list_t; 143 | 144 | typedef struct _tai_s16_list_t 145 | { 146 | uint32_t count; 147 | int16_t *list; 148 | } tai_s16_list_t; 149 | 150 | typedef struct _tai_u32_list_t 151 | { 152 | uint32_t count; 153 | uint32_t *list; 154 | } tai_u32_list_t; 155 | 156 | typedef struct _tai_s32_list_t 157 | { 158 | uint32_t count; 159 | int32_t *list; 160 | } tai_s32_list_t; 161 | 162 | typedef struct _tai_u64_list_t 163 | { 164 | uint32_t count; 165 | uint64_t *list; 166 | } tai_u64_list_t; 167 | 168 | typedef struct _tai_s64_list_t 169 | { 170 | uint32_t count; 171 | int64_t *list; 172 | } tai_s64_list_t; 173 | 174 | typedef struct _tai_float_list_t 175 | { 176 | uint32_t count; 177 | float *list; 178 | } tai_float_list_t; 179 | 180 | typedef struct _tai_u32_range_t 181 | { 182 | uint32_t min; 183 | uint32_t max; 184 | } tai_u32_range_t; 185 | 186 | typedef struct _tai_s32_range_t 187 | { 188 | int32_t min; 189 | int32_t max; 190 | } tai_s32_range_t; 191 | 192 | typedef struct _tai_object_map_list_t 193 | { 194 | /** Number of entries in the map */ 195 | uint32_t count; 196 | 197 | /** Map list */ 198 | tai_object_map_t *list; 199 | 200 | /** Number of tai_object_map_t allocated in the list */ 201 | uint32_t _alloced; 202 | 203 | } tai_object_map_list_t; 204 | 205 | // Forward declaration of tai_attribute_value_t for tai_attr_value_list_t 206 | union _tai_attribute_value_t; 207 | typedef union _tai_attribute_value_t tai_attribute_value_t; 208 | 209 | typedef struct _tai_attr_value_list_t 210 | { 211 | /** Number of attribute values in the list */ 212 | uint32_t count; 213 | 214 | /** Attribute value list */ 215 | tai_attribute_value_t *list; 216 | 217 | /** Number of attribute values allocated in the list */ 218 | uint32_t _alloced; 219 | } tai_attr_value_list_t; 220 | 221 | // Forward declaration of tai_attribute_t for tai_notification_fn 222 | struct _tai_attribute_t; 223 | typedef struct _tai_attribute_t tai_attribute_t; 224 | 225 | /** 226 | * @brief TAI notification callback 227 | * 228 | * @param[in] context User context 229 | * @param[in] oid object ID 230 | * @param[in] attr_count Number of attributes 231 | * @param[in] attr_list List of updated attributes 232 | */ 233 | typedef void (*tai_notification_fn)( 234 | _In_ void* context, 235 | _In_ tai_object_id_t oid, 236 | _In_ uint32_t attr_count, 237 | _In_ tai_attribute_t const * const attr_list); 238 | 239 | /** 240 | * @brief TAI notification handler 241 | * 242 | * Generic notification handler which can be used by any TAI objects 243 | * 244 | * The handler will be set by TAI adapter host by using TAI attribute 245 | * whose value type must be #tai_pointer_t #tai_notification_handler_t 246 | * 247 | */ 248 | typedef struct _tai_notification_handler_t { 249 | void* context; 250 | tai_notification_fn notify; 251 | } tai_notification_handler_t; 252 | 253 | /** 254 | * @brief Data Type 255 | * 256 | * To use enum values as attribute value is tai_int32_t s32 257 | */ 258 | typedef union _tai_attribute_value_t 259 | { 260 | bool booldata; 261 | char chardata[32]; 262 | tai_uint8_t u8; 263 | tai_int8_t s8; 264 | tai_uint16_t u16; 265 | tai_int16_t s16; 266 | tai_uint32_t u32; 267 | tai_int32_t s32; 268 | tai_uint64_t u64; 269 | tai_int64_t s64; 270 | tai_float_t flt; 271 | tai_pointer_t ptr; 272 | tai_object_id_t oid; 273 | tai_object_list_t objlist; 274 | tai_char_list_t charlist; 275 | tai_u8_list_t u8list; 276 | tai_s8_list_t s8list; 277 | tai_u16_list_t u16list; 278 | tai_s16_list_t s16list; 279 | tai_u32_list_t u32list; 280 | tai_s32_list_t s32list; 281 | tai_u64_list_t u64list; 282 | tai_s64_list_t s64list; 283 | tai_float_list_t floatlist; 284 | tai_u32_range_t u32range; 285 | tai_s32_range_t s32range; 286 | tai_object_map_list_t objmaplist; 287 | tai_attr_value_list_t attrlist; 288 | tai_notification_handler_t notification; 289 | } tai_attribute_value_t; 290 | 291 | typedef struct _tai_attribute_t 292 | { 293 | tai_attr_id_t id; 294 | tai_attribute_value_t value; 295 | } tai_attribute_t; 296 | 297 | typedef struct _tai_attribute_capability_t { 298 | tai_attr_id_t id; 299 | 300 | /* default value is set by TAI adapter */ 301 | bool valid_defaultvalue; 302 | /* min is set by TAI adapter */ 303 | bool valid_min; 304 | /* max is set by TAI adapter */ 305 | bool valid_max; 306 | /* supportedvalues is set by TAI adapter */ 307 | bool valid_supportedvalues; 308 | 309 | /* default value of this attribute */ 310 | tai_attribute_value_t defaultvalue; 311 | 312 | /* minimum value of this attribute */ 313 | tai_attribute_value_t min; 314 | 315 | /* maximum value of this attribute */ 316 | tai_attribute_value_t max; 317 | 318 | /* supported values of this attribute ( only valid for enum attribute ) */ 319 | tai_attr_value_list_t supportedvalues; 320 | 321 | } tai_attribute_capability_t; 322 | 323 | /** 324 | * @} 325 | */ 326 | #endif /** __TAITYPES_H_ */ 327 | -------------------------------------------------------------------------------- /logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/logo/logo.png -------------------------------------------------------------------------------- /meta/.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | taimetadata.c 3 | taimetadata.h 4 | -------------------------------------------------------------------------------- /meta/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | TAI_META_OUT_DIR ?= $(abspath .) 4 | 5 | INCLUDE ?= -I $(TAI_META_OUT_DIR) -I ../inc 6 | 7 | CFLAGS ?= -fPIC $(INCLUDE) -Wall -Werror 8 | 9 | ifdef DEBUG 10 | CFLAGS += -ggdb -g3 -O0 11 | else 12 | CFLAGS += -O2 13 | endif 14 | 15 | LDFLAGS ?= -shared 16 | 17 | _SRCS ?= $(addprefix $(TAI_META_OUT_DIR)/,$(filter-out taimetadata.c,$(wildcard *.c))) 18 | _HEADERS ?= $(addprefix $(TAI_META_OUT_DIR)/,$(filter-out taimetadata.h,$(wildcard *.h))) 19 | 20 | SRCS ?= $(TAI_META_OUT_DIR)/taimetadata.c $(_SRCS) 21 | HEADERS ?= $(TAI_META_OUT_DIR)/taimetadata.h $(_HEADERS) 22 | OBJS = $(addsuffix .o,$(basename $(SRCS))) 23 | 24 | $(TAI_META_OUT_DIR)/libmetatai.so: $(OBJS) 25 | $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) 26 | 27 | $(_SRCS): $(_HEADERS) 28 | if [ $(TAI_META_OUT_DIR) != $(abspath .) ]; then cp $(notdir $@) $(TAI_META_OUT_DIR)/; fi 29 | 30 | $(_HEADERS): 31 | if [ $(TAI_META_OUT_DIR) != $(abspath .) ]; then cp $(notdir $@) $(TAI_META_OUT_DIR)/; fi 32 | 33 | $(TAI_META_OUT_DIR)/taimetadata.c $(TAI_META_OUT_DIR)/taimetadata.h: $(TAI_META_CUSTOM_FILES) $(wildcard ../inc/*) $(_HEADERS) 34 | tai_meta_generator --out-dir $(TAI_META_OUT_DIR) ../inc/tai.h $(TAI_META_CUSTOM_FILES) 35 | 36 | test: 37 | make -C sample 38 | make -C test TAI_META_OUT_DIR=$(abspath sample) 39 | LD_LIBRARY_PATH=$(abspath sample) ./test/test 40 | 41 | clean: 42 | $(RM) $(addprefix $(TAI_META_OUT_DIR)/,libmetatai.so taimetadata.c taimetadata.h) *.o 43 | if [ $(TAI_META_OUT_DIR) != $(abspath .) ]; then $(RM) $(_SRCS) $(_HEADERS); fi 44 | -------------------------------------------------------------------------------- /meta/README.md: -------------------------------------------------------------------------------- 1 | Metadata for TAI 2 | ================ 3 | 4 | Metadata for TAI is a set of auto generated (based on TAI headers) data 5 | and functions which allow TAI attributes serialization and more. 6 | 7 | Metadata is generated as ANSI C source and header. 8 | 9 | Parser also forces headers to be well formated when adding new code. 10 | 11 | As same as TAI itself, TAI metadata is based upon and quite common to the 12 | SAI metadata. 13 | 14 | 15 | ## How to build 16 | 17 | ### native build 18 | 19 | #### prerequisite 20 | 21 | - gcc 22 | - python3 23 | - libclang6.0 24 | 25 | ```sh 26 | $ make 27 | ``` 28 | 29 | ### Docker build 30 | 31 | #### prerequisite 32 | 33 | - docker 34 | 35 | ```sh 36 | $ make docker-image 37 | $ make docker 38 | ``` 39 | -------------------------------------------------------------------------------- /meta/sample/Makefile: -------------------------------------------------------------------------------- 1 | TAI_META_OUT_DIR ?= $(abspath .)/ 2 | 3 | all: 4 | TAI_META_CUSTOM_FILES=$(abspath ./custom.h) TAI_META_OUT_DIR=$(TAI_META_OUT_DIR) $(MAKE) -C .. 5 | 6 | clean: 7 | TAI_META_OUT_DIR=$(TAI_META_OUT_DIR) $(MAKE) -C .. $@ 8 | -------------------------------------------------------------------------------- /meta/sample/custom.h: -------------------------------------------------------------------------------- 1 | #ifndef __CUSTOM_MODULE__ 2 | #define __CUSTOM_MODULE__ 3 | 4 | #include 5 | 6 | /** 7 | * @brief Custom enum 8 | */ 9 | typedef enum _tai_module_custom_status_t 10 | { 11 | TAI_MODULE_CUSTOM_STATUS_UNKNOWN, 12 | TAI_MODULE_CUSTOM_STATUS_A, 13 | TAI_MODULE_CUSTOM_STATUS_B, 14 | TAI_MODULE_CUSTOM_STATUS_MAX, 15 | } tai_module_custom_status_t; 16 | 17 | /** 18 | * @brief definition of custom module attributes 19 | */ 20 | typedef enum _custom_module_attr_t 21 | { 22 | TAI_MODULE_ATTR_CUSTOM_START = TAI_MODULE_ATTR_CUSTOM_RANGE_START, 23 | 24 | /** 25 | * @brief Custom attribute 26 | * 27 | * @type #tai_module_custom_status_t 28 | * @flags READ_ONLY 29 | */ 30 | TAI_MODULE_ATTR_CUSTOM_STATUS, 31 | 32 | TAI_MODULE_ATTR_CUSTOM_END = TAI_MODULE_ATTR_CUSTOM_RANGE_END, 33 | 34 | } custom_module_attr_t; 35 | 36 | #endif // __CUSTOM_MODULE__ 37 | -------------------------------------------------------------------------------- /meta/taimetadatalogger.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taimetadatalogger.h 3 | * 4 | * @brief This module defines TAI Metadata Logger 5 | * 6 | * @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc. 7 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 8 | * All rights reserved. 9 | * 10 | * This source code is licensed under the BSD-style license found in the 11 | * LICENSE file in the root directory of this source tree. 12 | * 13 | * This source code includes software licensed by Microsoft under the 14 | * Apache License, Version 2.0 15 | * 16 | */ 17 | 18 | #ifndef __TAIMETADATALOGGER_H_ 19 | #define __TAIMETADATALOGGER_H_ 20 | 21 | /** 22 | * @defgroup TAIMETADATALOGGER TAI - Metadata Logger Definitions 23 | * 24 | * @{ 25 | */ 26 | 27 | /** 28 | * @brief Log level function definition. 29 | * 30 | * User can specify his own function that will be called when message log level 31 | * will be greater or equal to #tai_metadata_log_level. 32 | * 33 | * @param[in] log_level Log level 34 | * @param[in] file Source file 35 | * @param[in] line Line number in file 36 | * @param[in] function Function name 37 | * @param[in] format Format of logging 38 | * @param[in] ... Variable parameters 39 | */ 40 | typedef void (*tai_metadata_log_fn)( 41 | _In_ tai_log_level_t log_level, 42 | _In_ const char *file, 43 | _In_ int line, 44 | _In_ const char *function, 45 | _In_ const char *format, 46 | _In_ ...); 47 | 48 | /** 49 | * @brief User specified log function. 50 | * 51 | * TODO: add a set function to update this? 52 | */ 53 | extern volatile tai_metadata_log_fn tai_metadata_log; 54 | 55 | /** 56 | * @brief Log level for TAI metadata macros. 57 | * 58 | * Log level can be changed by user at any time. 59 | * 60 | * TODO: add a set function to update this? 61 | */ 62 | extern volatile tai_log_level_t tai_metadata_log_level; 63 | 64 | /** 65 | * @brief Helper log macro definition 66 | * 67 | * If logger function is NULL, stderr is used to print messages. Also, fprintf 68 | * function will validate parameters at compilation time. 69 | */ 70 | #define TAI_META_LOG(loglevel,format,...)\ 71 | if (loglevel >= tai_metadata_log_level)\ 72 | {\ 73 | if (tai_metadata_log == NULL) /* or syslog? */ \ 74 | fprintf(stderr, "%s:%d %s: " format "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);\ 75 | else\ 76 | tai_metadata_log(loglevel, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__);\ 77 | } 78 | 79 | /* 80 | * Helper macros. 81 | */ 82 | 83 | #define TAI_META_LOG_ENTER() TAI_META_LOG(TAI_LOG_LEVEL_DEBUG, ":> enter"); 84 | #define TAI_META_LOG_DEBUG(format,...) TAI_META_LOG(TAI_LOG_LEVEL_DEBUG, ":- " format, ##__VA_ARGS__) 85 | #define TAI_META_LOG_INFO(format,...) TAI_META_LOG(TAI_LOG_LEVEL_INFO, ":- " format, ##__VA_ARGS__) 86 | #define TAI_META_LOG_NOTICE(format,...) TAI_META_LOG(TAI_LOG_LEVEL_NOTICE, ":- " format, ##__VA_ARGS__) 87 | #define TAI_META_LOG_WARN(format,...) TAI_META_LOG(TAI_LOG_LEVEL_WARN, ":- " format, ##__VA_ARGS__) 88 | #define TAI_META_LOG_ERROR(format,...) TAI_META_LOG(TAI_LOG_LEVEL_ERROR, ":- " format, ##__VA_ARGS__) 89 | #define TAI_META_LOG_CRITICAL(format,...) TAI_META_LOG(TAI_LOG_LEVEL_CRITICAL, ":- " format, ##__VA_ARGS__) 90 | #define TAI_META_LOG_EXIT() TAI_META_LOG(TAI_LOG_LEVEL_DEBUG, ":< exit"); 91 | 92 | /** 93 | * @} 94 | */ 95 | #endif /** __TAIMETADATALOGGER_H_ */ 96 | -------------------------------------------------------------------------------- /meta/taimetadatautils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taimetadatautils.h 3 | * 4 | * @brief This module defines TAI Metadata Utilities 5 | * 6 | * @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc. 7 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 8 | * All rights reserved. 9 | * 10 | * This source code is licensed under the BSD-style license found in the 11 | * LICENSE file in the root directory of this source tree. 12 | * 13 | * This source code includes software licensed by Microsoft under the 14 | * Apache License, Version 2.0 15 | * 16 | */ 17 | 18 | #ifndef __TAIMETADATAUTILS_H_ 19 | #define __TAIMETADATAUTILS_H_ 20 | 21 | #include "taimetadatatypes.h" 22 | 23 | /** 24 | * @defgroup TAIMETADATAUTILS TAI - Metadata Utilities Definitions 25 | * 26 | * @{ 27 | */ 28 | 29 | /** 30 | * @brief Is allowed object type 31 | * 32 | * @param[in] metadata Attribute metadata 33 | * @param[in] object_type Object type to be checked 34 | * 35 | * @return True if object is allowed on this attribute, false otherwise 36 | */ 37 | extern bool tai_metadata_is_allowed_object_type( 38 | _In_ const tai_attr_metadata_t *metadata, 39 | _In_ tai_object_type_t object_type); 40 | 41 | /** 42 | * @brief Is allowed enum value 43 | * 44 | * @param[in] metadata Attribute metadata 45 | * @param[in] value Enum value to be checked 46 | * 47 | * @return True if enum value is allowed on this attribute, false otherwise 48 | */ 49 | extern bool tai_metadata_is_allowed_enum_value( 50 | _In_ const tai_attr_metadata_t *metadata, 51 | _In_ int value); 52 | 53 | /** 54 | * @brief Gets attribute metadata based on object type and attribute id 55 | * 56 | * @param[in] object_type Object type 57 | * @param[in] attr_id Attribute Id 58 | * 59 | * @return Pointer to object metadata or NULL in case of failure 60 | */ 61 | extern const tai_attr_metadata_t* tai_metadata_get_attr_metadata( 62 | _In_ tai_object_type_t object_type, 63 | _In_ tai_attr_id_t attr_id); 64 | 65 | /** 66 | * @brief Gets attribute metadata based on attribute id name 67 | * 68 | * @param[in] attr_id_name Attribute id name 69 | * 70 | * @return Pointer to object metadata or NULL in case of failure 71 | */ 72 | extern const tai_attr_metadata_t* tai_metadata_get_attr_metadata_by_attr_id_name( 73 | _In_ const char *attr_id_name); 74 | 75 | /** 76 | * @brief Gets string representation of enum value 77 | * 78 | * @param[in] metadata Enum metadata 79 | * @param[in] value Enum value to be converted to string 80 | * 81 | * @return String representation of enum value or NULL if value was not found 82 | */ 83 | extern const char* tai_metadata_get_enum_value_name( 84 | _In_ const tai_enum_metadata_t *metadata, 85 | _In_ int value); 86 | 87 | /** 88 | * @brief Gets attribute from attribute list by attribute id. 89 | * 90 | * @param[in] id Attribute id to be found. 91 | * @param[in] attr_count Total number of attributes. 92 | * @param[in] attr_list List of attributes to search. 93 | * 94 | * @return Attribute pointer with requested ID or NULL if not found. 95 | * When multiple attributes with the same id are passed, only first 96 | * attribute is returned. 97 | */ 98 | extern const tai_attribute_t* tai_metadata_get_attr_by_id( 99 | _In_ tai_attr_id_t id, 100 | _In_ uint32_t attr_count, 101 | _In_ const tai_attribute_t *attr_list); 102 | 103 | /** 104 | * @brief Gets object type info 105 | * 106 | * @param[in] object_type Object type 107 | * 108 | * @return Object type info structure or NULL if not found 109 | */ 110 | extern const tai_object_type_info_t* tai_metadata_get_object_type_info( 111 | _In_ tai_object_type_t object_type); 112 | 113 | /** 114 | * @brief Checks if object type is valid 115 | * 116 | * @param[in] object_type Object type 117 | * 118 | * @return True if object type is valid, false otherwise 119 | */ 120 | extern bool tai_metadata_is_object_type_valid( 121 | _In_ tai_object_type_t object_type); 122 | 123 | /** 124 | * @brief Check if condition met. 125 | * 126 | * List of attributes will be examined in terms of conditions. This is 127 | * convenient since user can pass list when calling create API. If 128 | * condition attribute is not on the list, then default value will be 129 | * examined. 130 | * 131 | * NOTE: When multiple attributes with the same ID are passed, 132 | * tai_metadata_get_attr_by_id will select only first one. 133 | * Function will not be able to handle multiple attributes 134 | * 135 | * @param[in] metadata Metadata of attribute that we need to check. 136 | * @param[in] attr_count Number of attributes. 137 | * @param[in] attr_list Attribute list to check. All attributes must 138 | * belong to the same object type as metadata parameter. 139 | * 140 | * @return True if condition is in force, false otherwise. False will be also 141 | * returned if any of input pointers is NULL or attribute is not conditional. 142 | */ 143 | extern bool tai_metadata_is_condition_met( 144 | _In_ const tai_attr_metadata_t *metadata, 145 | _In_ uint32_t attr_count, 146 | _In_ const tai_attribute_t *attr_list); 147 | 148 | /** 149 | * @brief Allocation info 150 | * 151 | * hint for the allocation 152 | * 153 | */ 154 | 155 | typedef struct _tai_alloc_info_t { 156 | uint32_t list_size; 157 | 158 | /** 159 | * @brief reference attribute for size information 160 | */ 161 | const tai_attribute_t* reference; 162 | } tai_alloc_info_t; 163 | 164 | /** 165 | * @brief Allocate tai_attribute_t value 166 | * 167 | * By passing info == NULL, it will use default list size for the list value 168 | * allocation 169 | * 170 | * @param[in] metadata Attribute metadata 171 | * @param[in] attr Attribute to allocate 172 | * @param[in] info Allocation information 173 | * 174 | * @return TAI_STATUS_SUCCESS on success, 175 | * TAI_STATUS_INVALID_PARAMETER/TAI_STATUS_NO_MEMORY on failure 176 | */ 177 | extern tai_status_t tai_metadata_alloc_attr_value( 178 | _In_ const tai_attr_metadata_t* const metadata, 179 | _In_ tai_attribute_t* const attr, 180 | _In_ const tai_alloc_info_t* const info); 181 | 182 | /** 183 | * @brief Free tai_attribute_t value 184 | * 185 | * @param[in] metadata Attribute metadata 186 | * @param[in] attr Attribute to free 187 | * @param[in] info Allocation information 188 | * 189 | * @return TAI_STATUS_SUCCESS on success, 190 | * TAI_STATUS_INVALID_PARAMETER on failure 191 | */ 192 | extern tai_status_t tai_metadata_free_attr_value( 193 | _In_ const tai_attr_metadata_t* const metadata, 194 | _In_ tai_attribute_t* const attr, 195 | _In_ const tai_alloc_info_t* const info); 196 | 197 | /** 198 | * @brief Clear tai_attribute_t value 199 | * 200 | * @param[in] metadata Attribute metadata 201 | * @param[in] attr Attribute to clear 202 | * 203 | * @return TAI_STATUS_SUCCESS on success, 204 | * TAI_STATUS_INVALID_PARAMETER on failure 205 | */ 206 | extern tai_status_t tai_metadata_clear_attr_value( 207 | _In_ const tai_attr_metadata_t* const metadata, 208 | _In_ tai_attribute_t* const attr); 209 | 210 | /** 211 | * @brief Deep copy tai_attribute_t value 212 | * 213 | * @param[in] metadata Attribute metadata 214 | * @param[in] in original attribute for the copy 215 | * @param[in] out destination for the copy 216 | * 217 | * @return TAI_STATUS_SUCCESS on success, 218 | * TAI_STATUS_INVALID_PARAMETER on failure 219 | */ 220 | extern tai_status_t tai_metadata_deepcopy_attr_value( 221 | _In_ const tai_attr_metadata_t* const metadata, 222 | _In_ const tai_attribute_t* const in, 223 | _Out_ tai_attribute_t* const out); 224 | 225 | /** 226 | * @brief Deep equal tai_attribute_t value 227 | * 228 | * @param[in] metadata Attribute metadata 229 | * @param[in] lhs 230 | * @param[in] rhs 231 | * @param[out] result 232 | * 233 | * @return TAI_STATUS_SUCCESS on success, 234 | * TAI_STATUS_INVALID_PARAMETER on failure 235 | */ 236 | extern tai_status_t tai_metadata_deepequal_attr_value( 237 | _In_ const tai_attr_metadata_t* const metadata, 238 | _In_ const tai_attribute_t* const lhs, 239 | _In_ const tai_attribute_t* const rhs, 240 | _Out_ bool* result); 241 | 242 | extern tai_status_t tai_metadata_le_attr_value( 243 | _In_ const tai_attr_metadata_t* const metadata, 244 | _In_ const tai_attribute_t* const lhs, 245 | _In_ const tai_attribute_t* const rhs, 246 | _Out_ bool* result); 247 | 248 | extern tai_status_t tai_metadata_ge_attr_value( 249 | _In_ const tai_attr_metadata_t* const metadata, 250 | _In_ const tai_attribute_t* const lhs, 251 | _In_ const tai_attribute_t* const rhs, 252 | _Out_ bool* result); 253 | 254 | /** 255 | * @} 256 | */ 257 | #endif /** __TAIMETADATAUTILS_H_ */ 258 | -------------------------------------------------------------------------------- /meta/test/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /meta/test/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -g3 -Wall -Werror -I $(TAI_META_OUT_DIR) -I ../ -I ../../inc -o test test.c -L $(TAI_META_OUT_DIR) -lmetatai 3 | -------------------------------------------------------------------------------- /stub/.gitignore: -------------------------------------------------------------------------------- 1 | libtai.so 2 | -------------------------------------------------------------------------------- /stub/Makefile: -------------------------------------------------------------------------------- 1 | LIB := -L ../meta/ -lmetatai 2 | INCLUDE := -I ../meta -I ../inc 3 | 4 | all: 5 | gcc -shared -fPIC $(INCLUDE) stub_tai.c -o libtai.so $(LIB) 6 | 7 | clean: 8 | rm libtai.so 9 | -------------------------------------------------------------------------------- /stub/README.md: -------------------------------------------------------------------------------- 1 | TAI stub library 2 | ================ 3 | 4 | TAI stub library is an example TAI library. 5 | TAI library implementers can use this as a reference implementation. 6 | 7 | ## How to build 8 | 9 | #### prerequisite 10 | 11 | - [TAI meta library](https://github.com/Telecominfraproject/oopt-tai/tree/master/meta) 12 | 13 | ``` 14 | $ make 15 | ``` 16 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | TAI_TEST_TARGET ?= ../tools/framework/examples/basic/libtai.so 2 | 3 | ifndef TAI_TEST_CASE 4 | TAI_TEST_CASE := test_base.py 5 | endif 6 | 7 | ifndef TAI_TAISH_SERVER 8 | TAI_TAISH_SERVER := ../tools/taish/taish_server 9 | endif 10 | 11 | ifndef LD_LIBRARY_PATH 12 | LD_LIBRARY_PATH := $(dir $(TAI_TEST_TARGET)) 13 | endif 14 | 15 | .PHONY: all c python 16 | 17 | all: c python 18 | 19 | ../meta/libmetatai.so: 20 | $(MAKE) -C $(@D) 21 | 22 | c: $(TAI_TEST_TARGET) 23 | gcc -I ../inc -o test test.c -L $(dir $(TAI_TEST_TARGET)) -ltai 24 | LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) ./test 25 | 26 | python: taish $(TAI_TAISH_SERVER) $(TAI_TEST_TARGET) 27 | TAI_TEST_MODULE_LOCATION=$(TAI_TEST_MODULE_LOCATION) PATH=$(dir $(TAI_TAISH_SERVER)):${PATH} LD_LIBRARY_PATH=$(dir $(TAI_TEST_TARGET)) python -m unittest $(TAI_TEST_CASE) -f -v 28 | 29 | taish: 30 | which taish 2>&1 > /dev/null || (cd $(dir $(TAI_TAISH_SERVER)) && python setup.py install) 31 | 32 | $(TAI_TEST_TARGET): 33 | $(MAKE) -C $(@D) 34 | 35 | $(TAI_TAISH_SERVER): 36 | $(MAKE) -C $(@D) 37 | 38 | clean: 39 | rm test 40 | -------------------------------------------------------------------------------- /tests/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "0": { 3 | "attrs": { 4 | "admin-status": "down", 5 | "custom": true 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | tai_module_api_t *module_api; 7 | tai_network_interface_api_t *network_interface_api; 8 | tai_host_interface_api_t *host_interface_api; 9 | tai_meta_api_t *meta_api; 10 | 11 | #define TAI_MAX_HOST_IFS 8 12 | #define TAI_MAX_NET_IFS 8 13 | 14 | int g_module_location_head = 0; 15 | int g_module_location_tail = 0; 16 | char g_module_locations[TAI_MAX_MODULES+1][TAI_MAX_HARDWARE_ID_LEN]; 17 | 18 | tai_object_id_t g_module_ids[TAI_MAX_MODULES]; 19 | tai_object_id_t g_netif_ids[TAI_MAX_MODULES][TAI_MAX_NET_IFS]; 20 | tai_object_id_t g_hostif_ids[TAI_MAX_MODULES][TAI_MAX_HOST_IFS]; 21 | 22 | 23 | void module_shutdown(tai_object_id_t module_id) 24 | { 25 | printf("Module shutdown request received for module_id %lx", module_id); 26 | } 27 | 28 | void module_state_change(tai_object_id_t module_id, tai_module_oper_status_t status) 29 | { 30 | printf("Module state change received for module_id %lx. New state: %d", 31 | module_id, status); 32 | } 33 | 34 | tai_status_t create_modules() { 35 | tai_status_t status; 36 | tai_attribute_t attr[4]; 37 | int network_ifs; 38 | int host_ifs; 39 | int i; 40 | 41 | while (g_module_location_head != g_module_location_tail) { 42 | attr[0].id = TAI_MODULE_ATTR_LOCATION; 43 | attr[0].value.charlist.count = strlen(g_module_locations[g_module_location_tail]); 44 | attr[0].value.charlist.list = g_module_locations[g_module_location_tail]; 45 | attr[1].id = TAI_MODULE_ATTR_MODULE_SHUTDOWN_REQUEST_NOTIFY; 46 | attr[1].value.ptr = module_shutdown; 47 | attr[2].id = TAI_MODULE_ATTR_MODULE_STATE_CHANGE_NOTIFY; 48 | attr[2].value.ptr = module_state_change; 49 | status = module_api->create_module(&g_module_ids[g_module_location_tail], 3, attr); 50 | if ( status != TAI_STATUS_SUCCESS ) { 51 | return status; 52 | } 53 | 54 | attr[0].id = TAI_MODULE_ATTR_NUM_NETWORK_INTERFACES; 55 | attr[0].value.u32 = 0; 56 | status = module_api->get_module_attribute(g_module_ids[g_module_location_tail], &attr[0]); 57 | if ( status != TAI_STATUS_SUCCESS ) { 58 | return status; 59 | } 60 | printf("number of network interfaces on module %s: %d\n", 61 | g_module_locations[g_module_location_tail], attr[0].value.u32); 62 | network_ifs = attr[0].value.u32; 63 | 64 | for (i = 0; i < network_ifs; i++) { 65 | attr[0].id = TAI_NETWORK_INTERFACE_ATTR_INDEX; 66 | attr[0].value.u32 = i; 67 | 68 | attr[1].id = TAI_NETWORK_INTERFACE_ATTR_TX_DIS; 69 | attr[1].value.booldata = false; 70 | 71 | attr[2].id = TAI_NETWORK_INTERFACE_ATTR_TX_LASER_FREQ; 72 | attr[2].value.u64 = 191300000000000; 73 | 74 | attr[3].id = TAI_NETWORK_INTERFACE_ATTR_OUTPUT_POWER; 75 | attr[3].value.flt = 1.0; 76 | 77 | status = network_interface_api->create_network_interface( 78 | &g_netif_ids[g_module_location_tail][i], 79 | g_module_ids[g_module_location_tail], 4, &attr[0]); 80 | if ( status != TAI_STATUS_SUCCESS ) { 81 | return status; 82 | } 83 | } 84 | 85 | attr[0].id = TAI_MODULE_ATTR_NUM_HOST_INTERFACES; 86 | attr[0].value.u32 = 0; 87 | status = module_api->get_module_attribute(g_module_ids[g_module_location_tail], &attr[0]); 88 | if ( status != TAI_STATUS_SUCCESS ) { 89 | return status; 90 | } 91 | printf("number of host interfaces on module %s: %d\n", 92 | g_module_locations[g_module_location_tail], attr[0].value.u32); 93 | host_ifs = attr[0].value.u32; 94 | 95 | for (i = 0; i < host_ifs; i++) { 96 | attr[0].id = TAI_HOST_INTERFACE_ATTR_INDEX; 97 | attr[0].value.u32 = i; 98 | 99 | status = host_interface_api->create_host_interface( 100 | &g_hostif_ids[g_module_location_tail][i], 101 | g_module_ids[g_module_location_tail], 1, &attr[0]); 102 | if ( status != TAI_STATUS_SUCCESS ) { 103 | return status; 104 | } 105 | } 106 | 107 | attr[0].id = TAI_MODULE_ATTR_ADMIN_STATUS; 108 | attr[0].value.u32 = TAI_MODULE_ADMIN_STATUS_UP; 109 | 110 | status = module_api->set_module_attribute( 111 | g_module_ids[g_module_location_tail], &attr[0]); 112 | if ( status != TAI_STATUS_SUCCESS ) { 113 | return status; 114 | } 115 | 116 | g_module_location_tail = (g_module_location_tail + 1) % (TAI_MAX_MODULES+1); 117 | } 118 | return status; 119 | } 120 | 121 | void module_event(bool present, char * module_location) 122 | { 123 | int next_head = (g_module_location_head + 1) % (TAI_MAX_MODULES+1); 124 | 125 | printf("module_event: module %s is %s\n", 126 | module_location, present ? "present" : "absent"); 127 | if (present && (next_head != g_module_location_tail)) { 128 | strcpy(g_module_locations[g_module_location_head], module_location); 129 | g_module_location_head = next_head; 130 | } 131 | return; 132 | } 133 | 134 | tai_service_method_table_t g_service_table = { 135 | .module_presence = module_event 136 | }; 137 | 138 | int main() { 139 | tai_status_t status; 140 | int i; 141 | status = tai_api_initialize(0, &g_service_table); 142 | if ( status != TAI_STATUS_SUCCESS ) { 143 | printf("failed to initialize TAI\n"); 144 | return 1; 145 | } 146 | tai_log_set(TAI_API_MODULE, TAI_LOG_LEVEL_INFO, NULL); 147 | tai_log_set(TAI_API_HOSTIF, TAI_LOG_LEVEL_INFO, NULL); 148 | tai_log_set(TAI_API_NETWORKIF, TAI_LOG_LEVEL_INFO, NULL); 149 | 150 | status = tai_api_query(TAI_API_MODULE, (void**)&module_api); 151 | if ( status != TAI_STATUS_SUCCESS ) { 152 | printf("no api for TAI_API_MODULE\n"); 153 | return 1; 154 | } 155 | 156 | printf("module_api: %p\n", module_api); 157 | 158 | status = tai_api_query(TAI_API_NETWORKIF, (void**)&network_interface_api); 159 | if ( status != TAI_STATUS_SUCCESS ) { 160 | printf("no api for TAI_API_NETWORKIF\n"); 161 | return 1; 162 | } 163 | 164 | printf("network_interface_api: %p\n", network_interface_api); 165 | 166 | status = tai_api_query(TAI_API_HOSTIF, (void**)&host_interface_api); 167 | if ( status != TAI_STATUS_SUCCESS ) { 168 | printf("no api for TAI_API_HOSTIF\n"); 169 | return 1; 170 | } 171 | 172 | printf("host_interface_api: %p\n", host_interface_api); 173 | 174 | status = tai_api_query(TAI_API_META, (void**)&meta_api); 175 | if ( status != TAI_STATUS_SUCCESS ) { 176 | printf("no api for TAI_API_META\n"); 177 | } 178 | 179 | printf("meta_api: %p\n", meta_api); 180 | 181 | sleep(1); 182 | create_modules(); 183 | 184 | printf("module oid: 0x%lx\n", g_module_ids[0]); 185 | 186 | if ( meta_api != NULL ) { 187 | uint32_t count; 188 | const tai_attr_metadata_t * const *list; 189 | const tai_attr_metadata_t *meta; 190 | tai_metadata_key_t key; 191 | key.oid = g_module_ids[0]; 192 | status = meta_api->list_metadata(&key, &count, &list); 193 | printf("module list metadata: status: %d, count: %u, list: %p\n", status, count, list); 194 | 195 | key.oid = g_netif_ids[0][0]; 196 | status = meta_api->list_metadata(&key, &count, &list); 197 | printf("netif list metadata: status: %d, count: %u, list: %p\n", status, count, list); 198 | 199 | meta = meta_api->get_attr_metadata(&key, TAI_NETWORK_INTERFACE_ATTR_INDEX); 200 | if ( meta == NULL ) { 201 | printf("failed to get TAI_NETWORK_INTERFACE_ATTR_INDEX metadata\n"); 202 | return 1; 203 | } 204 | if (!meta->ismandatoryoncreate) { 205 | printf("wrong TAI_NETWORK_INTERFACE_ATTR_INDEX metadata. must be MANDATORY_ON_CREATE\n"); 206 | return 1; 207 | } 208 | 209 | } 210 | 211 | status = tai_api_uninitialize(); 212 | if ( status != TAI_STATUS_SUCCESS ) { 213 | printf("failed to uninitialize TAI\n"); 214 | return 1; 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /tools/framework/README.md: -------------------------------------------------------------------------------- 1 | TAI library framework 2 | --- 3 | 4 | a framework to build TAI library. 5 | see examples/stub for how to use it. 6 | -------------------------------------------------------------------------------- /tools/framework/examples/.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | taimetadata.c 3 | taimetadata.h 4 | -------------------------------------------------------------------------------- /tools/framework/examples/basic/Makefile: -------------------------------------------------------------------------------- 1 | TAI_DIR ?= ../../../.. 2 | TAI_FRAMEWORK_PLATFORM_HEADER ?= basic.hpp 3 | TAI_PROG ?= libtai-basic.so 4 | TAI_META_CUSTOM_FILES ?= $(abspath $(wildcard custom/* )) 5 | 6 | include ../../make/lib.mk 7 | -------------------------------------------------------------------------------- /tools/framework/examples/basic/basic.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __BASIC_HPP__ 2 | #define __BASIC_HPP__ 3 | 4 | #include "platform.hpp" 5 | #include 6 | 7 | namespace tai::basic { 8 | 9 | using namespace tai::framework; 10 | 11 | const uint8_t BASIC_NUM_MODULE = 8; 12 | const uint8_t BASIC_NUM_NETIF = 1; 13 | const uint8_t BASIC_NUM_HOSTIF = 2; 14 | 15 | // the same object ID format as examples/stub is used 16 | const uint8_t OBJECT_TYPE_SHIFT = 48; 17 | 18 | class Platform : public tai::framework::Platform { 19 | public: 20 | Platform(const tai_service_method_table_t * services); 21 | ~Platform(); 22 | tai_status_t create(tai_object_type_t type, tai_object_id_t module_id, uint32_t attr_count, const tai_attribute_t * const attr_list, tai_object_id_t *id); 23 | tai_status_t remove(tai_object_id_t id); 24 | tai_object_type_t get_object_type(tai_object_id_t id); 25 | tai_object_id_t get_module_id(tai_object_id_t id); 26 | }; 27 | 28 | class Module; 29 | class NetIf; 30 | class HostIf; 31 | 32 | using S_Module = std::shared_ptr; 33 | using S_NetIf = std::shared_ptr; 34 | using S_HostIf = std::shared_ptr; 35 | 36 | // The FSM for state handling of the hardware 37 | // 38 | // It is not mandatory to implement FSM to use the TAI library framework. 39 | // You can see that examples/stub doesn't implement it. 40 | // 41 | // The TAI library framework defines 4 FSM states, INIT, WAITING_CONFIGURATION, READY and END. 42 | // The FSM starts with INIT and stops when it reaches to END 43 | // The TAI library framework doesn't have any assumption on how to transit between these states. 44 | // 45 | // You need to implement FSM::cb(FSMState state) which returns fsm_callback for handling every states other than END. 46 | // ( If FSM::cb(FSMState state) returns nullptr, the state goes to END ) 47 | // The callback returns the next state which the FSM transit. 48 | // 49 | // When the framework want to transit to another state (described in basic.cpp when this happens), 50 | // the framework triggers an event. This event can be captured through eventfd. 51 | // `int tai::framework::FSM::get_event_fd()` returns the event fd and `FSMState tai::framework::FSM::next_state()` returns 52 | // the next state which the framework is requesting to transit. 53 | // 54 | // In typical case, the callback respects what the framework is requesting, and return the next state promptly. 55 | // 56 | // If needed, you can define additional states and implement fsm_callbacks for them. 57 | // 58 | // You can implement FSM::state_change_cb() which returns fsm_state_change_callback. 59 | // This callback will get called everytime when the FSM state changes. 60 | // 61 | // In this example, a FSM is created per module and shared among module and its netif/hostif. 62 | // A FSM is fed to a constructor of Object. 63 | // 64 | // set_module/set_netif/set_hostif are implemented to enable the access to TAI objects from FSM 65 | // it is not mandatory and required by the framework, but you will find it necessary most of the time to do meaningful stuff 66 | class FSM : public tai::framework::FSM { 67 | // requirements to inherit tai::FSM 68 | public: 69 | bool configured(); 70 | private: 71 | fsm_state_change_callback state_change_cb(); 72 | fsm_callback cb(FSMState state); 73 | 74 | // methods/fields specific to this example 75 | public: 76 | FSM(Location loc) : m_loc(loc), m_module(nullptr), m_netif(nullptr), m_hostif{}, m_no_transit(false) {} 77 | int set_module(S_Module module); 78 | int set_netif(S_NetIf netif); 79 | int set_hostif(S_HostIf hostif, int index); 80 | 81 | tai_status_t remove_module(); 82 | tai_status_t remove_netif(); 83 | tai_status_t remove_hostif(int index); 84 | 85 | tai_status_t set_tx_dis(const tai_attribute_t* const attribute); 86 | tai_status_t get_tx_dis(tai_attribute_t* const attribute); 87 | 88 | tai_status_t get_tributary_mapping(tai_attribute_t* const attribute); 89 | 90 | Location location() { 91 | return m_loc; 92 | } 93 | 94 | private: 95 | FSMState _state_change_cb(FSMState current, FSMState next, void* user); 96 | 97 | FSMState _init_cb(FSMState current, void* user); 98 | FSMState _waiting_configuration_cb(FSMState current, void* user); 99 | FSMState _ready_cb(FSMState current, void* user); 100 | 101 | Location m_loc; 102 | S_Module m_module; 103 | S_NetIf m_netif; 104 | S_HostIf m_hostif[BASIC_NUM_HOSTIF]; 105 | std::atomic m_no_transit; 106 | }; 107 | 108 | using S_FSM = std::shared_ptr; 109 | 110 | template 111 | class Object : public tai::framework::Object { 112 | public: 113 | Object(uint32_t count, const tai_attribute_t *list, S_FSM fsm) : tai::framework::Object(count, list, fsm, reinterpret_cast(fsm.get()), 114 | std::bind(&Object::default_setter, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), 115 | std::bind(&Object::default_getter, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), 116 | std::bind(&Object::default_cap_getter, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)) {} 117 | 118 | tai_object_id_t id() const { 119 | return m_id; 120 | } 121 | 122 | protected: 123 | tai_object_id_t m_id; 124 | 125 | private: 126 | tai_status_t default_setter(uint32_t count, const tai_attribute_t* const attrs, FSMState* fsm, void* const user, const tai::framework::error_info* const info) { 127 | for ( auto i = 0; i < static_cast(count); i++ ) { 128 | auto attribute = &attrs[i]; 129 | auto meta = tai_metadata_get_attr_metadata(T, attribute->id); 130 | if ( meta == nullptr ) { 131 | TAI_ERROR("no metadata for attribute 0x%x", attribute->id); 132 | return info[i].status; 133 | } 134 | auto ret = tai::framework::Object::config().direct_set(std::make_shared(meta, *attribute)); 135 | if ( ret != TAI_STATUS_SUCCESS ) { 136 | return convert_tai_error_to_list(ret, info[i].index); 137 | } 138 | } 139 | return TAI_STATUS_SUCCESS; 140 | } 141 | 142 | tai_status_t default_getter(uint32_t count, tai_attribute_t* const attrs, void* const user, const tai::framework::error_info* const info) { 143 | for ( auto i = 0; i< static_cast(count); i++ ) { 144 | auto attribute = &attrs[i]; 145 | auto meta = tai_metadata_get_attr_metadata(T, attribute->id); 146 | auto value = tai::framework::Object::config().direct_get(attribute->id); 147 | if ( value != nullptr ) { 148 | tai_attribute_t in = {attribute->id, *value}; 149 | auto ret = tai_metadata_deepcopy_attr_value(meta, &in, attribute); 150 | if ( ret != TAI_STATUS_SUCCESS ) { 151 | return info[i].status; 152 | } 153 | } else if ( meta == nullptr || meta->isreadonly ) { 154 | return info[i].status; 155 | } else if ( meta->defaultvalue != NULL ) { 156 | tai_attribute_t in = {attribute->id, *meta->defaultvalue}; 157 | auto ret = tai_metadata_deepcopy_attr_value(meta, &in, attribute); 158 | if ( ret != TAI_STATUS_SUCCESS ) { 159 | return convert_tai_error_to_list(ret, info[i].index); 160 | } 161 | } else { 162 | return TAI_STATUS_UNINITIALIZED; 163 | } 164 | } 165 | return TAI_STATUS_SUCCESS; 166 | } 167 | 168 | tai_status_t default_cap_getter(uint32_t count, tai_attribute_capability_t* const caps, void* const user, const tai::framework::error_info* const info) { 169 | for ( auto i = 0; i< static_cast(count); i++ ) { 170 | auto cap = &caps[i]; 171 | auto meta = tai_metadata_get_attr_metadata(T, cap->id); 172 | if ( meta == nullptr ) { 173 | return convert_tai_error_to_list(TAI_STATUS_ATTR_NOT_SUPPORTED_0, info[i].index); 174 | } 175 | if ( meta->defaultvalue != nullptr ) { 176 | cap->defaultvalue = *meta->defaultvalue; 177 | } 178 | } 179 | return TAI_STATUS_SUCCESS; 180 | } 181 | }; 182 | 183 | class Module : public Object { 184 | public: 185 | // 4th argument to the Object constructor is a user context which is passed in getter()/setter() callbacks 186 | // getter()/setter() callbacks is explained in basic.hpp 187 | Module(uint32_t count, const tai_attribute_t *list, S_FSM fsm) : Object(count, list, fsm), m_fsm(fsm) { 188 | std::string loc; 189 | for ( auto i = 0; i < static_cast(count); i++ ) { 190 | if ( list[i].id == TAI_MODULE_ATTR_LOCATION ) { 191 | loc = std::string(list[i].value.charlist.list, list[i].value.charlist.count); 192 | break; 193 | } 194 | } 195 | if ( loc == "" ) { 196 | throw Exception(TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING); 197 | } 198 | auto i = std::stoi(loc); 199 | m_id = static_cast(uint64_t(TAI_OBJECT_TYPE_MODULE) << OBJECT_TYPE_SHIFT | i); 200 | if ( i >= BASIC_NUM_MODULE ) { 201 | throw Exception(TAI_STATUS_INVALID_PARAMETER); 202 | } 203 | } 204 | 205 | S_FSM fsm() { 206 | return m_fsm; 207 | } 208 | private: 209 | S_FSM m_fsm; 210 | }; 211 | 212 | 213 | class NetIf : public Object { 214 | public: 215 | NetIf(S_Module module, uint32_t count, const tai_attribute_t *list) : Object(count, list, module->fsm()) { 216 | int index = -1; 217 | for ( auto i = 0; i < static_cast(count); i++ ) { 218 | if ( list[i].id == TAI_NETWORK_INTERFACE_ATTR_INDEX ) { 219 | index = list[i].value.u32; 220 | break; 221 | } 222 | } 223 | if ( index < 0 ) { 224 | throw Exception(TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING); 225 | } 226 | if ( index >= BASIC_NUM_NETIF ) { 227 | throw Exception(TAI_STATUS_INVALID_PARAMETER); 228 | } 229 | m_id = static_cast(uint64_t(TAI_OBJECT_TYPE_NETWORKIF) << OBJECT_TYPE_SHIFT | (module->id() & 0xff) << 8 | index); 230 | } 231 | }; 232 | 233 | class HostIf : public Object { 234 | public: 235 | HostIf(S_Module module, uint32_t count, const tai_attribute_t *list) : Object(count, list, module->fsm()) { 236 | int index = -1; 237 | for ( auto i = 0; i < static_cast(count); i++ ) { 238 | if ( list[i].id == TAI_HOST_INTERFACE_ATTR_INDEX ) { 239 | index = list[i].value.u32; 240 | break; 241 | } 242 | } 243 | if ( index < 0 ) { 244 | throw Exception(TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING); 245 | } 246 | if ( index >= BASIC_NUM_HOSTIF ) { 247 | throw Exception(TAI_STATUS_INVALID_PARAMETER); 248 | } 249 | m_id = static_cast(uint64_t(TAI_OBJECT_TYPE_HOSTIF) << OBJECT_TYPE_SHIFT | (module->id() & 0xff) << 8 | index); 250 | } 251 | }; 252 | 253 | }; 254 | 255 | #ifdef TAI_EXPOSE_PLATFORM 256 | using tai::basic::Platform; 257 | #endif 258 | 259 | #endif // __BASIC_HPP__ 260 | -------------------------------------------------------------------------------- /tools/framework/examples/basic/custom/module.h: -------------------------------------------------------------------------------- 1 | #ifndef __TAI_BASIC_MODULE__ 2 | #define __TAI_BASIC_MODULE__ 3 | 4 | #include 5 | 6 | typedef enum _basic_module_attr_t 7 | { 8 | /** 9 | * @brief Custom attribute example 10 | * 11 | * @type bool 12 | * @flags CREATE_AND_SET 13 | */ 14 | TAI_MODULE_ATTR_CUSTOM = TAI_MODULE_ATTR_CUSTOM_RANGE_START, 15 | 16 | /** 17 | * @brief Custom list attribute example 18 | * 19 | * @type tai_u32_list_t 20 | * @flags CREATE_AND_SET 21 | */ 22 | TAI_MODULE_ATTR_CUSTOM_LIST, 23 | 24 | 25 | } basic_module_attr_t; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /tools/framework/examples/basic/custom/netif.h: -------------------------------------------------------------------------------- 1 | #ifndef __TAI_BASIC_NETIF__ 2 | #define __TAI_BASIC_NETIF__ 3 | 4 | #include 5 | 6 | /** 7 | * @custom tai_network_interface_fec_type_t 8 | */ 9 | typedef enum _tai_custom_fec_type_t 10 | { 11 | TAI_NETWORK_INTERFACE_FEC_TYPE_PROPRIETARY = 10, 12 | } tai_custom_fec_type_t; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /tools/framework/examples/stub/Makefile: -------------------------------------------------------------------------------- 1 | TAI_DIR ?= ../../../../ 2 | TAI_FRAMEWORK_PLATFORM_HEADER ?= stub.hpp 3 | TAI_PROG ?= libtai-stub.so 4 | 5 | include ../../make/lib.mk 6 | -------------------------------------------------------------------------------- /tools/framework/examples/stub/stub.cpp: -------------------------------------------------------------------------------- 1 | #include "stub.hpp" 2 | #include "logger.hpp" 3 | 4 | namespace tai::stub { 5 | 6 | // Platform constructor 7 | // 8 | // In this example, we call module_presence blindly with the presence flag 'true' 9 | // when the callback is given. 10 | Platform::Platform(const tai_service_method_table_t * services) : tai::framework::Platform(services) { 11 | 12 | if ( services != nullptr && services->module_presence != nullptr ) { 13 | for ( auto i = 0; i < STUB_NUM_MODULE; i++ ) { 14 | services->module_presence(true, const_cast(std::to_string(i).c_str())); 15 | } 16 | } 17 | } 18 | 19 | tai_status_t Platform::create(tai_object_type_t type, tai_object_id_t module_id, uint32_t attr_count, const tai_attribute_t *attr_list, tai_object_id_t *id) { 20 | std::shared_ptr obj; 21 | try { 22 | switch (type) { 23 | case TAI_OBJECT_TYPE_MODULE: 24 | obj = std::make_shared(attr_count, attr_list); 25 | break; 26 | case TAI_OBJECT_TYPE_NETWORKIF: 27 | { 28 | auto t = get_object_type(module_id); 29 | if ( t != TAI_OBJECT_TYPE_MODULE ) { 30 | return TAI_STATUS_UNINITIALIZED; 31 | } 32 | obj = std::make_shared(module_id, attr_count, attr_list); 33 | } 34 | break; 35 | case TAI_OBJECT_TYPE_HOSTIF: 36 | { 37 | auto t = get_object_type(module_id); 38 | if ( t != TAI_OBJECT_TYPE_MODULE ) { 39 | return TAI_STATUS_UNINITIALIZED; 40 | } 41 | obj = std::make_shared(module_id, attr_count, attr_list); 42 | } 43 | break; 44 | default: 45 | return TAI_STATUS_NOT_SUPPORTED; 46 | } 47 | } catch (tai_status_t e) { 48 | return e; 49 | } 50 | 51 | auto oid = obj->id(); 52 | auto it = m_objects.find(oid); 53 | if ( it != m_objects.end() ) { 54 | return TAI_STATUS_ITEM_ALREADY_EXISTS; 55 | } 56 | m_objects[oid] = obj; 57 | *id = oid; 58 | return TAI_STATUS_SUCCESS; 59 | } 60 | 61 | tai_object_type_t Platform::get_object_type(tai_object_id_t id) { 62 | auto it = m_objects.find(id); 63 | if ( it == m_objects.end() ) { 64 | return TAI_OBJECT_TYPE_NULL; 65 | } 66 | auto type = static_cast(id >> OBJECT_TYPE_SHIFT); 67 | switch (type) { 68 | case TAI_OBJECT_TYPE_MODULE: 69 | case TAI_OBJECT_TYPE_NETWORKIF: 70 | case TAI_OBJECT_TYPE_HOSTIF: 71 | return type; 72 | default: 73 | return TAI_OBJECT_TYPE_NULL; 74 | } 75 | } 76 | 77 | tai_object_id_t Platform::get_module_id(tai_object_id_t id) { 78 | auto it = m_objects.find(id); 79 | if ( it == m_objects.end() ) { 80 | return TAI_NULL_OBJECT_ID; 81 | } 82 | auto type = static_cast(id >> OBJECT_TYPE_SHIFT); 83 | switch (type) { 84 | case TAI_OBJECT_TYPE_MODULE: 85 | return id; 86 | case TAI_OBJECT_TYPE_NETWORKIF: 87 | case TAI_OBJECT_TYPE_HOSTIF: 88 | { 89 | auto idx = ((id >> 8) & 0xff); 90 | auto module_id = static_cast(uint64_t(TAI_OBJECT_TYPE_MODULE) << OBJECT_TYPE_SHIFT | idx); 91 | auto it = m_objects.find(module_id); 92 | if ( it == m_objects.end() ) { 93 | return TAI_NULL_OBJECT_ID; 94 | } 95 | return module_id; 96 | } 97 | default: 98 | return TAI_OBJECT_TYPE_NULL; 99 | } 100 | } 101 | 102 | // List all attributes which is supported by the library in tai::framework::Config::m_info 103 | // 104 | // If an attribute is not listed in m_info, the framework returns NOT_SUPPORTED err 105 | // when user tries to get/set the attribute. 106 | // 107 | // The simplest way to create an item in the list is to use AttributeInfo(tai_attribute_id_t id). 108 | // With this, the framework will provide basic functionality for getting/setting (if the attribute is not READ_ONLY ) 109 | // the attribute. 110 | // Once it set, it gets stored in memory and the same value can be retrieved by get(). 111 | // 112 | // AttributeInfo has several methods to add more control over how the attribute get handled. 113 | // In this example set_default() and set_validator() are used. 114 | // 115 | // - AttributeInfo::set_default 116 | // sets the default value. It overrides the default value specified in TAI header by @default 117 | // 118 | // - AttributeInfo::set_validator 119 | // sets the validator. It is called before setting the value. 120 | // In this example, it is used to prohibit setting TAI_MODULE_ADMIN_STATUS_UNKNOWN and TAI_MODULE_ADMIN_STATUS_MAX 121 | // 122 | // see examples/basic for more advanced methods 123 | 124 | static const tai_attribute_value_t default_tai_module_vendor_name_value = { 125 | .charlist = {4, (char*)"STUB"}, 126 | }; 127 | 128 | static const tai_attribute_value_t default_tai_module_num_network_interfaces = { 129 | .u32 = STUB_NUM_NETIF, 130 | }; 131 | 132 | static const tai_attribute_value_t default_tai_module_num_host_interfaces = { 133 | .u32 = STUB_NUM_HOSTIF, 134 | }; 135 | 136 | using M = AttributeInfo; 137 | using N = AttributeInfo; 138 | using H = AttributeInfo; 139 | 140 | // sadly 'auto' can't be used here 141 | template <> const AttributeInfoMap Config::m_info { 142 | stub::M(TAI_MODULE_ATTR_LOCATION), 143 | stub::M(TAI_MODULE_ATTR_VENDOR_NAME) 144 | .set_default(&tai::stub::default_tai_module_vendor_name_value), 145 | stub::M(TAI_MODULE_ATTR_NUM_NETWORK_INTERFACES) 146 | .set_default(&tai::stub::default_tai_module_num_network_interfaces), 147 | stub::M(TAI_MODULE_ATTR_NUM_HOST_INTERFACES) 148 | .set_default(&tai::stub::default_tai_module_num_host_interfaces), 149 | stub::M(TAI_MODULE_ATTR_ADMIN_STATUS) 150 | .set_validator(EnumValidator({TAI_MODULE_ADMIN_STATUS_DOWN, TAI_MODULE_ADMIN_STATUS_UP})), 151 | stub::M(TAI_MODULE_ATTR_MODULE_SHUTDOWN_REQUEST_NOTIFY), 152 | stub::M(TAI_MODULE_ATTR_MODULE_STATE_CHANGE_NOTIFY), 153 | }; 154 | 155 | template <> const AttributeInfoMap Config::m_info { 156 | stub::N(TAI_NETWORK_INTERFACE_ATTR_INDEX), 157 | stub::N(TAI_NETWORK_INTERFACE_ATTR_TX_DIS), 158 | stub::N(TAI_NETWORK_INTERFACE_ATTR_TX_LASER_FREQ), 159 | stub::N(TAI_NETWORK_INTERFACE_ATTR_OUTPUT_POWER), 160 | }; 161 | 162 | template <> const AttributeInfoMap Config::m_info { 163 | stub::H(TAI_HOST_INTERFACE_ATTR_INDEX), 164 | }; 165 | } 166 | -------------------------------------------------------------------------------- /tools/framework/examples/stub/stub.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __STUB_HPP__ 2 | #define __STUB_HPP__ 3 | 4 | #include "platform.hpp" 5 | 6 | namespace tai::stub { 7 | 8 | using namespace tai::framework; 9 | 10 | // Total number of modules 11 | const uint8_t STUB_NUM_MODULE = 4; 12 | // The number of network interface which one module has 13 | const uint8_t STUB_NUM_NETIF = 1; 14 | // The number of host interface which one module has 15 | const uint8_t STUB_NUM_HOSTIF = 2; 16 | 17 | /* 18 | The TAI library framwork doesn't specify how to assign an object ID to 19 | TAI objects. You can decide how to assign it. 20 | 21 | In this example, we use the following format 22 | 23 | # Object ID for module 24 | 16 48 ( = OBJECT_TYPE_SHIFT ) 25 | ◀──────────────▶ ◀─────────────────────────────────────────────▶ 26 | ┌───────────────┬──────────────────────────────────────────────┐ 27 | │ Object │ Module location converted to int │ 28 | │ Type │ │ 29 | └───────────────┴──────────────────────────────────────────────┘ 30 | 31 | # Object id for netif/hostif 32 | 16 32 16 33 | ◀──────────────▶◀─────────────────────────────▶◀───────────────▶ 34 | ┌───────────────┬──────────────────────────────┬───────────────┐ 35 | │ Object │ Module location converted to │ Index │ 36 | │ Type │ int │ │ 37 | └───────────────┴──────────────────────────────┴───────────────┘ 38 | 39 | Module location will be retrieved from TAI_MODULE_ATTR_LOCATION 40 | The valid value for the attribute is '1', '2', '3' and '4' ( STUB_NUM_MODULE = 4 ) 41 | 42 | Index will be retrieved from TAI_NETWORK_INTERFACE_ATTR_INDEX/TAI_HOST_INTERFACE_ATTR_INDEX 43 | The valid value for the attribute is 0 for netif and 0 and 1 for hostif 44 | ( STUB_NUM_NETIF = 1, STUB_NUM_HOSTIF = 2 ) 45 | */ 46 | const uint8_t OBJECT_TYPE_SHIFT = 48; 47 | 48 | // Platform must be implemented to use the TAI library framework. 49 | // It is a singleton in the library and will get created by tai_api_initialize() 50 | // and destroyed by tai_api_uninitialize() 51 | // 52 | // tai::framework::Platform requires 4 virtual methods create, remove, get_object_type and 53 | // get_module_id to be implemented. 54 | class Platform : public tai::framework::Platform { 55 | public: 56 | Platform(const tai_service_method_table_t * services); 57 | tai_status_t create(tai_object_type_t type, tai_object_id_t module_id, uint32_t attr_count, const tai_attribute_t * const attr_list, tai_object_id_t *id); 58 | tai_status_t remove(tai_object_id_t id) { 59 | return TAI_STATUS_NOT_SUPPORTED; 60 | } 61 | tai_object_type_t get_object_type(tai_object_id_t id); 62 | tai_object_id_t get_module_id(tai_object_id_t id); 63 | }; 64 | 65 | // Define TAI objects which will be created in Platform::create() 66 | // tai::framework::Object requires to implement id() which returns the object ID 67 | // 68 | // In this example, we store it in 'm_id' by following the format mentioned above. 69 | 70 | class Module : public tai::framework::Object { 71 | public: 72 | Module(uint32_t count, const tai_attribute_t *list) : Object(count, list) { 73 | std::string loc; 74 | for ( auto i = 0; i < static_cast(count); i++ ) { 75 | if ( list[i].id == TAI_MODULE_ATTR_LOCATION ) { 76 | loc = std::string(list[i].value.charlist.list, list[i].value.charlist.count); 77 | break; 78 | } 79 | } 80 | if ( loc == "" ) { 81 | throw Exception(TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING); 82 | } 83 | auto i = std::stoi(loc); 84 | m_id = static_cast(uint64_t(TAI_OBJECT_TYPE_MODULE) << OBJECT_TYPE_SHIFT | i); 85 | } 86 | tai_object_id_t id() const { 87 | return m_id; 88 | } 89 | private: 90 | tai_object_id_t m_id; 91 | }; 92 | 93 | class NetIf : public tai::framework::Object { 94 | public: 95 | NetIf(tai_object_id_t module_id, uint32_t count, const tai_attribute_t *list) : Object(count, list) { 96 | int index = -1; 97 | for ( auto i = 0; i < static_cast(count); i++ ) { 98 | if ( list[i].id == TAI_NETWORK_INTERFACE_ATTR_INDEX ) { 99 | index = list[i].value.u32; 100 | break; 101 | } 102 | } 103 | if ( index < 0 ) { 104 | throw Exception(TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING); 105 | } 106 | m_id = static_cast(uint64_t(TAI_OBJECT_TYPE_NETWORKIF) << OBJECT_TYPE_SHIFT | (module_id & 0xff) << 8 | index); 107 | } 108 | tai_object_id_t id() const { 109 | return m_id; 110 | } 111 | private: 112 | tai_object_id_t m_id; 113 | }; 114 | 115 | class HostIf : public tai::framework::Object { 116 | public: 117 | HostIf(tai_object_id_t module_id, uint32_t count, const tai_attribute_t *list) : Object(count, list) { 118 | int index = -1; 119 | for ( auto i = 0; i < static_cast(count); i++ ) { 120 | if ( list[i].id == TAI_HOST_INTERFACE_ATTR_INDEX ) { 121 | index = list[i].value.u32; 122 | break; 123 | } 124 | } 125 | if ( index < 0 ) { 126 | throw Exception(TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING); 127 | } 128 | m_id = static_cast(uint64_t(TAI_OBJECT_TYPE_HOSTIF) << OBJECT_TYPE_SHIFT | (module_id & 0xff) << 8 | index); 129 | } 130 | tai_object_id_t id() const { 131 | return m_id; 132 | } 133 | private: 134 | tai_object_id_t m_id; 135 | }; 136 | 137 | }; 138 | 139 | #ifdef TAI_EXPOSE_PLATFORM 140 | using tai::stub::Platform; 141 | #endif 142 | 143 | #endif // __STUB_HPP__ 144 | -------------------------------------------------------------------------------- /tools/framework/fsm.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __TAI_FRAMEWORK_FSM_HPP__ 2 | #define __TAI_FRAMEWORK_FSM_HPP__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace tai::framework { 13 | 14 | using FSMState = int; 15 | 16 | const auto FSM_STATE_INIT = FSMState(0); 17 | const auto FSM_STATE_WAITING_CONFIGURATION = FSMState(100); 18 | const auto FSM_STATE_READY = FSMState(200); 19 | const auto FSM_STATE_END = FSMState(300); 20 | 21 | using fsm_callback = std::function; 22 | using fsm_state_change_callback = std::function; 23 | 24 | class FSM; 25 | 26 | using S_FSM = std::shared_ptr; 27 | 28 | class FSM { 29 | public: 30 | FSM() : m_event_fd(0), m_current_state(FSM_STATE_INIT) {} 31 | ~FSM() { 32 | shutdown(); 33 | } 34 | int start() { 35 | if ( m_event_fd != 0 ) { 36 | return -1; 37 | } 38 | m_event_fd = eventfd(0, EFD_SEMAPHORE); 39 | if ( m_event_fd < 0 ) { 40 | return -1; 41 | } 42 | m_th = std::thread(&FSM::loop, this); 43 | return 0; 44 | } 45 | 46 | // configured() returns if the FSM state can go beyond WAITING_CONFIGURATION 47 | // when it's returning 'false', set_attribute()/clear_attribute() won't 48 | // move the FSM state beyond WAITING_CONFIGURATION 49 | // typically configured() should check if module and netif are created 50 | // and module's admin status is 'up' 51 | virtual bool configured() { return true; }; 52 | 53 | int shutdown() { 54 | if ( m_event_fd == 0 ) { 55 | return 0; 56 | } 57 | transit(FSM_STATE_END); 58 | m_th.join(); 59 | close(m_event_fd); 60 | m_event_fd = 0; 61 | m_current_state = FSM_STATE_INIT; 62 | return 0; 63 | } 64 | 65 | int loop() { 66 | while (true) { 67 | auto f = cb(m_current_state); 68 | auto next = FSM_STATE_END; 69 | if ( f != nullptr ) { 70 | next = f(m_current_state, this); 71 | } 72 | 73 | m_next_state = next; 74 | 75 | auto s_cb = state_change_cb(); 76 | if ( s_cb != nullptr ) { 77 | m_next_state = s_cb(m_current_state, m_next_state, this); 78 | } 79 | 80 | m_prev_state = m_current_state; 81 | m_current_state = m_next_state; 82 | 83 | if ( next == FSM_STATE_END ) { 84 | break; 85 | } 86 | 87 | } 88 | return 0; 89 | } 90 | 91 | int transit(FSMState state) { 92 | std::unique_lock m(m_queue_mutex); 93 | if (m_queue.size() > 0 && m_queue.back() == state) { 94 | return 0; 95 | } 96 | m_queue.push(state); 97 | if ( m_event_fd > 0 ) { 98 | uint64_t v = 1; 99 | return write(m_event_fd, &v, sizeof(uint64_t)); 100 | } 101 | return 0; 102 | } 103 | 104 | int get_event_fd() { 105 | return m_event_fd; 106 | } 107 | 108 | FSMState get_state() { 109 | return m_current_state; 110 | } 111 | 112 | FSMState next_state() { 113 | std::unique_lock m(m_queue_mutex); 114 | if ( m_queue.empty() ) { 115 | return get_state(); 116 | } 117 | auto state = m_queue.front(); 118 | m_queue.pop(); 119 | return state; 120 | } 121 | 122 | FSMState prev_state() { 123 | return m_prev_state; 124 | } 125 | 126 | private: 127 | virtual fsm_callback cb(FSMState state) { return nullptr; } 128 | virtual fsm_state_change_callback state_change_cb() { return nullptr; } 129 | 130 | int m_event_fd; 131 | FSMState m_current_state, m_next_state, m_prev_state; 132 | std::mutex m_queue_mutex; 133 | std::queue m_queue; 134 | std::thread m_th; 135 | }; 136 | } 137 | 138 | #endif // __TAI_FRAMEWORK_FSM_HPP__ 139 | -------------------------------------------------------------------------------- /tools/framework/make/lib.mk: -------------------------------------------------------------------------------- 1 | TAI_PROG ?= libtai.so 2 | 3 | ifndef TAI_DIR 4 | $(error $TAI_DIR not defined) 5 | endif 6 | 7 | ifndef TAI_FRAMEWORK_PLATFORM_HEADER 8 | $(error $TAI_FRAMEWORK_PLATFORM_HEADER not defined) 9 | endif 10 | 11 | TAI_FRAMEWORK_DIR ?= $(TAI_DIR)/tools/framework 12 | TAI_LIB_DIR ?= $(TAI_DIR)/tools/lib 13 | 14 | TAI_META_OUT_DIR ?= $(abspath .) 15 | 16 | SRCS ?= $(wildcard *.cpp $(TAI_LIB_DIR)/*.cpp $(TAI_FRAMEWORK_DIR)/*.cpp) $(sort $(addprefix $(TAI_META_OUT_DIR)/,$(notdir $(wildcard $(TAI_DIR)/meta/*.c)) taimetadata.c)) $(VENDOR_SRC) 17 | HEADERS ?= $(wildcard *.hpp $(TAI_LIB_DIR)/*.hpp $(TAI_FRAMEWORK_DIR)/*.hpp) $(sort $(addprefix $(TAI_META_OUT_DIR)/,$(notdir $(wildcard $(TAI_DIR)/meta/*.h)) taimetadata.h)) $(TAI_META_CUSTOM_FILES) $(VENDOR_HEADERS) 18 | OBJS = $(addsuffix .o,$(basename $(SRCS))) 19 | 20 | INCLUDE ?= $(VENDOR_INCLUDE) -I $(TAI_META_OUT_DIR) -I $(TAI_DIR)/inc -I $(TAI_DIR)/meta -I $(TAI_LIB_DIR) -I $(TAI_FRAMEWORK_DIR) 21 | 22 | CFLAGS ?= $(VENDOR_CFLAGS) -DTAI_EXPOSE_PLATFORM -fPIC $(INCLUDE) -Wall -Werror 23 | # -fno-gnu-unique 24 | # tai::Logger::get_instance() is an inline method of Logger and it returns a static Logger. 25 | # when the library is used under tai-mux which uses dlopen(), we want to make the logger per library not globally unique 26 | # hence we need -fno-gnu-unique option 27 | # ref) https://stackoverflow.com/questions/38510621/destructor-of-a-global-static-variable-in-a-shared-library-is-not-called-on-dlcl 28 | # 29 | # Alternative solution is to make tai::Logger::get_instance() non-inline ( implement it in a cpp file ) 30 | CFLAGS += -fno-gnu-unique 31 | 32 | ifdef DEBUG 33 | CFLAGS += -g3 34 | endif 35 | 36 | CXXFLAGS ?= $(VENDOR_CXXFLAGS) $(CFLAGS) -std=c++17 -include $(TAI_FRAMEWORK_PLATFORM_HEADER) 37 | 38 | LDFLAGS ?= $(VENDOR_LDFLAGS) -shared -lpthread 39 | 40 | $(TAI_PROG): meta $(OBJS) $(HEADERS) Makefile 41 | $(CXX) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) 42 | if [ $(TAI_PROG) != libtai.so ]; then ln -sf $(TAI_PROG) libtai.so; fi 43 | 44 | meta: 45 | $(MAKE) -C $(TAI_DIR)/meta TAI_META_CUSTOM_FILES="$(TAI_META_CUSTOM_FILES)" TAI_META_OUT_DIR=$(TAI_META_OUT_DIR) 46 | 47 | clean: 48 | $(RM) $(TAI_PROG) $(OBJS) libtai.so 49 | $(MAKE) -C $(TAI_DIR)/meta clean TAI_META_OUT_DIR=$(TAI_META_OUT_DIR) 50 | -------------------------------------------------------------------------------- /tools/framework/object.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __TAI_FRAMEWORK_OBJECT_HPP__ 2 | #define __TAI_FRAMEWORK_OBJECT_HPP__ 3 | 4 | #include 5 | #include "config.hpp" 6 | 7 | namespace tai::framework { 8 | 9 | class BaseObject { 10 | public: 11 | virtual tai_object_type_t type() const = 0; 12 | virtual tai_object_id_t id() const = 0; 13 | virtual tai_status_t get_attributes(uint32_t attr_count, tai_attribute_t* const attr_list) = 0; 14 | virtual tai_status_t set_attributes(uint32_t attr_count, const tai_attribute_t* const attr_list) = 0; 15 | virtual tai_status_t clear_attributes(uint32_t attr_count, const tai_attr_id_t* const attr_id_list) = 0; 16 | virtual tai_status_t get_capabilities(uint32_t count, tai_attribute_capability_t* const list) = 0; 17 | }; 18 | 19 | using S_BaseObject = std::shared_ptr; 20 | 21 | enum transit_cond_context { TRANSIT_COND_CONTEXT_SET, TRANSIT_COND_CONTEXT_CLEAR }; 22 | 23 | using transit_cond_fn = std::function; 24 | 25 | template 26 | class Object : public BaseObject { 27 | public: 28 | Object(uint32_t attr_count = 0 , const tai_attribute_t* const attr_list = nullptr, S_FSM fsm = std::make_shared(), void* user = nullptr, default_setter_f setter = nullptr, default_getter_f getter = nullptr, default_cap_getter_f cap_getter = nullptr) : m_fsm(fsm), m_config(attr_count, attr_list, user, setter, getter, cap_getter) {} 29 | 30 | bool configured() { 31 | return m_fsm->configured(); 32 | } 33 | 34 | tai_object_type_t type() const { return T; } 35 | tai_status_t get_attributes(uint32_t attr_count, tai_attribute_t* const attr_list); 36 | tai_status_t set_attributes(uint32_t attr_count, const tai_attribute_t* const attr_list); 37 | tai_status_t clear_attributes(uint32_t attr_count, const tai_attr_id_t* const attr_id_list); 38 | tai_status_t get_capabilities(uint32_t count, tai_attribute_capability_t* const list); 39 | 40 | tai_status_t notify(tai_attr_id_t notification_id, const std::vector& ids, bool alarm = false); 41 | tai_status_t notify_alarm(tai_attr_id_t notification_id, const std::vector& ids); 42 | 43 | int clear_alarm_cache() { 44 | return m_alarm_cache.clear_all(); 45 | } 46 | 47 | Config& config() { 48 | return m_config; 49 | } 50 | 51 | protected: 52 | S_FSM fsm() { 53 | return m_fsm; 54 | } 55 | 56 | void set_transit_cond(transit_cond_fn f) { 57 | m_transit_cond = f; 58 | } 59 | 60 | 61 | private: 62 | 63 | std::mutex m_mtx; 64 | 65 | S_FSM m_fsm; 66 | 67 | Config m_config; 68 | Config m_alarm_cache; 69 | 70 | transit_cond_fn m_transit_cond; 71 | 72 | tai_status_t _get_attributes(uint32_t attr_count, tai_attribute_t* const attr_list); 73 | tai_status_t _set_attributes(uint32_t attr_count, const tai_attribute_t* const attr_list); 74 | tai_status_t _clear_attributes(uint32_t attr_count, const tai_attr_id_t* const attr_list); 75 | tai_status_t _get_capabilities(uint32_t count, tai_attribute_capability_t* const list); 76 | 77 | tai_status_t _transit(FSMState next, transit_cond_context ctx); 78 | }; 79 | 80 | template 81 | tai_status_t Object::get_attributes(uint32_t attr_count, tai_attribute_t* const attr_list) { 82 | std::unique_lock lk(m_mtx); 83 | return _get_attributes(attr_count, attr_list); 84 | } 85 | 86 | template 87 | tai_status_t Object::_get_attributes(uint32_t attr_count, tai_attribute_t* const attr_list) { 88 | return m_config.get_attributes(attr_count, attr_list); 89 | } 90 | 91 | template 92 | tai_status_t Object::set_attributes(uint32_t attr_count, const tai_attribute_t* const attr_list) { 93 | std::unique_lock lk(m_mtx); 94 | return _set_attributes(attr_count, attr_list); 95 | } 96 | 97 | template 98 | tai_status_t Object::_set_attributes(uint32_t attr_count, const tai_attribute_t* const attr_list) { 99 | auto next_state = m_fsm->get_state(); 100 | auto ret = m_config.set_attributes(attr_count, attr_list, next_state); 101 | if ( ret != TAI_STATUS_SUCCESS ) { 102 | return ret; 103 | } 104 | return _transit(next_state, TRANSIT_COND_CONTEXT_SET); 105 | } 106 | 107 | template 108 | tai_status_t Object::clear_attributes(uint32_t attr_count, const tai_attr_id_t* const attr_id_list) { 109 | std::unique_lock lk(m_mtx); 110 | return _clear_attributes(attr_count, attr_id_list); 111 | } 112 | 113 | template 114 | tai_status_t Object::_clear_attributes(uint32_t attr_count, const tai_attr_id_t* const attr_id_list) { 115 | auto next_state = m_fsm->get_state(); 116 | auto ret = m_config.clear_attributes(attr_count, attr_id_list, next_state); 117 | if ( ret != TAI_STATUS_SUCCESS ) { 118 | return ret; 119 | } 120 | return _transit(next_state, TRANSIT_COND_CONTEXT_CLEAR); 121 | } 122 | 123 | template 124 | tai_status_t Object::get_capabilities(uint32_t count, tai_attribute_capability_t* const list) { 125 | std::unique_lock lk(m_mtx); 126 | return _get_capabilities(count, list); 127 | } 128 | 129 | template 130 | tai_status_t Object::_get_capabilities(uint32_t count, tai_attribute_capability_t* const list) { 131 | return m_config.get_capabilities(count, list); 132 | } 133 | 134 | template 135 | tai_status_t Object::_transit(FSMState next, transit_cond_context ctx) { 136 | if ( !m_transit_cond ) { // default transit behaviod 137 | auto max_state = FSM_STATE_READY; 138 | if ( !configured() ){ 139 | max_state = FSM_STATE_WAITING_CONFIGURATION; 140 | } 141 | if ( max_state < next ) { 142 | next = max_state; 143 | } 144 | if ( m_fsm->get_state() != next ) { 145 | m_fsm->transit(next); 146 | } 147 | } else if ( m_transit_cond(&next, ctx) ) { // call custom transit callback 148 | m_fsm->transit(next); 149 | } 150 | return TAI_STATUS_SUCCESS; 151 | } 152 | 153 | template 154 | tai_status_t Object::notify(tai_attr_id_t notification_id, const std::vector& ids, bool alarm) { 155 | std::unique_lock lk(m_mtx); 156 | std::vector alarm_ids; 157 | std::vector attrs; 158 | std::vector ptrs; 159 | auto a = m_config.get(notification_id); 160 | tai_notification_handler_t n; 161 | if ( a == nullptr ) { 162 | return TAI_STATUS_FAILURE; 163 | } 164 | n = a->notification; 165 | if ( n.notify == nullptr ) { 166 | return TAI_STATUS_FAILURE; 167 | } 168 | tai_status_t ret; 169 | for ( auto attr_id : ids ) { 170 | auto meta = tai_metadata_get_attr_metadata(T, attr_id); 171 | getter f = [this](tai_attribute_t* a){ return this->_get_attributes(1, a); }; 172 | S_Attribute attr; 173 | try { 174 | attr = std::make_shared(meta, f); 175 | } catch (Exception &e) { 176 | TAI_ERROR("getting attribute %s for notification failed: %s", meta->attridshortname, e.what()); 177 | continue; 178 | } 179 | ptrs.emplace_back(attr); // only used for memory management 180 | bool notify = true; 181 | if ( alarm ) { 182 | auto c = m_alarm_cache.get(attr_id); 183 | notify = attr->cmp(c); 184 | } 185 | if ( notify ) { 186 | attrs.emplace_back(*attr->raw()); 187 | if ( alarm ) { 188 | if ( meta->isreadonly ) { 189 | if ( (ret = m_alarm_cache.set_readonly(attr, true)) < 0 ) { 190 | return ret; 191 | } 192 | } else { 193 | if ( (ret = m_alarm_cache.set(attr, true)) < 0 ) { 194 | return ret; 195 | } 196 | } 197 | } 198 | } 199 | } 200 | if (attrs.size()) { 201 | TAI_DEBUG("sending notification 0x%lx", id()); 202 | n.notify(n.context, id(), attrs.size(), attrs.data()); 203 | } 204 | return TAI_STATUS_SUCCESS; 205 | } 206 | 207 | template 208 | tai_status_t Object::notify_alarm(tai_attr_id_t notification_id, const std::vector& ids) { 209 | return notify(notification_id, ids, true); 210 | } 211 | 212 | } 213 | 214 | #endif // __TAI_FRAMEWORK_OBJECT_HPP__ 215 | -------------------------------------------------------------------------------- /tools/framework/platform.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __TAI_FRAMEWORK_PLATFORM_HPP__ 2 | #define __TAI_FRAMEWORK_PLATFORM_HPP__ 3 | 4 | #include "object.hpp" 5 | 6 | namespace tai::framework { 7 | 8 | using Location = std::string; 9 | 10 | class Platform { 11 | public: 12 | Platform(const tai_service_method_table_t * services) : m_services(services) {}; 13 | virtual ~Platform() {}; 14 | virtual tai_status_t create(tai_object_type_t type, tai_object_id_t module_id, uint32_t attr_count, const tai_attribute_t *attr_list, tai_object_id_t *id) { return TAI_STATUS_NOT_SUPPORTED; } 15 | tai_status_t create(tai_object_type_t type, uint32_t attr_count, const tai_attribute_t *attr_list, tai_object_id_t *id) { 16 | return create(type, TAI_NULL_OBJECT_ID, attr_count, attr_list, id); 17 | } 18 | virtual tai_status_t remove(tai_object_id_t id) = 0; 19 | 20 | S_BaseObject get(tai_object_id_t id, tai_object_type_t filter = TAI_OBJECT_TYPE_NULL) { 21 | auto it = m_objects.find(id); 22 | if ( it == m_objects.end() ) { 23 | return nullptr; 24 | } 25 | if ( filter == TAI_OBJECT_TYPE_NULL || it->second->type() == filter ) { 26 | return it->second; 27 | } 28 | return nullptr; 29 | } 30 | 31 | virtual tai_object_type_t get_object_type(tai_object_id_t id) = 0; 32 | virtual tai_object_id_t get_module_id(tai_object_id_t id) = 0; 33 | 34 | virtual tai_status_t set_log(tai_api_t tai_api_id, tai_log_level_t log_level, tai_log_fn log_fn) { 35 | return TAI_STATUS_SUCCESS; 36 | } 37 | 38 | virtual tai_status_t list_metadata(const tai_metadata_key_t *const key, uint32_t *count, const tai_attr_metadata_t *const **list) { 39 | auto type = key->type; 40 | if ( key->oid != TAI_NULL_OBJECT_ID ) { 41 | type = get_object_type(key->oid); 42 | } 43 | auto info = tai_metadata_all_object_type_infos[type]; 44 | if ( info == nullptr ) { 45 | *count = tai_metadata_attr_sorted_by_id_name_count; 46 | *list = tai_metadata_attr_sorted_by_id_name; 47 | return TAI_STATUS_SUCCESS; 48 | } 49 | *count = info->attrmetadatalength; 50 | *list = info->attrmetadata; 51 | return TAI_STATUS_SUCCESS; 52 | } 53 | 54 | virtual const tai_attr_metadata_t* get_attr_metadata(const tai_metadata_key_t *const key, tai_attr_id_t attr_id) { 55 | auto type = key->type; 56 | if ( key->oid != TAI_NULL_OBJECT_ID ) { 57 | type = get_object_type(key->oid); 58 | } 59 | return tai_metadata_get_attr_metadata(type, attr_id); 60 | } 61 | 62 | virtual const tai_object_type_info_t* get_object_info(const tai_metadata_key_t *const key) { 63 | auto type = key->type; 64 | if ( key->oid != TAI_NULL_OBJECT_ID ) { 65 | type = get_object_type(key->oid); 66 | } 67 | return tai_metadata_get_object_type_info(type); 68 | } 69 | 70 | protected: 71 | const tai_service_method_table_t * m_services; 72 | // we don't need a lock to access m_objects/m_fsms since TAI API is not thread-safe 73 | std::map m_objects; 74 | std::map m_fsms; 75 | }; 76 | 77 | }; 78 | 79 | #endif // __PLATFORM_HPP__ 80 | -------------------------------------------------------------------------------- /tools/lib/README.md: -------------------------------------------------------------------------------- 1 | TAI C++ common library 2 | --- 3 | 4 | a small common/helper library which helps both TAI library developer and user. 5 | This library is used in TAI library framework and TAI shell. 6 | -------------------------------------------------------------------------------- /tools/lib/attribute.cpp: -------------------------------------------------------------------------------- 1 | #include "attribute.hpp" 2 | #include "logger.hpp" 3 | #include 4 | 5 | namespace tai { 6 | 7 | Attribute::Attribute(const tai_attr_metadata_t* const meta, const std::string& value, const tai_serialize_option_t* const option) : m_meta(meta) { 8 | tai_attribute_t attr = {.id = meta->attrid}; 9 | auto ret = tai_deserialize_attribute_value(value.c_str(), meta, &attr.value, option); 10 | if ( ret == TAI_STATUS_BUFFER_OVERFLOW ) { 11 | tai_alloc_info_t alloc_info = { .reference = &attr }; 12 | ret = tai_metadata_alloc_attr_value(meta, &attr, &alloc_info); 13 | if ( ret != TAI_STATUS_SUCCESS ) { 14 | throw Exception(ret); 15 | } 16 | ret = tai_deserialize_attribute_value(value.c_str(), meta, &attr.value, option); 17 | if ( ret < 0 ) { 18 | tai_metadata_free_attr_value(meta, &attr, nullptr); 19 | throw Exception(ret); 20 | } 21 | } else if ( ret < 0 ) { 22 | throw Exception(ret); 23 | } 24 | m_attr = attr; 25 | } 26 | 27 | std::string Attribute::to_string(tai_serialize_option_t* option) { 28 | auto size = tai_serialize_attribute(nullptr, 0, m_meta, &m_attr, option); 29 | if ( size < 0 ) { 30 | return "null"; 31 | } 32 | auto p = std::make_unique(size+10); 33 | auto ret = tai_serialize_attribute(p.get(), size+1, m_meta, &m_attr, option); 34 | if ( ret < 0 || ret > size+1 ) { 35 | return "null"; 36 | } 37 | return std::string(p.get()); 38 | } 39 | 40 | bool cmp(const S_Attribute lhs, const S_Attribute rhs) { 41 | return lhs->cmp(rhs); 42 | } 43 | 44 | inline bool operator==(const S_Attribute lhs, const S_Attribute rhs) { return cmp(lhs, rhs) == 0; } 45 | inline bool operator!=(const S_Attribute lhs, const S_Attribute rhs) { return cmp(lhs, rhs) != 0; } 46 | std::ostream& operator<<(std::ostream& os, const S_Attribute attr) { return attr->str(os); } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /tools/lib/attribute.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __ATTRIBUTE_HPP__ 2 | #define __ATTRIBUTE_HPP__ 3 | 4 | #include 5 | #include "tai.h" 6 | #include "taimetadata.h" 7 | 8 | #include "exception.hpp" 9 | #include "logger.hpp" 10 | 11 | #include 12 | #include 13 | 14 | namespace tai { 15 | 16 | class Attribute; 17 | 18 | using S_Attribute = std::shared_ptr; 19 | using S_ConstAttribute = std::shared_ptr; 20 | 21 | using getter = std::function; 22 | 23 | class Attribute { 24 | public: 25 | Attribute(const tai_attr_metadata_t* const meta, getter getter) : m_meta(meta) { 26 | if ( meta == nullptr ) { 27 | throw Exception(TAI_STATUS_INVALID_PARAMETER); 28 | } 29 | tai_attribute_t attr{.id = meta->attrid}; 30 | tai_status_t ret; 31 | for (int i = 0; i < 3; i++ ) { 32 | tai_alloc_info_t alloc_info = { .reference = &attr }; 33 | ret = tai_metadata_alloc_attr_value(meta, &attr, &alloc_info); 34 | if ( ret != TAI_STATUS_SUCCESS ) { 35 | goto err; 36 | } 37 | ret = getter(&attr); 38 | if ( ret == TAI_STATUS_SUCCESS ) { 39 | break; 40 | } else if ( ret != TAI_STATUS_BUFFER_OVERFLOW ) { 41 | goto err; 42 | } 43 | } 44 | 45 | if ( ret != TAI_STATUS_SUCCESS ) { 46 | err: 47 | tai_metadata_free_attr_value(meta, &attr, nullptr); 48 | throw Exception(ret); 49 | } 50 | m_attr = attr; 51 | } 52 | 53 | Attribute(const tai_attr_metadata_t* const meta, const tai_attribute_t* const src) : m_meta(meta) { 54 | if ( meta == nullptr || src == nullptr ) { 55 | throw Exception(TAI_STATUS_INVALID_PARAMETER); 56 | } 57 | tai_attribute_t attr = {.id = src->id}; 58 | tai_alloc_info_t info{ 59 | .reference=src, 60 | }; 61 | auto ret = tai_metadata_alloc_attr_value(meta, &attr, &info); 62 | if ( ret != TAI_STATUS_SUCCESS ) { 63 | throw Exception(ret); 64 | } 65 | ret = tai_metadata_deepcopy_attr_value(meta, src, &attr); 66 | if ( ret != TAI_STATUS_SUCCESS ) { 67 | throw Exception(ret); 68 | } 69 | m_attr = attr; 70 | } 71 | 72 | Attribute(const tai_attr_metadata_t* const meta, const tai_attribute_t& src) : Attribute(meta, &src) {} 73 | Attribute(const Attribute& a) : Attribute(a.metadata(), a.raw()) {} 74 | 75 | Attribute(const tai_attr_metadata_t* const meta, const std::string& value, const tai_serialize_option_t* const option = nullptr); 76 | 77 | int id() { 78 | return m_attr.id; 79 | } 80 | 81 | ~Attribute() { 82 | tai_metadata_free_attr_value(m_meta, &m_attr, nullptr); 83 | } 84 | const tai_attribute_t* const raw() const { 85 | return &m_attr; 86 | } 87 | 88 | const tai_attr_metadata_t* const metadata() const { 89 | return m_meta; 90 | } 91 | 92 | bool cmp(const tai_attribute_t* const rhs) { 93 | if ( rhs == nullptr ) { 94 | return true; 95 | } 96 | bool equal; 97 | tai_metadata_deepequal_attr_value(m_meta, &m_attr, rhs, &equal); 98 | return !equal; 99 | } 100 | 101 | bool cmp(const tai_attribute_value_t* const rhs) { 102 | if ( rhs == nullptr ) { 103 | return true; 104 | } 105 | tai_attribute_t a{m_meta->attrid, *rhs}; 106 | return cmp(&a); 107 | } 108 | 109 | bool cmp(const S_Attribute rhs) { 110 | return cmp(rhs->raw()); 111 | } 112 | 113 | std::string to_string(tai_serialize_option_t* option = nullptr); 114 | 115 | std::ostream& str(std::ostream& os) { 116 | tai_serialize_option_t option = { true, true, false }; 117 | os << to_string(&option); 118 | return os; 119 | } 120 | private: 121 | tai_attribute_t m_attr; 122 | const tai_attr_metadata_t* const m_meta; 123 | }; 124 | 125 | bool cmp(const S_Attribute lhs, const S_Attribute rhs); 126 | 127 | inline bool operator==(const S_Attribute lhs, const S_Attribute rhs); 128 | inline bool operator!=(const S_Attribute lhs, const S_Attribute rhs); 129 | std::ostream& operator<<(std::ostream& os, const S_Attribute attr); 130 | 131 | } 132 | 133 | #endif // __ATTRIBUTE_HPP__ 134 | -------------------------------------------------------------------------------- /tools/lib/capability.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __CAPABILITY_HPP__ 2 | #define __CAPABILITY_HPP__ 3 | 4 | #include "attribute.hpp" 5 | #include 6 | 7 | namespace tai { 8 | 9 | class Capability; 10 | 11 | using S_Capability = std::shared_ptr; 12 | 13 | using cap_getter = std::function; 14 | 15 | class Capability { 16 | public: 17 | Capability(const tai_attr_metadata_t* const meta, cap_getter getter) : m_meta(meta), m_cap() { 18 | if ( meta == nullptr ) { 19 | throw Exception(TAI_STATUS_INVALID_PARAMETER); 20 | } 21 | if ( meta->isenum && meta->enummetadata != nullptr ) { 22 | tai_attr_metadata_t m = { 23 | .attrvaluetype = TAI_ATTR_VALUE_TYPE_ATTRLIST, 24 | .attrlistvaluetype = TAI_ATTR_VALUE_TYPE_S32 25 | }; 26 | tai_alloc_info_t alloc_info = { 27 | .list_size = static_cast(meta->enummetadata->valuescount) 28 | }; 29 | tai_attribute_t a = {}; 30 | auto ret = tai_metadata_alloc_attr_value(&m, &a, &alloc_info); 31 | if ( ret != TAI_STATUS_SUCCESS ) { 32 | throw Exception(ret); 33 | } 34 | m_cap.supportedvalues = a.value.attrlist; 35 | } 36 | m_cap.id = meta->attrid; 37 | auto ret = getter(&m_cap); 38 | if ( ret != TAI_STATUS_SUCCESS ) { 39 | _free(); 40 | throw Exception(ret); 41 | } 42 | } 43 | 44 | const tai_attribute_capability_t* const raw(){ 45 | return &m_cap; 46 | } 47 | 48 | ~Capability(){ 49 | _free(); 50 | } 51 | 52 | private: 53 | const tai_attr_metadata_t* const m_meta; 54 | tai_attribute_capability_t m_cap; 55 | 56 | tai_status_t _free() { 57 | if ( !m_meta->isenum || m_meta->enummetadata == nullptr ) { 58 | return TAI_STATUS_SUCCESS; 59 | } 60 | tai_attr_metadata_t m{ 61 | .attrvaluetype = TAI_ATTR_VALUE_TYPE_ATTRLIST, 62 | .attrlistvaluetype = TAI_ATTR_VALUE_TYPE_S32 63 | }; 64 | tai_attribute_t a{.value = {.attrlist = m_cap.supportedvalues}}; 65 | return tai_metadata_free_attr_value(&m, &a, nullptr); 66 | } 67 | }; 68 | } 69 | 70 | #endif // __CAPABILITY_HPP__ 71 | -------------------------------------------------------------------------------- /tools/lib/exception.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __EXCEPTION_HPP__ 2 | #define __EXCEPTION_HPP__ 3 | 4 | #include "tai.h" 5 | #include 6 | 7 | namespace tai { 8 | 9 | struct Exception : public std::exception { 10 | public: 11 | Exception(tai_status_t err) : m_err(err) { 12 | tai_serialize_option_t option{true, false, false}; 13 | auto size = tai_serialize_status(nullptr, 0, m_err, &option); 14 | char buf[size+1]; 15 | tai_serialize_status(buf, size+1, m_err, &option); 16 | m_msg = buf; 17 | } 18 | virtual const char* what() const noexcept { 19 | return m_msg.c_str(); 20 | } 21 | tai_status_t err() { 22 | return m_err; 23 | } 24 | private: 25 | tai_status_t m_err; 26 | std::string m_msg; 27 | }; 28 | 29 | }; 30 | 31 | #endif // __EXCEPTION_HPP__ 32 | -------------------------------------------------------------------------------- /tools/lib/logger.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __LOGGER_HPP__ 2 | #define __LOGGER_HPP__ 3 | 4 | #include "tai.h" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace tai { 10 | 11 | static const std::string to_string(tai_log_level_t level) { 12 | switch (level) { 13 | case TAI_LOG_LEVEL_DEBUG: 14 | return "DEBUG"; 15 | case TAI_LOG_LEVEL_INFO: 16 | return "INFO"; 17 | case TAI_LOG_LEVEL_NOTICE: 18 | return "INFO"; 19 | case TAI_LOG_LEVEL_WARN: 20 | return "WARN"; 21 | case TAI_LOG_LEVEL_ERROR: 22 | return "ERROR"; 23 | case TAI_LOG_LEVEL_CRITICAL: 24 | return "CRITICAL"; 25 | default: 26 | return std::to_string(static_cast(level)); 27 | } 28 | } 29 | 30 | class Logger { 31 | private: 32 | Logger() = default; 33 | ~Logger() = default; 34 | public: 35 | Logger(const Logger&) = delete; 36 | Logger& operator=(const Logger&) = delete; 37 | Logger(Logger&&) = delete; 38 | Logger& operator=(Logger&&) = delete; 39 | 40 | static Logger& get_instance() { 41 | static Logger logger; 42 | return logger; 43 | } 44 | 45 | tai_status_t set_log(tai_api_t tai_api_id, tai_log_level_t log_level, tai_log_fn log_fn) { 46 | std::unique_lock lk(m_mtx); 47 | m_fn_map[tai_api_id] = {log_level, log_fn}; 48 | return TAI_STATUS_SUCCESS; 49 | } 50 | 51 | template 52 | void log(tai_api_t tai_api_id, tai_log_level_t log_level, const std::string& file, int line, const std::string& function, const std::string& format, Args... args) { 53 | std::unique_lock lk(m_mtx); 54 | auto it = m_fn_map.find(tai_api_id); 55 | if ( it == m_fn_map.end() && log_level >= TAI_LOG_LEVEL_ERROR ) { 56 | goto def; 57 | } else if ( it != m_fn_map.end() && it->second.first <= log_level ){ 58 | if ( it->second.second != nullptr ) { 59 | it->second.second(log_level, file.c_str(), line, function.c_str(), format.c_str(), args...); 60 | } else { 61 | def: 62 | std::fprintf(stderr, ("%s [%s@%d]" + format + "\n").c_str(), to_string(log_level).c_str(), function.c_str(), line, args...); 63 | } 64 | } 65 | } 66 | 67 | private: 68 | std::map> m_fn_map; 69 | std::mutex m_mtx; 70 | }; 71 | 72 | #define _TAI_LOG(api, level, format, ...) ::tai::Logger::get_instance().log(api, level, __FILE__, __LINE__, __PRETTY_FUNCTION__, format, ##__VA_ARGS__) 73 | #define TAI_LOG(level, format, ...) _TAI_LOG(TAI_API_UNSPECIFIED, level, format, ##__VA_ARGS__) 74 | 75 | #define TAI_DEBUG(format, ...) TAI_LOG(TAI_LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) 76 | #define TAI_INFO(format, ...) TAI_LOG(TAI_LOG_LEVEL_INFO, format, ##__VA_ARGS__) 77 | #define TAI_WARN(format, ...) TAI_LOG(TAI_LOG_LEVEL_WARN, format, ##__VA_ARGS__) 78 | #define TAI_ERROR(format, ...) TAI_LOG(TAI_LOG_LEVEL_ERROR, format, ##__VA_ARGS__) 79 | #define TAI_CRITICAL(format, ...) TAI_LOG(TAI_LOG_LEVEL_CRITICAL, format, ##__VA_ARGS__) 80 | 81 | } 82 | 83 | #endif // __LOGGER_HPP__ 84 | -------------------------------------------------------------------------------- /tools/lib/test/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /tools/lib/test/Makefile: -------------------------------------------------------------------------------- 1 | TOP_DIR ?= ../../../ 2 | 3 | run: test 4 | LD_LIBRARY_PATH=$(TOP_DIR)/meta ./test 5 | 6 | test: $(TOP_DIR)/meta/libmetatai.so $(wildcard ../*.cpp ../*.hpp) test.cpp 7 | g++ -g3 -Wall -std=c++17 -o test test.cpp ../attribute.cpp -L $(TOP_DIR)/meta -I $(TOP_DIR)/inc -I $(TOP_DIR)/meta -I .. -lmetatai 8 | 9 | $(TOP_DIR)/meta/libmetatai.so: 10 | $(MAKE) -C $(TOP_DIR)/meta 11 | 12 | FORCE: 13 | -------------------------------------------------------------------------------- /tools/lib/test/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "attribute.hpp" 3 | 4 | #include "taimetadata.h" 5 | 6 | int main() { 7 | const auto meta = tai_metadata_get_attr_metadata(TAI_OBJECT_TYPE_MODULE, TAI_MODULE_ATTR_TRIBUTARY_MAPPING); 8 | tai_serialize_option_t option = {.human = true, .valueonly = true}; 9 | { 10 | auto attr = tai::Attribute(meta, "[]", &option); 11 | std::cout << attr.to_string(&option) << std::endl; 12 | if ( attr.to_string(&option) != "[]" ) { 13 | return -1; 14 | } 15 | std::cout << "." << std::endl; 16 | } 17 | { 18 | auto attr = tai::Attribute(meta, "[{\"oid:0x1\": [\"oid:0x2\"]}]", &option); 19 | if ( attr.to_string(&option) != "[{\"oid:0x1\": [\"oid:0x2\"]}]" ) { 20 | return -1; 21 | } 22 | std::cout << "." << std::endl; 23 | } 24 | { 25 | auto src = tai::Attribute(meta, "[{\"oid:0x1\": [\"oid:0x2\"]}]", &option); 26 | auto dst = src; 27 | if ( dst.to_string(&option) != "[{\"oid:0x1\": [\"oid:0x2\"]}]" ) { 28 | return -1; 29 | } 30 | std::cout << "." << std::endl; 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tools/meta-generator/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.egg-info 3 | -------------------------------------------------------------------------------- /tools/meta-generator/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = tai_meta_generator 3 | version = 0.1.0 4 | description = TAI meta library generator 5 | 6 | [options] 7 | packages = find: 8 | install_requires = 9 | libclang 10 | jinja2 11 | zip_safe = False 12 | 13 | [options.entry_points] 14 | console_scripts = 15 | tai_meta_generator = tai_meta_generator.main:main 16 | -------------------------------------------------------------------------------- /tools/meta-generator/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup() 4 | -------------------------------------------------------------------------------- /tools/meta-generator/tai_meta_generator/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Telecominfraproject/oopt-tai/c30b16ac15309bd175b2568dd71c41a28e388da8/tools/meta-generator/tai_meta_generator/__init__.py -------------------------------------------------------------------------------- /tools/taish/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.pb.cc 3 | *.pb.h 4 | taish_server 5 | *.so 6 | build 7 | dist 8 | -------------------------------------------------------------------------------- /tools/taish/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /tools/taish/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | -------------------------------------------------------------------------------- /tools/taish/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: proto 2 | 3 | TAI_DIR := ../../ 4 | TAI_META_DIR := $(TAI_DIR)/meta 5 | TAI_LIB_DIR := $(TAI_DIR)/tools/lib 6 | TAI_FRAMEWORK_DIR := $(TAI_DIR)/tools/framework 7 | TAI_BASIC_LIB_DIR := $(TAI_FRAMEWORK_DIR)/examples/basic/ 8 | 9 | CFLAGS ?= -std=c++17 -fPIC -Wall -Werror 10 | 11 | ifdef DEBUG 12 | CFLAGS += -g3 -O0 13 | else 14 | CFLAGS += -O2 15 | endif 16 | 17 | LDFLAGS ?= -static-libstdc++ `pkg-config --libs protobuf grpc++ grpc` -L. -ltai -L ../../meta/ -Wl,'--no-as-needed' -lmetatai -lgrpc++_reflection -lpthread 18 | INCLUDE ?= -I $(TAI_META_DIR) -I $(TAI_DIR)/inc -I ./include -I ./lib -I $(TAI_LIB_DIR) 19 | 20 | LIB_GRPC_SRCS := lib/taish.grpc.pb.cc lib/taish.pb.cc 21 | LIB_OBJS = lib/server.o $(TAI_LIB_DIR)/attribute.o $(LIB_GRPC_SRCS:%.cc=%.o) 22 | SERVER_SRCS := server/main.cpp 23 | SERVER_OBJS := $(SERVER_SRCS:%.cpp=%.o) 24 | 25 | OBJS = $(LIB_OBJS) $(SERVER_OBJS) 26 | 27 | PROG := taish_server 28 | LIB_PROG := libtaigrpc.so 29 | 30 | $(PROG): proto $(TAI_META_DIR)/taimetadata.h $(TAI_META_DIR)/libmetatai.so $(OBJS) libtai.so 31 | $(CXX) $(CFLAGS) $(INCLUDE) -o $@ $(OBJS) $(LDFLAGS) 32 | 33 | $(TAI_META_DIR)/taimetadata.h $(TAI_META_DIR)/libmetatai.so: 34 | $(MAKE) -C $(TAI_META_DIR) 35 | 36 | libtai.so: Makefile 37 | $(MAKE) -C $(TAI_BASIC_LIB_DIR) clean 38 | $(MAKE) -C $(TAI_BASIC_LIB_DIR) 39 | ln -sf $(TAI_BASIC_LIB_DIR)/$@ $@ 40 | 41 | lib: proto $(LIB_OBJS) Makefile 42 | $(CXX) -shared $(CFLAGS) $(INCLUDE) -o $(LIB_PROG) $(LIB_OBJS) $(LDFLAGS) 43 | 44 | .cc.o: Makefile 45 | mkdir -p $(@D) 46 | $(CXX) $(INCLUDE) $(CFLAGS) -c -o $@ $< 47 | 48 | .cpp.o: Makefile 49 | mkdir -p $(@D) 50 | $(CXX) $(CFLAGS) $(INCLUDE) -c -o $@ $< 51 | 52 | proto: lib/taish.grpc.pb.cc lib/taish.grpc.pb.h lib/taish.pb.cc lib/taish.pb.h 53 | 54 | lib/taish.pb.cc lib/taish.pb.h: proto/taish/taish.proto 55 | protoc --cpp_out=./lib -I proto/taish taish.proto 56 | 57 | lib/taish.grpc.pb.cc lib/taish.grpc.pb.h: proto/taish/taish.proto 58 | protoc --grpc_out=./lib --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` -I proto/taish taish.proto 59 | 60 | python: 61 | python -m pip install wheel grpcio-tools 62 | $(MAKE) -C client 63 | python setup.py bdist_wheel 64 | python -m pip wheel -r requirements.txt -w dist 65 | pip install dist/*.whl 66 | 67 | clean: 68 | -rm -f ${OBJS} */*.pb\.* ${PROG} ${LIB_PROG} 69 | -------------------------------------------------------------------------------- /tools/taish/README.md: -------------------------------------------------------------------------------- 1 | TAI Shell (taish) 2 | --- 3 | 4 | taish is a tool/library which provides TAI debug shell/api function. 5 | It comes with 3 components. 6 | 7 | 1. standalone taish server `taish-server` 8 | 2. command line interface `taish` 9 | 3. taish library `libtaigrpc.so` 10 | 11 | taish uses [gRPC](https://grpc.io/) for the server/client communication. 12 | `taish-server` is a simple standalone tool written in C++ which provides taish gRPC API. 13 | As for TAI handling, it just creates module, netif and hostif with 14 | mandatory attributes and do nothing else. 15 | 16 | You can access the taish gRPC API using `taish` command. It is written in Python 17 | and provides human friendly interactive shell interface. 18 | 19 | By using `libtaigrpc.so`, you can also put taish server functionality into 20 | your TAI application. Since `libtaigrpc.so` provides the exactly same gRPC API as 21 | `taish-server`, you can use `taish` command. 22 | 23 | ## How to build `taish-server` 24 | 25 | ### native build 26 | 27 | #### prerequisite 28 | 29 | - make 30 | - g++ 31 | - grpc 32 | 33 | ``` 34 | $ make 35 | ``` 36 | 37 | 38 | ### docker build (recommended) 39 | 40 | #### prerequisite 41 | 42 | - make 43 | - docker 44 | 45 | ``` 46 | $ cd $(TAI_TOP_DIR) 47 | $ make docker-image # build container image for building TAI components 48 | $ make bash # run bash in the container 49 | root@ubuntu-bionic:/data# cd tools/taish/ 50 | root@ubuntu-bionic:/data/tools/taish# make 51 | ``` 52 | 53 | ## Usage 54 | 55 | ### `taish-server` 56 | 57 | ``` 58 | $ ./taish-server 59 | ``` 60 | 61 | By default `taish-server` listens on `0.0.0.0:50051`. You can change it by using 62 | `-i` and `-p` options. 63 | 64 | ``` 65 | $ ./taish-server -i 127.0.0.1 -p 10000 66 | ``` 67 | 68 | ### `taish` 69 | 70 | ``` 71 | $ ./client/taish.py --addr 72 | > 73 | ``` 74 | 75 | #### `list` command 76 | 77 | ``` 78 | > list 79 | module: 1 0x1000000000000 80 | hostif: 0 0x2000000000000 81 | hostif: 1 0x2000000000001 82 | netif: 0 0x3000000000000 83 | module: 2 0x1000000000001 84 | hostif: 0 0x2000000000100 85 | hostif: 1 0x2000000000101 86 | netif: 0 0x3000000000100 87 | > 88 | ``` 89 | 90 | `list` command displays all module, netif and hostif which are created by TAI 91 | application. 92 | 93 | In the example output above, it shows that 2 modules whose [location](https://github.com/Telecominfraproject/oopt-tai/blob/master/inc/taimodule.h#L122) is 94 | '1' and '2' respectively are created. The module '1' has 2 host interfaces whose [index](https://github.com/Telecominfraproject/oopt-tai/blob/master/inc/taihostif.h#L92) is 0 and 1, 95 | and 1 network interface whose [index](https://github.com/Telecominfraproject/oopt-tai/blob/master/inc/tainetworkif.h#L155) is 0. 96 | The output also shows object id of them. 97 | 98 | 99 | #### `module` command 100 | 101 | ``` 102 | > module 1 103 | module(1)> 104 | ``` 105 | 106 | `module` command selects which module to handle in successive commands. 107 | You need to specify valid location which can be known by `list` command. 108 | 109 | After executing the command, the prompt will change to show you which module 110 | is selected. 111 | 112 | #### `netif`, `hostif` command 113 | 114 | ``` 115 | > netif 0 116 | no module selected. 117 | > module 1 118 | module(1)> netif 0 119 | module(1)/netif(0)> hostif 0 120 | module(1)/hostif(0)> hostif 1 121 | module(1)/hostif(1)> 122 | ``` 123 | 124 | `netif` and `hostif` commands select which network interface or host interface 125 | to handle in successive commands. You need to specify valid index which can be 126 | known by `list` command. 127 | 128 | Also, before using these commands, you need to specify `module` first. 129 | In the example output above, the first command `netif 0` is failed since no 130 | module was selected. 131 | 132 | As same as `module` command, the prompt will change to show you which netif/hostif 133 | is selected after executing the command. 134 | 135 | #### `quit` command 136 | 137 | ``` 138 | module(1)/hostif(1)> q 139 | module(1)> q 140 | ``` 141 | 142 | This command is used to unselect the current selected TAI objected. 143 | 144 | #### `list-attr` command 145 | 146 | ``` 147 | module(1)> list-attr 148 | name readonly value 149 | ------------------------------ ---------- ------------------------------ 150 | location false 151 | vendor-name true 152 | vendor-part-number true 153 | vendor-serial-number true 154 | firmware-versions true 155 | oper-status true [unknown|initialize|ready|max] 156 | temp true 157 | power true 158 | num-host-interfaces true 159 | num-network-interfaces true 160 | admin-status false [unknown|down|up|max] 161 | tributary-mapping false 162 | module-shutdown-request-notify false 163 | module-state-change-notify false 164 | module(1)> 165 | module(1)> 166 | module(1)> 167 | module(1)> netif 0 168 | module(1)/netif(0)> list-attr 169 | name readonly value 170 | --------------------------------- ---------- ----------------------------------------------------------------------------------------------------------------------------- 171 | index false 172 | tx-align-status true [loss|out|cmu-lock|ref-clock|timing] 173 | rx-align-status true [modem-sync|modem-lock|loss|out|timing] 174 | tx-enable false 175 | tx-grid-spacing false [unknown|100-ghz|50-ghz|33-ghz|25-ghz|12-5-ghz|6-25-ghz|max] 176 | output-power false 177 | current-output-power true 178 | tx-laser-freq false 179 | tx-fine-tune-laser-freq false 180 | modulation-format false [unknown|bpsk|dp-bpsk|qpsk|dp-qpsk|8-qam|dp-8-qam|16-qam|dp-16-qam|32-qam|dp-32-qam|64-qam|dp-64-qam|max] 181 | current-ber true 182 | current-ber-period true 183 | differential-encoding false 184 | oper-status false [unknown|reset|initialize|low-power|high-power-up|tx-off|tx-turn-on|ready|tx-turn-off|high-power-down|fault|max] 185 | min-laser-freq true 186 | max-laser-freq true 187 | laser-grid-support true [unknown|100-ghz|50-ghz|33-ghz|25-ghz|12-5-ghz|6-25-ghz|max] 188 | current-input-power true 189 | current-post-voa-total-power true 190 | current-provisioned-channel-power true 191 | pulse-shaping-tx false 192 | pulse-shaping-rx false 193 | pulse-shaping-tx-beta false 194 | pulse-shaping-rx-beta false 195 | voa-rx false 196 | loopback-type false [none|shallow|deep|max] 197 | prbs-type false [none|prbs7|prbs9|prbs11|prbs15|prbs20|prbs23|prbs31|max] 198 | module(1)/netif(0)> 199 | module(1)/netif(0)> 200 | module(1)/netif(0)> 201 | module(1)/netif(0)> q 202 | module(1)> hostif 0 203 | module(1)/hostif(0)> list-attr 204 | name readonly value 205 | --------------- ---------- ------------------------------------- 206 | index false 207 | lane-fault true [loss-of-lock|tx-fifio-err] 208 | tx-align-status true [cdr-lock-fault|loss|out|deskew-lock] 209 | fec-type false [none|rs|fc] 210 | loopback-type false [none|shallow|deep|max] 211 | module(1)/hostif(0)> 212 | 213 | ``` 214 | 215 | `list-attr` command displays all TAI attributes for selected TAI object. 216 | If you execute this command when you are selecting a module, it will list all 217 | [TAI module attributes](https://github.com/Telecominfraproject/oopt-tai/blob/master/inc/taimodule.h). 218 | Same for netif and hostif. 219 | 220 | The output also shows attribute type and readonly flag. 221 | If the attribute type is enum, it shows valid enum values. 222 | 223 | #### `get` command 224 | 225 | ``` 226 | module(1)> get location 227 | 1 228 | module(1)> get oper-status 229 | ready 230 | module(1)> 231 | ``` 232 | 233 | `get` command gets TAI attribute. You need to specify valid attribute name 234 | which can be known by `list-attr` command. 235 | 236 | #### `set` command 237 | 238 | ``` 239 | module(1)/netif(0)> set output-power -1.0 240 | module(1)/netif(0)> set modulation-format dp-16-qam 241 | module(1)/netif(0)> set current-ber 242 | attribute current-ber is read-only 243 | ``` 244 | 245 | `set` command sets TAI attribute. You need to specify valid attribute name and 246 | value which can be known by `list-attr` command. 247 | Obviously, you can't set a value to read-only attributes. 248 | -------------------------------------------------------------------------------- /tools/taish/client/.gitignore: -------------------------------------------------------------------------------- 1 | *_pb2.py 2 | *_grpc.py 3 | __pycache__ 4 | *egg-info 5 | -------------------------------------------------------------------------------- /tools/taish/client/Makefile: -------------------------------------------------------------------------------- 1 | TAISH_DIR := .. 2 | 3 | all: taish/taish_pb2.py taish/taish_pb2_grpc.py 4 | 5 | taish/taish_pb2.py taish/taish_pb2_grpc.py: $(TAISH_DIR)/proto/taish/taish.proto 6 | python -m grpc_tools.protoc -I$(TAISH_DIR)/proto --python_out=. --grpc_python_out=. $(TAISH_DIR)/proto/taish/taish.proto 7 | 8 | clean: 9 | $(RM) -r __pycache__ *pb2.py *pb2_grpc.py 10 | -------------------------------------------------------------------------------- /tools/taish/client/taish/cli.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018-2019 Nippon Telegraph and Telephone Corporation. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from prompt_toolkit.document import Document 8 | from prompt_toolkit.completion import Completion, WordCompleter 9 | from prompt_toolkit.completion import Completer as PromptCompleter 10 | from prompt_toolkit import print_formatted_text as print 11 | 12 | import sys 13 | 14 | 15 | class InvalidInput(Exception): 16 | def __init__(self, msg, candidates=[]): 17 | self.msg = msg 18 | self.candidates = candidates 19 | 20 | def __str__(self): 21 | return self.msg 22 | 23 | 24 | class AsyncWordCompleter(WordCompleter): 25 | async def get_completions_async(self, document, complete_event): 26 | # Get list of words. 27 | words = self.words 28 | if callable(words): 29 | words = await words() 30 | 31 | # Get word/text before cursor. 32 | if self.sentence: 33 | word_before_cursor = document.text_before_cursor 34 | else: 35 | word_before_cursor = document.get_word_before_cursor( 36 | WORD=self.WORD, pattern=self.pattern 37 | ) 38 | 39 | if self.ignore_case: 40 | word_before_cursor = word_before_cursor.lower() 41 | 42 | def word_matches(word: str) -> bool: 43 | """True when the word before the cursor matches.""" 44 | if self.ignore_case: 45 | word = word.lower() 46 | 47 | if self.match_middle: 48 | return word_before_cursor in word 49 | else: 50 | return word.startswith(word_before_cursor) 51 | 52 | for a in words: 53 | if word_matches(a): 54 | display = self.display_dict.get(a, a) 55 | display_meta = self.meta_dict.get(a, "") 56 | yield Completion( 57 | text=a, 58 | start_position=-len(word_before_cursor), 59 | display=display, 60 | display_meta=display_meta, 61 | ) 62 | 63 | 64 | class Completer(PromptCompleter): 65 | def __init__(self, attrnames, valuenames=[], hook=None): 66 | if type(attrnames) == list: 67 | self._attrnames = lambda: attrnames 68 | else: 69 | self._attrnames = attrnames 70 | 71 | if type(valuenames) == list: 72 | self._valuenames = lambda _: valuenames 73 | else: 74 | self._valuenames = valuenames 75 | 76 | self._hook = hook 77 | 78 | def get_completions(self, document, complete_event=None): 79 | t = document.text.split() 80 | if len(t) == 0 or (len(t) == 1 and document.text[-1] != " "): 81 | # attribute name completion 82 | for c in self._attrnames(): 83 | if c.startswith(document.text): 84 | yield Completion(c, start_position=-len(document.text)) 85 | elif len(t) > 2 or (len(t) == 2 and document.text[-1] == " "): 86 | # invalid input for both get() and set(). no completion possible 87 | return 88 | else: 89 | # value completion 90 | 91 | if self._hook and self._hook(): 92 | return 93 | 94 | # complete the first argument 95 | doc = Document(t[0]) 96 | c = list(self.get_completions(doc)) 97 | if len(c) == 0: 98 | return 99 | elif len(c) > 1: 100 | # search perfect match 101 | l = [v.text for v in c if v.text == t[0]] 102 | if len(l) == 0: 103 | return 104 | attrname = l[0] 105 | else: 106 | attrname = c[0].text 107 | 108 | text = t[1] if len(t) > 1 else "" 109 | 110 | for c in self._valuenames(attrname): 111 | if c.startswith(text): 112 | yield Completion(c, start_position=-len(text)) 113 | 114 | 115 | class Object(object): 116 | XPATH = "" 117 | 118 | def __init__(self, parent): 119 | self.parent = parent 120 | self._commands = {} 121 | 122 | @self.command() 123 | async def quit(line): 124 | return self.parent if self.parent else sys.exit(0) 125 | 126 | def add_command(self, handler, completer=None, name=None): 127 | self.command(completer, name)(handler) 128 | 129 | def del_command(self, name): 130 | del self._commands[name] 131 | 132 | def command(self, completer=None, name=None): 133 | def f(func): 134 | async def _inner(line): 135 | v = await func(line) 136 | return v if v else self 137 | 138 | self._commands[name if name else func.__name__] = { 139 | "func": _inner, 140 | "completer": completer, 141 | } 142 | 143 | return f 144 | 145 | async def help(self, text="", short=True): 146 | text = text.lstrip() 147 | try: 148 | v = text.split() 149 | if len(text) > 0 and text[-1] == " ": 150 | # needs to show all candidates for the next argument 151 | v.append(" ") 152 | line = await self.complete_input(v) 153 | except InvalidInput as e: 154 | return ", ".join(e.candidates) 155 | return line[-1].strip() 156 | 157 | def commands(self): 158 | return list(self._commands.keys()) 159 | 160 | async def completion(self, document, complete_event=None): 161 | # complete_event is None when this method is called by complete_input() 162 | if complete_event == None and len(document.text) == 0: 163 | return 164 | t = document.text.split() 165 | if len(t) == 0 or (len(t) == 1 and document.text[-1] != " "): 166 | # command completion 167 | for cmd in self.commands(): 168 | if cmd.startswith(document.text): 169 | yield Completion(cmd, start_position=-len(document.text)) 170 | else: 171 | # argument completion 172 | # complete command(t[0]) first 173 | try: 174 | cmd = (await self.complete_input([t[0]]))[0] 175 | except InvalidInput: 176 | return 177 | v = self._commands.get(cmd) 178 | if not v: 179 | return 180 | c = v["completer"] 181 | if c: 182 | # do argument completion with text after the command (t[0]) 183 | new_document = Document(document.text[len(t[0]) :].lstrip()) 184 | async for v in c.get_completions_async(new_document, complete_event): 185 | yield v 186 | 187 | async def complete_input(self, line): 188 | 189 | if len(line) == 0: 190 | raise InvalidInput( 191 | "invalid command. available commands: {}".format(self.commands()), 192 | self.commands(), 193 | ) 194 | 195 | for i in range(len(line)): 196 | doc = Document(" ".join(line[: i + 1])) 197 | c = [v async for v in self.completion(doc)] 198 | if len(c) == 0: 199 | if i == 0: 200 | raise InvalidInput( 201 | "invalid command. available commands: {}".format( 202 | self.commands() 203 | ), 204 | self.commands(), 205 | ) 206 | else: 207 | # t[0] must be already completed 208 | v = self._commands.get(line[0]) 209 | assert v 210 | cmpl = v["completer"] 211 | if cmpl: 212 | doc = Document(" ".join(line[:i] + [" "])) 213 | candidates = [v.text async for v in self.completion(doc)] 214 | # if we don't have any candidates with empty input, it means the value needs 215 | # to be passed as an opaque value 216 | if len(candidates) == 0: 217 | continue 218 | 219 | raise InvalidInput( 220 | "invalid argument. candidates: {}".format(candidates), 221 | candidates, 222 | ) 223 | else: 224 | # no command completer, the command doesn't take any argument 225 | continue 226 | elif len(c) > 1: 227 | # search for a perfect match 228 | t = [v for v in c if v.text == line[i]] 229 | if len(t) == 0: 230 | candidates = [v.text for v in c] 231 | raise InvalidInput( 232 | "ambiguous {}. candidates: {}".format( 233 | "command" if i == 0 else "argument", candidates 234 | ), 235 | candidates, 236 | ) 237 | c[0] = t[0] 238 | line[i] = c[0].text 239 | return line 240 | 241 | async def exec(self, cmd): 242 | line = cmd.split() 243 | try: 244 | line = await self.complete_input(line) 245 | if line[0] in self._commands: 246 | return await self._commands[line[0]]["func"](line=line[1:]) 247 | else: 248 | raise InvalidInput( 249 | "invalid command. available commands: {}".format(self.commands()) 250 | ) 251 | except InvalidInput as e: 252 | print(str(e)) 253 | return self 254 | -------------------------------------------------------------------------------- /tools/taish/config/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "2": { 3 | "attrs": { 4 | "admin-status": "down" 5 | }, 6 | "netif": { 7 | "0": { 8 | "attrs": { 9 | "modulation-format": "dp-qpsk" 10 | } 11 | } 12 | }, 13 | "hostif": { 14 | "0": { 15 | "attrs": { 16 | } 17 | }, 18 | "1": { 19 | "attrs": { 20 | } 21 | } 22 | } 23 | }, 24 | "6": { 25 | "attrs": { 26 | "admin-status": "down" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tools/taish/include/taigrpc.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taigrpc.hpp 3 | * 4 | * @brief This module defines TAI gRPC server 5 | * 6 | * @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation 7 | * 8 | * This source code is licensed under the BSD-style license found in the 9 | * LICENSE file in the root directory of this source tree. 10 | */ 11 | 12 | #ifndef __TAIGRPC_HPP__ 13 | #define __TAIGRPC_HPP__ 14 | 15 | #include "tai.h" 16 | #include "taish.grpc.pb.h" 17 | #include "taimetadata.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "attribute.hpp" 29 | 30 | struct tai_api_module_t 31 | { 32 | std::string location; 33 | bool present; 34 | tai_object_id_t id; 35 | std::map hostifs; 36 | std::map netifs; 37 | }; 38 | 39 | typedef tai_status_t (*tai_api_list_module_fn)(_Inout_ std::vector& list); 40 | 41 | // this hook function will be called when taish library created or removed a TAI object 42 | // type : the object type, we can't use tai_object_type_query() since the object with the oid is 43 | // already removed when this function is called 44 | // oid : the object id of the created or removed object 45 | // is_create : a flag to indicated whether the update is create or remove 46 | typedef void (*tai_object_update_fn)(tai_object_type_t type, tai_object_id_t oid, int index, bool is_create); 47 | 48 | struct tai_api_method_table_t 49 | { 50 | tai_module_api_t* module_api; 51 | tai_host_interface_api_t* hostif_api; 52 | tai_network_interface_api_t* netif_api; 53 | tai_meta_api_t* meta_api; 54 | tai_api_list_module_fn list_module; 55 | tai_object_update_fn object_update; 56 | }; 57 | 58 | struct tai_notification_t { 59 | tai_object_id_t oid; 60 | std::vector attrs; 61 | }; 62 | 63 | struct tai_subscription_t { 64 | std::mutex mtx; 65 | std::queue q; 66 | std::condition_variable cv; 67 | }; 68 | 69 | class TAINotifier { 70 | public: 71 | TAINotifier(tai_meta_api_t* m) : m_meta_api(m) {}; 72 | int notify(const tai_notification_t& n); 73 | int subscribe(void* id, tai_subscription_t* s) { 74 | std::unique_lock lk(mtx); 75 | if ( m.find(id) != m.end() ) { 76 | return -1; 77 | } 78 | m[id] = s; 79 | return 0; 80 | } 81 | int desubscribe(void* id) { 82 | std::unique_lock lk(mtx); 83 | if ( m.find(id) == m.end() ) { 84 | return -1; 85 | } 86 | m.erase(id); 87 | return 0; 88 | } 89 | int size() { 90 | std::unique_lock lk(mtx); 91 | return m.size(); 92 | } 93 | tai_meta_api_t* meta_api() { 94 | return m_meta_api; 95 | } 96 | private: 97 | std::map m; 98 | std::mutex mtx; 99 | tai_meta_api_t* m_meta_api; 100 | }; 101 | 102 | class TAIServiceImpl final : public taish::TAI::Service { 103 | public: 104 | TAIServiceImpl(const tai_api_method_table_t* const api) : m_api(api) {}; 105 | ::grpc::Status ListModule(::grpc::ServerContext* context, const taish::ListModuleRequest* request, ::grpc::ServerWriter< taish::ListModuleResponse>* writer); 106 | ::grpc::Status ListAttributeMetadata(::grpc::ServerContext* context, const taish::ListAttributeMetadataRequest* request, ::grpc::ServerWriter< taish::ListAttributeMetadataResponse>* writer); 107 | ::grpc::Status GetAttributeMetadata(::grpc::ServerContext* context, const taish::GetAttributeMetadataRequest* request, taish::GetAttributeMetadataResponse* response); 108 | ::grpc::Status GetAttributeCapability(::grpc::ServerContext* context, const taish::GetAttributeCapabilityRequest* request, taish::GetAttributeCapabilityResponse* response); 109 | ::grpc::Status GetAttribute(::grpc::ServerContext* context, const taish::GetAttributeRequest* request, taish::GetAttributeResponse* response); 110 | ::grpc::Status SetAttribute(::grpc::ServerContext* context, const taish::SetAttributeRequest* request, taish::SetAttributeResponse* response); 111 | ::grpc::Status ClearAttribute(::grpc::ServerContext* context, const taish::ClearAttributeRequest* request, taish::ClearAttributeResponse* response); 112 | ::grpc::Status Monitor(::grpc::ServerContext* context, const taish::MonitorRequest* request, ::grpc::ServerWriter< taish::MonitorResponse>* writer); 113 | ::grpc::Status SetLogLevel(::grpc::ServerContext* context, const taish::SetLogLevelRequest* request, taish::SetLogLevelResponse* response); 114 | ::grpc::Status Create(::grpc::ServerContext* context, const taish::CreateRequest* request, taish::CreateResponse* response); 115 | ::grpc::Status Remove(::grpc::ServerContext* context, const taish::RemoveRequest* request, taish::RemoveResponse* response); 116 | private: 117 | std::shared_ptr get_notifier(tai_object_id_t oid, tai_attr_id_t nid) { 118 | auto key = std::pair(oid, nid); 119 | if ( m_notifiers.find(key) == m_notifiers.end() ) { 120 | m_notifiers[key] = std::make_shared(m_api->meta_api); 121 | } 122 | return m_notifiers[key]; 123 | } 124 | const tai_api_method_table_t* const m_api; 125 | std::mutex m_mtx; // mutex for serialized TAI API calls 126 | 127 | std::map, std::shared_ptr> m_notifiers; 128 | std::mutex m_notifiers_mtx; // mutex to protect m_notifiers 129 | 130 | }; 131 | 132 | const tai_attr_metadata_t* const get_metadata(tai_meta_api_t* meta_api, const tai_metadata_key_t * const key, tai_attr_id_t attr_id); 133 | 134 | #endif // __TAIGRPC_HPP__ 135 | -------------------------------------------------------------------------------- /tools/taish/proto/taish/taish.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package taish; 4 | 5 | service TAI { 6 | rpc ListModule(ListModuleRequest) returns (stream ListModuleResponse); 7 | rpc ListAttributeMetadata(ListAttributeMetadataRequest) returns (stream ListAttributeMetadataResponse); 8 | rpc GetAttributeMetadata(GetAttributeMetadataRequest) returns (GetAttributeMetadataResponse); 9 | rpc GetAttribute(GetAttributeRequest) returns (GetAttributeResponse); 10 | rpc GetAttributeCapability(GetAttributeCapabilityRequest) returns (GetAttributeCapabilityResponse); 11 | rpc SetAttribute(SetAttributeRequest) returns (SetAttributeResponse); 12 | rpc ClearAttribute(ClearAttributeRequest) returns (ClearAttributeResponse); 13 | rpc Monitor(MonitorRequest) returns (stream MonitorResponse); 14 | rpc SetLogLevel(SetLogLevelRequest) returns (SetLogLevelResponse); 15 | rpc Create(CreateRequest) returns (CreateResponse); 16 | rpc Remove(RemoveRequest) returns (RemoveResponse); 17 | } 18 | 19 | enum TAIObjectType { 20 | UNKNOWN = 0; 21 | MODULE = 1; 22 | HOSTIF = 2; 23 | NETIF = 3; 24 | } 25 | 26 | enum TAIAPIType { 27 | UNSPECIFIED_API = 0; 28 | MODULE_API = 1; 29 | HOSTIF_API = 2; 30 | NETIF_API = 3; 31 | } 32 | 33 | enum TAILogLevel { 34 | DEBUG = 0; 35 | INFO = 1; 36 | NOTICE = 2; 37 | WARN = 3; 38 | ERROR = 4; 39 | CRITICAL = 5; 40 | } 41 | 42 | message SerializeOption { 43 | bool human = 1; 44 | bool value_only = 2; 45 | bool json = 3; 46 | } 47 | 48 | message ListModuleRequest { 49 | } 50 | 51 | message ListModuleResponse { 52 | Module module = 1; 53 | } 54 | 55 | message ListAttributeMetadataRequest { 56 | TAIObjectType object_type = 1; 57 | uint64 oid = 2; 58 | string location = 3; 59 | } 60 | 61 | message ListAttributeMetadataResponse { 62 | AttributeMetadata metadata = 1; 63 | } 64 | 65 | message GetAttributeMetadataRequest { 66 | TAIObjectType object_type = 1; 67 | oneof attr { 68 | uint64 attr_id = 2; 69 | string attr_name = 3; 70 | } 71 | SerializeOption serialize_option = 4; 72 | uint64 oid = 5; 73 | string location = 6; 74 | } 75 | 76 | message GetAttributeMetadataResponse { 77 | AttributeMetadata metadata = 1; 78 | } 79 | 80 | message GetAttributeCapabilityRequest { 81 | uint64 oid = 1; 82 | uint64 attr_id = 2; 83 | SerializeOption serialize_option = 3; 84 | } 85 | 86 | message GetAttributeCapabilityResponse { 87 | AttributeCapability capability = 1; 88 | } 89 | 90 | message GetAttributeRequest { 91 | uint64 oid = 1; 92 | reserved 2; 93 | SerializeOption serialize_option = 3; 94 | repeated Attribute attributes = 4; 95 | } 96 | 97 | message GetAttributeResponse { 98 | reserved 1; 99 | repeated Attribute attributes = 2; 100 | } 101 | 102 | message SetAttributeRequest { 103 | uint64 oid = 1; 104 | reserved 2; 105 | SerializeOption serialize_option = 3; 106 | repeated Attribute attributes = 4; 107 | } 108 | 109 | message SetAttributeResponse { 110 | } 111 | 112 | message ClearAttributeRequest { 113 | uint64 oid = 1; 114 | uint64 attr_id = 2; 115 | } 116 | 117 | message ClearAttributeResponse { 118 | } 119 | 120 | message MonitorRequest { 121 | uint64 oid = 1; 122 | uint64 notification_attr_id = 2; 123 | SerializeOption serialize_option = 3; 124 | } 125 | 126 | message MonitorResponse { 127 | repeated Attribute attrs = 1; 128 | } 129 | 130 | message SetLogLevelRequest { 131 | TAIAPIType api = 1; 132 | TAILogLevel level = 2; 133 | } 134 | 135 | message SetLogLevelResponse { 136 | } 137 | 138 | message CreateRequest { 139 | TAIObjectType object_type = 1; 140 | repeated Attribute attrs = 2; 141 | uint64 module_id = 3; 142 | SerializeOption serialize_option = 4; 143 | } 144 | 145 | message CreateResponse { 146 | uint64 oid = 1; 147 | } 148 | 149 | message RemoveRequest { 150 | uint64 oid = 1; 151 | } 152 | 153 | message RemoveResponse { 154 | } 155 | 156 | message Attribute { 157 | uint64 attr_id = 1; 158 | string value = 2; 159 | } 160 | 161 | message AttributeMetadata { 162 | uint64 attr_id = 1; 163 | string name = 2; 164 | string short_name = 3; 165 | TAIObjectType object_type = 4; 166 | string usage = 5; 167 | bool is_readonly = 6; 168 | bool is_mandatoryoncreate = 7; 169 | bool is_createonly = 8; 170 | bool is_createandset = 9; 171 | bool is_key = 10; 172 | bool is_enum = 11; 173 | } 174 | 175 | message AttributeCapability { 176 | uint64 attr_id = 1; 177 | string default_value = 2; 178 | string min = 3; 179 | string max = 4; 180 | repeated string supportedvalues = 5; 181 | } 182 | 183 | message HostInterface { 184 | uint64 oid = 1; 185 | uint32 index = 2; 186 | uint64 module_oid = 3; 187 | } 188 | 189 | message NetworkInterface { 190 | uint64 oid = 1; 191 | uint32 index = 2; 192 | uint64 module_oid = 3; 193 | } 194 | 195 | message Module { 196 | uint64 oid = 1; 197 | string location = 2; 198 | repeated HostInterface hostifs = 3; 199 | repeated NetworkInterface netifs = 4; 200 | bool present = 5; 201 | } 202 | -------------------------------------------------------------------------------- /tools/taish/requirements.txt: -------------------------------------------------------------------------------- 1 | prompt_toolkit 2 | tabulate 3 | protobuf 4 | grpcio 5 | -------------------------------------------------------------------------------- /tools/taish/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | import subprocess as sp 3 | import os 4 | 5 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 6 | 7 | with open('requirements.txt') as f: 8 | install_requires = f.read().split() 9 | 10 | with open('README.md', 'r') as f: 11 | long_description = f.read() 12 | 13 | cmd = 'make -C ./client' 14 | sp.run(cmd.split()) 15 | 16 | # list tags on the current branch 17 | cmd = ['sh', '-c', '(which git && git log --decorate --simplify-by-decoration --pretty=oneline HEAD --format=%d) || echo latest'] 18 | proc = sp.Popen(cmd, stdout=sp.PIPE) 19 | 20 | version = None 21 | for line in iter(proc.stdout.readline, b''): 22 | s = line.decode('utf-8').strip() 23 | for v in s.split(','): 24 | l = v.strip('()').strip() 25 | if l.startswith('tag: v'): 26 | version = l.split()[1][1:] 27 | break; 28 | if version: 29 | break 30 | 31 | if version == None: 32 | version = '1.0a1' 33 | 34 | setuptools.setup( 35 | name='taish', 36 | version=version, 37 | install_requires=install_requires, 38 | description='TAI shell', 39 | long_description=long_description, 40 | long_description_content_type='text/markdown', 41 | url='https://github.com/Telecominfraproject/oopt-tai/tree/master/tools/taish', 42 | package_dir={'': 'client'}, 43 | packages=setuptools.find_namespace_packages(where='client'), 44 | python_requires='>=3.7', 45 | entry_points={ 46 | 'console_scripts': [ 47 | 'taish = taish.main:main', 48 | ], 49 | }, 50 | ) 51 | --------------------------------------------------------------------------------