summaryrefslogtreecommitdiff
path: root/v5/apf_interpreter.h
blob: 914e35633334e667b4569244d4b016cd3e327da2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * Copyright 2023, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef APF_INTERPRETER_V5_H_
#define APF_INTERPRETER_V5_H_

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Returns the max version of the APF instruction set supported by apf_run().
 * APFv6 is a superset of APFv4. APFv6 interpreters are able to run APFv4 code.
 */
uint32_t apf_version();

/**
 * Allocates a buffer for the APF program to build a reply packet.
 *
 * Unless in a critical low memory state, the firmware must allow allocating at
 * least one 1500 byte buffer for every call to apf_run(). The interpreter will
 * have at most one active allocation at any given time, and will always either
 * transmit or deallocate the buffer before apf_run() returns.
 *
 * It is OK if the firmware decides to limit allocations to at most one per
 * apf_run() invocation.
 *
 * The firmware MAY choose to allocate a larger buffer than requested, and
 * give the apf_interpreter a pointer to the middle of the buffer. This will
 * allow firmware to later (during or after apf_transmit_buffer call) populate
 * any required headers, trailers, etc.
 *
 * @param size - the minimum size of buffer to allocate
 * @return the pointer to the allocated region. The function can return NULL to
 *         indicate allocation failure, for example if too many buffers are
 *         pending transmit. Returning NULL will most likely result in the
 *         apf_run() returning PASS.
 */
uint8_t* apf_allocate_buffer(int size);

/**
 * Transmits the allocated buffer and deallocates it.
 *
 * The apf_interpreter will not read/write from/to the buffer once it calls
 * this function.
 *
 * The content of the buffer between [ptr, ptr + len) are the bytes to be
 * transmitted, starting from the ethernet header and not including any
 * CRC bytes at the end.
 *
 * The firmware is expected to make its best effort to transmit. If it
 * exhausts retries, or if there is no channel for too long and the transmit
 * queue is full, then it is OK for the packet to be dropped. The firmware should
 * prefer to fail allocation if transmit is likely to fail.
 *
 * apf_transmit_buffer() should be asynchronous, which means the actual packet
 * transmission can happen sometime after the function returns.
 *
 * @param ptr - pointer to the transmit buffer, must have been previously
 *             returned by apf_allocate_buffer and not deallocated.
 * @param len - the number of bytes to be transmitted (possibly less than
 *              the allocated buffer), 0 means don't transmit the buffer
 *              but only deallocate it
 * @param dscp - the upper 6 bits of the TOS field in the IPv4 header or traffic
 *             class field in the IPv6 header.
 * @return non-zero if the firmware *knows* the transmit will fail, zero if
 *         the firmware thinks the transmit will succeed. Returning an error
 *         will likely result in apf_run() returning PASS.
 */
int apf_transmit_buffer(uint8_t* ptr, int len, uint8_t dscp);

/**
 * Runs an APF program over a packet.
 *
 * The return value of apf_run indicates whether the packet should
 * be passed or dropped. As a part of apf_run execution, the APF
 * program can call apf_allocate_buffer()/apf_transmit_buffer() to construct
 * a reply packet and transmit it.
 *
 * The text section containing the program instructions starts at address
 * program and stops at + program_len - 1, and the writable data section
 * begins at program + program_len and ends at program + ram_len - 1,
 * as described in the following diagram:
 *
 *     program         program + program_len    program + ram_len
 *        |    text section    |      data section      |
 *        +--------------------+------------------------+
 *
 * @param program - the program bytecode, followed by the writable data region.
 * @param program_len - the length in bytes of the read-only portion of the APF
 *                    buffer pointed to by {@code program}.
 * @param ram_len - total length of the APF buffer pointed to by
 *                  {@code program}, including the read-only bytecode
 *                  portion and the read-write data portion.
 * @param packet - the packet bytes, starting from the ethernet header.
 * @param packet_len - the length of {@code packet} in bytes, not
 *                     including trailers/CRC.
 * @param filter_age_16384ths - the number of 1/16384 seconds since the filter
 *                     was programmed.
 *
 * @return non-zero if packet should be passed, zero if packet should
 *                  be dropped.
 */
int apf_run(uint8_t* const program, const uint32_t program_len,
            const uint32_t ram_len, const uint8_t* const packet,
            const uint32_t packet_len, const uint32_t filter_age_16384ths);

#ifdef __cplusplus
}
#endif

#endif  // APF_INTERPRETER_V5_H_