/* *=========================================================================== * ipnet_udp_fast_deliver_data *=========================================================================== * Description: Deliver an UDP packet to a socket that is bound to a unicast * address. * Parameters: sock - The socket the packet will be delivered to. * pkt - The UDP packet to deliver. * nat_t - NAT_T processing. * Returns: IP_TRUE - The fast path processing was successful. * IP_FALSE - Need to use the normal receive path. * */ IP_STATIC Ip_bool ipnet_udp_fast_deliver_data(Ipnet_socket *sock, Ipcom_pkt *pkt, int *nat_t) { Ipnet_pkt_udp *udp_hdr; int original_start = pkt->start; Ipcom_socket_eventcb event_cb = sock->ipcom.event_cb; udp_hdr = (Ipnet_pkt_udp*) &pkt->data[pkt->tlstart]; if (IP_UNLIKELY(pkt->end - pkt->tlstart < IPNET_UDP_HDR_SIZE || pkt->end - pkt->tlstart < ip_ntohs(udp_hdr->ulen))) return IP_FALSE; if (udp_hdr->sum != 0 && IP_BIT_ISFALSE(pkt->flags, IPCOM_PKT_FLAG_LOOPED_BACK)) { Ip_u16 chksum; /* Only check packets that was not created locally */ #ifdef IPCOM_USE_HW_CHECKSUM_RX if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_HW_CHECKSUM)) chksum = 0; else if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_TL_CHECKSUM)) chksum = ipcom_in_checksum_finish(pkt->chk); else #endif /* IPCOM_USE_HW_CHECKSUM_RX */ { pkt->chk += ipcom_in_checksum_update(&pkt->data[pkt->tlstart], (Ip_size_t) ip_ntohs(udp_hdr->ulen)); chksum = ipcom_in_checksum_finish(pkt->chk); } if (IP_UNLIKELY(chksum != 0)) return IP_FALSE; } pkt->fd = sock->ipcom.fd; pkt->start = pkt->tlstart + IPNET_UDP_HDR_SIZE; if (IP_UNLIKELY(ipnet_udp_encapsulation(sock, pkt, nat_t))) { /* Continue processing */ ipcom_pkt_set_info(pkt, IPNET_PKT_INFO_ENCAP_UDP, sizeof(*udp_hdr), udp_hdr); pkt->start = original_start; return IP_FALSE; } if (ipnet_queue_received_packet(pkt, sock) != 0) { pkt->start = original_start; return IP_FALSE; } if (event_cb != IP_NULL) event_cb(&sock->ipcom, pkt, IP_SOEVENT_CB_INPKT); IPCOM_MIB2(udpInDatagrams++); IPCOM_MIB2_U64_INC(udpHCInDatagrams); return IP_TRUE; }
static void cad_q6dec_session_async_callback(struct cadi_evt_struct_type *evt, void *data) { struct q6dec_session_data *self = (struct q6dec_session_data *)data; struct q6dec_sesson_buffer_node *node = NULL; struct q6dec_sesson_buffer_node *prev_node = NULL; if (CAD_EVT_STATUS_BUF_DONE != evt->cad_event_header.cmd_event_id) /* unknow event, and do nothing */ return; mutex_lock(&self->session_mutex); node = self->used_buf_list; while (node) { if (node->buf == evt->cad_event_data.buf_data.buffer) { if (prev_node == NULL) { /* first node */ self->used_buf_list = node->next; break; } prev_node->next = node->next; break; } prev_node = node; node = node->next; } if (node) { D("========>return buffer number %d, 0x%x\n", self->ret_counter, (u32) node); self->ret_counter++; /* find match, add free buffer to the free list */ node->next = self->free_buf_list; self->free_buf_list = node; if (self->need_buffer_done) { D("Signal buffer done event\n"); up(&self->buf_done_sem); } if (self->used_buf_list == NULL) { D("Signal all buffer done event\n"); up(&self->all_buf_done_sem); } } mutex_unlock(&self->session_mutex); if (event_cb != NULL) event_cb(); return; }
/* *=========================================================================== * ipnet_udp_input *=========================================================================== * Description: Input handler for packet to UDP sockets. This function will * NOT free the packet if the operation fails. * Parameters: pkt - The received packet, must be freed by the called if * this function fails. * is_multicast - Set to IP_TRUE if the packet was sent to a * multicast address. * proto - The protocol number. * src_addr - The address (Ipv4 or IPv6) of the sender. * dst_addr - The address (Ipv4 or IPv6) of the receiver (this system). * socklookup - A pointer to a function that can return the socket * that is associated with this packet. * nat_t - NAT traversal; if used. * Returns: 0 >= number of matching sockets, <0 = error code * */ IP_GLOBAL int ipnet_udp_input(Ipcom_pkt *pkt, Ip_bool is_multicast, IP_CONST void* src_addr, IP_CONST void* dst_addr, Ipnet_sock_lookup_f socklookup, int *nat_t) { Ipnet_pkt_udp *udp_hdr; int retval; int ulen_h; Ipnet_socket *sock; Ip_u16 src_port; Ip_u16 dst_port; Ip_bool pkt_no_rx_cache; IPCOM_WV_MARKER_1 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_VERBOSE, 1, 3, IPCOM_WV_NETDEVENT_START, ipnet_udp_input, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input++); IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_UDP_INPUT); if (IP_UNLIKELY(pkt->end - pkt->start < IPNET_UDP_HDR_SIZE)) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 4, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_BADHLEN, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_hdr_trunc++); IPCOM_MIB2(udpInErrors++); return -IP_ERRNO_EINVAL; } udp_hdr = (Ipnet_pkt_udp*) &pkt->data[pkt->start]; ulen_h = ip_ntohs(udp_hdr->ulen); src_port = ip_ntohs(udp_hdr->sport); dst_port = ip_ntohs(udp_hdr->dport); if (IP_UNLIKELY(pkt->end - pkt->start < ulen_h)) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 5, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_BADLEN, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_hdr_trunc++); IPCOM_MIB2(udpInErrors++); return -IP_ERRNO_EINVAL; } pkt->end = pkt->start + ulen_h; if (udp_hdr->sum != 0 && IP_BIT_ISFALSE(pkt->flags, IPCOM_PKT_FLAG_LOOPED_BACK)) { Ip_u16 chksum; /* Only check packets that was not created locally */ #ifdef IPCOM_USE_HW_CHECKSUM_RX if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_HW_CHECKSUM)) chksum = 0; else if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_TL_CHECKSUM)) chksum = ipcom_in_checksum_finish(pkt->chk); else #endif /* IPCOM_USE_HW_CHECKSUM_RX */ { pkt->chk += ipcom_in_checksum_update(&pkt->data[pkt->start], (Ip_size_t) ulen_h); chksum = ipcom_in_checksum_finish(pkt->chk); } if (IP_UNLIKELY(chksum != 0)) { /* Wrong checksum */ IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 6, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_BADSUM, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_badchksum++); IPCOM_MIB2(udpInErrors++); return -IP_ERRNO_EINVAL; } } /* Move the start to beginning of application data */ pkt->start += IPNET_UDP_HDR_SIZE; if (is_multicast) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_INFO, 1, 7, IPCOM_WV_NETDEVENT_INFO, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_RECEIVE, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_multicast++); retval = ipnet_raw_input(pkt, IP_FALSE, IP_IPPROTO_UDP, src_addr, src_port, dst_addr, dst_port, socklookup); if (retval >= 0) { /* The packet must be freed unlesss an error occured */ ipcom_pkt_free(pkt); IPCOM_MIB2(udpInDatagrams++); IPCOM_MIB2_U64_INC(udpHCInDatagrams); } else { IPCOM_MIB2(udpInErrors++); } return retval; } sock = socklookup(pkt->vr_index, IP_IPPROTO_UDP, dst_addr, dst_port, src_addr, src_port); if (sock == IP_NULL) /* No matching socket, try the wildcard group */ sock = socklookup(IPCOM_VR_ANY, IP_IPPROTO_UDP, dst_addr, dst_port, src_addr, src_port); if (sock != IP_NULL) { Ipcom_socket_eventcb event_cb = sock->ipcom.event_cb; /* Verify NAT traversal */ if (IP_UNLIKELY(ipnet_udp_encapsulation(sock, pkt, nat_t))) { ipcom_pkt_set_info(pkt, IPNET_PKT_INFO_ENCAP_UDP, sizeof(*udp_hdr), udp_hdr); pkt->start -= IPNET_UDP_HDR_SIZE; return 0; } IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_INFO, 1, 8, IPCOM_WV_NETDEVENT_INFO, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_RECEIVE, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_sock_match++); pkt->fd = sock->ipcom.fd; pkt_no_rx_cache = IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_NO_RX_CACHE); retval = ipnet_queue_received_packet(pkt, sock); if (retval < 0) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 9, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_QUEUE_FULL, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_queue_pkt_err++); IPCOM_MIB2(udpInErrors++); return retval; } IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_INFO, 1, 10, IPCOM_WV_NETDEVENT_INFO, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_RECEIVE, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_queue_pkt_ok++); if (event_cb != IP_NULL) event_cb(&sock->ipcom, pkt, IP_SOEVENT_CB_INPKT); IPCOM_MIB2(udpInDatagrams++); IPCOM_MIB2_U64_INC(udpHCInDatagrams); if (IP_BIT_ISFALSE(sock->flags, IPNET_SOCKET_FLAG_RX_CACHED) && !pkt_no_rx_cache) ipnet_sock_add_to_rx_cache(sock, src_addr, src_port, dst_addr, dst_port, ipnet_udp_fast_deliver_data); return 1; } else { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 13, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_NOPORT, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_sock_nomatch++); IPCOM_MIB2(udpNoPorts++); } IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 14, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_NOPORT, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_econnrefused++); return -IP_ERRNO_ECONNREFUSED; }