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