Changes in uspace/lib/c/generic/net/packet.c [49bd793b:5fe7692] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/net/packet.c
r49bd793b r5fe7692 36 36 */ 37 37 38 #include <assert.h>39 38 #include <malloc.h> 40 39 #include <mem.h> … … 45 44 #include <sys/mman.h> 46 45 47 #include <adt/ hash_table.h>46 #include <adt/generic_field.h> 48 47 #include <net/packet.h> 49 48 #include <net/packet_header.h> 50 49 51 /** Packet hash table size. */ 52 #define PACKET_HASH_TABLE_SIZE 128 50 /** Packet map page size. */ 51 #define PACKET_MAP_SIZE 100 52 53 /** Returns the packet map page index. 54 * @param[in] packet_id The packet identifier. 55 */ 56 #define PACKET_MAP_PAGE(packet_id) (((packet_id) - 1) / PACKET_MAP_SIZE) 57 58 /** Returns the packet index in the corresponding packet map page. 59 * @param[in] packet_id The packet identifier. 60 */ 61 #define PACKET_MAP_INDEX(packet_id) (((packet_id) - 1) % PACKET_MAP_SIZE) 62 63 /** Type definition of the packet map page. */ 64 typedef packet_t *packet_map_t[PACKET_MAP_SIZE]; 65 66 /** Packet map. 67 * Maps packet identifiers to the packet references. 68 * @see generic_field.h 69 */ 70 GENERIC_FIELD_DECLARE(gpm, packet_map_t); 53 71 54 72 /** Packet map global data. */ … … 57 75 fibril_rwlock_t lock; 58 76 /** Packet map. */ 59 hash_table_t packet_map; 60 /** Packet map operations */ 61 hash_table_operations_t operations; 77 gpm_t packet_map; 62 78 } pm_globals; 63 79 64 typedef struct { 65 link_t link; 66 packet_t *packet; 67 } pm_entry_t; 68 69 /** 70 * Hash function for the packet mapping hash table 71 */ 72 static hash_index_t pm_hash(unsigned long key[]) 73 { 74 return (hash_index_t) key[0] % PACKET_HASH_TABLE_SIZE; 75 } 76 77 /** 78 * Key compare function for the packet mapping hash table 79 */ 80 static int pm_compare(unsigned long key[], hash_count_t keys, link_t *link) 81 { 82 pm_entry_t *entry = list_get_instance(link, pm_entry_t, link); 83 return entry->packet->packet_id == key[0]; 84 } 85 86 /** 87 * Remove callback for the packet mapping hash table 88 */ 89 static void pm_remove_callback(link_t *link) 90 { 91 pm_entry_t *entry = list_get_instance(link, pm_entry_t, link); 92 free(entry); 93 } 94 95 /** 96 * Wrapper used when destroying the whole table 97 */ 98 static void pm_free_wrapper(link_t *link, void *ignored) 99 { 100 pm_entry_t *entry = list_get_instance(link, pm_entry_t, link); 101 free(entry); 102 } 103 80 GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t); 104 81 105 82 /** Initializes the packet map. … … 110 87 int pm_init(void) 111 88 { 112 int rc = EOK;89 int rc; 113 90 114 91 fibril_rwlock_initialize(&pm_globals.lock); 115 92 116 93 fibril_rwlock_write_lock(&pm_globals.lock); 117 118 pm_globals.operations.hash = pm_hash; 119 pm_globals.operations.compare = pm_compare; 120 pm_globals.operations.remove_callback = pm_remove_callback; 121 122 if (!hash_table_create(&pm_globals.packet_map, PACKET_HASH_TABLE_SIZE, 1, 123 &pm_globals.operations)) 124 rc = ENOMEM; 125 94 rc = gpm_initialize(&pm_globals.packet_map); 126 95 fibril_rwlock_write_unlock(&pm_globals.lock); 127 96 … … 131 100 /** Finds the packet mapping. 132 101 * 133 * @param[in] packet_id Packet identifier to be found. 134 * 135 * @return The found packet reference. 136 * @return NULL if the mapping does not exist. 137 * 102 * @param[in] packet_id The packet identifier to be found. 103 * @return The found packet reference. 104 * @return NULL if the mapping does not exist. 138 105 */ 139 106 packet_t *pm_find(packet_id_t packet_id) 140 107 { 108 packet_map_t *map; 109 packet_t *packet; 110 141 111 if (!packet_id) 142 112 return NULL; 143 113 144 114 fibril_rwlock_read_lock(&pm_globals.lock); 145 146 unsigned long key = packet_id; 147 link_t *link = hash_table_find(&pm_globals.packet_map, &key); 148 149 packet_t *packet; 150 if (link != NULL) { 151 pm_entry_t *entry = 152 hash_table_get_instance(link, pm_entry_t, link); 153 packet = entry->packet; 154 } else 155 packet = NULL; 156 115 if (packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)) { 116 fibril_rwlock_read_unlock(&pm_globals.lock); 117 return NULL; 118 } 119 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet_id)); 120 if (!map) { 121 fibril_rwlock_read_unlock(&pm_globals.lock); 122 return NULL; 123 } 124 packet = (*map) [PACKET_MAP_INDEX(packet_id)]; 157 125 fibril_rwlock_read_unlock(&pm_globals.lock); 158 126 return packet; … … 161 129 /** Adds the packet mapping. 162 130 * 163 * @param[in] packet Packet to be remembered. 164 * 165 * @return EOK on success. 166 * @return EINVAL if the packet is not valid. 167 * @return ENOMEM if there is not enough memory left. 168 * 131 * @param[in] packet The packet to be remembered. 132 * @return EOK on success. 133 * @return EINVAL if the packet is not valid. 134 * @return EINVAL if the packet map is not initialized. 135 * @return ENOMEM if there is not enough memory left. 169 136 */ 170 137 int pm_add(packet_t *packet) 171 138 { 139 packet_map_t *map; 140 int rc; 141 172 142 if (!packet_is_valid(packet)) 173 143 return EINVAL; 174 144 175 145 fibril_rwlock_write_lock(&pm_globals.lock); 176 177 pm_entry_t *entry = malloc(sizeof(pm_entry_t)); 178 if (entry == NULL) { 179 fibril_rwlock_write_unlock(&pm_globals.lock); 180 return ENOMEM; 181 } 182 183 entry->packet = packet; 184 185 unsigned long key = packet->packet_id; 186 hash_table_insert(&pm_globals.packet_map, &key, &entry->link); 187 146 147 if (PACKET_MAP_PAGE(packet->packet_id) < 148 gpm_count(&pm_globals.packet_map)) { 149 map = gpm_get_index(&pm_globals.packet_map, 150 PACKET_MAP_PAGE(packet->packet_id)); 151 } else { 152 do { 153 map = (packet_map_t *) malloc(sizeof(packet_map_t)); 154 if (!map) { 155 fibril_rwlock_write_unlock(&pm_globals.lock); 156 return ENOMEM; 157 } 158 bzero(map, sizeof(packet_map_t)); 159 rc = gpm_add(&pm_globals.packet_map, map); 160 if (rc < 0) { 161 fibril_rwlock_write_unlock(&pm_globals.lock); 162 free(map); 163 return rc; 164 } 165 } while (PACKET_MAP_PAGE(packet->packet_id) >= 166 gpm_count(&pm_globals.packet_map)); 167 } 168 169 (*map) [PACKET_MAP_INDEX(packet->packet_id)] = packet; 188 170 fibril_rwlock_write_unlock(&pm_globals.lock); 189 190 171 return EOK; 191 172 } 192 173 193 /** Remove the packet mapping 194 * 195 * @param[in] packet The packet to be removed 196 * 197 */ 198 void pm_remove(packet_t *packet) 199 { 200 assert(packet_is_valid(packet)); 201 174 /** Releases the packet map. */ 175 void pm_destroy(void) 176 { 177 int count; 178 int index; 179 packet_map_t *map; 180 packet_t *packet; 181 202 182 fibril_rwlock_write_lock(&pm_globals.lock); 203 204 unsigned long key = packet->packet_id; 205 hash_table_remove(&pm_globals.packet_map, &key, 1); 206 207 fibril_rwlock_write_unlock(&pm_globals.lock); 208 } 209 210 /** Release the packet map. */ 211 void pm_destroy(void) 212 { 213 fibril_rwlock_write_lock(&pm_globals.lock); 214 hash_table_apply(&pm_globals.packet_map, pm_free_wrapper, NULL); 215 hash_table_destroy(&pm_globals.packet_map); 216 /* Leave locked */ 183 count = gpm_count(&pm_globals.packet_map); 184 while (count > 0) { 185 map = gpm_get_index(&pm_globals.packet_map, count - 1); 186 for (index = PACKET_MAP_SIZE - 1; index >= 0; --index) { 187 packet = (*map)[index]; 188 if (packet_is_valid(packet)) 189 munmap(packet, packet->length); 190 } 191 } 192 gpm_destroy(&pm_globals.packet_map, free); 193 /* leave locked */ 217 194 } 218 195 … … 222 199 * The packet is inserted right before the packets of the same order value. 223 200 * 224 * @param[in,out] first First packet of the queue. Sets the first 225 * packet of the queue. The original first packet 226 * may be shifted by the new packet. 227 * @param[in] packet Packet to be added. 228 * @param[in] order Packet order value. 229 * @param[in] metric Metric value of the packet. 230 * 231 * @return EOK on success. 232 * @return EINVAL if the first parameter is NULL. 233 * @return EINVAL if the packet is not valid. 234 * 201 * @param[in,out] first The first packet of the queue. Sets the first packet of 202 * the queue. The original first packet may be shifted by 203 * the new packet. 204 * @param[in] packet The packet to be added. 205 * @param[in] order The packet order value. 206 * @param[in] metric The metric value of the packet. 207 * @return EOK on success. 208 * @return EINVAL if the first parameter is NULL. 209 * @return EINVAL if the packet is not valid. 235 210 */ 236 211 int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric) 237 212 { 238 if ((!first) || (!packet_is_valid(packet))) 213 packet_t *item; 214 215 if (!first || !packet_is_valid(packet)) 239 216 return EINVAL; 240 217 241 218 pq_set_order(packet, order, metric); 242 219 if (packet_is_valid(*first)) { 243 packet_t *cur = *first; 244 220 item = * first; 245 221 do { 246 if (cur->order < order) { 247 if (cur->next) 248 cur = pm_find(cur->next); 249 else { 250 cur->next = packet->packet_id; 251 packet->previous = cur->packet_id; 252 222 if (item->order < order) { 223 if (item->next) { 224 item = pm_find(item->next); 225 } else { 226 item->next = packet->packet_id; 227 packet->previous = item->packet_id; 253 228 return EOK; 254 229 } 255 230 } else { 256 packet->previous = cur->previous; 257 packet->next = cur->packet_id; 258 259 cur->previous = packet->packet_id; 260 cur = pm_find(packet->previous); 261 262 if (cur) 263 cur->next = packet->packet_id; 231 packet->previous = item->previous; 232 packet->next = item->packet_id; 233 item->previous = packet->packet_id; 234 item = pm_find(packet->previous); 235 if (item) 236 item->next = packet->packet_id; 264 237 else 265 238 *first = packet; 266 267 239 return EOK; 268 240 } 269 } while (packet_is_valid(cur)); 270 } 271 241 } while (packet_is_valid(item)); 242 } 272 243 *first = packet; 273 244 return EOK; … … 341 312 342 313 next = pm_find(packet->next); 343 if (next) 314 if (next) { 344 315 next->previous = packet->previous; 345 346 previous = pm_find(packet->previous); 347 if (previous) 348 previous->next = packet->next ; 349 316 previous = pm_find(next->previous); 317 if (previous) 318 previous->next = next->packet_id; 319 } 350 320 packet->previous = 0; 351 321 packet->next = 0;
Note:
See TracChangeset
for help on using the changeset viewer.