1 /* 2 * Copyright (C) 2022 The Android Open Source Project 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 package com.android.net.module.util; 18 19 import android.os.Build; 20 import android.system.ErrnoException; 21 22 import androidx.annotation.NonNull; 23 import androidx.annotation.RequiresApi; 24 25 /** 26 * 27 * Generic bitmap class for use with BPF programs. Corresponds to a BpfMap 28 * array type with key->int and value->uint64_t defined in the bpf program. 29 * 30 */ 31 @RequiresApi(Build.VERSION_CODES.S) 32 public class BpfBitmap { 33 private BpfMap<Struct.S32, Struct.S64> mBpfMap; 34 35 /** 36 * Create a BpfBitmap map wrapper with "path" of filesystem. 37 * 38 * @param path The path of the BPF map. 39 */ BpfBitmap(@onNull String path)40 public BpfBitmap(@NonNull String path) throws ErrnoException { 41 mBpfMap = new BpfMap<>(path, Struct.S32.class, Struct.S64.class); 42 } 43 44 /** 45 * Retrieves the value from BpfMap for the given key. 46 * 47 * @param key The key in the map corresponding to the value to return. 48 */ getBpfMapValue(Struct.S32 key)49 private long getBpfMapValue(Struct.S32 key) throws ErrnoException { 50 Struct.S64 curVal = mBpfMap.getValue(key); 51 if (curVal != null) { 52 return curVal.val; 53 } else { 54 return 0; 55 } 56 } 57 58 /** 59 * Retrieves the bit for the given index in the bitmap. 60 * 61 * @param index Position in bitmap. 62 */ get(int index)63 public boolean get(int index) throws ErrnoException { 64 if (index < 0) return false; 65 66 Struct.S32 key = new Struct.S32(index >> 6); 67 return ((getBpfMapValue(key) >>> (index & 63)) & 1L) != 0; 68 } 69 70 /** 71 * Set the specified index in the bitmap. 72 * 73 * @param index Position to set in bitmap. 74 */ set(int index)75 public void set(int index) throws ErrnoException { 76 set(index, true); 77 } 78 79 /** 80 * Unset the specified index in the bitmap. 81 * 82 * @param index Position to unset in bitmap. 83 */ unset(int index)84 public void unset(int index) throws ErrnoException { 85 set(index, false); 86 } 87 88 /** 89 * Change the specified index in the bitmap to set value. 90 * 91 * @param index Position to unset in bitmap. 92 * @param set Boolean indicating to set or unset index. 93 */ set(int index, boolean set)94 public void set(int index, boolean set) throws ErrnoException { 95 if (index < 0) throw new IllegalArgumentException("Index out of bounds."); 96 97 Struct.S32 key = new Struct.S32(index >> 6); 98 long mask = (1L << (index & 63)); 99 long val = getBpfMapValue(key); 100 if (set) val |= mask; else val &= ~mask; 101 mBpfMap.updateEntry(key, new Struct.S64(val)); 102 } 103 104 /** 105 * Clears the map. The map may already be empty. 106 * 107 * @throws ErrnoException if updating entry to 0 fails. 108 */ clear()109 public void clear() throws ErrnoException { 110 mBpfMap.forEach((key, value) -> { 111 mBpfMap.updateEntry(key, new Struct.S64(0)); 112 }); 113 } 114 115 /** 116 * Checks if all bitmap values are 0. 117 */ isEmpty()118 public boolean isEmpty() throws ErrnoException { 119 Struct.S32 key = mBpfMap.getFirstKey(); 120 while (key != null) { 121 if (getBpfMapValue(key) != 0) { 122 return false; 123 } 124 key = mBpfMap.getNextKey(key); 125 } 126 return true; 127 } 128 } 129