Changeset 609243f4 in mainline for uspace/lib/c/generic/net/packet.c
- Timestamp:
- 2011-10-07T15:46:01Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e2c50e1
- Parents:
- f51b1d3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/net/packet.c
rf51b1d3 r609243f4 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 141 packet_t *packet; 110 111 142 if (!packet_id) 112 143 return NULL; 113 144 114 145 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)]; 146 link_t *link = 147 hash_table_find(&pm_globals.packet_map, &packet_id); 148 if (link != NULL) { 149 pm_entry_t *entry = 150 hash_table_get_instance(link, pm_entry_t, link); 151 packet = entry->packet; 152 } else 153 packet = NULL; 154 125 155 fibril_rwlock_read_unlock(&pm_globals.lock); 126 156 return packet; … … 129 159 /** Adds the packet mapping. 130 160 * 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. 161 * @param[in] packet Packet to be remembered. 162 * 163 * @return EOK on success. 164 * @return EINVAL if the packet is not valid. 165 * @return ENOMEM if there is not enough memory left. 166 * 136 167 */ 137 168 int pm_add(packet_t *packet) 138 169 { 139 packet_map_t *map;140 int rc;141 142 170 if (!packet_is_valid(packet)) 143 171 return EINVAL; 144 172 145 173 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)); 174 pm_entry_t *entry = malloc(sizeof (pm_entry_t)); 175 if (entry == NULL) { 176 fibril_rwlock_write_unlock(&pm_globals.lock); 177 return ENOMEM; 167 178 } 168 169 (*map) [PACKET_MAP_INDEX(packet->packet_id)] = packet; 179 180 entry->packet = packet; 181 hash_table_insert(&pm_globals.packet_map, &packet->packet_id, 182 &entry->link); 170 183 fibril_rwlock_write_unlock(&pm_globals.lock); 171 184 return EOK; 172 185 } 173 186 174 /** Releases the packet map. */ 187 /** Remove the packet mapping 188 * 189 * @param[in] packet The packet to be removed 190 * 191 */ 192 void pm_remove(packet_t *packet) 193 { 194 assert(packet_is_valid(packet)); 195 196 fibril_rwlock_write_lock(&pm_globals.lock); 197 hash_table_remove(&pm_globals.packet_map, &packet->packet_id, 1); 198 fibril_rwlock_write_unlock(&pm_globals.lock); 199 } 200 201 /** Release the packet map. */ 175 202 void pm_destroy(void) 176 203 { 177 int count;178 int index;179 packet_map_t *map;180 packet_t *packet;181 182 204 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 */ 205 hash_table_apply(&pm_globals.packet_map, pm_free_wrapper, NULL); 206 hash_table_destroy(&pm_globals.packet_map); 207 /* Leave locked */ 194 208 } 195 209 … … 199 213 * The packet is inserted right before the packets of the same order value. 200 214 * 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. 215 * @param[in,out] first First packet of the queue. Sets the first 216 * packet of the queue. The original first packet 217 * may be shifted by the new packet. 218 * @param[in] packet Packet to be added. 219 * @param[in] order Packet order value. 220 * @param[in] metric Metric value of the packet. 221 * 222 * @return EOK on success. 223 * @return EINVAL if the first parameter is NULL. 224 * @return EINVAL if the packet is not valid. 225 * 210 226 */ 211 227 int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric) 212 228 { 213 packet_t *item; 214 215 if (!first || !packet_is_valid(packet)) 229 if ((!first) || (!packet_is_valid(packet))) 216 230 return EINVAL; 217 231 218 232 pq_set_order(packet, order, metric); 219 233 if (packet_is_valid(*first)) { 220 item = * first; 234 packet_t *cur = *first; 235 221 236 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; 237 if (cur->order < order) { 238 if (cur->next) 239 cur = pm_find(cur->next); 240 else { 241 cur->next = packet->packet_id; 242 packet->previous = cur->packet_id; 243 228 244 return EOK; 229 245 } 230 246 } 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; 247 packet->previous = cur->previous; 248 packet->next = cur->packet_id; 249 250 cur->previous = packet->packet_id; 251 cur = pm_find(packet->previous); 252 253 if (cur) 254 cur->next = packet->packet_id; 237 255 else 238 256 *first = packet; 257 239 258 return EOK; 240 259 } 241 } while (packet_is_valid( item));260 } while (packet_is_valid(cur)); 242 261 } 262 243 263 *first = packet; 244 264 return EOK; … … 312 332 313 333 next = pm_find(packet->next); 314 if (next) {334 if (next) 315 335 next->previous = packet->previous; 316 previous = pm_find(next->previous); 317 if (previous) 318 previous->next = next->packet_id; 319 } 336 337 previous = pm_find(packet->previous); 338 if (previous) 339 previous->next = packet->next ; 340 320 341 packet->previous = 0; 321 342 packet->next = 0;
Note:
See TracChangeset
for help on using the changeset viewer.