mirror of
https://github.com/Telecominfraproject/oopt-tai-implementations.git
synced 2025-11-03 03:27:58 +00:00
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "tai_ac400/oopt-tai"]
|
||||
path = tai_ac400/oopt-tai
|
||||
url = https://github.com/Telecominfraproject/oopt-tai.git
|
||||
[submodule "tai_mux/oopt-tai"]
|
||||
path = tai_mux/oopt-tai
|
||||
url = https://github.com/Telecominfraproject/oopt-tai.git
|
||||
|
||||
3
tai_mux/.gitignore
vendored
Normal file
3
tai_mux/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.so
|
||||
test/test
|
||||
build
|
||||
201
tai_mux/LICENSE
Normal file
201
tai_mux/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
22
tai_mux/Makefile
Normal file
22
tai_mux/Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
CC := g++
|
||||
CFLAGS := -std=c++11 -fPIC
|
||||
INCLUDES := -I ./oopt-tai/inc
|
||||
BUILDDIR := build
|
||||
SRCDIR := .
|
||||
SRCEXT := cpp
|
||||
SOURCES := $(shell ls $(SRCDIR)/*.cpp)
|
||||
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
|
||||
|
||||
TARGET := libtai-mux.so
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) $(CFLAGS) -shared $^ -o $@ -ldl -lpthread
|
||||
|
||||
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
|
||||
@mkdir -p $(BUILDDIR)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
-rm -r $(BUILDDIR) $(TARGET)
|
||||
69
tai_mux/README.md
Normal file
69
tai_mux/README.md
Normal file
@@ -0,0 +1,69 @@
|
||||
MUX TAI implementation
|
||||
===
|
||||
|
||||
MUX TAI library ( `libtai-mux.so` ) is a TAI library to multiplex multiple TAI
|
||||
libraries. `libtai-mux.so` can be used for hardware which supports multiple
|
||||
types of optical module which supports TAI. In such hardware, each optical module
|
||||
vendors provides `libtai.so` for their modules. `libtai-mux.so` dynamically loads
|
||||
these library and provides a single multiplexed TAI interface to TAI adapter host.
|
||||
|
||||
### platform adapter
|
||||
|
||||
Inside `libtai-mux.so`, platform adapter detects the presence of optical
|
||||
modules and decides which `libtai.so` to use for detected modules.
|
||||
|
||||
`libtai-mux.so` has modular design to support various types of
|
||||
platform adapter. User can choose which platform adapter to use by
|
||||
passing an environment variable `TAI_MUX_PLATFORM_ADAPTER`.
|
||||
|
||||
Currently, only `static` platform adapter is supported.
|
||||
|
||||
#### static platform adapter
|
||||
|
||||
static platform adapter is a platform adapter which uses static configuration
|
||||
for module detection and `libtai.so` loading.
|
||||
|
||||
Here is a sample configuration.
|
||||
|
||||
```json
|
||||
{
|
||||
"1": "libtai-a.so",
|
||||
"2": "libtai-a.so",
|
||||
"3": "libtai-a.so",
|
||||
"4": "libtai-a.so",
|
||||
"5": "libtai-b.so",
|
||||
"6": "libtai-b.so",
|
||||
"7": "libtai-b.so",
|
||||
"8": "libtai-b.so"
|
||||
}
|
||||
```
|
||||
|
||||
The format is `json`. The key is the location of the module and the value is
|
||||
the library to use for it.
|
||||
|
||||
By using the configuration above, `libtai-a.so` is used for modules
|
||||
whose location is 1,2,3,4, and `libtai-b.so` is used for modules whose location
|
||||
is 5,6,7,8.
|
||||
|
||||
An environment variable `TAI_MUX_STATIC_CONFIG_FILE` is used to let the
|
||||
static platform adapter know the location of the configuration file.
|
||||
|
||||
### HOW TO BUILD
|
||||
|
||||
```
|
||||
$ git submodule update --init
|
||||
$ make
|
||||
```
|
||||
|
||||
### HOW TO TEST
|
||||
|
||||
```
|
||||
$ cd test
|
||||
$ make
|
||||
$ ./run.sh
|
||||
```
|
||||
|
||||
### Licensing
|
||||
`libtai-mux.so` is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.
|
||||
|
||||
external library `json.hpp` which is distributed under MIT License is used in `libtai-mux.so`
|
||||
17300
tai_mux/json.hpp
Normal file
17300
tai_mux/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
56
tai_mux/module_adapter.cpp
Normal file
56
tai_mux/module_adapter.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "module_adapter.hpp"
|
||||
#include <dlfcn.h>
|
||||
#include <map>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
|
||||
#define LOAD_TAI_API(name) \
|
||||
m_ ## name = (name ## _fn) dlsym(m_dl, #name); \
|
||||
if ( m_ ## name == nullptr ) { \
|
||||
throw std::runtime_error( #name " undefined");\
|
||||
}
|
||||
|
||||
ModuleAdapter::ModuleAdapter(const std::string& name, uint64_t flags, const tai_service_method_table_t* services) : m_name(name) {
|
||||
m_dl = dlopen(name.c_str(), RTLD_NOW);
|
||||
if ( m_dl == nullptr ) {
|
||||
throw std::runtime_error(dlerror());
|
||||
}
|
||||
LOAD_TAI_API(tai_api_initialize)
|
||||
LOAD_TAI_API(tai_api_uninitialize)
|
||||
LOAD_TAI_API(tai_api_query)
|
||||
LOAD_TAI_API(tai_log_set)
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
auto status = tai_api_initialize(flags, services);
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
ss << "failed to initialize " << name << ":" << status;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
status = tai_api_query(TAI_API_MODULE, (void **)(&m_module_api));
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
ss << "failed to query TAI_API_MODULE :" << status;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
status = tai_api_query(TAI_API_NETWORKIF, (void **)(&m_netif_api));
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
ss << "failed to query TAI_API_NETWORKIF:" << status;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
status = tai_api_query(TAI_API_HOSTIF, (void **)(&m_hostif_api));
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
ss << "failed to query TAI_API_HOSTIF:" << status;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
ModuleAdapter::~ModuleAdapter() {
|
||||
dlclose(m_dl);
|
||||
}
|
||||
|
||||
uint64_t ModuleAdapter::dl_address(const std::string& name) {
|
||||
return (uint64_t)dlopen(name.c_str(), RTLD_NOW | RTLD_NOLOAD);
|
||||
}
|
||||
172
tai_mux/module_adapter.hpp
Normal file
172
tai_mux/module_adapter.hpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#ifndef __MODULE_ADAPTER_HPP__
|
||||
#define __MODULE_ADAPTER_HPP__
|
||||
|
||||
#include <string>
|
||||
#include "tai.h"
|
||||
|
||||
typedef tai_status_t (*tai_api_initialize_fn) (uint64_t, const tai_service_method_table_t *);
|
||||
typedef tai_status_t (*tai_api_uninitialize_fn) (void);
|
||||
typedef tai_status_t (*tai_api_query_fn) (tai_api_t, void**);
|
||||
typedef tai_status_t (*tai_log_set_fn) (tai_api_t, tai_log_level_t);
|
||||
typedef tai_object_type_t (*tai_object_type_query_fn) (tai_object_id_t);
|
||||
typedef tai_object_id_t (*tai_module_id_query_fn) (tai_object_id_t);
|
||||
|
||||
// corresponds to one dynamic library
|
||||
class ModuleAdapter {
|
||||
public:
|
||||
ModuleAdapter(const std::string& name, uint64_t flags, const tai_service_method_table_t* services);
|
||||
~ModuleAdapter();
|
||||
static uint64_t dl_address(const std::string& name);
|
||||
|
||||
tai_status_t tai_api_initialize(uint64_t flags, const tai_service_method_table_t* services) {
|
||||
return m_tai_api_initialize(flags, services);
|
||||
}
|
||||
tai_status_t tai_api_query(tai_api_t tai_api_id, void** api_method_table) {
|
||||
return m_tai_api_query(tai_api_id, api_method_table);
|
||||
}
|
||||
tai_status_t tai_api_uninitialize(void) {
|
||||
return m_tai_api_uninitialize();
|
||||
}
|
||||
tai_status_t tai_log_set(tai_api_t tai_api_id, tai_log_level_t log_level) {
|
||||
return m_tai_log_set(tai_api_id, log_level);
|
||||
}
|
||||
tai_object_type_t tai_object_type_query(tai_object_id_t tai_object_id) {
|
||||
return m_tai_object_type_query(tai_object_id);
|
||||
}
|
||||
tai_object_id_t tai_module_id_query(tai_object_id_t tai_object_id) {
|
||||
return m_tai_module_id_query(tai_object_id);
|
||||
}
|
||||
|
||||
tai_status_t create_module(
|
||||
_Out_ tai_object_id_t *module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list,
|
||||
_In_ tai_module_notification_t *notifications) {
|
||||
if ( m_module_api == nullptr || m_module_api->create_module == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_module_api->create_module(module_id, attr_count, attr_list, notifications);
|
||||
}
|
||||
|
||||
tai_status_t remove_module(
|
||||
_In_ tai_object_id_t module_id) {
|
||||
if ( m_module_api == nullptr || m_module_api->remove_module == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_module_api->remove_module(module_id);
|
||||
}
|
||||
|
||||
tai_status_t set_module_attributes(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
if ( m_module_api == nullptr || m_module_api->set_module_attributes == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_module_api->set_module_attributes(module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t get_module_attributes(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ tai_attribute_t *attr_list) {
|
||||
if ( m_module_api == nullptr || m_module_api->get_module_attributes == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_module_api->get_module_attributes(module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t create_network_interface(
|
||||
_Out_ tai_object_id_t *network_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
if ( m_netif_api == nullptr || m_netif_api->create_network_interface == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_netif_api->create_network_interface(network_interface_id, module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t remove_network_interface(
|
||||
_In_ tai_object_id_t network_interface_id) {
|
||||
if ( m_netif_api == nullptr || m_netif_api->remove_network_interface == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_netif_api->remove_network_interface(network_interface_id);
|
||||
}
|
||||
|
||||
tai_status_t set_network_interface_attributes(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
if ( m_netif_api == nullptr || m_netif_api->set_network_interface_attributes == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_netif_api->set_network_interface_attributes(network_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t get_network_interface_attributes(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ tai_attribute_t *attr_list) {
|
||||
if ( m_netif_api == nullptr || m_netif_api->get_network_interface_attributes == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_netif_api->get_network_interface_attributes(network_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t create_host_interface(
|
||||
_Out_ tai_object_id_t *host_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
if ( m_hostif_api == nullptr || m_hostif_api->create_host_interface == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_hostif_api->create_host_interface(host_interface_id, module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t remove_host_interface(
|
||||
_In_ tai_object_id_t host_interface_id) {
|
||||
if ( m_hostif_api == nullptr || m_hostif_api->remove_host_interface == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_hostif_api->remove_host_interface(host_interface_id);
|
||||
}
|
||||
|
||||
tai_status_t set_host_interface_attributes(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
if ( m_hostif_api == nullptr || m_hostif_api->set_host_interface_attributes == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_hostif_api->set_host_interface_attributes(host_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t get_host_interface_attributes(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ tai_attribute_t *attr_list) {
|
||||
if ( m_hostif_api == nullptr || m_hostif_api->get_host_interface_attributes == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_hostif_api->get_host_interface_attributes(host_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
private:
|
||||
void* m_dl;
|
||||
const std::string& m_name;
|
||||
tai_api_initialize_fn m_tai_api_initialize;
|
||||
tai_api_uninitialize_fn m_tai_api_uninitialize;
|
||||
tai_api_query_fn m_tai_api_query;
|
||||
tai_log_set_fn m_tai_log_set;
|
||||
tai_object_type_query_fn m_tai_object_type_query;
|
||||
tai_module_id_query_fn m_tai_module_id_query;
|
||||
|
||||
tai_module_api_t* m_module_api;
|
||||
tai_host_interface_api_t* m_hostif_api;
|
||||
tai_network_interface_api_t* m_netif_api;
|
||||
};
|
||||
|
||||
#endif
|
||||
269
tai_mux/mux.cpp
Normal file
269
tai_mux/mux.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
#include "mux.hpp"
|
||||
|
||||
Multiplexier *g_mux;
|
||||
|
||||
static const tai_attribute_value_t * find_attribute_in_list(
|
||||
_In_ tai_attr_id_t attr_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list)
|
||||
{
|
||||
while (attr_count--) {
|
||||
if (attr_list->id == attr_id) {
|
||||
return &attr_list->value;
|
||||
}
|
||||
attr_list++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::create_host_interface(
|
||||
_Out_ tai_object_id_t *host_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
tai_object_id_t m_id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
if ( g_mux->get_mapping(module_id, &m_adapter, &m_id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
tai_object_id_t id;
|
||||
auto ret = m_adapter->create_host_interface(&id, m_id, attr_count, attr_list);
|
||||
if ( ret != TAI_STATUS_SUCCESS ) {
|
||||
return ret;
|
||||
}
|
||||
if ( g_mux->create_mapping(host_interface_id, m_adapter, id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::remove_host_interface(
|
||||
_In_ tai_object_id_t host_interface_id) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(host_interface_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
auto ret = m_adapter->remove_host_interface(id);
|
||||
if ( ret != TAI_STATUS_SUCCESS ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( g_mux->remove_mapping(host_interface_id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::set_host_interface_attributes(_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(host_interface_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_adapter->set_host_interface_attributes(id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::get_host_interface_attributes(_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(host_interface_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_adapter->get_host_interface_attributes(id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::create_network_interface(
|
||||
_Out_ tai_object_id_t *network_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
tai_object_id_t m_id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
if ( g_mux->get_mapping(module_id, &m_adapter, &m_id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
tai_object_id_t id;
|
||||
auto ret = m_adapter->create_network_interface(&id, m_id, attr_count, attr_list);
|
||||
if ( ret != TAI_STATUS_SUCCESS ) {
|
||||
return ret;
|
||||
}
|
||||
if ( g_mux->create_mapping(network_interface_id, m_adapter, id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::remove_network_interface(
|
||||
_In_ tai_object_id_t network_interface_id) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(network_interface_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
auto ret = m_adapter->remove_network_interface(id);
|
||||
if ( ret != TAI_STATUS_SUCCESS ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( g_mux->remove_mapping(network_interface_id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::set_network_interface_attributes(_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(network_interface_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_adapter->set_network_interface_attributes(id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::get_network_interface_attributes(_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(network_interface_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_adapter->get_network_interface_attributes(id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::create_module(
|
||||
_Out_ tai_object_id_t *module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list,
|
||||
_In_ tai_module_notification_t *notifications) {
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
auto mod_addr = find_attribute_in_list(TAI_MODULE_ATTR_LOCATION, attr_count, attr_list);
|
||||
if ( mod_addr == nullptr ) {
|
||||
return TAI_STATUS_MANDATORY_ATTRIBUTE_MISSING;
|
||||
}
|
||||
|
||||
const std::string location(mod_addr->charlist.list);
|
||||
|
||||
auto m_adapter = g_mux->get_module_adapter(location);
|
||||
|
||||
if ( m_adapter == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
tai_object_id_t id;
|
||||
|
||||
auto ret = m_adapter->create_module(&id, attr_count, attr_list, notifications);
|
||||
if ( ret != TAI_STATUS_SUCCESS ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( g_mux->create_mapping(module_id, m_adapter, id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::remove_module(_In_ tai_object_id_t module_id) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(module_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
auto ret = m_adapter->remove_module(id);
|
||||
if ( ret != TAI_STATUS_SUCCESS ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( g_mux->remove_mapping(module_id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::set_module_attributes(_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(module_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_adapter->set_module_attributes(id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
tai_status_t Multiplexier::get_module_attributes(_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list) {
|
||||
tai_object_id_t id;
|
||||
ModuleAdapter *m_adapter;
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if ( g_mux->get_mapping(module_id, &m_adapter, &id) != 0 ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return m_adapter->get_module_attributes(id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
Multiplexier* create_mux(platform_adapter_t pa_kind, uint64_t flags, const tai_service_method_table_t* services) {
|
||||
try {
|
||||
return new Multiplexier(pa_kind, flags, services);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
148
tai_mux/mux.hpp
Normal file
148
tai_mux/mux.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#ifndef __MUX_HPP__
|
||||
#define __MUX_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include "platform_adapter.hpp"
|
||||
#include "static_platform_adapter.hpp"
|
||||
#include "module_adapter.hpp"
|
||||
#include "tai.h"
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
|
||||
class OIDAllocator {
|
||||
public:
|
||||
tai_object_id_t next() {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if ( !m_bitset.test(i) ) {
|
||||
m_bitset.set(i);
|
||||
return tai_object_id_t(i);
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("OID max reach");
|
||||
}
|
||||
void free(tai_object_id_t oid) {
|
||||
m_bitset.reset(oid);
|
||||
}
|
||||
private:
|
||||
std::bitset<256> m_bitset;
|
||||
};
|
||||
|
||||
// singleton
|
||||
class Multiplexier {
|
||||
public:
|
||||
Multiplexier(platform_adapter_t pa_kind, uint64_t flags, const tai_service_method_table_t* services) {
|
||||
switch ( pa_kind ) {
|
||||
case PLATFORM_ADAPTER_STATIC:
|
||||
m_pa = new StaticPlatformAdapter(flags, services);
|
||||
break;
|
||||
default:
|
||||
std::stringstream ss;
|
||||
ss << "unsupported platform_adapter :" << pa_kind;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
~Multiplexier(){
|
||||
if ( m_pa != nullptr ) {
|
||||
delete m_pa;
|
||||
}
|
||||
}
|
||||
|
||||
ModuleAdapter * get_module_adapter(const std::string& location) {
|
||||
return m_pa->get_module_adapter(location);
|
||||
}
|
||||
|
||||
tai_status_t create_module(
|
||||
_Out_ tai_object_id_t *module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list,
|
||||
_In_ tai_module_notification_t *notifications);
|
||||
|
||||
tai_status_t remove_module(
|
||||
_In_ tai_object_id_t module_id);
|
||||
|
||||
tai_status_t set_module_attributes(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list);
|
||||
|
||||
tai_status_t get_module_attributes(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list);
|
||||
|
||||
tai_status_t create_network_interface(
|
||||
_Out_ tai_object_id_t *network_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list);
|
||||
|
||||
tai_status_t remove_network_interface(
|
||||
_In_ tai_object_id_t network_interface_id);
|
||||
|
||||
tai_status_t set_network_interface_attributes(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list);
|
||||
|
||||
tai_status_t get_network_interface_attributes(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list);
|
||||
|
||||
tai_status_t create_host_interface(
|
||||
_Out_ tai_object_id_t *host_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list);
|
||||
|
||||
tai_status_t remove_host_interface(
|
||||
_In_ tai_object_id_t host_interface_id);
|
||||
|
||||
tai_status_t set_host_interface_attributes(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list);
|
||||
|
||||
tai_status_t get_host_interface_attributes(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list);
|
||||
|
||||
private:
|
||||
Multiplexier(const Multiplexier&){}
|
||||
void operator = (const Multiplexier&){}
|
||||
PlatformAdapter *m_pa;
|
||||
std::map<tai_object_id_t, std::pair<tai_object_id_t, ModuleAdapter* >> m_map;
|
||||
OIDAllocator m_oid_allocator;
|
||||
|
||||
int get_mapping(const tai_object_id_t& id, ModuleAdapter **adapter, tai_object_id_t *real_id) {
|
||||
if ( m_map.find(id) == m_map.end() ) {
|
||||
return -1;
|
||||
}
|
||||
auto pair = m_map[id];
|
||||
*adapter = pair.second;
|
||||
*real_id = pair.first;
|
||||
return 0;
|
||||
};
|
||||
|
||||
int create_mapping(tai_object_id_t *id, ModuleAdapter* adapter, const tai_object_id_t& real_id) {
|
||||
auto value = std::pair<tai_object_id_t, ModuleAdapter*>(real_id, adapter);
|
||||
*id = m_oid_allocator.next();
|
||||
m_map[*id] = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remove_mapping(tai_object_id_t id) {
|
||||
if ( m_map.find(id) == m_map.end() ) {
|
||||
return 0;
|
||||
}
|
||||
m_map.erase(id);
|
||||
m_oid_allocator.free(id);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
Multiplexier* create_mux(platform_adapter_t pa_kind, uint64_t flags, const tai_service_method_table_t* services);
|
||||
#endif
|
||||
1
tai_mux/oopt-tai
Submodule
1
tai_mux/oopt-tai
Submodule
Submodule tai_mux/oopt-tai added at 865afb0201
22
tai_mux/platform_adapter.hpp
Normal file
22
tai_mux/platform_adapter.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __PLATFORM_ADAPTER_HPP__
|
||||
#define __PLATFORM_ADAPTER_HPP__
|
||||
|
||||
#include <string>
|
||||
|
||||
class ModuleAdapter;
|
||||
|
||||
enum platform_adapter_t {
|
||||
PLATFORM_ADAPTER_UNKNOWN,
|
||||
PLATFORM_ADAPTER_STATIC,
|
||||
};
|
||||
|
||||
class PlatformAdapter {
|
||||
public:
|
||||
virtual ModuleAdapter* get_module_adapter(const std::string& location) = 0;
|
||||
PlatformAdapter(){}
|
||||
private:
|
||||
PlatformAdapter(const PlatformAdapter&){}
|
||||
void operator = (const PlatformAdapter&){}
|
||||
};
|
||||
|
||||
#endif
|
||||
44
tai_mux/static_platform_adapter.cpp
Normal file
44
tai_mux/static_platform_adapter.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "static_platform_adapter.hpp"
|
||||
|
||||
StaticPlatformAdapter::StaticPlatformAdapter(uint64_t flags, const tai_service_method_table_t* services) {
|
||||
std::string config_file = TAI_MUX_STATIC_DEFAULT_CONFIG;
|
||||
auto e = std::getenv(TAI_MUX_STATIC_CONFIG_FILE.c_str());
|
||||
if ( e != nullptr ) {
|
||||
config_file = e;
|
||||
}
|
||||
|
||||
std::ifstream ifs(config_file);
|
||||
if ( !ifs ) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::istreambuf_iterator<char> it(ifs), last;
|
||||
std::string config(it, last);
|
||||
|
||||
std::map<uint64_t, ModuleAdapter*> map;
|
||||
auto c = json::parse(config);
|
||||
|
||||
for ( json::iterator it = c.begin(); it != c.end(); ++it ) {
|
||||
auto location = it.key();
|
||||
auto lib = it.value().get<std::string>();
|
||||
auto dl = ModuleAdapter::dl_address(lib);
|
||||
ModuleAdapter *ma = nullptr;
|
||||
if ( dl == 0 ) {
|
||||
ma = new ModuleAdapter(lib, flags, &m_services);
|
||||
dl = ModuleAdapter::dl_address(lib);
|
||||
map[dl] = ma;
|
||||
} else {
|
||||
ma = map[dl];
|
||||
}
|
||||
m_ma_map[location] = ma;
|
||||
if ( services != nullptr && services->module_presence != nullptr ) {
|
||||
services->module_presence(true, const_cast<char*>(location.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StaticPlatformAdapter::~StaticPlatformAdapter() {
|
||||
for ( auto& pair : m_ma_map ) {
|
||||
delete pair.second;
|
||||
}
|
||||
}
|
||||
33
tai_mux/static_platform_adapter.hpp
Normal file
33
tai_mux/static_platform_adapter.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __STATIC_PLATFORM_ADAPTER_HPP__
|
||||
#define __STATIC_PLATFORM_ADAPTER_HPP__
|
||||
|
||||
#include <thread>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "platform_adapter.hpp"
|
||||
#include "module_adapter.hpp"
|
||||
#include "tai.h"
|
||||
#include "json.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
const std::string TAI_MUX_STATIC_CONFIG_FILE = "TAI_MUX_STATIC_CONFIG_FILE";
|
||||
const std::string TAI_MUX_STATIC_DEFAULT_CONFIG = "/etc/tai/mux/static.json";
|
||||
|
||||
class StaticPlatformAdapter : public PlatformAdapter {
|
||||
public:
|
||||
StaticPlatformAdapter(uint64_t flags, const tai_service_method_table_t* services);
|
||||
~StaticPlatformAdapter();
|
||||
ModuleAdapter* get_module_adapter(const std::string& location) {
|
||||
return m_ma_map[location];
|
||||
};
|
||||
private:
|
||||
std::map<std::string, ModuleAdapter*> m_ma_map;
|
||||
std::thread m_th;
|
||||
tai_service_method_table_t m_services;
|
||||
};
|
||||
|
||||
#endif
|
||||
225
tai_mux/tai.cpp
Normal file
225
tai_mux/tai.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
#include "mux.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
extern Multiplexier *g_mux;
|
||||
|
||||
const std::string PLATFORM_ADAPTER = "TAI_MUX_PLATFORM_ADAPTER";
|
||||
|
||||
#ifndef DEFAULT_PLATFORM_ADAPTER
|
||||
#define DEFAULT_PLATFORM_ADAPTER "static"
|
||||
#endif
|
||||
|
||||
tai_status_t tai_api_initialize(_In_ uint64_t flags,
|
||||
_In_ const tai_service_method_table_t* services)
|
||||
{
|
||||
if ( g_mux != nullptr ) {
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
auto pa = std::getenv(PLATFORM_ADAPTER.c_str());
|
||||
std::string pa_name;
|
||||
if ( pa == nullptr ) {
|
||||
pa_name = DEFAULT_PLATFORM_ADAPTER;
|
||||
} else {
|
||||
pa_name = std::string(pa);
|
||||
}
|
||||
platform_adapter_t pa_kind;
|
||||
if ( pa_name == "static" ) {
|
||||
pa_kind = PLATFORM_ADAPTER_STATIC;
|
||||
}
|
||||
g_mux = create_mux(pa_kind, flags, services);
|
||||
if ( g_mux == nullptr ) {
|
||||
return TAI_STATUS_FAILURE;
|
||||
}
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t tai_api_uninitialize(void) {
|
||||
if ( g_mux != nullptr ) {
|
||||
delete g_mux;
|
||||
g_mux = nullptr;
|
||||
}
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static tai_status_t mux_create_host_interface(
|
||||
_Out_ tai_object_id_t *host_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
return g_mux->create_host_interface(host_interface_id, module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_remove_host_interface(_In_ tai_object_id_t host_interface_id)
|
||||
{
|
||||
return g_mux->remove_host_interface(host_interface_id);
|
||||
}
|
||||
|
||||
static tai_status_t mux_set_host_interface_attributes(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list)
|
||||
{
|
||||
return g_mux->set_host_interface_attributes(host_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_set_host_interface_attribute(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_In_ const tai_attribute_t *attr)
|
||||
{
|
||||
return g_mux->set_host_interface_attributes(host_interface_id, 1, attr);
|
||||
}
|
||||
|
||||
static tai_status_t mux_get_host_interface_attributes(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list)
|
||||
{
|
||||
return g_mux->get_host_interface_attributes(host_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_get_host_interface_attribute(
|
||||
_In_ tai_object_id_t host_interface_id,
|
||||
_Out_ tai_attribute_t *attr)
|
||||
{
|
||||
return g_mux->get_host_interface_attributes(host_interface_id, 1, attr);
|
||||
}
|
||||
|
||||
tai_host_interface_api_t mux_host_interface_api = {
|
||||
.create_host_interface = mux_create_host_interface,
|
||||
.remove_host_interface = mux_remove_host_interface,
|
||||
.set_host_interface_attribute = mux_set_host_interface_attribute,
|
||||
.set_host_interface_attributes = mux_set_host_interface_attributes,
|
||||
.get_host_interface_attribute = mux_get_host_interface_attribute,
|
||||
.get_host_interface_attributes = mux_get_host_interface_attributes
|
||||
};
|
||||
|
||||
static tai_status_t mux_create_network_interface(
|
||||
_Out_ tai_object_id_t *network_interface_id,
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list) {
|
||||
return g_mux->create_network_interface(network_interface_id, module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_remove_network_interface(_In_ tai_object_id_t network_interface_id)
|
||||
{
|
||||
return g_mux->remove_network_interface(network_interface_id);
|
||||
}
|
||||
|
||||
static tai_status_t mux_set_network_interface_attributes(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list)
|
||||
{
|
||||
return g_mux->set_network_interface_attributes(network_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_set_network_interface_attribute(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_In_ const tai_attribute_t *attr)
|
||||
{
|
||||
return g_mux->set_network_interface_attributes(network_interface_id, 1, attr);
|
||||
}
|
||||
|
||||
static tai_status_t mux_get_network_interface_attributes(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list)
|
||||
{
|
||||
return g_mux->get_network_interface_attributes(network_interface_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_get_network_interface_attribute(
|
||||
_In_ tai_object_id_t network_interface_id,
|
||||
_Out_ tai_attribute_t *attr)
|
||||
{
|
||||
return g_mux->get_network_interface_attributes(network_interface_id, 1, attr);
|
||||
}
|
||||
|
||||
tai_network_interface_api_t mux_network_interface_api = {
|
||||
.create_network_interface = mux_create_network_interface,
|
||||
.remove_network_interface = mux_remove_network_interface,
|
||||
.set_network_interface_attribute = mux_set_network_interface_attribute,
|
||||
.set_network_interface_attributes = mux_set_network_interface_attributes,
|
||||
.get_network_interface_attribute = mux_get_network_interface_attribute,
|
||||
.get_network_interface_attributes = mux_get_network_interface_attributes
|
||||
};
|
||||
|
||||
static tai_status_t mux_create_module(
|
||||
_Out_ tai_object_id_t *module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list,
|
||||
_In_ tai_module_notification_t *notifications)
|
||||
{
|
||||
return g_mux->create_module(module_id, attr_count, attr_list, notifications);
|
||||
}
|
||||
|
||||
static tai_status_t mux_remove_module(_In_ tai_object_id_t module_id)
|
||||
{
|
||||
return g_mux->remove_module(module_id);
|
||||
}
|
||||
|
||||
static tai_status_t mux_set_module_attributes(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list)
|
||||
{
|
||||
return g_mux->set_module_attributes(module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_set_module_attribute(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ const tai_attribute_t *attr)
|
||||
{
|
||||
return mux_set_module_attributes(module_id, 1, attr);
|
||||
}
|
||||
|
||||
static tai_status_t mux_get_module_attributes(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_In_ uint32_t attr_count,
|
||||
_Out_ tai_attribute_t *attr_list)
|
||||
{
|
||||
return g_mux->get_module_attributes(module_id, attr_count, attr_list);
|
||||
}
|
||||
|
||||
static tai_status_t mux_get_module_attribute(
|
||||
_In_ tai_object_id_t module_id,
|
||||
_Out_ tai_attribute_t *attr)
|
||||
{
|
||||
return mux_get_module_attributes(module_id, 1, attr);
|
||||
}
|
||||
|
||||
tai_module_api_t mux_module_api = {
|
||||
.create_module = mux_create_module,
|
||||
.remove_module = mux_remove_module,
|
||||
.set_module_attribute = mux_set_module_attribute,
|
||||
.set_module_attributes = mux_set_module_attributes,
|
||||
.get_module_attribute = mux_get_module_attribute,
|
||||
.get_module_attributes = mux_get_module_attributes
|
||||
};
|
||||
|
||||
tai_status_t tai_api_query(_In_ tai_api_t tai_api_id,
|
||||
_Out_ void** api_method_table)
|
||||
{
|
||||
if ( api_method_table == nullptr ) {
|
||||
return TAI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
switch (tai_api_id) {
|
||||
case TAI_API_MODULE:
|
||||
*api_method_table = &mux_module_api;
|
||||
break;
|
||||
case TAI_API_HOSTIF:
|
||||
*api_method_table = &mux_host_interface_api;
|
||||
break;
|
||||
case TAI_API_NETWORKIF:
|
||||
*api_method_table = &mux_network_interface_api;
|
||||
break;
|
||||
default:
|
||||
return TAI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
tai_status_t tai_log_set(tai_api_t tai_api_id, tai_log_level_t log_level) {
|
||||
return TAI_STATUS_SUCCESS;
|
||||
}
|
||||
16
tai_mux/test/Makefile
Normal file
16
tai_mux/test/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
CC := g++
|
||||
CFLAGS := -std=c++11
|
||||
INCLUDES := -I ../oopt-tai/inc
|
||||
|
||||
test: test.cpp libtai.so libtai-stub.so
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ -L . -ltai
|
||||
|
||||
libtai.so:
|
||||
ln -s ../libtai-mux.so $@
|
||||
|
||||
libtai-stub.so:
|
||||
$(MAKE) -C ../oopt-tai/stub/
|
||||
ln -s ../oopt-tai/stub/libtai.so $@
|
||||
|
||||
clean:
|
||||
-rm test
|
||||
3
tai_mux/test/run.sh
Executable file
3
tai_mux/test/run.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
LD_LIBRARY_PATH=. TAI_MUX_PLATFORM_ADAPTER=static TAI_MUX_STATIC_CONFIG_FILE=./static.json $1 ./test
|
||||
4
tai_mux/test/static.json
Normal file
4
tai_mux/test/static.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"1": "libtai-stub.so",
|
||||
"2": "libtai-stub.so"
|
||||
}
|
||||
183
tai_mux/test/test.cpp
Normal file
183
tai_mux/test/test.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <map>
|
||||
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
#include "unistd.h"
|
||||
|
||||
#include "tai.h"
|
||||
|
||||
tai_module_api_t *module_api;
|
||||
tai_network_interface_api_t *netif_api;
|
||||
tai_host_interface_api_t *hostif_api;
|
||||
|
||||
tai_module_notification_t notification = {0};
|
||||
|
||||
int fd;
|
||||
std::queue<std::pair<bool, std::string>> q;
|
||||
std::mutex m;
|
||||
|
||||
class module {
|
||||
public:
|
||||
module(tai_object_id_t id) : m_id(id) {
|
||||
std::vector<tai_attribute_t> list;
|
||||
tai_attribute_t attr;
|
||||
attr.id = TAI_MODULE_ATTR_NUM_HOST_INTERFACES;
|
||||
list.push_back(attr);
|
||||
attr.id = TAI_MODULE_ATTR_NUM_NETWORK_INTERFACES;
|
||||
list.push_back(attr);
|
||||
auto status = module_api->get_module_attributes(id, list.size(), list.data());
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
throw std::runtime_error("faile to get attribute");
|
||||
}
|
||||
std::cout << "num hostif: " << list[0].value.u32 << std::endl;
|
||||
std::cout << "num netif: " << list[1].value.u32 << std::endl;
|
||||
create_hostif(list[0].value.u32);
|
||||
create_netif(list[1].value.u32);
|
||||
}
|
||||
private:
|
||||
tai_object_id_t m_id;
|
||||
std::vector<tai_object_id_t> netifs;
|
||||
std::vector<tai_object_id_t> hostifs;
|
||||
int create_hostif(uint32_t num);
|
||||
int create_netif(uint32_t num);
|
||||
};
|
||||
|
||||
int module::create_netif(uint32_t num) {
|
||||
for ( int i = 0; i < num; i++ ) {
|
||||
tai_object_id_t id;
|
||||
std::vector<tai_attribute_t> list;
|
||||
tai_attribute_t attr;
|
||||
attr.id = TAI_NETWORK_INTERFACE_ATTR_INDEX;
|
||||
attr.value.u32 = i;
|
||||
list.push_back(attr);
|
||||
auto status = netif_api->create_network_interface(&id, m_id, list.size(), list.data());
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
throw std::runtime_error("failed to create network interface");
|
||||
}
|
||||
std::cout << "netif: " << id << std::endl;
|
||||
netifs.push_back(id);
|
||||
|
||||
list.clear();
|
||||
|
||||
attr.id = TAI_NETWORK_INTERFACE_ATTR_TX_ENABLE;
|
||||
attr.value.booldata = true;
|
||||
list.push_back(attr);
|
||||
|
||||
attr.id = TAI_NETWORK_INTERFACE_ATTR_TX_CHANNEL;
|
||||
attr.value.u16 = 10;
|
||||
list.push_back(attr);
|
||||
|
||||
attr.id = TAI_NETWORK_INTERFACE_ATTR_TX_GRID_SPACING;
|
||||
attr.value.u32 = TAI_NETWORK_INTERFACE_TX_GRID_SPACING_100_GHZ;
|
||||
list.push_back(attr);
|
||||
|
||||
attr.id = TAI_NETWORK_INTERFACE_ATTR_MODULATION_FORMAT;
|
||||
attr.value.u32 = TAI_NETWORK_INTERFACE_MODULATION_FORMAT_DP_16_QAM;
|
||||
list.push_back(attr);
|
||||
|
||||
status = netif_api->set_network_interface_attributes(id, list.size(), list.data());
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
throw std::runtime_error("failed to set netif attribute");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int module::create_hostif(uint32_t num) {
|
||||
for ( int i = 0; i < num; i++ ) {
|
||||
tai_object_id_t id;
|
||||
std::vector<tai_attribute_t> list;
|
||||
tai_attribute_t attr;
|
||||
attr.id = TAI_HOST_INTERFACE_ATTR_INDEX;
|
||||
attr.value.u32 = i;
|
||||
list.push_back(attr);
|
||||
auto status = hostif_api->create_host_interface(&id, m_id, list.size(), list.data());
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
throw std::runtime_error("failed to create host interface");
|
||||
}
|
||||
std::cout << "hostif: " << id << std::endl;
|
||||
hostifs.push_back(id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<tai_object_id_t, module*> modules;
|
||||
|
||||
void module_presence(bool present, char* location) {
|
||||
uint64_t v;
|
||||
std::lock_guard<std::mutex> g(m);
|
||||
q.push(std::pair<bool, std::string>(present, std::string(location)));
|
||||
write(fd, &v, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
tai_status_t create_module(const std::string& location, tai_object_id_t& m_id) {
|
||||
std::vector<tai_attribute_t> list;
|
||||
tai_attribute_t attr;
|
||||
attr.id = TAI_MODULE_ATTR_LOCATION;
|
||||
attr.value.charlist.count = location.size();
|
||||
attr.value.charlist.list = (char*)location.c_str();
|
||||
list.push_back(attr);
|
||||
return module_api->create_module(&m_id, list.size(), list.data(), ¬ification);
|
||||
}
|
||||
|
||||
int main() {
|
||||
tai_log_set(tai_api_t(0), TAI_LOG_LEVEL_INFO);
|
||||
|
||||
tai_service_method_table_t services;
|
||||
|
||||
fd = eventfd(0, 0);
|
||||
|
||||
services.module_presence = module_presence;
|
||||
|
||||
auto status = tai_api_initialize(0, &services);
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
std::cout << "failed to init" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = tai_api_query(TAI_API_MODULE, (void **)(&module_api));
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = tai_api_query(TAI_API_NETWORKIF, (void **)(&netif_api));
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = tai_api_query(TAI_API_HOSTIF, (void **)(&hostif_api));
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
uint64_t v;
|
||||
read(fd, &v, sizeof(uint64_t));
|
||||
{
|
||||
std::lock_guard<std::mutex> g(m);
|
||||
while ( ! q.empty() ) {
|
||||
auto p = q.front();
|
||||
std::cout << "present: " << p.first << ", loc: " << p.second << std::endl;
|
||||
if ( p.first ) {
|
||||
tai_object_id_t m_id = 0;
|
||||
status = create_module(p.second, m_id);
|
||||
if ( status != TAI_STATUS_SUCCESS ) {
|
||||
std::cerr << "failed to create module: " << status << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << "module id: " << m_id << std::endl;
|
||||
modules[m_id] = new module(m_id);
|
||||
}
|
||||
q.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user