Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/net/packet.c

    r49bd793b r5fe7692  
    3636 */
    3737
    38 #include <assert.h>
    3938#include <malloc.h>
    4039#include <mem.h>
     
    4544#include <sys/mman.h>
    4645
    47 #include <adt/hash_table.h>
     46#include <adt/generic_field.h>
    4847#include <net/packet.h>
    4948#include <net/packet_header.h>
    5049
    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. */
     64typedef 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 */
     70GENERIC_FIELD_DECLARE(gpm, packet_map_t);
    5371
    5472/** Packet map global data. */
     
    5775        fibril_rwlock_t lock;
    5876        /** Packet map. */
    59         hash_table_t packet_map;
    60         /** Packet map operations */
    61         hash_table_operations_t operations;
     77        gpm_t packet_map;
    6278} pm_globals;
    6379
    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 
     80GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
    10481
    10582/** Initializes the packet map.
     
    11087int pm_init(void)
    11188{
    112         int rc = EOK;
     89        int rc;
    11390
    11491        fibril_rwlock_initialize(&pm_globals.lock);
    11592       
    11693        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);
    12695        fibril_rwlock_write_unlock(&pm_globals.lock);
    12796       
     
    131100/** Finds the packet mapping.
    132101 *
    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.
    138105 */
    139106packet_t *pm_find(packet_id_t packet_id)
    140107{
     108        packet_map_t *map;
     109        packet_t *packet;
     110
    141111        if (!packet_id)
    142112                return NULL;
    143        
     113
    144114        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)];
    157125        fibril_rwlock_read_unlock(&pm_globals.lock);
    158126        return packet;
     
    161129/** Adds the packet mapping.
    162130 *
    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.
    169136 */
    170137int pm_add(packet_t *packet)
    171138{
     139        packet_map_t *map;
     140        int rc;
     141
    172142        if (!packet_is_valid(packet))
    173143                return EINVAL;
    174        
     144
    175145        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;
    188170        fibril_rwlock_write_unlock(&pm_globals.lock);
    189        
    190171        return EOK;
    191172}
    192173
    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. */
     175void pm_destroy(void)
     176{
     177        int count;
     178        int index;
     179        packet_map_t *map;
     180        packet_t *packet;
     181
    202182        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 */
    217194}
    218195
     
    222199 * The packet is inserted right before the packets of the same order value.
    223200 *
    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.
    235210 */
    236211int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric)
    237212{
    238         if ((!first) || (!packet_is_valid(packet)))
     213        packet_t *item;
     214
     215        if (!first || !packet_is_valid(packet))
    239216                return EINVAL;
    240        
     217
    241218        pq_set_order(packet, order, metric);
    242219        if (packet_is_valid(*first)) {
    243                 packet_t *cur = *first;
    244                
     220                item = * first;
    245221                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;
    253228                                        return EOK;
    254229                                }
    255230                        } 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;
    264237                                else
    265238                                        *first = packet;
    266                                
    267239                                return EOK;
    268240                        }
    269                 } while (packet_is_valid(cur));
    270         }
    271        
     241                } while (packet_is_valid(item));
     242        }
    272243        *first = packet;
    273244        return EOK;
     
    341312
    342313        next = pm_find(packet->next);
    343         if (next)
     314        if (next) {
    344315                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        }
    350320        packet->previous = 0;
    351321        packet->next = 0;
Note: See TracChangeset for help on using the changeset viewer.