Example #1
0
/************************************************************************
* DESCRIPTION: RAW send function.
*************************************************************************/
static fnet_int32_t fnet_raw_snd( fnet_socket_if_t *sk, fnet_uint8_t *buf, fnet_size_t len, fnet_flag_t flags, const struct sockaddr *addr)
{
    fnet_netbuf_t           *nb;
    fnet_error_t            error = FNET_ERR_OK;
    const struct sockaddr   *foreign_addr;
    fnet_bool_t             flags_save = FNET_FALSE;

    fnet_isr_lock();

    if(len > sk->send_buffer.count_max)
    {
        error = FNET_ERR_MSGSIZE;   /* Message too long. */
        goto ERROR;
    }

    if(addr)
    {
        foreign_addr = addr;
    }
    else
    {
        foreign_addr = &sk->foreign_addr;
    }

    if((nb = fnet_netbuf_from_buf(buf, len, FNET_FALSE)) == 0)
    {
        error = FNET_ERR_NOMEM;     /* Cannot allocate memory.*/
        goto ERROR;
    }

    if((flags & MSG_DONTROUTE) != 0u) /* Save */
    {
        flags_save = sk->options.so_dontroute;
        sk->options.so_dontroute = FNET_TRUE;
    }

    error = fnet_raw_output(&sk->local_addr, foreign_addr, (fnet_uint8_t)sk->protocol_number, &(sk->options), nb);

    if((flags & MSG_DONTROUTE) != 0u) /* Restore.*/
    {
        sk->options.so_dontroute = flags_save;
    }

    if((error == FNET_ERR_OK) && (sk->options.local_error == FNET_ERR_OK)) /* We get RAW or ICMP error.*/
    {
        fnet_isr_unlock();
        return (fnet_int32_t)(len);
    }

ERROR:
    fnet_socket_set_error(sk, error);
    fnet_isr_unlock();
    return (FNET_ERR);
}
/************************************************************************
* NAME: fnet_free_mem_status
*
* DESCRIPTION: Returns a quantity of free memory (for debug needs)
*              
*************************************************************************/
unsigned long fnet_mempool_free_mem_status( fnet_mempool_desc_t mpool)
{
    struct fnet_mempool * mempool = (struct fnet_mempool *)mpool;
    unsigned long total_size = 0;
    fnet_mempool_unit_header_t *t_mem;

    fnet_isr_lock();

    t_mem = mempool->free_ptr;

    if(t_mem == 0)
        return 0;

    total_size += t_mem->size;
    /* FNET_DEBUG("%d,",t_mem->size*sizeof(FNET_ALLOC_HDR_T));*/

    while(t_mem->ptr != mempool->free_ptr)
    {
        t_mem = t_mem->ptr;
        total_size += t_mem->size;
    /* FNET_DEBUG("%d,",t_mem->size*sizeof(FNET_ALLOC_HDR_T));*/
    }
    /*FNET_DEBUG("");*/


    fnet_isr_unlock();

    return (total_size * mempool->unit_size);
}
/************************************************************************
* NAME: fnet_malloc_max
*
* DESCRIPTION: Returns a maximum size of posible allocated memory chunk.
*              
*************************************************************************/
unsigned long fnet_mempool_malloc_max( fnet_mempool_desc_t mpool )
{
    struct fnet_mempool * mempool = (struct fnet_mempool *)mpool;
    unsigned long max = 0;
    fnet_mempool_unit_header_t *t_mem;

    fnet_isr_lock();

    t_mem = mempool->free_ptr;

    if(t_mem == 0)
        return 0;

    max = t_mem->size;
    /*FNET_DEBUG("%d,", t_mem->size * sizeof(FNET_ALLOC_HDR_T));*/

    while(t_mem->ptr && (t_mem->ptr != mempool->free_ptr))
    {
        t_mem = t_mem->ptr;

        if(t_mem->size > max)
            max = t_mem->size;

        /*FNET_DEBUG("%d,", t_mem->size * sizeof(FNET_ALLOC_HDR_T));*/
    }

    /*FNET_DEBUG("");*/

    fnet_isr_unlock();

    return (max * mempool->unit_size);
}
Example #4
0
/************************************************************************
* NAME: fnet_udp_detach
*
* DESCRIPTION: UDP close function.
*************************************************************************/
static fnet_return_t fnet_udp_detach( fnet_socket_if_t *sk )
{
    fnet_isr_lock();
    fnet_socket_release(&fnet_udp_prot_if.head, sk);
    fnet_isr_unlock();
    return (FNET_OK);
}
Example #5
0
/************************************************************************
* NAME: fnet_raw_detach
*
* DESCRIPTION: RAW close function.
*************************************************************************/
static int fnet_raw_detach( fnet_socket_t *sk )
{
    fnet_isr_lock();
    fnet_socket_release(&fnet_raw_prot_if.head, sk);
    fnet_isr_unlock();
    return (FNET_OK);
}
Example #6
0
/************************************************************************
* NAME: fnet_event_raise
*
* DESCRIPTION: This function raise registerted event. 
*************************************************************************/
void fnet_event_raise( fnet_event_desc_t event_number )
{
    unsigned int        vector_number = (unsigned int)(event_number);
    fnet_isr_entry_t    *isr_temp;

    isr_temp = fnet_isr_table;

    fnet_isr_lock();

    while(isr_temp != 0)
    {
        if(isr_temp->vector_number == vector_number)
        {
            if(isr_temp->handler_top)
                isr_temp->handler_top(isr_temp->cookie);

            if(fnet_locked == 1)
            {
                isr_temp->pended = 0;

                if(isr_temp->handler_bottom)
                    isr_temp->handler_bottom(isr_temp->cookie);
            }
            else
                isr_temp->pended = 1;

            break;
        }

        isr_temp = isr_temp->next;
    }

    fnet_isr_unlock();
}
Example #7
0
/************************************************************************
* NAME: fnet_free_mem_status
*
* DESCRIPTION: Returns a quantity of free memory (for debug needs)
*              
*************************************************************************/
fnet_size_t fnet_mempool_free_mem_status( fnet_mempool_desc_t mpool)
{
    struct fnet_mempool         * mempool = (struct fnet_mempool *)mpool;
    fnet_size_t                 total_size = 0u;
    fnet_mempool_unit_header_t  *t_mem;

    fnet_isr_lock();

    t_mem = mempool->free_ptr;

    if(t_mem)
    {
        total_size += t_mem->size;
        #if 0
         FNET_DEBUG("%d,",t_mem->size*sizeof(FNET_ALLOC_HDR_T));
        #endif

        while(t_mem->ptr != mempool->free_ptr)
        {
            t_mem = t_mem->ptr;
            total_size += t_mem->size;
        #if 0
            FNET_DEBUG("%d,",t_mem->size*sizeof(FNET_ALLOC_HDR_T));*/
        #endif
        }
    }

    fnet_isr_unlock();

    return (total_size * mempool->unit_size);
}
Example #8
0
/************************************************************************
* NAME: fnet_arp_get_mac
*
* DESCRIPTION: Gets MAC address of valid ARP cache entry.
*************************************************************************/
fnet_bool_t fnet_arp_get_mac( fnet_netif_desc_t netif_desc, fnet_ip4_addr_t ip_addr, fnet_mac_addr_t mac_addr)
{
    fnet_netif_t    *netif = (fnet_netif_t *)netif_desc;
    fnet_arp_if_t   *arpif;
    fnet_mac_addr_t *macaddr_p;
    fnet_bool_t     result = FNET_FALSE;

    if(netif)
    {
        arpif = netif->arp_if_ptr;
        if(arpif)
        {
            fnet_isr_lock();

            macaddr_p = fnet_arp_lookup(netif, ip_addr);

            if(macaddr_p)
            {
                if(mac_addr)
                {
                    fnet_memcpy (mac_addr, *macaddr_p, sizeof(fnet_mac_addr_t));
                }
                result = FNET_TRUE;
            }

            fnet_isr_unlock();
        }
    }
    return result;
}
void *fnet_mempool_malloc(fnet_mempool_desc_t mpool, unsigned nbytes )
{
    struct fnet_mempool * mempool = (struct fnet_mempool *)mpool;
    fnet_mempool_unit_header_t *p, *prevp;
    unsigned nunits;

    fnet_isr_lock();

    nunits = ((nbytes + mempool->unit_size - 1) / mempool->unit_size) + 1;

    prevp = mempool->free_ptr;

    for (p = prevp->ptr; ; prevp = p, p = p->ptr)
    {
        if(p->size >= nunits)
        {
            if(p->size == nunits)
            {
                prevp->ptr = p->ptr;
            }
            else
            {
                p->size -= nunits; /* Put to the top. */
                p = (fnet_mempool_unit_header_t *)((unsigned long)p + p->size*mempool->unit_size);
                p->size = nunits;
            }

            mempool->free_ptr = prevp;

            fnet_isr_unlock();

            return (void *)((unsigned long)p + mempool->unit_size);
        }

        if(p == mempool->free_ptr)
        {
            fnet_isr_unlock();
            return 0;
        }
    }

    
    fnet_isr_unlock();
    return 0;
}
Example #10
0
/************************************************************************
* NAME: fnet_udp_connect
*
* DESCRIPTION: UDP connect function.
*************************************************************************/
static fnet_return_t fnet_udp_connect( fnet_socket_if_t *sk, struct sockaddr *foreign_addr)
{
    fnet_isr_lock();

    fnet_memcpy(&sk->foreign_addr, foreign_addr, sizeof(sk->foreign_addr));
    sk->state = SS_CONNECTED;
    fnet_socket_buffer_release(&sk->receive_buffer);

    fnet_isr_unlock();
    return (FNET_OK);
}
Example #11
0
/************************************************************************
* NAME: fnet_raw_connect
*
* DESCRIPTION: RAW connect function.
*************************************************************************/
static int fnet_raw_connect( fnet_socket_t *sk, struct sockaddr *foreign_addr)
{
    fnet_isr_lock();
    
    sk->foreign_addr = *foreign_addr;
    sk->local_addr.sa_port = 0;
    sk->foreign_addr.sa_port = 0;
    sk->state = SS_CONNECTED;
    fnet_socket_buffer_release(&sk->receive_buffer);
    fnet_isr_unlock();
    return (FNET_OK);
}
/************************************************************************
* NAME: fnet_netif_drain
*
* DESCRIPTION: This function calls "drain" functions of all currently 
*              installed network interfaces. 
*************************************************************************/
void fnet_netif_drain( void )
{
    fnet_netif_t *net_if_ptr;

    fnet_isr_lock();

    for (net_if_ptr = fnet_netif_list; net_if_ptr; net_if_ptr = net_if_ptr->next)
    {
        if(net_if_ptr->api->drain)
            net_if_ptr->api->drain(net_if_ptr);
    }

    fnet_isr_unlock();
}
Example #13
0
void fnet_loop_output_ip4(fnet_netif_t *netif, fnet_ip4_addr_t dest_ip_addr, fnet_netbuf_t* nb)
{
    FNET_COMP_UNUSED_ARG(dest_ip_addr);
    
    fnet_isr_lock();
    
    /* MTU check */
    if (nb->total_length <= netif->mtu)
        fnet_ip_input(netif, nb);
    else
        fnet_netbuf_free_chain(nb);
        
    fnet_isr_unlock();
}
Example #14
0
/************************************************************************
* NAME: fnet_arp_send_request
*
* DESCRIPTION: Public function. Sends ARP request.
*************************************************************************/
void fnet_arp_send_request( fnet_netif_desc_t netif_desc, fnet_ip4_addr_t ip_addr )
{
    fnet_netif_t    *netif = (fnet_netif_t *)netif_desc;
    fnet_arp_if_t   *arpif;

    if(netif)
    {
        arpif = netif->arp_if_ptr;
        if(arpif)
        {
            fnet_isr_lock();

            fnet_arp_request(netif, ip_addr);

            fnet_isr_unlock();
        }
    }
}
Example #15
0
/************************************************************************
* DESCRIPTION:  RAW shutdown function.
*************************************************************************/
static fnet_return_t fnet_raw_shutdown( fnet_socket_if_t *sk, fnet_sd_flags_t how )
{
    fnet_isr_lock();

    if((how & SD_READ) != 0u)
    {
        sk->receive_buffer.is_shutdown = FNET_TRUE;
        fnet_socket_buffer_release(&sk->receive_buffer);
    }

    if((how & SD_WRITE) != 0u)
    {
        sk->send_buffer.is_shutdown = FNET_TRUE;
    }

    fnet_isr_unlock();

    return (FNET_OK);
}
Example #16
0
/************************************************************************
* NAME: fnet_raw_shutdown
*
* DESCRIPTION:  RAW shutdown function.
*************************************************************************/
static int fnet_raw_shutdown( fnet_socket_t *sk, int how )
{
    fnet_isr_lock();

    if((how & SD_READ) != 0)
    {
        sk->receive_buffer.is_shutdown = 1;
        fnet_socket_buffer_release(&sk->receive_buffer);
    }

    if((how & SD_WRITE) != 0)
    {
        sk->send_buffer.is_shutdown = 1;
    }

    fnet_isr_unlock();

    return (FNET_OK);
}
Example #17
0
/************************************************************************
* NAME: fnet_arp_resolve
*
* DESCRIPTION: This function finds the first unused or the oldest
*              ARP table entry and makes a new entry
*              to prepare it for an ARP reply.
*************************************************************************/
void fnet_arp_resolve(fnet_netif_t *netif, fnet_ip4_addr_t ipaddr, fnet_netbuf_t *nb)
{
    fnet_arp_if_t       *arpif = netif->arp_if_ptr;
    fnet_index_t        i;
    fnet_arp_entry_t    *entry;

    fnet_isr_lock();
    for (i = 0U; i < FNET_CFG_ARP_TABLE_SIZE; i++)
    {
        if (ipaddr == arpif->arp_table[i].prot_addr)
        {
            break;
        }
    }

    /* If no unused entry is found, create it. */
    if (i == FNET_CFG_ARP_TABLE_SIZE)
    {
        entry = fnet_arp_add_entry(netif, ipaddr, fnet_eth_null_addr);
    }
    else
    {
        entry = &arpif->arp_table[i];
    }

    if (entry->hold)
    {
        fnet_netbuf_free_chain(entry->hold);
        entry->hold = NULL;
    }

    if ((i == FNET_CFG_ARP_TABLE_SIZE) || ((entry->hold) && (((fnet_timer_ticks() - entry->hold_time) * FNET_TIMER_PERIOD_MS) > 1000U)) || (!entry->hold))
    {
        entry->hold_time = fnet_timer_ticks();
        entry->hold = nb;
        fnet_arp_request(netif, ipaddr);
    }
    else
    {
        entry->hold = nb;
    }
    fnet_isr_unlock();
}
Example #18
0
/************************************************************************
* NAME: fnet_arp_drain
*
* DESCRIPTION: This function tries to free not critical parts
*              of memory used by ARP protocol.
*************************************************************************/
void fnet_arp_drain(fnet_netif_t *netif)
{
    fnet_index_t    i;
    fnet_arp_if_t   *arpif = netif->arp_if_ptr;

    fnet_isr_lock();

    /* ARP table drain.*/
    for (i = 0U; i < FNET_CFG_ARP_TABLE_SIZE; i++)
    {
        if (arpif->arp_table[i].hold)
        {
            fnet_netbuf_free_chain(arpif->arp_table[i].hold);
            arpif->arp_table[i].hold      = 0;
            arpif->arp_table[i].hold_time = 0U;
        }
    }

    fnet_isr_unlock();
}
/************************************************************************
* NAME: fnet_arp_drain
*
* DESCRIPTION: This function tries to free not critical parts 
*              of memory used by ARP protocol.
*************************************************************************/
void fnet_arp_drain(fnet_netif_t *netif)
{
   int i;
   fnet_arp_if_t * arpif = &(((fnet_eth_if_t *)(netif->if_ptr))->arp_if); //PFI
     
   fnet_isr_lock();
   
   /* ARP table drain.*/
   for(i=0;i<FNET_ARP_TABLE_SIZE;i++)
   {
      if(arpif->arp_table[i].hold)
      {
         fnet_netbuf_free_chain(arpif->arp_table[i].hold);
         arpif->arp_table[i].hold=0;
         arpif->arp_table[i].hold_time=0;
      }
   }
  
   fnet_isr_unlock();
}
Example #20
0
/************************************************************************
* NAME: fnet_event_raise
*
* DESCRIPTION: This function raise registerted event.
*************************************************************************/
void fnet_event_raise(fnet_event_desc_t event_number)
{
    fnet_uint32_t vector_number = (fnet_uint32_t)(event_number);
    fnet_isr_entry_t *isr_temp;

    isr_temp = fnet_isr_table;

    fnet_isr_lock();

    while (isr_temp != 0)
    {
        if (isr_temp->vector_number == vector_number)
        {
            if (isr_temp->handler_top)
            {
                isr_temp->handler_top(isr_temp->cookie);
            }

            if (fnet_locked == 1u)
            {
                isr_temp->pended = FNET_FALSE;

                if (isr_temp->handler_bottom)
                {
                    isr_temp->handler_bottom(isr_temp->cookie);
                }
            }
            else
            {
                isr_temp->pended = FNET_TRUE;
            }

            break;
        }

        isr_temp = isr_temp->next;
    }

    fnet_isr_unlock();
}
    /*FNET_DEBUG("");*/

    fnet_isr_unlock();

    return (max * mempool->unit_size);
}

#if 0 /* For Debug needs.*/
int fnet_mempool_check( fnet_mempool_desc_t mpool )
{

    volatile struct fnet_mempool * mempool = (struct fnet_mempool *)mpool;
    volatile fnet_mempool_unit_header_t *t_mem;
    int i = 0;

    fnet_isr_lock();

    t_mem = mempool->free_ptr;

    if(t_mem == 0)
        return 0;

    while(t_mem->ptr != mempool->free_ptr)
    {
        i++;
        
        if((i>100)||(t_mem->ptr == 0)||(t_mem->ptr == (void *)0xFFFFFFFF))
        {
            fnet_println("!!!MEMPOOL CRASH!!!");
            return FNET_ERR;
        }
        
        if( (((unsigned long)t_mem) < (unsigned long)t_mem->ptr) && ((t_mem->size + (unsigned long)t_mem) > (unsigned long)t_mem->ptr))
        {
            fnet_println("!!!MEMPOOL FREE CRASH!!!");
            return FNET_ERR;
        }
        
        t_mem = t_mem->ptr;

    }


    fnet_isr_unlock();
   

    return FNET_OK;
}
Example #22
0
/************************************************************************
* NAME: fnet_malloc_max
*
* DESCRIPTION: Returns a maximum size of posible allocated memory chunk.
*              
*************************************************************************/
fnet_size_t fnet_mempool_malloc_max( fnet_mempool_desc_t mpool )
{
    struct fnet_mempool         *mempool = (struct fnet_mempool *)mpool;
    fnet_size_t                 max = 0u;
    fnet_mempool_unit_header_t  *t_mem;

    fnet_isr_lock();

    t_mem = mempool->free_ptr;

    if(t_mem)
    {

        max = t_mem->size;
    #if 0
        FNET_DEBUG("%d,", t_mem->size * sizeof(FNET_ALLOC_HDR_T));
    #endif

        while((t_mem->ptr) && (t_mem->ptr != mempool->free_ptr))
        {
            t_mem = t_mem->ptr;

            if(t_mem->size > max)
            {
                max = t_mem->size;
            }    
        #if 0
            FNET_DEBUG("%d,", t_mem->size * sizeof(FNET_ALLOC_HDR_T));
        #endif
        }
    #if 0
        FNET_DEBUG("");
    #endif
    }

    fnet_isr_unlock();

    return (max * mempool->unit_size);
}
Example #23
0
/************************************************************************
* NAME: fnet_malloc_max
*
* DESCRIPTION: Returns a maximum size of posible allocated memory chunk.
*              
*************************************************************************/
fnet_size_t fnet_mempool_malloc_max( fnet_mempool_desc_t mpool )
{
    struct fnet_mempool         *mempool = (struct fnet_mempool *)mpool;
    fnet_size_t                 max = 0u;
    fnet_mempool_unit_header_t  *t_mem;

    fnet_isr_lock();

    t_mem = mempool->free_ptr;

    if(t_mem)
    {

        max = t_mem->size;
    #if 0
        FNET_DEBUG("%d,", t_mem->size * sizeof(FNET_ALLOC_HDR_T));
    #endif

        while((t_mem->ptr) && (t_mem->ptr != mempool->free_ptr))
        {
            t_mem = t_mem->ptr;

            if(t_mem->size > max)
            {
                max = t_mem->size;
            }    
        #if 0
            FNET_DEBUG("%d,", t_mem->size * sizeof(FNET_ALLOC_HDR_T));
        #endif
        }
    #if 0
        FNET_DEBUG("");
    #endif
    }

    fnet_isr_unlock();

    return (max * mempool->unit_size);
}

#if 0 /* For Debug needs.*/
fnet_return_t fnet_mempool_check( fnet_mempool_desc_t mpool )
{

    volatile struct fnet_mempool * mempool = (struct fnet_mempool *)mpool;
    volatile fnet_mempool_unit_header_t *t_mem;
    fnet_index_t i = 0u;

    fnet_isr_lock();

    t_mem = mempool->free_ptr;

    if(t_mem)
    {

        while(t_mem->ptr != mempool->free_ptr)
        {
            i++;
            
            if((i>100u)||(t_mem->ptr == 0)||(t_mem->ptr == (void *)0xFFFFFFFF))
            {
                fnet_println("!!!MEMPOOL CRASH!!!");
                return FNET_ERR;
            }
            
            if( (((fnet_uint32_t)t_mem) < (fnet_uint32_t)t_mem->ptr) && ((t_mem->size + (fnet_uint32_t)t_mem) > (fnet_uint32_t)t_mem->ptr))
            {
                fnet_println("!!!MEMPOOL FREE CRASH!!!");
                return FNET_ERR;
            }
            
            t_mem = t_mem->ptr;

        }
    }


    fnet_isr_unlock();
    return FNET_OK;
}
Example #24
0
/************************************************************************
* NAME: fnet_arp_get_entry
*
* DESCRIPTION: This function Retrieves ARP cache entry of
*             the specified network interface.
*************************************************************************/
fnet_bool_t fnet_arp_get_entry ( fnet_netif_desc_t netif_desc, fnet_index_t n, fnet_arp_entry_info_t *entry_info )
{
    fnet_netif_t    *netif = (fnet_netif_t *)netif_desc;
    fnet_bool_t     result = FNET_FALSE;
    fnet_arp_if_t   *arpif;
    fnet_index_t    i;

    if(netif && entry_info)
    {
        arpif = netif->arp_if_ptr;

        if(arpif)
        {
            for(i = 0u; i < FNET_CFG_ARP_TABLE_SIZE; i++)
            {
                /* Skip NOT_USED prefixes. */
                if(arpif->arp_table[i].prot_addr != 0U)
                {
                    if(n == 0u)
                    {
                        fnet_isr_lock();
                        /* Fill entry.*/
                        entry_info->ip_addr = arpif->arp_table[i].prot_addr;
                        fnet_memcpy(entry_info->mac_addr, arpif->arp_table[i].hard_addr, sizeof(fnet_mac_addr_t));
                        fnet_isr_unlock();

                        result = FNET_TRUE;
                        break;
                    }
                    n--;
                }
            }
        }
    }
    return result;
}
Example #25
0
/************************************************************************
* NAME: fnet_udp_snd
*
* DESCRIPTION: UDP send function.
*************************************************************************/
static fnet_int32_t fnet_udp_snd( fnet_socket_if_t *sk, fnet_uint8_t *buf, fnet_size_t len, fnet_flag_t flags, const struct sockaddr *addr)
{
    fnet_netbuf_t           *nb;
    fnet_error_t            error = FNET_ERR_OK;
    const struct sockaddr   *foreign_addr;
    fnet_bool_t             flags_save = FNET_FALSE;

    fnet_isr_lock();

#if FNET_CFG_TCP_URGENT
    if(flags & MSG_OOB)
    {
        error = FNET_ERR_OPNOTSUPP; /* Operation not supported.*/
        goto ERROR;
    }
#endif /* FNET_CFG_TCP_URGENT */

    if(len > sk->send_buffer.count_max)
    {
        error = FNET_ERR_MSGSIZE;   /* Message too long. */
        goto ERROR;
    }

    if(addr)
    {
        foreign_addr = addr;
    }
    else
    {
        foreign_addr = &sk->foreign_addr;
    }

    if((nb = fnet_netbuf_from_buf(buf, len, FNET_FALSE)) == 0)
    {
        error = FNET_ERR_NOMEM;     /* Cannot allocate memory.*/
        goto ERROR;
    }

    if(sk->local_addr.sa_port == 0u)
    {
        sk->local_addr.sa_port = fnet_socket_get_uniqueport(sk->protocol_interface->head, &sk->local_addr); /* Get ephemeral port.*/
    }

    if((flags & MSG_DONTROUTE) != 0u) /* Save */
    {
        flags_save = sk->options.so_dontroute; 
        sk->options.so_dontroute = FNET_TRUE;
    }

    error = fnet_udp_output(&sk->local_addr, foreign_addr, &(sk->options), nb);

    if((flags & MSG_DONTROUTE) != 0u) /* Restore.*/
    {
        sk->options.so_dontroute = flags_save; 
    }

    if((error == FNET_ERR_OK) && (sk->options.local_error == FNET_ERR_OK)) /* We get UDP or ICMP error.*/
    {
        fnet_isr_unlock();
        return (fnet_int32_t)(len);
    }

ERROR:
    fnet_socket_set_error(sk, error);
    fnet_isr_unlock();
    return (FNET_ERR);
}
/************************************************************************
* NAME: fnet_netif_init
*
* DESCRIPTION: This function installs & inits a network interface.
*************************************************************************/
int fnet_netif_init( fnet_netif_t *netif, unsigned char *hw_addr, unsigned int hw_addr_size )
{
    int result = FNET_OK;
    
    if(netif && netif->api)
    {
        fnet_os_mutex_lock();   
        
        fnet_isr_lock();
        
        netif->next = fnet_netif_list;

        if(netif->next != 0)
            netif->next->prev = netif;

        netif->prev = 0;
        fnet_netif_list = netif;
        
        fnet_netif_assign_scope_id( netif ); /* Asign Scope ID.*/
        
        netif->features = FNET_NETIF_FEATURE_NONE;


        /* Interface HW initialization.*/
        if(netif->api->init && ((result = netif->api->init(netif)) == FNET_OK))
        {
            #if FNET_CFG_IGMP && FNET_CFG_IP4       
                /**************************************************************
                 * RFC1112 7.2
                 *   To support IGMP, every level 2 host must
                 *   join the "all-hosts" group (address 224.0.0.1) on each network
                 *   interface at initialization time and must remain a member for as long
                 *   as the host is active.
                 *
                 * NOTE:(224.0.0.1) membership is never reported by IGMP.
                 **************************************************************/
                 /* Join HW interface. */
                fnet_netif_join_ip4_multicast ( netif, FNET_IP4_ADDR_INIT(224, 0, 0, 1) );
            #endif  /* FNET_CFG_IGMP */
            
            /* Set HW Address.*/    
            fnet_netif_set_hw_addr(netif, hw_addr, hw_addr_size);
                
            /* Interface-Type specific initialisation. */ 
            switch(netif->api->type)
            {
            #if (FNET_CFG_CPU_ETH0 ||FNET_CFG_CPU_ETH1)
                case (FNET_NETIF_TYPE_ETHERNET):
                    result = fnet_eth_init(netif);
                    break;
            #endif /* FNET_CFG_ETH */
                default:
                    break;
            
            }
        }

        fnet_printf("ETH - Initialization: %s, ID:%d\n", netif->name, netif->scope_id);
        fnet_printf("	 - IP: %x, GW: %x\n", netif->ip4_addr.address, netif->ip4_addr.gateway);
        fnet_printf("	 - MASK: %x, DHCP?: %d\n", netif->ip4_addr.netmask, netif->ip4_addr.is_automatic);
        fnet_printf("	 - MTU: %d\n", netif->mtu);
        fnet_printf("	 - MTU: %x\n", netif->if_ptr);



        fnet_isr_unlock();
        
        fnet_os_mutex_unlock();
    }
    
    return result;
}
/************************************************************************
* NAME: fnet_netif_init_all
*
* DESCRIPTION: Initialization of all supported interfaces.
*************************************************************************/
int fnet_netif_init_all( void )
{
    int result = FNET_OK;

    fnet_isr_lock();

    fnet_netif_list = fnet_netif_default = 0;
    
    /***********************************
     * Initialize IFs.
     ************************************/
#if FNET_CFG_CPU_ETH0  
    /* Initialise eth0 interface.*/
    {
    	fnet_mac_addr_t macaddr = {0x00,0x11,0x22,0x33,0x44,0x55};
   
        /* Set MAC Address.*/
	    fnet_str_to_mac(FNET_CFG_CPU_ETH0_MAC_ADDR, macaddr);
        result = fnet_netif_init(FNET_ETH0_IF, macaddr, sizeof(fnet_mac_addr_t));
        if(result == FNET_ERR)
            goto INIT_ERR;
    }
#endif
#if FNET_CFG_CPU_ETH1 
    /* Initialise eth0 interface.*/
    {
    	fnet_mac_addr_t macaddr = {0x00,0x11,0x22,0x33,0x33,0x55};
   
        /* Set MAC Address.*/
	    fnet_str_to_mac(FNET_CFG_CPU_ETH1_MAC_ADDR, macaddr);
        result = fnet_netif_init(FNET_ETH1_IF, macaddr, sizeof(fnet_mac_addr_t));
        if(result == FNET_ERR)
            goto INIT_ERR;
    }    
#endif    
#if FNET_CFG_LOOPBACK
    /* Initialise Loop-back interface.*/
    result = fnet_netif_init(FNET_LOOP_IF);
    if(result == FNET_ERR)
        goto INIT_ERR;
#endif /* FNET_CFG_LOOPBACK */

    /***********************************
     * Set default parameters.
     ************************************/
    fnet_netif_set_default(FNET_CFG_DEFAULT_IF); /* Default interface.*/

/* Set address parameters of the Ethernet interface.*/
#if FNET_CFG_IP4
    #if FNET_CFG_CPU_ETH0
    {
        fnet_netif_set_ip4_addr(FNET_ETH0_IF, FNET_CFG_ETH0_IP4_ADDR);
        fnet_netif_set_ip4_subnet_mask(FNET_ETH0_IF, (unsigned long)FNET_CFG_ETH0_IP4_MASK);
        fnet_netif_set_ip4_gateway(FNET_ETH0_IF, FNET_CFG_ETH0_IP4_GW);
    #if FNET_CFG_DNS    
        fnet_netif_set_ip4_dns(FNET_ETH0_IF, FNET_CFG_ETH0_IP4_DNS);
    #endif
    }
    #endif /* FNET_CFG_CPU_ETH0 */
    #if FNET_CFG_CPU_ETH1
    {
        fnet_netif_set_ip4_addr(FNET_ETH1_IF, FNET_CFG_ETH1_IP4_ADDR);
        fnet_netif_set_ip4_subnet_mask(FNET_ETH1_IF, (unsigned long)FNET_CFG_ETH1_IP4_MASK);
        fnet_netif_set_ip4_gateway(FNET_ETH1_IF, FNET_CFG_ETH1_IP4_GW);
    #if FNET_CFG_DNS    
        fnet_netif_set_ip4_dns(FNET_ETH1_IF, FNET_CFG_ETH1_IP4_DNS);
    #endif
    }
    #endif /* FNET_CFG_CPU_ETH0 */    
#endif /* FNET_CFG_ETH */

/* Set address parameters of the Loopback interface.*/
#if FNET_CFG_LOOPBACK && FNET_CFG_IP4
    fnet_netif_set_ip4_addr(FNET_LOOP_IF, FNET_CFG_LOOPBACK_IP4_ADDR);
#endif /* FNET_CFG_LOOPBACK */

INIT_ERR:
    fnet_isr_unlock();
    return result;
}
/************************************************************************
* NAME: fnet_malloc
*
* DESCRIPTION: Allocates memory in the memory pool.
*              
*************************************************************************/
#if FNET_MEMPOOL_MALLOC_BEST_CHOICE /* Choose the best. */
void *fnet_mempool_malloc(fnet_mempool_desc_t mpool, unsigned nbytes )
{
    struct fnet_mempool * mempool = (struct fnet_mempool *)mpool;
    fnet_mempool_unit_header_t *p, *prevp;
    fnet_mempool_unit_header_t *best_p =0;
    fnet_mempool_unit_header_t *best_p_prev =0;
    unsigned nunits;
    void * res;

    fnet_isr_lock();

    nunits = ((nbytes + mempool->unit_size - 1) / mempool->unit_size) + 1;

    prevp = mempool->free_ptr;
    
    best_p_prev = prevp;
    
    /* Find the best one. */
    for(p = prevp->ptr; ; prevp = p, p = p->ptr)
    {
        if( (p->size >= nunits) && ( (best_p==0) || ((best_p)&&(best_p->size > p->size)) ) )
        {
            best_p_prev = prevp;
            best_p = p;  
        }
        
        if(p == mempool->free_ptr)
            break; /* End of list is reached. */
    }

    if(best_p)
    {
        if(best_p->size == nunits)
        {
            best_p_prev->ptr = best_p->ptr;
        }
        else
        {
            best_p->size -= nunits; /* Put to the top. */
            best_p = (fnet_mempool_unit_header_t *)((unsigned long)best_p + best_p->size*mempool->unit_size);
            best_p->size = nunits;
        }

        mempool->free_ptr = best_p_prev;
        res = (void *)((unsigned long)best_p + mempool->unit_size);
#if 0 /* Clear mem.*/
        fnet_memset_zero( res, (nunits-1)* mempool->unit_size ); 
#endif  
    }
    else
    {
		/* Break here to detect allocation errors */
        res = 0;
    }

#if FNET_DEBUG_MEMPOOL_CHECK    
    if(res)
    {
        int i;
        
        for(i=DEBUG_last_free_addr_num; i<DEBUG_ALLOCATED_ADDR_MAX; i++)
        {
            if(DEBUG_allocated_addr[i].address == 0)
            {
                /* Save allocated address */
                DEBUG_allocated_addr[i].address = res;
                DEBUG_allocated_addr[i].size = nunits;
                
                break;
            }
        
        }
        if( i==DEBUG_ALLOCATED_ADDR_MAX)
            fnet_println ("Addr_table_overload!!!");
    }
#endif
    
    fnet_isr_unlock();
    
    return res;
}
/************************************************************************
* NAME: fnet_free
*
* DESCRIPTION: Frees memory in the mempool.
*              
*************************************************************************/
void fnet_mempool_free( fnet_mempool_desc_t mpool, void *ap )
{
    struct fnet_mempool * mempool = (struct fnet_mempool *)mpool;
    
    fnet_mempool_unit_header_t *bp, *p;

    if(ap != 0)
    {
        fnet_isr_lock();
      
        /* Block pointer = allocated memory block addr - allocation unit size.*/
        bp = (fnet_mempool_unit_header_t *)((unsigned long)ap - mempool->unit_size); /* Point to block header. */ 


#if FNET_DEBUG_MEMPOOL_CHECK
    {
        int i;
        
        for(i=0; i<DEBUG_ALLOCATED_ADDR_MAX; i++)
        {
            if(DEBUG_allocated_addr[i].address == ap)
            {
                if(DEBUG_allocated_addr[i].size == bp->size)
                {
                    DEBUG_allocated_addr[i].address = 0; // Clear;
                    DEBUG_last_free_addr_num = i-50;
                    if (DEBUG_last_free_addr_num < 0)
                         DEBUG_last_free_addr_num = 0;
                    break;
                }
                else
                {
                    fnet_println ("Wrong free size!!!!!!!!");
                    break;
                }
            }
        
        }
        if( i==DEBUG_ALLOCATED_ADDR_MAX)
            fnet_println ("This addr never allocated before!!!!!!!!");
    }
#endif

        for (p = mempool->free_ptr; !((bp > p) && (bp < p->ptr)); p = p->ptr)
        {
            
#if FNET_DEBUG_MEMPOOL_CHECK /* Debug Check. */
            if( (p <= bp) && ((unsigned long)bp <= ((unsigned long)p + p->size)) )/* The block is already free */ 
            {
                fnet_println("Already Free UPS");
                fnet_isr_unlock();
                return; 
            }
#endif            
                
            
            if((p >= p->ptr) && ((bp > p) || (bp < p->ptr)))
            {
                break; /* Freed block at start or end of arena. */
            }
        }

        if((fnet_mempool_unit_header_t *)((unsigned long)bp + bp->size*mempool->unit_size) == p->ptr)
        {
            bp->size += p->ptr->size;
            bp->ptr = p->ptr->ptr;
        }
        else
        {
            bp->ptr = p->ptr;
        }

        if((fnet_mempool_unit_header_t *)((unsigned long)p + p->size*mempool->unit_size) == bp)
        {
            p->size += bp->size;
            p->ptr = bp->ptr;
        }
        else
        {
            p->ptr = bp;
        }
        
        mempool->free_ptr = p;
 
        fnet_isr_unlock();
    }

}