/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _I_OFFLOAD_MANAGER_H_
#define _I_OFFLOAD_MANAGER_H_
/* External Includes */
#include <sys/types.h>
/* Internal Includes */
#include "OffloadStatistics.h"
class IOffloadManager {
public:
enum RET {
FAIL_TOO_MANY_PREFIXES = -6,
FAIL_UNSUPPORTED = -5,
FAIL_INPUT_CHECK = -4,
FAIL_HARDWARE = -3,
FAIL_UNNEEDED = -2,
FAIL_TRY_AGAIN = -1,
SUCCESS = 0,
SUCCESS_DUPLICATE_CONFIG = 1,
SUCCESS_NO_OP = 2,
SUCCESS_OPTIMIZED = 3
}; /* RET */
enum IP_FAM {
V4 = 0,
V6 = 1,
INVALID = 2
}; /* IP_FAM */
/* Overloading to use for addresses as well */
typedef struct Prefix {
IP_FAM fam;
uint32_t v4Addr;
uint32_t v4Mask;
uint32_t v6Addr[4];
uint32_t v6Mask[4];
} prefix_t;
/* ---------------------------- LIFECYCLE ------------------------------- */
virtual ~IOffloadManager(){}
/* ---------------------- ASYNC EVENT CALLBACKS ------------------------- */
class IpaEventListener {
public:
enum StoppedReason {
/**
* Offload was stopped due to the configuration being removed via
* setUpstreamParameters/removeDownstream.
*/
REQUESTED,
/**
* Offload was stopped due to an internal (to IPA or modem) error.
*
* Statistics may be temporarily unavailable.
*/
ERROR,
/**
* Offload was stopped because the upstream connection has
* migrated to unsupported radio access technology.
*
* Statistics will still be available.
*/
UNSUPPORTED
}; /* StoppedReason */
virtual ~IpaEventListener(){}
/**
* Called when Offload first begins to occur on any upstream and
* tether interface pair. It should be paired with an onOffloadStopped
* call.
*/
virtual void onOffloadStarted(){}
/**
* Called when Offload stops occurring on all upstream and tether
* interface pairs. It comes after a call to onOffloadStarted.
*
* @param reason Reason that Offload was stopped
*/
virtual void onOffloadStopped(StoppedReason /* reason */){}
/**
* Called when the hardware can support Offload again.
*
* Any statistics that were previously unavailable, may be queried
* again at this time.
*/
virtual void onOffloadSupportAvailable(){}
/**
* Called when the limit set via setQuota has expired.
*
* It is implied that Offload has been stopped on all upstream and
* tether interface pairs when this callback is called.
*/
virtual void onLimitReached(){}
}; /* IpaEventListener */
/**
* Request notifications about asynchronous events that occur in hardware.
*
* The calling client must be able to handle the callback on a separate
* thread (i.e. their implementation of IpaEventListener must be thread
* safe).
*
* @return SUCCESS iff callback successfully registered
*
* Remarks: This can't really be allowed to fail.
*/
virtual RET registerEventListener(IpaEventListener* /* listener */) = 0;
/**
* Unregister a previously registered listener.
*
* @return SUCCESS iff callback successfully unregistered
* FAIL_INPUT_CHECK if callback was never registered
*/
virtual RET unregisterEventListener(IpaEventListener* /* listener */) = 0;
class ConntrackTimeoutUpdater {
public:
enum L4Protocol {
TCP = 0,
UDP = 1
}; /* L4Protocol */
typedef struct IpAddrPortPair {
uint32_t ipAddr;
uint16_t port;
} ipAddrPortPair_t;
typedef struct NatTimeoutUpdate {
IpAddrPortPair src;
IpAddrPortPair dst;
L4Protocol proto;
} natTimeoutUpdate_t;
virtual ~ConntrackTimeoutUpdater(){}
virtual void updateTimeout(NatTimeoutUpdate /* update */) {}
}; /* ConntrackTimeoutUpdater */
/**
* Register a callback that may be called if the OffloadManager wants to
* update the timeout value in conntrack of kernel.
*
* The calling client must be able to handle the callback on a separate
* thread (i.e. their implementation of ConntrackTimeoutUpdater must be
* thread safe)
*
* @return SUCCESS iff callback successfully registered
*
* Remarks: This can't really be allowed to fail
*/
virtual RET registerCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0;
/**
* Unregister a previously registered callback.
*
* @return SUCCESS iff callback successfully unregistered
* FAIL_INPUT_CHECK if callback was never registered
*/
virtual RET unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0;
/* ----------------------------- CONFIG --------------------------------- */
/**
* Provide a file descriptor for use with conntrack library
*
* @param fd File Descriptor that has been opened and bound to groups
* @param groups Groups (bit mask) that fd has been bound to
*
* @return SUCCESS iff IOffloadManager needed this file descriptor and
* it was properly bound.
* FAIL_INPUT_CHECK if IOffloadManager needed this file descriptor
* but it was found to not be properly bound
* FAIL_UNNEEDED if IOffloadManager determined that it does not need
* a file descriptor bound to these groups.
*/
virtual RET provideFd(int /* fd */, unsigned int /* group */) = 0;
/**
* Indicate that IOffloadManager <b>must</b> cease using all file
* descriptors passed via provideFd API.
*
* After this call returns, the file descriptors will likely be closed by
* the calling client.
*
* @return SUCCESS iff IOffloadManager has stopped using all file
* descriptors
* FAIL_TRY_AGAIN if IOffloadManager needs more time with these
* file descriptors before it can release them
*
* Remarks: Currently, it would be very difficult to handle a FAIL_TRY_AGAIN
* because HAL serivce does not own a thread outside of RPC
* Threadpool to reschedule this call.
*/
virtual RET clearAllFds() = 0;
/**
* Query whether STA+AP offload is supported on this device.
*
* @return true if supported, false otherwise
*/
virtual bool isStaApSupported() = 0;
/* ------------------------------ ROUTE --------------------------------- */
/**
* Add a downstream prefix that <i>may</i> be forwarded.
*
* The Prefix may be an IPv4 or IPv6 address to signify which family can be
* offloaded from the specified tether interface. If the given IP family,
* as determined by the Prefix, has a corresponding upstream configured,
* then traffic should be forwarded between the two interfaces.
*
* Only traffic that has a downstream address within the specified Prefix
* can be forwarded. Traffic from the same downstream interface that falls
* outside of the Prefix will be unaffected and can be forwarded iff it was
* previously configured via a separate addDownstream call.
*
* If no upstream has been configured, then this information must be cached
* so that offload may begin once an upstream is configured.
*
* This API does <b>not</b> replace any previously configured downstreams
* and must be explicitly removed by calling removeDownstream or by clearing
* the entire configuration by calling stopAllOffload.
*
* @return SUCCESS The new information was accepted
* FAIL_TOO_MANY_PREFIXES The hardware has already accepted the max
* number of Prefixes that can be supported.
* If offload is desired on this Prefix then
* another must be removed first.
* FAIL_UNSUPPORTED The hardware cannot forward traffic from this
* downstream interface and will never be able to.
*/
virtual RET addDownstream(const char* /* downstream */,
const Prefix& /* prefix */) = 0;
/**
* Remove a downstream Prefix that forwarding was previously requested for.
*
* The Prefix may be an IPv4 or IPv6 address. Traffic outside of this
* Prefix is not affected.
*
* @return SUCCESS iff forwarding was previously occurring and has been
* stopped
* SUCCESS_NO_OP iff forwarding was not previously occurring and
* therefore no action needed to be taken
*/
virtual RET removeDownstream(const char* /* downstream */,
const Prefix& /* prefix */) = 0;
/**
* Indicate that hardware should forward traffic from any configured
* downstreams to the specified upstream.
*
* When iface is non-null and non-empty and v4Gw is valid, then any
* currently configured or future configured IPv4 downstreams should be
* forwarded to this upstream interface.
*
* When iface is non-null and non-empty and v6Gw is valid, then any
* currently configured or future configured IPv6 downstreams should be
* forwarded to this upstream interface.
*
* @param iface Upstream interface name. Only one is needed because IPv4
* and IPv6 interface names are required to match.
* @param v4Gw The address of the IPv4 Gateway on the iface
* @param v6Gw The address of one of the IPv6 Gateways on the iface
*
* @return SUCCESS iff the specified configuration was applied
* SUCCESS_DUPLICATE_CONFIG if this configuration <i>exactly</i>
* matches a previously provided
* configuration. This means that no
* action has to be taken, but, the
* configuration was previously accepted
* and applied.
* FAIL_UNSUPPORTED if hardware cannot support forwarding to this
* upstream interface
*
* Remarks: This overrides any previously configured parameters
*/
virtual RET setUpstream(const char* /* iface */, const Prefix& /* v4Gw */,
const Prefix& /* v6Gw */) = 0;
/**
* All traffic must be returned to the software path and all configuration
* (including provided file descriptors) must be forgotten.
*
* @return SUCCESS If all offload was successfully stopped and provided
* file descriptors were released.
*
* Remarks: This can't really fail?
*/
virtual RET stopAllOffload() = 0;
/* --------------------------- STATS/POLICY ----------------------------- */
/**
* Instruct hardware to stop forwarding traffic and send a callback after
* limit bytes have been transferred in either direction on this upstream
* interface.
*
* @param upstream Upstream interface name that the limit should apply to
* @param limit Bytes limit that can occur before action should be taken
*
* @return SUCCESS If the limit was successfully applied
* SUCCESS_OPTIMIZED If the limit was sufficiently high to be
* interpreted as "no quota".
* FAIL_HARDWARE If the limit was rejected by the hardware
* FAIL_UNSUPPORTED If metering is not supported on this interface
* FAIL_TRY_AGAIN If this upstream has not been previously
* configured to allow offload
* (via setUpstreamParameters)
*/
virtual RET setQuota(const char* /* upstream */, uint64_t /* limit */) = 0;
/**
* Query for statistics counters in hardware.
*
* This returns an aggregate of all hardware accelerated traffic which
* has occurred on this upstream interface.
*
* @param upstream Interface on which traffic entered/exited
* @param reset Whether hardware counters should reset after returning
* current statistics
* @param ret Output variable where statistics are returned
*
* @return SUCCESS If the statistics were successfully populated in ret and
* were successfully reset if requested.
* FAIL_TRY_AGAIN If the statistics are not currently available but
* may be available later. This may occur during
* a subsystem restart.
* FAIL_UNSUPPORTED If statistics are not supported on this upstream
*/
virtual RET getStats(const char* /* upstream */, bool /* reset */,
OffloadStatistics& /* ret */) = 0;
}; /* IOffloadManager */
#endif /* _I_OFFLOAD_MANAGER_H_ */