├── test ├── README.md ├── zeta-aca-test_controllerScript │ ├── README.md │ └── data │ │ ├── zeta_data.json │ │ └── zeta_data_sdn.json ├── CMakeLists.txt ├── gtest │ └── aca_test_on_demand.cpp └── travis_test │ └── build_2_container.sh ├── docs ├── images │ ├── Agent_dhcp.jpg │ ├── Agent_v2.jpg │ ├── Agent_flow1.JPG │ ├── Agent_flow2.JPG │ ├── Agent_diagram.JPG │ ├── ovs_components.png │ ├── Agent_components.jpg │ ├── communication_alcor.jpg │ ├── gateway_direct_path.jpg │ ├── Experimental_topology.JPG │ ├── Zeta_environment_setup.jpg │ ├── communication_neutron.jpg │ ├── zeta_packet_processing.jpg │ ├── Agent_ovs_communication.jpg │ ├── zeta_integration_example.jpg │ ├── Agent_unified_flow_manager.jpg │ └── zeta_integration_high_level.jpg ├── Understanding_DHCP.pdf ├── logs │ ├── 50_runs_full_physical.log │ └── 10_runs_summary_container.log ├── compute_communication.adoc ├── table_of_content.adoc ├── pending-items.adoc └── mizar_communication.adoc ├── src ├── proto3 │ └── CMakeLists.txt ├── grpc │ └── CMakeLists.txt ├── ovs │ ├── libfluid-msg │ │ ├── util │ │ │ ├── ethaddr.cc │ │ │ └── ipaddr.cc │ │ └── of10 │ │ │ └── of10match.cc │ ├── libfluid-base │ │ ├── OFClient.cc │ │ ├── OFConnection.cc │ │ ├── base │ │ │ └── EventLoop.cc │ │ ├── TLS.cc │ │ └── OFServerSettings.cc │ └── aca_ovs_control.cpp ├── comm │ ├── aca_message_producer.cpp │ ├── aca_message_pulsar_producer.cpp │ └── aca_grpc_client.cpp └── CMakeLists.txt ├── SCHEDULE.md ├── CMakeLists.txt ├── include ├── hashmap │ ├── README.md │ ├── LICENSE │ └── HashMap.h ├── libfluid-base │ ├── TLS.hh │ ├── base │ │ ├── BaseOFClient.hh │ │ ├── config.h │ │ ├── EventLoop.hh │ │ └── BaseOFServer.hh │ └── OFClient.hh ├── libfluid-msg │ ├── util │ │ ├── ethaddr.hh │ │ └── ipaddr.hh │ ├── of10 │ │ └── of10match.hh │ └── ofcommon │ │ └── action.hh ├── aca_config.h ├── aca_dhcp_programming_if.h ├── aca_grpc_client.h ├── aca_oam_port_manager.h ├── aca_message_consumer.h ├── aca_message_producer.h ├── aca_async_grpc_server.h ├── aca_message_pulsar_producer.h ├── aca_dataplane_mizar.h ├── aca_comm_mgr.h ├── aca_net_config.h ├── aca_dhcp_state_handler.h ├── aca_vlan_manager.h ├── aca_dataplane_ovs.h ├── aca_message_pulsar_consumer.h ├── of_message.h ├── aca_net_programming_if.h ├── aca_ovs_l2_programmer.h ├── aca_zeta_oam_server.h ├── aca_zeta_programming.h ├── of_controller.h ├── aca_ovs_l3_programmer.h └── aca_arp_responder.h ├── LICENSE ├── etc └── k8s │ ├── images │ ├── scripts │ │ ├── aca-start.sh │ │ └── aca-node-init.sh │ └── Dockerfile │ ├── aca-daemonset.yaml │ └── aca-cluster_init.sh ├── .gitmodules ├── .github └── workflows │ └── acaci.yml ├── .travis.yml ├── .gitignore └── README.md /test/README.md: -------------------------------------------------------------------------------- 1 | # NetworkControlAgent 2 | Next Generation Cloud Networking 3 | 4 | # Summary 5 | Test code folder -------------------------------------------------------------------------------- /docs/images/Agent_dhcp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_dhcp.jpg -------------------------------------------------------------------------------- /docs/images/Agent_v2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_v2.jpg -------------------------------------------------------------------------------- /docs/Understanding_DHCP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/Understanding_DHCP.pdf -------------------------------------------------------------------------------- /docs/images/Agent_flow1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_flow1.JPG -------------------------------------------------------------------------------- /docs/images/Agent_flow2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_flow2.JPG -------------------------------------------------------------------------------- /docs/images/Agent_diagram.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_diagram.JPG -------------------------------------------------------------------------------- /docs/images/ovs_components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/ovs_components.png -------------------------------------------------------------------------------- /docs/images/Agent_components.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_components.jpg -------------------------------------------------------------------------------- /docs/images/communication_alcor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/communication_alcor.jpg -------------------------------------------------------------------------------- /docs/images/gateway_direct_path.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/gateway_direct_path.jpg -------------------------------------------------------------------------------- /docs/logs/50_runs_full_physical.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/logs/50_runs_full_physical.log -------------------------------------------------------------------------------- /docs/images/Experimental_topology.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Experimental_topology.JPG -------------------------------------------------------------------------------- /docs/images/Zeta_environment_setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Zeta_environment_setup.jpg -------------------------------------------------------------------------------- /docs/images/communication_neutron.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/communication_neutron.jpg -------------------------------------------------------------------------------- /docs/images/zeta_packet_processing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/zeta_packet_processing.jpg -------------------------------------------------------------------------------- /docs/images/Agent_ovs_communication.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_ovs_communication.jpg -------------------------------------------------------------------------------- /docs/images/zeta_integration_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/zeta_integration_example.jpg -------------------------------------------------------------------------------- /docs/images/Agent_unified_flow_manager.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/Agent_unified_flow_manager.jpg -------------------------------------------------------------------------------- /docs/images/zeta_integration_high_level.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurewei-cloud/alcor-control-agent/HEAD/docs/images/zeta_integration_high_level.jpg -------------------------------------------------------------------------------- /src/proto3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE(FindProtobuf) 2 | FIND_PACKAGE(Protobuf REQUIRED) 3 | INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) 4 | file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/../../alcor/schema/proto3/*.proto") 5 | PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles}) 6 | ADD_LIBRARY(proto ${ProtoHeaders} ${ProtoSources}) -------------------------------------------------------------------------------- /docs/compute_communication.adoc: -------------------------------------------------------------------------------- 1 | = Interface with Arktos 2 | Eric Li 3 | v0.1, 2020-03-20 4 | :toc: right 5 | 6 | The below diagrams shows the interaction between components and work flow for Arktos, Alcor and Mizar. 7 | 8 | image::images/Agent_diagram.JPG["Component diagram", width=800, link="images/Agent_diagram.JPG"] 9 | 10 | image::images/Agent_flow1.JPG["Agent flow 1", width=800, link="images/Agent_flow1.JPG"] 11 | 12 | image::images/Agent_flow2.JPG["Agent flow 2", width=800, link="images/Agent_flow2.JPG"] -------------------------------------------------------------------------------- /SCHEDULE.md: -------------------------------------------------------------------------------- 1 | - Basic Functionality (P0 7/31) 2 | - Able to attach transit agent to the corresponding vNIC(veth) 3 | - Able to attach transit switch/router on the physical NIC 4 | - Able to create VPC/Subnet/Endpoint and send traffic between the endpoints on the new dataplane 5 | - listen to messages from network controller through Kafka 6 | - deserialize protobuf messages 7 | - program the transit switch/router/endpoint through transit daemon 8 | - functional test, UT, E2E 9 | 10 | - Scale out/in 11 | 12 | - Transit Placement 13 | 14 | - Disaster recovery (P0 8/30) 15 | - NCA gets error message and do local recovery 16 | - VPC-level recovery 17 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(AlcorControlAgent) 3 | 4 | # CMAKE_BUILD_TYPE can be Debug or Release 5 | set(CMAKE_BUILD_TYPE Debug) 6 | 7 | set(CMAKE_CXX_STANDARD 17) 8 | 9 | # Set the version number. 10 | set(CPPKAFKA_VERSION_MAJOR 0) 11 | set(CPPKAFKA_VERSION_MINOR 3) 12 | set(CPPKAFKA_VERSION_REVISION 1) 13 | set(CPPKAFKA_VERSION "${CPPKAFKA_VERSION_MAJOR}.${CPPKAFKA_VERSION_MINOR}.${CPPKAFKA_VERSION_REVISION}") 14 | set(RDKAFKA_MIN_VERSION 0x00090400) 15 | 16 | #add_compile_options(-O0) # enable no optimization during development 17 | add_compile_options(-Wall -Wextra -pedantic -Wpedantic -Wno-error -Wno-unused-variable -Wno-unused-parameter -Wno-sequence-point -Wno-parentheses -Wno-pedantic -Wno-reorder -Wno-sign-compare) 18 | 19 | add_subdirectory(src) 20 | add_subdirectory(test) 21 | -------------------------------------------------------------------------------- /include/hashmap/README.md: -------------------------------------------------------------------------------- 1 | # hashMap 2 | A concurrent thread-safe hash map implemented in C++. 3 | 4 | Anyone can use the hash-map by simply including the header files in the "inc" folder. 5 | Currently, copy and move of the hash is not supported. 6 | 7 | A main is provided to test the basic scenarios of the hash-map. 8 | 9 | The hash map is implemented as an array of hash buckets. 10 | Each hash bucket is a single linked list of hash nodes and has a mutex associated with it. 11 | Multiple threads can read from the same bucket simulatenously, but only one thread can write 12 | into the same bucket. Since the mutex is per bucket, if multiple threads try to write into different 13 | buckets simulatenously, they will be allowed to do so. This allows some level of concurrency for the hash map. 14 | 15 | The mutex is implemented as "std::shared_timed_mutex" from C++14 and uses "std::unique_lock" from C++11 for writes 16 | and "std::shared_lock" from C++14 for reading from a bucket. 17 | -------------------------------------------------------------------------------- /docs/table_of_content.adoc: -------------------------------------------------------------------------------- 1 | ## Table of Content 2 | 3 | ### Design 4 | 5 | * xref:high_level_design.adoc[High Level Design] 6 | * xref:major_components.adoc[Major Components] 7 | * Key System Flows 8 | * https://github.com/futurewei-cloud/alcor/blob/master/docs/visionary_design/table_of_content.adoc[Alcor Controller Design] 9 | // * xref:comm.adoc[Controller and Control Agent Communication] 10 | * xref:compute_communication.adoc [Communication Protocol with Arktos Compute] 11 | * https://github.com/futurewei-cloud/alcor/blob/master/docs/visionary_design/dataplane_abstraction.adoc[Dataplane Abstraction] 12 | ** xref:ovs_communication.adoc[Integration with OVS] 13 | ** xref:mizar_communication.adoc[Integration with Mizar] 14 | * xref:dhcp_programming.adoc [DHCP Programming Design] 15 | 16 | ### Development and Testing 17 | * xref:../src/README.md[Getting Started] 18 | 19 | // ### Test 20 | // * xref:../test/e2eTestSetup.adoc[E2E Test Setup 1] 21 | // * xref:../test/e2eTestSetup_small.adoc[E2E Test Setup 2] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Futurewei Cloud 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /include/hashmap/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kaushik Basu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /etc/k8s/images/scripts/aca-start.sh: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #!/bin/bash 16 | 17 | nsenter -t 1 -m -u -n -i /aca_build/bin/AlcorControlAgent -d -m -------------------------------------------------------------------------------- /etc/k8s/images/Dockerfile: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | FROM debian 16 | COPY scripts/aca-start.sh / 17 | RUN chmod u+x aca-start.sh 18 | CMD ["./aca-start.sh"] 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | [submodule "alcor"] 16 | path = alcor 17 | url = https://github.com/futurewei-cloud/alcor.git 18 | ignore = untracked 19 | -------------------------------------------------------------------------------- /include/libfluid-base/TLS.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /** @file Functions for secure communication using SSL */ 17 | #ifndef __SSL_IMPL_HH__ 18 | #define __SSL_IMPL_HH__ 19 | 20 | namespace fluid_base { 21 | /** SSL implementation pointer for internal library use. */ 22 | extern void* tls_obj; 23 | 24 | /** Initialize SSL parameters. You must call this function before 25 | asking any object to communicate in a secure manner. 26 | 27 | @param cert The controller's certificate signed by a CA 28 | @param privkey The controller's private key to be used with the 29 | certificate 30 | @param trustedcert A CA certificate that signs certificates of trusted 31 | switches */ 32 | void libfluid_tls_init(const char* cert, const char* privkey, const char* trustedcert); 33 | 34 | /** Free SSL data. You must call this function after you don't need secure 35 | communication anymore. */ 36 | void libfluid_tls_clear(); 37 | } 38 | 39 | #endif -------------------------------------------------------------------------------- /etc/k8s/aca-daemonset.yaml: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | apiVersion: apps/v1 16 | kind: DaemonSet 17 | metadata: 18 | name: aca 19 | namespace: default 20 | spec: 21 | selector: 22 | matchLabels: 23 | job: aca 24 | template: 25 | metadata: 26 | labels: 27 | job: aca 28 | spec: 29 | hostPID: true 30 | restartPolicy: Always 31 | containers: 32 | - image: fwnetworking/aca:aca 33 | name: aca 34 | securityContext: 35 | privileged: true 36 | -------------------------------------------------------------------------------- /.github/workflows/acaci.yml: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | name: Agent Build CI 16 | 17 | on: 18 | push: 19 | paths: 20 | - '**' 21 | - '!docs/**' 22 | pull_request: 23 | paths: 24 | - '**' 25 | - '!docs/**' 26 | 27 | jobs: 28 | 29 | build: 30 | 31 | runs-on: ubuntu-latest 32 | 33 | steps: 34 | - uses: actions/checkout@v1 35 | with: 36 | token: ${{ secrets.ACCESS_TOKEN }} 37 | submodules: true 38 | - name: Build Alcor Control Agent 39 | run: ./build/build.sh 40 | working-directory: . 41 | -------------------------------------------------------------------------------- /include/libfluid-msg/util/ethaddr.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #ifndef __MACADDRESS_H__ 17 | #define __MACADDRESS_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace fluid_msg{ 28 | 29 | class EthAddress { 30 | public: 31 | EthAddress(); 32 | EthAddress(const char* address); 33 | EthAddress(const std::string &address); 34 | EthAddress(const EthAddress &other); 35 | EthAddress(const uint8_t* data); 36 | 37 | EthAddress& operator=(const EthAddress &other); 38 | bool operator==(const EthAddress &other) const; 39 | std::string to_string() const; 40 | void set_data(uint8_t* array); 41 | uint8_t* get_data(){return this->data;} 42 | static uint8_t* data_from_string(const std::string &address); 43 | 44 | private: 45 | uint8_t data[6]; 46 | // void data_from_string(const std::string &address); 47 | }; 48 | } 49 | #endif /* __MACADDRESS_H__ */ 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/grpc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Find Protobuf installation 3 | # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. 4 | set(protobuf_MODULE_COMPATIBLE TRUE) 5 | find_package(Protobuf CONFIG REQUIRED) 6 | message(STATUS "Using protobuf ${protobuf_VERSION}") 7 | 8 | set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) 9 | set(_PROTOBUF_PROTOC $) 10 | 11 | # Find gRPC installation 12 | # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. 13 | find_package(gRPC CONFIG REQUIRED) 14 | message(STATUS "Using gRPC ${gRPC_VERSION}") 15 | 16 | set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure) 17 | set(_GRPC_CPP_PLUGIN_EXECUTABLE $) 18 | 19 | # Proto file 20 | get_filename_component(aca_proto "${CMAKE_CURRENT_SOURCE_DIR}/../../alcor/schema/proto3/*.proto" ABSOLUTE) 21 | get_filename_component(aca_proto_path "${aca_proto}" PATH) 22 | 23 | set(aca_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/goalstateprovisioner.pb.cc") 24 | set(aca_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/goalstateprovisioner.pb.h") 25 | set(aca_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/goalstateprovisioner.grpc.pb.cc") 26 | set(aca_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/goalstateprovisioner.grpc.pb.h") 27 | add_custom_command( 28 | OUTPUT "${aca_proto_srcs}" "${aca_proto_hdrs}" "${aca_grpc_srcs}" "${aca_grpc_hdrs}" 29 | COMMAND ${_PROTOBUF_PROTOC} 30 | ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" 31 | --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" 32 | -I "${aca_proto_path}" 33 | --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" 34 | "${aca_proto}" 35 | DEPENDS "${aca_proto}") 36 | 37 | # Include generated *.pb.h files 38 | include_directories("${CMAKE_CURRENT_BINARY_DIR}") 39 | 40 | ADD_LIBRARY(grpc ${aca_proto_srcs} ${aca_proto_hdrs} ${aca_grpc_srcs} ${aca_grpc_hdrs}) -------------------------------------------------------------------------------- /src/ovs/libfluid-msg/util/ethaddr.cc: -------------------------------------------------------------------------------- 1 | #include "libfluid-msg/util/ethaddr.hh" 2 | #include 3 | 4 | namespace fluid_msg{ 5 | 6 | EthAddress::EthAddress():data(){ 7 | } 8 | 9 | EthAddress::EthAddress(const char* address) { 10 | std::string sadress(address); 11 | memcpy(this->data, data_from_string(address), IFHWADDRLEN); 12 | } 13 | 14 | EthAddress::EthAddress(const std::string &address) { 15 | memcpy(this->data, data_from_string(address),IFHWADDRLEN); 16 | } 17 | 18 | EthAddress::EthAddress(const uint8_t* data) { 19 | memcpy(this->data, data, IFHWADDRLEN); 20 | } 21 | 22 | EthAddress::EthAddress(const EthAddress &other) { 23 | memcpy(this->data, other.data, IFHWADDRLEN); 24 | } 25 | 26 | EthAddress& EthAddress::operator=(const EthAddress &other) { 27 | if (this != &other) { 28 | memcpy(this->data, other.data, IFHWADDRLEN); 29 | } 30 | return *this; 31 | } 32 | 33 | bool EthAddress::operator==(const EthAddress &other) const { 34 | return memcmp(other.data, this->data, IFHWADDRLEN) == 0; 35 | } 36 | 37 | std::string EthAddress::to_string() const { 38 | std::stringstream ss; 39 | ss << std::hex << std::setfill('0'); 40 | for (int i = 0; i < IFHWADDRLEN; i++) { 41 | ss << std::setw(2) << (int) data[i]; 42 | if (i < IFHWADDRLEN - 1) 43 | ss << ':'; 44 | } 45 | 46 | return ss.str(); 47 | } 48 | void EthAddress::set_data(uint8_t* array){ 49 | memcpy(this->data, array, IFHWADDRLEN); 50 | } 51 | 52 | uint8_t* EthAddress::data_from_string(const std::string &address) { 53 | static uint8_t data[6]; 54 | char sc; 55 | int byte; 56 | std::stringstream ss(address); 57 | ss << std::hex; 58 | for (int i = 0; i < IFHWADDRLEN; i++) { 59 | ss >> byte; 60 | ss >> sc; 61 | data[i] = (uint8_t) byte; 62 | } 63 | return data; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /docs/pending-items.adoc: -------------------------------------------------------------------------------- 1 | = OVS Programming Design — Pending Items 2 | Eric Li , Xiaodong Zhang 3 | v0.1, 2020-04-17 4 | :toc: right 5 | 6 | 7 | == Workflow of Network Configuration Programming 8 | 9 | === Router Programming 10 | 11 | Scenario A: 12 | Routing workflow between different EPs in the same subnet on different hosts 13 | [source,c++] 14 | -------------------------------------------------------------------------------- 15 | 1. The packet from virtual machine 1 on the left reaches the br-int via the Linux bridge and is tagged with VLAN ID Tag 16 | 2. Reach br-tun, convert VLAN ID to Tunnel ID, send from VxLAN Tunnel, and reach another compute node 17 | 3. Go through the reverse process on another compute node to reach the virtual machine on the right 18 | -------------------------------------------------------------------------------- 19 | ================================ 20 | Scenario B: 21 | Routing workflow for accessing internet 22 | [source,c++] 23 | -------------------------------------------------------------------------------- 24 | 1. Packet leaves the virtual machine, passes the Linux bridge, arrives at br-int, and is tagged with VLAN ID 25 | 2. Reach br-tun, convert VLAN ID to Tunnel ID 26 | 3. Enter the VxLAN channel from the physical network card 27 | 4. Network card from the VxLAN channel to the Neutron node 28 | 5. Reach the br-tun connected to the physical network card and convert the Tunnel ID to VLAN ID 29 | 6. Reach br-int, then router, router's NAT table will convert fixed IP address to floatiing IP address, and then route to br-ex 30 | 7. Go out from the physical network card connected to br-ex to the external network 31 | -------------------------------------------------------------------------------- 32 | ================================ 33 | Scenario C: 34 | 35 | Accessing an EP from an external network IP is the opposite process. 36 | 37 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | language: c 16 | 17 | dist: bionic 18 | addons: 19 | apt: 20 | packages: 21 | - "python3" 22 | - "python3-pip" 23 | - "python3-setuptools" 24 | - "docker.io" 25 | before_script: 26 | - sudo apt-get update 27 | - sudo systemctl unmask docker.service 28 | - sudo systemctl unmask docker.socket 29 | - sudo systemctl start docker 30 | - sudo systemctl enable docker 31 | - pip3 install docker 32 | # Build ACA 33 | # - ./build/build.sh 34 | 35 | script: 36 | - echo "Compile and run unit test" 37 | - ./test/travis_test/build_2_container.sh compile_and_run_unit_test 38 | - echo "Start ping test" # Commented out due to issue 216 39 | - ./test/travis_test/build_2_container.sh 2_port_test_traffic 40 | 41 | -------------------------------------------------------------------------------- /src/ovs/libfluid-base/OFClient.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "libfluid-base/OFClient.hh" 5 | #include "libfluid-base/base/BaseOFConnection.hh" 6 | #include "libfluid-base/base/BaseOFServer.hh" 7 | #include "libfluid-base/OFConnection.hh" 8 | #include "libfluid-base/OFServer.hh" 9 | #include "libfluid-base/base/of.hh" 10 | 11 | namespace fluid_base { 12 | 13 | OFClient::OFClient( 14 | const std::string& addr, 15 | const bool domainsocket, 16 | const int port, 17 | const bool secure, 18 | const struct OFServerSettings ofsc) : 19 | BaseOFClient(addr, domainsocket, port, secure), 20 | OFConnectionProcessor(this) {} 21 | 22 | OFClient::~OFClient() {} 23 | 24 | bool OFClient::start(bool block) { 25 | return BaseOFClient::start(block); 26 | } 27 | 28 | void OFClient::stop() { 29 | if (conn) { 30 | conn->close(); 31 | } 32 | // Stop BaseOFClient 33 | BaseOFClient::stop(); 34 | } 35 | 36 | void OFClient::set_config(OFServerSettings ofsc) { 37 | OFConnectionProcessor::set_config(ofsc); 38 | } 39 | 40 | void OFClient::base_message_callback(BaseOFConnection* c, void* data, size_t len) { 41 | OFConnectionProcessor::base_message_callback(c, data, len); 42 | } 43 | 44 | void OFClient::free_data(void* data) { 45 | BaseOFClient::free_data(data); 46 | } 47 | 48 | void OFClient::base_connection_callback(BaseOFConnection* c, BaseOFConnection::Event event_type) { 49 | OFConnectionProcessor::base_connection_callback(c, event_type); 50 | if (event_type == BaseOFConnection::EVENT_CLOSED) { 51 | // reconnect 52 | if (!this->connect()) { 53 | fprintf(stderr, "OFClient reconnect failed"); 54 | } else { 55 | fprintf(stderr, "OFClient reconnect success"); 56 | } 57 | } 58 | } 59 | 60 | void OFClient::on_new_conn(OFConnection* cc) { 61 | if (conn) { 62 | conn->close(); 63 | } 64 | conn.reset(cc); 65 | } 66 | } // namespace fluid_base 67 | -------------------------------------------------------------------------------- /include/libfluid-base/base/BaseOFClient.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | 21 | #include "EventLoop.hh" 22 | #include "BaseOFConnection.hh" 23 | 24 | #include 25 | 26 | namespace fluid_base { 27 | 28 | class BaseOFClient : public BaseOFHandler { 29 | public: 30 | BaseOFClient( 31 | const std::string& addr, 32 | const bool domainsocket, 33 | const int port, 34 | const bool secure); 35 | virtual ~BaseOFClient(); 36 | 37 | bool start(bool block = false); 38 | void stop(); 39 | 40 | // BaseOFHandler methods 41 | // virtual void base_connection_callback( 42 | // BaseOFConnection* conn, 43 | // BaseOFConnection::Event event_type) override; 44 | // virtual void base_message_callback(BaseOFConnection* conn, void* data, size_t len); 45 | virtual void free_data(void* data) override; 46 | 47 | protected: 48 | bool connect(); 49 | 50 | private: 51 | const std::string address; 52 | const bool domainsocket; 53 | const int port; 54 | const bool secure; 55 | 56 | bool blocking; 57 | 58 | EventLoop* evloop; 59 | pthread_t evthread; 60 | int nconn; 61 | 62 | class LibEventBaseOFClient; 63 | friend class LibEventBaseOFClient; 64 | LibEventBaseOFClient* m_implementation; 65 | }; 66 | 67 | } // namespace fluid_base -------------------------------------------------------------------------------- /include/libfluid-base/OFClient.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #pragma once 17 | 18 | #include "base/BaseOFConnection.hh" 19 | #include "base/BaseOFClient.hh" 20 | #include "OFServer.hh" 21 | #include "OFConnection.hh" 22 | #include "OFServerSettings.hh" 23 | #include 24 | 25 | namespace fluid_base { 26 | 27 | class OFClient : private BaseOFClient, private OFConnectionProcessor, public OFHandler { 28 | public: 29 | OFClient( 30 | const std::string& addr, 31 | const bool domainsocket, 32 | const int port, 33 | const bool secure, 34 | const struct OFServerSettings ofsc = OFServerSettings()); 35 | virtual ~OFClient(); 36 | 37 | virtual bool start(bool block = false); 38 | 39 | virtual void stop(); 40 | 41 | void set_config(OFServerSettings ofsc); 42 | 43 | // virtual void connection_callback(OFConnection *conn, OFConnection::Event event_type){}; 44 | // virtual void message_callback(OFConnection *conn, uint8_t type, void *data, size_t len){}; 45 | virtual void free_data(void* data) final; 46 | 47 | protected: 48 | void base_message_callback(BaseOFConnection* c, void* data, size_t len) final; 49 | void base_connection_callback(BaseOFConnection* c, BaseOFConnection::Event event_type) final; 50 | 51 | void on_new_conn(OFConnection* cc) final; 52 | 53 | std::unique_ptr conn; 54 | }; 55 | 56 | } // namespace fluid_base -------------------------------------------------------------------------------- /include/aca_config.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_CONFIG_H 16 | #define ACA_CONFIG_H 17 | 18 | #define MAX_PORT_SCAN_RETRY 300 19 | #define PORT_SCAN_SLEEP_INTERVAL 1000 // 1000ms = 1s 20 | 21 | // prefix to indicate it is an Alcor Distributed Router host mac 22 | // (aka host DVR mac) 23 | #define HOST_DVR_MAC_PREFIX "fe:16:11:" 24 | #define HOST_DVR_MAC_MATCH HOST_DVR_MAC_PREFIX + "00:00:00/ff:ff:ff:00:00:00" 25 | 26 | #define DHCP_MSG_OPTS_DNS_LENGTH (5) //max 5 dns address 27 | 28 | #define DEFAULT_MTU 9000 29 | 30 | #define ON_DEMAND_ENTRY_CLEANUP_FREQUENCY_IN_MICROSECONDS 10000000 // 10 seconds 31 | 32 | #define ON_DEMAND_ENTRY_EXPIRATION_IN_MICROSECONDS 10000000 // 10 seconds 33 | 34 | #define REQUEST_UUID_ON_DEMAND_PAYLOAD_MAP_MAX_SIZE 1000000 // one million 35 | 36 | #define REQUEST_UUID_ON_DEMAND_PAYLOAD_MAP_SIZE_CHECK_FREQUENCY_IN_MICROSECONDS \ 37 | 1000 // 10 microsecond, which is 1 millisecond 38 | 39 | #endif // #ifndef ACA_CONFIG_H -------------------------------------------------------------------------------- /include/libfluid-base/base/config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated from config.h.in by configure. */ 2 | /* config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Define to 1 if you have the header file. */ 5 | #define HAVE_DLFCN_H 1 6 | 7 | /* Define to 1 if you have the header file. */ 8 | #define HAVE_INTTYPES_H 1 9 | 10 | /* Define to 1 if you have the header file. */ 11 | #define HAVE_MEMORY_H 1 12 | 13 | /* Define to 1 if you have the header file. */ 14 | #define HAVE_STDINT_H 1 15 | 16 | /* Define to 1 if you have the header file. */ 17 | #define HAVE_STDLIB_H 1 18 | 19 | /* Define to 1 if you have the header file. */ 20 | #define HAVE_STRINGS_H 1 21 | 22 | /* Define to 1 if you have the header file. */ 23 | #define HAVE_STRING_H 1 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #define HAVE_SYS_STAT_H 1 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #define HAVE_SYS_TYPES_H 1 30 | 31 | /* Define if the system has OpenSSL TLS support */ 32 | // for arm, this not work 33 | // #define HAVE_TLS 1 34 | 35 | /* Define to 1 if you have the header file. */ 36 | #define HAVE_UNISTD_H 1 37 | 38 | /* Define to the sub-directory where libtool stores uninstalled libraries. */ 39 | #define LT_OBJDIR ".libs/" 40 | 41 | /* Define to the address where bug reports for this package should be sent. */ 42 | #define PACKAGE_BUGREPORT "allanv@cpqd.com.br" 43 | 44 | /* Define to the full name of this package. */ 45 | #define PACKAGE_NAME "libfluid_base" 46 | 47 | /* Define to the full name and version of this package. */ 48 | #define PACKAGE_STRING "libfluid_base 1.0" 49 | 50 | /* Define to the one symbol short name of this package. */ 51 | #define PACKAGE_TARNAME "libfluid_base" 52 | 53 | /* Define to the home page for this package. */ 54 | #define PACKAGE_URL "http://www.cpqd.com.br/" 55 | 56 | /* Define to the version of this package. */ 57 | #define PACKAGE_VERSION "1.0" 58 | 59 | /* Define to 1 if you have the ANSI C header files. */ 60 | #define STDC_HEADERS 1 61 | -------------------------------------------------------------------------------- /include/libfluid-msg/util/ipaddr.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #ifndef __IPADDRESS_H__ 17 | #define __IPADDRESS_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace fluid_msg{ 27 | 28 | enum {NONE = 0, IPV4 = 4, IPV6 = 6 }; 29 | 30 | class IPAddress { 31 | public: 32 | IPAddress(); 33 | IPAddress(const char* address); 34 | IPAddress(const std::string &address); 35 | IPAddress(const IPAddress &other); 36 | IPAddress(const uint32_t ip_addr); 37 | IPAddress(const uint8_t ip_addr[16]); 38 | IPAddress(const struct in_addr& ip_addr); 39 | IPAddress(const struct in6_addr& ip_addr); 40 | ~IPAddress(){}; 41 | 42 | IPAddress& operator=(const IPAddress& other); 43 | bool operator==(const IPAddress& other) const; 44 | int get_version() const; 45 | void setIPv4(uint32_t address); 46 | void setIPv6(uint8_t address[16]); 47 | uint32_t getIPv4(); 48 | uint8_t * getIPv6(); 49 | static uint32_t IPv4from_string(const std::string &address); 50 | static struct in6_addr IPv6from_string(const std::string &address); 51 | 52 | private: 53 | int version; 54 | union { 55 | uint32_t ipv4; 56 | uint8_t ipv6[16]; 57 | }; 58 | }; 59 | } 60 | #endif /* __IPADDRESS_H__ */ 61 | -------------------------------------------------------------------------------- /include/aca_dhcp_programming_if.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_DHCP_PROGRAMMING_IF_H 16 | #define ACA_DHCP_PROGRAMMING_IF_H 17 | 18 | #include "aca_config.h" 19 | #include 20 | 21 | using namespace std; 22 | 23 | namespace aca_dhcp_programming_if 24 | { 25 | 26 | struct dhcp_config { 27 | string mac_address; 28 | string ipv4_address; 29 | string ipv6_address; 30 | string subnet_mask; 31 | string gateway_address; 32 | string port_host_name; 33 | string dns_addresses[DHCP_MSG_OPTS_DNS_LENGTH]; 34 | }; 35 | 36 | // DHCP programming interface class 37 | class ACA_Dhcp_Programming_Interface { 38 | public: 39 | // pure virtual functions providing interface framework. 40 | virtual int add_dhcp_entry(dhcp_config *dhcp_config_in) = 0; 41 | 42 | virtual int update_dhcp_entry(dhcp_config *dhcp_config_in) = 0; 43 | 44 | virtual int delete_dhcp_entry(dhcp_config *dhcp_config_in) = 0; 45 | }; 46 | } // namespace aca_dhcp_programming_if 47 | #endif // #ifndef ACA_DHCP_PROGRAMMING_IF_H 48 | -------------------------------------------------------------------------------- /include/aca_grpc_client.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include "goalstateprovisioner.grpc.pb.h" 20 | 21 | using namespace alcor::schema; 22 | using grpc::Server; 23 | using grpc::ServerBuilder; 24 | using grpc::ServerContext; 25 | using grpc::ServerReader; 26 | using grpc::ServerReaderWriter; 27 | using grpc::ServerWriter; 28 | using grpc::Status; 29 | 30 | class GoalStateProvisionerClientImpl final : public GoalStateProvisioner::Service { 31 | public: 32 | std::unique_ptr stub_; 33 | std::shared_ptr chan_; 34 | void RequestGoalStates(HostRequest *request, grpc::CompletionQueue *cq); 35 | explicit GoalStateProvisionerClientImpl(){}; 36 | void ConnectToNCM(); 37 | void RunClient(); 38 | bool a = chan_ == nullptr; 39 | }; 40 | 41 | struct AsyncClientCall { 42 | alcor::schema::HostRequestReply reply; 43 | grpc::ClientContext context; 44 | grpc::Status status; 45 | std::unique_ptr > response_reader; 46 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | # Prerequisites 16 | *.d 17 | 18 | # Object files 19 | *.o 20 | *.ko 21 | *.obj 22 | *.elf 23 | 24 | # Linker output 25 | *.ilk 26 | *.map 27 | *.exp 28 | 29 | # Precompiled Headers 30 | *.gch 31 | *.pch 32 | 33 | # Libraries 34 | *.lib 35 | *.a 36 | *.la 37 | *.lo 38 | 39 | # Shared objects (inc. Windows DLLs) 40 | *.dll 41 | *.so 42 | *.so.* 43 | *.dylib 44 | 45 | # Executables 46 | *.exe 47 | *.out 48 | *.app 49 | *.i*86 50 | *.x86_64 51 | *.hex 52 | 53 | # Debug files 54 | *.dSYM/ 55 | *.su 56 | *.idb 57 | *.pdb 58 | 59 | # Kernel Module Compile Results 60 | *.mod* 61 | *.cmd 62 | .tmp_versions/ 63 | modules.order 64 | Module.symvers 65 | Mkfile.old 66 | dkms.conf 67 | 68 | # CMake file 69 | **/cmake-build-debug 70 | **/CMakeCache.txt 71 | **/cmake_install.cmake 72 | **/install_manifest.txt 73 | **/CMakeFiles/ 74 | **/CTestTestfile.cmake 75 | **/Makefile 76 | **/*.cbp 77 | **/CMakeScripts 78 | **/compile_commands.json 79 | 80 | # python 81 | *.swp 82 | __pycache__ 83 | 84 | # Other files to ignore 85 | .vscode/ 86 | cppkafka/ 87 | .DS_Store 88 | AlcorControlAgent 89 | gs_tests 90 | aca_tests 91 | *.pb.h 92 | *.pb.cc 93 | *aca_data.json 94 | *.log -------------------------------------------------------------------------------- /test/zeta-aca-test_controllerScript/README.md: -------------------------------------------------------------------------------- 1 | # Pseudo Controller for Zeta/ACA Integration Tests 2 | 3 | The pseudo controller is a python script that acts as a controller between Zeta and ACA during the integration tests, and it does the following: 4 | 5 | - Creates Zeta resources(zgc, vpc, nodes, ports, etc) by calling the Zeta Northbound APIs. 6 | - Sends the data needed for ACA to construct its GoalState to the ACA nodes. 7 | - Calls test case DISABLED_zeta_scale_container, constructs the GoalStates do some validation, and start Busybox container(s), each of which has one zeta port. 8 | - If the above steps are all successful, the pseudo controller will execute 3 ping commands from the containers on the parent node to the containers on the child node, before it executes another 3 ping commands from containers on the child node to containers on the parent node, in order to verify the results of the previous steps. 9 | 10 | ## Usage 11 | 12 | There are now two ways to use the controller: 13 | 14 | 1. To create up to 1,000,000 port and run the tests DISABLED_zeta_scale_container, with flags to control how many ports to create in total, how many ports each /ports POST call should generate(up to 4,000 ports), how much time the pseudo controller sleeps after each call, and how many ports to send to the aca nodes(this also equals the total # of containers that the aca nodes will create) the user should run: 15 | 16 | ```sh 17 | python3 run.py total_ports_to_create number_of_ports_each_call amount_of_time_to_sleep amount_of_ports_to_send_to_aca 18 | ``` 19 | 20 | 2. If no parameters are specified, 2 ports will be created and be sent to the aca nodes, after which the ping will be performed between these two ports. 21 | 22 | ## Known Issues 23 | 24 | 1. It is suggested that the total amount of ports to send to aca not to exceed 10, the reason for this is, after the data is sent to the aca nodes and the gtest are called, because of the large amount of data to process for the ACA(thus with longer time needed and more output will be produced), the pseudo controller will be 'frozen', and users may have to stop the controller by `control + c`. 25 | Please note that, even if the pseudo controller is 'frozen', it doesn't mean the gtests failed. You can execute the gtests on the aca nodes manually, and the gtests should run and you should see the results. 26 | -------------------------------------------------------------------------------- /include/aca_oam_port_manager.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_OAM_PORT_MANAGER_H 16 | #define ACA_OAM_PORT_MANAGER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | namespace aca_oam_port_manager 27 | { 28 | class Aca_Oam_Port_Manager { 29 | public: 30 | Aca_Oam_Port_Manager(); 31 | ~Aca_Oam_Port_Manager(); 32 | 33 | static Aca_Oam_Port_Manager &get_instance(); 34 | 35 | void create_entry_unsafe(uint port_number); 36 | void add_oam_port_rule(uint port_number); 37 | int remove_oam_port_rule(uint port_number); 38 | 39 | 40 | 41 | //Determine whether the port is an oam_server_port 42 | bool is_oam_server_port(uint port_number); 43 | 44 | bool is_exist_oam_port_rule(uint port_number); 45 | private: 46 | int _create_oam_ofp(uint port_number); 47 | int _delete_oam_ofp(uint port_number); 48 | void _clear_all_data(); 49 | 50 | // unordered_set 51 | unordered_set _oam_ports_cache; 52 | 53 | // mutex for reading and writing to _oam_ports_cache 54 | mutex _oam_ports_cache_mutex; 55 | }; 56 | 57 | } // namespace aca_oam_port_manager 58 | #endif //#ifndef ACA_OAM_PORT_MANAGER_H -------------------------------------------------------------------------------- /src/ovs/libfluid-base/OFConnection.cc: -------------------------------------------------------------------------------- 1 | #include "libfluid-base/base/BaseOFConnection.hh" 2 | #include "libfluid-base/OFConnection.hh" 3 | #include "libfluid-base/base/BaseOFConnection.hh" 4 | 5 | namespace fluid_base { 6 | 7 | OFConnection::OFConnection(BaseOFConnection* c, OFHandler* ofhandler) { 8 | this->ofhandler = ofhandler; 9 | this->conn = c; 10 | this->conn->set_manager(this); 11 | this->id = c->get_id(); 12 | this->peer_address = c->get_peer_address(); 13 | this->set_state(STATE_HANDSHAKE); 14 | this->set_alive(true); 15 | this->set_version(0); 16 | this->application_data = NULL; 17 | } 18 | 19 | int OFConnection::get_id() { 20 | return this->id; 21 | } 22 | 23 | std::string OFConnection::get_peer_address() { 24 | return this->peer_address; 25 | } 26 | 27 | bool OFConnection::is_alive() { 28 | return this->alive; 29 | } 30 | 31 | void OFConnection::set_alive(bool alive) { 32 | this->alive = alive; 33 | } 34 | 35 | uint8_t OFConnection::get_state() { 36 | return state; 37 | } 38 | 39 | void OFConnection::set_state(OFConnection::State state) { 40 | this->state = state; 41 | } 42 | 43 | uint8_t OFConnection::get_version() { 44 | return this->version; 45 | } 46 | 47 | void OFConnection::set_version(uint8_t version) { 48 | this->version = version; 49 | } 50 | 51 | OFHandler* OFConnection::get_ofhandler() { 52 | return this->ofhandler; 53 | } 54 | 55 | void OFConnection::send(void* data, size_t len) { 56 | if (this->conn != NULL) 57 | this->conn->send((uint8_t*) data, len); 58 | } 59 | 60 | void OFConnection::add_timed_callback(void* (*cb)(void*), 61 | int interval, 62 | void* arg) { 63 | if (this->conn != NULL) 64 | this->conn->add_timed_callback(cb, interval, arg); 65 | } 66 | 67 | void* OFConnection::get_application_data() { 68 | return this->application_data; 69 | } 70 | 71 | void OFConnection::set_application_data(void* data) { 72 | this->application_data = data; 73 | } 74 | 75 | void OFConnection::close() { 76 | // Don't close twice 77 | if (this->conn == NULL) 78 | return; 79 | 80 | set_state(STATE_DOWN); 81 | // Close the BaseOFConnection. This will trigger 82 | // BaseOFHandler::base_connection_callback. Then BaseOFServer will take 83 | // care of freeing it for us, so we can lose track of it. 84 | this->conn->close(); 85 | this->conn = NULL; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /include/aca_message_consumer.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef KAFKA_CONSUMER_H 16 | #define KAFKA_CONSUMER_H 17 | 18 | #include "cppkafka/consumer.h" 19 | #include "cppkafka/configuration.h" 20 | 21 | using cppkafka::Configuration; 22 | using cppkafka::Consumer; 23 | using std::string; 24 | 25 | namespace messagemanager 26 | { 27 | class MessageConsumer { 28 | private: 29 | string brokers_list; //IP addresses of Kafka brokers, format: :, example:10.213.43.188:9092 30 | 31 | string group_id; //Group id of the Kafka consumer 32 | 33 | string topic_name; //A string representation of the topic to be consumed, for example: /hostid/00000000-0000-0000-0000-000000000000/netwconf/ 34 | 35 | Configuration config; //Configuration of the Kafka consumer 36 | 37 | Consumer *ptr_consumer; //A pointer to the Kafka consumer 38 | 39 | public: 40 | MessageConsumer(string brokers, string group_id); 41 | 42 | ~MessageConsumer(); 43 | 44 | string getBrokers() const; 45 | 46 | string getLastTopicName() const; 47 | 48 | string getGroupId() const; 49 | 50 | void setGroupId(string group_id); 51 | 52 | bool consumeDispatched(string topic); 53 | 54 | private: 55 | void setBrokers(string brokers); 56 | 57 | void setLastTopicName(string topic); 58 | }; 59 | 60 | } // namespace messagemanager 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/aca_message_producer.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef KAFKA_PRODUCER_H 16 | #define KAFKA_PRODUCER_H 17 | 18 | #include "cppkafka/producer.h" 19 | #include "cppkafka/configuration.h" 20 | 21 | using namespace std; 22 | using namespace cppkafka; 23 | 24 | namespace messagemanager 25 | { 26 | class MessageProducer { 27 | private: 28 | string brokers_list; //IP addresses of Kafka brokers, format: :, example:10.213.43.188:9092 29 | 30 | string topic_name; //A string representation of the topic name to be published, example: /hostid/00000000-0000-0000-0000-000000000000/netwconf/ 31 | 32 | int partition_value = -1; //Number of partitions used for a given topic, set by publisher 33 | 34 | Configuration config; //Configuration of a producer 35 | 36 | Producer *ptr_producer; //A pointer to the kafka producer 37 | 38 | public: 39 | MessageProducer(string brokers, string topic, int partition); 40 | 41 | ~MessageProducer(); 42 | 43 | string getBrokers() const; 44 | 45 | string getTopicName() const; 46 | 47 | void setTopicName(string topic); 48 | 49 | int getPartitionValue() const; 50 | 51 | void setPartitionValue(int partition); 52 | 53 | void publish(string message); 54 | 55 | private: 56 | void setBrokers(string brokers); 57 | }; 58 | 59 | } // namespace messagemanager 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/aca_async_grpc_server.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include "goalstateprovisioner.grpc.pb.h" 20 | 21 | using grpc::Server; 22 | using grpc::ServerAsyncResponseWriter; 23 | using grpc::ServerBuilder; 24 | using grpc::ServerCompletionQueue; 25 | using grpc::ServerContext; 26 | using grpc::Status; 27 | 28 | class Aca_Async_GRPC_Server final { 29 | public: 30 | ~Aca_Async_GRPC_Server(); 31 | Aca_Async_GRPC_Server(); 32 | void Run(); 33 | void StopServer(); 34 | 35 | private: 36 | class CallData { 37 | public: 38 | CallData(alcor::schema::GoalStateProvisioner::AsyncService *service, 39 | ServerCompletionQueue *cq); 40 | void Proceed(); 41 | 42 | private: 43 | alcor::schema::GoalStateProvisioner::AsyncService *service_; 44 | ServerCompletionQueue *cq_; 45 | ServerContext ctx_; 46 | alcor::schema::GoalState request_; 47 | alcor::schema::GoalStateOperationReply reply_; 48 | ServerAsyncResponseWriter responder_; 49 | 50 | enum CallStatus { CREATE, PROCESS, FINISH }; 51 | CallStatus status_; 52 | }; 53 | 54 | void HandleRpcs(); 55 | std::unique_ptr cq_; 56 | alcor::schema::GoalStateProvisioner::AsyncService service_; 57 | std::unique_ptr server_; 58 | }; -------------------------------------------------------------------------------- /include/aca_message_pulsar_producer.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef PULSAR_PRODUCER_H 16 | #define PULSAR_PRODUCER_H 17 | 18 | #include "pulsar/Client.h" 19 | #include "pulsar/Producer.h" 20 | #include "pulsar/ProducerConfiguration.h" 21 | #include "pulsar/Message.h" 22 | #include "pulsar/MessageBuilder.h" 23 | #include "pulsar/Result.h" 24 | 25 | using namespace std; 26 | using namespace pulsar; 27 | 28 | namespace aca_message_pulsar 29 | { 30 | class ACA_Message_Pulsar_Producer { 31 | private: 32 | string brokers_list; //IP addresses of Pulsar brokers, format: pulsar://:, example:pulsar://10.213.43.188:9092 33 | 34 | string topic_name; //A string representation of the topic name to be published, example: /hostid/00000000-0000-0000-0000-000000000000/netwconf/ 35 | 36 | ClientConfiguration client_config; //Configuration of the pulsar client 37 | 38 | Client *ptr_client; //A pointer to the pulsar client 39 | 40 | public: 41 | ACA_Message_Pulsar_Producer(string brokers, string topic); 42 | 43 | ~ACA_Message_Pulsar_Producer(); 44 | 45 | string getBrokers() const; 46 | 47 | string getTopicName() const; 48 | 49 | void setTopicName(string topic); 50 | 51 | bool publish(string message); 52 | 53 | bool publish(string message, string key); 54 | 55 | 56 | private: 57 | void setBrokers(string brokers); 58 | 59 | }; 60 | 61 | } // aca_message_pulsar 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/aca_dataplane_mizar.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | // Note: mizar dataplane end to end support is no longer maintained going forward 16 | 17 | #ifndef ACA_DATAPLANCE_MIZAR_H 18 | #define ACA_DATAPLANCE_MIZAR_H 19 | 20 | #include "aca_net_programming_if.h" 21 | 22 | // mizar dataplane implementation class 23 | namespace aca_dataplane_mizar 24 | { 25 | class ACA_Dataplane_Mizar : public aca_net_programming_if::ACA_Core_Net_Programming_Interface { 26 | public: 27 | int initialize(); 28 | 29 | int update_vpc_state_workitem(const alcor::schema::VpcState current_VpcState, 30 | alcor::schema::GoalStateOperationReply &gsOperationReply); 31 | 32 | int update_subnet_state_workitem(const alcor::schema::SubnetState current_SubnetState, 33 | alcor::schema::GoalStateOperationReply &gsOperationReply); 34 | 35 | int update_port_state_workitem(const alcor::schema::PortState current_PortState, 36 | alcor::schema::GoalState &parsed_struct, 37 | alcor::schema::GoalStateOperationReply &gsOperationReply); 38 | 39 | private: 40 | int load_agent_xdp(std::string interface, ulong &culminative_time); 41 | 42 | int unload_agent_xdp(std::string interface, ulong &culminative_time); 43 | 44 | int execute_command(int command, void *input_struct, ulong &culminative_time); 45 | }; 46 | } // namespace aca_dataplane_mizar 47 | #endif // #ifndef ACA_DATAPLANCE_MIZAR_H -------------------------------------------------------------------------------- /include/aca_comm_mgr.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_COMM_MGR_H 16 | #define ACA_COMM_MGR_H 17 | 18 | #include "goalstateprovisioner.grpc.pb.h" 19 | 20 | using std::string; 21 | 22 | namespace aca_comm_manager 23 | { 24 | class Aca_Comm_Manager { 25 | public: 26 | static Aca_Comm_Manager &get_instance(); 27 | 28 | int deserialize(const unsigned char *mq_buffer, size_t buffer_length, 29 | alcor::schema::GoalState &parsed_struct); 30 | 31 | int deserialize(const unsigned char *mq_buffer, size_t buffer_length, 32 | alcor::schema::GoalStateV2 &parsed_struct); 33 | 34 | int update_goal_state(alcor::schema::GoalState &goal_state_message, 35 | alcor::schema::GoalStateOperationReply &gsOperationReply); 36 | 37 | int update_goal_state(alcor::schema::GoalStateV2 &goal_state_message, 38 | alcor::schema::GoalStateOperationReply &gsOperationReply); 39 | 40 | // compiler will flag error when below is called 41 | Aca_Comm_Manager(Aca_Comm_Manager const &) = delete; 42 | void operator=(Aca_Comm_Manager const &) = delete; 43 | 44 | private: 45 | // constructor and destructor marked as private so that noone can call it 46 | // for the singleton implementation 47 | Aca_Comm_Manager(){}; 48 | ~Aca_Comm_Manager(){}; 49 | 50 | void print_goal_state(alcor::schema::GoalState parsed_struct); 51 | 52 | void print_goal_state(alcor::schema::GoalStateV2 parsed_struct); 53 | 54 | }; 55 | } // namespace aca_comm_manager 56 | #endif 57 | -------------------------------------------------------------------------------- /etc/k8s/aca-cluster_init.sh: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #!/bin/bash 16 | 17 | set -euo pipefail 18 | 19 | function main() { 20 | timeout=600 21 | running="running" 22 | 23 | # Start aca on all nodes. 24 | kubectl apply -f aca-daemonset.yaml 25 | validate $running aca-daemonset.yaml aca $timeout 26 | } 27 | 28 | function validate() { 29 | PODS=$(kubectl get pods | grep $3 | awk '{print $1}') 30 | end=$((SECONDS+$4)) 31 | 32 | for POD in ${PODS}; do 33 | echo -n "Waiting for pod:$POD" 34 | while [[ $SECONDS -lt $end ]]; do 35 | if [[ $1 == "running" ]]; then 36 | check_running $POD || break 37 | else 38 | check_done $POD || break 39 | fi 40 | done 41 | echo 42 | if [[ $SECONDS -lt $end ]]; then 43 | echo "Pod:${POD} now $1!" 44 | else 45 | echo "ERROR: ${POD} timed out after $4 seconds!" 46 | kubectl delete -f $2 47 | exit 1 48 | fi 49 | done 50 | 51 | echo 52 | echo "All $3 pods now $1!" 53 | echo 54 | } 55 | 56 | function check_done() { 57 | if [[ $(kubectl logs $1 --tail 1) == "done" ]]; then 58 | return 1 59 | else 60 | sleep 2 61 | echo -n "." 62 | return 0 63 | fi 64 | } 65 | 66 | function check_running() { 67 | if [[ $(kubectl get pod $1 -o go-template --template "{{.status.phase}}") == "Running" ]]; then 68 | return 1 69 | else 70 | sleep 2 71 | echo -n "." 72 | return 0 73 | fi 74 | } 75 | 76 | main -------------------------------------------------------------------------------- /include/aca_net_config.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_NET_CONFIG_H 16 | #define ACA_NET_CONFIG_H 17 | 18 | #include 19 | 20 | using std::string; 21 | 22 | const string IP_NETNS_PREFIX = "ip netns "; 23 | 24 | struct veth_config { 25 | string veth_name; 26 | string ip; 27 | string prefix_len; 28 | string mac; 29 | string gateway_ip; 30 | }; 31 | 32 | namespace aca_net_config 33 | { 34 | class Aca_Net_Config { 35 | public: 36 | static Aca_Net_Config &get_instance(); 37 | 38 | int create_namespace(string ns_name, ulong &culminative_time); 39 | 40 | int create_veth_pair(string veth_name, string peer_name, ulong &culminative_time); 41 | 42 | int delete_veth_pair(string peer_name, ulong &culminative_time); 43 | 44 | int setup_peer_device(string peer_name, ulong &culminative_time); 45 | 46 | int move_to_namespace(string veth_name, string ns_name, ulong &culminative_time); 47 | 48 | int setup_veth_device(string ns_name, veth_config new_veth_config, ulong &culminative_time); 49 | 50 | int rename_veth_device(string ns_name, string org_veth_name, 51 | string new_veth_name, ulong &culminative_time); 52 | 53 | int add_gw(string ns_name, string gateway_ip, ulong &culminative_time); 54 | 55 | int execute_system_command(string cmd_string); 56 | 57 | int execute_system_command(string cmd_string, ulong &culminative_time); 58 | 59 | std::string execute_system_command_with_return(string cmd_string); 60 | 61 | // compiler will flag error when below is called 62 | Aca_Net_Config(Aca_Net_Config const &) = delete; 63 | void operator=(Aca_Net_Config const &) = delete; 64 | 65 | private: 66 | Aca_Net_Config(){}; 67 | ~Aca_Net_Config(){}; 68 | }; 69 | 70 | } // namespace aca_net_config 71 | #endif -------------------------------------------------------------------------------- /include/aca_dhcp_state_handler.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_DHCP_STATE_HANDLER_H 16 | #define ACA_DHCP_STATE_HANDLER_H 17 | 18 | #include "aca_dhcp_programming_if.h" 19 | #include "goalstateprovisioner.grpc.pb.h" 20 | 21 | namespace aca_dhcp_state_handler 22 | { 23 | class Aca_Dhcp_State_Handler { 24 | public: 25 | static Aca_Dhcp_State_Handler &get_instance(); 26 | 27 | // process ONE DHCP state 28 | int update_dhcp_state_workitem(const alcor::schema::DHCPState current_DHCPState, 29 | alcor::schema::GoalState &parsed_struct, 30 | alcor::schema::GoalStateOperationReply &gsOperationReply); 31 | 32 | // process 0 to N DHCP states 33 | int update_dhcp_states(alcor::schema::GoalState &parsed_struct, 34 | alcor::schema::GoalStateOperationReply &gsOperationReply); 35 | 36 | // process ONE DHCP state 37 | int update_dhcp_state_workitem_v2(const alcor::schema::DHCPState current_DHCPState, 38 | alcor::schema::GoalStateV2 &parsed_struct, 39 | alcor::schema::GoalStateOperationReply &gsOperationReply); 40 | 41 | // process 0 to N DHCP states 42 | int update_dhcp_states(alcor::schema::GoalStateV2 &parsed_struct, 43 | alcor::schema::GoalStateOperationReply &gsOperationReply); 44 | 45 | private: 46 | // constructor and destructor marked as private so that noone can call it 47 | // for the singleton implementation 48 | Aca_Dhcp_State_Handler(); 49 | ~Aca_Dhcp_State_Handler(); 50 | 51 | aca_dhcp_programming_if::ACA_Dhcp_Programming_Interface *dhcp_programming_if; 52 | }; 53 | } // namespace aca_dhcp_state_handler 54 | #endif // @ifndef ACA_DHCP_STATE_HANDLER_H 55 | -------------------------------------------------------------------------------- /src/ovs/libfluid-base/base/EventLoop.cc: -------------------------------------------------------------------------------- 1 | #include "libfluid-base/base/EventLoop.hh" 2 | #include 3 | #include 4 | 5 | namespace fluid_base { 6 | 7 | // Define our own value, since the stdint.h define doesn't work in C++ 8 | #define OF_MAX_LEN 0xFFFF 9 | 10 | // See FIXME in EventLoop::EventLoop 11 | //extern "C" void event_base_add_virtual(struct event_base *); 12 | //extern "C" void event_base_del_virtual(struct event_base *); 13 | 14 | class EventLoop::LibEventEventLoop { 15 | private: 16 | friend class EventLoop; 17 | struct event_base *base; 18 | }; 19 | 20 | EventLoop::EventLoop(int id, marl::Scheduler* scheduler) { 21 | this->id = id; 22 | this->m_implementation = new EventLoop::LibEventEventLoop; 23 | 24 | this->m_implementation->base = event_base_new(); 25 | 26 | // pass marl scheduler from main thread (OFController : OFServer initialization) 27 | this->m_scheduler = scheduler; 28 | 29 | this->stopped = false; 30 | if (!this->m_implementation->base) { 31 | fprintf(stderr, "Error creating EventLoop %d\n", id); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | /* FIXME: dirty hack warning! 36 | We add a virtual event to prevent the loop from exiting when there are 37 | no events. 38 | 39 | This fix is needed because libevent 2.0 doesn't have the flag 40 | EVLOOP_NO_EXIT_ON_EMPTY. Version 2.1 fixes this, so this will have to 41 | be changed in the future (to make it prettier and to avoid breaking 42 | anything). 43 | 44 | See: 45 | http://stackoverflow.com/questions/7645217/user-triggered-event-in-libevent 46 | */ 47 | //event_base_add_virtual(this->m_implementation->base); 48 | } 49 | 50 | EventLoop::~EventLoop() { 51 | event_base_free(this->m_implementation->base); 52 | delete this->m_implementation; 53 | } 54 | 55 | void EventLoop::run() { 56 | // Only run if EventLoop::stop hasn't been called first 57 | if (stopped) return; 58 | 59 | //// The m_scheduler is passed from main thread (OFController : OFServer construction), and then bind it in each new Eventloop pthread_create 60 | m_scheduler->bind(); 61 | defer(m_scheduler->unbind()); 62 | 63 | event_base_dispatch(this->m_implementation->base); 64 | // See note in EventLoop::EventLoop. Here we disable the virtual event 65 | // to guarantee that nothing blocks. 66 | //event_base_del_virtual(this->m_implementation->base); 67 | event_base_loop(this->m_implementation->base, EVLOOP_NO_EXIT_ON_EMPTY); 68 | } 69 | 70 | void EventLoop::stop() { 71 | // Prevent run from running if it's not started :) 72 | this->stopped = true; 73 | event_base_loopbreak(this->m_implementation->base); 74 | } 75 | 76 | void* EventLoop::thread_adapter(void* arg) { 77 | ((EventLoop*) arg)->run(); 78 | return NULL; 79 | } 80 | 81 | void* EventLoop::get_base() { 82 | return this->m_implementation->base; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /include/libfluid-base/base/EventLoop.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /** @file */ 17 | #ifndef __EVENTLOOP_HH__ 18 | #define __EVENTLOOP_HH__ 19 | 20 | #include "marl/defer.h" 21 | #include "marl/scheduler.h" 22 | 23 | namespace fluid_base { 24 | 25 | class BaseOFServer; 26 | class BaseOFConnection; 27 | class OvsdbClient; 28 | class OvsdbConnection; 29 | class BaseOFClient; 30 | 31 | /** 32 | A EventLoop runs an event loop for connections. It will activate the callbacks 33 | associated with them. The class using an EventLoop should tipically assign 34 | incoming connections in a round-robin fashion. 35 | 36 | There might be more than one event loop in use in applications. In this case, 37 | each EventLoop can be run in a thread. 38 | */ 39 | // An EventLoop is pretty much a simple wrapper around libevent's event_base 40 | class EventLoop { 41 | public: 42 | /** 43 | Create a EventLoop. 44 | 45 | @param id event loop id 46 | */ 47 | EventLoop(int id, marl::Scheduler* scheduler); 48 | ~EventLoop(); 49 | 50 | /** 51 | Run this event loop (which will block the calling thread). When 52 | EventLoop::stop is called, this method will unblock, run the callbacks 53 | of pending events and return. 54 | 55 | Calling EventLoop::stop first will prevent this method from running. */ 56 | void run(); 57 | 58 | /** 59 | Force the event loop to stop. It will finish running the current event 60 | callback and then force EventLoop::run to continue its flow (deal with 61 | remaining events and quit). 62 | 63 | Calling this method first will prevent EventLoop::run from running. */ 64 | void stop(); 65 | 66 | /** 67 | This method is just an adapter for passing the EventLoop::run method to 68 | pthread_create. */ 69 | static void* thread_adapter(void* arg); 70 | 71 | 72 | private: 73 | int id; 74 | bool stopped; 75 | 76 | friend class BaseOFServer; 77 | friend class BaseOFConnection; 78 | friend class OvsdbClient; 79 | friend class OvsdbConnection; 80 | friend class BaseOFClient; 81 | void* get_base(); 82 | 83 | class LibEventEventLoop; 84 | friend class LibEventEventLoop; 85 | LibEventEventLoop* m_implementation; 86 | marl::Scheduler* m_scheduler; 87 | }; 88 | 89 | } 90 | 91 | #endif -------------------------------------------------------------------------------- /src/ovs/libfluid-base/TLS.cc: -------------------------------------------------------------------------------- 1 | #include "libfluid-base/base/config.h" 2 | 3 | #if defined(HAVE_TLS) 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "libfluid-base/TLS.hh" 15 | 16 | namespace fluid_base { 17 | 18 | void* tls_obj = NULL; 19 | pthread_mutex_t* ssl_locks; 20 | int ssl_num_locks; 21 | 22 | static unsigned long get_thread_id_cb(void) { 23 | return (unsigned long) pthread_self(); 24 | } 25 | 26 | static void thread_lock_cb(int mode, int which, const char * f, int l) { 27 | if (which < ssl_num_locks) { 28 | if (mode & CRYPTO_LOCK) { 29 | pthread_mutex_lock(&(ssl_locks[which])); 30 | } else { 31 | pthread_mutex_unlock(&(ssl_locks[which])); 32 | } 33 | } 34 | } 35 | 36 | // TODO: make these function idempotent 37 | 38 | void libfluid_tls_init(const char* cert, const char* privkey, const char* trustedcert) { 39 | int i; 40 | SSL_CTX *server_ctx; 41 | 42 | tls_obj = NULL; 43 | 44 | ssl_num_locks = CRYPTO_num_locks(); 45 | ssl_locks = (pthread_mutex_t*) malloc(ssl_num_locks * sizeof(pthread_mutex_t)); 46 | if (ssl_locks == NULL) 47 | return; 48 | 49 | for (i = 0; i < ssl_num_locks; i++) { 50 | pthread_mutex_init(&(ssl_locks[i]), NULL); 51 | } 52 | 53 | // TODO: change this to the CRYPTO_THREADID family of functions to aid 54 | // portability. While this will work on Linux, it is deprecated and should 55 | // be changed. 56 | CRYPTO_set_id_callback(get_thread_id_cb); 57 | CRYPTO_set_locking_callback(thread_lock_cb); 58 | 59 | /* Initialize OpenSSL */ 60 | SSL_load_error_strings(); 61 | SSL_library_init(); 62 | 63 | /* Stop if there's no entropy */ 64 | if (!RAND_poll()) 65 | return; 66 | 67 | server_ctx = SSL_CTX_new(SSLv23_server_method()); 68 | 69 | if (!SSL_CTX_load_verify_locations(server_ctx, trustedcert, NULL)) { 70 | fprintf(stderr, "Error loading verification CA certificate.\n"); 71 | return; 72 | } 73 | SSL_CTX_set_verify(server_ctx, SSL_VERIFY_PEER | 74 | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); 75 | 76 | if (!SSL_CTX_use_certificate_chain_file(server_ctx, cert)) { 77 | fprintf(stderr, "Error loading certificate.\n"); 78 | return; 79 | } 80 | 81 | if (!SSL_CTX_use_PrivateKey_file(server_ctx, privkey, SSL_FILETYPE_PEM)) { 82 | fprintf(stderr, "Error loading private key.\n"); 83 | return; 84 | } 85 | 86 | tls_obj = server_ctx; 87 | } 88 | 89 | void libfluid_tls_clear() { 90 | // TODO: investigate how to free the memory (~84k) that is still reachable 91 | // after this function runs. 92 | if (tls_obj != NULL) { 93 | SSL_CTX_free((SSL_CTX*) tls_obj); 94 | } 95 | } 96 | 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../build/tests) 4 | 5 | 6 | FIND_LIBRARY(RDKAFKA rdkafka /usr/lib/x86_64-linux-gnu NO_DEFAULT_PATH) 7 | FIND_LIBRARY(CPPKAFKA cppkafka /usr/local/lib NO_DEFAULT_PATH) 8 | FIND_LIBRARY(PULSAR pulsar /usr/lib NO_DEFAULT_PATH) 9 | #FIND_LIBRARY(OPENVSWITCH openvswitch /usr/local/lib NO_DEFAULT_PATH) 10 | FIND_LIBRARY(MESSAGEMANAGER messagemanager ${CMAKE_CURRENT_SOURCE_DIR}/../include NO_DEFAULT_PATH) 11 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) 12 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/proto3) 13 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/grpc) 14 | include_directories(/var/local/git/marl/marl/include) 15 | link_libraries(${PULSAR}) 16 | link_libraries(/var/local/git/marl/marl/build/libmarl.a) 17 | 18 | set(THREADS_PREFER_PTHREAD_FLAG ON) 19 | find_package(Threads REQUIRED) 20 | 21 | # Find Protobuf installation 22 | # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. 23 | set(protobuf_MODULE_COMPATIBLE TRUE) 24 | find_package(Protobuf CONFIG REQUIRED) 25 | message(STATUS "Using protobuf ${protobuf_VERSION}") 26 | 27 | # Find gRPC installation 28 | # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. 29 | find_package(gRPC CONFIG REQUIRED) 30 | message(STATUS "Using gRPC ${gRPC_VERSION}") 31 | 32 | set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure) 33 | set(_GRPC_CPP_PLUGIN_EXECUTABLE $) 34 | 35 | # Setup gtest 36 | enable_testing() 37 | find_package(GTest REQUIRED) 38 | include_directories(${GTEST_INCLUDE_DIR}) 39 | 40 | # Add test cpp file 41 | add_executable( 42 | aca_tests 43 | gtest/aca_test_main.cpp 44 | gtest/aca_test_dhcp.cpp 45 | gtest/aca_test_net_config.cpp 46 | gtest/aca_test_openflow.cpp 47 | gtest/aca_test_ovs_l2.cpp 48 | gtest/aca_test_ovs_l3.cpp 49 | gtest/aca_test_ovs_util.cpp 50 | gtest/aca_test_oam.cpp 51 | gtest/aca_test_zeta_programming.cpp 52 | gtest/aca_test_arp.cpp 53 | gtest/aca_test_on_demand.cpp 54 | gtest/aca_test_mq.cpp) 55 | 56 | # Link test executable against gtest & gtest_main 57 | target_link_libraries(aca_tests gtest gtest_main) 58 | target_link_libraries(aca_tests pulsar) 59 | #target_link_libraries(aca_tests openvswitch) 60 | target_link_libraries(aca_tests AlcorControlAgentLib) 61 | target_link_libraries(aca_tests proto) 62 | target_link_libraries(aca_tests grpc) 63 | target_link_libraries(aca_tests ${_GRPC_GRPCPP_UNSECURE}) 64 | target_link_libraries(aca_tests ${PROTOBUF_LIBRARY}) 65 | target_link_libraries(aca_tests Threads::Threads) 66 | 67 | add_test( 68 | NAME aca_tests 69 | COMMAND aca_tests 70 | ) 71 | 72 | # goal state test to process goal state message and send to local client 73 | add_executable(gs_tests func_tests/gs_tests.cpp) 74 | 75 | target_link_libraries(gs_tests AlcorControlAgentLib) 76 | target_link_libraries(gs_tests proto) 77 | target_link_libraries(gs_tests ${PROTOBUF_LIBRARY}) 78 | target_link_libraries(gs_tests grpc) 79 | target_link_libraries(gs_tests ${_GRPC_GRPCPP_UNSECURE}) -------------------------------------------------------------------------------- /src/comm/aca_message_producer.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #include 16 | #include 17 | #include "aca_message_producer.h" 18 | 19 | using namespace std; 20 | using namespace cppkafka; 21 | 22 | namespace messagemanager 23 | { 24 | MessageProducer::MessageProducer(string brokers, string topic, int partition) 25 | { 26 | setBrokers(brokers); 27 | setTopicName(topic); 28 | setPartitionValue(partition); 29 | 30 | // Construct the configuration 31 | this->config = { { "metadata.broker.list", this->brokers_list } }; 32 | 33 | // Create the producer 34 | this->ptr_producer = new Producer(this->config); 35 | } 36 | 37 | MessageProducer::~MessageProducer() 38 | { 39 | delete ptr_producer; 40 | } 41 | 42 | string MessageProducer::getBrokers() const 43 | { 44 | return this->brokers_list; 45 | } 46 | 47 | string MessageProducer::getTopicName() const 48 | { 49 | return this->topic_name; 50 | } 51 | 52 | void MessageProducer::setTopicName(string topic) 53 | { 54 | this->topic_name = topic; 55 | } 56 | 57 | int MessageProducer::getPartitionValue() const 58 | { 59 | return this->partition_value; 60 | } 61 | 62 | void MessageProducer::setPartitionValue(int partition) 63 | { 64 | if (partition < -1) { 65 | throw invalid_argument("Negative partition value"); 66 | } 67 | 68 | this->partition_value = partition; 69 | } 70 | 71 | void MessageProducer::publish(string message) 72 | { 73 | // Create a message builder for this topic 74 | MessageBuilder builder(this->topic_name); 75 | 76 | // Get the partition. If no partition is provided, this will be an unassigned one 77 | if (partition_value != -1) { 78 | builder.partition(this->partition_value); 79 | } 80 | 81 | // Set the payload on this builder 82 | builder.payload(message); 83 | 84 | // Actually produce the message 85 | this->ptr_producer->produce(builder); 86 | 87 | // Flush all produced messages 88 | this->ptr_producer->flush(); 89 | } 90 | 91 | void MessageProducer::setBrokers(string brokers) 92 | { 93 | //TODO: validate string as IP address 94 | this->brokers_list = brokers; 95 | } 96 | 97 | } // namespace messagemanager 98 | -------------------------------------------------------------------------------- /include/aca_vlan_manager.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_VLAN_MANAGER_H 16 | #define ACA_VLAN_MANAGER_H 17 | 18 | #include "goalstateprovisioner.grpc.pb.h" 19 | #include "hashmap/HashMap.h" 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | using namespace std; 27 | 28 | // TODO: implement a better available internal vlan ids 29 | static atomic_uint current_available_vlan_id(1); 30 | 31 | // Vlan Manager class 32 | namespace aca_vlan_manager 33 | { 34 | struct vpc_table_entry { 35 | uint vlan_id; 36 | 37 | // list of ovs_ports names on this host in the same VPC to share the same internal vlan_id 38 | // CTSL::HashMap 39 | CTSL::HashMap ovs_ports; 40 | 41 | string zeta_gateway_id; 42 | }; 43 | 44 | class ACA_Vlan_Manager { 45 | public: 46 | static ACA_Vlan_Manager &get_instance(); 47 | 48 | void clear_all_data(); 49 | 50 | uint get_or_create_vlan_id(uint tunnel_id); 51 | 52 | int create_ovs_port(string vpc_id, string ovs_port, uint tunnel_id, ulong &culminative_time); 53 | 54 | int delete_ovs_port(string vpc_id, string ovs_port, uint tunnel_id, ulong &culminative_time); 55 | 56 | int create_l2_neighbor(string virtual_ip, string virtual_mac, string remote_host_ip, 57 | uint tunnel_id, ulong &culminative_time); 58 | 59 | int delete_l2_neighbor(string virtual_ip, string virtual_mac, uint tunnel_id, 60 | ulong &culminative_time); 61 | 62 | void set_zeta_gateway(uint tunnel_id, const string auxGateway_id); 63 | 64 | int remove_zeta_gateway(uint tunnel_id); 65 | 66 | string get_zeta_gateway_id(uint tunnel_id); 67 | 68 | bool is_exist_zeta_gateway(const string auxGateway_id); 69 | 70 | uint get_tunnelId_by_vlanId(uint vlan_id); 71 | 72 | // compiler will flag error when below is called 73 | ACA_Vlan_Manager(ACA_Vlan_Manager const &) = delete; 74 | void operator=(ACA_Vlan_Manager const &) = delete; 75 | 76 | private: 77 | ACA_Vlan_Manager(){}; 78 | ~ACA_Vlan_Manager(){}; 79 | 80 | // CTSL::HashMap 81 | CTSL::HashMap _vpcs_table; 82 | // mutex for reading and writing to _vpcs_table 83 | mutex _vpcs_table_mutex; 84 | void create_entry(uint tunnel_id); 85 | }; 86 | } // namespace aca_vlan_manager 87 | #endif // #ifndef ACA_VLAN_MANAGER_H 88 | -------------------------------------------------------------------------------- /include/aca_dataplane_ovs.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_DATAPLANCE_OVS_H 16 | #define ACA_DATAPLANCE_OVS_H 17 | 18 | #include "aca_net_programming_if.h" 19 | 20 | // OVS dataplane implementation class 21 | namespace aca_dataplane_ovs 22 | { 23 | class ACA_Dataplane_OVS : public aca_net_programming_if::ACA_Core_Net_Programming_Interface { 24 | public: 25 | int initialize(); 26 | 27 | int update_vpc_state_workitem(const alcor::schema::VpcState current_VpcState, 28 | alcor::schema::GoalStateOperationReply &gsOperationReply); 29 | 30 | int update_subnet_state_workitem(const alcor::schema::SubnetState current_SubnetState, 31 | alcor::schema::GoalStateOperationReply &gsOperationReply); 32 | 33 | int update_port_state_workitem(const alcor::schema::PortState current_PortState, 34 | alcor::schema::GoalState &parsed_struct, 35 | alcor::schema::GoalStateOperationReply &gsOperationReply); 36 | 37 | int update_port_state_workitem(const alcor::schema::PortState current_PortState, 38 | alcor::schema::GoalStateV2 &parsed_struct, 39 | alcor::schema::GoalStateOperationReply &gsOperationReply); 40 | 41 | int update_neighbor_state_workitem(const alcor::schema::NeighborState current_NeighborState, 42 | alcor::schema::GoalState &parsed_struct, 43 | alcor::schema::GoalStateOperationReply &gsOperationReply); 44 | 45 | int update_neighbor_state_workitem(const alcor::schema::NeighborState current_NeighborState, 46 | alcor::schema::GoalStateV2 &parsed_struct, 47 | alcor::schema::GoalStateOperationReply &gsOperationReply); 48 | 49 | int update_router_state_workitem(const alcor::schema::RouterState current_RouterState, 50 | alcor::schema::GoalState &parsed_struct, 51 | alcor::schema::GoalStateOperationReply &gsOperationReply); 52 | 53 | int update_router_state_workitem(const alcor::schema::RouterState current_RouterState, 54 | alcor::schema::GoalStateV2 &parsed_struct, 55 | alcor::schema::GoalStateOperationReply &gsOperationReply); 56 | }; 57 | } // namespace aca_dataplane_ovs 58 | #endif // #ifndef ACA_DATAPLANCE_OVS_H -------------------------------------------------------------------------------- /src/ovs/libfluid-base/OFServerSettings.cc: -------------------------------------------------------------------------------- 1 | #include "libfluid-base/OFServerSettings.hh" 2 | 3 | namespace fluid_base { 4 | 5 | OFServerSettings::OFServerSettings() { 6 | this->_supported_versions = 0; 7 | this->add_version(1); 8 | this->version_set_by_hand = false; 9 | this->echo_interval(15); 10 | this->liveness_check(true); 11 | this->handshake(true); 12 | this->dispatch_all_messages(false); 13 | this->use_hello_elements(false); 14 | this->keep_data_ownership(true); 15 | } 16 | 17 | OFServerSettings& OFServerSettings::supported_version(const uint8_t version) { 18 | // If the user sets the version by hand, then all supported versions must 19 | // be explicitly declared. 20 | if (not this->version_set_by_hand) { 21 | this->version_set_by_hand = true; 22 | this->_supported_versions = 0; 23 | } 24 | this->add_version(version); 25 | return *this; 26 | } 27 | 28 | void OFServerSettings::add_version(const uint8_t version) { 29 | this->_supported_versions |= (1 << version); 30 | 31 | unsigned int x = 0; 32 | this->_max_supported_version = 0; 33 | for (x = (unsigned int) this->_supported_versions; 34 | x > 0; 35 | x = x >> 1, this->_max_supported_version++); 36 | this->_max_supported_version--; 37 | } 38 | 39 | uint32_t* OFServerSettings::supported_versions() { 40 | // We return a pointer because an OFServerSettings object is supposed to 41 | // be exclusively user by an OFServer instance which has a copy of it. 42 | 43 | // TODO: since this->_supported_versions is just an uint32_t, we can only 44 | // support OpenFlow versions lower than 31. It might be a problem some day, 45 | // so it would be nice to change the implementation to a proper uint32_t 46 | // array. 47 | return &this->_supported_versions; 48 | } 49 | 50 | uint8_t OFServerSettings::max_supported_version() { 51 | return this->_max_supported_version; 52 | } 53 | 54 | OFServerSettings& OFServerSettings::echo_interval(const int ei) { 55 | this->_echo_interval = ei; 56 | return *this; 57 | } 58 | 59 | int OFServerSettings::echo_interval() { 60 | return this->_echo_interval; 61 | } 62 | 63 | OFServerSettings& OFServerSettings::liveness_check(const bool liveness_check) { 64 | this->_liveness_check = liveness_check; 65 | return *this; 66 | } 67 | 68 | bool OFServerSettings::liveness_check() { 69 | return this->_liveness_check; 70 | } 71 | 72 | OFServerSettings& OFServerSettings::handshake(const bool handshake) { 73 | this->_handshake = handshake; 74 | return *this; 75 | } 76 | 77 | bool OFServerSettings::handshake() { 78 | return this->_handshake; 79 | } 80 | 81 | OFServerSettings& OFServerSettings::dispatch_all_messages(const bool dispatch_all_messages) { 82 | this->_dispatch_all_messages = dispatch_all_messages; 83 | return *this; 84 | } 85 | 86 | bool OFServerSettings::dispatch_all_messages() { 87 | return this->_dispatch_all_messages; 88 | } 89 | 90 | bool OFServerSettings::use_hello_elements() { 91 | return this->_use_hello_elements; 92 | } 93 | 94 | OFServerSettings& OFServerSettings::use_hello_elements(const bool use_hello_elements) { 95 | this->_use_hello_elements = use_hello_elements; 96 | return *this; 97 | } 98 | 99 | bool OFServerSettings::keep_data_ownership() { 100 | return this->_keep_data_ownership; 101 | } 102 | 103 | OFServerSettings& OFServerSettings::keep_data_ownership(const bool keep_data_ownership) { 104 | this->_keep_data_ownership = keep_data_ownership; 105 | return *this; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /include/aca_message_pulsar_consumer.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef PULSAR_CONSUMER_H 16 | #define PULSAR_CONSUMER_H 17 | 18 | #include "pulsar/Client.h" 19 | #include "pulsar/Consumer.h" 20 | #include "pulsar/ConsumerConfiguration.h" 21 | #include "pulsar/Message.h" 22 | #include "pulsar/Result.h" 23 | #include "pulsar/ConsumerType.h" 24 | #include "pulsar/KeySharedPolicy.h" 25 | 26 | 27 | using namespace pulsar; 28 | using std::string; 29 | 30 | namespace aca_message_pulsar 31 | { 32 | class ACA_Message_Pulsar_Consumer { 33 | private: 34 | string brokers_list; // IP addresses of pulsar brokers, format: pulsar:://:, example: pulsar://10.213.43.188:9092 35 | 36 | string multicast_subscription_name; // Subscription name of the multicast pulsar consumer 37 | string unicast_subscription_name; // Subscription name of the unicast pulsar consumer 38 | 39 | string multicast_topic_name; //A string representation of the topic to be consumed, for example: /hostid/00000000-0000-0000-0000-000000000000/netwconf/ 40 | string unicast_topic_name; 41 | 42 | ConsumerConfiguration multicast_consumer_config; //Configuration of the mulitcast pulsar consumer 43 | ConsumerConfiguration unicast_consumer_config; //Configuration of the unicast pulsar consumer 44 | 45 | Client *ptr_multicast_client; //A pointer to the multicast pulsar client 46 | Client *ptr_unicast_client; //A pointer to the unicast pulsar client 47 | 48 | Consumer multicast_consumer; 49 | Consumer unicast_consumer; 50 | 51 | private: 52 | void setMulticastSubscriptionName(string subscription_name); 53 | 54 | void setUnicastSubscriptionName(string subscription_name); 55 | 56 | void setBrokers(string brokers); 57 | 58 | void setMulticastTopicName(string topic); 59 | 60 | void setUnicastTopicName(string topic); 61 | 62 | 63 | 64 | public: 65 | ACA_Message_Pulsar_Consumer(string topic, string brokers, string subscription_name); 66 | 67 | ~ACA_Message_Pulsar_Consumer(); 68 | 69 | string getBrokers() const; 70 | 71 | string getMulticastTopicName() const; 72 | 73 | string getUnicastTopicName() const; 74 | 75 | string getMulticastSubscriptionName() const; 76 | 77 | string getUnicastSubscriptionName() const; 78 | 79 | bool multicastConsumerDispatched(); 80 | 81 | bool unicastConsumerDispatched(int stickyHash); 82 | 83 | //static void listener(Consumer consumer, const Message& message); 84 | 85 | 86 | }; 87 | 88 | } // namespace aca_message_pulsar 89 | #endif 90 | -------------------------------------------------------------------------------- /include/of_message.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #pragma once 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | class OFRawBuf { 23 | public: 24 | virtual ~OFRawBuf() = default; 25 | virtual void* data() = 0; 26 | virtual size_t len() = 0; 27 | }; 28 | 29 | class OFMessage { 30 | public: 31 | virtual ~OFMessage() = default; 32 | // xid 33 | virtual uint32_t xid() = 0; 34 | virtual void set_xid(uint32_t id) = 0; 35 | // pack 36 | virtual std::shared_ptr pack() = 0; 37 | }; 38 | 39 | typedef uint32_t ofmsg_xid_t; 40 | typedef std::shared_ptr ofmsg_ptr_t; 41 | typedef std::shared_ptr ofbuf_ptr_t; 42 | 43 | class BundleFlowModMessage { 44 | public: 45 | BundleFlowModMessage(const std::vector flow_mods, std::atomic* fm_xid) : 46 | _flow_mods(flow_mods), 47 | _fm_xid(fm_xid) { } 48 | 49 | ~BundleFlowModMessage() = default; 50 | 51 | uint32_t get_bundle_id() { 52 | return _bundle_id; 53 | } 54 | 55 | std::shared_ptr pack_open_req(); 56 | std::shared_ptr pack_commit_req(); 57 | std::vector > pack_flow_mods(); 58 | 59 | private: 60 | // bundle_id is generated from BundleCtrlMessage->pack() 61 | uint32_t _bundle_id; 62 | // starting x_id (auto increased for each message in this bundle, so all unique) 63 | // need to sync auto increased value with caller for overall OF msg xid management 64 | std::atomic* _fm_xid; 65 | // each flow mod message may have different op_type, like bundling add/mod/delete flow operations together 66 | std::vector _flow_mods; 67 | }; 68 | 69 | class BundleReplyMessage { 70 | public: 71 | BundleReplyMessage() { } 72 | 73 | ~BundleReplyMessage() = default; 74 | 75 | uint32_t get_bundle_id() { 76 | return _bundle_id; 77 | } 78 | 79 | uint16_t get_type() { 80 | return _type; 81 | } 82 | 83 | void unpack(void* data); 84 | 85 | private: 86 | uint32_t _bundle_id; 87 | 88 | uint16_t _type; 89 | }; 90 | 91 | ofmsg_ptr_t create_add_flow(const std::string& flow, bool bundle = false); 92 | ofmsg_ptr_t create_mod_flow(const std::string& flow, bool strict); 93 | ofmsg_ptr_t create_del_flow(const std::string& match, bool strict); 94 | std::vector create_add_flows(const std::vector& flows, bool bundle = false); 95 | ofbuf_ptr_t create_packet_out(const char* option); -------------------------------------------------------------------------------- /docs/mizar_communication.adoc: -------------------------------------------------------------------------------- 1 | = Communication Protocol with Mizar 2 | Eric Li 3 | v0.1, 2020-03-20 4 | :toc: right 5 | 6 | == Communication between ACA and kernel mode Transit Agent 7 | 8 | +--------------------+ 9 | | Alcor Control | 10 | | Agent | 11 | +--------------------+ 12 | | Transit Daemon | 13 | +------------------ -+ User Mode 14 | +--------------------------------------------------+ 15 | +--------------------+ Kernel Mode 16 | | Transit Agent | 17 | | xdp program | 18 | +--------------------+ 19 | 20 | == Workflow with Mizar 21 | 22 | . Customer creates a new VPC 23 | .. Allocate transit router 24 | ... Smart placement [router1, router2] 25 | ... Go to router1, router2 and add VPC to the VPC table (Call “Update VPC”) (VPC table) 26 | . Customer creates new network(subnet) 27 | .. Allocate transit switch 28 | ... Smart placement [Switch1, Switch2] 29 | ... Go to router1, and router2 and “Update net” (net table) 30 | ... Go to s1, s2 and call “Update net" (net table) 31 | . Customer create a VM with endpoint 1 at net0 32 | .. Allocate endpoint 33 | ... Go to all switches (s1,s2) update endpoint 34 | .... make sure at least one or more transit switch ready before the next step 35 | .... TODO: need to be able to notify network controller that a particular transit switch programming is completed 36 | ... Go to VM Host create endpoint and update the transit switch info in endpoint table 37 | 38 | == Mizar Network Configuration 39 | 40 | [width="100%",options="header"] 41 | |==================== 42 | | VPC table | 43 | | VPC0 | {10.0.0.0/16,[172.3,172.4]} 44 | |==================== 45 | 46 | [width="100%",options="header"] 47 | |==================== 48 | |Network Table | 49 | |Net0 |{10.0.0.0/25,[172.1,172.2]} 50 | |==================== 51 | 52 | [width="100%",options="header"] 53 | |==================== 54 | |Endpoint Table | | | 55 | |10.0.0.1 |Net0 |VPC0 |[172.1,...] 56 | |10.0.0.2 |Net0 |VPC0 |[172.2,...] 57 | |==================== 58 | 59 | == Transit Agent Manager 60 | 61 | This will interface with user mode Transit daemon to program the transit router/switch/endpoint. Using the below APIs: 62 | 63 | *mizar/src/rpcgen/trn_rpc_protocol.x* 64 | 65 | [source,c] 66 | ------------------------------------------------------------ 67 | int UPDATE_VPC(rpc_trn_vpc_t) = 1; 68 | int UPDATE_NET(rpc_trn_network_t) = 2; 69 | int UPDATE_EP(rpc_trn_endpoint_t) = 3; 70 | int UPDATE_AGENT_EP(rpc_trn_endpoint_t) = 4; 71 | int UPDATE_AGENT_MD(rpc_trn_agent_metadata_t) = 5; 72 | 73 | int DELETE_VPC(rpc_trn_vpc_key_t) = 6; 74 | int DELETE_NET(rpc_trn_network_key_t) = 7; 75 | int DELETE_EP(rpc_trn_endpoint_key_t) = 8; 76 | int DELETE_AGENT_EP(rpc_trn_endpoint_key_t) = 9; 77 | int DELETE_AGENT_MD(void) = 10; 78 | 79 | rpc_trn_vpc_t GET_VPC(rpc_trn_vpc_key_t) = 11; 80 | rpc_trn_network_t GET_NET(rpc_trn_network_key_t) = 12; 81 | rpc_trn_endpoint_t GET_EP(rpc_trn_endpoint_key_t) = 13; 82 | rpc_trn_endpoint_t GET_AGENT_EP(rpc_trn_endpoint_key_t) = 14; 83 | rpc_trn_agent_metadata_t GET_AGENT_MD(void) = 15; 84 | 85 | int LOAD_TRANSIT_XDP(rpc_trn_xdp_intf_t) = 16; 86 | int LOAD_TRANSIT_AGENT_XDP(rpc_trn_xdp_intf_t) = 17; 87 | 88 | int UNLOAD_TRANSIT_XDP(rpc_intf_t) = 18; 89 | int UNLOAD_TRANSIT_AGENT_XDP(rpc_intf_t) = 19; 90 | ------------------------------------------------------------ 91 | 92 | Note: XDP programs are preloaded on physical NIC when system is booted up. For XDP programs attached to virtual interfaces, they will be loaded on demand by ACA when new ports are created on VMs or containers. -------------------------------------------------------------------------------- /include/aca_net_programming_if.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_NET_PROGRAMMING_IF_H 16 | #define ACA_NET_PROGRAMMING_IF_H 17 | 18 | #include "goalstateprovisioner.grpc.pb.h" 19 | 20 | // Core Network Programming Interface class 21 | namespace aca_net_programming_if 22 | { 23 | class ACA_Core_Net_Programming_Interface { 24 | public: 25 | // pure virtual functions providing interface framework. 26 | virtual int initialize() = 0; 27 | 28 | virtual int 29 | update_vpc_state_workitem(const alcor::schema::VpcState current_VpcState, 30 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 31 | 32 | virtual int 33 | update_subnet_state_workitem(const alcor::schema::SubnetState current_SubnetState, 34 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 35 | 36 | virtual int 37 | update_port_state_workitem(const alcor::schema::PortState current_PortState, 38 | alcor::schema::GoalState &parsed_struct, 39 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 40 | 41 | virtual int 42 | update_port_state_workitem(const alcor::schema::PortState current_PortState, 43 | alcor::schema::GoalStateV2 &parsed_struct, 44 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 45 | 46 | virtual int 47 | update_neighbor_state_workitem(const alcor::schema::NeighborState current_NeighborState, 48 | alcor::schema::GoalState &parsed_struct, 49 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 50 | 51 | virtual int 52 | update_neighbor_state_workitem(const alcor::schema::NeighborState current_NeighborState, 53 | alcor::schema::GoalStateV2 &parsed_struct, 54 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 55 | 56 | virtual int 57 | update_router_state_workitem(const alcor::schema::RouterState current_RouterState, 58 | alcor::schema::GoalState &parsed_struct, 59 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 60 | 61 | virtual int 62 | update_router_state_workitem(const alcor::schema::RouterState current_RouterState, 63 | alcor::schema::GoalStateV2 &parsed_struct, 64 | alcor::schema::GoalStateOperationReply &gsOperationReply) = 0; 65 | }; 66 | } // namespace aca_net_programming_if 67 | #endif // #ifndef ACA_NET_PROGRAMMING_IF_H 68 | -------------------------------------------------------------------------------- /include/libfluid-base/base/BaseOFServer.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /** @file */ 17 | #ifndef __BASEOFSERVER_HH__ 18 | #define __BASEOFSERVER_HH__ 19 | 20 | #include 21 | #include 22 | 23 | #include "EventLoop.hh" 24 | #include "BaseOFConnection.hh" 25 | 26 | #include 27 | 28 | namespace fluid_base { 29 | 30 | /** 31 | A BaseOFServer manages the very basic functions of OpenFlow connections, such 32 | as notifying of new messages and network-level events. It is an abstract class 33 | that should be overriden by another class to provide OpenFlow features. 34 | */ 35 | class BaseOFServer : public BaseOFHandler { 36 | public: 37 | /** 38 | Create a BaseOFServer. 39 | 40 | @param address address to bind the server 41 | @param port TCP port on which the server will listen 42 | @param nevloops number of event loops to run. Connections will be 43 | attributed to event loops running on threads on a 44 | round-robin fashion. The first event loop will listen for 45 | new connections. 46 | @param secure whether the connections should use TLS. TLS support must 47 | compiled into the library and you need to call libfluid_ssl_init before you 48 | can use this feature. 49 | */ 50 | BaseOFServer(const char* address, 51 | const int port, 52 | const int nevloops = 1, 53 | const bool secure = false); 54 | virtual ~BaseOFServer(); 55 | 56 | /** 57 | Start the server. It will listen at the port declared in the 58 | constructor, assigning connections to event loops running in threads and 59 | optionally blocking the calling thread until BaseOFServer::stop is called. 60 | 61 | @param block block the calling thread while the server is running 62 | */ 63 | virtual bool start(bool block = false); 64 | 65 | /** 66 | Stop the server. It will stop listening to new connections and signal the 67 | event loops to stop running. 68 | 69 | It will eventually unblock BaseOFServer::start if it is blocking. 70 | */ 71 | virtual void stop(); 72 | 73 | // BaseOFHandler methods 74 | virtual void base_connection_callback(BaseOFConnection* conn, 75 | BaseOFConnection::Event event_type); 76 | virtual void base_message_callback(BaseOFConnection* conn, 77 | void* data, 78 | size_t len) { printf("Calling fake msgcb\n"); }; 79 | virtual void free_data(void* data); 80 | 81 | private: 82 | // TODO: hide part of this in LibEventBaseOFServer 83 | char* address; 84 | char port[6]; 85 | 86 | EventLoop** eventloops; 87 | EventLoop* main; 88 | pthread_t* threads; 89 | bool blocking; 90 | bool secure; 91 | 92 | int eventloop; 93 | int nthreads; 94 | int nconn; 95 | 96 | bool listen(EventLoop* w); 97 | EventLoop* choose_eventloop(); 98 | 99 | class LibEventBaseOFServer; 100 | friend class LibEventBaseOFServer; 101 | LibEventBaseOFServer* m_implementation; 102 | }; 103 | 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /include/libfluid-msg/of10/of10match.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #ifndef OF10OPENFLOW_MATCH_H 17 | #define OF10OPENFLOW_MATCH_H 1 18 | 19 | #include 20 | #include 21 | #include "../util/util.h" 22 | #include "../util/ethaddr.hh" 23 | #include "../util/ipaddr.hh" 24 | #include "openflow-10.h" 25 | 26 | namespace fluid_msg { 27 | 28 | namespace of10 { 29 | 30 | class Match { 31 | private: 32 | uint32_t wildcards_; /* Wildcard fields. */ 33 | uint16_t in_port_; /* Input switch port. */ 34 | EthAddress dl_src_; /* Ethernet source address. */ 35 | EthAddress dl_dst_; /* Ethernet destination address. */ 36 | uint16_t dl_vlan_; /* Input VLAN id. */ 37 | uint8_t dl_vlan_pcp_; /* Input VLAN priority. */ 38 | uint16_t dl_type_; /* Ethernet frame type. */ 39 | uint8_t nw_tos_; /* IP ToS (actually DSCP field, 6 bits). */ 40 | uint8_t nw_proto_; /* IP protocol or lower 8 bits of 41 | * ARP opcode. */ 42 | IPAddress nw_src_; /* IP source address. */ 43 | IPAddress nw_dst_; /* IP destination address. */ 44 | uint16_t tp_src_; /* TCP/UDP source port. */ 45 | uint16_t tp_dst_; /* TCP/UDP destination port. */ 46 | public: 47 | Match(); 48 | ~Match() { 49 | } 50 | ; 51 | bool operator==(const Match &other) const; 52 | bool operator!=(const Match &other) const; 53 | size_t pack(uint8_t *buffer); 54 | of_error unpack(uint8_t *buffer); 55 | uint32_t wildcards() { 56 | return this->wildcards_; 57 | } 58 | uint16_t in_port() { 59 | return this->in_port_; 60 | } 61 | EthAddress dl_src() { 62 | return this->dl_src_; 63 | } 64 | EthAddress dl_dst() { 65 | return this->dl_dst_; 66 | } 67 | uint16_t dl_vlan() { 68 | return this->dl_vlan_; 69 | } 70 | uint8_t dl_vlan_pcp() { 71 | return this->dl_vlan_pcp_; 72 | } 73 | uint16_t dl_type() { 74 | return this->dl_type_; 75 | } 76 | uint8_t nw_tos() { 77 | return this->nw_tos_; 78 | } 79 | uint8_t nw_proto() { 80 | return this->nw_proto_; 81 | } 82 | IPAddress nw_src() { 83 | return this->nw_src_; 84 | } 85 | IPAddress nw_dst() { 86 | return this->nw_dst_; 87 | } 88 | uint16_t tp_src() { 89 | return this->tp_src_; 90 | } 91 | uint16_t tp_dst() { 92 | return this->tp_dst_; 93 | } 94 | 95 | void wildcards(uint32_t wildcards); 96 | void in_port(uint16_t in_port); 97 | void dl_src(const EthAddress &dl_src); 98 | void dl_dst(const EthAddress &dl_dst); 99 | void dl_vlan(uint16_t dl_vlan); 100 | void dl_vlan_pcp(uint8_t dl_vlan_pcp); 101 | void dl_type(uint16_t dl_type); 102 | void nw_tos(uint8_t nw_tos); 103 | void nw_proto(uint8_t nw_proto); 104 | void nw_src(const IPAddress &nw_src); 105 | void nw_dst(const IPAddress &nw_dst); 106 | void nw_src(const IPAddress &nw_src, uint32_t prefix); 107 | void nw_dst(const IPAddress &nw_src, uint32_t prefix); 108 | void tp_src(uint16_t tp_src); 109 | void tp_dst(uint16_t tp_dst); 110 | }; 111 | 112 | } //End of Namespace of10 113 | } //End of namespace fluid_msg 114 | #endif 115 | 116 | -------------------------------------------------------------------------------- /src/ovs/libfluid-msg/util/ipaddr.cc: -------------------------------------------------------------------------------- 1 | #include "libfluid-msg/util/ipaddr.hh" 2 | #include 3 | #include 4 | 5 | namespace fluid_msg{ 6 | 7 | IPAddress::IPAddress():version(NONE){ 8 | memset(&ipv6, 0x0, 16); 9 | } 10 | 11 | IPAddress::IPAddress(const char* address){ 12 | std::string saddress(address); 13 | if (saddress.find('.') != std::string::npos){ 14 | this->version = IPV4; 15 | this->ipv4 = IPv4from_string(address); 16 | } 17 | else if (saddress.find(':') != std::string::npos){ 18 | this->version = IPV6; 19 | struct in6_addr addr = IPv6from_string(address); 20 | memcpy(this->ipv6, &addr, 16); 21 | } 22 | } 23 | 24 | IPAddress::IPAddress(const std::string &address){ 25 | if (address.find('.') != std::string::npos){ 26 | this->version = IPV4; 27 | this->ipv4 = IPv4from_string(address); 28 | } 29 | else if (address.find(':') != std::string::npos){ 30 | this->version = IPV6; 31 | struct in6_addr addr = IPv6from_string(address); 32 | memcpy(this->ipv6, &addr, 16); 33 | } 34 | } 35 | 36 | IPAddress::IPAddress(const IPAddress &other): version(other.version) { 37 | if(this->version == IPV4){ 38 | this->ipv4 = other.ipv4; 39 | } 40 | else { 41 | memcpy(&this->ipv6, &other.ipv6, 16); 42 | } 43 | } 44 | 45 | IPAddress::IPAddress(const uint32_t ip_addr): version(IPV4), ipv4(ip_addr){ 46 | } 47 | 48 | IPAddress::IPAddress(const uint8_t ip_addr[16]):version(IPV6){ 49 | memcpy(this->ipv6, ip_addr, 16); 50 | } 51 | 52 | IPAddress::IPAddress(const struct in_addr& ip_addr):version(IPV4), ipv4(ip_addr.s_addr) { 53 | } 54 | 55 | IPAddress::IPAddress(const struct in6_addr& ip_addr):version(IPV6){ 56 | memcpy(&ipv6, &ip_addr, sizeof(struct in6_addr)); 57 | } 58 | 59 | IPAddress& IPAddress::operator=(const IPAddress &other) { 60 | if (this != &other) { 61 | this->version = other.version; 62 | if(this->version == IPV4){ 63 | this->ipv4 = other.ipv4; 64 | } 65 | else { 66 | memcpy(&this->ipv6, &other.ipv6, 16); 67 | } 68 | } 69 | return *this; 70 | } 71 | 72 | bool IPAddress::operator==(const IPAddress &other) const { 73 | if (this->version == IPV4 && other.version == IPV4){ 74 | return (this->ipv4 == other.ipv4); 75 | } 76 | else { 77 | if (this->version == IPV6 && other.version == IPV6){ 78 | return memcmp(other.ipv6, &other.ipv6, 16); 79 | } 80 | } 81 | return false; 82 | 83 | } 84 | 85 | int IPAddress::get_version() const { 86 | return this->version; 87 | } 88 | 89 | void IPAddress::setIPv4(uint32_t address){ 90 | this->version = IPV4; 91 | this->ipv4 = address; 92 | } 93 | 94 | void IPAddress::setIPv6(uint8_t address[16]){ 95 | this->version = IPV6; 96 | memcpy(this->ipv6, address, 16); 97 | } 98 | 99 | uint32_t IPAddress::getIPv4(){ 100 | return this->ipv4; 101 | } 102 | 103 | uint8_t* IPAddress::getIPv6(){ 104 | return this->ipv6; 105 | } 106 | 107 | uint32_t IPAddress::IPv4from_string(const std::string &address){ 108 | struct in_addr n; 109 | int pos = address.find('/'); 110 | if (pos != std::string::npos){ 111 | int prefix = atoi(address.substr(pos+1).c_str()); 112 | std::string ip = address.substr(0, pos); 113 | inet_pton(AF_INET, ip.c_str(), &n); 114 | for(int i = prefix; i < 32; i++){ 115 | n.s_addr &= ~(1 << i); 116 | } 117 | } 118 | else{ 119 | inet_pton(AF_INET, address.c_str(), &n); 120 | } 121 | return n.s_addr; 122 | } 123 | 124 | struct in6_addr IPAddress::IPv6from_string(const std::string &address){ 125 | struct in6_addr n6; 126 | inet_pton(AF_INET6, address.c_str(), &n6); 127 | return n6; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /test/zeta-aca-test_controllerScript/data/zeta_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "zeta_api_ip": "http://10.213.43.90", 3 | "aca_nodes": { 4 | "ip": [ 5 | "10.213.43.92", 6 | "10.213.43.93" 7 | ], 8 | "username": "***", 9 | "password": "***" 10 | }, 11 | "server_aca_repo_path": "/home/user/src/Github.com/zzxgzgz/alcor-control-agent", 12 | "ZGC_data": { 13 | "name": "ZGC_test106", 14 | "description": "ZGC_test106", 15 | "ip_start": "192.168.20.100", 16 | "ip_end": "192.168.20.115", 17 | "port_ibo": "8300", 18 | "overlay_type": "vxlan" 19 | }, 20 | "VPC_data": [ 21 | { 22 | "vpc_id": "3dda2801-d675-4688-a63f-dcda8d327f61", 23 | "vni": "888" 24 | } 25 | ], 26 | "PORT_data": [ 27 | { 28 | "port_id": "333d4fae-7dec-11d0-a765-00a0c9341120", 29 | "vpc_id": "3dda2801-d675-4688-a63f-dcda8d327f61", 30 | "ips_port": [ 31 | { 32 | "ip": "10.10.0.92", 33 | "vip": "" 34 | } 35 | ], 36 | "mac_port": "cc:dd:ee:ff:11:22", 37 | "ip_node": "192.168.20.92", 38 | "mac_node": "e8:bd:d1:01:77:ec" 39 | }, 40 | { 41 | "port_id": "99976feae-7dec-11d0-a765-00a0c9342230", 42 | "vpc_id": "3dda2801-d675-4688-a63f-dcda8d327f61", 43 | "ips_port": [ 44 | { 45 | "ip": "10.10.0.93", 46 | "vip": "" 47 | } 48 | ], 49 | "mac_port": "6c:dd:ee:ff:11:32", 50 | "ip_node": "192.168.20.93", 51 | "mac_node": "e8:bd:d1:01:72:c8" 52 | } 53 | ], 54 | "NODE_data": [ 55 | { 56 | "zgc_id": "zgc_id", 57 | "description": "znode90", 58 | "name": "znode90", 59 | "ip_control": "192.168.20.190", 60 | "id_control": "ubuntu", 61 | "pwd_control": "Lab12345", 62 | "inf_tenant": "ens4", 63 | "mac_tenant": "52:54:00:5e:99:ac", 64 | "inf_zgc": "ens3", 65 | "mac_zgc": "52:54:00:f5:aa:52" 66 | }, 67 | { 68 | "zgc_id": "zgc_id", 69 | "description": "znode91", 70 | "name": "znode91", 71 | "ip_control": "192.168.20.191", 72 | "id_control": "ubuntu", 73 | "pwd_control": "Lab12345", 74 | "inf_tenant": "ens4", 75 | "mac_tenant": "52:54:00:5a:2a:01", 76 | "inf_zgc": "ens3", 77 | "mac_zgc": "52:54:00:ed:60:ab" 78 | }, 79 | { 80 | "zgc_id": "zgc_id", 81 | "description": "znode92", 82 | "name": "znode92", 83 | "ip_control": "192.168.20.192", 84 | "id_control": "ubuntu", 85 | "pwd_control": "Lab12345", 86 | "inf_tenant": "ens4", 87 | "mac_tenant": "52:54:00:8b:04:15", 88 | "inf_zgc": "ens3", 89 | "mac_zgc": "52:54:00:0f:51:3a" 90 | }, 91 | { 92 | "zgc_id": "zgc_id", 93 | "description": "znode93", 94 | "name": "znode93", 95 | "ip_control": "192.168.20.193", 96 | "id_control": "ubuntu", 97 | "pwd_control": "Lab12345", 98 | "inf_tenant": "ens4", 99 | "mac_tenant": "52:54:00:0a:2e:8b", 100 | "inf_zgc": "ens3", 101 | "mac_zgc": "52:54:00:42:b4:e6" 102 | }, 103 | { 104 | "zgc_id": "zgc_id", 105 | "description": "znode94", 106 | "name": "znode94", 107 | "ip_control": "192.168.20.194", 108 | "id_control": "ubuntu", 109 | "pwd_control": "Lab12345", 110 | "inf_tenant": "ens4", 111 | "mac_tenant": "52:54:00:63:8f:4d", 112 | "inf_zgc": "ens3", 113 | "mac_zgc": "52:54:00:38:52:89" 114 | }, 115 | { 116 | "zgc_id": "zgc_id", 117 | "description": "znode95", 118 | "name": "znode95", 119 | "ip_control": "192.168.20.195", 120 | "id_control": "ubuntu", 121 | "pwd_control": "Lab12345", 122 | "inf_tenant": "ens4", 123 | "mac_tenant": "52:54:00:99:03:ae", 124 | "inf_zgc": "ens3", 125 | "mac_zgc": "52:54:00:3e:6c:e8" 126 | } 127 | ] 128 | } -------------------------------------------------------------------------------- /test/gtest/aca_test_on_demand.cpp: -------------------------------------------------------------------------------- 1 | #include "aca_log.h" 2 | #include "aca_util.h" 3 | #include "aca_config.h" 4 | #include "aca_vlan_manager.h" 5 | #include "aca_ovs_l2_programmer.h" 6 | #include "aca_comm_mgr.h" 7 | #include "gtest/gtest.h" 8 | #include "goalstate.pb.h" 9 | #include "aca_ovs_control.h" 10 | #include /* for getopt */ 11 | #include 12 | #include 13 | #include 14 | #include "aca_grpc.h" 15 | #include "aca_grpc_client.h" 16 | #include "aca_on_demand_engine.h" 17 | 18 | extern GoalStateProvisionerClientImpl *g_grpc_client; 19 | 20 | TEST(aca_on_demand_testcases, DISABLED_grpc_client_connectivity_test) 21 | { 22 | sleep(10); 23 | ACA_LOG_INFO("%s", "Start of DISABLED_grpc_client_connectivity_test\n"); 24 | ASSERT_NE(g_grpc_client, nullptr); 25 | ACA_LOG_INFO("%s", "Made sure that g_grpc_server is not null\n"); 26 | 27 | // test sending a request with an expected request_id, which should return 28 | // a reply with the same request_id, and a SUCCESS operation status. 29 | 30 | HostRequest example_request_with_expected_id; 31 | grpc::CompletionQueue cq; 32 | example_request_with_expected_id.add_state_requests(); 33 | string expected_request_id = "12345"; 34 | string unexpected_request_id = "54321"; 35 | 36 | example_request_with_expected_id.mutable_state_requests(0)->set_request_id(expected_request_id); 37 | ACA_LOG_INFO("Channel state: %d\n", g_grpc_client->chan_->GetState(false)); 38 | ACA_LOG_INFO("Request one's request ID: %s\n", 39 | example_request_with_expected_id.state_requests(0).request_id().c_str()); 40 | g_grpc_client->RequestGoalStates(&example_request_with_expected_id, &cq); 41 | 42 | HostRequest example_request_with_unexpected_id; 43 | example_request_with_unexpected_id.add_state_requests(); 44 | example_request_with_unexpected_id.mutable_state_requests(0)->set_request_id(unexpected_request_id); 45 | ACA_LOG_INFO("Request two's request ID: %s\n", 46 | example_request_with_unexpected_id.state_requests(0).request_id().c_str()); 47 | 48 | g_grpc_client->RequestGoalStates(&example_request_with_unexpected_id, &cq); 49 | 50 | void *got_tag; 51 | bool ok = false; 52 | HostRequestReply_HostRequestOperationStatus hostOperationStatus; 53 | OperationStatus replyStatus; 54 | 55 | ACA_LOG_INFO("%s\n", "Beginning of process_async_grpc_replies"); 56 | int counter = 0; 57 | while (cq.Next(&got_tag, &ok)) { 58 | counter = counter + 1; 59 | ACA_LOG_INFO("Inside the while loop, counter: %d\n", counter); 60 | if (ok) { 61 | ACA_LOG_INFO("%s\n", "This call is OK"); 62 | AsyncClientCall *call = static_cast(got_tag); 63 | ACA_LOG_INFO("%s\n", "Static cast done successfully"); 64 | if (call->status.ok()) { 65 | ACA_LOG_INFO("%s\n", "Got an GRPC reply that is OK, need to process it."); 66 | for (int i = 0; i < call->reply.operation_statuses_size(); i++) { 67 | hostOperationStatus = call->reply.operation_statuses(i); 68 | replyStatus = hostOperationStatus.operation_status(); 69 | ACA_LOG_INFO("This reply has request ID: %s\n", 70 | hostOperationStatus.request_id().c_str()); 71 | if (hostOperationStatus.request_id() == expected_request_id) { 72 | ASSERT_EQ(hostOperationStatus.operation_status(), OperationStatus::SUCCESS); 73 | } else { 74 | ASSERT_EQ(hostOperationStatus.operation_status(), OperationStatus::FAILURE); 75 | } 76 | } 77 | ACA_LOG_DEBUG("Return from NCM - Reply Status: %s\n", 78 | to_string(replyStatus).c_str()); 79 | } else { 80 | ACA_LOG_INFO("%s, error details: %s\n", "Call->status.ok() is false", 81 | call->status.error_message().c_str()); 82 | } 83 | delete call; 84 | } else { 85 | ACA_LOG_INFO("%s\n", "Got an GRPC reply that is NOT OK, don't need to process the data"); 86 | } 87 | if (counter == 2) 88 | break; 89 | } 90 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/futurewei-cloud/alcor-control-agent.svg?branch=master)](https://travis-ci.org/github/futurewei-cloud/alcor-control-agent) 2 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 3 | [![Percentage of issues still open](http://isitmaintained.com/badge/open/futurewei-cloud/alcor-control-agent.svg)](http://isitmaintained.com/project/futurewei-cloud/alcor-control-agent "Percentage of issues still open") 4 | [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/futurewei-cloud/alcor-control-agent.svg)](http://isitmaintained.com/project/futurewei-cloud/alcor-control-agent "Average time to resolve an issue") 5 | 6 | # Alcor Control Agent 7 | Next-gen networking control plane - Alcor Control Agent 8 | 9 | * For information about how to use Alcor Control Agent, visit [Getting Started](src/README.md) 10 | * To ask questions, raise feature requests and get assistance from our community, join [Alcor Slack](https://alcor-networking.slack.com/) channels ([invitation](https://join.slack.com/t/alcor-networking/shared_invite/zt-cudckviu-hcsMI4LWB4cRWy4hn3N3oQ) for first-time participant) or [Google Group](https://groups.google.com/forum/#!forum/alcor-dev) 11 | * To report an issue, visit [Issues page](https://https://github.com/futurewei-cloud/alcor-control-agent/issues) 12 | 13 | In this README: 14 | 15 | - [Introduction](#introduction) 16 | - [Repositories](#repositories) 17 | - [Directory Structure](#directory-structure) 18 | - [Notes](#notes) 19 | 20 | ## Introduction 21 | 22 | The Cloud Fabric Alcor Control Agent (ACA) runs on each host machine. It serves as a stateless proxy between Alcor controller and host machine networking components for control plane operations. Below are the highlevel Agent components. 23 | 24 | ![Agent Components](docs/images/Agent_v2.jpg) 25 | 26 | ## Repositories 27 | The Alcor project is divided across a few GitHub repositories. 28 | 29 | - [alcor/alcor](https://github.com/futurewei-cloud/alcor): 30 | This is the main repository of Alcor Regional Controller that you are currently looking at. 31 | It hosts controllers' source codes, build and deployment instructions, and various documents that detail the design of Alcor. 32 | 33 | - [alcor/alcor_control_agent](https://github.com/futurewei-cloud/alcor-control-agent): 34 | This repository contains source codes for a host-level stateless agent that connects regional controllers to the host data-plane component. 35 | It is responsible for programming on-host data plane with various network configuration for CURD of _VPC, subnet, port, Security group etc._, 36 | and monitoring network health of containers and VMs on the host. 37 | 38 | - [alcor/integration](https://github.com/futurewei-cloud/alcor-int): 39 | The integration repository contains codes and scripts for end-to-end integration of Alcor control plane with popular orchestration platforms and data plane implementations. 40 | We currently support integration with Kubernetes (via CNI plugin) and Mizar Data Plane. 41 | We will continue to integrate with other orchestration systems and data plane implementations. 42 | 43 | ## Directory Structure 44 | This main repository of Alcor Control Agent is organized as follows: 45 | * build: script and docker files for building 46 | * docs: design documentation 47 | * etc/k8s: k8s integration files 48 | * include: header files 49 | * src: source code 50 | * test: Unit and integration test code 51 | 52 | ## Notes 53 | * ovs_control.h and ovs_control.cpp is based on https://github.com/openvswitch/ovs/blob/master/utilities/ovs-ofctl.c 54 | * libfluid-base/*.h(*.cpp) and libfluid-msg/*.h(*.cpp) are based on https://github.com/OpenNetworkingFoundation/libfluid, the usage of derived class is based on https://github.com/OpenNetworkingFoundation/libfluid/tree/master/examples/controller 55 | * aca_grpc.cpp is based on https://github.com/grpc/grpc/blob/v1.30.0/examples/cpp/route_guide/route_guide_server.cc 56 | * HashMap.h and HashNode.h is based on https://github.com/kshk123/hashMap 57 | -------------------------------------------------------------------------------- /include/aca_ovs_l2_programmer.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_OVS_L2_PROGRAMMER_H 16 | #define ACA_OVS_L2_PROGRAMMER_H 17 | 18 | #include "goalstateprovisioner.grpc.pb.h" 19 | #undef UNUSED 20 | #include "of_controller.h" 21 | #include 22 | #include 23 | 24 | #define PRIORITY_HIGH 50 25 | #define PRIORITY_MID 25 26 | #define PRIORITY_LOW 1 27 | 28 | // OVS L2 programmer implementation class 29 | namespace aca_ovs_l2_programmer 30 | { 31 | class ACA_OVS_L2_Programmer { 32 | public: 33 | static ACA_OVS_L2_Programmer &get_instance(); 34 | 35 | void get_local_host_ips(); 36 | 37 | bool is_ip_on_the_same_host(const std::string hosting_port_ip); 38 | 39 | int setup_ovs_bridges_if_need(); 40 | 41 | int setup_ovs_controller(const std::string ctrler_ip, const int ctrler_port); 42 | 43 | void clean_up_ovs_controller(); 44 | 45 | std::string get_system_port_id(std::string port_name); 46 | 47 | int create_port(const std::string vpc_id, const std::string port_name, 48 | const std::string virtual_ip, const std::string virtual_mac, 49 | uint tunnel_id, ulong &culminative_time); 50 | 51 | int delete_port(const std::string vpc_id, const std::string port_name, 52 | uint tunnel_id, ulong &culminative_time); 53 | 54 | int create_or_update_l2_neighbor(const std::string virtual_ip, const std::string virtual_mac, 55 | const std::string remote_host_ip, 56 | uint tunnel_id, ulong &culminative_time); 57 | 58 | int delete_l2_neighbor(const std::string virtual_ip, const std::string virtual_mac, 59 | uint tunnel_id, ulong &culminative_time); 60 | 61 | void execute_ovsdb_command(const std::string cmd_string, 62 | ulong &culminative_time, int &overall_rc); 63 | 64 | void execute_openflow_command(const std::string cmd_string, 65 | ulong &culminative_time, int &overall_rc); 66 | 67 | void execute_openflow(ulong &culminative_time, 68 | const std::string bridge, 69 | const std::string flow_string, 70 | const std::string action = "add"); 71 | 72 | void packet_out(const char *bridge, const char *options); 73 | 74 | // compiler will flag the error when below is called. 75 | ACA_OVS_L2_Programmer(ACA_OVS_L2_Programmer const &) = delete; 76 | void operator=(ACA_OVS_L2_Programmer const &) = delete; 77 | 78 | private: 79 | OFController* ofctrl; 80 | std::unordered_map port_id_map; 81 | std::vector host_ips_vector; 82 | 83 | ACA_OVS_L2_Programmer(){}; 84 | 85 | ~ACA_OVS_L2_Programmer(){}; 86 | 87 | std::unordered_map get_ovs_bridge_mapping(); 88 | 89 | std::unordered_map get_system_port_ids(); 90 | }; 91 | } // namespace aca_ovs_l2_programmer 92 | #endif // #ifndef ACA_OVS_L2_PROGRAMMER_H -------------------------------------------------------------------------------- /test/zeta-aca-test_controllerScript/data/zeta_data_sdn.json: -------------------------------------------------------------------------------- 1 | { 2 | "zeta_api_ip": "http://172.16.50.8", 3 | "aca_nodes": { 4 | "ip": [ 5 | "172.16.50.221", 6 | "172.16.50.222" 7 | ], 8 | "username": "***", 9 | "password": "***" 10 | }, 11 | "server_aca_repo_path": "/home/sdn/alcor-control-agent", 12 | "ZGC_data": { 13 | "name": "ZGC_test", 14 | "description": "ZGC_test", 15 | "ip_start": "172.16.150.80", 16 | "ip_end": "172.16.150.95", 17 | "port_ibo": "8300", 18 | "overlay_type": "vxlan" 19 | }, 20 | "VPC_data": [ 21 | { 22 | "vpc_id": "3dda2801-d675-4688-a63f-dcda8d327f61", 23 | "vni": "888" 24 | } 25 | ], 26 | "PORT_data": [ 27 | { 28 | "port_id": "333d4fae-7dec-11d0-a765-00a0c9341120", 29 | "vpc_id": "3dda2801-d675-4688-a63f-dcda8d327f61", 30 | "ips_port": [ 31 | { 32 | "ip": "10.10.0.92", 33 | "vip": "" 34 | } 35 | ], 36 | "mac_port": "cc:dd:ee:ff:11:22", 37 | "ip_node": "172.16.150.221", 38 | "mac_node": "64:6e:97:0d:80:a9" 39 | }, 40 | { 41 | "port_id": "99976feae-7dec-11d0-a765-00a0c9342230", 42 | "vpc_id": "3dda2801-d675-4688-a63f-dcda8d327f61", 43 | "ips_port": [ 44 | { 45 | "ip": "10.10.0.93", 46 | "vip": "" 47 | } 48 | ], 49 | "mac_port": "6c:dd:ee:ff:11:32", 50 | "ip_node": "172.16.150.222", 51 | "mac_node": "64:6e:97:1c:8e:65" 52 | } 53 | ], 54 | "NODE_data": [ 55 | { 56 | "zgc_id": "zgc_id", 57 | "description": "znode90", 58 | "name": "znode90", 59 | "ip_control": "172.16.50.190", 60 | "id_control": "ubuntu", 61 | "pwd_control": "Lab12345", 62 | "inf_tenant": "ens4", 63 | "mac_tenant": "52:54:00:a9:3f:b9", 64 | "inf_zgc": "ens3", 65 | "mac_zgc": "52:54:00:1a:cf:38" 66 | }, 67 | { 68 | "zgc_id": "zgc_id", 69 | "description": "znode91", 70 | "name": "znode91", 71 | "ip_control": "172.16.50.191", 72 | "id_control": "ubuntu", 73 | "pwd_control": "Lab12345", 74 | "inf_tenant": "ens4", 75 | "mac_tenant": "52:54:00:69:4d:be", 76 | "inf_zgc": "ens3", 77 | "mac_zgc": "52:54:00:0c:1e:f9" 78 | }, 79 | { 80 | "zgc_id": "zgc_id", 81 | "description": "znode92", 82 | "name": "znode92", 83 | "ip_control": "172.16.50.192", 84 | "id_control": "ubuntu", 85 | "pwd_control": "Lab12345", 86 | "inf_tenant": "ens4", 87 | "mac_tenant": "52:54:00:bb:47:12", 88 | "inf_zgc": "ens3", 89 | "mac_zgc": "52:54:00:bd:96:0b" 90 | }, 91 | { 92 | "zgc_id": "zgc_id", 93 | "description": "znode93", 94 | "name": "znode93", 95 | "ip_control": "172.16.50.193", 96 | "id_control": "ubuntu", 97 | "pwd_control": "Lab12345", 98 | "inf_tenant": "ens4", 99 | "mac_tenant": "52:54:00:ad:3d:1c", 100 | "inf_zgc": "ens3", 101 | "mac_zgc": "52:54:00:f3:ba:7c" 102 | }, 103 | { 104 | "zgc_id": "zgc_id", 105 | "description": "znode94", 106 | "name": "znode94", 107 | "ip_control": "172.16.50.194", 108 | "id_control": "ubuntu", 109 | "pwd_control": "Lab12345", 110 | "inf_tenant": "ens4", 111 | "mac_tenant": "52:54:00:b9:30:17", 112 | "inf_zgc": "ens3", 113 | "mac_zgc": "52:54:00:3d:27:36" 114 | }, 115 | { 116 | "zgc_id": "zgc_id", 117 | "description": "znode95", 118 | "name": "znode95", 119 | "ip_control": "172.16.50.195", 120 | "id_control": "ubuntu", 121 | "pwd_control": "Lab12345", 122 | "inf_tenant": "ens4", 123 | "mac_tenant": "52:54:00:1e:40:5a", 124 | "inf_zgc": "ens3", 125 | "mac_zgc": "52:54:00:23:17:1b" 126 | } 127 | ] 128 | } -------------------------------------------------------------------------------- /src/comm/aca_message_pulsar_producer.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #include 16 | #include 17 | #include "aca_message_pulsar_producer.h" 18 | #include "aca_log.h" 19 | 20 | 21 | using namespace std; 22 | using namespace pulsar; 23 | 24 | namespace aca_message_pulsar 25 | { 26 | ACA_Message_Pulsar_Producer::ACA_Message_Pulsar_Producer(string brokers, string topic) 27 | { 28 | setBrokers(brokers); 29 | setTopicName(topic); 30 | 31 | // Create client 32 | this->ptr_client= new Client(brokers,this->client_config); 33 | } 34 | 35 | ACA_Message_Pulsar_Producer::~ACA_Message_Pulsar_Producer() 36 | { 37 | delete this->ptr_client; 38 | } 39 | 40 | string ACA_Message_Pulsar_Producer::getBrokers() const 41 | { 42 | return this->brokers_list; 43 | } 44 | 45 | string ACA_Message_Pulsar_Producer::getTopicName() const 46 | { 47 | return this->topic_name; 48 | } 49 | 50 | void ACA_Message_Pulsar_Producer::setTopicName(string topic) 51 | { 52 | this->topic_name = topic; 53 | } 54 | 55 | 56 | bool ACA_Message_Pulsar_Producer::publish(string message) 57 | { 58 | Result result; 59 | 60 | // Create a producer 61 | Producer producer; 62 | result = this->ptr_client->createProducer(this->topic_name,producer); 63 | if(result != ResultOk){ 64 | ACA_LOG_ERROR("Failed to create producer, result=%d.\n", result); 65 | return EXIT_FAILURE; 66 | } 67 | 68 | // Create a message 69 | Message msg = MessageBuilder().setContent(message).build(); 70 | result = producer.send(msg); 71 | if(result != ResultOk){ 72 | ACA_LOG_ERROR("Failed to send message %s.\n", message.c_str()); 73 | return EXIT_FAILURE; 74 | } 75 | 76 | ACA_LOG_INFO("Successfully send message %s\n", message.c_str()); 77 | 78 | // Flush all produced messages 79 | producer.flush(); 80 | producer.close(); 81 | return EXIT_SUCCESS; 82 | 83 | } 84 | 85 | bool ACA_Message_Pulsar_Producer::publish(string message, string orderingKey) 86 | { 87 | Result result; 88 | 89 | // Create a producer 90 | Producer producer; 91 | result = this->ptr_client->createProducer(this->topic_name,producer); 92 | if(result != ResultOk){ 93 | ACA_LOG_ERROR("Failed to create producer, result=%d.\n", result); 94 | return EXIT_FAILURE; 95 | } 96 | 97 | // Create a message 98 | Message msg = MessageBuilder().setContent(message).setOrderingKey(orderingKey).build(); 99 | result = producer.send(msg); 100 | if(result != ResultOk){ 101 | ACA_LOG_ERROR("Failed to send message %s.\n", message.c_str()); 102 | return EXIT_FAILURE; 103 | } 104 | 105 | ACA_LOG_INFO("Successfully send message %s\n", message.c_str()); 106 | 107 | // Flush all produced messages 108 | producer.flush(); 109 | producer.close(); 110 | return EXIT_SUCCESS; 111 | 112 | } 113 | void ACA_Message_Pulsar_Producer::setBrokers(string brokers) 114 | { 115 | //TODO: validate string as IP address 116 | this->brokers_list = brokers; 117 | } 118 | 119 | } // namespace aca_message_pulsar 120 | -------------------------------------------------------------------------------- /docs/logs/10_runs_summary_container.log: -------------------------------------------------------------------------------- 1 | 10 goalstate message making GRPC sync call one by one (containers run): 2 | 3 | [***METRICS***] Grand ACA message_total_operation_time: 287736732 nanoseconds or 287 milliseconds 4 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 309260017 nanoseconds or 309 milliseconds 5 | 6 | [***METRICS***] Grand ACA message_total_operation_time: 285838421 nanoseconds or 285 milliseconds 7 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 302548620 nanoseconds or 302 milliseconds 8 | 9 | [***METRICS***] Grand ACA message_total_operation_time: 305146998 nanoseconds or 305 milliseconds 10 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 331036486 nanoseconds or 331 milliseconds 11 | 12 | [***METRICS***] Grand ACA message_total_operation_time: 297145722 nanoseconds or 297 milliseconds 13 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 320532589 nanoseconds or 320 milliseconds 14 | 15 | [***METRICS***] Grand ACA message_total_operation_time: 335791963 nanoseconds or 335 milliseconds 16 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 359490913 nanoseconds or 359 milliseconds 17 | 18 | [***METRICS***] Grand ACA message_total_operation_time: 315427563 nanoseconds or 315 milliseconds 19 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 333704573 nanoseconds or 333 milliseconds 20 | 21 | [***METRICS***] Grand ACA message_total_operation_time: 292985320 nanoseconds or 292 milliseconds 22 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 315479531 nanoseconds or 315 milliseconds 23 | 24 | [***METRICS***] Grand ACA message_total_operation_time: 296757779 nanoseconds or 296 milliseconds 25 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 319079605 nanoseconds or 319 milliseconds 26 | 27 | [***METRICS***] Grand ACA message_total_operation_time: 302073981 nanoseconds or 302 milliseconds 28 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 341244002 nanoseconds or 341 milliseconds 29 | 30 | [***METRICS***] Grand ACA message_total_operation_time: 313873332 nanoseconds or 313 milliseconds 31 | [***METRICS***] GRPC E2E send_goalstate_sync call took: 334800676 nanoseconds or 334 milliseconds 32 | 33 | 34 | 10 goalstate message using one GRPC streaming channel (containers run): 35 | 36 | [***METRICS***] Grand ACA message_total_operation_time: 297429190 nanoseconds or 297 milliseconds 37 | [***METRICS***] Grand send_goalstate_sync call took: 304332299 nanoseconds or 304 milliseconds 38 | 39 | [***METRICS***] Grand ACA message_total_operation_time: 306296174 nanoseconds or 306 milliseconds 40 | [***METRICS***] Grand send_goalstate_sync call took: 314512298 nanoseconds or 314 milliseconds 41 | 42 | [***METRICS***] Grand ACA message_total_operation_time: 294239598 nanoseconds or 294 milliseconds 43 | [***METRICS***] Grand send_goalstate_sync call took: 304991126 nanoseconds or 304 milliseconds 44 | 45 | [***METRICS***] Grand ACA message_total_operation_time: 302513023 nanoseconds or 302 milliseconds 46 | [***METRICS***] Grand send_goalstate_sync call took: 309381901 nanoseconds or 309 milliseconds 47 | 48 | [***METRICS***] Grand ACA message_total_operation_time: 301059778 nanoseconds or 301 milliseconds 49 | [***METRICS***] Grand send_goalstate_sync call took: 308335725 nanoseconds or 308 milliseconds 50 | 51 | [***METRICS***] Grand ACA message_total_operation_time: 309987145 nanoseconds or 309 milliseconds 52 | [***METRICS***] Grand send_goalstate_sync call took: 317679109 nanoseconds or 317 milliseconds 53 | 54 | [***METRICS***] Grand ACA message_total_operation_time: 292076701 nanoseconds or 292 milliseconds 55 | [***METRICS***] Grand send_goalstate_sync call took: 298405058 nanoseconds or 298 milliseconds 56 | 57 | [***METRICS***] Grand ACA message_total_operation_time: 317321501 nanoseconds or 317 milliseconds 58 | [***METRICS***] Grand send_goalstate_sync call took: 326716910 nanoseconds or 326 milliseconds 59 | 60 | [***METRICS***] Grand ACA message_total_operation_time: 329574278 nanoseconds or 329 milliseconds 61 | [***METRICS***] Grand send_goalstate_sync call took: 338692747 nanoseconds or 338 milliseconds 62 | 63 | [***METRICS***] Grand ACA message_total_operation_time: 310421129 nanoseconds or 310 milliseconds 64 | [***METRICS***] Grand send_goalstate_sync call took: 316471534 nanoseconds or 316 milliseconds 65 | -------------------------------------------------------------------------------- /src/comm/aca_grpc_client.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2015 gRPC authors. 4 | * Copyright 2019 The Alcor Authors - file modified. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "goalstateprovisioner.grpc.pb.h" 29 | #include "aca_comm_mgr.h" 30 | #include "aca_log.h" 31 | #include "aca_grpc_client.h" 32 | #include "aca_util.h" 33 | 34 | // extern string g_grpc_server_port; 35 | extern string g_ncm_address; 36 | extern string g_ncm_port; 37 | 38 | using namespace alcor::schema; 39 | using aca_comm_manager::Aca_Comm_Manager; 40 | 41 | void GoalStateProvisionerClientImpl::RequestGoalStates(HostRequest *request, 42 | grpc::CompletionQueue *cq) 43 | { 44 | std::chrono::_V2::steady_clock::time_point start = std::chrono::steady_clock::now(); 45 | grpc::ClientContext ctx; 46 | alcor::schema::HostRequestReply reply; 47 | 48 | // check current grpc channel state, try to connect if needed 49 | grpc_connectivity_state current_state = chan_->GetState(true); 50 | if (current_state == grpc_connectivity_state::GRPC_CHANNEL_SHUTDOWN || 51 | current_state == grpc_connectivity_state::GRPC_CHANNEL_TRANSIENT_FAILURE) { 52 | ACA_LOG_INFO("%s, it is: [%d]\n", 53 | "Channel state is not READY/CONNECTING/IDLE. Try to reconnnect.", 54 | current_state); 55 | this->ConnectToNCM(); 56 | reply.mutable_operation_statuses()->Add(); 57 | reply.mutable_operation_statuses()->at(0).set_operation_status(OperationStatus::FAILURE); 58 | return; 59 | } 60 | AsyncClientCall *call = new AsyncClientCall; 61 | call->response_reader = stub_->AsyncRequestGoalStates(&call->context, *request, cq); 62 | call->response_reader->Finish(&call->reply, &call->status, (void *)call); 63 | ACA_LOG_INFO("Sent hostOperationRequest on thread: %ld\n", std::this_thread::get_id()); 64 | std::chrono::_V2::steady_clock::time_point end = std::chrono::steady_clock::now(); 65 | auto send_host_operation_request_time = 66 | std::chrono::duration_cast(end - start).count(); 67 | ACA_LOG_DEBUG("[METRICS] RequestGoalStates: [%ld], update finished at: [%ld]\nElapsed time for sending hostOperationRequest took: %ld microseconds or %ld milliseconds\n", 68 | start, end, send_host_operation_request_time, 69 | (send_host_operation_request_time / 1000)); 70 | return; 71 | } 72 | 73 | void GoalStateProvisionerClientImpl::ConnectToNCM() 74 | { 75 | ACA_LOG_INFO("%s\n", "Trying to init a new sub to connect to the NCM"); 76 | grpc::ChannelArguments args; 77 | // Channel does a keep alive ping every 10 seconds; 78 | args.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, 10000); 79 | // If the channel does receive the keep alive ping result in 20 seconds, it closes the connection 80 | args.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 20000); 81 | 82 | // Allow keep alive ping even if there are no calls in flight 83 | args.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1); 84 | 85 | chan_ = grpc::CreateCustomChannel(g_ncm_address + ":" + g_ncm_port, 86 | grpc::InsecureChannelCredentials(), args); 87 | stub_ = GoalStateProvisioner::NewStub(chan_); 88 | 89 | ACA_LOG_INFO("%s\n", "After initing a new sub to connect to the NCM"); 90 | } 91 | 92 | void GoalStateProvisionerClientImpl::RunClient() 93 | { 94 | ACA_LOG_INFO("Running a grpc client in a separate thread id: %ld\n", 95 | std::this_thread::get_id()); 96 | this->ConnectToNCM(); 97 | } -------------------------------------------------------------------------------- /include/aca_zeta_oam_server.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_ZETA_OAM_SERVER_H 16 | #define ACA_ZETA_OAM_SERVER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | //#include 23 | #include "hashmap/HashMap.h" 24 | #include "goalstateprovisioner.grpc.pb.h" 25 | 26 | using namespace std; 27 | namespace aca_zeta_oam_server 28 | { 29 | //OAM Message Type 30 | #define OAM_MSG_FLOW_INJECTION (0) 31 | #define OAM_MSG_FLOW_DELETION (1) 32 | #define OAM_MSG_NONE (2) 33 | #define OAM_MSG_MAX (3) 34 | 35 | struct oam_match { 36 | string sip; 37 | string dip; 38 | string sport; 39 | string dport; 40 | string proto; 41 | uint vni; 42 | }; 43 | 44 | struct oam_action { 45 | string inst_nw_dst; 46 | string node_nw_dst; 47 | string inst_dl_dst; 48 | string node_dl_dst; 49 | string idle_timeout; 50 | }; 51 | 52 | struct flow_inject_msg { 53 | struct in_addr inner_src_ip; // Inner Packet SIP 54 | struct in_addr inner_dst_ip; // Inner Packet DIP 55 | uint16_t src_port; // Inner Packet SPort 56 | uint16_t dst_port; // Inner Packet DPort 57 | uint8_t proto; // Inner Packet Protocol 58 | uint8_t vni[3]; // tunnel_id, 3bytes 59 | struct in_addr inst_dst_ip; // Destination Inst IP 60 | struct in_addr node_dst_ip; // Destination Node IP 61 | uint8_t inst_dst_mac[6]; // Destination Inst MAC 62 | uint8_t node_dst_mac[6]; // Destination Node MAC 63 | uint16_t idle_timeout; // 0 - 65536s 64 | }; 65 | 66 | struct flow_del_msg { 67 | struct in_addr inner_src_ip; 68 | struct in_addr inner_dst_ip; 69 | uint16_t src_port; 70 | uint16_t dst_port; 71 | uint8_t proto; 72 | uint8_t vni[3]; 73 | }; 74 | 75 | struct oam_message { 76 | uint32_t op_code; 77 | union op_data { 78 | struct flow_inject_msg msg_inject_flow; 79 | struct flow_del_msg msg_del_flow; 80 | } data; 81 | }; 82 | 83 | class ACA_Zeta_Oam_Server { 84 | public: 85 | ACA_Zeta_Oam_Server(); 86 | ~ACA_Zeta_Oam_Server(); 87 | 88 | static ACA_Zeta_Oam_Server &get_instance(); 89 | void oams_recv(uint32_t udp_dport, void *message); 90 | 91 | private: 92 | uint8_t _get_message_type(oam_message *oammsg); 93 | string _get_mac_addr(uint8_t *mac); 94 | uint _get_tunnel_id(uint8_t *vni); 95 | bool _validate_oam_message(oam_message *oammsg); 96 | bool _check_oam_server_port(uint32_t udp_dport, oam_match match); 97 | oam_match _get_oam_match_field(oam_message *oammsg); 98 | oam_action _get_oam_action_field(oam_message *oammsg); 99 | 100 | int _add_direct_path(oam_match match, oam_action action); 101 | int _del_direct_path(oam_match match); 102 | 103 | void _init_oam_msg_ops(); 104 | void _parse_oam_flow_injection(uint32_t udp_dport, oam_message *oammsg); 105 | void _parse_oam_flow_deletion(uint32_t udp_dport, oam_message *oammsg); 106 | void _parse_oam_none(uint32_t /* in_port */, oam_message *oammsg); 107 | 108 | void (aca_zeta_oam_server::ACA_Zeta_Oam_Server ::*_parse_oam_msg_ops[OAM_MSG_MAX])( 109 | uint32_t udp_dpost, oam_message *oammsg); 110 | }; 111 | } // namespace aca_zeta_oam_server 112 | #endif // #ifndef ACA_Zeta_OAM_SERVER_H -------------------------------------------------------------------------------- /include/libfluid-msg/ofcommon/action.hh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 Open Networking Foundation 2 | // Copyright 2020 Futurewei Cloud 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #ifndef ACTION_H 17 | #define ACTION_H 18 | 19 | #include 20 | #include 21 | #include "../util/util.h" 22 | #include "openflow-common.hh" 23 | 24 | namespace fluid_msg { 25 | 26 | class Action { 27 | protected: 28 | uint16_t type_; 29 | uint16_t length_; 30 | public: 31 | Action(); 32 | Action(uint16_t type, uint16_t length); 33 | virtual ~Action() { 34 | } 35 | ; 36 | virtual size_t pack(uint8_t *buffer); 37 | virtual of_error unpack(uint8_t *buffer); 38 | virtual bool equals(const Action & other); 39 | virtual bool operator==(const Action &other) const; 40 | virtual bool operator!=(const Action &other) const; 41 | virtual Action* clone() { 42 | return new Action(*this); 43 | } 44 | virtual uint16_t set_order() const { 45 | return 0; 46 | } 47 | uint16_t type() { 48 | return this->type_; 49 | } 50 | uint16_t length() { 51 | return this->length_; 52 | } 53 | void type(uint16_t type) { 54 | this->type_ = type; 55 | } 56 | void length(uint16_t length) { 57 | this->length_ = length; 58 | } 59 | static Action * make_of10_action(uint16_t type); 60 | static Action * make_of13_action(uint16_t type); 61 | static bool delete_all(Action * action) { 62 | delete action; 63 | return true; 64 | } 65 | 66 | }; 67 | 68 | class ActionList { 69 | private: 70 | uint16_t length_; 71 | std::list action_list_; 72 | public: 73 | ActionList() 74 | : length_(0) { 75 | } 76 | ; 77 | ActionList(std::list action_list); 78 | ActionList(const ActionList &other); 79 | bool operator==(const ActionList &other) const; 80 | bool operator!=(const ActionList &other) const; 81 | ActionList& operator=(ActionList other); 82 | ~ActionList(); 83 | size_t pack(uint8_t *buffer); 84 | of_error unpack10(uint8_t *buffer); 85 | of_error unpack13(uint8_t *buffer); 86 | friend void swap(ActionList& first, ActionList& second); 87 | uint16_t length() { 88 | return this->length_; 89 | } 90 | std::list action_list(){ 91 | return this->action_list_; 92 | } 93 | void add_action(Action &action); 94 | void add_action(Action *act); 95 | void length(uint16_t length) { 96 | this->length_ = length; 97 | } 98 | }; 99 | 100 | struct comp_action_set_order { 101 | bool operator()(Action * lhs, Action* rhs) const { 102 | return lhs->set_order() < rhs->set_order(); 103 | } 104 | }; 105 | 106 | class ActionSet { 107 | private: 108 | uint16_t length_; 109 | std::set action_set_; 110 | public: 111 | ActionSet() 112 | : length_(0) { 113 | } 114 | ; 115 | ActionSet(std::set action_set); 116 | ActionSet(const ActionSet &other); 117 | bool operator==(const ActionSet &other) const; 118 | bool operator!=(const ActionSet &other) const; 119 | ActionSet& operator=(ActionSet other); 120 | ~ActionSet(); 121 | size_t pack(uint8_t *buffer); 122 | of_error unpack(uint8_t *buffer); 123 | friend void swap(ActionSet& first, ActionSet& second); 124 | uint16_t length() { 125 | return this->length_; 126 | } 127 | std::set action_set(){ 128 | return this->action_set_; 129 | } 130 | void add_action(Action &action); 131 | void add_action(Action *act); 132 | void length(uint16_t length) { 133 | this->length_ = length; 134 | } 135 | }; 136 | 137 | } //End of namespace fluid_msg 138 | #endif 139 | -------------------------------------------------------------------------------- /include/aca_zeta_programming.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_ZETA_PROGRAMMING_H 16 | #define ACA_ZETA_PROGRAMMING_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include "goalstateprovisioner.grpc.pb.h" 22 | #include "hashmap/HashMap.h" 23 | 24 | using namespace std; 25 | 26 | static atomic_uint current_available_group_id(1); 27 | 28 | namespace aca_zeta_programming 29 | { 30 | class FWD_Info { 31 | public: 32 | string ip_addr; 33 | string mac_addr; 34 | 35 | FWD_Info(){}; 36 | ~FWD_Info(){}; 37 | FWD_Info(string ip_addr, string mac_addr) 38 | { 39 | this->ip_addr = ip_addr; 40 | this->mac_addr = mac_addr; 41 | } 42 | 43 | // Overload "==" for hash operation 44 | bool operator==(const FWD_Info &other) const 45 | { 46 | return ((ip_addr == other.ip_addr) && (mac_addr == other.mac_addr)); 47 | }; 48 | 49 | // Overload "!=" for hash operation 50 | bool operator!=(const FWD_Info &other) const 51 | { 52 | return ((ip_addr != other.ip_addr) || (mac_addr != other.mac_addr)); 53 | }; 54 | }; 55 | 56 | //Implement the hash of FWD_info based on std::hash<> 57 | class FWD_Info_Hash { 58 | public: 59 | std::size_t operator()(const FWD_Info &rhs) const 60 | { 61 | return std::hash()(rhs.ip_addr + rhs.mac_addr); 62 | } 63 | }; // namespace aca_zeta_programming 64 | 65 | struct zeta_config { 66 | uint group_id; 67 | uint oam_port; 68 | 69 | // CTSL::HashMap 70 | CTSL::HashMap zeta_buckets; 71 | }; 72 | 73 | class ACA_Zeta_Programming { 74 | public: 75 | ACA_Zeta_Programming(); 76 | ~ACA_Zeta_Programming(); 77 | static ACA_Zeta_Programming &get_instance(); 78 | 79 | void create_entry(string zeta_gateway_id, uint oam_port, 80 | alcor::schema::GatewayConfiguration current_AuxGateway); 81 | 82 | void clear_all_data(); 83 | 84 | int create_zeta_config(const alcor::schema::GatewayConfiguration current_AuxGateway, 85 | uint tunnel_id); 86 | 87 | int delete_zeta_config(const alcor::schema::GatewayConfiguration current_AuxGateway, 88 | uint tunnel_id); 89 | 90 | bool group_rule_exists(uint group_id); 91 | 92 | uint get_oam_port(string zeta_gateway_id); 93 | 94 | uint get_group_id(string zeta_gateway_id); 95 | 96 | bool group_rule_info_correct(uint group_id, string gws_ip, string gws_mac); 97 | 98 | private: 99 | int _create_group_punt_rule(uint tunnel_id, uint group_id); 100 | int _delete_group_punt_rule(uint tunnel_id); 101 | 102 | int _create_zeta_group_entry(zeta_config *zeta_config_in); 103 | int _update_zeta_group_entry(zeta_config *zeta_config_in); 104 | int _delete_zeta_group_entry(zeta_config *zeta_config_in); 105 | 106 | // hashtable 107 | CTSL::HashMap _zeta_config_table; 108 | 109 | //The mutex for modifying group table entry 110 | std::timed_mutex _group_operation_mutex; 111 | 112 | // mutex for reading and writing to _zeta_config_table 113 | mutex _zeta_config_table_mutex; 114 | }; 115 | } // namespace aca_zeta_programming 116 | #endif // #ifndef ACA_ZETA_PROGRAMMING_H -------------------------------------------------------------------------------- /test/travis_test/build_2_container.sh: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #!/bin/bash 16 | 17 | BUILD="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 18 | code_dir=$(dirname $BUILD) 19 | code_dir=$(dirname $code_dir) 20 | echo "build path is $BUILD" 21 | echo "code path is $code_dir" 22 | 23 | # Initialize the needed mizar submodule 24 | # git submodule update --init --recursive 25 | 26 | # Create and Start the build contrainer 27 | if [ "$1" == "compile_and_run_unit_test" ]; then 28 | echo " --- images list ---" 29 | docker images 30 | echo " --- build image ---" 31 | docker build -f $code_dir/build/Dockerfile -t aca_build0 . 32 | echo " --- images list ---" 33 | docker images 34 | echo " --- container list ---" 35 | docker ps -a 36 | echo " --- create container ---" 37 | docker rm -f aca_PARENT || true 38 | docker create -v $code_dir:/mnt/host/code -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --name aca_PARENT aca_build0:latest /bin/bash 39 | docker start aca_PARENT 40 | docker exec aca_PARENT bash -c "/etc/init.d/openvswitch-switch restart && \ 41 | ovs-vswitchd --pidfile --detach" 42 | docker rm -f aca_CHILD || true 43 | docker create -v $code_dir:/mnt/host/code -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --name aca_CHILD aca_build0:latest /bin/bash 44 | docker start aca_CHILD 45 | docker exec aca_CHILD bash -c "/etc/init.d/openvswitch-switch restart && \ 46 | ovs-vswitchd --pidfile --detach" 47 | echo " --- container list ---" 48 | docker ps -a 49 | echo " --- building alcor-control-agent ---" 50 | docker exec aca_CHILD bash -c "cd /mnt/host/code && cmake . && make" 51 | docker exec aca_PARENT bash -c "cd /mnt/host/code && cmake . && make" 52 | echo " --- running test case---" 53 | echo " --- basic test case---" 54 | # run basic test case, ./build/tests/aca_tests 55 | docker exec aca_CHILD bash -c "cd /mnt/host/code && ./build/tests/aca_tests" 56 | 57 | elif [ "$1" == "2_port_test_traffic" ]; then 58 | echo " --- 2_ports_CREATE test case---" 59 | parent_container_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' aca_PARENT) 60 | child_container_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' aca_CHILD) 61 | echo "aca_PARENT ip: $parent_container_ip" 62 | echo "aca_CHILD ip: $child_container_ip" 63 | # run DISABLED_2_ports_CREATE_test_traffic_PARENT and DISABLED_2_ports_CREATE_test_traffic_CHILD 64 | docker exec -d aca_CHILD /bin/bash -c "cd /mnt/host/code && ./build/tests/aca_tests --gtest_also_run_disabled_tests --gtest_filter=*DISABLED_2_ports_CREATE_test_traffic_CHILD_V2 -p $parent_container_ip" & 65 | sleep 5 66 | docker exec aca_PARENT /bin/bash -c "cd /mnt/host/code && ./build/tests/aca_tests --gtest_also_run_disabled_tests --gtest_filter=*DISABLED_2_ports_CREATE_test_traffic_PARENT_V2 -c $child_container_ip" 67 | 68 | # run fake grpc server 69 | docker exec aca_PARENT bash -c "cd /mnt/host/code && nohup ./build/tests/gs_tests -m -d &" 70 | # run testcase to try to connect to the fake server 71 | docker exec aca_CHILD bash -c "cd /mnt/host/code && ./build/tests/aca_tests --gtest_also_run_disabled_tests --gtest_filter=*DISABLED_grpc_client_connectivity_test -a $parent_container_ip -p 54321" 72 | 73 | 74 | fi 75 | -------------------------------------------------------------------------------- /etc/k8s/images/scripts/aca-node-init.sh: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright(c) 2020 Futurewei Cloud 3 | # 4 | # Permission is hereby granted, 5 | # free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | # to whom the Software is furnished to do so, subject to the following conditions: 8 | # 9 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #!/bin/bash 16 | 17 | echo "1--- installing mizar dependencies ---" && \ 18 | apt-get update -y && apt-get install -y \ 19 | rpcbind \ 20 | rsyslog \ 21 | build-essential \ 22 | clang-9 \ 23 | llvm-9 \ 24 | libelf-dev \ 25 | openvswitch-switch \ 26 | iproute2 \ 27 | net-tools \ 28 | iputils-ping \ 29 | ethtool \ 30 | curl \ 31 | python3 \ 32 | python3-pip \ 33 | netcat \ 34 | libcmocka-dev \ 35 | lcov 36 | pip3 install httpserver netaddr 37 | make -C ~/mizar-mp/AlcorControlAgent/mizar 38 | 39 | echo "2--- installing librdkafka ---" && \ 40 | apt-get update -y && apt-get install -y --no-install-recommends\ 41 | librdkafka-dev \ 42 | doxygen \ 43 | libssl-dev \ 44 | zlib1g-dev \ 45 | libboost-program-options-dev \ 46 | libboost-all-dev \ 47 | && apt-get clean 48 | 49 | echo "3--- installing cppkafka ---" && \ 50 | apt-get update -y && apt-get install -y cmake 51 | git clone https://github.com/mfontanini/cppkafka.git /var/local/git/cppkafka && \ 52 | cd /var/local/git/cppkafka && \ 53 | mkdir build && \ 54 | cd build && \ 55 | cmake .. && \ 56 | make && \ 57 | make install && \ 58 | ldconfig && \ 59 | rm -rf /var/local/git/cppkafka 60 | 61 | echo "4--- installing grpc dependencies ---" && \ 62 | apt-get update -y && apt-get install -y \ 63 | cmake libssl-dev \ 64 | autoconf git pkg-config \ 65 | automake libtool make g++ unzip 66 | cd ~ 67 | 68 | # installing grpc and its dependencies 69 | GRPC_RELEASE_TAG="v1.24.x" 70 | echo "5--- cloning grpc repo ---" && \ 71 | git clone -b $GRPC_RELEASE_TAG https://github.com/grpc/grpc /var/local/git/grpc && \ 72 | cd /var/local/git/grpc && \ 73 | git submodule update --init && \ 74 | echo "--- installing c-ares ---" && \ 75 | cd /var/local/git/grpc/third_party/cares/cares && \ 76 | git fetch origin && \ 77 | git checkout cares-1_15_0 && \ 78 | mkdir -p cmake/build && \ 79 | cd cmake/build && \ 80 | cmake -DCMAKE_BUILD_TYPE=Release ../.. && \ 81 | make -j4 install && \ 82 | cd ../../../../.. && \ 83 | rm -rf third_party/cares/cares && \ 84 | echo "--- installing protobuf ---" && \ 85 | cd /var/local/git/grpc/third_party/protobuf && \ 86 | mkdir -p cmake/build && \ 87 | cd cmake/build && \ 88 | cmake -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release .. && \ 89 | make -j4 install && \ 90 | cd ../../../.. && \ 91 | rm -rf third_party/protobuf && \ 92 | echo "--- installing grpc ---" && \ 93 | cd /var/local/git/grpc && \ 94 | mkdir -p cmake/build && \ 95 | cd cmake/build && \ 96 | cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DgRPC_PROTOBUF_PROVIDER=package -DgRPC_ZLIB_PROVIDER=package -DgRPC_CARES_PROVIDER=package -DgRPC_SSL_PROVIDER=package -DCMAKE_BUILD_TYPE=Release ../.. && \ 97 | make -j4 install && \ 98 | echo "--- installing google test ---" && \ 99 | cd /var/local/git/grpc/third_party/googletest && \ 100 | cmake -Dgtest_build_samples=ON -DBUILD_SHARED_LIBS=ON . && \ 101 | make && \ 102 | make install && \ 103 | rm -rf /var/local/git/grpc 104 | 105 | echo "6--- " 106 | # building alcor-control-agent 107 | cd ~/mizar-mp/AlcorControlAgent && cmake . && make 108 | ln -snf ~/mizar-mp/AlcorControlAgent/build/ /aca_build 109 | -------------------------------------------------------------------------------- /include/of_controller.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #pragma once 16 | 17 | #include "of_message.h" 18 | 19 | #undef OFP_ASSERT 20 | #undef CONTAINER_OF 21 | #undef ARRAY_SIZE 22 | #undef ROUND_UP 23 | 24 | #include "libfluid-base/OFServer.hh" 25 | #include "libfluid-msg/of10msg.hh" 26 | #include "libfluid-msg/of13msg.hh" 27 | 28 | #include "marl/defer.h" 29 | #include "marl/event.h" 30 | #include "marl/scheduler.h" 31 | #include "marl/waitgroup.h" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | 51 | using namespace fluid_base; 52 | using namespace fluid_msg; 53 | 54 | class OFController : public OFServer { 55 | public: 56 | OFController(const std::unordered_map switch_dpid_map, 57 | const std::unordered_map port_id_map, 58 | const char* address = "0.0.0.0", 59 | const int port = 1234, 60 | const int nthreads = 4, 61 | bool secure = false) : 62 | xid(0), 63 | switch_dpid_map(switch_dpid_map), 64 | port_id_map(port_id_map), 65 | OFServer(address, port, nthreads, secure, 66 | OFServerSettings() 67 | .supported_version(4) // OF version 1 is OF 1.0 and version 4 is 1.3 68 | .echo_interval(30)) { 69 | } 70 | 71 | ~OFController() = default; 72 | 73 | void stop() override; 74 | 75 | void message_callback(OFConnection* ofconn, uint8_t type, void* data, size_t len) override; 76 | 77 | void connection_callback(OFConnection* ofconn, OFConnection::Event type) override; 78 | 79 | OFConnection* get_instance(std::string bridge); 80 | 81 | void add_switch_to_conn_map(std::string bridge, int ofconn_id, OFConnection* ofconn); 82 | 83 | void remove_switch_from_conn_map(std::string bridge); 84 | 85 | void remove_switch_from_conn_map(int ofconn_id); 86 | 87 | void remove_switch_from_conn_maps(std::string bridge, int ofconn_id); 88 | 89 | void setup_default_br_int_flows(); 90 | 91 | void setup_default_br_tun_flows(); 92 | 93 | void execute_flow(const std::string br, const std::string flow_str, const std::string action = "add"); 94 | 95 | void packet_out(const char* br, const char* opt); 96 | 97 | private: 98 | 99 | // tracking xid (ovs transaction id) 100 | std::atomic xid; 101 | 102 | // k is bridge name like 'br-int', v is OFConnection* obj 103 | std::unordered_map switch_conn_map; 104 | 105 | // k is ofconnection id like '0', v is bridge name associated with it 106 | std::unordered_map switch_id_map; 107 | 108 | // k is dpid (query from ovs), v is bridge name associated with it 109 | std::unordered_map switch_dpid_map; 110 | 111 | // k is port name like (patch-int/tun and vxlan-generic), v is ofport id of it from ovsdb 112 | std::unordered_map port_id_map; 113 | 114 | std::mutex switch_map_mutex; 115 | 116 | void send_flow(OFConnection *ofconn, ofmsg_ptr_t &&p); 117 | 118 | void send_packet_out(OFConnection *ofconn, ofbuf_ptr_t &&po); 119 | 120 | void send_bundle_flow_mods(OFConnection *ofconn, std::vector flow_mods); 121 | }; 122 | -------------------------------------------------------------------------------- /include/aca_ovs_l3_programmer.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_OVS_L3_PROGRAMMER_H 16 | #define ACA_OVS_L3_PROGRAMMER_H 17 | 18 | #include "goalstateprovisioner.grpc.pb.h" 19 | #include 20 | #include 21 | 22 | using namespace std; 23 | using namespace alcor::schema; 24 | 25 | // port id is stored as the key to ports table 26 | struct neighbor_port_table_entry { 27 | string virtual_ip; 28 | string virtual_mac; 29 | string host_ip; 30 | }; 31 | 32 | // routing rule id is stored as the key to routing_rules table 33 | struct routing_rule_entry { 34 | string destination; // destination IP, could be 154.12.42.24/32 (host address) or 0.0.0.0/0 (network address) 35 | alcor::schema::DestinationType destination_type; 36 | string next_hop_ip; 37 | string next_hop_mac; 38 | uint priority; 39 | }; 40 | 41 | // subnet id is stored as the key to subnet_routing_table 42 | struct subnet_routing_table_entry { 43 | string vpc_id; 44 | alcor::schema::NetworkType network_type; 45 | string cidr; 46 | uint tunnel_id; 47 | string gateway_ip; 48 | string gateway_mac; 49 | // list of neighbor ports within the subnet 50 | // hashtable 51 | unordered_map neighbor_ports; 52 | // list of routing rules for this subnet 53 | // hashtable 54 | unordered_map routing_rules; 55 | }; 56 | 57 | // OVS L3 programmer implementation class 58 | namespace aca_ovs_l3_programmer 59 | { 60 | class ACA_OVS_L3_Programmer { 61 | public: 62 | static ACA_OVS_L3_Programmer &get_instance(); 63 | 64 | void clear_all_data(); 65 | 66 | int create_or_update_router(RouterConfiguration ¤t_RouterConfiguration, 67 | GoalState &parsed_struct, 68 | ulong &culminative_time_dataplane_programming_time); 69 | 70 | int create_or_update_router(RouterConfiguration ¤t_RouterConfiguration, 71 | GoalStateV2 &parsed_struct, 72 | ulong &culminative_time_dataplane_programming_time); 73 | 74 | int delete_router(RouterConfiguration ¤t_RouterConfiguration, 75 | ulong &culminative_time_dataplane_programming_time); 76 | 77 | int create_or_update_l3_neighbor(const string neighbor_id, const string vpc_id, 78 | const string subnet_id, const string virtual_ip, 79 | const string virtual_mac, 80 | const string remote_host_ip, uint tunnel_id, 81 | ulong &culminative_time_dataplane_programming_time); 82 | 83 | int delete_l3_neighbor(const string neighbor_id, const string subnet_id, 84 | const string virtual_ip, ulong &culminative_time); 85 | 86 | // compiler will flag the error when below is called. 87 | ACA_OVS_L3_Programmer(ACA_OVS_L3_Programmer const &) = delete; 88 | void operator=(ACA_OVS_L3_Programmer const &) = delete; 89 | 90 | private: 91 | ACA_OVS_L3_Programmer(){}; 92 | ~ACA_OVS_L3_Programmer(){}; 93 | 94 | string _host_dvr_mac; 95 | 96 | // hashtable > 97 | unordered_map > _routers_table; 98 | 99 | // mutex for reading and writing to routers_table 100 | // consider using a read / write lock to improve performance 101 | mutex _routers_table_mutex; 102 | }; 103 | } // namespace aca_ovs_l3_programmer 104 | #endif // #ifndef ACA_OVS_L3_PROGRAMMER_H -------------------------------------------------------------------------------- /include/hashmap/HashMap.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2018 Kaushik Basu 4 | // Copyright 2019 The Alcor Authors - file modified. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | #ifndef HASH_MAP_H_ 25 | #define HASH_MAP_H_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "HashNode.h" 32 | 33 | constexpr size_t HASH_SIZE_DEFAULT = 1031; // A prime number as hash size gives a better distribution of values in buckets 34 | namespace CTSL //Concurrent Thread Safe Library 35 | { 36 | //The class represting the hash map. 37 | //It is expected for user defined types, the hash function will be provided. 38 | //By default, the std::hash function will be used 39 | //If the hash size is not provided, then a defult size of 1031 will be used 40 | //The hash table itself consists of an array of hash buckets. 41 | //Each hash bucket is implemented as singly linked list with the head as a dummy node created 42 | //during the creation of the bucket. All the hash buckets are created during the construction of the map. 43 | //Locks are taken per bucket, hence multiple threads can write simultaneously in different buckets in the hash map 44 | template > class HashMap { 45 | public: 46 | HashMap(size_t hashSize_ = HASH_SIZE_DEFAULT) : hashSize(hashSize_) 47 | { 48 | hashTable = new HashBucket[hashSize]; //create the hash table as an array of hash buckets 49 | } 50 | 51 | ~HashMap() 52 | { 53 | delete[] hashTable; 54 | } 55 | //Copy and Move of the HashMap are not supported at this moment 56 | HashMap(const HashMap &) = delete; 57 | HashMap(HashMap &&) = delete; 58 | HashMap &operator=(const HashMap &) = delete; 59 | HashMap &operator=(HashMap &&) = delete; 60 | 61 | //Function to find an entry in the hash map matching the key. 62 | //If key is found, the corresponding value is copied into the parameter "value" and function returns true. 63 | //If key is not found, function returns false. 64 | bool find(const K &key, V &value) const 65 | { 66 | size_t hashValue = hashFn(key) % hashSize; 67 | return hashTable[hashValue].find(key, value); 68 | } 69 | 70 | //Function to insert into the hash map. 71 | //If key already exists, update the value, else insert a new node in the bucket with the pair. 72 | void insert(const K &key, const V &value) 73 | { 74 | size_t hashValue = hashFn(key) % hashSize; 75 | hashTable[hashValue].insert(key, value); 76 | } 77 | 78 | //Function to remove an entry from the bucket, if found 79 | void erase(const K &key) 80 | { 81 | size_t hashValue = hashFn(key) % hashSize; 82 | hashTable[hashValue].erase(key); 83 | } 84 | 85 | //Function to see if the whole hashtable is empty. 86 | bool empty() const 87 | { 88 | for (size_t i = 0; i < hashSize; i++) { 89 | auto hash_node = (hashTable[i]).head; 90 | if (hash_node == nullptr) { 91 | // no entry for this hashtable bucket, go look at the next bucket 92 | continue; 93 | } else { 94 | // found an entry in this hashtable bucket, 95 | // return false since the hashtable is not emply 96 | return false; 97 | } 98 | } 99 | 100 | // went through the whole table and didn't find any hashtable bucket 101 | // return true since the hashtable is emply 102 | return true; 103 | } 104 | 105 | //Function to clean up the hasp map, i.e., remove all entries from it 106 | void clear() 107 | { 108 | for (size_t i = 0; i < hashSize; i++) { 109 | (hashTable[i]).clear(); 110 | } 111 | } 112 | 113 | HashBucket *hashTable; 114 | const size_t hashSize; 115 | 116 | private: 117 | F hashFn; 118 | }; 119 | } // namespace CTSL 120 | #endif 121 | -------------------------------------------------------------------------------- /src/ovs/aca_ovs_control.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #include "aca_ovs_control.h" 16 | #include "ovs_control.h" 17 | #include "aca_log.h" 18 | #include "aca_util.h" 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | using namespace ovs_control; 25 | 26 | extern string g_ofctl_command; 27 | extern string g_ofctl_target; 28 | extern string g_ofctl_options; 29 | 30 | namespace aca_ovs_control 31 | { 32 | ACA_OVS_Control &ACA_OVS_Control::get_instance() 33 | { 34 | // Instance is destroyed when program exits. 35 | // It is instantiated on first use. 36 | static ACA_OVS_Control instance; 37 | 38 | return instance; 39 | } 40 | 41 | int ACA_OVS_Control::control() 42 | { 43 | int overall_rc = EXIT_SUCCESS; 44 | 45 | // char target[g_ofctl_target.size() + 1]; 46 | char *target = new char[g_ofctl_target.size() + 1]; 47 | g_ofctl_target.copy(target, g_ofctl_target.size() + 1); 48 | target[g_ofctl_target.size()] = '\0'; 49 | 50 | // char options[g_ofctl_options.size() + 1]; 51 | char *options = new char[g_ofctl_options.size() + 1]; 52 | g_ofctl_options.copy(options, g_ofctl_options.size() + 1); 53 | options[g_ofctl_options.size()] = '\0'; 54 | 55 | if (g_ofctl_command.compare("monitor") == 0) { 56 | monitor(target, options); 57 | } else if (g_ofctl_command.compare("dump-flows") == 0) { 58 | dump_flows(target, options); 59 | } else if (g_ofctl_command.compare("flow-exists") == 0) { 60 | flow_exists(target, options); 61 | } else if (g_ofctl_command.compare("add-flow") == 0) { 62 | add_flow(target, options); 63 | } else if (g_ofctl_command.compare("mod-flows") == 0) { 64 | mod_flows(target, options); 65 | } else if (g_ofctl_command.compare("del-flows") == 0) { 66 | del_flows(target, options); 67 | } else if (g_ofctl_command.compare("packet-out") == 0) { 68 | packet_out(target, options); 69 | } else { 70 | cout << "Usage: -c -t -o " << endl; 71 | cout << " commands: monitor, dump-flows, add-flow, mod-flows, del-flows, packet-out..." 72 | << endl; 73 | cout << " target: swtich name, such as br-int, br-tun, ..." << endl; 74 | cout << " options: " << endl; 75 | cout << " moinor: \"[miss-len] [invalid-ttl] [resume] [watch:format]\"" << endl; 76 | cout << " packet-out: \"in_port= packet= [actions=]\"" 77 | << endl; 78 | } 79 | 80 | delete target; 81 | delete options; 82 | 83 | return overall_rc; 84 | } 85 | 86 | int ACA_OVS_Control::dump_flows(const char *bridge, const char *opt) 87 | { 88 | return OVS_Control::get_instance().dump_flows(bridge, opt); 89 | } 90 | 91 | int ACA_OVS_Control::flow_exists(const char *bridge, const char *flow) 92 | { 93 | return OVS_Control::get_instance().dump_flows(bridge, flow, false); 94 | } 95 | 96 | int ACA_OVS_Control::add_flow(const char *bridge, const char *opt) 97 | { 98 | return OVS_Control::get_instance().add_flow(bridge, opt); 99 | } 100 | 101 | int ACA_OVS_Control::mod_flows(const char *bridge, const char *opt) 102 | { 103 | bool strict = true; 104 | return OVS_Control::get_instance().mod_flows(bridge, opt, strict); 105 | } 106 | 107 | int ACA_OVS_Control::del_flows(const char *bridge, const char *opt) 108 | { 109 | bool strict = true; 110 | return OVS_Control::get_instance().del_flows(bridge, opt, strict); 111 | } 112 | 113 | void ACA_OVS_Control::monitor(const char *bridge, const char *opt) 114 | { 115 | OVS_Control::get_instance().monitor(bridge, opt); 116 | } 117 | 118 | void ACA_OVS_Control::packet_out(const char *bridge, const char *opt) 119 | { 120 | OVS_Control::get_instance().packet_out(bridge, opt); 121 | } 122 | 123 | } // namespace aca_ovs_control 124 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../build/bin) 2 | 3 | set(SOURCES 4 | ./comm/aca_message_producer.cpp 5 | ./comm/aca_message_consumer.cpp 6 | ./comm/aca_message_pulsar_consumer.cpp 7 | ./comm/aca_message_pulsar_producer.cpp 8 | ./comm/aca_comm_mgr.cpp 9 | ./comm/aca_grpc.cpp 10 | ./comm/aca_grpc_client.cpp 11 | ./dp_abstraction/aca_goal_state_handler.cpp 12 | ./dp_abstraction/aca_dataplane_ovs.cpp 13 | ./net_config/aca_net_config.cpp 14 | ./ovs/aca_ovs_l2_programmer.cpp 15 | ./ovs/aca_ovs_l3_programmer.cpp 16 | ./ovs/aca_vlan_manager.cpp 17 | ./ovs/ovs_control.cpp 18 | ./ovs/aca_ovs_control.cpp 19 | ./ovs/aca_arp_responder.cpp 20 | ./ovs/libfluid-base/base/BaseOFClient.cc 21 | ./ovs/libfluid-base/base/BaseOFConnection.cc 22 | ./ovs/libfluid-base/base/BaseOFServer.cc 23 | ./ovs/libfluid-base/base/EventLoop.cc 24 | ./ovs/libfluid-base/OFClient.cc 25 | ./ovs/libfluid-base/OFConnection.cc 26 | ./ovs/libfluid-base/OFServer.cc 27 | ./ovs/libfluid-base/OFServerSettings.cc 28 | ./ovs/libfluid-base/TLS.cc 29 | ./ovs/libfluid-msg/of10/of10action.cc 30 | ./ovs/libfluid-msg/of10/of10common.cc 31 | ./ovs/libfluid-msg/of10/of10match.cc 32 | ./ovs/libfluid-msg/of13/of13action.cc 33 | ./ovs/libfluid-msg/of13/of13common.cc 34 | ./ovs/libfluid-msg/of13/of13instruction.cc 35 | ./ovs/libfluid-msg/of13/of13match.cc 36 | ./ovs/libfluid-msg/of13/of13meter.cc 37 | ./ovs/libfluid-msg/ofcommon/action.cc 38 | ./ovs/libfluid-msg/ofcommon/common.cc 39 | ./ovs/libfluid-msg/ofcommon/msg.cc 40 | ./ovs/libfluid-msg/util/ethaddr.cc 41 | ./ovs/libfluid-msg/util/ipaddr.cc 42 | ./ovs/libfluid-msg/of10msg.cc 43 | ./ovs/libfluid-msg/of13msg.cc 44 | ./ovs/of_message.cpp 45 | ./ovs/of_controller.cpp 46 | ./on_demand/aca_on_demand_engine.cpp 47 | ./dhcp/aca_dhcp_state_handler.cpp 48 | ./dhcp/aca_dhcp_server.cpp 49 | ./zeta/aca_zeta_oam_server.cpp 50 | ./zeta/aca_zeta_programming.cpp 51 | ) 52 | 53 | #Find libevent installation 54 | find_path(LIBEVENT_INCLUDE_DIR 55 | NAMES event2/thread.h 56 | HINTS /usr/include 57 | REQUIRED) 58 | 59 | FIND_LIBRARY(LIBUUID_LIBRARIES uuid) 60 | FIND_LIBRARY(RDKAFKA rdkafka /usr/lib/x86_64-linux-gnu NO_DEFAULT_PATH) 61 | FIND_LIBRARY(CPPKAFKA cppkafka /usr/local/lib NO_DEFAULT_PATH) 62 | FIND_LIBRARY(PULSAR pulsar /usr/lib NO_DEFAULT_PATH) 63 | FIND_LIBRARY(MESSAGEMANAGER messagemanager ${CMAKE_CURRENT_SOURCE_DIR}/../include NO_DEFAULT_PATH) 64 | link_libraries(${RDKAFKA} ${CPPKAFKA} ${PULSAR}) 65 | link_libraries(/usr/lib/x86_64-linux-gnu/libuuid.so) 66 | link_libraries(/usr/lib/x86_64-linux-gnu/libevent_pthreads.so) 67 | link_libraries(/usr/lib/x86_64-linux-gnu/libpthread.so) 68 | link_libraries(/usr/local/lib/libopenvswitch.a) #this was installed by aca-machine-init.sh 69 | link_libraries(/var/local/git/marl/marl/build/libmarl.a) #this was built by aca-machine-init.sh 70 | include_directories(${RDKAFKA_INCLUDE_DIR} ${CPPKAFKA_INCLUDE_DIR} ${PULSAR_INCLUDE_DIR} ${LIBEVENT_INCLUDE_DIR}) 71 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) 72 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/proto3) 73 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/grpc) 74 | include_directories(/usr/local/include/openvswitch) 75 | include_directories(/usr/local/include/openflow) 76 | include_directories(/var/local/git/marl/marl/include) 77 | 78 | # Find Protobuf installation 79 | # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. 80 | set(protobuf_MODULE_COMPATIBLE TRUE) 81 | find_package(Protobuf CONFIG REQUIRED) 82 | message(STATUS "Using protobuf ${protobuf_VERSION}") 83 | 84 | # Find gRPC installation 85 | # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. 86 | find_package(gRPC CONFIG REQUIRED) 87 | message(STATUS "Using gRPC ${gRPC_VERSION}") 88 | 89 | set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure) 90 | set(_GRPC_CPP_PLUGIN_EXECUTABLE $) 91 | 92 | add_library(AlcorControlAgentLib STATIC ${SOURCES}) 93 | target_link_libraries(AlcorControlAgentLib event) #Libevent linking is '-levent', thus linked lib is 'event' in the cmd 94 | target_link_libraries(AlcorControlAgentLib ssl) 95 | target_link_libraries(AlcorControlAgentLib crypto) 96 | target_link_libraries(AlcorControlAgentLib rt) 97 | 98 | add_executable(AlcorControlAgent aca_main.cpp) 99 | target_link_libraries(AlcorControlAgent cppkafka) 100 | target_link_libraries(AlcorControlAgent rdkafka) 101 | target_link_libraries(AlcorControlAgent pulsar) 102 | target_link_libraries(AlcorControlAgent AlcorControlAgentLib) 103 | target_link_libraries(AlcorControlAgent proto) 104 | target_link_libraries(AlcorControlAgent grpc) 105 | target_link_libraries(AlcorControlAgent ${PROTOBUF_LIBRARY}) 106 | target_link_libraries(AlcorControlAgent ${_GRPC_GRPCPP_UNSECURE}) 107 | 108 | 109 | add_dependencies(AlcorControlAgentLib proto grpc) 110 | add_subdirectory(proto3) 111 | add_subdirectory(grpc) -------------------------------------------------------------------------------- /src/ovs/libfluid-msg/of10/of10match.cc: -------------------------------------------------------------------------------- 1 | #include "libfluid-msg/of10/of10match.hh" 2 | 3 | namespace fluid_msg { 4 | 5 | namespace of10 { 6 | 7 | Match::Match() 8 | : in_port_(0), 9 | dl_vlan_(0), 10 | dl_vlan_pcp_(0), 11 | dl_type_(0), 12 | nw_tos_(0), 13 | nw_proto_(0), 14 | tp_src_(0), 15 | tp_dst_(0), 16 | dl_src_(), 17 | dl_dst_(), 18 | nw_src_((uint32_t) 0), 19 | nw_dst_((uint32_t) 0), 20 | wildcards_(of10::OFPFW_ALL) { 21 | } 22 | 23 | bool Match::operator==(const Match &other) const { 24 | return ((this->in_port_ == other.in_port_) 25 | && (this->wildcards_ == other.wildcards_) 26 | && (this->dl_vlan_ == other.dl_vlan_) 27 | && (this->dl_vlan_pcp_ == other.dl_vlan_pcp_) 28 | && (this->dl_type_ == other.dl_type_) 29 | && (this->nw_tos_ == other.nw_tos_) 30 | && (this->nw_proto_ == other.nw_proto_) 31 | && (this->tp_src_ == other.tp_src_) && (this->tp_dst_ == other.tp_dst_) 32 | && (this->nw_src_ == other.nw_src_) && (this->nw_dst_ == other.nw_dst_) 33 | && (this->dl_src_ == other.dl_src_) && (this->dl_dst_ == other.dl_dst_)); 34 | } 35 | 36 | bool Match::operator!=(const Match &other) const { 37 | return !(*this == other); 38 | } 39 | 40 | void Match::wildcards(uint32_t wildcards) { 41 | this->wildcards_ = wildcards; 42 | } 43 | 44 | void Match::in_port(uint16_t in_port) { 45 | this->in_port_ = in_port; 46 | this->wildcards_ &= ~of10::OFPFW_IN_PORT; 47 | } 48 | 49 | void Match::dl_src(const EthAddress &dl_src) { 50 | this->dl_src_ = dl_src; 51 | this->wildcards_ &= ~of10::OFPFW_DL_SRC; 52 | } 53 | 54 | void Match::dl_dst(const EthAddress &dl_dst) { 55 | this->dl_dst_ = dl_dst; 56 | this->wildcards_ &= ~of10::OFPFW_DL_DST; 57 | } 58 | 59 | void Match::dl_vlan(uint16_t dl_vlan) { 60 | this->dl_vlan_ = dl_vlan; 61 | this->wildcards_ &= ~of10::OFPFW_DL_VLAN; 62 | } 63 | 64 | void Match::dl_vlan_pcp(uint8_t dl_vlan_pcp) { 65 | this->dl_vlan_pcp_ = dl_vlan_pcp; 66 | this->wildcards_ &= ~of10::OFPFW_DL_VLAN_PCP; 67 | } 68 | 69 | void Match::dl_type(uint16_t dl_type) { 70 | this->dl_type_ = dl_type; 71 | this->wildcards_ &= ~of10::OFPFW_DL_TYPE; 72 | } 73 | 74 | void Match::nw_tos(uint8_t nw_tos) { 75 | this->nw_tos_ = nw_tos; 76 | this->wildcards_ &= ~of10::OFPFW_NW_TOS; 77 | } 78 | 79 | void Match::nw_proto(uint8_t nw_proto) { 80 | this->nw_proto_ = nw_proto; 81 | this->wildcards_ &= ~of10::OFPFW_NW_PROTO; 82 | } 83 | 84 | void Match::nw_src(const IPAddress &nw_src) { 85 | this->nw_src_ = nw_src; 86 | this->wildcards_ &= ~of10::OFPFW_NW_SRC_MASK; 87 | } 88 | 89 | void Match::nw_dst(const IPAddress &nw_dst) { 90 | this->nw_dst_ = nw_dst; 91 | this->wildcards_ &= ~of10::OFPFW_NW_DST_MASK; 92 | } 93 | 94 | void Match::nw_src(const IPAddress &nw_src, uint32_t prefix) { 95 | this->nw_src_ = nw_src; 96 | uint32_t index = 32 - prefix; 97 | this->wildcards_ &= ~of10::OFPFW_NW_SRC_MASK; 98 | this->wildcards_ |= (index << of10::OFPFW_NW_SRC_SHIFT); 99 | } 100 | 101 | void Match::nw_dst(const IPAddress &nw_dst, uint32_t prefix) { 102 | this->nw_dst_ = nw_dst; 103 | uint32_t index = 32 - prefix; 104 | this->wildcards_ &= ~of10::OFPFW_NW_DST_MASK; 105 | this->wildcards_ |= (index << of10::OFPFW_NW_DST_SHIFT); 106 | } 107 | 108 | void Match::tp_src(uint16_t tp_src) { 109 | this->tp_src_ = tp_src; 110 | this->wildcards_ &= ~of10::OFPFW_TP_SRC; 111 | } 112 | 113 | void Match::tp_dst(uint16_t tp_dst) { 114 | this->tp_dst_ = tp_dst; 115 | this->wildcards_ &= ~of10::OFPFW_TP_DST; 116 | } 117 | 118 | size_t Match::pack(uint8_t *buffer) { 119 | struct of10::ofp_match *m = (struct ofp_match*) buffer; 120 | m->wildcards = hton32(this->wildcards_); 121 | m->in_port = hton16(this->in_port_); 122 | memcpy(m->dl_src, this->dl_src_.get_data(), OFP_ETH_ALEN); 123 | memcpy(m->dl_dst, this->dl_dst_.get_data(), OFP_ETH_ALEN); 124 | m->dl_vlan = hton16(this->dl_vlan_); 125 | m->dl_vlan_pcp = this->dl_vlan_pcp_; 126 | memset(m->pad1, 0x0, 1); 127 | m->dl_type = hton16(this->dl_type_); 128 | m->nw_tos = this->nw_tos_; 129 | m->nw_proto = this->nw_proto_; 130 | memset(m->pad2, 0x0, 2); 131 | m->nw_src = hton32(this->nw_src_.getIPv4()); 132 | m->nw_dst = hton32(this->nw_dst_.getIPv4()); 133 | m->tp_src = hton16(this->tp_src_); 134 | m->tp_dst = hton16(this->tp_dst_); 135 | return 0; 136 | } 137 | 138 | of_error Match::unpack(uint8_t *buffer) { 139 | struct of10::ofp_match *m = (struct ofp_match*) buffer; 140 | this->wildcards_ = ntoh32(m->wildcards); 141 | this->in_port_ = ntoh16(m->in_port); 142 | this->dl_src_.set_data(m->dl_src); 143 | this->dl_dst_.set_data(m->dl_dst); 144 | this->dl_vlan_ = ntoh16(m->dl_vlan); 145 | this->dl_vlan_pcp_ = m->dl_vlan_pcp; 146 | this->dl_type_ = ntoh16(m->dl_type); 147 | this->nw_tos_ = m->nw_tos; 148 | this->nw_proto_ = m->nw_proto; 149 | this->nw_src_.setIPv4(ntoh32(m->nw_src)); 150 | this->nw_dst_.setIPv4(ntoh32(m->nw_dst)); 151 | this->tp_src_ = ntoh16(m->tp_src); 152 | this->tp_dst_ = ntoh16(m->tp_dst); 153 | return 0; 154 | } 155 | 156 | } //End of namespace of10 157 | } //End of namespace fluid_msg 158 | -------------------------------------------------------------------------------- /include/aca_arp_responder.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright(c) 2020 Futurewei Cloud 3 | // 4 | // Permission is hereby granted, 5 | // free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, 6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | // 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | #ifndef ACA_ARP_RESPONDER_H 16 | #define ACA_ARP_RESPONDER_H 17 | 18 | #include 19 | #include 20 | #include "hashmap/HashMap.h" 21 | #include 22 | 23 | using namespace std; 24 | 25 | namespace aca_arp_responder 26 | { 27 | #define ARP_ENTRY_DATA_SET(pData, pConfig) \ 28 | do { \ 29 | (pData)->ipv4_address = (pConfig)->ipv4_address; \ 30 | (pData)->vlan_id = (pConfig)->vlan_id; \ 31 | } while (0) 32 | 33 | #define ARP_TABLE_DATA_SET(pData, pConfig) \ 34 | do { \ 35 | (pData)->mac_address = (pConfig)->mac_address; \ 36 | } while (0) 37 | 38 | struct arp_config { 39 | string mac_address; 40 | string ipv4_address; 41 | string ipv6_address; 42 | uint16_t vlan_id; 43 | string port_host_name; 44 | }; 45 | 46 | struct arp_entry_data { 47 | string ipv4_address; 48 | string ipv6_address; 49 | uint16_t vlan_id; 50 | bool operator==(const arp_entry_data &p) const 51 | { 52 | return ipv4_address == p.ipv4_address && vlan_id == p.vlan_id; 53 | } 54 | 55 | bool operator!=(const arp_entry_data &p) const 56 | { 57 | return ipv4_address != p.ipv4_address || vlan_id != p.vlan_id; 58 | } 59 | }; 60 | 61 | struct arp_hash { 62 | size_t operator()(const arp_entry_data &p) const 63 | { 64 | return hash()(p.ipv4_address) ^ (hash()(p.vlan_id) << 1); 65 | } 66 | }; 67 | 68 | struct arp_table_data { 69 | string mac_address; 70 | }; 71 | 72 | struct arp_message { 73 | uint16_t hrd; 74 | uint16_t pro; 75 | uint8_t hln; 76 | uint8_t pln; 77 | uint16_t op; 78 | uint8_t sha[6]; 79 | uint32_t spa; 80 | uint8_t tha[6]; 81 | uint32_t tpa; 82 | } __attribute__((__packed__)); 83 | 84 | struct vlan_message { 85 | uint16_t vlan_proto; //should always be 0x8100 86 | uint16_t vlan_tci; 87 | }; 88 | 89 | //ARP Message Type 90 | #define ARP_MSG_ARPREQUEST (0x1) 91 | #define ARP_MSG_ARPREPLY (0x2) 92 | 93 | //ARP Message Fields 94 | #define ARP_MSG_HRD_TYPE (0x1) 95 | #define ARP_MSG_PRO_TYPE (0x0800) 96 | #define ARP_MSG_HRD_LEN (0x6) 97 | #define ARP_MSG_PRO_LEN (0x4) 98 | 99 | class ACA_ARP_Responder { 100 | public: 101 | static ACA_ARP_Responder &get_instance(); 102 | 103 | bool does_arp_entry_exist(arp_entry_data stData); 104 | 105 | /* Managemet Plane Ops*/ 106 | int add_arp_entry(arp_config *arp_config_in); 107 | int create_or_update_arp_entry(arp_config *arp_config_in); 108 | int delete_arp_entry(arp_config *arp_config_in); 109 | 110 | /* Data plane Ops */ 111 | int arp_recv(uint32_t in_port, void *vlanmsg, void *message); 112 | void arp_xmit(uint32_t in_port, void *vlanmsg, void *message, int is_find); 113 | string _get_requested_ip(arp_message *arpmsg); 114 | string _get_source_ip(arp_message *arpmsg); 115 | int _parse_arp_request(uint32_t in_port, vlan_message *vlanmsg, arp_message *arpmsg); 116 | 117 | private: 118 | ACA_ARP_Responder(); 119 | ~ACA_ARP_Responder(); 120 | 121 | CTSL::HashMap _arp_db; 122 | 123 | /*************** Initialization and De-initialization ***********************/ 124 | void _init_arp_db(); 125 | void _deinit_arp_db(); 126 | void _init_arp_ofp(); 127 | void _deinit_arp_ofp(); 128 | 129 | /*************** Management plane operations ***********************/ 130 | void _validate_mac_address(const char *mac_string); 131 | void _validate_ipv4_address(const char *ip_address); 132 | void _validate_ipv6_address(const char *ip_address); 133 | int _validate_arp_entry(arp_config *arp_cfg_in); 134 | 135 | /**************** Data plane operations *********************/ 136 | int _validate_arp_message(arp_message *arpmsg); 137 | 138 | arp_message *_pack_arp_reply(arp_message *arpreq, string mac_address); 139 | 140 | string _serialize_arp_message(vlan_message *vlanmsg, arp_message *arpmsg); 141 | }; 142 | } // namespace aca_arp_responder 143 | #endif // #ifndef ACA_ARP_RESPONDER_H 144 | --------------------------------------------------------------------------------