/* * Copyright (c) 2017-2019 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace libconfig { class Setting; } namespace transport { namespace core { namespace portal_details { static constexpr uint32_t pit_size = 1024; class HandlerMemory { #ifdef __vpp__ public: HandlerMemory() {} HandlerMemory(const HandlerMemory &) = delete; HandlerMemory &operator=(const HandlerMemory &) = delete; TRANSPORT_ALWAYS_INLINE void *allocate(std::size_t size) { return utils::FixedBlockAllocator<128, 8192>::getInstance().allocateBlock(); } TRANSPORT_ALWAYS_INLINE void deallocate(void *pointer) { utils::FixedBlockAllocator<128, 8192>::getInstance().deallocateBlock( pointer); } #else public: HandlerMemory() {} HandlerMemory(const HandlerMemory &) = delete; HandlerMemory &operator=(const HandlerMemory &) = delete; TRANSPORT_ALWAYS_INLINE void *allocate(std::size_t size) { return ::operator new(size); } TRANSPORT_ALWAYS_INLINE void deallocate(void *pointer) { ::operator delete(pointer); } #endif }; // The allocator to be associated with the handler objects. This allocator only // needs to satisfy the C++11 minimal allocator requirements. template class HandlerAllocator { public: using value_type = T; explicit HandlerAllocator(HandlerMemory &mem) : memory_(mem) {} template HandlerAllocator(const HandlerAllocator &other) noexcept : memory_(other.memory_) {} TRANSPORT_ALWAYS_INLINE bool operator==( const HandlerAllocator &other) const noexcept { return &memory_ == &other.memory_; } TRANSPORT_ALWAYS_INLINE bool operator!=( const HandlerAllocator &other) const noexcept { return &memory_ != &other.memory_; } TRANSPORT_ALWAYS_INLINE T *allocate(std::size_t n) const { return static_cast(memory_.allocate(sizeof(T) * n)); } TRANSPORT_ALWAYS_INLINE void deallocate(T *p, std::size_t /*n*/) const { return memory_.deallocate(p); } private: template friend class HandlerAllocator; // The underlying memory. HandlerMemory &memory_; }; // Wrapper class template for handler objects to allow handler memory // allocation to be customised. The allocator_type type and get_allocator() // member function are used by the asynchronous operations to obtain the // allocator. Calls to operator() are forwarded to the encapsulated handler. template class CustomAllocatorHandler { public: using allocator_type = HandlerAllocator; CustomAllocatorHandler(HandlerMemory &m, Handler h) : memory_(m), handler_(h) {} allocator_type get_allocator() const noexcept { return allocator_type(memory_); } template void operator()(Args &&...args) { handler_(std::forward(args)...); } private: HandlerMemory &memory_; Handler handler_; }; // Helper function to wrap a handler object to add custom allocation. template inline CustomAllocatorHandler makeCustomAllocatorHandler( HandlerMemory &m, Handler h) { return CustomAllocatorHandler(m, h); } class Pool { public: Pool(asio::io_service &io_service) : io_service_(io_service) { increasePendingInterestPool(); } TRANSPORT_ALWAYS_INLINE void increasePendingInterestPool() { // Create pool of pending interests to reuse for (uint32_t i = 0; i < pit_size; i++) { pending_interests_pool_.add(new PendingInterest( Interest::Ptr(nullptr), std::make_unique(io_service_))); } } PendingInterest::Ptr getPendingInterest() { auto res = pending_interests_pool_.get(); while (TRANSPORT_EXPECT_FALSE(!res.first)) { increasePendingInterestPool(); res = pending_interests_pool_.get(); } return std::move(res.second); } private: utils::ObjectPool pending_interests_pool_; asio::io_service &io_service_; }; } // namespace portal_details class PortalConfiguration; using PendingInterestHashTable = std::unordered_map; using interface::BindConfig; /** * Portal is a opaque class which is used for sending/receiving interest/data * packets over multiple kind of connector. The connector itself is defined by * the template ForwarderInt, which is resolved at compile time. It is then not * possible to decide at runtime what the connector will be. * * The tasks performed by portal are the following: * - Sending/Receiving Interest packets * - Sending/Receiving Data packets * - Set timers (one per interest), in order to trigger events if an interest is * not satisfied * - Register a producer prefix to the local forwarder * * The way of working of portal is event-based, which means that data and * interests are sent/received in a asynchronous manner, and the notifications * are performed through callbacks. * * The portal class is not thread safe, appropriate locking is required by the * users of this class. */ class Portal { public: using ConsumerCallback = interface::Portal::ConsumerCallback; using ProducerCallback = interface::Portal::ProducerCallback; friend class PortalConfiguration; Portal() : Portal(internal_io_service_) {} Portal(asio::io_service &io_service) : io_module_(nullptr, [](IoModule *module) { IoModule::unload(module); }), io_service_(io_service), packet_pool_(io_service), app_name_("libtransport_application"), consumer_callback_(nullptr), producer_callback_(nullptr), is_consumer_(false) { /** * This workaroung allows to initialize memory for packet buffers *before* * any static variables that may be initialized in the io_modules. In this * way static variables in modules will be destroyed before the packet * memory. */ PacketManager<>::getInstance(); } /** * Set the consumer callback. * * @param consumer_callback - The pointer to the ConsumerCallback object. */ void setConsumerCallback(ConsumerCallback *consumer_callback) { consumer_callback_ = consumer_callback; } /** * Set the producer callback. * * @param producer_callback - The pointer to the ProducerCallback object. */ void setProducerCallback(ProducerCallback *producer_callback) { producer_callback_ = producer_callback; } /** * Specify the output interface to use. This method will be useful in a future * scenario where the library will be able to forward packets without * connecting to a local forwarder. Now it is not used. * * @param output_interface - The output interface to use for * forwarding/receiving packets. */ TRANSPORT_ALWAYS_INLINE void setOutputInterface( const std::string &output_interface) { io_module_->setOutputInterface(output_interface); } /** * Connect the transport to the local hicn forwarder. * * @param is_consumer - Boolean specifying if the application on top of portal * is a consumer or a producer. */ TRANSPORT_ALWAYS_INLINE void connect(bool is_consumer = true) { if (!io_module_) { pending_interest_hash_table_.reserve(portal_details::pit_size); io_module_.reset(IoModule::load(io_module_path_.c_str())); assert(io_module_); io_module_->init(std::bind(&Portal::processIncomingMessages, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), std::bind(&Portal::setLocalRoutes, this), io_service_, app_name_); io_module_->connect(is_consumer); is_consumer_ = is_consumer; } } /** * Destructor. */ ~Portal() { killConnection(); } /** * Compute name hash */ TRANSPORT_ALWAYS_INLINE uint32_t getHash(const
/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * tcp/tcp_format.c: tcp formatting
 *
 * Copyright (c) 2008 Eliot Dresselhaus
 *
 * Permission is hereby granted, 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, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, 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, 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.
 */

#include <vnet/ip/ip.h>
#include <vnet/tcp/tcp.h>

u8 *
format_tcp_flags (u8