Changeset d7ff048 in mainline for uspace/lib/c/generic/net/packet.c


Ignore:
Timestamp:
2011-10-08T13:08:53Z (13 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bf08ff0
Parents:
8367d1d (diff), 80099c19 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

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

    r8367d1d rd7ff048  
    3636 */
    3737
     38#include <assert.h>
    3839#include <malloc.h>
    3940#include <mem.h>
     
    4445#include <sys/mman.h>
    4546
    46 #include <adt/generic_field.h>
     47#include <adt/hash_table.h>
    4748#include <net/packet.h>
    4849#include <net/packet_header.h>
    4950
    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
    7153
    7254/** Packet map global data. */
     
    7557        fibril_rwlock_t lock;
    7658        /** Packet map. */
    77         gpm_t packet_map;
     59        hash_table_t packet_map;
     60        /** Packet map operations */
     61        hash_table_operations_t operations;
    7862} pm_globals;
    7963
    80 GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
     64typedef 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 */
     72static 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 */
     80static 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 */
     89static 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 */
     98static 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
    81104
    82105/** Initializes the packet map.
     
    87110int pm_init(void)
    88111{
    89         int rc;
     112        int rc = EOK;
    90113
    91114        fibril_rwlock_initialize(&pm_globals.lock);
    92115       
    93116        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       
    95126        fibril_rwlock_write_unlock(&pm_globals.lock);
    96127       
     
    100131/** Finds the packet mapping.
    101132 *
    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 *
    105138 */
    106139packet_t *pm_find(packet_id_t packet_id)
    107140{
    108         packet_map_t *map;
    109         packet_t *packet;
    110 
    111141        if (!packet_id)
    112142                return NULL;
    113 
     143       
    114144        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       
    125157        fibril_rwlock_read_unlock(&pm_globals.lock);
    126158        return packet;
     
    129161/** Adds the packet mapping.
    130162 *
    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 *
    136169 */
    137170int pm_add(packet_t *packet)
    138171{
    139         packet_map_t *map;
    140         int rc;
    141 
    142172        if (!packet_is_valid(packet))
    143173                return EINVAL;
    144 
     174       
    145175        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;
    167181        }
    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       
    170188        fibril_rwlock_write_unlock(&pm_globals.lock);
     189       
    171190        return EOK;
    172191}
    173192
    174 /** Releases the packet map. */
     193/** Remove the packet mapping
     194 *
     195 * @param[in] packet The packet to be removed
     196 *
     197 */
     198void 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. */
    175211void pm_destroy(void)
    176212{
    177         int count;
    178         int index;
    179         packet_map_t *map;
    180         packet_t *packet;
    181 
    182213        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 */
    194217}
    195218
     
    199222 * The packet is inserted right before the packets of the same order value.
    200223 *
    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 *
    210235 */
    211236int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric)
    212237{
    213         packet_t *item;
    214 
    215         if (!first || !packet_is_valid(packet))
     238        if ((!first) || (!packet_is_valid(packet)))
    216239                return EINVAL;
    217 
     240       
    218241        pq_set_order(packet, order, metric);
    219242        if (packet_is_valid(*first)) {
    220                 item = * first;
     243                packet_t *cur = *first;
     244               
    221245                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                                       
    228253                                        return EOK;
    229254                                }
    230255                        } 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;
    237264                                else
    238265                                        *first = packet;
     266                               
    239267                                return EOK;
    240268                        }
    241                 } while (packet_is_valid(item));
     269                } while (packet_is_valid(cur));
    242270        }
     271       
    243272        *first = packet;
    244273        return EOK;
     
    312341
    313342        next = pm_find(packet->next);
    314         if (next) {
     343        if (next)
    315344                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       
    320350        packet->previous = 0;
    321351        packet->next = 0;
Note: See TracChangeset for help on using the changeset viewer.