2 * FreeRTOS Kernel V10.3.0
\r
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
28 /* WinPCap includes. */
\r
30 #include "remote-ext.h"
\r
33 #include "net/uip.h"
\r
34 #include "net/uip_arp.h"
\r
35 #include "net/clock-arch.h"
\r
37 /* FreeRTOS includes. */
\r
38 #include "FreeRTOS.h"
\r
43 * Query the computer the simulation is being executed on to find the network
\r
44 * interfaces it has installed.
\r
46 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );
\r
49 * Open the network interface. The number of the interface to be opened is set
\r
50 * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
52 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
\r
55 * Configure the capture filter to allow blocking reads, and to filter out
\r
56 * packets that are not of interest to this demo.
\r
58 static void prvConfigureCaptureBehaviour( void );
\r
60 pcap_t *pxOpenedInterfaceHandle = NULL;
\r
61 LARGE_INTEGER freq, sys_start_time;
\r
63 #define archNUM_BUFFERS 5
\r
64 #define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )
\r
66 static void prvInterruptSimulator( void *pvParameters );
\r
68 static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];
\r
69 static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];
\r
71 static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };
\r
72 static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;
\r
74 unsigned char *uip_buf = NULL;
\r
75 char cErrorBuffer[PCAP_ERRBUF_SIZE];
\r
77 void vNetifTx( void )
\r
79 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
80 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
82 /*-----------------------------------------------------------*/
\r
84 UBaseType_t uxNetifRx( void )
\r
86 UBaseType_t xDataLen;
\r
87 unsigned char *pucTemp;
\r
89 /* Check there is really data available. */
\r
90 xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];
\r
91 if( xDataLen != 0L )
\r
94 /* The buffer pointed to by uip_buf is going to change. Remember which
\r
95 buffer uip_buf is currently pointing to. */
\r
98 /* Point uip_buf at the next buffer that contains data. */
\r
99 uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];
\r
101 /* The buffer pointed to by
\r
102 pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by
\r
103 uip_buf, but the buffer uip_buf was pointing to on entry to this
\r
104 function is free. Set
\r
105 pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free
\r
107 pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;
\r
108 lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;
\r
110 ucNextBufferToProcess++;
\r
111 if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )
\r
113 ucNextBufferToProcess = 0L;
\r
119 /*-----------------------------------------------------------*/
\r
121 BaseType_t xNetifInit( void )
\r
124 pcap_if_t *pxAllNetworkInterfaces;
\r
126 /* Allocate a free buffer to each buffer pointer. */
\r
127 for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )
\r
129 pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );
\r
132 /* Start with uip_buf pointing to a buffer that is not referenced from the
\r
133 pucEthernetBufferPointers[] array. */
\r
134 uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );
\r
136 /* Query the computer the simulation is being executed on to find the
\r
137 network interfaces it has installed. */
\r
138 pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();
\r
140 /* Open the network interface. The number of the interface to be opened is
\r
141 set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
142 Calling this function will set the pxOpenedInterfaceHandle variable. If,
\r
143 after calling this function, pxOpenedInterfaceHandle is equal to NULL, then
\r
144 the interface could not be opened. */
\r
145 if( pxAllNetworkInterfaces != NULL )
\r
147 prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
\r
153 /*-----------------------------------------------------------*/
\r
155 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
\r
157 pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
\r
158 long lInterfaceNumber = 1;
\r
160 if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
\r
162 printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );
\r
163 pxAllNetworkInterfaces = NULL;
\r
166 if( pxAllNetworkInterfaces != NULL )
\r
168 /* Print out the list of network interfaces. The first in the list
\r
169 is interface '1', not interface '0'. */
\r
170 for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )
\r
172 printf( "%d. %s", lInterfaceNumber, xInterface->name );
\r
174 if( xInterface->description != NULL )
\r
176 printf( " (%s)\r\n", xInterface->description );
\r
180 printf( " (No description available)\r\n") ;
\r
183 lInterfaceNumber++;
\r
187 if( lInterfaceNumber == 1 )
\r
189 /* The interface number was never incremented, so the above for() loop
\r
190 did not execute meaning no interfaces were found. */
\r
191 printf( " \r\nNo network interfaces were found.\r\n" );
\r
192 pxAllNetworkInterfaces = NULL;
\r
195 printf( "\r\nThe interface that will be opened is set by configNETWORK_INTERFACE_TO_USE which should be defined in FreeRTOSConfig.h\r\n" );
\r
196 printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );
\r
198 if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )
\r
200 printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );
\r
202 if( pxAllNetworkInterfaces != NULL )
\r
204 /* Free the device list, as no devices are going to be opened. */
\r
205 pcap_freealldevs( pxAllNetworkInterfaces );
\r
206 pxAllNetworkInterfaces = NULL;
\r
210 return pxAllNetworkInterfaces;
\r
212 /*-----------------------------------------------------------*/
\r
214 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
\r
216 pcap_if_t *xInterface;
\r
219 /* Walk the list of devices until the selected device is located. */
\r
220 xInterface = pxAllNetworkInterfaces;
\r
221 for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )
\r
223 xInterface = xInterface->next;
\r
226 /* Open the selected interface. */
\r
227 pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */
\r
228 UIP_CONF_BUFFER_SIZE, /* The size of the packet to capture. */
\r
229 PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscious mode as the MAC and
\r
230 IP address is going to be "simulated", and
\r
231 not be the real MAC and IP address. This allows
\r
232 trafic to the simulated IP address to be routed
\r
233 to uIP, and trafic to the real IP address to be
\r
234 routed to the Windows TCP/IP stack. */
\r
235 0xfffffffL, /* The read time out. This is going to block
\r
236 until data is available. */
\r
237 NULL, /* No authentication is required as this is
\r
238 not a remote capture session. */
\r
242 if ( pxOpenedInterfaceHandle == NULL )
\r
244 printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );
\r
248 /* Configure the capture filter to allow blocking reads, and to filter
\r
249 out packets that are not of interest to this demo. */
\r
250 prvConfigureCaptureBehaviour();
\r
253 /* The device list is no longer required. */
\r
254 pcap_freealldevs( pxAllNetworkInterfaces );
\r
256 /*-----------------------------------------------------------*/
\r
258 static void prvConfigureCaptureBehaviour( void )
\r
260 struct bpf_program xFilterCode;
\r
261 const long lMinBytesToCopy = 10L, lBlocking = 0L;
\r
262 unsigned long ulNetMask;
\r
264 /* Unblock a read as soon as anything is received. */
\r
265 pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );
\r
267 /* Allow blocking. */
\r
268 pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );
\r
270 /* Set up a filter so only the packets of interest are passed to the uIP
\r
271 stack. cErrorBuffer is used for convenience to create the string. Don't
\r
272 confuse this with an error message. */
\r
273 sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );
\r
275 ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
\r
277 if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
\r
279 printf("\r\nThe packet filter string is invalid\r\n" );
\r
283 if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
\r
285 printf( "\r\nAn error occurred setting the packet filter.\r\n" );
\r
289 /* Create a task that simulates an interrupt in a real system. This will
\r
290 block waiting for packets, then send a message to the uIP task when data
\r
292 xTaskCreate( prvInterruptSimulator, ( signed char * ) "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );
\r
294 /*-----------------------------------------------------------*/
\r
296 static void prvInterruptSimulator( void *pvParameters )
\r
298 static struct pcap_pkthdr *pxHeader;
\r
299 const unsigned char *pucPacketData;
\r
300 extern QueueHandle_t xEMACEventQueue;
\r
301 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
\r
304 /* Just to kill the compiler warning. */
\r
305 ( void ) pvParameters;
\r
309 /* Get the next packet. */
\r
310 lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );
\r
313 /* Is the next buffer into which data should be placed free? */
\r
314 if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )
\r
316 /* Copy the data from the captured packet into the buffer. */
\r
317 memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );
\r
319 /* Note the amount of data that was copied. */
\r
320 lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;
\r
322 /* Move onto the next buffer, wrapping around if necessary. */
\r
323 ucNextBufferToFill++;
\r
324 if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )
\r
326 ucNextBufferToFill = 0U;
\r
329 /* Data was received and stored. Send a message to the uIP task
\r
331 xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );
\r