1 /* 2 * Copyright (c) 2017, The Linux Foundation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 #ifndef _I_OFFLOAD_MANAGER_H_ 30 #define _I_OFFLOAD_MANAGER_H_ 31 32 /* External Includes */ 33 #include <sys/types.h> 34 35 /* Internal Includes */ 36 #include "OffloadStatistics.h" 37 38 39 class IOffloadManager { 40 public: 41 enum RET { 42 FAIL_TOO_MANY_PREFIXES = -6, 43 FAIL_UNSUPPORTED = -5, 44 FAIL_INPUT_CHECK = -4, 45 FAIL_HARDWARE = -3, 46 FAIL_UNNEEDED = -2, 47 FAIL_TRY_AGAIN = -1, 48 SUCCESS = 0, 49 SUCCESS_DUPLICATE_CONFIG = 1, 50 SUCCESS_NO_OP = 2, 51 SUCCESS_OPTIMIZED = 3 52 }; /* RET */ 53 54 enum IP_FAM { 55 V4 = 0, 56 V6 = 1, 57 INVALID = 2 58 }; /* IP_FAM */ 59 60 /* Overloading to use for addresses as well */ 61 typedef struct Prefix { 62 IP_FAM fam; 63 uint32_t v4Addr; 64 uint32_t v4Mask; 65 uint32_t v6Addr[4]; 66 uint32_t v6Mask[4]; 67 } prefix_t; 68 69 /* ---------------------------- LIFECYCLE ------------------------------- */ ~IOffloadManager()70 virtual ~IOffloadManager(){} 71 72 /* ---------------------- ASYNC EVENT CALLBACKS ------------------------- */ 73 class IpaEventListener { 74 public: 75 enum StoppedReason { 76 /** 77 * Offload was stopped due to the configuration being removed via 78 * setUpstreamParameters/removeDownstream. 79 */ 80 REQUESTED, 81 /** 82 * Offload was stopped due to an internal (to IPA or modem) error. 83 * 84 * Statistics may be temporarily unavailable. 85 */ 86 ERROR, 87 /** 88 * Offload was stopped because the upstream connection has 89 * migrated to unsupported radio access technology. 90 * 91 * Statistics will still be available. 92 */ 93 UNSUPPORTED 94 }; /* StoppedReason */ ~IpaEventListener()95 virtual ~IpaEventListener(){} 96 /** 97 * Called when Offload first begins to occur on any upstream and 98 * tether interface pair. It should be paired with an onOffloadStopped 99 * call. 100 */ onOffloadStarted()101 virtual void onOffloadStarted(){} 102 /** 103 * Called when Offload stops occurring on all upstream and tether 104 * interface pairs. It comes after a call to onOffloadStarted. 105 * 106 * @param reason Reason that Offload was stopped 107 */ onOffloadStopped(StoppedReason)108 virtual void onOffloadStopped(StoppedReason /* reason */){} 109 /** 110 * Called when the hardware can support Offload again. 111 * 112 * Any statistics that were previously unavailable, may be queried 113 * again at this time. 114 */ onOffloadSupportAvailable()115 virtual void onOffloadSupportAvailable(){} 116 /** 117 * Called when the limit set via setQuota has expired. 118 * 119 * It is implied that Offload has been stopped on all upstream and 120 * tether interface pairs when this callback is called. 121 */ onLimitReached()122 virtual void onLimitReached(){} 123 }; /* IpaEventListener */ 124 125 /** 126 * Request notifications about asynchronous events that occur in hardware. 127 * 128 * The calling client must be able to handle the callback on a separate 129 * thread (i.e. their implementation of IpaEventListener must be thread 130 * safe). 131 * 132 * @return SUCCESS iff callback successfully registered 133 * 134 * Remarks: This can't really be allowed to fail. 135 */ 136 virtual RET registerEventListener(IpaEventListener* /* listener */) = 0; 137 /** 138 * Unregister a previously registered listener. 139 * 140 * @return SUCCESS iff callback successfully unregistered 141 * FAIL_INPUT_CHECK if callback was never registered 142 */ 143 virtual RET unregisterEventListener(IpaEventListener* /* listener */) = 0; 144 145 class ConntrackTimeoutUpdater { 146 public: 147 enum L4Protocol { 148 TCP = 0, 149 UDP = 1 150 }; /* L4Protocol */ 151 typedef struct IpAddrPortPair { 152 uint32_t ipAddr; 153 uint16_t port; 154 } ipAddrPortPair_t; 155 typedef struct NatTimeoutUpdate { 156 IpAddrPortPair src; 157 IpAddrPortPair dst; 158 L4Protocol proto; 159 } natTimeoutUpdate_t; ~ConntrackTimeoutUpdater()160 virtual ~ConntrackTimeoutUpdater(){} updateTimeout(NatTimeoutUpdate)161 virtual void updateTimeout(NatTimeoutUpdate /* update */) {} 162 }; /* ConntrackTimeoutUpdater */ 163 164 /** 165 * Register a callback that may be called if the OffloadManager wants to 166 * update the timeout value in conntrack of kernel. 167 * 168 * The calling client must be able to handle the callback on a separate 169 * thread (i.e. their implementation of ConntrackTimeoutUpdater must be 170 * thread safe) 171 * 172 * @return SUCCESS iff callback successfully registered 173 * 174 * Remarks: This can't really be allowed to fail 175 */ 176 virtual RET registerCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0; 177 /** 178 * Unregister a previously registered callback. 179 * 180 * @return SUCCESS iff callback successfully unregistered 181 * FAIL_INPUT_CHECK if callback was never registered 182 */ 183 virtual RET unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0; 184 185 /* ----------------------------- CONFIG --------------------------------- */ 186 /** 187 * Provide a file descriptor for use with conntrack library 188 * 189 * @param fd File Descriptor that has been opened and bound to groups 190 * @param groups Groups (bit mask) that fd has been bound to 191 * 192 * @return SUCCESS iff IOffloadManager needed this file descriptor and 193 * it was properly bound. 194 * FAIL_INPUT_CHECK if IOffloadManager needed this file descriptor 195 * but it was found to not be properly bound 196 * FAIL_UNNEEDED if IOffloadManager determined that it does not need 197 * a file descriptor bound to these groups. 198 */ 199 virtual RET provideFd(int /* fd */, unsigned int /* group */) = 0; 200 /** 201 * Indicate that IOffloadManager <b>must</b> cease using all file 202 * descriptors passed via provideFd API. 203 * 204 * After this call returns, the file descriptors will likely be closed by 205 * the calling client. 206 * 207 * @return SUCCESS iff IOffloadManager has stopped using all file 208 * descriptors 209 * FAIL_TRY_AGAIN if IOffloadManager needs more time with these 210 * file descriptors before it can release them 211 * 212 * Remarks: Currently, it would be very difficult to handle a FAIL_TRY_AGAIN 213 * because HAL serivce does not own a thread outside of RPC 214 * Threadpool to reschedule this call. 215 */ 216 virtual RET clearAllFds() = 0; 217 /** 218 * Query whether STA+AP offload is supported on this device. 219 * 220 * @return true if supported, false otherwise 221 */ 222 virtual bool isStaApSupported() = 0; 223 224 /* ------------------------------ ROUTE --------------------------------- */ 225 /** 226 * Add a downstream prefix that <i>may</i> be forwarded. 227 * 228 * The Prefix may be an IPv4 or IPv6 address to signify which family can be 229 * offloaded from the specified tether interface. If the given IP family, 230 * as determined by the Prefix, has a corresponding upstream configured, 231 * then traffic should be forwarded between the two interfaces. 232 * 233 * Only traffic that has a downstream address within the specified Prefix 234 * can be forwarded. Traffic from the same downstream interface that falls 235 * outside of the Prefix will be unaffected and can be forwarded iff it was 236 * previously configured via a separate addDownstream call. 237 * 238 * If no upstream has been configured, then this information must be cached 239 * so that offload may begin once an upstream is configured. 240 * 241 * This API does <b>not</b> replace any previously configured downstreams 242 * and must be explicitly removed by calling removeDownstream or by clearing 243 * the entire configuration by calling stopAllOffload. 244 * 245 * @return SUCCESS The new information was accepted 246 * FAIL_TOO_MANY_PREFIXES The hardware has already accepted the max 247 * number of Prefixes that can be supported. 248 * If offload is desired on this Prefix then 249 * another must be removed first. 250 * FAIL_UNSUPPORTED The hardware cannot forward traffic from this 251 * downstream interface and will never be able to. 252 */ 253 virtual RET addDownstream(const char* /* downstream */, 254 const Prefix& /* prefix */) = 0; 255 /** 256 * Remove a downstream Prefix that forwarding was previously requested for. 257 * 258 * The Prefix may be an IPv4 or IPv6 address. Traffic outside of this 259 * Prefix is not affected. 260 * 261 * @return SUCCESS iff forwarding was previously occurring and has been 262 * stopped 263 * SUCCESS_NO_OP iff forwarding was not previously occurring and 264 * therefore no action needed to be taken 265 */ 266 virtual RET removeDownstream(const char* /* downstream */, 267 const Prefix& /* prefix */) = 0; 268 /** 269 * Indicate that hardware should forward traffic from any configured 270 * downstreams to the specified upstream. 271 * 272 * When iface is non-null and non-empty and v4Gw is valid, then any 273 * currently configured or future configured IPv4 downstreams should be 274 * forwarded to this upstream interface. 275 * 276 * When iface is non-null and non-empty and v6Gw is valid, then any 277 * currently configured or future configured IPv6 downstreams should be 278 * forwarded to this upstream interface. 279 * 280 * @param iface Upstream interface name. Only one is needed because IPv4 281 * and IPv6 interface names are required to match. 282 * @param v4Gw The address of the IPv4 Gateway on the iface 283 * @param v6Gw The address of one of the IPv6 Gateways on the iface 284 * 285 * @return SUCCESS iff the specified configuration was applied 286 * SUCCESS_DUPLICATE_CONFIG if this configuration <i>exactly</i> 287 * matches a previously provided 288 * configuration. This means that no 289 * action has to be taken, but, the 290 * configuration was previously accepted 291 * and applied. 292 * FAIL_UNSUPPORTED if hardware cannot support forwarding to this 293 * upstream interface 294 * 295 * Remarks: This overrides any previously configured parameters 296 */ 297 virtual RET setUpstream(const char* /* iface */, const Prefix& /* v4Gw */, 298 const Prefix& /* v6Gw */) = 0; 299 /** 300 * All traffic must be returned to the software path and all configuration 301 * (including provided file descriptors) must be forgotten. 302 * 303 * @return SUCCESS If all offload was successfully stopped and provided 304 * file descriptors were released. 305 * 306 * Remarks: This can't really fail? 307 */ 308 virtual RET stopAllOffload() = 0; 309 310 /* --------------------------- STATS/POLICY ----------------------------- */ 311 /** 312 * Instruct hardware to stop forwarding traffic and send a callback after 313 * limit bytes have been transferred in either direction on this upstream 314 * interface. 315 * 316 * @param upstream Upstream interface name that the limit should apply to 317 * @param limit Bytes limit that can occur before action should be taken 318 * 319 * @return SUCCESS If the limit was successfully applied 320 * SUCCESS_OPTIMIZED If the limit was sufficiently high to be 321 * interpreted as "no quota". 322 * FAIL_HARDWARE If the limit was rejected by the hardware 323 * FAIL_UNSUPPORTED If metering is not supported on this interface 324 * FAIL_TRY_AGAIN If this upstream has not been previously 325 * configured to allow offload 326 * (via setUpstreamParameters) 327 */ 328 virtual RET setQuota(const char* /* upstream */, uint64_t /* limit */) = 0; 329 /** 330 * Query for statistics counters in hardware. 331 * 332 * This returns an aggregate of all hardware accelerated traffic which 333 * has occurred on this upstream interface. 334 * 335 * @param upstream Interface on which traffic entered/exited 336 * @param reset Whether hardware counters should reset after returning 337 * current statistics 338 * @param ret Output variable where statistics are returned 339 * 340 * @return SUCCESS If the statistics were successfully populated in ret and 341 * were successfully reset if requested. 342 * FAIL_TRY_AGAIN If the statistics are not currently available but 343 * may be available later. This may occur during 344 * a subsystem restart. 345 * FAIL_UNSUPPORTED If statistics are not supported on this upstream 346 */ 347 virtual RET getStats(const char* /* upstream */, bool /* reset */, 348 OffloadStatistics& /* ret */) = 0; 349 }; /* IOffloadManager */ 350 #endif /* _I_OFFLOAD_MANAGER_H_ */ 351