0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FreeRTOSを動かしてみる(14)

Last updated at Posted at 2023-12-27

前回の続き

FreeRTOSのIPスタック

arp応答をLinuxと同じように返しても動かないということは完全にFreeRTOSののIPスタックの問題

arp発行している場所を突き止めて、そこから追っていく。

ARPの発行元

(gdb) bt 
#0  pfOutput (pxDescriptor=0x200067a0 <xInterfaces.5>, pxNetworkBuffer=0x20010990 <xNetworkBufferDescriptors.0>, xReleaseAfterSend=1) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/virtether/NetworkInterface.c:173
#1  0x00003db8 in FreeRTOS_OutputARPRequest (ulIPAddress=23374016) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_ARP.c:1316
#2  0x0000bdb8 in prvTCPPrepareConnect_IPV4 (pxSocket=0x20113808) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPv4.c:367
#3  0x0000b57e in prvTCPPrepareConnect (pxSocket=<optimized out>) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission.c:496
#4  0x0000b59a in prvTCPMakeSurePrepared (pxSocket=<optimized out>) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission.c:87
#5  0x0000b9fa in prvTCPSendPacket (pxSocket=pxSocket@entry=0x20113808) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission.c:139
#6  0x0000a436 in xTCPSocketCheck (pxSocket=pxSocket@entry=0x20113808) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_IP.c:226
#7  0x000091b8 in xTCPTimerCheck (xWillSleep=xWillSleep@entry=1) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_Sockets.c:4828

prvTCPPrepareConnect_IPV4の中で接続する前にarpを送っている

(gdb) f 2
#2  0x0000bdd6 in prvTCPPrepareConnect_IPV4 (pxSocket=0x20113808) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPv4.c:368
368	            FreeRTOS_OutputARPRequest( ulRemoteIP );
(gdb) l 350
345	    switch( eReturned )
346	    {
347	        case eARPCacheHit:    /* An ARP table lookup found a valid entry. */
348	            break;            /* We can now prepare the SYN packet. */

(gdb) p eReturned 
$1 = eARPCacheMiss

TCPで送ろうとしたけど送り先がわからんという話
なのでここでeARPCacheHitが返るようにする必要がある。

(gdb) l 343
338	        }
339	    #endif /* ipconfigHAS_PRINTF != 0 */
340	
341	    ulRemoteIP = FreeRTOS_htonl( pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4 );
342	    /* Determine the ARP cache status for the requested IP address. */
343	    eReturned = eARPGetCacheEntry( &( ulRemoteIP ), &( xEthAddress ), &( pxSocket->pxEndPoint ) );

eARPGetCacheEntryを見ていく
マルチキャストでもブロードキャストでも無い場合はeARPGetCacheEntryGateWayに行くらしい

 971         if( xIsIPv4Multicast( ulAddressToLookup ) != 0 )
 ...
 992         else if( ( FreeRTOS_htonl( ulAddressToLookup ) & 0xffU ) == 0xffU ) /* Is this a broadcast address li     ke x.x.x.255 ? */
...
1005         else1006         {
1007             eReturn = eARPGetCacheEntryGateWay( pulIPAddress, pxMACAddress, ppxEndPoint );
1008         }

でここが本命

1085                 eReturn = prvCacheLookup( ulAddressToLookup, pxMACAddress, ppxEndPoint );

ふむ

(gdb) p/x xARPCache 
$12 = {{ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}, {ulIPAddress = 0x0, xMACAddress = {ucBytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, ucAge = 0x0, ucValid = 0x0, pxEndPoint = 0x0}}

ここに値を入れる必要がある

FreeRTOS-Plus-TCP$ grep xARPCache . -wnrI | fgrep -v "/test/" | grep " = "
./source/FreeRTOS_ARP.c:635:                lResult = xARPCache[ x ].ulIPAddress;
./source/FreeRTOS_ARP.c:672:                    xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
./source/FreeRTOS_ARP.c:742:            xARPCache[ xLocation.xUseEntry ].ulIPAddress = ulIPAddress;
./source/FreeRTOS_ARP.c:750:                xARPCache[ xLocation.xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
./source/FreeRTOS_ARP.c:751:                xARPCache[ xLocation.xUseEntry ].ucValid = ( uint8_t ) pdTRUE;
./source/FreeRTOS_ARP.c:752:                xARPCache[ xLocation.xUseEntry ].pxEndPoint = pxEndPoint;
./source/FreeRTOS_ARP.c:756:                xARPCache[ xLocation.xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_RETRANSMISSIONS;
./source/FreeRTOS_ARP.c:757:                xARPCache[ xLocation.xUseEntry ].ucValid = ( uint8_t ) pdFALSE;
./source/FreeRTOS_ARP.c:827:                xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
./source/FreeRTOS_ARP.c:828:                xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE;
./source/FreeRTOS_ARP.c:829:                xARPCache[ x ].pxEndPoint = pxEndPoint;
./source/FreeRTOS_ARP.c:852:                    BaseType_t xOtherIsLocal = ( FreeRTOS_FindEndPointOnNetMask( xARPCache[ x ].ulIPAddress, 3 ) != NULL ) ? 1 : 0; /* ARP remote address. */
./source/FreeRTOS_ARP.c:874:            ucMinAgeFound = xARPCache[ x ].ucAge;
./source/FreeRTOS_ARP.c:919:                *pulIPAddress = xARPCache[ x ].ulIPAddress;
./source/FreeRTOS_ARP.c:924:                    *( ppxInterface ) = xARPCache[ x ].pxEndPoint->pxNetworkInterface;
./source/FreeRTOS_ARP.c:1142:                    *( ppxEndPoint ) = xARPCache[ x ].pxEndPoint;
./source/FreeRTOS_ARP.c:1201:                xARPCache[ x ].ulIPAddress = 0U;

751Lか828Lあたりだろうな

 690 void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
 691                             const uint32_t ulIPAddress,
 692                             struct xNetworkEndPoint * pxEndPoint )
...
 776 static BaseType_t prvFindCacheEntry( const MACAddress_t * pxMACAddress,
 777                                      const uint32_t ulIPAddress,
 778                                      struct xNetworkEndPoint * pxEndPoint,
 779                                      CacheLocation_t * pxLocation )

これあれか、ドライバがarpテーブル更新する必要があるのか?

試しに更新してみたら一応ARPはHITするようになった

Breakpoint 1, prvTCPPrepareConnect_IPV4 (pxSocket=0x20113808) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPv4.c:344
344	    switch( eReturned )
$1 = eARPCacheMiss

Breakpoint 1, prvTCPPrepareConnect_IPV4 (pxSocket=0x20113808) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPv4.c:344
344	    switch( eReturned )
$2 = eARPCacheHit

なのにいつまでたってもSYNパケットがドライバにやってこない

EndPointがnullだとダメらしい

prvTCPReturnPacket_IPV4 (pxSocket=pxSocket@entry=0x20113808, pxDescriptor=pxDescriptor@entry=0x0 <isr_vector>, ulLen=ulLen@entry=52, xReleaseAfterSend=xReleaseAfterSend@entry=0) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPv4.c:88
163	            if( pxNetworkBuffer->pxEndPoint == NULL )
164	            {
165	                prvTCPReturn_SetEndPoint( pxSocket, pxNetworkBuffer, uxIPHeaderSize );
166	
167	                if( pxNetworkBuffer->pxEndPoint == NULL )
168	                {
169	                    if( xDoRelease != pdFALSE )
170	                    {
171	                        vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
(gdb) 

EndPointを枠だけ作ってみた

NetworkEndPoint_t opposit_ep = {0};

絶対おかしいやろこれ

^C
Program received signal SIGINT, Interrupt.
vAssertCalled () at main.c:139
139	        while( looping == 0LU )
(gdb) bt 
#0  vAssertCalled () at main.c:139
#1  0x0000bd4a in prvTCPReturnPacket_IPV4 (pxSocket=pxSocket@entry=0x201138f8, pxDescriptor=pxDescriptor@entry=0x0 <isr_vector>, ulLen=ulLen@entry=52, xReleaseAfterSend=xReleaseAfterSend@entry=0) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPv4.c:283
#2  0x0000b5c4 in prvTCPReturnPacket (pxSocket=pxSocket@entry=0x201138f8, pxDescriptor=pxDescriptor@entry=0x0 <isr_vector>, ulLen=ulLen@entry=52, xReleaseAfterSend=xReleaseAfterSend@entry=0) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission.c:288
#3  0x0000ba44 in prvTCPSendPacket (pxSocket=pxSocket@entry=0x201138f8) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission.c:175
#4  0x0000a436 in xTCPSocketCheck (pxSocket=pxSocket@entry=0x201138f8) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_IP.c:226
#5  0x000091b8 in xTCPTimerCheck (xWillSleep=xWillSleep@entry=1) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_Sockets.c:4828
#6  0x00005edc in vCheckNetworkTimers () at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_IP_Timers.c:302
#7  0x00005b84 in prvProcessIPEventsAndTimers () at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_IP.c:266
#8  0x00005cae in prvIPTask (pvParameters=<optimized out>) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_IP.c:247
#9  0x00000290 in prvPortStartFirstTask () at /home/voyager/workspace/freertos/freertos_cm3/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c:247
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) f 1
#1  0x0000bd4a in prvTCPReturnPacket_IPV4 (pxSocket=pxSocket@entry=0x201138f8, pxDescriptor=pxDescriptor@entry=0x0 <isr_vector>, ulLen=ulLen@entry=52, xReleaseAfterSend=xReleaseAfterSend@entry=0) at /home/voyager/workspace/freertos/FreeRTOS-Plus-TCP/source/FreeRTOS_TCP_Transmission_IPv4.c:283
283	            configASSERT( pxNetworkBuffer->pxEndPoint->pxNetworkInterface != NULL );
(gdb) p pxEndPoint->pxNetworkInterface
No symbol "pxEndPoint" in current context.
(gdb) l
278	            #endif /* if( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 ) */
279	
280	            /* Send! */
281	            iptraceNETWORK_INTERFACE_OUTPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer );
282	
283	            configASSERT( pxNetworkBuffer->pxEndPoint->pxNetworkInterface != NULL );
284	            configASSERT( pxNetworkBuffer->pxEndPoint->pxNetworkInterface->pfOutput != NULL );
285	
286	            NetworkInterface_t * pxInterface = pxNetworkBuffer->pxEndPoint->pxNetworkInterface;
287	            ( void ) pxInterface->pfOutput( pxInterface, pxNetworkBuffer, xDoRelease );
(gdb) p pxNetworkBuffer 
$4 = (NetworkBufferDescriptor_t *) 0x20010408 <xIPTaskStack.1+39756>
(gdb) p pxNetworkBuffer->pxEndPoint 
$5 = (struct xNetworkEndPoint *) 0x20011374 <opposit_ep>
(gdb) p pxNetworkBuffer->pxEndPoint->pxNetworkInterface->pfOutput 
$6 = (NetworkInterfaceOutputFunction_t) 0xf5 <Default_Handler2>
(gdb) 

とりあえず通すためと割り切る

NetworkInterface_t opposit_if = {
    .pfOutput = pfOutput,
    .pxEndPoint = &opposit_ep,
};

一応データは飛んだが未接続と判断された

[6768] NetworkInterface.c(195) pfOutput ip:0 po:0 bp:0 len:66 r:0 data:
aa 00 02 11 22 33 00 00 00 00 00 00 08 00 45 00
00 34 00 02 00 00 80 06 16 19 00 00 00 00 c0 a8
64 01 05 01 1b ee 02 02 02 02 00 00 00 00 80 02
0b 68 1a 14 00 00 02 04 05 b4 01 03 03 00 01 01
04 02
[3678] FreeRTOS_Sockets.c(3854) FreeRTOS_connect uxEvents:20 xResut:0 fr:0xdaa1 
[3678] app_client.c(98) vTCPSend not connected. -128 fr:0xdb7d 
[3678] FreeRTOS_Sockets.c(4747) FreeRTOS_shutdown pdFREERTOS_ERRNO_ENOTCONN fr:0xdafd 

逆も同じくどこかへ消えていった

[2608] NetworkInterface.c(262) ether_task rx data to stack:1 sz:74 data:
aa 00 02 aa bb cc aa 00 02 11 22 33 08 00 45 00
00 3c 05 16 40 00 40 06 ec 51 c0 a8 64 01 c0 a8
64 02 de 24 1b ef d6 03 72 f8 00 00 00 00 a0 02
fe 2e d7 19 00 00 02 04 05 a6 04 02 08 0a 19 30
cd 30 00 00 00 00 01 03 03 07 
 fr:0x291 

3行目末尾が 02になっているからこれがSYNパケットで問題ないが
LinuxにしろFreeRTOSにしろACKパケットが返ってこない

EndPoint設定したら受信したデータがポートフォワードされてるっぽい

[6768] NetworkInterface.c(195) pfOutput ip:0 po:0 bp:0 len:98 r:1 data:
aa 00 02 11 22 33 00 00 00 00 00 00 08 00 45 00
00 54 2e 03 00 00 40 01 03 52 c0 a8 64 02 c0 a8
64 01 00 00 37 7f 00 28 00 01 12 c6 8b 65 00 00
00 00 61 59 0a 00 00 00 00 00 10 11 12 13 14 15
16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
 fr:0x5837 
[2608] NetworkInterface.c(262) ether_task rx data to stack:1 sz:98 data:
aa 00 02 11 22 33 00 00 00 00 00 00 08 00 45 00
00 54 2e 03 00 00 40 01 03 52 c0 a8 64 02 c0 a8
64 01 00 00 37 7f 00 28 00 01 12 c6 8b 65 00 00
00 00 61 59 0a 00 00 00 00 00 10 11 12 13 14 15
16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
 fr:0x291 

どう考えてもARPテーブルの内容保持にEndPointとかInterFaceとかの情報が必要とは思えないし
この解決方法はなしだな。

だとすると本来意図されている動きを見つける必要がある

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?