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 extern "C" const char *otbrVendorInfraLinkSelect(void); 61 #endif 62 63 namespace otbr { 64 namespace Utils { 65 66 /** 67 * This class implements Infrastructure Link Selector. 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 explicit InfraLinkSelector(std::vector<const char *> aInfraLinkNames); 78 79 /** 80 * This destructor destroys the InfraLinkSelector instance. 81 */ 82 ~InfraLinkSelector(void); 83 84 /** 85 * This method selects an infrastructure link among infrastructure link candidates using rules below: 86 * 87 * The infrastructure link in the most usable state is selected: 88 * Prefer `up and running` to `up` 89 * Prefer `up` to `down` 90 * Prefer `down` to `invalid` 91 * Once an interface is selected, it's preferred if either is true: 92 * The interface is still `up and running` 93 * No other interface is `up and running` 94 * The interface has been `up and running` within last 10 seconds 95 * 96 * @returns The selected infrastructure link. 97 */ 98 const char *Select(void); 99 100 private: 101 /** 102 * This enumeration infrastructure link states. 103 */ 104 enum LinkState : uint8_t 105 { 106 kInvalid, ///< The infrastructure link is invalid. 107 kDown, ///< The infrastructure link is down. 108 kUp, ///< The infrastructure link is up, but not running. 109 kUpAndRunning, ///< The infrastructure link is up and running. 110 111 }; 112 113 struct LinkInfo 114 { 115 LinkState mState = kInvalid; 116 Clock::time_point mLastRunningTime; 117 bool mWasUpAndRunning = false; 118 119 bool Update(LinkState aState); 120 }; 121 122 static constexpr const char *kDefaultInfraLinkName = ""; 123 static constexpr auto kInfraLinkSelectionDelay = Milliseconds(10000); 124 125 const char *SelectGeneric(void); 126 127 static const char *LinkStateToString(LinkState aState); 128 static LinkState QueryInfraLinkState(const char *aInfraLinkName); 129 void Update(MainloopContext &aMainloop) override; 130 void Process(const MainloopContext &aMainloop) override; 131 void ReceiveNetLinkMessage(void); 132 void HandleInfraLinkStateChange(uint32_t aInfraLinkIndex); 133 134 std::vector<const char *> mInfraLinkNames; 135 std::map<const char *, LinkInfo> mInfraLinkInfos; 136 int mNetlinkSocket = -1; 137 const char *mCurrentInfraLink = nullptr; 138 TaskRunner mTaskRunner; 139 bool mRequireReselect = true; 140 }; 141 142 } // namespace Utils 143 } // namespace otbr 144 145 #endif // __linux__ 146 147 #endif // INFRA_LINK_SELECTOR_HPP_ 148