1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Internet Protocol (IP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "tx_thread.h"
29 #include "nx_ip.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _nx_ip_raw_packet_receive PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Yuxin Zhou, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function retrieves the first packet from the received raw */
45 /* packet list and returns it to the caller. If no packet is present */
46 /* the routine may optionally suspend waiting on the list for a */
47 /* packet. */
48 /* */
49 /* INPUT */
50 /* */
51 /* ip_ptr IP control block pointer */
52 /* packet_ptr Pointer to return allocated */
53 /* packet */
54 /* wait_option Suspension option */
55 /* */
56 /* OUTPUT */
57 /* */
58 /* status Completion status */
59 /* */
60 /* CALLS */
61 /* */
62 /* _tx_thread_system_suspend Suspend thread */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* Application Code */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
73 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* */
76 /**************************************************************************/
_nx_ip_raw_packet_receive(NX_IP * ip_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)77 UINT _nx_ip_raw_packet_receive(NX_IP *ip_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
78 {
79 TX_INTERRUPT_SAVE_AREA
80
81 UINT status; /* Return status */
82 TX_THREAD *thread_ptr; /* Working thread pointer */
83 NX_PACKET *work_ptr; /* Working packet pointer */
84
85 #ifdef TX_ENABLE_EVENT_TRACE
86 TX_TRACE_BUFFER_ENTRY *trace_event;
87 ULONG trace_timestamp;
88 #endif
89
90
91 /* If trace is enabled, insert this event into the trace buffer. */
92 NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_RAW_PACKET_RECEIVE, ip_ptr, 0, wait_option, 0, NX_TRACE_IP_EVENTS, &trace_event, &trace_timestamp);
93
94 /* Disable interrupts to get a packet from the pool. */
95 TX_DISABLE
96
97 /* Determine if there is an available packet. */
98 if (ip_ptr -> nx_ip_raw_received_packet_count)
99 {
100
101 /* Yes, a packet is available. Decrement the raw packet receive count. */
102 ip_ptr -> nx_ip_raw_received_packet_count--;
103
104 /* Pickup the first raw packet pointer. */
105 work_ptr = ip_ptr -> nx_ip_raw_received_packet_head;
106
107 /* Modify the available list to point at the next packet in the pool. */
108 ip_ptr -> nx_ip_raw_received_packet_head = work_ptr -> nx_packet_queue_next;
109
110 /* Determine if the tail pointer points to the same packet. */
111 if (ip_ptr -> nx_ip_raw_received_packet_tail == work_ptr)
112 {
113
114 /* Yes, just set tail pointer to NULL since we must be at the end of the queue. */
115 ip_ptr -> nx_ip_raw_received_packet_tail = NX_NULL;
116 }
117
118 /* Place the raw packet pointer in the return destination. */
119 *packet_ptr = work_ptr;
120
121 /* Update the trace event with the status. */
122 NX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, NX_TRACE_IP_RAW_PACKET_RECEIVE, 0, *packet_ptr, 0, 0);
123
124 /* Set status to success. */
125 status = NX_SUCCESS;
126 }
127 else
128 {
129
130 /* Determine if the request specifies suspension. */
131 if (wait_option)
132 {
133
134 /* Prepare for suspension of this thread. */
135
136 /* Pickup thread pointer. */
137 thread_ptr = _tx_thread_current_ptr;
138
139 /* Setup cleanup routine pointer. */
140 thread_ptr -> tx_thread_suspend_cleanup = _nx_ip_raw_packet_cleanup;
141
142 /* Setup cleanup information, i.e. this IP control
143 block. */
144 thread_ptr -> tx_thread_suspend_control_block = (void *)ip_ptr;
145
146 /* Save the return packet pointer address as well. */
147 thread_ptr -> tx_thread_additional_suspend_info = (void *)packet_ptr;
148
149 /* Setup suspension list. */
150 if (ip_ptr -> nx_ip_raw_packet_suspension_list)
151 {
152
153 /* This list is not NULL, add current thread to the end. */
154 thread_ptr -> tx_thread_suspended_next =
155 ip_ptr -> nx_ip_raw_packet_suspension_list;
156 thread_ptr -> tx_thread_suspended_previous =
157 (ip_ptr -> nx_ip_raw_packet_suspension_list) -> tx_thread_suspended_previous;
158 ((ip_ptr -> nx_ip_raw_packet_suspension_list) -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr;
159 (ip_ptr -> nx_ip_raw_packet_suspension_list) -> tx_thread_suspended_previous = thread_ptr;
160 }
161 else
162 {
163
164 /* No other threads are suspended. Setup the head pointer and
165 just setup this threads pointers to itself. */
166 ip_ptr -> nx_ip_raw_packet_suspension_list = thread_ptr;
167 thread_ptr -> tx_thread_suspended_next = thread_ptr;
168 thread_ptr -> tx_thread_suspended_previous = thread_ptr;
169 }
170
171 /* Increment the suspended thread count. */
172 ip_ptr -> nx_ip_raw_packet_suspended_count++;
173
174 /* Set the state to suspended. */
175 thread_ptr -> tx_thread_state = TX_TCP_IP;
176
177 /* Set the suspending flag. */
178 thread_ptr -> tx_thread_suspending = TX_TRUE;
179
180 /* Temporarily disable preemption. */
181 _tx_thread_preempt_disable++;
182
183 /* Save the timeout value. */
184 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
185
186 /* Restore interrupts. */
187 TX_RESTORE
188
189 /* Call actual thread suspension routine. */
190 _tx_thread_system_suspend(thread_ptr);
191
192 /* Update the trace event with the status. */
193 NX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, NX_TRACE_IP_RAW_PACKET_RECEIVE, 0, *packet_ptr, 0, 0);
194
195 /* Return the completion status. */
196 return(thread_ptr -> tx_thread_suspend_status);
197 }
198 else
199 {
200
201 /* Immediate return, return error completion. */
202 status = NX_NO_PACKET;
203 }
204 }
205
206 /* Restore interrupts. */
207 TX_RESTORE
208
209 /* Return completion status. */
210 return(status);
211 }
212
213