xref: /xnu-11215.41.3/bsd/skywalk/nexus/flowswitch/flow/flow_stats.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
1 /*
2  * Copyright (c) 2018-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 #include <skywalk/os_skywalk_private.h>
30 #include <skywalk/nexus/flowswitch/flow/flow_var.h>
31 #include <skywalk/nexus/flowswitch/fsw_var.h>
32 
33 #define FS_ZONE_NAME            "flow.stats"
34 
35 unsigned int flow_stats_size;           /* size of zone element */
36 struct skmem_cache *flow_stats_cache;   /* cache for flow_stats */
37 
38 os_refgrp_decl(static, flow_stats_refgrp, "flow_stats", NULL);
39 
40 static int __flow_stats_inited = 0;
41 
42 void
flow_stats_init(void)43 flow_stats_init(void)
44 {
45 	ASSERT(!__flow_stats_inited);
46 
47 	flow_stats_size = sizeof(struct flow_stats);
48 	/* request for 16-bytes alignment (due to fe_key) */
49 	flow_stats_cache = skmem_cache_create(FS_ZONE_NAME, flow_stats_size,
50 	    16, NULL, NULL, NULL, NULL, NULL, 0);
51 	if (flow_stats_cache == NULL) {
52 		panic("%s: skmem_cache create failed (%s)",
53 		    __func__, FS_ZONE_NAME);
54 		/* NOTREACHED */
55 		__builtin_unreachable();
56 	}
57 
58 	__flow_stats_inited = 1;
59 }
60 
61 void
flow_stats_fini(void)62 flow_stats_fini(void)
63 {
64 	if (__flow_stats_inited) {
65 		skmem_cache_destroy(flow_stats_cache);
66 		flow_stats_cache = NULL;
67 		__flow_stats_inited = 0;
68 	}
69 }
70 
71 struct flow_stats *
flow_stats_alloc(boolean_t cansleep)72 flow_stats_alloc(boolean_t cansleep)
73 {
74 	struct flow_stats *fs;
75 
76 	_CASSERT((offsetof(struct flow_stats, fs_stats) % 16) == 0);
77 	_CASSERT((offsetof(struct sk_stats_flow, sf_key) % 16) == 0);
78 
79 	/* XXX -fbounds-safety: fix after skmem merge */
80 	fs = __unsafe_forge_bidi_indexable(struct flow_stats *,
81 	    skmem_cache_alloc(flow_stats_cache,
82 	    (cansleep ? SKMEM_SLEEP : SKMEM_NOSLEEP)), flow_stats_size);
83 
84 	if (fs == NULL) {
85 		return NULL;
86 	}
87 	/*
88 	 * sf_key is 16-bytes aligned which requires fe to begin on
89 	 * a 16-bytes boundary as well.  This alignment is specified
90 	 * at flow_stats_cache creation time and we assert here.
91 	 */
92 	ASSERT(IS_P2ALIGNED(fs, 16));
93 	bzero(fs, flow_stats_size);
94 	os_ref_init(&fs->fs_refcnt, &flow_stats_refgrp);
95 	SK_DF(SK_VERB_MEM, "allocated fs 0x%llx", SK_KVA(fs));
96 	return fs;
97 }
98 
99 void
flow_stats_free(struct flow_stats * fs)100 flow_stats_free(struct flow_stats *fs)
101 {
102 	VERIFY(os_ref_get_count(&fs->fs_refcnt) == 0);
103 
104 	SK_DF(SK_VERB_MEM, "freeing fs 0x%llx", SK_KVA(fs));
105 	skmem_cache_free(flow_stats_cache, fs);
106 }
107