blob: 27b6b9b38b36c7b000628ddd1fa02eb4c6e0c40d [file] [log] [blame]
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +09001/*
2 * Copyright (C) 2019 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
17package com.android.server;
18
19import android.annotation.NonNull;
lucaslin1a6095c2021-03-12 00:46:33 +080020import android.net.ConnectivityManager;
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +090021import android.util.SparseBooleanArray;
22
23import com.android.internal.annotations.GuardedBy;
Remi NGUYEN VANf3ba3cd2019-08-01 16:25:50 +090024import com.android.internal.annotations.VisibleForTesting;
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +090025
26/**
27 * Class used to reserve and release net IDs.
28 *
29 * <p>Instances of this class are thread-safe.
Lorenzo Colittif7a98032023-11-15 07:51:27 +000030 *
31 * NetIds are currently 16 bits long and consume 16 bits in the fwmark.
32 * The reason they are large is that applications might get confused if the netId counter
33 * wraps - for example, Network#equals would return true for a current network
34 * and a long-disconnected network.
35 * We could in theory fix this by splitting the identifier in two, e.g., a 24-bit generation
36 * counter and an 8-bit netId. Java Network objects would be constructed from the full 32-bit
37 * number, but only the 8-bit number would be used by netd and the fwmark.
38 * We'd have to fix all code that assumes that it can take a netId or a mark and construct
39 * a Network object from it.
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +090040 */
41public class NetIdManager {
42 // Sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
43 public static final int MIN_NET_ID = 100; // some reserved marks
44 // Top IDs reserved by IpSecService
lucaslin1a6095c2021-03-12 00:46:33 +080045 public static final int MAX_NET_ID = ConnectivityManager.getIpSecNetIdRange().getLower() - 1;
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +090046
47 @GuardedBy("mNetIdInUse")
48 private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
49
50 @GuardedBy("mNetIdInUse")
51 private int mLastNetId = MIN_NET_ID - 1;
52
Remi NGUYEN VANf3ba3cd2019-08-01 16:25:50 +090053 private final int mMaxNetId;
54
55 public NetIdManager() {
56 this(MAX_NET_ID);
57 }
58
59 @VisibleForTesting
60 NetIdManager(int maxNetId) {
61 mMaxNetId = maxNetId;
62 }
63
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +090064 /**
65 * Get the first netId that follows the provided lastId and is available.
66 */
Remi NGUYEN VANf3ba3cd2019-08-01 16:25:50 +090067 private int getNextAvailableNetIdLocked(
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +090068 int lastId, @NonNull SparseBooleanArray netIdInUse) {
69 int netId = lastId;
Remi NGUYEN VANf3ba3cd2019-08-01 16:25:50 +090070 for (int i = MIN_NET_ID; i <= mMaxNetId; i++) {
71 netId = netId < mMaxNetId ? netId + 1 : MIN_NET_ID;
Remi NGUYEN VANe9741e42019-06-13 16:12:02 +090072 if (!netIdInUse.get(netId)) {
73 return netId;
74 }
75 }
76 throw new IllegalStateException("No free netIds");
77 }
78
79 /**
80 * Reserve a new ID for a network.
81 */
82 public int reserveNetId() {
83 synchronized (mNetIdInUse) {
84 mLastNetId = getNextAvailableNetIdLocked(mLastNetId, mNetIdInUse);
85 // Make sure NetID unused. http://b/16815182
86 mNetIdInUse.put(mLastNetId, true);
87 return mLastNetId;
88 }
89 }
90
91 /**
92 * Clear a previously reserved ID for a network.
93 */
94 public void releaseNetId(int id) {
95 synchronized (mNetIdInUse) {
96 mNetIdInUse.delete(id);
97 }
98 }
99}