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 #include "nx_packet.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _nx_ip_raw_packet_processing PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Yuxin Zhou, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function processes a received raw IP packet from the */
46 /* _nx_ip_packet_receive function and either queues it or gives it to */
47 /* the first suspended thread waiting for a raw IP packet. */
48 /* */
49 /* INPUT */
50 /* */
51 /* ip_ptr Pointer to IP control block */
52 /* packet_ptr Pointer to packet to send */
53 /* protocol The upper layer protocol */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* None */
58 /* */
59 /* CALLS */
60 /* */
61 /* _tx_thread_system_resume Resume suspended thread */
62 /* _nx_packet_release Release the raw packet */
63 /* [nx_ip_raw_packet_filter] User-defined packet filter */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _nx_ip_packet_receive Packet receive processing */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
74 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* */
77 /**************************************************************************/
_nx_ip_raw_packet_processing(NX_IP * ip_ptr,ULONG protocol,NX_PACKET * packet_ptr)78 UINT _nx_ip_raw_packet_processing(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr)
79 {
80
81 TX_INTERRUPT_SAVE_AREA
82 TX_THREAD *thread_ptr;
83
84 /* Add debug information. */
85 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
86
87 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
88 /* If raw packet filter is installed */
89 if (ip_ptr -> nx_ip_raw_packet_filter)
90 {
91 if ((ip_ptr -> nx_ip_raw_packet_filter)(ip_ptr, (protocol >> 16) & 0xFF, packet_ptr) != NX_SUCCESS)
92 {
93 return(1); /* Raw filter did not consume this packet. Allow the caller to process this packet. */
94 }
95 else
96 {
97 return(NX_SUCCESS); /* The caller should not process this packet. */
98 }
99 }
100 #else
101 NX_PARAMETER_NOT_USED(protocol);
102 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
103
104 /* Disable interrupts. */
105 TX_DISABLE
106
107 /* Determine if there is a thread waiting for the IP packet. If so, just
108 give the packet to the waiting thread. */
109 thread_ptr = ip_ptr -> nx_ip_raw_packet_suspension_list;
110 if (thread_ptr)
111 {
112
113 /* Yes, a thread is suspended on the raw IP packet queue. */
114
115 /* See if this is the only suspended thread on the list. */
116 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
117 {
118
119 /* Yes, the only suspended thread. */
120
121 /* Update the head pointer. */
122 ip_ptr -> nx_ip_raw_packet_suspension_list = NX_NULL;
123 }
124 else
125 {
126
127 /* At least one more thread is on the same expiration list. */
128
129 /* Update the list head pointer. */
130 ip_ptr -> nx_ip_raw_packet_suspension_list = thread_ptr -> tx_thread_suspended_next;
131
132 /* Update the links of the adjacent threads. */
133 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous =
134 thread_ptr -> tx_thread_suspended_previous;
135 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next =
136 thread_ptr -> tx_thread_suspended_next;
137 }
138
139 /* Decrement the suspension count. */
140 ip_ptr -> nx_ip_raw_packet_suspended_count--;
141
142 /* Prepare for resumption of the first thread. */
143
144 /* Clear cleanup routine to avoid timeout. */
145 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
146
147 /* Temporarily disable preemption. */
148 _tx_thread_preempt_disable++;
149
150 /* Add debug information. */
151 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
152
153 /* Restore interrupts. */
154 TX_RESTORE
155
156 /* Return this packet pointer to the suspended thread waiting for
157 a block. */
158 *((NX_PACKET **)thread_ptr -> tx_thread_additional_suspend_info) = packet_ptr;
159
160 /* Put return status into the thread control block. */
161 thread_ptr -> tx_thread_suspend_status = NX_SUCCESS;
162
163 /* Resume thread. */
164 _tx_thread_system_resume(thread_ptr);
165 }
166 else
167 {
168
169 /* The packet is queued only if the number of packets in the queue does not exceed
170 user-speicified limit. */
171 if (ip_ptr -> nx_ip_raw_received_packet_count >= ip_ptr -> nx_ip_raw_received_packet_max)
172 {
173 _nx_packet_release(packet_ptr);
174 return(NX_SUCCESS); /* This packet has been released so the caller should not
175 further process it. */
176 }
177
178
179
180 /* Otherwise, queue the raw IP packet in a FIFO manner on the raw packet list. */
181
182 /* Clear the next packet pointer. */
183 packet_ptr -> nx_packet_queue_next = NX_NULL;
184
185 /* Determine if the queue is empty. */
186 if (ip_ptr -> nx_ip_raw_received_packet_tail)
187 {
188
189 /* List is not empty, place the raw packet at the end of the raw packet list. */
190 (ip_ptr -> nx_ip_raw_received_packet_tail) -> nx_packet_queue_next = packet_ptr;
191 ip_ptr -> nx_ip_raw_received_packet_tail = packet_ptr;
192 }
193 else
194 {
195
196 /* This is the first entry on the queue so set the head and tail pointers. */
197 ip_ptr -> nx_ip_raw_received_packet_head = packet_ptr;
198 ip_ptr -> nx_ip_raw_received_packet_tail = packet_ptr;
199 }
200
201 /* Increment the raw packet received count. */
202 ip_ptr -> nx_ip_raw_received_packet_count++;
203
204 /* Restore interrupts. */
205 TX_RESTORE
206 }
207
208 /* The packet is enqueued, therefore return NX_SUCCESS so the stack does not
209 further process this packet. */
210 return(NX_SUCCESS);
211 }
212
213