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 #include "openthread-br/config.h" 38 39 #if __linux__ 40 41 #include <assert.h> 42 #include <map> 43 #include <utility> 44 #include <vector> 45 46 #include <openthread/backbone_router_ftd.h> 47 48 #include "common/code_utils.hpp" 49 #include "common/mainloop.hpp" 50 #include "common/task_runner.hpp" 51 #include "common/time.hpp" 52 53 #if OTBR_ENABLE_VENDOR_INFRA_LINK_SELECT 54 /** 55 * This function implements platform specific rules for selecting infrastructure link. 56 * 57 * This function should return the infrastructure link that is selected by platform specific rules. 58 * If the function returns nullptr, the generic infrastructure link selections rules will be applied. 59 * 60 */ 61 extern "C" const char *otbrVendorInfraLinkSelect(void); 62 #endif 63 64 namespace otbr { 65 namespace Utils { 66 67 /** 68 * This class implements Infrastructure Link Selector. 69 * 70 */ 71 class InfraLinkSelector : public MainloopProcessor, private NonCopyable 72 { 73 public: 74 /** 75 * This constructor initializes the InfraLinkSelector instance. 76 * 77 * @param[in] aInfraLinkNames A list of infrastructure link candidates to select from. 78 * 79 */ 80 explicit InfraLinkSelector(std::vector<const char *> aInfraLinkNames); 81 82 /** 83 * This destructor destroys the InfraLinkSelector instance. 84 * 85 */ 86 ~InfraLinkSelector(void); 87 88 /** 89 * This method selects an infrastructure link among infrastructure link candidates using rules below: 90 * 91 * The infrastructure link in the most usable state is selected: 92 * Prefer `up and running` to `up` 93 * Prefer `up` to `down` 94 * Prefer `down` to `invalid` 95 * Once an interface is selected, it's preferred if either is true: 96 * The interface is still `up and running` 97 * No other interface is `up and running` 98 * The interface has been `up and running` within last 10 seconds 99 * 100 * @returns The selected infrastructure link. 101 * 102 */ 103 const char *Select(void); 104 105 private: 106 /** 107 * This enumeration infrastructure link states. 108 * 109 */ 110 enum LinkState : uint8_t 111 { 112 kInvalid, ///< The infrastructure link is invalid. 113 kDown, ///< The infrastructure link is down. 114 kUp, ///< The infrastructure link is up, but not running. 115 kUpAndRunning, ///< The infrastructure link is up and running. 116 117 }; 118 119 struct LinkInfo 120 { 121 LinkState mState = kInvalid; 122 Clock::time_point mLastRunningTime; 123 bool mWasUpAndRunning = false; 124 125 bool Update(LinkState aState); 126 }; 127 128 static constexpr const char *kDefaultInfraLinkName = ""; 129 static constexpr auto kInfraLinkSelectionDelay = Milliseconds(10000); 130 131 const char *SelectGeneric(void); 132 133 static const char *LinkStateToString(LinkState aState); 134 static LinkState QueryInfraLinkState(const char *aInfraLinkName); 135 void Update(MainloopContext &aMainloop) override; 136 void Process(const MainloopContext &aMainloop) override; 137 void ReceiveNetLinkMessage(void); 138 void HandleInfraLinkStateChange(uint32_t aInfraLinkIndex); 139 140 std::vector<const char *> mInfraLinkNames; 141 std::map<const char *, LinkInfo> mInfraLinkInfos; 142 int mNetlinkSocket = -1; 143 const char *mCurrentInfraLink = nullptr; 144 TaskRunner mTaskRunner; 145 bool mRequireReselect = true; 146 }; 147 148 } // namespace Utils 149 } // namespace otbr 150 151 #endif // __linux__ 152 153 #endif // INFRA_LINK_SELECTOR_HPP_ 154