|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * CNetworkPartitionManager |
|
16 * System Includes |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 #ifdef WIN32 |
|
24 #include <winsock2.h> |
|
25 #else |
|
26 #include <netinet/in.h> |
|
27 #endif |
|
28 #include <assert.h> |
|
29 #include <math.h> |
|
30 |
|
31 |
|
32 /******************************************************************************* |
|
33 * |
|
34 * Local Includes |
|
35 * |
|
36 ******************************************************************************/ |
|
37 #include "CNetworkPartitionManager.h" |
|
38 |
|
39 |
|
40 /******************************************************************************* |
|
41 * |
|
42 * PUBLIC METHOD: CNetworkPartitionManager |
|
43 * |
|
44 ******************************************************************************/ |
|
45 CNetworkPartitionManager::CNetworkPartitionManager() |
|
46 { |
|
47 } |
|
48 |
|
49 |
|
50 /******************************************************************************* |
|
51 * |
|
52 * PUBLIC METHOD: ~CNetworkPartitionManager |
|
53 * |
|
54 ******************************************************************************/ |
|
55 CNetworkPartitionManager::~CNetworkPartitionManager() |
|
56 { |
|
57 } |
|
58 |
|
59 |
|
60 /******************************************************************************* |
|
61 * |
|
62 * PUBLIC METHOD: SetConfiguration |
|
63 * |
|
64 ******************************************************************************/ |
|
65 int CNetworkPartitionManager::SetConfiguration( int aBaseNetworkAddress, int aBaseNetworkBitCount, int aSegmentSize ) |
|
66 { |
|
67 int err; |
|
68 int i; |
|
69 |
|
70 // check the params |
|
71 assert( aBaseNetworkBitCount > 0 ); |
|
72 assert( aBaseNetworkBitCount <= 31 ); |
|
73 assert( aSegmentSize > 0 ); |
|
74 |
|
75 // check that the chunk size is a power of two |
|
76 err = IsPowerOfTwo( aSegmentSize ); |
|
77 if( err == 0 ) { |
|
78 return -1; |
|
79 } |
|
80 |
|
81 // calculate the number of bits for each part |
|
82 iBaseNetworkPartBitcount = aBaseNetworkBitCount; |
|
83 iHostPartBitcount = log2( aSegmentSize ); |
|
84 iSegmentPartBitcount = 32 - iBaseNetworkPartBitcount - iHostPartBitcount; |
|
85 if( iSegmentPartBitcount < 1 ) { |
|
86 return -1; |
|
87 } |
|
88 iSegmentCount = 1<<iSegmentPartBitcount; |
|
89 |
|
90 // create the useful netmasks |
|
91 iBaseNetworkNetmask = NetmaskFromBitcount( iBaseNetworkPartBitcount ); |
|
92 iCompleteSegmentNetmask = NetmaskFromBitcount( 32 - iHostPartBitcount ); |
|
93 |
|
94 // save the other info |
|
95 iBaseNetworkAddress = htonl((ntohl(aBaseNetworkAddress) & iBaseNetworkNetmask)); |
|
96 iSegmentSize = aSegmentSize; |
|
97 |
|
98 // now create the list of all available segments |
|
99 err = iAddressAllocator.AddToIntegerPool( 0, iSegmentCount-1 ); |
|
100 if( err == -1 ) { |
|
101 return -1; |
|
102 } |
|
103 |
|
104 // create a mask for the segment bits in position |
|
105 for( iSegmentMask = 0, i = 0; i < iSegmentPartBitcount; i++ ) { |
|
106 iSegmentMask |= 1<<(iHostPartBitcount + i); |
|
107 } |
|
108 |
|
109 |
|
110 // done |
|
111 return 0; |
|
112 } |
|
113 |
|
114 |
|
115 /******************************************************************************* |
|
116 * |
|
117 * PUBLIC METHOD: AllocateNetworkChunk |
|
118 * |
|
119 ******************************************************************************/ |
|
120 int CNetworkPartitionManager::AllocateNetworkSegment( int *aNetmaskBitcount, int *aSegmentSize ) |
|
121 { |
|
122 int segment_number, complete_address, shifted_segment_number; |
|
123 |
|
124 // check |
|
125 assert( aSegmentSize != NULL ); |
|
126 |
|
127 // allocate a segment number |
|
128 segment_number = iAddressAllocator.AllocateInteger(); |
|
129 if( segment_number == -1 ) { |
|
130 return -1; |
|
131 } |
|
132 |
|
133 |
|
134 // make a complete address for the segment number |
|
135 complete_address = ntohl( iBaseNetworkAddress ); |
|
136 shifted_segment_number = (segment_number << iHostPartBitcount) & (iSegmentMask); |
|
137 complete_address |= shifted_segment_number; |
|
138 |
|
139 |
|
140 // set the return values |
|
141 complete_address = htonl( complete_address ); |
|
142 *aNetmaskBitcount = iBaseNetworkPartBitcount + iSegmentPartBitcount; |
|
143 *aSegmentSize = iSegmentSize; |
|
144 assert( (*aNetmaskBitcount + log2(*aSegmentSize)) == 32 ); |
|
145 |
|
146 // done |
|
147 return complete_address; |
|
148 } |
|
149 |
|
150 |
|
151 /******************************************************************************* |
|
152 * |
|
153 * PUBLIC METHOD: FreeNetworkChunk |
|
154 * |
|
155 ******************************************************************************/ |
|
156 int CNetworkPartitionManager::FreeNetworkSegment( int aSegmentBaseAddress ) |
|
157 { |
|
158 int i, err; |
|
159 int segment_number; |
|
160 int lower_bits_segment_mask; |
|
161 |
|
162 // create a mask for the segment bits in the lower part of the work |
|
163 for( lower_bits_segment_mask = 0, i = 0; i < iSegmentPartBitcount; i++ ) { |
|
164 lower_bits_segment_mask |= 1<<i; |
|
165 } |
|
166 |
|
167 // extract the segment number |
|
168 segment_number = ntohl( aSegmentBaseAddress ); |
|
169 segment_number = segment_number >> iHostPartBitcount; |
|
170 segment_number &= lower_bits_segment_mask; |
|
171 |
|
172 // make sure this number is in the expected range |
|
173 assert( (segment_number >= 0) && (segment_number < iSegmentCount) ); |
|
174 |
|
175 // free the segment - this will assert that there are no duplicates |
|
176 err = iAddressAllocator.FreeInteger( segment_number ); |
|
177 assert( err == 0 ); |
|
178 |
|
179 // done |
|
180 return 0; |
|
181 } |
|
182 |
|
183 |
|
184 /**************************************************************************************** |
|
185 * |
|
186 * PRIVATE: log2 |
|
187 * |
|
188 ***************************************************************************************/ |
|
189 int CNetworkPartitionManager::log2( int aValue ) |
|
190 { |
|
191 double base; |
|
192 double value; |
|
193 double simple_result, integer_result; |
|
194 int rv; |
|
195 |
|
196 // if the value is less than zero then we have an error which I want to catch NOW |
|
197 assert( aValue >= 0 ); |
|
198 |
|
199 // if the value is zero then - this is also an error? |
|
200 assert( aValue > 0 ); |
|
201 |
|
202 // calculate the logarithm using doubles (we have to) and convert back to integer |
|
203 base = 2; |
|
204 value = (double)aValue; |
|
205 simple_result = log(value) / log(base); |
|
206 integer_result = ceil(simple_result); |
|
207 rv = (int)integer_result; |
|
208 |
|
209 // since this is not very nice (the need for ceil) I verify the result |
|
210 if( (1<<rv) != aValue ) { |
|
211 fprintf( stderr, "CRITICAL ERROR: log2() made an incorrect calculation - log2(%d) => %d (%g,%g,%g,%g).\n", aValue, rv, base, value, |
|
212 simple_result, integer_result ); |
|
213 } |
|
214 assert( (1<<rv) == aValue ); |
|
215 |
|
216 // done - success |
|
217 return rv; |
|
218 } |
|
219 |
|
220 |
|
221 /**************************************************************************************** |
|
222 * |
|
223 * PRIVATE: IsPowerOfTwo |
|
224 * |
|
225 ***************************************************************************************/ |
|
226 int CNetworkPartitionManager::IsPowerOfTwo( int aValue ) |
|
227 { |
|
228 int bit_count = 0, i; |
|
229 |
|
230 // check how many bits are set |
|
231 for( i = 0; i < 32; i++ ) { |
|
232 if( (aValue & 0x1) != 0 ) { |
|
233 bit_count++; |
|
234 } |
|
235 } |
|
236 |
|
237 // if more than one bit is set then this number is not a power of two |
|
238 return ((bit_count > 1) ? 0 : 1); |
|
239 } |
|
240 |
|
241 |
|
242 /**************************************************************************************** |
|
243 * |
|
244 * PRIVATE: NetmaskFromBitcount |
|
245 * |
|
246 ***************************************************************************************/ |
|
247 int CNetworkPartitionManager::NetmaskFromBitcount( int aBitCount ) |
|
248 { |
|
249 int i, netmask = 0; |
|
250 for( netmask = 0, i = 0; i < aBitCount; i++ ) { |
|
251 netmask |= 1<<(31-i); |
|
252 } |
|
253 return netmask; |
|
254 } |