xref: /xnu-10002.81.5/bsd/skywalk/nexus/flowswitch/flow/flow_stats.c (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
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 	if ((fs = skmem_cache_alloc(flow_stats_cache,
80 	    (cansleep ? SKMEM_SLEEP : SKMEM_NOSLEEP))) != NULL) {
81 		/*
82 		 * sf_key is 16-bytes aligned which requires fe to begin on
83 		 * a 16-bytes boundary as well.  This alignment is specified
84 		 * at flow_stats_cache creation time and we assert here.
85 		 */
86 		ASSERT(IS_P2ALIGNED(fs, 16));
87 		bzero(fs, flow_stats_size);
88 		os_ref_init(&fs->fs_refcnt, &flow_stats_refgrp);
89 		SK_DF(SK_VERB_MEM, "allocated fs 0x%llx", SK_KVA(fs));
90 	}
91 
92 	return fs;
93 }
94 
95 void
flow_stats_free(struct flow_stats * fs)96 flow_stats_free(struct flow_stats *fs)
97 {
98 	VERIFY(os_ref_get_count(&fs->fs_refcnt) == 0);
99 
100 	SK_DF(SK_VERB_MEM, "freeing fs 0x%llx", SK_KVA(fs));
101 	skmem_cache_free(flow_stats_cache, fs);
102 }
103