RGMII以太网测试方案

一 方案框图

 二 实现步骤

1.模组的MAC通过RGMII接口与PHY连接

2.MAC层数据经过RGMII到达PHY的PCS层

3.设置PHY的PCS层回环,使PCS层数据回到MAC层

4.判断MAC层TX与RX接收的数据。如果MAC能接收到数据,测试PASS,否则失败

三 测试代码

int main(int argc, char **argv)
{
    int i, datalen, frame_length, sd, bytes;
    char *interface = "eth0";
    uint8_t data[IP_MAXPACKET];
    uint8_t src_mac[6];
    uint8_t dst_mac[6];
    uint8_t ether_frame[IP_MAXPACKET];
    struct sockaddr_ll device;
    struct ifreq ifr;
	int recvlen=0;
	uint8_t buffer[IP_MAXPACKET];
    int loopback_state=0;

    // Submit request for a socket descriptor to look up interface.
    if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
    { 
        perror("socket() failed to get socket descriptor for using ioctl()");
        exit(EXIT_FAILURE);
    }

    // Use ioctl() to look up interface name and get its MAC address.
    memset(&ifr, 0, sizeof(ifr));
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
    if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
    {
        perror("ioctl() failed to get source MAC address ");
        return (EXIT_FAILURE);
    }
    close(sd);

    // Copy source MAC address.
    memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6);

    // Report source MAC address to stdout.
    printf("MAC address for interface %s is ", interface);
    for (i = 0; i < 5; i++)
    {
        printf("%02x:", src_mac[i]);
    }
    printf("%02x\n", src_mac[5]);

    // Find interface index from interface name and store index in
    // struct sockaddr_ll device, which will be used as an argument of sendto().
    memset(&device, 0, sizeof(device));
    if ((device.sll_ifindex = if_nametoindex(interface)) == 0)
    {
        perror("if_nametoindex() failed to obtain interface index ");
        exit(EXIT_FAILURE);
    }
    printf("Index for interface %s is %i\n", interface, device.sll_ifindex);

    // Set destination MAC address: you need to fill these out
    dst_mac[0] = 0x10; //设置目的网卡地址
    dst_mac[1] = 0x78;
    dst_mac[2] = 0xd2;
    dst_mac[3] = 0xc6;
    dst_mac[4] = 0x2f;
    dst_mac[5] = 0x89;

    // Fill out sockaddr_ll.
    device.sll_family = AF_PACKET;
    memcpy(device.sll_addr, src_mac, 6);
    device.sll_halen = htons(6);

    // 发送的data,长度可以任意,但是抓包时看到最小数据长度为46,这是以太网协议规定以太网帧数据域部分最小为46字节,不足的自动补零处理
    datalen = 12;
    data[0] = 0x11;
    data[1] = 0x12;
    data[2] = 0x13;
    data[3] = 0x14;
    data[4] = 0x15;
    data[5] = 0x16;
    data[6] = 0x17;
    data[7] = 0x18;
    data[8] = 0x19;
    data[9] = 0x20;
    data[10] = 0x21;
    data[11] = 0x22;

    // Fill out ethernet frame header.
    frame_length = 6 + 6 + 2 + datalen;
    // Destination and Source MAC addresses
    memcpy(ether_frame, dst_mac, 6);
    memcpy(ether_frame + 6, src_mac, 6);

    ether_frame[12] = ETH_P_DEAN / 256;
    ether_frame[13] = ETH_P_DEAN % 256;

    // data
    memcpy(ether_frame + 14, data, datalen);
    // Submit request for a raw socket descriptor.
    if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
    { //创建正真发送的socket
        perror("socket() failed ");
        exit(EXIT_FAILURE);
    }
    // Send ethernet frame to socket.
    if ((bytes = sendto(sd, ether_frame, frame_length, 0, (struct sockaddr *)&device, sizeof(device))) <= 0)
    {
        perror("sendto() failed");
        exit(EXIT_FAILURE);
    }
   	for(i=0;i<bytes;i++){
			printf(" %02x",ether_frame[i]);
			if((i+1)%16==0){
					printf("\n");
			}
	}
	printf("\n");
	

	recvlen=recvfrom(sd,buffer,sizeof(buffer),0,NULL,NULL);

	for(i=0;i<recvlen;i++){
		printf(" %02x",buffer[i]);
		if((i+1)%16==0){
				printf("\n");
		}
	}
	printf("\n");

    for(i=0;i<recvlen;i++){

        if(bytes>recvlen)
        {
            loopback_state=0;
            break;
        }
        else if(ether_frame[i]!=buffer[i])
        {
            loopback_state=0;
            break;
        }
    }
	if (loopback_state == 1)
    {
         printf("phy loopback OK\n");
    }
    else
    {
        printf("phy loopback error\n");
    }
    // Close socket descriptor.
    close(sd);

    return (EXIT_SUCCESS);
}

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值