1/*
2 * Copyright (c) 2019-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _SKYWALK_OS_CHANNEL_EVENT_H_
30#define _SKYWALK_OS_CHANNEL_EVENT_H_
31
32#ifdef PRIVATE
33#include <stdint.h>
34#include <mach/vm_types.h>
35#include <skywalk/os_packet.h>
36
37
38#define OS_CHANNEL_EVENT_HAS_PACKET_EXPIRY_STATUS (1)
39
40typedef enum : uint32_t {
41 CHANNEL_EVENT_PACKET_TRANSMIT_STATUS = 1,
42 CHANNEL_EVENT_PACKET_TRANSMIT_EXPIRED = 2,
43#if defined(LIBSYSCALL_INTERFACE) || defined(BSD_KERNEL_PRIVATE)
44 CHANNEL_EVENT_MIN = CHANNEL_EVENT_PACKET_TRANSMIT_STATUS,
45 CHANNEL_EVENT_MAX = CHANNEL_EVENT_PACKET_TRANSMIT_EXPIRED,
46#endif /* LIBSYSCALL_INTERFACE || BSD_KERNEL_PRIVATE */
47} os_channel_event_type_t;
48
49
50/*
51 * Subtypes of the `transmission status' channel event.
52 *
53 * NOTE: When adding new event subtypes, check whether
54 * the constant `OS_CHANNEL_EVENT_MAX_SUBEVENT_COUNT'
55 * has to be updated.
56 */
57typedef enum : int32_t {
58 CHANNEL_EVENT_SUCCESS = 0,
59 CHANNEL_EVENT_PKT_TRANSMIT_STATUS_ERR_FLUSH = 1,
60 CHANNEL_EVENT_PKT_TRANSMIT_STATUS_ERR_RETRY_FAILED = 2,
61} os_channel_event_error_t;
62
63typedef struct os_channel_event_packet_transmit_status {
64 packet_id_t packet_id;
65 int32_t packet_status;
66} os_channel_event_packet_transmit_status_t;
67
68/*
69 * Subtypes of the `transmission expired' channel event.
70 *
71 * NOTE: When adding new event subtypes, check whether
72 * the constant `OS_CHANNEL_EVENT_MAX_SUBEVENT_COUNT'
73 * has to be updated.
74 */
75typedef enum : uint16_t {
76 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ERR_NOT_EXPIRED = 0,
77 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ERR_EXPIRED_DROPPED = 1,
78 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ERR_EXPIRED_NOT_DROPPED = 2,
79} os_channel_event_packet_tx_expiration_status_t;
80
81typedef enum : uint16_t {
82 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_NONE = 0,
83 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_HW = 1,
84 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_DRIVER = 2,
85 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_NETIF = 3,
86 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_FSW = 4,
87 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_AQM = 5,
88 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_CHANNEL = 6,
89 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_PROTO_1 = 7,
90 CHANNEL_EVENT_PKT_TRANSMIT_EXPIRED_ORIGIN_PROTO_2 = 8,
91} os_channel_packet_tx_expiration_origin_t;
92
93typedef struct os_channel_event_packet_transmit_expired {
94 packet_id_t packet_id;
95 uint64_t packet_tx_expiration_deadline;
96 uint64_t packet_tx_expiration_timestamp;
97 uint16_t packet_tx_expiration_status;
98 uint16_t packet_tx_expiration_origin;
99} os_channel_event_packet_transmit_expired_t;
100
101/* Maximal number of distinct subevent types */
102#define OS_CHANNEL_EVENT_MAX_SUBEVENT_COUNT (3)
103
104union __os_channel_event_largest_event_payload {
105 os_channel_event_packet_transmit_status_t tx;
106 os_channel_event_packet_transmit_expired_t ex;
107};
108#define CHANNEL_EVENT_MAX_PAYLOAD_LEN (sizeof(union __os_channel_event_largest_event_payload))
109
110#ifndef KERNEL
111/*
112 * opaque handles
113 */
114typedef uint64_t os_channel_event_handle_t;
115typedef mach_vm_address_t os_channel_event_t;
116
117struct os_channel_event_data {
118 os_channel_event_type_t event_type;
119 boolean_t event_more;
120 uint16_t event_data_length;
121 uint8_t *event_data __counted_by(event_data_length);
122};
123
124#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
125extern int
126os_channel_event_get_next_event(const os_channel_event_handle_t event_handle,
127 const os_channel_event_t prev_event, os_channel_event_t *event);
128extern int os_channel_event_get_event_data(const os_channel_event_t, struct os_channel_event_data *);
129#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
130#endif /* KERNEL */
131
132#if defined(LIBSYSCALL_INTERFACE) || defined(BSD_KERNEL_PRIVATE)
133
134/*
135 * The metadata object is placed at the front of every batch of events.
136 * It is followed by `emd_nevents' instances of the `__kern_channel_event'
137 * structure (see below).
138 */
139struct __kern_channel_event_metadata {
140 os_channel_event_type_t emd_etype;
141 uint32_t emd_nevents;
142};
143#define __KERN_CHANNEL_EVENT_OFFSET \
144 (sizeof(struct __kern_channel_event_metadata))
145
146/*
147 * Individual channel events are represented by the
148 * `__kern_channel_event' structure, which comprises
149 * the event header fields, plus the opaque event payload
150 * in the `ev_data' flexible array member.
151 *
152 * CHANNEL_EVENT_MAX_PAYLOAD_LEN
153 * <---------------------------->
154 * +----------------------------+------------------------------+
155 * |struct __kern_channel_event | event payload |
156 * +----------------------------+------------------------------+
157 * <--------------------------------------------------------->
158 * CHANNEL_EVENT_MAX_LEN
159 */
160struct __kern_channel_event {
161 os_channel_event_type_t ev_type;
162 uint32_t ev_flags;
163 uint16_t _reserved;
164 uint16_t ev_dlen;
165 uint8_t ev_data[__counted_by(ev_dlen)];
166};
167
168/* event_flags */
169#define CHANNEL_EVENT_FLAG_MORE_EVENT 0x1
170
171#define CHANNEL_EVENT_MAX_LEN (sizeof(struct __kern_channel_event) + \
172 CHANNEL_EVENT_MAX_PAYLOAD_LEN)
173
174#endif /* LIBSYSCALL_INTERFACE || BSD_KERNEL_PRIVATE */
175
176#if defined(BSD_KERNEL_PRIVATE)
177__BEGIN_DECLS
178extern errno_t kern_channel_event_transmit_status_with_packet(
179 const kern_packet_t, const ifnet_t);
180extern void kern_channel_event_notify(struct __kern_channel_ring *);
181extern int kern_channel_event_sync(struct __kern_channel_ring *, struct proc *,
182 uint32_t);
183__END_DECLS
184#endif /* BSD_KERNEL_PRIVATE */
185
186#ifdef KERNEL
187__BEGIN_DECLS
188/* Post a `packet transmit status' event to an ifnet device */
189extern errno_t kern_channel_event_transmit_status(const ifnet_t,
190 os_channel_event_packet_transmit_status_t *, uint32_t);
191/* Post a `packet transmit status' event to a flowswitch */
192extern errno_t kern_channel_event_transmit_status_with_nexus(const uuid_t,
193 os_channel_event_packet_transmit_status_t *, uint32_t);
194/* Post a `packet transmit expired' event to an ifnet device */
195extern errno_t kern_channel_event_transmit_expired(const ifnet_t,
196 os_channel_event_packet_transmit_expired_t *, uint32_t);
197/* Post a `packet transmit expired' event to a flowswitch */
198extern errno_t kern_channel_event_transmit_expired_with_nexus(const uuid_t,
199 os_channel_event_packet_transmit_expired_t *, uint32_t);
200__END_DECLS
201#endif /* KERNEL */
202
203#endif /* PRIVATE */
204#endif /* !_SKYWALK_OS_CHANNEL_EVENT_H_ */
205