前回の続き
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とかの情報が必要とは思えないし
この解決方法はなしだな。
だとすると本来意図されている動きを見つける必要がある