/* *=========================================================================== * ipcom_hash_new *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ipcom_hash * ipcom_hash_new(Ipcom_hash_obj_func obj_hash_func, Ipcom_hash_key_func key_hash_func, Ipcom_hash_cmp_func obj_key_cmp) { Ipcom_hash *head; ip_assert(obj_hash_func != IP_NULL); ip_assert(key_hash_func != IP_NULL); ip_assert(obj_key_cmp != IP_NULL); head = IPCOM_MALLOC_STATIC(sizeof(*head)); if (head == IP_NULL) return IP_NULL; head->table = IPCOM_CALLOC_STATIC(IPCOM_HASH_INITIAL_SIZE, sizeof(*head->table)); if (head->table == IP_NULL) { IPCOM_FREE_STATIC(head); return IP_NULL; } head->obj_hash_func = obj_hash_func; head->key_hash_func = key_hash_func; head->obj_key_cmp = obj_key_cmp; head->size = IPCOM_HASH_INITIAL_SIZE; head->elem = 0; return head; }
/* *=========================================================================== * ipcom_proc_copyenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipcom_proc_copyenv(Ipcom_proc *proc_c) { Ipcom_proc *proc_p; Ip_err retval; proc_p = ipcom_proc_self(); ip_assert(proc_p != IP_NULL); ip_assert(proc_c != IP_NULL); if (proc_p->env_tree == IP_NULL) /* Parent process has no environment variables */ return; /* Create child environment semaphore and tree */ retval = ipcom_once(&proc_c->env_once, ipcom_env_init, proc_c); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return; } ipcom_mutex_lock(proc_p->env_mutex); ipcom_hash_for_each(proc_p->env_tree, (Ipcom_hash_foreach_cb_func) ipcom_env_clone, proc_c->env_tree); ipcom_mutex_unlock(proc_p->env_mutex); }
/* *=========================================================================== * ipnet_netlink_register_ops *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipnet_rtnetlink_register_family_event(int family, int cmd, Ip_size_t maxattr, Ip_size_t min_size, Ipnet_rtnetlink_do_t doit, Ipnet_netlink_dump_t dumpit) { Ipnet_rtnetlink_table_t *table; /**/ if (ipnet->rtnetlink_links[family] == IP_NULL) { ipnet->rtnetlink_links[family] = ipcom_calloc(IP_RTM_NR_MSGTYPES, sizeof(Ipnet_rtnetlink_table_t *)); ip_assert(ipnet->rtnetlink_links[family] != IP_NULL); } ip_assert(ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] == IP_NULL); ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] = ipcom_calloc(1, sizeof(Ipnet_rtnetlink_table_t)); ip_assert(ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] != IP_NULL); table = ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE]; table->nl_cmd = cmd; table->nl_func_table.nl_rta_max = maxattr; table->nl_func_table.nl_size_min = IP_NLMSG_LENGTH(min_size); table->nl_func_table.nl_do = doit; table->nl_func_table.nl_dump = dumpit; }
/* *=========================================================================== * ipcom_hash_add *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipcom_hash_add(Ipcom_hash *head, void *obj) { unsigned hash_index; Ip_err err; ip_assert(head->size > 0); if ((head->elem + 1) * 100 / head->size > IPCOM_HASH_HIGH_WATER_MARK) { err = ipcom_hash_resize(head, IP_TRUE); if (err != IPCOM_SUCCESS) return err; } if (head->size / 2 <= head->elem) /* The size of the hash table is locked and it has reached the capacity limit */ return IPCOM_ERR_REACHED_MAX; hash_index = head->obj_hash_func(obj) % head->size; /* Find an empty slot at the hash index or after it if another object hash:ed to the same value */ while (head->table[hash_index % head->size] != IP_NULL) { if (head->table[hash_index % head->size] == obj) return IPCOM_ERR_DUPLICATE; hash_index++; } head->table[hash_index % head->size] = obj; head->elem++; return IPCOM_SUCCESS; }
/* *=========================================================================== * ipcom_clearenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_clearenv(void) { #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM Ip_err retval; Ipcom_proc *proc; proc = ipcom_proc_self(); ip_assert(proc != IP_NULL); retval = ipcom_once(&proc->env_once, ipcom_env_init, proc); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return -1; } ipcom_proc_clearenv(proc); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) /*!! Are all environment variables cleaned up by OS automatically? */ return 0; #elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1 /*! Hmmmm */ return -1; #else return -1; #endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */ }
/* *=========================================================================== * ipcom_hash_for_each *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC void ipcom_hash_for_each(Ipcom_hash *head, Ipcom_hash_foreach_cb_func cb_func, void *data) { unsigned i; unsigned x; void **elems; if (head->elem == 0) return; elems = IPCOM_MALLOC_DYNAMIC(head->elem * sizeof(void*)); /*lint !e647 */ if (elems == IP_NULL) { IP_PANIC(); return; } for (i = 0, x = 0; i < head->size; i++) if (head->table[i] != IP_NULL) elems[x++] = head->table[i]; ip_assert(x == head->elem); for (i = 0; i < x; i++) cb_func(elems[i], data); IPCOM_FREE_DYNAMIC(elems); }
/* *=========================================================================== * ipcom_env_init *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC Ip_err ipcom_env_init(void *procptr) { Ipcom_proc *proc = procptr; ip_assert(proc != IP_NULL); (void)ipcom_mutex_create(&proc->env_mutex); proc->env_tree = ipcom_hash_new((Ipcom_hash_obj_func)ipcom_env_hash_obj, (Ipcom_hash_key_func)ipcom_env_hash_key, (Ipcom_hash_cmp_func)ipcom_env_hash_cmp); ip_assert(proc->env_tree != IP_NULL); return IPCOM_SUCCESS; }
/* *=========================================================================== * ipnet_cmd_qc_next_arg *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipnet_cmd_qc_next_arg(Ipnet_cmd_qc *p) { ip_assert(p->argc > 0); p->argv++; p->argc--; }
/* *=========================================================================== * ipnet_nat_proxy_sip_modmsg *=========================================================================== * Description: Modify message and adjust length * Parameters: newdata - pointer to new data * newlen - length of new data * olddata - pointer to old data * oldlen - length of old data * ppend - pointer to pointer to last byte of message * Returns: 0 = ok * -1 = message too long */ IP_STATIC int ipnet_nat_proxy_sip_modmsg(char *newdata, int newlen, char *olddata, int oldlen, char **ppend) { char *pmax = (char *)sipbuf + sizeof(sipbuf) - 1; int diff = newlen - oldlen; int movelen = (*ppend + 1) - (olddata + oldlen); ip_assert(movelen >= 0); if (pmax - *ppend < diff) { IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_modmsg() :: message to long"); return -1; } /* Make space for new data */ ipcom_memmove(olddata + newlen, olddata + oldlen, movelen); *ppend += diff; /* Copy in new data */ ipcom_memcpy(olddata, newdata, newlen); return 0; }
/* *=========================================================================== * ipnet_sock_tcp_append_send_data *=========================================================================== * Description: Append data to the last packet in the send queue up to * a full MSS segment. * Parameters: send_tail - The last element of the send queue. * pbuf - Pointer to the data buffer pointer. The buffer * pointer (*pbuf) will point to the first byte * that has not been copied. * plen - A pointer to the length length of *pbuf, will * contain the number of bytes not copied when this * function returns. * mss - The maximum segment size for this segment. * Returns: Number of bytes appended. * */ IP_STATIC int ipnet_sock_tcp_append_send_data(Ipcom_pkt *send_tail, Ip_u8 **pbuf, int *plen, int mss) { int bytes_appended; int len = *plen; if (mss <= send_tail->end - send_tail->start) /* mss must have been decresed after the send_tail was created */ return 0; bytes_appended = IP_MIN(mss - (send_tail->end - send_tail->start), len); ip_assert(bytes_appended >= 0); if (send_tail->chk != 0 && (send_tail->end & 0x1) == 0) { /* End is even, just add the checksum of the appended data to the current checksum */ send_tail->chk += ipnet_in_checksum_memcpy(&send_tail->data[send_tail->end], *pbuf, bytes_appended); } else { /* The checksum will be wrong unless the last odd byte is included in the new checksum, since odd bytes is handled as if the byte behind it is 0 (which is probably false now when more data is appended) */ ipnet_copy_from_user(&send_tail->data[send_tail->end], *pbuf, bytes_appended); /* Calculate the checksum when sending instead */ send_tail->chk = 0; } send_tail->end += bytes_appended; ip_assert(send_tail->end <= send_tail->maxlen); *pbuf = *pbuf + bytes_appended; *plen -= bytes_appended; return bytes_appended; }
/* *=========================================================================== * ipcom_getenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC char * ipcom_getenv(const char *name) { #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM Ip_err retval; Ipcom_proc *proc; Ipcom_env_entry *env; char *value = IP_NULL; proc = ipcom_proc_self(); ip_assert(proc != IP_NULL); retval = ipcom_once(&proc->env_once, ipcom_env_init, proc); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return IP_NULL; } ipcom_mutex_lock(proc->env_mutex); env = ipcom_hash_get(proc->env_tree, name); if (env != IP_NULL) value = (char *)env->value; ipcom_mutex_unlock(proc->env_mutex); return value; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) char *env; static char buf[256]; env = get_env(current_process(), name); if (env != IP_NULL) { ipcom_strncpy(buf, env, sizeof(buf)); free_buf((union SIGNAL **)&env); return (char *)buf; } return IP_NULL; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE return getenv(name); #elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1 static char buf[256]; Ip_size_t buf_size = sizeof(buf); return ipcom_sysvar_get(name, buf, &buf_size); #else return IP_NULL; #endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */ }
/* *=========================================================================== * ipcom_buffer_free *=========================================================================== * Description: Frees any memory used for the buffer. * Parameters: * Returns: * */ IP_PUBLIC void ipcom_buffer_free(Ipcom_buffer *buffer) { #ifdef IP_DEBUG ipcom_memset(buffer->buf, 0xdd, buffer->alloc); #endif ip_assert( buffer->buf && buffer ); ipcom_free(buffer->buf); ipcom_free(buffer); }
/* *=========================================================================== * ipnet_gre_tmo *=========================================================================== * Description: Reassembly timeout handler. * Parameters: netif - A GRE tunnel interface. * Returns: 0 = success, <0 = error code. * */ IP_STATIC void ipnet_gre_seq_tmo(Ipnet_netif *netif) { Ipnet_pkt_gre *gre_hdr; Ipcom_pkt *pkt; Ipnet_gre_t *gre = netif->ipcom.pdrv; /* RFC 2890, chapter 2.2 ... Under no circumstances should a packet wait more that OUTOFORDER_TIMER milliseconds in the buffer. If a packet has been waiting that long, the receiver MUST immediately traverse the buffer in sorted order, decapsulating packets (and ignoring any sequence number gaps) until there are no more packets in the buffer that have been waiting longer than OUTOFORDER_TIMER milliseconds. The "last successfully decapsulated sequence number" should then be set to the last packet so decapsulated. ... */ pkt = ipcom_pqueue_get_next(gre->reassembly_queue); ip_assert(pkt != IP_NULL); gre->recv_seqnum = IP_GET_NTOHL(&pkt->data[pkt->start]); do { pkt = ipcom_pqueue_remove_next(gre->reassembly_queue); /* Discard the sequence number option and make place for a GRE header */ pkt->start += IPNET_GRE_OPT_SEQNUM_SIZE - IPNET_GRE_HDR_SIZE; gre_hdr = (Ipnet_pkt_gre *)&pkt->data[pkt->start]; gre_hdr->flags_reserved0_ver = 0; if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_IPV4)) gre_hdr->protocol_type = ip_htons(0x0800); else if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_IPV6)) gre_hdr->protocol_type = ip_htons(0x86DD); (void) ipnet_gre_input(netif, pkt); ++gre->recv_seqnum; } while (IP_NULL != (pkt = ipcom_pqueue_get_next(gre->reassembly_queue)) && gre->recv_seqnum == IP_GET_NTOHL(&pkt->data[pkt->start])); if (pkt != IP_NULL) { Ip_u32 timeout = IPNET_PKT_GET_TIMEOUT_ABS(pkt); /* More out of order packets waiting, schedule a timeout of the time remaining until this packet sequence timer timeouts */ (void) ipnet_timeout_schedule((timeout < ipnet->msec_now ? 0 : timeout - ipnet->msec_now), (Ipnet_timeout_handler) ipnet_gre_seq_tmo, netif, &gre->reassembly_tmo); } }
/* *=========================================================================== * ipcom_list_remove *=========================================================================== * Description: Remove list entry pointer to by 'entry' from its list. * Parameters: entry - Pointer to the list entry to remove. * Returns: . * */ IP_PUBLIC void ipcom_list_remove(Ipcom_list *entry) { ipcom_list_assert(IP_NULL, entry); ip_assert(entry->head->size > 0); entry->next->prev = entry->prev; entry->prev->next = entry->next; entry->head->size--; entry->head = IP_NULL; }
/* *=========================================================================== * ipcom_unsetenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_unsetenv(const char *name) { #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM Ip_err retval; Ipcom_proc *proc; Ipcom_env_entry *env; proc = ipcom_proc_self(); ip_assert(proc != IP_NULL); retval = ipcom_once(&proc->env_once, ipcom_env_init, proc); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return -1; } ipcom_mutex_lock(proc->env_mutex); env = ipcom_hash_get(proc->env_tree, name); if (env != IP_NULL) ipcom_env_delete(env, proc->env_tree); ipcom_mutex_unlock(proc->env_mutex); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) set_env(current_process(), name, NULL); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && defined(IP_PORT_VXWORKS) { char buf[256]; int ret; ipcom_snprintf(buf, sizeof(buf), "%s=", name); ret = (int)putenv(buf); return ret == 0 ? 0 : -1; } #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE return unsetenv(name); #elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1 (void)ipcom_sysvar_unset(name); return 0; #else return 0; #endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */ }
/* *=========================================================================== * ipcom_buffer_get *=========================================================================== * Description: Gets data from the beginning of the buffer. * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipcom_buffer_get(Ipcom_buffer *buffer, Ip_u8 *buf, Ip_u32 len) { ip_assert(len <= (buffer->end - buffer->offset)); if(len > (buffer->end - buffer->offset)) return IPCOM_ERR_FAILED; ipcom_memcpy(buf, buffer->buf + buffer->offset, len); buffer->offset += len; return IPCOM_SUCCESS; }
/* *=========================================================================== * ipcom_freeaddrinfo *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC void ipcom_freeaddrinfo(struct Ip_addrinfo *ai) { #if defined(IP_PORT_OSE5) ip_assert(ipcom_getaddrinfo_fallback > 0); if (ipcom_getaddrinfo_fallback == 1) freeaddrinfo((struct addrinfo *)ai); else ipcom_freeaddrinfo2(ai); #else ipcom_freeaddrinfo2(ai); #endif }
ZBUF_ID zbufSockRecvfrom ( int s, /* socket to receive from */ int flags, /* flags to underlying protocols */ int * pLen, /* number of bytes requested/returned */ struct sockaddr *from, /* where to copy sender's addr */ int * pFromLen /* value/result length of <from> */ ) { ZBUF_ID zbufId; /* zbuf returned to user */ ZBUF_SEG zbufSeg = NULL; /* received zbuf chain */ int status; /* recvfrom() return status */ char* buf = NULL; int so_type; socklen_t optlen = sizeof(int); if (-1 == getsockopt(s, (int)SOL_SOCKET, (int)SO_TYPE, (char*)&so_type, (int*)&optlen)) return (ZBUF_ID)NULL; ZBUF_ID_CREATE(zbufId); /* create ID for recv data */ if (zbufId == (ZBUF_ID)NULL) return (ZBUF_ID)NULL; if (so_type == SOCK_DGRAM) { if((status = recvfrom(s, (char*)&zbufSeg, *pLen, flags | IP_MSG_ZBUF, from, pFromLen)) < 0) goto cleanup; } else { ip_assert(so_type == SOCK_STREAM); buf = ipcom_malloc(*pLen); if (buf == NULL) goto cleanup; if ((status = recvfrom(s, buf, *pLen, flags | IP_MSG_ZBUF, from, pFromLen)) < 0) goto cleanup; if ((zbufSeg = zbufInsertBuf(zbufId, NULL, 0, buf, status, simple_free, 0)) == NULL) goto cleanup; } ZBUF_SETSEG(zbufId, zbufSeg); *pLen = status; return zbufId; cleanup: if (zbufId) ZBUF_ID_DELETE_EMPTY(zbufId); if (buf) ipcom_free(buf); return (ZBUF_ID)NULL; }
/* *=========================================================================== * ipcom_clearenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipcom_proc_clearenv(Ipcom_proc *proc) { ip_assert(proc != IP_NULL); ipcom_mutex_lock(proc->env_mutex); /* Remove all environment variable entries */ ipcom_hash_for_each(proc->env_tree, (Ipcom_hash_foreach_cb_func) ipcom_env_delete, proc->env_tree); ipcom_mutex_unlock(proc->env_mutex); }
/* *=========================================================================== * ipcom_buffer_decr_cap *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipcom_buffer_decr_cap(Ipcom_buffer *buffer, Ip_u32 len) { ip_assert( len <= ipcom_buffer_capacity(buffer) ); if(len > ipcom_buffer_capacity(buffer)) return IPCOM_ERR_FAILED; IPCOM_LOG4(DEBUG2, "ipcom_buffer_decr_cap :: buf=%x, len=%d, end=%d, offset=%d", buffer, len, buffer->end, buffer->offset); buffer->end += len; return IPCOM_SUCCESS; }
/* *=========================================================================== * ipcom_buffer_consume_end *=========================================================================== * Description: Consumes the given number of bytes from the end of the buffer. * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipcom_buffer_consume_end(Ipcom_buffer *buffer, Ip_u32 bytes) { ip_assert( bytes <= (buffer->end - buffer->offset) ); if(bytes > (buffer->end - buffer->offset)) return IPCOM_ERR_FAILED; IPCOM_LOG4(DEBUG2, "ipcom_buffer_consume_end :: buf=%x, bytes=%d, end=%d, offset=%d", buffer, bytes, buffer->end, buffer->offset); buffer->end -= bytes; return IPCOM_SUCCESS; }
/* *=========================================================================== * ipnet_wlan_ioctl *=========================================================================== * Description: WLAN IO control. * Parameters: netif - The network interface to operate on. * command - * data - Depends on command. * Returns: 0 = success, < 0 = error code * */ IP_STATIC int ipnet_wlan_ioctl(Ipnet_netif *netif, Ip_u32 command, void *data) { int ret = 0; Ipcom_iwreq *iw = data; Ipcom_wlan_func wlan_if; ip_assert(netif->ipcom.link_addr_size == IPNET_WLAN_ADDR_SIZE); switch(command) { case IP_SIOCSIWATTACHFUNC: case IP_SIOCSIWREMOVEFUNC: if(command == IP_SIOCSIWATTACHFUNC) { netif->wlan->aux_link_ioctl = (int (*)(Ipnet_netif *, Ip_u32, void *))iw->u.data.pointer; } if(netif->wlan->aux_link_ioctl != IP_NULL) { wlan_if.link_input = (int (*)(Ipcom_netif *, Ipcom_pkt *))netif->link_input; ret = netif->wlan->aux_link_ioctl(netif, command, &wlan_if); netif->link_input = (Ipnet_link_input)wlan_if.link_input; } if(command == IP_SIOCSIWREMOVEFUNC) { netif->wlan->aux_link_ioctl = IP_NULL; } break; default: if(netif->wlan->aux_link_ioctl) { ret = netif->wlan->aux_link_ioctl(netif, command, data); if(ret <= 0) { break; } } ret = netif->wlan->eth_link_ioctl(netif, command, data); } return ret; }
/* *=========================================================================== * ipcom_spinlock_unlock *=========================================================================== * Description: * Parameters: * Returns: * */ IP_FASTTEXT IP_PUBLIC void ipcom_spinlock_unlock(Ipcom_spinlock sl_handle) { #ifdef IPCOM_USE_SMP Ipcom_vxworks_spinlock_t *sl = (Ipcom_vxworks_spinlock_t*) sl_handle; VX_MEM_BARRIER_RW(); /* build a memory fence for load and store */ if (vxAtomicInc(&sl->count) < 0) /* Contention for this lock, let's wakeup one of the tasks that is blocked on this lock */ semGive(sl->sem); #else IPCOM_UNUSED_ARG(sl_handle); ip_assert(sl_handle == IPCOM_SPINLOCK_TAG); taskUnlock(); #endif }
/* *=========================================================================== * ipnet_loopback_drv_output *=========================================================================== * Description: Loops back the packet. * Parameters: netif - The interface the packet was sent to. * pkt - The packet to loopback. pkt->start is the offset to the * IP header. * Returns: 0 = success, 0< = error code. * */ IP_STATIC int ipnet_loopback_drv_output(Ipcom_netif *netif, Ipcom_pkt *pkt) { int ret = 0; /* The ipcom_pkt_input_queue() frees the packet if it cannot be queued, add a reference so that packet is still allocated if that happens */ IPCOM_PKT_ADD_REF(pkt); IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_RX); IP_BIT_SET(pkt->flags, IPCOM_PKT_FLAG_LOOPED_BACK); ret = ipcom_pkt_input_queue(netif, pkt); if (IP_UNLIKELY(ret != -IP_ERRNO_EWOULDBLOCK)) { ip_assert(IPCOM_PKT_HAS_MULTIPLE_OWNERS(pkt)); ipcom_pkt_free(pkt); } return ret; }
/* *=========================================================================== * ipcom_cmd_smptest_server *=========================================================================== * Description: This is the server part of the smptest command * Parameters: The address we should listen to, and info about how many sockets * we should use. * Returns: 0 on success. -1 on failure. */ IP_STATIC int ipcom_cmd_smptest_server() { Ipcom_proc_attr attr; unsigned int i; Ipcom_proc *proc; int retval; spawn_number_server = 0; if ( 0 != ipcom_sem_create( &sem_wait_server, 0 ) ) { ipcom_printf("ipcom_sem_create failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return -1; } ipcom_atomic_set( &num_wait_server, smp_opt_server.num_sock ); ipcom_atomic_set( &listen_wait, smp_opt_server.num_sock ); ipcom_proc_attr_init(&attr); attr.priority = IPCOM_PRIORITY_DEFAULT; /* Hacky hacky way to write from a task.. copied from ipcom_mshell.c */ proc = ipcom_proc_self(); ip_assert( proc != 0 ); server_out = proc->shell_fd; for ( i = 0;i < smp_opt_server.num_sock;++i ) { retval = ipcom_proc_acreate("ipcom_cmd_smptest_server_spawn", (Ipcom_proc_func)ipcom_cmd_smptest_server_spawn, &attr, 0 ); if (retval != 0) { ipcom_printf( "Error spawning smptest server"IP_LF ); return retval; } } ipcom_sem_wait( sem_wait_server ); ipcom_sem_delete( &sem_wait_server ); return 0; }
/* *=========================================================================== * ipcom_hash_resize *=========================================================================== * Description: Doubles the size or cuts the size in half. * Parameters: head - The head of the hash table. * increase - Set to IP_TRUE to double the size, IP_FALSE * to half the size. * Returns: IPCOM_SUCCESS or IPCOM_ERR_NO_MEMORY if not enough memory * could be allocated. * */ IP_STATIC Ip_err ipcom_hash_resize(Ipcom_hash *head, Ip_bool increase) { void **old_hash_table; int old_size; int i; Ip_err err; old_hash_table = head->table; old_size = head->size; /* Keep the size odd since that will increase the chance of the high bits of the hash value to affect the low bits which is used as index in the hash table */ if (increase) head->size = (head->size << 1) + 3; else head->size = (head->size >> 1) - 1; head->table = IPCOM_CALLOC_STATIC(head->size, sizeof(*head->table)); if (head->table == IP_NULL) { IPCOM_LOG2(ERR, "ipcom_hash_resize :: ipcom_calloc(%d, %d) failed", head->size, sizeof(*head->table)); head->size = old_size; head->table = old_hash_table; return IPCOM_ERR_NO_MEMORY; } head->elem = 0; for (i = 0; i < old_size; i++) if (old_hash_table[i] != IP_NULL) { err = ipcom_hash_add(head, old_hash_table[i]); ip_assert(err == IPCOM_SUCCESS); (void)err; } IPCOM_FREE_STATIC(old_hash_table); return IPCOM_SUCCESS; }
/* *=========================================================================== * ipnet_pkt_queue_mbc_remove *=========================================================================== * Description: Removes an queue from a container queue and put pack a * default queue type. * Parameters: c - The MBC parent queue for 'q'. * q - The queue to remove. * Returns: 0 = success, <0 = error code (-IP_ERRNO_xxx) * */ IP_STATIC int ipnet_pkt_queue_mbc_remove(Ipnet_pkt_queue_mbc *c, Ipnet_pkt_queue *q) { Ip_u32 band; ip_assert(c->hdr.id == q->parent_id); for (band = 0; band < c->number_of_bands; band++) { if (q == c->bands[band]) { int ret = ipnet_pkt_queue_mbc_insert_default_queue(c, band); if (ret < 0) IPCOM_LOG3(WARNING, "MBC: Failed to replace %s:%d with a fifo in remove(): %s", q->type, q->id, ipcom_strerror(-ret)); return ret; } } return -IP_ERRNO_ESRCH; }
IP_FASTTEXT IP_PUBLIC void ipcom_spinlock_lock(Ipcom_spinlock sl_handle) { #ifdef IPCOM_USE_SMP Ipcom_vxworks_spinlock_t *sl = (Ipcom_vxworks_spinlock_t*) sl_handle; #ifdef IPCOM_SPINLOCK_BUSY_PERSIST int i; atomicVal_t count; try_again: if (vxCas(&sl->count, 1, 0)) goto got_it; for (i = IPCOM_SPINLOCK_BUSY_PERSIST; i > 0; --i) { count = vxAtomicGet(&sl->count); if (count < 0) break; if (count == 1) goto try_again; } #endif /* IPCOM_SPINLOCK_BUSY_PERSIST */ if (vxAtomicDec(&sl->count) <= 0) /* Contention for this lock, let's sleep until the lock gets available */ semTake(sl->sem, WAIT_FOREVER); else { #ifdef IPCOM_SPINLOCK_BUSY_PERSIST got_it: #endif /* prevent load/store re-ordering beyond this point */ VX_MEM_BARRIER_RW(); } #else IPCOM_UNUSED_ARG(sl_handle); ip_assert(sl_handle == IPCOM_SPINLOCK_TAG); taskLock(); #endif }
/* *=========================================================================== * ipcom_list_insert_last *=========================================================================== * Description: Insert list 'entry' last in the list 'head'. * Parameters: head - Pointer to the list header to insert 'entry' in. * entry - Pointer to the list entry to insert last. * Returns: . * */ IP_PUBLIC void ipcom_list_insert_last(Ipcom_list *head, Ipcom_list *entry) { #ifdef IP_ASSERT { Ipcom_list *tmp; for(tmp = head->next; tmp != head; tmp = tmp->next) ip_assert(entry != tmp); } #endif entry->prev = head->prev; entry->next = head; entry->next->prev = entry; entry->prev->next = entry; entry->head = head; head->size++; ipcom_list_assert(head, entry); }
/* *=========================================================================== * ipnet_vrrp_del_addr *=========================================================================== * Description: Deletes a virtual router address. * Parameters: netif - The network interface the VRIP was assigned to. * vrid - The VRID the address was assigned to. * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_vrrp_del_addr(Ipnet_netif *netif, Ip_u8 vrid, struct Ip_in_addr addr) { Ipnet_vrrp_addr_t *addr_entry; int i; ip_assert(ipnet->vrrp_addrs != IP_NULL); addr_entry = ipnet_vrrp_get_addr_entry(netif, vrid); if (addr_entry == IP_NULL) return -IP_ERRNO_ESRCH; i = ipnet_vrrp_addr_index(addr_entry, addr); if (i < 0) return -IP_ERRNO_ESRCH; IPCOM_LOG2(INFO, "VRRP: deleted address %s on %s", ipcom_inet_ntop(IP_AF_INET, &addr, ipnet->log_buf, sizeof(ipnet->log_buf)), netif->ipcom.name); if (--addr_entry->num_addrs > 0) { for (;i < addr_entry->num_addrs; i++) addr_entry->addrs[i] = addr_entry->addrs[i + 1]; } else { (void)ipcom_hash_remove(ipnet->vrrp_addrs, addr_entry); ipcom_free(addr_entry); if (ipnet->vrrp_addrs->elem == 0) { ipcom_hash_delete(ipnet->vrrp_addrs); ipnet->vrrp_addrs = IP_NULL; } } return 0; }