[W5300] Destination device의 MAC address를 알아내는 방법

안녕하세요.

FPGA를 이용해서 W5300을 제어하고 있습니다.
그래서 S/W를 이용하면 비교적 쉬운 제어들이 FPGA에서는 구현하기가 어렵네요.

MACRAW mode를 이용하다보니 상대방의 MAC address를 직접 알아내야 합니다.

ARP 명령어를 사용하면 그에 대한 response에 MAC address가 딸려온다는것까지는 알고 있습니다.

그렇다면 FPGA 제어로 ARP 명령어를 보내는 순서 또는 방법을 알고싶습니다.
혹은 S/W의 흐름 정도만 알려주셔도 많은 도움이 될 것 같습니다.

항상 감사드립니다.

(지난번에 문의했던 UDP packet이 빠지는 문제에 대한 해결은 좀 미뤄둔 상태입니다.)

FPGA로 어떻게 제어하시는지는 모르겠습니다만.

mcu처럼 쓰고 계시는 건지요?

ARP request packet을 data로 만든 후 send 명령을 W5300에 보내시면 됩니다.
ARP request packet은 wireshark 프로그램을 이용하여 패킷캡쳐를 통해 보실 수 있습니다.
그런형태의 data를 send 하시면 arp reply packet이 오게 됩니다.
해당 Data를 recv하신 다음 data를 parsing 하시면 destination의 Mac address를 알 수 있게 됩니다.

아래 S/W코드를 참고 하시기 바랍니다. (W5300이 아닌 다른 칩의 firmware니 그대로 쓰시면 안됩니다.)

uint32_t arp_request_send(uint8_t * target_ip)
{
int32_t ret;
uint8_t i;
uint8_t smac[6] = {0,0,0,0,0,0};
uint8_t sip[4] = {0,0,0,0};
uint8_t arp_packet[42] = {0,};

switch(getSn_SR(0))
{
	case SOCK_MACRAW :
		/*Destination MAC Address field*/
		for(i=0; i<6; i++)
		{
			arp_packet[i] = 0xff;
		}

		/*get Source Mac Address*/
		getSHAR(smac);

		/*Source Mac Address field*/
		for(i=6; i<12; i++)
		{
			arp_packet[i] = smac[i-6];
		}

		/*Ether Type field*/
		arp_packet[12] = 0x08; arp_packet[13] = 0x06;//Ether Type : ARP 0x0806

		/*ARP field*/
		arp_packet[14] = 0x00; arp_packet[15] = 0x01;//Hardware Type : Ethernet 0x0001
		arp_packet[16] = 0x08; arp_packet[17] = 0x00;//Protocol Type : IPv4 0x0800
		arp_packet[18] = 0x06;//Hardware Size : 0x0006
		arp_packet[19] = 0x04;//Protocol Size : 0x0004
		arp_packet[20] = 0x00; arp_packet[21] = 0x01;//OPcode : Request 0x0001
		/*Source Mac address field*/
		for(i=22; i<28; i++)
		{
			arp_packet[i] = smac[i-22];
		}
		/*get Source IP Address*/
		getSIPR(sip);

		/*Source IP address field*/
		for(i=28; i<32; i++)
		{
			arp_packet[i] = sip[i-28];
		}
		/*Target Mac address field*/
		for(i=32; i<38; i++)
		{
			arp_packet[i] = 0x00;//Target MAC : 00:00:00:00:00:00
		}
		/*Target IP address field*/
		for(i=38; i<42; i++)
		{
			arp_packet[i] = target_ip[i-38];
		}

		ret = sendto(0, arp_packet, sizeof(arp_packet), 0, 0); // arp packet send

		return ret;
	default :
		printf("Error : macraw socket not open\r\n");
		return -1;
}

}

int32_t arp_reply_recv(uint8_t * target_ip)
{
int32_t ret;
uint8_t i;
uint8_t dst_mac[6]; // request source mac
uint8_t src_mac[6]; // request target mac
//uint16_t ether_type = 0;
//uint16_t hardware_type;
//uint16_t protocol_type;
//uint8_t hardware_size;
//uint8_t Protocol_size;
uint16_t size, opcode;
uint8_t source_ip[4] = {0,0,0,0}; // request target ip
//uint8_t target_ip[4] = {0,0,0,0}; // request source ip

switch(getSn_SR(0))
{
	case SOCK_MACRAW :
		if((size = getSn_RX_RSR(0)) > 0)
		{
			ret = recvfrom(0, ethBuf0, size, 0, 0);

			if(ret <= 0)
			{
				printf("recvfrom error. %ld\r\n",ret);
				return ret;
			}
			else
			{
				getSHAR(dst_mac);

				if(dst_mac[0]!=ethBuf0[0] | dst_mac[1]!=ethBuf0[1] | dst_mac[2]!=ethBuf0[2] | dst_mac[3]!=ethBuf0[3] | dst_mac[4]!=ethBuf0[4] | dst_mac[5]!=ethBuf0[5])
				{
					printf("this packet is not my mac packet.\r\n");
					return -1;//no mymac error
				}

				if(ethBuf0[12]!=0x08 | ethBuf0[13]!=0x06) //ether type ARP: 0x0806
				{
					printf("this packet is not arp packet.\r\n");
					return -2;//no arp error
				}

				if(ethBuf0[20]!=0x00 | ethBuf0[21]!=0x02) //opcode reply : 0x0002
				{
					printf("this packet is not arp reply packet.\r\n");
					return -3;//no arp reply error
				}

				for(i=22; i<28; i++)
					src_mac[i-22] = ethBuf0[i];
				for(i=28; i<32; i++)
					source_ip[i-28] = ethBuf0[i];
				if(source_ip[0]==target_ip[0] & source_ip[1]==target_ip[1] & source_ip[2]==target_ip[2] & source_ip[3]==target_ip[3])
				{
					printf("RECV ARP packet from %2x:%2x:%2x:%2x:%2x:%2x\r\n",src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);
					printf("RECV ARP packet from %3d.%3d.%3d.%3d\r\n",source_ip[0],source_ip[1],source_ip[2],source_ip[3]);
					return 0;
				}
			}
		}
		return 0;
	default :
		printf("Error : macraw socket not open\r\n");
		return -1;
}

}

main(){
//MACRAW ARP scenario
setSn_MR2(0, Sn_MR2_BBLOCK|Sn_MR2_MBLOCK|Sn_MR2_6BLOCK);
printf(“Sn_MR2 register value : %x \r\n”,getSn_MR2(0));
while(1)
{
switch(getSn_SR(0))
{
case SOCK_MACRAW :
arp_reply_recv(WIZ_Dest_IP);
break;

			case SOCK_CLOSED:
				printf("in CLOSED\r\n");

				if((ret = socket(0, Sn_MR_MACRAW, 0, Sn_MR_MFEN)) != 0)
					return ret;
				//setSn_MR2(0, /*Sn_MR2_BBLOCK|*/Sn_MR2_MBLOCK/*|Sn_MR2_6BLOCK*/);
				printf("Opened, MACRAW Recv TEST\r\n");
				arp_request_send(WIZ_Dest_IP);
				break;

			default :
				printf("Error : macraw socket not open");
				break;
		}
	}


	//MACRAW recv scenario
	setSn_MR2(0, Sn_MR2_BBLOCK|Sn_MR2_MBLOCK|Sn_MR2_6BLOCK);
	printf("Sn_MR2 register value : %x \r\n",getSn_MR2(0));
	while(1)
	{
		switch(getSn_SR(0))
		{
			case SOCK_MACRAW :
				if((size = getSn_RX_RSR(0)) > 0)
				{
					printf("[RECV_DATA_LEN]:%d\r\n",size);
					ret = recvfrom(0, ethBuf0, size, 0, 5000);

					if(ret <= 0)
						return ret;
				}
				break;
			case SOCK_CLOSED:
				printf("in CLOSED\r\n");

				if((ret = socket(0, Sn_MR_MACRAW, 0, Sn_MR_MFEN)) != 0)
					return ret;
				printf("Opened, MACRAW Recv TEST\r\n");
				break;

			default :
				printf("Error : macraw socket not open");
				break;
		}
	}

}

감사합니다.

감사합니다. 많은 도움이 될 것 같습니다.

FPGA를 이용하여 W5300을 제어하는데
MCU가 W5300을 제어하는 것과 비슷하기는 합니다만(W5300 제어라는 것이 레지스터 세팅이니깐요.)
MCU에서는 library를 이용할 수 있는데 FPGA에서는 일일히 전부 구현을 해 주어야 한다는 점이 다를 것 같습니다.

감사합니다.

네 어려움이 있으시면 또 질문 주시기바랍니다 :slight_smile: