Files
2026-07-30 11:19:44 +05:30

1941 lines
54 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: iplite.c,v $ $Revision: 1.149.10.1 $
* $Source: /home/interpeak/CVSRoot/iplite2/src/iplite.c,v $
* $Author: xjiang1 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#define IPLITE_C
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "iplite_config.h"
#ifdef IP_PORT_INTEGRITY
#include "ipcom_ipcom2bsd.h"
#endif
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_netif.h>
#include <ipcom_os.h>
#include <ipcom_shell.h>
#include <ipcom_sock2.h>
#include <ipcom_syslog.h>
#ifdef IPLITE_ONE_FILE
#ifdef IP_GLOBAL
#undef IP_GLOBAL
#endif
#define IP_GLOBAL IP_STATIC
#endif
#include "iplite_h.h"
#include "iplite_loopback.h"
#include "iplite_netif.h"
#include "iplite_sock.h"
#ifdef IP_PORT_INTEGRITY
#include "ipcom_ipcom2bsd.h"
#endif
#ifdef IPCOM_USE_TCP
#include "iplite_tcp.h"
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* pkt->data size need to be IPLITE_PKT_ALIGNMENT larger for rounding up
* to correct &pkt->data[pkt->start] alignment on incoming buffers.
*/
#ifdef IPCOM_PKT_ALIGNMENT
#define IPLITE_PKT_ALIGNMENT IPCOM_PKT_ALIGNMENT
#else
#define IPLITE_PKT_ALIGNMENT 64
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
IP_EXTERN IP_CONST Iplite_conf_pkt_pool *iplite_conf_pkt_pool;
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_PUBLIC Ip_err iplite_start(void);
IP_PUBLIC Ip_err iplite_create(void);
IP_PUBLIC const char *iplite_version(void);
#ifdef IP_DEBUG
IP_STATIC void iplite_pkt_remove_from_alloc_list(Ipcom_pkt *pkt);
#endif
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
*===========================================================================
* Global data
*===========================================================================
*/
IP_PUBLIC Ip_size_t ipcom_port_pkt_hdr_extra_size = 0;
IP_PUBLIC Iplite_data iplite;
IP_PUBLIC Ip_u32 iplite_flags = 0;
/*
****************************************************************************
* 9 IPLITE_ONE_FILE
****************************************************************************
*/
#ifdef IPLITE_ONE_FILE
#include "iplite_frag.c"
#include "iplite_loopback.c"
#include "iplite_netif.c"
#include "iplite_raw.c"
#include "iplite_sock.c"
#include "iplite_sockpkt.c"
#include "iplite_udp.c"
#ifndef IPLITE_MEM_OPT
#include "iplite_ctrl.c"
#include "iplite_ioctl.c"
#include "iplite_sockopt.c"
#endif /* IPLITE_MEM_OPT */
#ifdef IPCOM_USE_INET
#include "iplite_ip4.c"
#endif
#ifdef IPCOM_USE_INET6
#include "iplite_ip6.c"
#endif
#ifdef IPCOM_USE_ETHERNET
#include "iplite_eth.c"
#endif
#ifdef IPPPP
#include "iplite_ppp.c"
#endif
#endif /* IPLITE_ONE_FILE */
#if defined(IP_PORT_VXWORKS) && defined(IPCOM_USE_SOCK_COMPAT)
IP_GLOBAL Ip_err ipcom_windnet_socklib_init(void);
#endif
/*
****************************************************************************
* 10 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iplite_pkt_drain
*===========================================================================
* Context: Soft interrupt
* Description: Frees all packets that is in reassembly queues and
* out-of-order TCP queues.
* Parameters:
* Returns:
*
*/
IP_STATIC void
iplite_pkt_drain(void *unused)
{
Ipcom_pkt *pkt;
Ipcom_pkt *tmp_pkt;
Ipcom_pkt **pkt_lists[2];
int n = 0;
int i;
(void) unused;
#ifdef IPCOM_USE_INET
pkt_lists[n] = &iplite.ip4.reassembly_list;
n++;
#endif
#ifdef IPCOM_USE_INET6
pkt_lists[n] = &iplite.ip6.reassembly_list;
n++;
#endif
IPLITE_CODE_ISLOCKED_ASSERT();
for (i = 0; i < n; i++)
{
pkt = *pkt_lists[i];
if (pkt)
iplite_timeout_cancel(IPLITE_PKT_GET_TMO(pkt));
while (pkt != IP_NULL)
{
tmp_pkt = pkt->next;
ipcom_pkt_free(pkt);
pkt = tmp_pkt;
}
*pkt_lists[i] = IP_NULL;
}
#ifdef IPCOM_USE_TCP
iplite_tcp_pkt_drain();
#endif
}
/*
*===========================================================================
* iplite_issue_pktavail_cb
*===========================================================================
* Context: Soft interrupt
* Description: Sends a IP_SOEVENT_CB_PKTAVAIL event to all sockets that
* want to know when more packets are available in the pool
* Parameters:
* Returns:
*
*/
IP_STATIC void
iplite_issue_pktavail_cb(void *unused)
{
int i;
Iplite_socket *sock;
(void) unused;
IP_BIT_CLR(iplite_flags, IPLITE_FLAG_PKTAVAIL_CB_PENDING);
for (i = IPLITE_SOCKET_STARTFD; i < IPLITE_CONF_MAX_SOCKETS; i++)
{
sock = iplite.sockets[i];
if (sock == IP_NULL
|| sock->ipcom.event_cb == IP_NULL
|| IP_BIT_ISFALSE(sock->flags, IPLITE_SOCKET_FLAG_PKTAVAIL_CB_PENDING))
continue;
IP_BIT_CLR(sock->flags, IPLITE_SOCKET_FLAG_PKTAVAIL_CB_PENDING);
(void)sock->ipcom.event_cb((Ipcom_socket *) sock, IP_NULL, IP_SOEVENT_CB_PKTAVAIL);
}
}
/*
*===========================================================================
* iplite_timeout_pq_cmp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
iplite_timeout_pq_cmp(const Iplite_timeout *tmo1, const Iplite_timeout *tmo2)
{
if (tmo1->msec == tmo2->msec)
return 0;
if (IPCOM_IS_LT(tmo1->msec, tmo2->msec))
return 1;
return -1;
}
/*
*===========================================================================
* iplite_timeout_pq_store_index
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
iplite_timeout_pq_store_index(Iplite_timeout *tmo, int pq_index)
{
tmo->pq_index = pq_index;
}
/*
*===========================================================================
* iplite_timeout_duration_until_next
*===========================================================================
* Description: Returns the duration, in milliseconds, until the next timeout
* event occurs.
* Parameters:
* Returns: The duration or -1 if no timeout is pending.
*
*/
IP_STATIC Ip_s32
iplite_timeout_duration_until_next(void)
{
Iplite_timeout *tmo;
tmo = ipcom_pqueue_get(iplite.timeouts, 1);
if (tmo == IP_NULL)
/* Wait forever */
return -1;
if (IPCOM_IS_GEQ(iplite.msec_now, tmo->msec))
/* Timeout event is pending now */
return 0;
return (Ip_s32) (tmo->msec - iplite.msec_now);
}
/*
*===========================================================================
* iplite_process_pending_timeouts
*===========================================================================
* Description: Calls the handler for all events that has timed out.
* Parameters:
* Returns:
*
*/
IP_STATIC void
iplite_process_pending_timeouts(void)
{
Iplite_timeout *tmo;
void *cookie;
Iplite_timeout_handler handler;
while ((tmo = ipcom_pqueue_get(iplite.timeouts, 1))
&& IPCOM_IS_GEQ(iplite.msec_now, tmo->msec))
{
cookie = tmo->cookie;
handler = tmo->handler;
iplite_timeout_cancel(tmo);
handler(cookie);
}
}
/*
*===========================================================================
* iplite_soft_interrupt
*===========================================================================
* Description: Runs all pending soft interrupt(s).
* Parameters:
* Returns:
*
*/
IP_STATIC void
iplite_soft_interrupt(void)
{
Iplite_soft_irq *soft_irq_head;
Iplite_soft_irq *soft_irq;
Ip_u32 msr;
IPLITE_CODE_ISLOCKED_ASSERT();
msr = ipcom_interrupt_disable();
soft_irq_head = iplite.soft_irq_head;
iplite.soft_irq_head = IP_NULL;
iplite.soft_irq_tail = IP_NULL;
iplite.soft_irq_pending = IP_FALSE;
ipcom_interrupt_enable(msr);
while (soft_irq_head)
{
soft_irq = soft_irq_head;
soft_irq_head = soft_irq->next;
soft_irq->pending = IP_FALSE;
soft_irq->handler(soft_irq->cookie);
}
}
/*
*===========================================================================
* iplite_tick
*===========================================================================
* Description: Calls iplite_tick() iplite_conf_ticks_per_sec times per second.
* Parameters:
* Returns:
*
*/
IP_STATIC void
iplite_tick(void)
{
Iplite_netif *netif;
int i;
Ip_u32 delta_sec;
ip_assert(IP_BIT_ISSET(iplite_flags, IPLITE_FLAG_CREATED));
delta_sec = (iplite.msec_now - iplite.msec_last) / 1000;
iplite.msec_last += delta_sec * 1000;
iplite.seconds += delta_sec;
iplite.ticks += 1;
/* Network interface callbacks */
for (i = 2; i < IPLITE_CONF_MAX_NETIF; i++)
if (IP_NULL != (netif = iplite.netifs[i]) && netif->link_tick != IP_NULL)
{
netif->link_tick(netif);
IPLITE_CODE_ISLOCKED_ASSERT();
}
IPLITE_CODE_ISLOCKED_ASSERT();
#ifdef IPCOM_USE_INET6
iplite_ip6_tick();
#endif
(void)iplite_timeout_schedule(1000 / IPLITE_CONF_TICKS_PER_SEC,
(Iplite_timeout_handler) iplite_tick,
IP_NULL,
IP_NULL);
}
/*
*===========================================================================
* iplite_pkt_input
*===========================================================================
* Context: Any non-interrupt context.
* Description: Inputs a packet to the stack.
* Parameters: netif - The interface the packet was received on.
* pkt - The received packet. pkt->start is the offset to the
* the link layer header.
* Returns:
*
*/
IP_STATIC void
iplite_pkt_input(struct Ipcom_netif_struct *ipcomif, Ipcom_pkt *pkt)
{
Iplite_netif *netif = (Iplite_netif *)ipcomif;
ip_assert(((Ip_u32)pkt->start & 0x1) == 0);
ip_assert(IP_BIT_ISSET(iplite_flags, IPLITE_FLAG_CREATED));
IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_INPUT);
IPLITE_DEBUG_LINE(iplite_pkt_check(pkt));
if (netif == IP_NULL)
netif = iplite_if_indextonetif(pkt->ifindex);
if (netif == IP_NULL || IP_BIT_ISFALSE(netif->ipcom.flags, IP_IFF_RUNNING))
{
ipcom_pkt_free(pkt);
return;
}
#if !defined(IP_PORT_ATI) && !defined(IP_PORT_VXWORKS) && !defined(IP_PORT_MQX)
ip_assert(pkt->ifindex == IPLITE_IF_LOOPBACK_INDEX
|| (pkt->start >= (ipcom_conf_max_link_hdr_size - netif->ipcom.link_hdr_size)));
#endif
pkt->next = IP_NULL;
pkt->ifindex = netif->ipcom.ifindex;
IPLITE_STATS(pkt_input++);
#ifdef IPCOM_USE_PACKET
/* Give a copy of packet to all matching packet sockets. */
if (iplite.num_packet_sock > 0)
{
if (iplite_packet_input(netif, pkt) == IP_FALSE)
return;
}
#endif
netif->link_input(netif, pkt);
}
/*
*===========================================================================
* ipcom_stackd_init
*===========================================================================
* Description: Init IPLITE deamon process.
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_s32
ipcom_stackd_init(void)
{
iplite.daemon_pid = ipcom_getpid();
iplite.msec_now = iplite_msec_now();
iplite.msec_last = (iplite.msec_now / 1000) * 1000;
(void)iplite_timeout_schedule(1000 / IPLITE_CONF_TICKS_PER_SEC,
(Iplite_timeout_handler) iplite_tick,
IP_NULL,
IP_NULL);
return ipcom_stackd_event(IP_FALSE);
}
/*
*===========================================================================
* ipcom_stackd_event
*===========================================================================
* Description: Run IPLITE deamon process.
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_s32
ipcom_stackd_event(Ip_bool is_timeout)
{
Ip_s32 msec_sleep_duration;
Ipcom_pkt *pkt;
IPLITE_CODE_LOCK();
/* Do this only once since it is expensive on some OSes */
iplite.msec_now = iplite_msec_now();
if (is_timeout == IP_FALSE)
iplite.daemon_posted = IP_FALSE;
if (iplite.soft_irq_pending)
iplite_soft_interrupt();
iplite_process_pending_timeouts();
/********** Input check ***********/
while (iplite.inq_num)
{
Ipcom_pkt *inq;
Ip_u32 msr;
/* Unhook all pending packet from the input queue */
msr = ipcom_interrupt_disable();
inq = iplite.inq_head;
iplite.inq_head = IP_NULL;
iplite.inq_num = 0;
ipcom_interrupt_enable(msr);
ip_assert(inq);
do {
/* Handle any pending soft interrupt first */
if (iplite.soft_irq_pending)
iplite_soft_interrupt();
pkt = inq;
inq = pkt->next;
iplite_pkt_input(IP_NULL, pkt);
} while (inq);
}
if (iplite.soft_irq_pending)
iplite_soft_interrupt();
msec_sleep_duration = iplite_timeout_duration_until_next();
IPLITE_CODE_UNLOCK();
return msec_sleep_duration;
}
/*
*===========================================================================
* iplited
*===========================================================================
* Description: Inputs packes to IPLITE.
* Parameters:
* Returns:
*
*/
#ifdef IPLITE_STACKD_INTERNAL
IP_STATIC
IPCOM_PROCESS(iplited)
{
Ip_s32 msec_sleep_duration;
Ip_bool is_timeout;
ipcom_proc_init();
/* Must be allocated here since our OSE implementation of
ipcom_block_xxx() uses the PID of the blocked process.
This is the process that will block on iplite.daemon_block */
if (ipcom_block_create(&iplite.daemon_block) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "Failed to create the inqueue block");
goto fail;
}
msec_sleep_duration = ipcom_stackd_init();
for (;;)
{
/* Wait for next timeout or event and process it */
is_timeout = (ipcom_block_wait(iplite.daemon_block, msec_sleep_duration)
== IPCOM_ERR_TIMEOUT);
msec_sleep_duration = ipcom_stackd_event(is_timeout);
}
fail:
ipcom_proc_exit();
}
#endif
/*
*===========================================================================
* ipcom_pkt_input
*===========================================================================
* Context: Any non-interrupt context.
* Description: Inputs a packet to the stack.
* Parameters: netif - The interface the packet was received on.
* pkt - The received packet. pkt->start is the offset to the
* the link layer header.
* Returns:
*
*/
IP_FASTTEXT IP_PUBLIC void
ipcom_pkt_input(struct Ipcom_netif_struct *ipcomif, Ipcom_pkt *pkt)
{
IPLITE_CODE_LOCK();
iplite_pkt_input(ipcomif, pkt);
IPLITE_CODE_UNLOCK();
}
/*
****************************************************************************
* 11 GLOBAL FUNCTIONS
****************************************************************************
*/
#ifdef IPLITE_DEBUG
/*
*===========================================================================
* iplite_pkt_remove_from_alloc_list
*===========================================================================
* Description: Removes the packet from the list of allocated packets.
* Parameters: pkt - The packet to remove.
* Returns:
*
*/
IP_STATIC void
iplite_pkt_remove_from_alloc_list(Ipcom_pkt *pkt)
{
Ipcom_pkt **pkt_it;
#ifdef IP_ASSERT
Ip_bool found = IP_FALSE;;
#endif
for (pkt_it = &iplite.allocated_pkt_list; *pkt_it != IP_NULL; pkt_it = &(*pkt_it)->next_alloc)
{
if (*pkt_it == pkt)
{
/* Unhook the packet */
*pkt_it = pkt->next_alloc;
pkt->next_alloc = IP_NULL;
#ifdef IP_ASSERT
found = IP_TRUE;
#endif
break;
}
}
pkt->next_alloc = (void *)-1;
ip_assert(found);
}
/*
*===========================================================================
* iplite_pkt_add_to_alloc_list
*===========================================================================
* Description: Adds a packet to the list of allocated packets.
* Parameters: pkt - The packet to add.
* Returns:
*
*/
IP_GLOBAL void
iplite_pkt_add_to_alloc_list(Ipcom_pkt *pkt)
{
Ip_u32 isr;
isr = ipcom_interrupt_disable();
#ifdef IP_ASSERT
{
int pool_index;
Ipcom_pkt *tpkt;
/* Check that 'pkt' is not already in allocated list. */
for (tpkt = iplite.allocated_pkt_list; tpkt != IP_NULL; tpkt = tpkt->next_alloc)
ip_assert(pkt != tpkt);
/* Check that 'pkt' is not in free list. */
for (pool_index = 0; pool_index < iplite.pkt_pool_elem; pool_index++)
for(tpkt = iplite.pkt_pool[pool_index].free_list; tpkt != IP_NULL; tpkt = tpkt->next)
ip_assert(pkt != tpkt);
}
#endif /* IP_ASSERT */
pkt->next_alloc = iplite.allocated_pkt_list;
iplite.allocated_pkt_list = pkt;
ipcom_interrupt_enable(isr);
}
#endif /* IPLITE_DEBUG */
/*
*===========================================================================
* iplite_schedule_soft_interrupt
*===========================================================================
* Context: Any context.
* Description: Schedules a function to be called as soon as possible.
* The function will be called from a non-interrupt context
* with interrupt enabled and the IPLITE code lock taken.
* Parameters: soft_irq - Pointer to a soft interrupt structure, the handler
* must free the memory if it is dynamically allocated.
* irq_is_enabled - Must be set to IP_TRUE if this function
* is called with interrupts enabled.
* Returns:
*
*/
IP_GLOBAL void
iplite_schedule_soft_interrupt(Iplite_soft_irq *soft_irq, Ip_bool irq_is_enabled)
{
Ip_u32 msr = 0;
if (irq_is_enabled)
msr = ipcom_interrupt_disable();
if (iplite.soft_irq_tail)
iplite.soft_irq_tail->next = soft_irq;
else
iplite.soft_irq_head = soft_irq;
iplite.soft_irq_tail = soft_irq;
iplite.soft_irq_pending = IP_TRUE;
soft_irq->pending = IP_TRUE;
soft_irq->next = IP_NULL;
if (irq_is_enabled)
ipcom_interrupt_enable(msr);
}
/*
*===========================================================================
* iplite_timeout_schedule
*===========================================================================
* Description: Schedules a function that will be called after msec_to_timeout
* milliseconds.
* Parameters: msec_to_timeout - Milliseconds until the timeout will occur.
* handler - The timeout handler.
* cookie - The user defined arguemnt to the handler.
* ptmo - The location where the timeout handler should be stored
* (needed to cancel the timer) or IP_NULL.
* Returns: 0 = success, <0 = error code.
*
*/
IP_GLOBAL int
iplite_timeout_schedule(Ip_u32 msec_to_timeout,
Iplite_timeout_handler handler,
void *cookie,
Iplite_timeout **ptmo)
{
Iplite_timeout *tmo;
if (iplite.tmo_list == IP_NULL)
{
int i;
const int num = 10;
iplite.tmo_list = ipcom_calloc(num, sizeof(Iplite_timeout));
if (iplite.tmo_list == IP_NULL)
{
IPCOM_LOG0(CRIT, "iplite_timeout_schedule: Failed to allocate memory");
IP_PANIC();
return -IP_ERRNO_ENOMEM;
}
for (i = 0; i < num - 1; i++)
iplite.tmo_list[i].cookie = &iplite.tmo_list[i + 1];
}
tmo = iplite.tmo_list;
iplite.tmo_list = tmo->cookie;
tmo->handler = handler;
tmo->cookie = cookie;
tmo->msec = iplite.msec_now + msec_to_timeout;
tmo->ptmo = ptmo;
if (ptmo != IP_NULL)
*ptmo = tmo;
(void)ipcom_pqueue_insert(iplite.timeouts, tmo);
if (tmo->pq_index == 1)
/* This is the next event to timeout, wake the IPLITE daemon
so it update its sleeping time */
IPCOM_STACKD_POST(IP_TRUE);
return 0;
}
/*
*===========================================================================
* iplite_timeout_cancel
*===========================================================================
* Description: Cancels a scheduled timeout.
* Parameters: tmo - The timeout event to remove.
* Returns:
*
*/
IP_GLOBAL void
iplite_timeout_cancel(Iplite_timeout *tmo)
{
if (tmo == IP_NULL || tmo->pq_index == 0)
return;
(void)ipcom_pqueue_remove(iplite.timeouts, tmo->pq_index);
tmo->cookie = iplite.tmo_list;
iplite.tmo_list = tmo;
/* If there's a reference pointer, clear it */
if (tmo->ptmo != IP_NULL)
*tmo->ptmo = IP_NULL;
}
/*
*===========================================================================
* iplite_timeout_msec_until
*===========================================================================
* Description: Milliseconds until this timeout triggers.
* Parameters: tmo - Handle to the timeout event.
* Returns:
*
*/
IP_GLOBAL Ip_u32
iplite_timeout_msec_until(Iplite_timeout *tmo)
{
return tmo->msec - iplite.msec_now;
}
/*
*===========================================================================
* iplite_msec_now
*===========================================================================
* Description: Returns a number that is increased by 1 for each milliseconds.
* Parameters:
* Returns: A value with millisecond resolution.
*
*/
IP_GLOBAL Ip_u32
iplite_msec_now(void)
{
struct Ip_timeval tv;
ipcom_microtime(&tv);
return (Ip_u32) (tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
/*
*===========================================================================
* iplite_create_mask
*===========================================================================
* Description: Creates a network mask with the 'netbits' leftmost bits set.
* Parameters: mask - Pointer to a buffer where the mask should be stored.
* netbits - The number of set bits.
* Returns:
*
*/
IP_GLOBAL void
iplite_create_mask(void *mask, int netbits)
{
int i;
for (i = 0; i < netbits; i++)
{
IP_BIT_SET(((Ip_u16*) mask)[i / 16], ip_htons(0x8000 >> (i % 16)));
}
}
/*
*===========================================================================
* iplite_timeval_to_msec
*===========================================================================
* Description: Converts timeval to millisecond.
* Parameters: tv - A pointer to a timeval struct or IP_NULL for inifinity.
* Returns: Millisecond representation of the timevalue.
*
*/
IP_GLOBAL Ip_s32
iplite_timeval_to_msec(struct Ip_timeval *tv)
{
if (tv == IP_NULL)
return -1;
return tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
}
/*
*===========================================================================
* iplite_kmalloc_impl
*===========================================================================
* Description: Allocates dynamic memory for everything except packets in
* IPLITE.
* Parameters: size - Number of octets to allocate.
* Returns: A pointer the allocated memory block or IP_NULL if the
* requested amount of memory could not be allocated.
*
*/
#ifdef IPCOM_USE_DMALLOC
IP_GLOBAL void *
iplite_kmalloc_impl(Ip_size_t size, const char *file, const char *function, Ip_u32 line)
#else
IP_GLOBAL void *
iplite_kmalloc_impl(Ip_size_t size)
#endif
{
Ip_size_t *buf;
IPLITE_CODE_ISLOCKED_ASSERT();
ip_assert(size > 0);
if (iplite.mem_used + size > IPLITE_CONF_MEM_MAX)
{
/*!! Tell the module to free all memory used as cache */
if (iplite.mem_used + size > IPLITE_CONF_MEM_MAX)
/* IPLITE is not allowed to use more memory */
return IP_NULL;
}
#ifdef IPCOM_USE_DMALLOC
buf = ipcom_dmalloc(size + sizeof(Ip_size_t), file, function, line);
#else
buf = ipcom_malloc(size + sizeof(Ip_size_t));
#endif
if (buf == IP_NULL)
return IP_NULL;
iplite.mem_used += size;
*buf = size;
buf++;
ipcom_memset(buf, 0, size);
return buf;
}
/*
*===========================================================================
* iplite_kfree
*===========================================================================
* Description: Frees a memory block that allocated by iplite_kmalloc_impl().
* Parameters: buf - A pointer to the block that should be freed.
* Returns:
*
*/
IP_GLOBAL void
iplite_kfree(void *ptr)
{
Ip_size_t *buf = (Ip_size_t *) ptr;
IPLITE_CODE_ISLOCKED_ASSERT();
ip_assert(ptr != IP_NULL);
--buf;
ip_assert(iplite.mem_used >= *buf);
iplite.mem_used -= *buf;
#ifdef IPCOM_USE_DMALLOC
ipcom_dfree(buf);
#else
ipcom_free(buf); /*lint !e424 Inappropriate deallocation */
#endif
}
/*
*===========================================================================
* ipnet_pkt_pool_hdr_ctor
*===========================================================================
* Description: Packet header constructor.
* Parameters: mc - memory slab cache managing this packet.
* pkt - packet header.
* Returns: IP_TRUE - the packet header was successfully initialized.
* IP_FALSE - the packet header initialization failed.
*
*/
IP_STATIC Ip_bool
ipnet_pkt_pool_hdr_ctor(Ipcom_memory_cache *mc, Ipcom_pkt *pkt)
{
IPCOM_UNUSED_ARG(mc);
pkt->next_fragment = IP_NULL;
pkt->next_original = IP_NULL;
pkt->next_part = IP_NULL;
return IP_TRUE;
}
IP_GLOBAL Ipcom_slab_ctor ipnet_pkt_pool_hdr_ctor_func =
(Ipcom_slab_ctor)ipnet_pkt_pool_hdr_ctor;
/*
*===========================================================================
* ipcom_pkt_malloc
*===========================================================================
* Description: Allocates the requested amount of MTU data. MTU data is
* defined as IP + transport + application (not link header).
* Parameters: [in] mtu - The amount of payload the packet must be able to hold.
* [in] fcflags - IP_FLAG_FC_xxx flags.
* Returns: An uninitialized packet.
*
*/
#ifdef IP_DEBUG
IP_PUBLIC Ipcom_pkt *
ipcom_pkt_dmalloc(Ip_size_t mtu, int fcflags, char *file, int line)
#else
IP_FASTTEXT IP_PUBLIC Ipcom_pkt *
ipcom_pkt_malloc(Ip_size_t mtu, int fcflags)
#endif /* IP_DEBUG */
{
Ip_u32 isr;
Ipcom_pkt *pkt;
Ip_bool wake_iplite_daemon = IP_FALSE;
#ifdef IP_DEBUG
int pool_index = 0;
#else
int pool_index;
#endif
#ifdef IP_ASSERT
if (IP_BIT_ISSET(fcflags, IP_FLAG_FC_STACKCONTEXT))
IPLITE_CODE_ISLOCKED_ASSERT();
if (IP_BIT_ISSET(fcflags, IP_FLAG_FC_BLOCKOK))
ip_assert(IP_BIT_ISFALSE(fcflags, IP_FLAG_FC_ISRCONTEXT));
#endif
#ifdef IPLITE_USE_EXTERNAL_PKT_BUF
if (mtu == 0)
return iplite_pkt_hdr_malloc(fcflags);
#endif
isr = ipcom_interrupt_disable();
for (;;)
{
for (pool_index = 0; pool_index < iplite.pkt_pool_elem; pool_index++)
{
if (mtu > iplite.pkt_pool[pool_index].mtu)
/* Packets in this pool are too small */
continue;
if (iplite.pkt_pool[pool_index].free_list)
/* Packets are available in this pool */
goto found;
if (iplite.drain_soft_irq.pending == IP_FALSE)
{
iplite.drain_soft_irq.handler = (Iplite_soft_irq_handler) iplite_pkt_drain;
iplite_schedule_soft_interrupt(&iplite.drain_soft_irq, IP_FALSE);
wake_iplite_daemon = IP_TRUE;
}
}
/* No packet found. */
ip_assert(pool_index == iplite.pkt_pool_elem);
if (mtu > iplite.pkt_pool[iplite.pkt_pool_elem-1].mtu)
{
/* No packet in the pool is big enough */
IPCOM_LOG1(DEBUG, "No packet pool buffer is big enough to store requested size: %d", mtu);
ip_assert2(mtu < 1048576);
goto leave;
}
if (IP_BIT_ISSET(fcflags, IP_FLAG_FC_BLOCKOK))
{
/* Block and wait for available packet */
ip_assert(IP_BIT_ISFALSE(fcflags, IP_FLAG_FC_ISRCONTEXT));
iplite.pkt_pool_blocked++;
ipcom_interrupt_enable(isr);
IPCOM_LOG0(DEBUG2, "Packet pool is exhausted, blocking");
if (IP_BIT_ISSET(fcflags, IP_FLAG_FC_STACKCONTEXT))
IPLITE_CODE_UNLOCK();
/*!! Ipnet has a IPCOM_STACKD_POST(IP_FALSE) here for no obvious reason? */
(void)ipcom_sem_wait(iplite.pkt_pool_sem);
if (IP_BIT_ISSET(fcflags, IP_FLAG_FC_STACKCONTEXT))
IPLITE_CODE_LOCK();
isr = ipcom_interrupt_disable();
}
else
{
/* No more packets to hand out. */
goto leave;
}
}
/* Get packet. */
found:
pkt = iplite.pkt_pool[pool_index].free_list;
ip_assert(pkt != IP_NULL);
IPCOM_PKT_TRACE_FL(pkt, IPCOM_PKT_ID_MALLOC, file, line);
iplite.pkt_pool[pool_index].free_list = pkt->next;
iplite.pkt_pool[pool_index].used++;
ipcom_interrupt_enable(isr);
if (wake_iplite_daemon)
IPCOM_STACKD_POST(IP_FALSE);
/* Init packet. */
pkt->fd = IP_INVALID_SOCKET;
pkt->flags = IPCOM_PKT_FLAG_ALLOC;
pkt->offset = 0;
pkt->chk = 0;
pkt->next = IP_NULL;
pkt->next_fragment = IP_NULL;
#ifdef IP_PORT_VXWORKS
pkt->next_extra_data = IP_NULL;
#endif
IPCOM_PKT_INIT_REF_COUNT(pkt);
ip_assert(pkt->next_original == IP_NULL);
ip_assert(pkt->data != IP_NULL);
ip_assert((int)mtu <= pkt->maxlen);
IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_INIT);
IPLITE_DEBUG_LINE(iplite_pkt_add_to_alloc_list(pkt));
return pkt;
leave:
ipcom_interrupt_enable(isr);
if (wake_iplite_daemon)
IPCOM_STACKD_POST(IP_FALSE);
return IP_NULL;
}
/*
*===========================================================================
* ipcom_pkt_free
*===========================================================================
* Description: Frees a packet that was allocted with ipcom_pkt_malloc().
* Parameters: [in] pkt - The packet to free.
* Returns:
*
*/
#ifdef IP_DEBUG
IP_PUBLIC void
ipcom_pkt_dfree(Ipcom_pkt *pkt, char *file, int line)
#else
IP_FASTTEXT IP_PUBLIC void
ipcom_pkt_free(Ipcom_pkt *pkt)
#endif /* IP_DEBUG */
{
Ip_u32 isr;
Ipcom_pkt *next_pkt;
int blocked = 0;
Ip_bool wake_iplite_daemon = IP_FALSE;
ip_assert(IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_ALLOC));
IPCOM_PKT_TRACE_FL(pkt, IPCOM_PKT_ID_DELREF, file, line);
#ifdef IP_DEBUG
iplite_pkt_check(pkt);
#ifdef IPCOM_USE_TCP
iplite_tcp_pkt_freecheck(pkt);
#endif
#endif /* IP_DEBUG */
if(pkt->next_original != IP_NULL)
{
ipcom_pkt_free(pkt->next_original);
pkt->next_original = IP_NULL;
}
for (; pkt != IP_NULL; pkt = next_pkt)
{
isr = ipcom_interrupt_disable();
next_pkt = pkt->next_fragment;
pkt->next_fragment = IP_NULL;
if (IPCOM_PKT_DEL_REF(pkt) != 0)
{
/* Someone else has a reference to this packet */
ipcom_interrupt_enable(isr);
continue;
}
IPLITE_DEBUG_LINE(iplite_pkt_remove_from_alloc_list(pkt));
IP_BIT_CLR(pkt->flags, IPCOM_PKT_FLAG_ALLOC);
blocked += iplite.pkt_pool_blocked;
iplite.pkt_pool_blocked = 0;
#ifdef IPLITE_USE_EXTERNAL_PKT_BUF
if (pkt->data_freefunc != IP_NULL)
{
ipcom_interrupt_enable(isr);
pkt->data_freefunc(pkt->data, pkt->data_freefunc_cookie);
isr = ipcom_interrupt_disable();
pkt->next = iplite.external_pkt_hdr_list;
iplite.external_pkt_hdr_list = pkt;
}
else
#endif /* IPLITE_USE_EXTERNAL_PKT_BUF */
{
Iplite_pkt_pool *pkt_pool;
ip_assert(pkt->data_freefunc == IP_NULL);
ip_assert(pkt->data != IP_NULL);
pkt_pool = &iplite.pkt_pool[(int)pkt->data_freefunc_cookie];
pkt->next = pkt_pool->free_list;
pkt_pool->free_list = pkt;
#ifdef IP_ASSERT
{
Ipcom_pkt *tmp_pkt;
/* Check that 'pkt' is not already in the free list. */
for(tmp_pkt = pkt_pool->free_list; tmp_pkt; tmp_pkt = tmp_pkt->next)
{
ip_assert(tmp_pkt->data_freefunc_cookie == pkt->data_freefunc_cookie);
ip_assert(tmp_pkt->maxlen == pkt->maxlen);
}
#ifdef IP_DEBUG
/* Check that 'pkt' is not already in allocated list. */
for (tmp_pkt = iplite.allocated_pkt_list; tmp_pkt != IP_NULL; tmp_pkt = tmp_pkt->next_alloc)
ip_assert(pkt != tmp_pkt);
#endif
}
#endif /* IP_ASSERT */
IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_FREEQ);
#ifdef IPLITE_DEBUG
pkt->ifindex = 0xffffffff;
pkt->start = pkt->maxlen + 3;
pkt->end = pkt->maxlen + 1;
pkt->next_fragment = (void *)-1;
#endif /* IPLITE_DEBUG */
}
if (IP_BIT_ISSET(iplite_flags, IPLITE_FLAG_PKTAVAIL_CB_PENDING)
&& !iplite.pktavail_soft_irq.pending)
{
iplite.pktavail_soft_irq.handler = (Iplite_soft_irq_handler) iplite_issue_pktavail_cb;
iplite_schedule_soft_interrupt(&iplite.pktavail_soft_irq, IP_FALSE);
wake_iplite_daemon = IP_TRUE;
}
ipcom_interrupt_enable(isr);
}
if (wake_iplite_daemon)
IPCOM_STACKD_POST(IP_FALSE);
/* Wake up processsing waiting to allocate packets */
while (blocked--)
(void)ipcom_sem_post(iplite.pkt_pool_sem);
}
/*
*===========================================================================
* iplite_pkt_clone
*===========================================================================
* Description: Makes a clone of a packet. Everything is cloned except for
* the total size that might be smaller for the clone
* (pkt->maxlen >= clone->maxlen)
* Parameters: orginal - The packet that should be cloned.
* Returns: The clone.
*
*/
IP_GLOBAL Ipcom_pkt *
iplite_pkt_clone(Ipcom_pkt *pkt)
{
Ipcom_pkt *clone;
int mtu;
IPLITE_DEBUG_LINE(Ip_u32 isr);
IPLITE_CODE_ISLOCKED_ASSERT();
ip_assert(IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_ALLOC));
ip_assert(pkt->start >= pkt->ipstart);
mtu = IP_MAX(pkt->maxlen - IPLITE_PKT_ALIGNMENT - ipcom_conf_max_link_hdr_size,
pkt->end - pkt->ipstart);
clone = ipcom_pkt_malloc(mtu,
IP_FLAG_FC_STACKCONTEXT);
if (clone == IP_NULL)
{
IPLITE_STATS(pkt_clone_nomem++);
return IP_NULL;
}
/* Must disable interrupts in debug since some debug fields can change if
* another packet is allocated or freed before the memcpy is done.
*/
IPLITE_DEBUG_LINE(isr = ipcom_interrupt_disable());
ipcom_memcpy(clone, pkt, ip_offsetof(Ipcom_pkt, maxlen));
IPLITE_DEBUG_LINE(ipcom_interrupt_enable(isr));
clone->ipstart = ipcom_conf_max_link_hdr_size;
clone->start = clone->ipstart + pkt->start - pkt->ipstart;
clone->end = clone->start + pkt->end - pkt->start;
ipcom_memcpy(&clone->data[clone->ipstart], &pkt->data[pkt->ipstart], pkt->end - pkt->ipstart);
IPLITE_DEBUG_LINE(iplite_pkt_check(clone));
return clone;
}
/*
*===========================================================================
* iplite_pkt_check
*===========================================================================
* Description: Check that an active packet is not in free list or in inputq
* Parameters: pkt - The packet to check.
* Returns:
*
*/
#ifdef IPLITE_DEBUG
IP_GLOBAL void
iplite_pkt_check(Ipcom_pkt *pkt)
{
Ip_u32 isr;
Ipcom_pkt *tmp_pkt;
int num;
int i;
#ifdef IP_ASSERT
Ip_bool found;
#endif
ip_assert(IPCOM_GET_PKT_ID(pkt) != IPCOM_PKT_ID_FREEQ);
if (pkt->ifindex == IPLITE_IF_LOOPBACK_INDEX)
{
if (IPCOM_PKT_HAS_MULTIPLE_OWNERS(pkt) == IP_FALSE)
ip_assert(IPCOM_GET_PKT_ID(pkt) != IPCOM_PKT_ID_INQ);
}
else
ip_assert(IPCOM_GET_PKT_ID(pkt) != IPCOM_PKT_ID_INQ);
isr = ipcom_interrupt_disable();
/* Check that pkt is not in the free list. */
for (tmp_pkt = iplite.pkt_hdr_list; tmp_pkt != IP_NULL; tmp_pkt = tmp_pkt->next)
ip_assert(IPCOM_GET_PKT_ID(tmp_pkt) == IPCOM_PKT_ID_FREEQ);
/* Check that the pool is sane */
for (i = 0; i < iplite.pkt_pool_elem; i++)
{
num = 0;
for (tmp_pkt = iplite.pkt_pool[i].free_list; tmp_pkt != IP_NULL; tmp_pkt = tmp_pkt->next)
num++;
ip_assert(iplite.pkt_pool[i].total >= num);
}
/* Check that pkt is not in the inqueue as well. */
num = 0;
for (tmp_pkt = iplite.inq_head; tmp_pkt != IP_NULL; tmp_pkt = tmp_pkt->next)
{
ip_assert(IPCOM_GET_PKT_ID(tmp_pkt) == IPCOM_PKT_ID_INQ
|| IPCOM_GET_PKT_ID(tmp_pkt) == IPCOM_PKT_ID_DELREF);
if (pkt->ifindex == IPLITE_IF_LOOPBACK_INDEX)
{
if (IPCOM_PKT_HAS_MULTIPLE_OWNERS(pkt) == IP_FALSE)
ip_assert(pkt != tmp_pkt);
}
else
ip_assert(pkt != tmp_pkt);
num++;
}
ip_assert(iplite.inq_num == num);
if (IPCOM_PKT_HAS_MULTIPLE_OWNERS(pkt) == IP_FALSE)
{
ip_assert(IPCOM_GET_PKT_ID(pkt) != IPCOM_PKT_ID_OUTQ);
ip_assert(IPCOM_GET_PKT_ID(pkt) != IPCOM_PKT_ID_NETIF_OUTQ);
}
/* Check that the packet is in the list of allocated packets */
#ifdef IP_ASSERT
found = IP_FALSE;
#endif
for (tmp_pkt = iplite.allocated_pkt_list; tmp_pkt != IP_NULL; tmp_pkt = tmp_pkt->next_alloc)
{
if (tmp_pkt == pkt)
{
#ifdef IP_ASSERT
found = IP_TRUE;
#endif
break;
}
}
ip_assert(found);
ipcom_interrupt_enable(isr);
}
#endif /* IPLITE_DEBUG */
/*
*===========================================================================
* iplite_is_stack_task
*===========================================================================
* Description:
* Parameters:
* Returns: IP_TRUE if current process is an IPLITE process.
*
*/
IP_GLOBAL Ip_bool
iplite_is_stack_task(void)
{
Ip_pid_t pid;
pid = ipcom_getpid();
if (pid == iplite.daemon_pid)
return IP_TRUE;
else
return IP_FALSE;
}
/*
****************************************************************************
* 12 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipcom_pkt_input_queue
*===========================================================================
* Context: Any
* Description: Queues packets for the input daemon. This function
* should be called directly in the interrupt routine for the
* network interface.
* Parameters: pkt - The received packet. pkt->start is the offset to the
* the link layer header.
* Returns:
*
*/
IP_PUBLIC int
ipcom_pkt_input_queue(struct Ipcom_netif_struct *ipcomif, Ipcom_pkt *pkt)
{
Iplite_netif *netif = (Iplite_netif *)ipcomif;
Ip_u32 isr;
ip_assert(((Ip_u32)pkt->start & 0x1) == 0);
#if !defined(IP_PORT_ATI) && !defined(IP_PORT_VXWORKS) && !defined(IP_PORT_MQX)
ip_assert(pkt->ifindex == IPLITE_IF_LOOPBACK_INDEX || (pkt->start >= (ipcom_conf_max_link_hdr_size - netif->ipcom.link_hdr_size)));
#endif
IPLITE_DEBUG_LINE(iplite_pkt_check(pkt));
ip_assert(IP_BIT_ISSET(iplite_flags, IPLITE_FLAG_CREATED));
pkt->next = IP_NULL;
pkt->ifindex = netif->ipcom.ifindex;
isr = ipcom_interrupt_disable();
IPLITE_DEBUG_LINE(ip_assert(IPCOM_GET_PKT_ID(pkt) == IPCOM_PKT_ID_RX));
if (iplite.inq_num < IPLITE_CONF_INQ_MAX)
{
if (iplite.inq_head != IP_NULL)
iplite.inq_tail->next = pkt;
else
iplite.inq_head = pkt;
iplite.inq_tail = pkt;
++iplite.inq_num;
IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_INQ);
ipcom_interrupt_enable(isr);
IPCOM_STACKD_POST(IP_FALSE);
return 0;
}
else
{
IPLITE_STATS(pkt_input_queue_full++);
ipcom_interrupt_enable(isr);
ipcom_pkt_free(pkt);
return -1;
}
}
/*
*===========================================================================
* iplite_kioevent
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
iplite_kioevent(Iplite_netif *netif, int event, void *data)
{
int i;
Ip_bool ifchange = IP_TRUE;
IPLITE_CODE_ISLOCKED_ASSERT();
/*!!TODO: REPAIR IPCOM OSE INET4 CLIENT EVENT CALLBACKS
* NOTE: they must use IOCTL now!
*/
switch (event)
{
case IP_EIOXUP :
ip_assert(!IP_BIT_ISSET(netif->ipcom.flags, IP_IFF_UP));
IP_BIT_SET(netif->ipcom.flags, IP_IFF_UP);
break;
case IP_EIOXDOWN :
ip_assert2(IP_BIT_ISSET(netif->ipcom.flags, IP_IFF_UP));
IP_BIT_CLR(netif->ipcom.flags, IP_IFF_UP);
break;
case IP_EIOXRUNNING:
IP_BIT_SET(netif->ipcom.flags, IP_IFF_RUNNING);
break;
case IP_EIOXSTOP:
IP_BIT_CLR(netif->ipcom.flags, IP_IFF_RUNNING);
break;
case IP_EIOXCHANGE:
break;
default:
ifchange = IP_FALSE;
break;
}
if (ifchange)
{
#ifdef IPCOM_USE_INET
iplite_ip4_kioevent(netif, event);
#endif
#ifdef IPCOM_USE_INET6
iplite_ip6_kioevent(netif, event);
#endif
}
/* Call interface event callbacks. */
IPLITE_CODE_UNLOCK();
for (i = 0; i < IPLITE_MAX_IF_EVENTCB; i++)
if (iplite.if_eventcb[i] != IP_NULL)
(void)iplite.if_eventcb[i](netif->ipcom.name, netif->ipcom.ifindex,
netif->ipcom.flags, event, data);
IPLITE_CODE_LOCK();
}
/*
*===========================================================================
* ipcom_pkt_create
*===========================================================================
* Description: Creates a valid Ipcom_pkt structure from user allocated memory.
* This function can be called in any context.
* Parameters: pkt - Pointer to user allocated memory that is at least
* sizeof(pkt) bytes long.
* data - Pointer to user allocated memory that will hold the
* IP packet data.
* data_len- The length of the buffer pointed to by 'data'.
* freefunc - A pointer to a function that will be called
* when IPLITE is done using the created packet. 1:st argument
* will be the created packet ('data' pointer is pkt->data),
* 2:nd argument is the same as the 'cookie' value passed to this
* function.
* cookie - User define data.
* Returns:
*/
IP_FASTTEXT IP_PUBLIC void
ipcom_pkt_create(Ipcom_pkt *pkt, void *data, Ip_size_t data_len,
Ipcom_pkt_freefunc data_freefunc, void *data_cookie)
{
pkt->next_fragment = IP_NULL;
pkt->next_original = IP_NULL;
pkt->next_part = IP_NULL;
pkt->fd = IP_INVALID_SOCKET;
pkt->vr_index = 0;
pkt->ifindex = 0;
pkt->next = IP_NULL;
pkt->flags = IPCOM_PKT_FLAG_ALLOC;
pkt->ipstart = 0;
pkt->maxlen = data_len;
pkt->offset = 0;
pkt->chk = 0;
pkt->data = data;
#ifdef IP_PORT_VXWORKS
pkt->done = IPCOM_PKT_DONE_DEFAULT;
#endif
pkt->data_freefunc = data_freefunc;
pkt->data_freefunc_cookie = data_cookie;
pkt->dtor = IP_NULL;
pkt->recurs_level = 0;
IPCOM_PKT_INIT_REF_COUNT(pkt);
#ifdef IPNET_USE_VLAN
pkt->link_cookie = 0;
#endif
#ifdef IPNET_USE_VRRP
IPCOM_PKT_SET_VRID(pkt, 0);
#endif
pkt->ipsec_skip = 0;
pkt->ipsec_hlen = 0;
pkt->ipsec_seq = 0;
pkt->ipsec_input = 0;
pkt->ipsec_domain = 0;
pkt->next_extra_data = 0;
pkt->force_frame_type = 0;
#ifdef IPCOM_FORWARDER
pkt->pkt = IP_NULL;
pkt->pipe = IP_NULL;
pkt->netif = IP_NULL;
#endif
#ifdef IPROHC
pkt->flag_rohc = IP_FALSE;
#endif
IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_INIT);
}
/*
*===========================================================================
* ipcom_stack_lock
*===========================================================================
* Description: Locks the IPLITE lock.
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
ipcom_stack_lock(void)
{
IPLITE_CODE_LOCK();
}
/*
*===========================================================================
* ipnet_timeval_to_msec
*===========================================================================
* Description: Unlocks the IPLITE lock.
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
ipcom_stack_unlock(void)
{
IPLITE_CODE_UNLOCK();
}
/*
*===========================================================================
* iplite_create
*===========================================================================
* Description: Shows how IPLITE can be started.
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iplite_create(void)
{
int indx, i;
int ret;
Ipcom_netif *netif;
Iplite_pkt_pool *pkt_pool;
Ipcom_pkt *pkt;
void *data;
#if defined(IPCOM_USE_LBP) || defined(IPCOM_USE_ETHERNET)
Ip_err retval;
#endif
#if IP_FD_SETSIZE < IPLITE_CONF_MAX_SOCKETS
#error IP_FD_SETSIZE_must_be_equal_to_or_greater_than_IPLITE_CONF_MAX_SOCKETS
#endif
ipcom_memset(&iplite, 0, sizeof(Iplite_data));
/* This is correct since the daemon will check all events before
* sleeping for the first time. It is also necessary since the
* daemon block cannot be posted before created.
*/
iplite.daemon_posted = IP_TRUE;
iplite.timeouts = ipcom_pqueue_new((Ipcom_pqueue_cmp_func) iplite_timeout_pq_cmp,
(Ipcom_pqueue_store_index) iplite_timeout_pq_store_index);
if (iplite.timeouts == IP_NULL)
{
IPCOM_LOG0(EMERG, "Failed to create priority queue for timeouts");
goto cleanup;
}
/* Update memory usage now */
iplite.last_fd = IPLITE_SOCKET_STARTFD;
#ifdef IPCOM_USE_TCP
iplite_tcp_create();
#endif
if (ipcom_sem_create(&iplite.pkt_pool_sem, 0) != IPCOM_SUCCESS)
{
IPCOM_LOG0(EMERG, "Failed to create the packet pool semaphore");
goto cleanup;
}
if (ipcom_mutex_create(&iplite.code_mutex) != IPCOM_SUCCESS)
{
IPCOM_LOG0(EMERG, "Failed to create the code mutex");
goto cleanup;
}
/* Initialize the packet pool */
IPLITE_CODE_LOCK();
#ifdef IPLITE_USE_EXTERNAL_PKT_BUF
if (ipcom_pkt_add_hdr_to_pool(IPLITE_NUM_PKT_HDR) < 0)
{
IPCOM_LOG1(EMERG, "Failed to allocate %d packet headers", IPLITE_NUM_PKT_HDR);
goto cleanup;
}
#endif /* IPLITE_USE_EXTERNAL_PKT_BUF */
for (indx = 0; iplite_conf_pkt_pool[indx].mtu != 0; indx++)
{
pkt_pool = &iplite.pkt_pool[indx];
/* Initialize the packet pool header. */
ip_assert(indx < IPLITE_CONF_MAX_PKTPOOL);
pkt_pool->mtu = iplite_conf_pkt_pool[indx].mtu;
if(pkt_pool->mtu > iplite.pkt_pool_max_mtu)
iplite.pkt_pool_max_mtu = pkt_pool->mtu;
ip_assert(pkt_pool->free_list == IP_NULL);
ip_assert(pkt_pool->total == 0);
pkt_pool->len = (Ip_u16) (IPLITE_PKT_ALIGNMENT
+ ipcom_conf_max_link_hdr_size
+ pkt_pool->mtu
+ IPLITE_CONF_CACHE_BUFSIZ);
/* Create pkt->data buffers. */
for (i = 0; i < iplite_conf_pkt_pool[indx].count; i++)
{
pkt = iplite_kmalloc(sizeof(Ipcom_pkt) + ipcom_port_pkt_hdr_extra_size);
if (pkt == IP_NULL)
goto nomem;
#ifdef IPCOM_VXWORKS_DRV_NULLPOOL
ipnet_pkt_pool_hdr_ctor_func(IP_NULL, pkt);
#endif
data = ipcom_calloc(1, pkt_pool->len);
if (data == IP_NULL)
{
nomem:
IPCOM_LOG3(EMERG, "Failed to allocate %d bytes to packet pool."
" %d buffer out of %d has been allocated",
pkt_pool->len, i, (int)iplite_conf_pkt_pool[indx].count);
IPLITE_CODE_UNLOCK();
goto cleanup;
}
ipcom_pkt_create(pkt,
data, pkt_pool->len - IPLITE_CONF_CACHE_BUFSIZ,
IP_NULL, (void *)indx);
pkt->next = pkt_pool->free_list;
pkt_pool->free_list = pkt;
pkt_pool->total++;
}
}
iplite.pkt_pool_elem = (Ip_u16)indx;
IPCOM_LOG0(DEBUG, "Packet pool was successfully initialized");
/* IPLITE is created. */
#ifdef IP_ASSERT
IP_BIT_SET(iplite_flags, IPLITE_FLAG_CREATED);
#endif
IPLITE_CODE_UNLOCK();
/* Allocate loopback interface */
netif = ipcom_if_malloc(IP_IFT_LOOP);
if (netif == IP_NULL)
goto cleanup;
/* Attach loopback interface */
ret = ipcom_if_attach(netif);
if (ret < 0)
goto cleanup;
/* Create Ethernet drivers */
#ifdef IPCOM_USE_ETHERNET
retval = ipcom_drv_eth_create();
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG1(CRIT, "iplite_create() :: ipcom_drv_eth_create() failed: %ld", retval);
goto cleanup;
}
#endif
#ifdef IPCOM_USE_LBP
retval = ipcom_drv_lbp_create();
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "iplite_create() :: ipcom_drv_lbp_create() failed: %ld", retval);
goto cleanup;
}
#endif
#if defined(IP_PORT_VXWORKS) && defined(IPCOM_USE_SOCK_COMPAT)
if (ipcom_windnet_socklib_init() < 0)
goto cleanup;
#endif
IPCOM_LOG0(DEBUG, "iplite_create() :: success");
return IPCOM_SUCCESS;
cleanup:
IPCOM_LOG0(ERR, "iplite_create() :: failed");
IP_PANIC();
return IPCOM_ERR_FAILED;
}
/*
*===========================================================================
* iplite_start
*===========================================================================
* Description: Start IPLITE
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iplite_start(void)
{
int ret;
IPLITE_CODE_LOCK();
/* Configure interfaces (adds addresses) */
ret = iplite_if_configure();
if (ret < 0)
{
IP_PANIC();
IPLITE_CODE_UNLOCK();
IPCOM_LOG1(CRIT, "failed to configure the stack (%s)", ipcom_strerror(-ret));
return IPCOM_ERR_FAILED;
}
#ifdef IPCOM_USE_MIB2
/* Initialize MIB2 variables */
#ifdef IPCOM_USE_INET
IPCOM_MIB2(ipReasmTimeout = IPLITE_CONF_REASSEMBLY_TIMEOUT); /*lint !e665 */
#endif
#ifdef IPCOM_USE_TCP
IPCOM_MIB2(tcpRtoAlgorithm = 4); /* Van Jacobson */ /*lint !e665 */
IPCOM_MIB2(tcpRtoMin = iplite_tcp_get_rto(IP_TRUE)); /*lint !e665 */
IPCOM_MIB2(tcpRtoMax = iplite_tcp_get_rto(IP_FALSE)); /*lint !e665 */
IPCOM_MIB2(tcpMaxConn = IPLITE_CONF_MAX_SOCKETS); /*lint !e665 */
#endif /* IPCOM_USE_TCP */
#endif /* IPSNP_USE_MIB2 */
/* IPLITE is configured. */
IP_BIT_SET(iplite_flags, IPLITE_FLAG_CONFIGURED);
IPLITE_CODE_UNLOCK();
#ifdef IPLITE_STACKD_INTERNAL
(void)ipcom_proc_create("iplited", (Ipcom_proc_func)iplited, IPCOM_PROC_STACK_DEFAULT, IP_NULL);
#endif
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* iplite_version
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC const char *
iplite_version(void)
{
return "@(#) IPLITE $Name: VXWORKS_ITER40_2019102207 $ - INTERPEAK_COPYRIGHT_STRING";
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/