1 /*
2 * Copyright (c) 2016-2022 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 #include <skywalk/os_skywalk_private.h>
30 #include <netinet/tcp_var.h>
31
32 static int kern_packet_clone_internal(const kern_packet_t, kern_packet_t *,
33 uint32_t, kern_packet_copy_mode_t);
34
35 #if (DEBUG || DEVELOPMENT)
36 __attribute__((noreturn))
37 void
pkt_subtype_assert_fail(const kern_packet_t ph,uint64_t type,uint64_t subtype)38 pkt_subtype_assert_fail(const kern_packet_t ph, uint64_t type, uint64_t subtype)
39 {
40 panic("invalid packet handle 0x%llx (type %llu != %llu || "
41 "subtype %llu != %llu)", ph, SK_PTR_TYPE(ph), type,
42 SK_PTR_SUBTYPE(ph), subtype);
43 /* NOTREACHED */
44 __builtin_unreachable();
45 }
46
47 __attribute__((noreturn))
48 void
pkt_type_assert_fail(const kern_packet_t ph,uint64_t type)49 pkt_type_assert_fail(const kern_packet_t ph, uint64_t type)
50 {
51 panic("invalid packet handle 0x%llx (type %llu != %llu)",
52 ph, SK_PTR_TYPE(ph), type);
53 /* NOTREACHED */
54 __builtin_unreachable();
55 }
56 #endif /* DEBUG || DEVELOPMENT */
57
58 errno_t
kern_packet_set_headroom(const kern_packet_t ph,const uint8_t headroom)59 kern_packet_set_headroom(const kern_packet_t ph, const uint8_t headroom)
60 {
61 return __packet_set_headroom(ph, headroom);
62 }
63
64 uint8_t
kern_packet_get_headroom(const kern_packet_t ph)65 kern_packet_get_headroom(const kern_packet_t ph)
66 {
67 return __packet_get_headroom(ph);
68 }
69
70 errno_t
kern_packet_set_link_header_offset(const kern_packet_t ph,const uint8_t off)71 kern_packet_set_link_header_offset(const kern_packet_t ph, const uint8_t off)
72 {
73 return __packet_set_headroom(ph, off);
74 }
75
76 uint16_t
kern_packet_get_link_header_offset(const kern_packet_t ph)77 kern_packet_get_link_header_offset(const kern_packet_t ph)
78 {
79 return __packet_get_headroom(ph);
80 }
81
82 errno_t
kern_packet_set_link_header_length(const kern_packet_t ph,const uint8_t off)83 kern_packet_set_link_header_length(const kern_packet_t ph, const uint8_t off)
84 {
85 return __packet_set_link_header_length(ph, off);
86 }
87
88 uint8_t
kern_packet_get_link_header_length(const kern_packet_t ph)89 kern_packet_get_link_header_length(const kern_packet_t ph)
90 {
91 return __packet_get_link_header_length(ph);
92 }
93
94 errno_t
kern_packet_set_link_broadcast(const kern_packet_t ph)95 kern_packet_set_link_broadcast(const kern_packet_t ph)
96 {
97 return __packet_set_link_broadcast(ph);
98 }
99
100 boolean_t
kern_packet_get_link_broadcast(const kern_packet_t ph)101 kern_packet_get_link_broadcast(const kern_packet_t ph)
102 {
103 return __packet_get_link_broadcast(ph);
104 }
105
106 errno_t
kern_packet_set_link_multicast(const kern_packet_t ph)107 kern_packet_set_link_multicast(const kern_packet_t ph)
108 {
109 return __packet_set_link_multicast(ph);
110 }
111
112 errno_t
kern_packet_set_link_ethfcs(const kern_packet_t ph)113 kern_packet_set_link_ethfcs(const kern_packet_t ph)
114 {
115 return __packet_set_link_ethfcs(ph);
116 }
117
118 boolean_t
kern_packet_get_link_multicast(const kern_packet_t ph)119 kern_packet_get_link_multicast(const kern_packet_t ph)
120 {
121 return __packet_get_link_multicast(ph);
122 }
123
124 boolean_t
kern_packet_get_link_ethfcs(const kern_packet_t ph)125 kern_packet_get_link_ethfcs(const kern_packet_t ph)
126 {
127 return __packet_get_link_ethfcs(ph);
128 }
129
130 /* deprecated -- no effect, use set_link_header_length instead */
131 errno_t
kern_packet_set_network_header_offset(const kern_packet_t ph,const uint16_t off)132 kern_packet_set_network_header_offset(const kern_packet_t ph,
133 const uint16_t off)
134 {
135 #pragma unused(ph, off)
136 return 0;
137 }
138
139 /* deprecated -- use get_link_header_length instead */
140 uint16_t
kern_packet_get_network_header_offset(const kern_packet_t ph)141 kern_packet_get_network_header_offset(const kern_packet_t ph)
142 {
143 return (uint16_t)__packet_get_headroom(ph) +
144 (uint16_t)__packet_get_link_header_length(ph);
145 }
146
147 /* deprecated */
148 errno_t
kern_packet_set_transport_header_offset(const kern_packet_t ph,const uint16_t off)149 kern_packet_set_transport_header_offset(const kern_packet_t ph,
150 const uint16_t off)
151 {
152 #pragma unused(ph, off)
153 return 0;
154 }
155
156 /* deprecated */
157 uint16_t
kern_packet_get_transport_header_offset(const kern_packet_t ph)158 kern_packet_get_transport_header_offset(const kern_packet_t ph)
159 {
160 #pragma unused(ph)
161 return 0;
162 }
163
164 boolean_t
kern_packet_get_transport_traffic_background(const kern_packet_t ph)165 kern_packet_get_transport_traffic_background(const kern_packet_t ph)
166 {
167 return __packet_get_transport_traffic_background(ph);
168 }
169
170 boolean_t
kern_packet_get_transport_traffic_realtime(const kern_packet_t ph)171 kern_packet_get_transport_traffic_realtime(const kern_packet_t ph)
172 {
173 return __packet_get_transport_traffic_realtime(ph);
174 }
175
176 boolean_t
kern_packet_get_transport_retransmit(const kern_packet_t ph)177 kern_packet_get_transport_retransmit(const kern_packet_t ph)
178 {
179 return __packet_get_transport_retransmit(ph);
180 }
181
182 boolean_t
kern_packet_get_transport_new_flow(const kern_packet_t ph)183 kern_packet_get_transport_new_flow(const kern_packet_t ph)
184 {
185 return __packet_get_transport_new_flow(ph);
186 }
187
188 boolean_t
kern_packet_get_transport_last_packet(const kern_packet_t ph)189 kern_packet_get_transport_last_packet(const kern_packet_t ph)
190 {
191 return __packet_get_transport_last_packet(ph);
192 }
193
194 int
kern_packet_set_service_class(const kern_packet_t ph,const kern_packet_svc_class_t sc)195 kern_packet_set_service_class(const kern_packet_t ph,
196 const kern_packet_svc_class_t sc)
197 {
198 return __packet_set_service_class(ph, sc);
199 }
200
201 kern_packet_svc_class_t
kern_packet_get_service_class(const kern_packet_t ph)202 kern_packet_get_service_class(const kern_packet_t ph)
203 {
204 return __packet_get_service_class(ph);
205 }
206
207 errno_t
kern_packet_set_compression_generation_count(const kern_packet_t ph,uint32_t gencnt)208 kern_packet_set_compression_generation_count(const kern_packet_t ph,
209 uint32_t gencnt)
210 {
211 return __packet_set_comp_gencnt(ph, gencnt);
212 }
213
214 errno_t
kern_packet_get_compression_generation_count(const kern_packet_t ph,uint32_t * pgencnt)215 kern_packet_get_compression_generation_count(const kern_packet_t ph, uint32_t *pgencnt)
216 {
217 return __packet_get_comp_gencnt(ph, pgencnt);
218 }
219
220 errno_t
kern_packet_get_service_class_index(const kern_packet_svc_class_t svc,uint32_t * index)221 kern_packet_get_service_class_index(const kern_packet_svc_class_t svc,
222 uint32_t *index)
223 {
224 if (index == NULL || !KPKT_VALID_SVC(svc)) {
225 return EINVAL;
226 }
227
228 *index = KPKT_SVCIDX(svc);
229 return 0;
230 }
231
232 boolean_t
kern_packet_is_high_priority(const kern_packet_t ph)233 kern_packet_is_high_priority(const kern_packet_t ph)
234 {
235 uint32_t sc;
236 boolean_t is_hi_priority;
237
238 sc = __packet_get_service_class(ph);
239
240 switch (sc) {
241 case PKT_SC_VI:
242 case PKT_SC_SIG:
243 case PKT_SC_VO:
244 case PKT_SC_CTL:
245 is_hi_priority = (PKT_ADDR(ph)->pkt_comp_gencnt == 0 ||
246 PKT_ADDR(ph)->pkt_comp_gencnt == TCP_ACK_COMPRESSION_DUMMY);
247 break;
248
249 case PKT_SC_BK_SYS:
250 case PKT_SC_BK:
251 case PKT_SC_BE:
252 case PKT_SC_RD:
253 case PKT_SC_OAM:
254 case PKT_SC_AV:
255 case PKT_SC_RV:
256 default:
257 is_hi_priority = false;
258 }
259 return is_hi_priority;
260 }
261
262 errno_t
kern_packet_set_traffic_class(const kern_packet_t ph,kern_packet_traffic_class_t tc)263 kern_packet_set_traffic_class(const kern_packet_t ph,
264 kern_packet_traffic_class_t tc)
265 {
266 return __packet_set_traffic_class(ph, tc);
267 }
268
269 kern_packet_traffic_class_t
kern_packet_get_traffic_class(const kern_packet_t ph)270 kern_packet_get_traffic_class(const kern_packet_t ph)
271 {
272 return __packet_get_traffic_class(ph);
273 }
274
275 errno_t
kern_packet_set_inet_checksum(const kern_packet_t ph,const packet_csum_flags_t flags,const uint16_t start,const uint16_t stuff,const boolean_t tx)276 kern_packet_set_inet_checksum(const kern_packet_t ph,
277 const packet_csum_flags_t flags, const uint16_t start,
278 const uint16_t stuff, const boolean_t tx)
279 {
280 return __packet_set_inet_checksum(ph, flags, start, stuff, tx);
281 }
282
283 packet_csum_flags_t
kern_packet_get_inet_checksum(const kern_packet_t ph,uint16_t * start,uint16_t * val,const boolean_t tx)284 kern_packet_get_inet_checksum(const kern_packet_t ph, uint16_t *start,
285 uint16_t *val, const boolean_t tx)
286 {
287 return __packet_get_inet_checksum(ph, start, val, tx);
288 }
289
290 void
kern_packet_set_flow_uuid(const kern_packet_t ph,const uuid_t flow_uuid)291 kern_packet_set_flow_uuid(const kern_packet_t ph, const uuid_t flow_uuid)
292 {
293 __packet_set_flow_uuid(ph, flow_uuid);
294 }
295
296 void
kern_packet_get_flow_uuid(const kern_packet_t ph,uuid_t * flow_uuid)297 kern_packet_get_flow_uuid(const kern_packet_t ph, uuid_t *flow_uuid)
298 {
299 __packet_get_flow_uuid(ph, *flow_uuid);
300 }
301
302 void
kern_packet_clear_flow_uuid(const kern_packet_t ph)303 kern_packet_clear_flow_uuid(const kern_packet_t ph)
304 {
305 __packet_clear_flow_uuid(ph);
306 }
307
308 void
kern_packet_get_euuid(const kern_packet_t ph,uuid_t euuid)309 kern_packet_get_euuid(const kern_packet_t ph, uuid_t euuid)
310 {
311 if (__probable(SK_PTR_TYPE(ph) == NEXUS_META_TYPE_PACKET)) {
312 uuid_copy(euuid, PKT_ADDR(ph)->pkt_policy_euuid);
313 } else {
314 uuid_clear(euuid);
315 }
316 }
317
318 void
kern_packet_set_policy_id(const kern_packet_t ph,uint32_t policy_id)319 kern_packet_set_policy_id(const kern_packet_t ph, uint32_t policy_id)
320 {
321 if (__probable(SK_PTR_TYPE(ph) == NEXUS_META_TYPE_PACKET)) {
322 PKT_ADDR(ph)->pkt_policy_id = policy_id;
323 }
324 }
325
326 uint32_t
kern_packet_get_policy_id(const kern_packet_t ph)327 kern_packet_get_policy_id(const kern_packet_t ph)
328 {
329 if (__probable(SK_PTR_TYPE(ph) == NEXUS_META_TYPE_PACKET)) {
330 return PKT_ADDR(ph)->pkt_policy_id;
331 } else {
332 return 0;
333 }
334 }
335
336 void
kern_packet_set_skip_policy_id(const kern_packet_t ph,uint32_t skip_policy_id)337 kern_packet_set_skip_policy_id(const kern_packet_t ph, uint32_t skip_policy_id)
338 {
339 if (__probable(SK_PTR_TYPE(ph) == NEXUS_META_TYPE_PACKET)) {
340 PKT_ADDR(ph)->pkt_skip_policy_id = skip_policy_id;
341 }
342 }
343
344 uint32_t
kern_packet_get_skip_policy_id(const kern_packet_t ph)345 kern_packet_get_skip_policy_id(const kern_packet_t ph)
346 {
347 if (__probable(SK_PTR_TYPE(ph) == NEXUS_META_TYPE_PACKET)) {
348 return PKT_ADDR(ph)->pkt_skip_policy_id;
349 } else {
350 return 0;
351 }
352 }
353
354 uint32_t
kern_packet_get_data_length(const kern_packet_t ph)355 kern_packet_get_data_length(const kern_packet_t ph)
356 {
357 return __packet_get_data_length(ph);
358 }
359
360 uint32_t
kern_packet_get_buflet_count(const kern_packet_t ph)361 kern_packet_get_buflet_count(const kern_packet_t ph)
362 {
363 return __packet_get_buflet_count(ph);
364 }
365
366 kern_buflet_t
kern_packet_get_next_buflet(const kern_packet_t ph,const kern_buflet_t bprev)367 kern_packet_get_next_buflet(const kern_packet_t ph, const kern_buflet_t bprev)
368 {
369 return __packet_get_next_buflet(ph, bprev);
370 }
371
372 errno_t
kern_packet_finalize(const kern_packet_t ph)373 kern_packet_finalize(const kern_packet_t ph)
374 {
375 return __packet_finalize(ph);
376 }
377
378 kern_packet_idx_t
kern_packet_get_object_index(const kern_packet_t ph)379 kern_packet_get_object_index(const kern_packet_t ph)
380 {
381 return __packet_get_object_index(ph);
382 }
383
384 errno_t
kern_packet_get_timestamp(const kern_packet_t ph,uint64_t * ts,boolean_t * valid)385 kern_packet_get_timestamp(const kern_packet_t ph, uint64_t *ts,
386 boolean_t *valid)
387 {
388 return __packet_get_timestamp(ph, ts, valid);
389 }
390
391 errno_t
kern_packet_set_timestamp(const kern_packet_t ph,uint64_t ts,boolean_t valid)392 kern_packet_set_timestamp(const kern_packet_t ph, uint64_t ts, boolean_t valid)
393 {
394 return __packet_set_timestamp(ph, ts, valid);
395 }
396
397 struct mbuf *
kern_packet_get_mbuf(const kern_packet_t pkt)398 kern_packet_get_mbuf(const kern_packet_t pkt)
399 {
400 struct __kern_packet *kpkt = SK_PTR_ADDR_KPKT(pkt);
401
402 if ((kpkt->pkt_pflags & PKT_F_MBUF_DATA) != 0) {
403 return kpkt->pkt_mbuf;
404 }
405 return NULL;
406 }
407
408 errno_t
kern_packet_get_timestamp_requested(const kern_packet_t ph,boolean_t * requested)409 kern_packet_get_timestamp_requested(const kern_packet_t ph,
410 boolean_t *requested)
411 {
412 return __packet_get_timestamp_requested(ph, requested);
413 }
414
415 void
kern_packet_tx_completion(const kern_packet_t ph,ifnet_t ifp)416 kern_packet_tx_completion(const kern_packet_t ph, ifnet_t ifp)
417 {
418 struct __kern_packet *kpkt = SK_PTR_ADDR_KPKT(ph);
419
420 PKT_TYPE_ASSERT(ph, NEXUS_META_TYPE_PACKET);
421 /*
422 * handling of transmit completion events.
423 */
424 (void) kern_channel_event_transmit_status_with_packet(ph, ifp);
425
426 /*
427 * handling of transmit completion timestamp request callbacks.
428 */
429 if ((kpkt->pkt_pflags & PKT_F_TX_COMPL_TS_REQ) != 0) {
430 __packet_perform_tx_completion_callbacks(ph, ifp);
431 }
432 }
433
434 errno_t
kern_packet_get_tx_completion_status(const kern_packet_t ph,kern_return_t * status)435 kern_packet_get_tx_completion_status(const kern_packet_t ph,
436 kern_return_t *status)
437 {
438 return __packet_get_tx_completion_status(ph, status);
439 }
440
441 errno_t
kern_packet_set_tx_completion_status(const kern_packet_t ph,kern_return_t status)442 kern_packet_set_tx_completion_status(const kern_packet_t ph,
443 kern_return_t status)
444 {
445 return __packet_set_tx_completion_status(ph, status);
446 }
447
448 void
kern_packet_set_group_start(const kern_packet_t ph)449 kern_packet_set_group_start(const kern_packet_t ph)
450 {
451 (void) __packet_set_group_start(ph);
452 }
453
454 boolean_t
kern_packet_get_group_start(const kern_packet_t ph)455 kern_packet_get_group_start(const kern_packet_t ph)
456 {
457 return __packet_get_group_start(ph);
458 }
459
460 void
kern_packet_set_group_end(const kern_packet_t ph)461 kern_packet_set_group_end(const kern_packet_t ph)
462 {
463 (void) __packet_set_group_end(ph);
464 }
465
466 boolean_t
kern_packet_get_group_end(const kern_packet_t ph)467 kern_packet_get_group_end(const kern_packet_t ph)
468 {
469 return __packet_get_group_end(ph);
470 }
471
472 errno_t
kern_packet_get_expire_time(const kern_packet_t ph,uint64_t * ts)473 kern_packet_get_expire_time(const kern_packet_t ph, uint64_t *ts)
474 {
475 return __packet_get_expire_time(ph, ts);
476 }
477
478 errno_t
kern_packet_set_expire_time(const kern_packet_t ph,const uint64_t ts)479 kern_packet_set_expire_time(const kern_packet_t ph, const uint64_t ts)
480 {
481 return __packet_set_expire_time(ph, ts);
482 }
483
484 errno_t
kern_packet_get_expiry_action(const kern_packet_t ph,packet_expiry_action_t * pea)485 kern_packet_get_expiry_action(const kern_packet_t ph, packet_expiry_action_t *pea)
486 {
487 return __packet_get_expiry_action(ph, pea);
488 }
489
490 errno_t
kern_packet_set_expiry_action(const kern_packet_t ph,packet_expiry_action_t pea)491 kern_packet_set_expiry_action(const kern_packet_t ph, packet_expiry_action_t pea)
492 {
493 return __packet_set_expiry_action(ph, pea);
494 }
495
496 errno_t
kern_packet_get_token(const kern_packet_t ph,void * __sized_by (* len)token,uint16_t * len)497 kern_packet_get_token(const kern_packet_t ph, void *__sized_by(*len)token, uint16_t *len)
498 {
499 return __packet_get_token(ph, token, len);
500 }
501
502 errno_t
kern_packet_set_token(const kern_packet_t ph,const void * __sized_by (len)token,const uint16_t len)503 kern_packet_set_token(const kern_packet_t ph, const void *__sized_by(len)token,
504 const uint16_t len)
505 {
506 return __packet_set_token(ph, token, len);
507 }
508
509 errno_t
kern_packet_get_packetid(const kern_packet_t ph,packet_id_t * pktid)510 kern_packet_get_packetid(const kern_packet_t ph, packet_id_t *pktid)
511 {
512 return __packet_get_packetid(ph, pktid);
513 }
514
515 errno_t
kern_packet_set_vlan_tag(const kern_packet_t ph,const uint16_t tag,const boolean_t tag_in_pkt)516 kern_packet_set_vlan_tag(const kern_packet_t ph, const uint16_t tag,
517 const boolean_t tag_in_pkt)
518 {
519 return __packet_set_vlan_tag(ph, tag, tag_in_pkt);
520 }
521
522 errno_t
kern_packet_get_vlan_tag(const kern_packet_t ph,uint16_t * tag,boolean_t * tag_in_pkt)523 kern_packet_get_vlan_tag(const kern_packet_t ph, uint16_t *tag,
524 boolean_t *tag_in_pkt)
525 {
526 return __packet_get_vlan_tag(ph, tag, tag_in_pkt);
527 }
528
529 uint16_t
kern_packet_get_vlan_id(const uint16_t tag)530 kern_packet_get_vlan_id(const uint16_t tag)
531 {
532 return __packet_get_vlan_id(tag);
533 }
534
535 uint8_t
kern_packet_get_vlan_priority(const uint16_t tag)536 kern_packet_get_vlan_priority(const uint16_t tag)
537 {
538 return __packet_get_vlan_priority(tag);
539 }
540
541 errno_t
kern_packet_get_app_metadata(const kern_packet_t ph,packet_app_metadata_type_t * app_type,uint8_t * app_metadata)542 kern_packet_get_app_metadata(const kern_packet_t ph,
543 packet_app_metadata_type_t *app_type, uint8_t *app_metadata)
544 {
545 return __packet_get_app_metadata(ph, app_type, app_metadata);
546 }
547
548 void
kern_packet_set_wake_flag(const kern_packet_t ph)549 kern_packet_set_wake_flag(const kern_packet_t ph)
550 {
551 return __packet_set_wake_flag(ph);
552 }
553
554 boolean_t
kern_packet_get_wake_flag(const kern_packet_t ph)555 kern_packet_get_wake_flag(const kern_packet_t ph)
556 {
557 return __packet_get_wake_flag(ph);
558 }
559
560 uint32_t
kern_inet_checksum(const void * data,uint32_t len,uint32_t sum0)561 kern_inet_checksum(const void *data, uint32_t len, uint32_t sum0)
562 {
563 return __packet_cksum(data, len, sum0);
564 }
565
566 uint32_t
kern_copy_and_inet_checksum(const void * __sized_by (len)src,void * __sized_by (len)dst,uint32_t len,uint32_t sum0)567 kern_copy_and_inet_checksum(const void *__sized_by(len) src, void *__sized_by(len) dst,
568 uint32_t len, uint32_t sum0)
569 {
570 uint32_t sum = __packet_copy_and_sum(src, dst, len, sum0);
571 return __packet_fold_sum_final(sum);
572 }
573
574 /*
575 * Source packet must be finalized (not dropped); cloned packet does not
576 * inherit the finalized flag, or the classified flag, so caller is
577 * responsible for finalizing it and classifying it (as needed).
578 */
579 static int
kern_packet_clone_internal(const kern_packet_t ph1,kern_packet_t * ph2,uint32_t skmflag,kern_packet_copy_mode_t mode)580 kern_packet_clone_internal(const kern_packet_t ph1, kern_packet_t *ph2,
581 uint32_t skmflag, kern_packet_copy_mode_t mode)
582 {
583 struct kern_pbufpool *pool;
584 struct __kern_packet *p1 = SK_PTR_ADDR_KPKT(ph1);
585 struct __kern_packet *p2 = NULL;
586 struct __kern_buflet *p1_buf, *p2_buf;
587 uint16_t bufs_cnt_alloc;
588 int m_how;
589 int err;
590
591 /* TODO: Add quantum support */
592 VERIFY(SK_PTR_TYPE(ph1) == NEXUS_META_TYPE_PACKET);
593
594 /* Source needs to be finalized (not dropped) and with 1 buflet */
595 if ((p1->pkt_qum.qum_qflags & QUM_F_DROPPED) != 0 ||
596 p1->pkt_bufs_cnt == 0) {
597 return EINVAL;
598 }
599
600 /* TODO: Add multi-buflet support */
601 VERIFY(p1->pkt_bufs_cnt == 1);
602
603 switch (mode) {
604 case KPKT_COPY_HEAVY:
605 /*
606 * Allocate a packet with the same number of buffers as that
607 * of the source packet's; this cannot be 0 per check above.
608 */
609 bufs_cnt_alloc = p1->pkt_bufs_cnt;
610 break;
611
612 case KPKT_COPY_LIGHT:
613 /*
614 * Allocate an "empty" packet with no buffers attached; this
615 * will work only on pools marked with "on-demand", which is
616 * the case today for device drivers needing shared buffers
617 * support.
618 *
619 * TODO: We could make this generic and applicable to regular
620 * pools, but it would involve detaching the buffer that comes
621 * attached to the constructed packet; this wouldn't be that
622 * lightweight in nature, but whatever. In such a case the
623 * number of buffers requested during allocation is the same
624 * as the that of the source packet's. For now, let it fail
625 * naturally on regular pools, as part of allocation below.
626 *
627 * XXX: This would also fail on quantums as we currently
628 * restrict quantums to have exactly one buffer.
629 */
630 bufs_cnt_alloc = 0;
631 break;
632
633 default:
634 VERIFY(0);
635 /* NOTREACHED */
636 __builtin_unreachable();
637 }
638
639 *ph2 = 0;
640 pool = __DECONST(struct kern_pbufpool *, SK_PTR_ADDR_KQUM(ph1)->qum_pp);
641 if (skmflag & SKMEM_NOSLEEP) {
642 err = kern_pbufpool_alloc_nosleep(pool, bufs_cnt_alloc, ph2);
643 m_how = M_NOWAIT;
644 } else {
645 err = kern_pbufpool_alloc(pool, bufs_cnt_alloc, ph2);
646 ASSERT(err != ENOMEM);
647 m_how = M_WAIT;
648 }
649 if (__improbable(err != 0)) {
650 /* See comments above related to KPKT_COPY_{HEAVY,LIGHT} */
651 goto error;
652 }
653 p2 = SK_PTR_ADDR_KPKT(*ph2);
654
655 /* Copy packet metadata */
656 _QUM_COPY(&(p1)->pkt_qum, &(p2)->pkt_qum);
657 _PKT_COPY(p1, p2);
658 ASSERT(p2->pkt_mbuf == NULL);
659 ASSERT(p2->pkt_bufs_max == p1->pkt_bufs_max);
660
661 /* clear trace id */
662 p2->pkt_trace_id = 0;
663 /* clear finalized and classified bits from clone */
664 p2->pkt_qum.qum_qflags &= ~(QUM_F_FINALIZED | QUM_F_FLOW_CLASSIFIED);
665
666 switch (mode) {
667 case KPKT_COPY_HEAVY:
668 /*
669 * Heavy: Copy buffer contents and extra metadata.
670 */
671 ASSERT(p2->pkt_bufs_cnt == p1->pkt_bufs_cnt);
672 if (__probable(p1->pkt_bufs_cnt != 0)) {
673 uint8_t *saddr, *daddr;
674 uint32_t copy_len;
675 /*
676 * TODO -- [email protected]
677 * Packets from compat driver could have dlen > dlim
678 * for flowswitch flow compatibility, cleanup when we
679 * make them consistent.
680 */
681 PKT_GET_FIRST_BUFLET(p1, p1->pkt_bufs_cnt, p1_buf);
682 PKT_GET_FIRST_BUFLET(p2, p2->pkt_bufs_cnt, p2_buf);
683 /*
684 * -fbounds-safety: buf_addr is of type
685 * mach_vm_address_t, and it's much easier to forge it
686 * here than chagne the type to a pointer in
687 * struct __buflet. Both saddr and daddr are only used
688 * for bcopy with copy_len as length, so the size of the
689 * forge is copy_len.
690 */
691 copy_len = MIN(p1_buf->buf_dlen, p1_buf->buf_dlim);
692 saddr = __unsafe_forge_bidi_indexable(void *,
693 p1_buf->buf_addr, copy_len);
694 daddr = __unsafe_forge_bidi_indexable(void *,
695 p2_buf->buf_addr, copy_len);
696 if (copy_len != 0) {
697 bcopy(saddr, daddr, copy_len);
698 }
699 *__DECONST(uint32_t *, &p2_buf->buf_dlim) =
700 p1_buf->buf_dlim;
701 p2_buf->buf_dlen = p1_buf->buf_dlen;
702 p2_buf->buf_doff = p1_buf->buf_doff;
703 }
704
705 /* Copy AQM metadata */
706 p2->pkt_flowsrc_type = p1->pkt_flowsrc_type;
707 p2->pkt_flowsrc_fidx = p1->pkt_flowsrc_fidx;
708 _CASSERT((offsetof(struct __flow, flow_src_id) % 8) == 0);
709 _UUID_COPY(p2->pkt_flowsrc_id, p1->pkt_flowsrc_id);
710 _UUID_COPY(p2->pkt_policy_euuid, p1->pkt_policy_euuid);
711 p2->pkt_policy_id = p1->pkt_policy_id;
712 p2->pkt_skip_policy_id = p1->pkt_skip_policy_id;
713
714 p2->pkt_pflags = p1->pkt_pflags;
715 if (p1->pkt_pflags & PKT_F_MBUF_DATA) {
716 ASSERT(p1->pkt_mbuf != NULL);
717 p2->pkt_mbuf = m_dup(p1->pkt_mbuf, m_how);
718 if (p2->pkt_mbuf == NULL) {
719 KPKT_CLEAR_MBUF_DATA(p2);
720 err = ENOBUFS;
721 goto error;
722 }
723 }
724 break;
725
726 case KPKT_COPY_LIGHT:
727 /*
728 * Lightweight: Duplicate buflet(s) and add refs.
729 */
730 ASSERT(p1->pkt_mbuf == NULL);
731 ASSERT(p2->pkt_bufs_cnt == 0);
732 if (__probable(p1->pkt_bufs_cnt != 0)) {
733 PKT_GET_FIRST_BUFLET(p1, p1->pkt_bufs_cnt, p1_buf);
734 p2_buf = &p2->pkt_qum_buf;
735 *__DECONST(uint16_t *, &p2->pkt_bufs_cnt) =
736 p1->pkt_bufs_cnt;
737 _KBUF_COPY(p1_buf, p2_buf);
738 ASSERT(p2_buf->buf_nbft_addr == 0);
739 ASSERT(p2_buf->buf_nbft_idx == OBJ_IDX_NONE);
740 }
741 ASSERT(p2->pkt_bufs_cnt == p1->pkt_bufs_cnt);
742 ASSERT(p2->pkt_bufs_max == p1->pkt_bufs_max);
743 ASSERT(err == 0);
744 break;
745 }
746
747 error:
748 if (err != 0 && p2 != NULL) {
749 uint32_t usecnt = 0;
750
751 ASSERT(p2->pkt_mbuf == NULL);
752 if (__probable(mode == KPKT_COPY_LIGHT)) {
753 /*
754 * This is undoing what _KBUF_COPY() did earlier,
755 * in case this routine is modified to handle regular
756 * pool (not on-demand), which also decrements the
757 * shared buffer's usecnt. For regular pool, calling
758 * kern_pubfpool_free() will not yield a call to
759 * destroy the metadata.
760 */
761 PKT_GET_FIRST_BUFLET(p2, p2->pkt_bufs_cnt, p2_buf);
762 KBUF_DTOR(p2_buf, usecnt);
763 }
764 kern_pbufpool_free(pool, *ph2);
765 *ph2 = 0;
766 }
767
768 return err;
769 }
770
771 errno_t
kern_packet_clone(const kern_packet_t ph1,kern_packet_t * ph2,kern_packet_copy_mode_t mode)772 kern_packet_clone(const kern_packet_t ph1, kern_packet_t *ph2,
773 kern_packet_copy_mode_t mode)
774 {
775 return kern_packet_clone_internal(ph1, ph2, 0, mode);
776 }
777
778 errno_t
kern_packet_clone_nosleep(const kern_packet_t ph1,kern_packet_t * ph2,kern_packet_copy_mode_t mode)779 kern_packet_clone_nosleep(const kern_packet_t ph1, kern_packet_t *ph2,
780 kern_packet_copy_mode_t mode)
781 {
782 return kern_packet_clone_internal(ph1, ph2, SKMEM_NOSLEEP, mode);
783 }
784
785 errno_t
kern_packet_add_buflet(const kern_packet_t ph,const kern_buflet_t bprev,const kern_buflet_t bnew)786 kern_packet_add_buflet(const kern_packet_t ph, const kern_buflet_t bprev,
787 const kern_buflet_t bnew)
788 {
789 return __packet_add_buflet(ph, bprev, bnew);
790 }
791
792 void
kern_packet_append(const kern_packet_t ph1,const kern_packet_t ph2)793 kern_packet_append(const kern_packet_t ph1, const kern_packet_t ph2)
794 {
795 /*
796 * TODO:
797 * Add assert for non-zero ph2 here after changing IOSkywalkFamily
798 * to use kern_packet_set_next() for clearing the next pointer.
799 */
800 kern_packet_set_next(ph1, ph2);
801 }
802
803 kern_packet_t
kern_packet_get_next(const kern_packet_t ph)804 kern_packet_get_next(const kern_packet_t ph)
805 {
806 struct __kern_packet *p, *next;
807
808 p = SK_PTR_ADDR_KPKT(ph);
809 next = p->pkt_nextpkt;
810 return next == NULL ? 0 : SK_PKT2PH(next);
811 }
812
813 void
kern_packet_set_next(const kern_packet_t ph1,const kern_packet_t ph2)814 kern_packet_set_next(const kern_packet_t ph1, const kern_packet_t ph2)
815 {
816 struct __kern_packet *p1, *p2;
817
818 ASSERT(ph1 != 0);
819 p1 = SK_PTR_ADDR_KPKT(ph1);
820 p2 = (ph2 == 0 ? NULL : SK_PTR_ADDR_KPKT(ph2));
821 p1->pkt_nextpkt = p2;
822 }
823
824 void
kern_packet_set_chain_counts(const kern_packet_t ph,uint32_t count,uint32_t bytes)825 kern_packet_set_chain_counts(const kern_packet_t ph, uint32_t count,
826 uint32_t bytes)
827 {
828 struct __kern_packet *p;
829
830 p = SK_PTR_ADDR_KPKT(ph);
831 p->pkt_chain_count = count;
832 p->pkt_chain_bytes = bytes;
833 }
834
835 void
kern_packet_get_chain_counts(const kern_packet_t ph,uint32_t * count,uint32_t * bytes)836 kern_packet_get_chain_counts(const kern_packet_t ph, uint32_t *count,
837 uint32_t *bytes)
838 {
839 struct __kern_packet *p;
840
841 p = SK_PTR_ADDR_KPKT(ph);
842 *count = p->pkt_chain_count;
843 *bytes = p->pkt_chain_bytes;
844 }
845
846 errno_t
kern_buflet_set_data_offset(const kern_buflet_t buf,const uint32_t doff)847 kern_buflet_set_data_offset(const kern_buflet_t buf, const uint32_t doff)
848 {
849 return __buflet_set_data_offset(buf, doff);
850 }
851
852 uint32_t
kern_buflet_get_data_offset(const kern_buflet_t buf)853 kern_buflet_get_data_offset(const kern_buflet_t buf)
854 {
855 return __buflet_get_data_offset(buf);
856 }
857
858 errno_t
kern_buflet_set_data_length(const kern_buflet_t buf,const uint32_t dlen)859 kern_buflet_set_data_length(const kern_buflet_t buf, const uint32_t dlen)
860 {
861 return __buflet_set_data_length(buf, dlen);
862 }
863
864 uint32_t
kern_buflet_get_data_length(const kern_buflet_t buf)865 kern_buflet_get_data_length(const kern_buflet_t buf)
866 {
867 return __buflet_get_data_length(buf);
868 }
869
870 void *
kern_buflet_get_object_address(const kern_buflet_t buf)871 kern_buflet_get_object_address(const kern_buflet_t buf)
872 {
873 return __buflet_get_object_address(buf);
874 }
875
876 uint32_t
kern_buflet_get_object_limit(const kern_buflet_t buf)877 kern_buflet_get_object_limit(const kern_buflet_t buf)
878 {
879 return __buflet_get_object_limit(buf);
880 }
881
882 void *
kern_buflet_get_data_address(const kern_buflet_t buf)883 kern_buflet_get_data_address(const kern_buflet_t buf)
884 {
885 return __buflet_get_data_address(buf);
886 }
887
888 errno_t
kern_buflet_set_data_address(const kern_buflet_t buf,const void * daddr)889 kern_buflet_set_data_address(const kern_buflet_t buf, const void *daddr)
890 {
891 return __buflet_set_data_address(buf, daddr);
892 }
893
894 errno_t
kern_buflet_set_buffer_offset(const kern_buflet_t buf,const uint32_t off)895 kern_buflet_set_buffer_offset(const kern_buflet_t buf, const uint32_t off)
896 {
897 return __buflet_set_buffer_offset(buf, off);
898 }
899
900 kern_segment_t
kern_buflet_get_object_segment(const kern_buflet_t buf,kern_obj_idx_seg_t * idx)901 kern_buflet_get_object_segment(const kern_buflet_t buf,
902 kern_obj_idx_seg_t *idx)
903 {
904 return __buflet_get_object_segment(buf, idx);
905 }
906
907 uint32_t
kern_buflet_get_data_limit(const kern_buflet_t buf)908 kern_buflet_get_data_limit(const kern_buflet_t buf)
909 {
910 return __buflet_get_data_limit(buf);
911 }
912
913 errno_t
kern_buflet_set_data_limit(const kern_buflet_t buf,const uint32_t dlim)914 kern_buflet_set_data_limit(const kern_buflet_t buf, const uint32_t dlim)
915 {
916 return __buflet_set_data_limit(buf, dlim);
917 }
918
919 packet_trace_id_t
kern_packet_get_trace_id(const kern_packet_t ph)920 kern_packet_get_trace_id(const kern_packet_t ph)
921 {
922 return __packet_get_trace_id(ph);
923 }
924
925 void
kern_packet_set_trace_id(const kern_packet_t ph,packet_trace_id_t trace_id)926 kern_packet_set_trace_id(const kern_packet_t ph, packet_trace_id_t trace_id)
927 {
928 return __packet_set_trace_id(ph, trace_id);
929 }
930
931 void
kern_packet_trace_event(const kern_packet_t ph,uint32_t event)932 kern_packet_trace_event(const kern_packet_t ph, uint32_t event)
933 {
934 return __packet_trace_event(ph, event);
935 }
936
937 errno_t
kern_packet_copy_bytes(kern_packet_t pkt,size_t off,size_t len,void * __sized_by (len)out_data)938 kern_packet_copy_bytes(kern_packet_t pkt, size_t off, size_t len,
939 void *__sized_by(len)out_data)
940 {
941 kern_buflet_t buflet = NULL;
942 size_t count;
943 uint8_t *addr;
944 uint32_t buflet_len;
945
946 buflet = __packet_get_next_buflet(pkt, buflet);
947 if (buflet == NULL) {
948 return EINVAL;
949 }
950 buflet_len = __buflet_get_data_length(buflet);
951 if (len > buflet_len) {
952 return EINVAL;
953 }
954 if (off > buflet_len) {
955 return EINVAL;
956 }
957 addr = __buflet_get_data_address(buflet);
958 if (addr == NULL) {
959 return EINVAL;
960 }
961 addr += __buflet_get_data_offset(buflet);
962 addr += off;
963 count = MIN(len, buflet_len - off);
964 bcopy((void *) addr, out_data, count);
965
966 return 0;
967 }
968
969 errno_t
kern_packet_set_fpd_sequence_number(__unused const kern_packet_t ph,__unused uint32_t seq_num)970 kern_packet_set_fpd_sequence_number(__unused const kern_packet_t ph, __unused uint32_t seq_num)
971 {
972 return 0;
973 }
974
975 errno_t
kern_packet_set_fpd_context_id(__unused const kern_packet_t ph,__unused uint16_t ctx_id)976 kern_packet_set_fpd_context_id(__unused const kern_packet_t ph, __unused uint16_t ctx_id)
977 {
978 return 0;
979 }
980
981 errno_t
kern_packet_set_fpd_command(__unused const kern_packet_t ph,__unused uint8_t cmd)982 kern_packet_set_fpd_command(__unused const kern_packet_t ph, __unused uint8_t cmd)
983 {
984 return 0;
985 }
986
987 errno_t
kern_packet_get_flowid(const kern_packet_t ph,packet_flowid_t * pflowid)988 kern_packet_get_flowid(const kern_packet_t ph, packet_flowid_t *pflowid)
989 {
990 return __packet_get_flowid(ph, pflowid);
991 }
992
993 void
kern_packet_set_trace_tag(const kern_packet_t ph,packet_trace_tag_t tag)994 kern_packet_set_trace_tag(const kern_packet_t ph, packet_trace_tag_t tag)
995 {
996 __packet_set_trace_tag(ph, tag);
997 }
998
999 packet_trace_tag_t
kern_packet_get_trace_tag(const kern_packet_t ph)1000 kern_packet_get_trace_tag(const kern_packet_t ph)
1001 {
1002 return __packet_get_trace_tag(ph);
1003 }
1004
1005 errno_t
kern_packet_get_tx_nexus_port_id(const kern_packet_t ph,uint32_t * nx_port_id)1006 kern_packet_get_tx_nexus_port_id(const kern_packet_t ph, uint32_t *nx_port_id)
1007 {
1008 return __packet_get_tx_nx_port_id(ph, nx_port_id);
1009 }
1010
1011 uint16_t
kern_packet_get_protocol_segment_size(const kern_packet_t ph)1012 kern_packet_get_protocol_segment_size(const kern_packet_t ph)
1013 {
1014 return __packet_get_protocol_segment_size(ph);
1015 }
1016
1017 void
kern_packet_set_segment_count(const kern_packet_t ph,uint8_t segcount)1018 kern_packet_set_segment_count(const kern_packet_t ph, uint8_t segcount)
1019 {
1020 __packet_set_segment_count(ph, segcount);
1021 }
1022
1023 void *
kern_packet_get_priv(const kern_packet_t ph)1024 kern_packet_get_priv(const kern_packet_t ph)
1025 {
1026 return __packet_get_priv(ph);
1027 }
1028
1029 void
kern_packet_set_priv(const kern_packet_t ph,void * priv)1030 kern_packet_set_priv(const kern_packet_t ph, void *priv)
1031 {
1032 return __packet_set_priv(ph, priv);
1033 }
1034
1035 void
kern_packet_get_tso_flags(const kern_packet_t ph,packet_tso_flags_t * flags)1036 kern_packet_get_tso_flags(const kern_packet_t ph, packet_tso_flags_t *flags)
1037 {
1038 return __packet_get_tso_flags(ph, flags);
1039 }
1040
1041 errno_t
kern_packet_check_for_expiry_and_notify(const kern_packet_t ph,ifnet_t ifp,uint16_t origin,uint16_t status)1042 kern_packet_check_for_expiry_and_notify(
1043 const kern_packet_t ph, ifnet_t ifp, uint16_t origin, uint16_t status)
1044 {
1045 errno_t err = 0;
1046 uint32_t nx_port_id = 0;
1047 packet_expiry_action_t exp_action = PACKET_EXPIRY_ACTION_NONE;
1048 os_channel_event_packet_transmit_expired_t exp_notif = {0};
1049
1050 if (__improbable(!ifp)) {
1051 return EINVAL;
1052 }
1053
1054 err = __packet_get_expire_time(ph, &exp_notif.packet_tx_expiration_deadline);
1055 if (__probable(err)) {
1056 if (err == ENOENT) {
1057 /* Expiration time is not set; can not continue; not an error. */
1058 return 0;
1059 }
1060 return err;
1061 }
1062
1063 err = __packet_get_expiry_action(ph, &exp_action);
1064 if (__probable(err)) {
1065 if (err == ENOENT) {
1066 /* Expiry action is not set; can not continue; not an error. */
1067 return 0;
1068 }
1069 return err;
1070 }
1071
1072 if (exp_action == PACKET_EXPIRY_ACTION_NONE) {
1073 /* Expiry action is no-op; can not continue; not an error. */
1074 return 0;
1075 }
1076
1077 exp_notif.packet_tx_expiration_timestamp = mach_absolute_time();
1078
1079 /* Check whether the packet has expired */
1080 if (exp_notif.packet_tx_expiration_timestamp < exp_notif.packet_tx_expiration_deadline) {
1081 /* The packet hasn't expired yet; can not continue; not an error */
1082 return 0;
1083 }
1084
1085 /* The packet has expired and notification is requested */
1086 err = __packet_get_packetid(ph, &exp_notif.packet_id);
1087 if (__improbable(err)) {
1088 return err;
1089 }
1090
1091 err = __packet_get_tx_nx_port_id(ph, &nx_port_id);
1092 if (__improbable(err)) {
1093 return err;
1094 }
1095
1096 exp_notif.packet_tx_expiration_status = status;
1097 exp_notif.packet_tx_expiration_origin = origin;
1098
1099 /* Send the notification status */
1100 err = kern_channel_event_transmit_expired(
1101 ifp, &exp_notif, nx_port_id);
1102
1103 return err;
1104 }
1105