1 /* 2 * Copyright (c) 2022, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file include definitions for the Infrastructure Link Selector. 32 */ 33 34 #ifndef INFRA_LINK_SELECTOR_HPP_ 35 #define INFRA_LINK_SELECTOR_HPP_ 36 37 #if __linux__ 38 39 #include <assert.h> 40 #include <map> 41 #include <utility> 42 #include <vector> 43 44 #include <openthread/backbone_router_ftd.h> 45 46 #include "common/code_utils.hpp" 47 #include "common/mainloop.hpp" 48 #include "common/task_runner.hpp" 49 #include "common/time.hpp" 50 51 #if OTBR_ENABLE_VENDOR_INFRA_LINK_SELECT 52 /** 53 * This function implements platform specific rules for selecting infrastructure link. 54 * 55 * This function should return the infrastructure link that is selected by platform specific rules. 56 * If the function returns nullptr, the generic infrastructure link selections rules will be applied. 57 * 58 */ 59 extern "C" const char *otbrVendorInfraLinkSelect(void); 60 #endif 61 62 namespace otbr { 63 namespace Utils { 64 65 /** 66 * This class implements Infrastructure Link Selector. 67 * 68 */ 69 class InfraLinkSelector : public MainloopProcessor, private NonCopyable 70 { 71 public: 72 /** 73 * This constructor initializes the InfraLinkSelector instance. 74 * 75 * @param[in] aInfraLinkNames A list of infrastructure link candidates to select from. 76 * 77 */ 78 explicit InfraLinkSelector(std::vector<const char *> aInfraLinkNames); 79 80 /** 81 * This destructor destroys the InfraLinkSelector instance. 82 * 83 */ 84 ~InfraLinkSelector(void); 85 86 /** 87 * This method selects an infrastructure link among infrastructure link candidates using rules below: 88 * 89 * The infrastructure link in the most usable state is selected: 90 * Prefer `up and running` to `up` 91 * Prefer `up` to `down` 92 * Prefer `down` to `invalid` 93 * Once an interface is selected, it's preferred if either is true: 94 * The interface is still `up and running` 95 * No other interface is `up and running` 96 * The interface has been `up and running` within last 10 seconds 97 * 98 * @returns The selected infrastructure link. 99 * 100 */ 101 const char *Select(void); 102 103 private: 104 /** 105 * This enumeration infrastructure link states. 106 * 107 */ 108 enum LinkState : uint8_t 109 { 110 kInvalid, ///< The infrastructure link is invalid. 111 kDown, ///< The infrastructure link is down. 112 kUp, ///< The infrastructure link is up, but not running. 113 kUpAndRunning, ///< The infrastructure link is up and running. 114 115 }; 116 117 struct LinkInfo 118 { 119 LinkState mState = kInvalid; 120 Clock::time_point mLastRunningTime; 121 bool mWasUpAndRunning = false; 122 123 bool Update(LinkState aState); 124 }; 125 126 static constexpr const char *kDefaultInfraLinkName = ""; 127 static constexpr auto kInfraLinkSelectionDelay = Milliseconds(10000); 128 129 const char *SelectGeneric(void); 130 131 static const char *LinkStateToString(LinkState aState); 132 static LinkState QueryInfraLinkState(const char *aInfraLinkName); 133 void Update(MainloopContext &aMainloop) override; 134 void Process(const MainloopContext &aMainloop) override; 135 void ReceiveNetLinkMessage(void); 136 void HandleInfraLinkStateChange(uint32_t aInfraLinkIndex); 137 138 std::vector<const char *> mInfraLinkNames; 139 std::map<const char *, LinkInfo> mInfraLinkInfos; 140 int mNetlinkSocket = -1; 141 const char * mCurrentInfraLink = nullptr; 142 TaskRunner mTaskRunner; 143 bool mRequireReselect = true; 144 }; 145 146 } // namespace Utils 147 } // namespace otbr 148 149 #endif // __linux__ 150 151 #endif // INFRA_LINK_SELECTOR_HPP_ 152