Changes in uspace/lib/c/generic/net/packet.c [5fe7692:49bd793b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/net/packet.c
r5fe7692 r49bd793b 36 36 */ 37 37 38 #include <assert.h> 38 39 #include <malloc.h> 39 40 #include <mem.h> … … 44 45 #include <sys/mman.h> 45 46 46 #include <adt/ generic_field.h>47 #include <adt/hash_table.h> 47 48 #include <net/packet.h> 48 49 #include <net/packet_header.h> 49 50 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); 51 /** Packet hash table size. */ 52 #define PACKET_HASH_TABLE_SIZE 128 71 53 72 54 /** Packet map global data. */ … … 75 57 fibril_rwlock_t lock; 76 58 /** Packet map. */ 77 gpm_t packet_map; 59 hash_table_t packet_map; 60 /** Packet map operations */ 61 hash_table_operations_t operations; 78 62 } pm_globals; 79 63 80 GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t); 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 81 104 82 105 /** Initializes the packet map. … … 87 110 int pm_init(void) 88 111 { 89 int rc ;112 int rc = EOK; 90 113 91 114 fibril_rwlock_initialize(&pm_globals.lock); 92 115 93 116 fibril_rwlock_write_lock(&pm_globals.lock); 94 rc = gpm_initialize(&pm_globals.packet_map); 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 95 126 fibril_rwlock_write_unlock(&pm_globals.lock); 96 127 … … 100 131 /** Finds the packet mapping. 101 132 * 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. 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 * 105 138 */ 106 139 packet_t *pm_find(packet_id_t packet_id) 107 140 { 108 packet_map_t *map;109 packet_t *packet;110 111 141 if (!packet_id) 112 142 return NULL; 113 143 114 144 fibril_rwlock_read_lock(&pm_globals.lock); 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)]; 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 125 157 fibril_rwlock_read_unlock(&pm_globals.lock); 126 158 return packet; … … 129 161 /** Adds the packet mapping. 130 162 * 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. 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 * 136 169 */ 137 170 int pm_add(packet_t *packet) 138 171 { 139 packet_map_t *map;140 int rc;141 142 172 if (!packet_is_valid(packet)) 143 173 return EINVAL; 144 174 145 175 fibril_rwlock_write_lock(&pm_globals.lock); 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)); 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; 167 181 } 168 169 (*map) [PACKET_MAP_INDEX(packet->packet_id)] = packet; 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 170 188 fibril_rwlock_write_unlock(&pm_globals.lock); 189 171 190 return EOK; 172 191 } 173 192 174 /** Releases the packet map. */ 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 202 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. */ 175 211 void pm_destroy(void) 176 212 { 177 int count;178 int index;179 packet_map_t *map;180 packet_t *packet;181 182 213 fibril_rwlock_write_lock(&pm_globals.lock); 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 */ 214 hash_table_apply(&pm_globals.packet_map, pm_free_wrapper, NULL); 215 hash_table_destroy(&pm_globals.packet_map); 216 /* Leave locked */ 194 217 } 195 218 … … 199 222 * The packet is inserted right before the packets of the same order value. 200 223 * 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. 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 * 210 235 */ 211 236 int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric) 212 237 { 213 packet_t *item; 214 215 if (!first || !packet_is_valid(packet)) 238 if ((!first) || (!packet_is_valid(packet))) 216 239 return EINVAL; 217 240 218 241 pq_set_order(packet, order, metric); 219 242 if (packet_is_valid(*first)) { 220 item = * first; 243 packet_t *cur = *first; 244 221 245 do { 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; 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 228 253 return EOK; 229 254 } 230 255 } else { 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; 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; 237 264 else 238 265 *first = packet; 266 239 267 return EOK; 240 268 } 241 } while (packet_is_valid( item));269 } while (packet_is_valid(cur)); 242 270 } 271 243 272 *first = packet; 244 273 return EOK; … … 312 341 313 342 next = pm_find(packet->next); 314 if (next) {343 if (next) 315 344 next->previous = packet->previous; 316 previous = pm_find(next->previous); 317 if (previous) 318 previous->next = next->packet_id; 319 } 345 346 previous = pm_find(packet->previous); 347 if (previous) 348 previous->next = packet->next ; 349 320 350 packet->previous = 0; 321 351 packet->next = 0;
Note:
See TracChangeset
for help on using the changeset viewer.