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