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 /** Address Resolution Protocol (ARP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_arp.h"
29 #include "nx_ip.h"
30 #include "nx_packet.h"
31
32 #ifndef NX_DISABLE_IPV4
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _nx_arp_queue_send PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Yuxin Zhou, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function sends packets from the ARP queue. */
46 /* */
47 /* INPUT */
48 /* */
49 /* ip_ptr Pointer to IP instance */
50 /* arp_ptr Pointer to ARP entry */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* _nx_packet_transmit_release Release ARP queued packet */
59 /* (nx_ip_fragment_processing) Fragment processing */
60 /* (ip_interface_link_driver_entry) User supplied link driver */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* _nx_arp_static_entry_create Create static entry */
65 /* _nx_arp_dynamic_entry_set Set dynamic entry */
66 /* _nx_arp_packet_receive Process the ARP packet */
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_arp_queue_send(NX_IP * ip_ptr,NX_ARP * arp_ptr)77 VOID _nx_arp_queue_send(NX_IP *ip_ptr, NX_ARP *arp_ptr)
78 {
79
80 TX_INTERRUPT_SAVE_AREA
81 NX_PACKET *queued_list_head;
82 NX_PACKET *packet_ptr;
83 NX_IP_DRIVER driver_request;
84
85 /* Initialize the queued list head to NULL. */
86 queued_list_head = NX_NULL;
87
88 /* Determine if this ARP entry has a packet queued up for sending. */
89
90 /* Disable interrupts before checking. */
91 TX_DISABLE
92
93 /* Look at the ARP packet queue pointer. */
94 if (arp_ptr -> nx_arp_packets_waiting)
95 {
96
97 /* Pickup the packet pointer and clear the ARP queue pointer. */
98 queued_list_head = arp_ptr -> nx_arp_packets_waiting;
99 arp_ptr -> nx_arp_packets_waiting = NX_NULL;
100 }
101
102 /* Restore previous interrupt posture. */
103 TX_RESTORE
104
105 /* Are there any packets queued to send? */
106 while (queued_list_head)
107 {
108
109 /* Pickup the first entry on the list. */
110 packet_ptr = queued_list_head;
111
112 /* Move to the next entry on the ARP packet queue. */
113 queued_list_head = queued_list_head -> nx_packet_queue_next;
114
115 /* Clear the packet's queue next pointer. */
116 packet_ptr -> nx_packet_queue_next = NX_NULL;
117
118 packet_ptr -> nx_packet_address.nx_packet_interface_ptr = arp_ptr -> nx_arp_ip_interface;
119
120 /* Build the driver request packet. */
121 driver_request.nx_ip_driver_physical_address_msw = arp_ptr -> nx_arp_physical_address_msw;
122 driver_request.nx_ip_driver_physical_address_lsw = arp_ptr -> nx_arp_physical_address_lsw;
123 driver_request.nx_ip_driver_ptr = ip_ptr;
124 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
125 driver_request.nx_ip_driver_packet = packet_ptr;
126 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
127
128 /* Determine if fragmentation is needed. */
129 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
130 {
131
132 #ifndef NX_DISABLE_FRAGMENTATION
133 /* Fragmentation is needed, call the fragment routine if available. */
134 if (ip_ptr -> nx_ip_fragment_processing)
135 {
136
137 /* Call the IP fragment processing routine. */
138 (ip_ptr -> nx_ip_fragment_processing)(&driver_request);
139 }
140 else
141 {
142 #endif /* NX_DISABLE_FRAGMENTATION */
143
144 #ifndef NX_DISABLE_IP_INFO
145
146 /* Increment the IP send packets dropped count. */
147 ip_ptr -> nx_ip_send_packets_dropped++;
148 #endif
149
150 /* Just release the packet. */
151 _nx_packet_transmit_release(packet_ptr);
152 #ifndef NX_DISABLE_FRAGMENTATION
153 }
154 #endif /* NX_DISABLE_FRAGMENTATION */
155 }
156 else
157 {
158
159 #ifndef NX_DISABLE_IP_INFO
160
161 /* Increment the IP packet sent count. */
162 ip_ptr -> nx_ip_total_packets_sent++;
163
164 /* Increment the IP bytes sent count. */
165 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - (ULONG)sizeof(NX_IPV4_HEADER);
166 #endif
167
168 /* If trace is enabled, insert this event into the trace buffer. */
169 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_PACKET_SEND, ip_ptr, packet_ptr, packet_ptr -> nx_packet_length, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
170
171 /* Send the queued IP packet out on the network via the attached driver. */
172 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry)(&driver_request);
173 }
174 }
175 }
176 #endif /* !NX_DISABLE_IPV4 */
177
178