1 /*
2 * Copyright (c) 2015 PLUMgrid, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 namespace ebpf {
20 namespace cc {
21
22 // Represent the numeric type of a protocol field
23 enum FieldType {
24 INVALID = 0,
25 UINT8_T,
26 UINT16_T,
27 UINT32_T,
28 UINT64_T,
29 #ifdef __SIZEOF_INT128__
30 UINT128_T,
31 #endif
32 VOID
33 };
34
enum_to_size(const FieldType t)35 static inline size_t enum_to_size(const FieldType t) {
36 switch (t) {
37 case UINT8_T: return sizeof(uint8_t);
38 case UINT16_T: return sizeof(uint16_t);
39 case UINT32_T: return sizeof(uint32_t);
40 case UINT64_T: return sizeof(uint64_t);
41 #ifdef __SIZEOF_INT128__
42 case UINT128_T: return sizeof(__uint128_t);
43 #endif
44 default:
45 return 0;
46 }
47 }
48
49 /// Convert a bit size to the next highest power of 2
next_base2(int v)50 static inline int next_base2(int v) {
51 --v;
52 v |= v >> 1;
53 v |= v >> 2;
54 v |= v >> 4;
55 v |= v >> 8;
56 v |= v >> 16;
57 ++v;
58 return v;
59 }
60
bits_to_uint(int v)61 static inline const char* bits_to_uint(int v) {
62 v = next_base2(v);
63 if (v <= 8) {
64 return "uint8_t";
65 } else if (v == 16) {
66 return "uint16_t";
67 } else if (v == 32) {
68 return "uint32_t";
69 } else if (v == 64) {
70 return "uint64_t";
71 } else if (v >= 128) {
72 /* in plumlet 128-bit integers should be 8-byte aligned,
73 * all other ints should have natural alignment */
74 return "unsigned __int128 __attribute__((packed, aligned(8)))";
75 }
76 return "void";
77 }
78
bits_to_enum(int v)79 static inline FieldType bits_to_enum(int v) {
80 v = next_base2(v);
81 if (v <= 8) {
82 return UINT8_T;
83 } else if (v == 16) {
84 return UINT16_T;
85 } else if (v == 32) {
86 return UINT32_T;
87 } else if (v == 64) {
88 return UINT64_T;
89 #ifdef __SIZEOF_INT128__
90 } else if (v >= 128) {
91 return UINT128_T;
92 #endif
93 }
94 return VOID;
95 }
96
bits_to_size(int v)97 static inline size_t bits_to_size(int v) {
98 return enum_to_size(bits_to_enum(v));
99 }
100
align_offset(size_t offset,FieldType ft)101 static inline size_t align_offset(size_t offset, FieldType ft) {
102 switch (ft) {
103 case UINT8_T:
104 return offset % 8 > 0 ? offset + (8 - offset % 8) : offset;
105 case UINT16_T:
106 return offset % 16 > 0 ? offset + (16 - offset % 16) : offset;
107 case UINT32_T:
108 return offset % 32 > 0 ? offset + (32 - offset % 32) : offset;
109 case UINT64_T:
110 #ifdef __SIZEOF_INT128__
111 case UINT128_T:
112 #endif
113 return offset % 64 > 0 ? offset + (64 - offset % 64) : offset;
114 default:
115 ;
116 }
117 return offset;
118 }
119
120 } // namespace cc
121 } // namespace ebpf
122