1941 lines
54 KiB
C
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
|
|
****************************************************************************
|
|
*/
|