blob: c127cbe62ec0d454f5c64e22a6636e76dae5bfbe [file] [log] [blame]
#if 1//MBTK_RGMII_TEST
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>// close()
#include <string.h>// strcpy, memset(), and memcpy()
#include <netdb.h> // struct addrinfo
#include <sys/types.h> // needed for socket(), uint8_t, uint16_t, uint32_t
#include <sys/socket.h> // needed for socket()
#include <netinet/in.h> // IPPROTO_ICMP, INET_ADDRSTRLEN
#include <netinet/ip.h>// struct ip and IP_MAXPACKET (which is 65535)
#include <netinet/ip_icmp.h> // struct icmp, ICMP_ECHO
#include <arpa/inet.h> // inet_pton() and inet_ntop()
#include <sys/ioctl.h> // macro ioctl is defined
//#include <bits/ioctls.h> // defines values for argument "request" of ioctl.
#include <net/if.h> // struct ifreq
#include <linux/if_ether.h> // ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD
#include <linux/if_packet.h> // struct sockaddr_ll (see man 7 packet)
//#include <net/ethernet.h>
#include <errno.h> // errno, perror()
#include <linux/mii.h>
#include <linux/sockios.h>
#include <linux/types.h>
#include "mbtk_at.h"
#define ETH_P_DEAN 0x8874 //自定义的以太网协议type
//mdio eth0 1 读取phy寄存器1的数值
//mdio eth0 0 0x1120 将0x1120写入 phy寄存器1
#define reteck(ret) \
if(ret < 0){ \
LOG("[RGMIITEST]%s : line: %d", __func__, __LINE__); \
goto lab; \
}
#if 0
#define help() \
printf("mdio:\n"); \
printf("read operation: mdio reg_addr\n"); \
printf("write operation: mdio reg_addr value\n"); \
printf("For example:\n"); \
printf("mdio eth0 1\n"); \
printf("mdio eth0 0 0x12\n\n"); \
exit(0);
#endif
int sockfd;
//net_name:网卡名字,mode:get 1/set 0,reg_addr: 寄存器地址,value:值
int mbtk_mdio(char* net_name,int mode, uint16_t reg_addr, uint16_t value)
{
if(net_name == NULL)
{
return -1;
}
struct mii_ioctl_data *mii = NULL;
struct ifreq ifr;
int ret;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, net_name, IFNAMSIZ - 1);
sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
reteck(sockfd);
//get phy address in smi bus
ret = ioctl(sockfd, SIOCGMIIPHY, &ifr);
reteck(ret);
mii = (struct mii_ioctl_data*)&ifr.ifr_data;
if(mode == 1)
{
mii->reg_num = reg_addr;
ret = ioctl(sockfd, SIOCGMIIREG, &ifr);
reteck(ret);
LOG("[RGMIITEST]read phy addr: 0x%x reg: 0x%x value : 0x%x\n", mii->phy_id, mii->reg_num, mii->val_out);
if (mii->reg_num == 0x1)
{
LOG("[RGMIITEST]Link Status\n");
if(mii->val_out& 0x0004)
{
LOG("[RGMIITEST]link is up\n");
}
else
{
LOG("[RGMIITEST]link is down\n");
}
}
}
else if(mode == 0)
{
mii->reg_num = reg_addr;
mii->val_in = value;
ret = ioctl(sockfd, SIOCSMIIREG, &ifr);
reteck(ret);
LOG("[RGMIITEST]write phy addr: 0x%x reg: 0x%x value : 0x%x\n", mii->phy_id, mii->reg_num, mii->val_in);
}
close(sockfd);
return 0;
lab:
close(sockfd);
return -1;
}
int mbtk_rgmii_loopback(void)
{
int i, datalen, frame_length, sd, bytes;
char *interface = "eth0";
uint8_t data[100];
uint8_t src_mac[6];
uint8_t dst_mac[6];
uint8_t ether_frame[100] = {0};
struct sockaddr_ll device;
struct ifreq ifr;
int recvlen=0;
uint8_t buffer[100] = {0};
int loopback_state=0;
int ret = -1;
// Submit request for a socket descriptor to look up interface.
if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
{
LOG("[RGMIITEST]socket() failed to get socket descriptor for using ioctl()");
return -1;
}
// 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)
{
close(sd);
LOG("[RGMIITEST]ioctl() failed to get source MAC address ");
return -1;
}
close(sd);
// Copy source MAC address.
memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6);
// Report source MAC address to stdout.
LOG("[RGMIITEST]MAC address for interface %s is %02x:%02x:%02x:%02x:%02x:%02x", interface, \
src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], 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)
{
LOG("[RGMIITEST]if_nametoindex() failed to obtain interface index ");
return -1;
}
LOG("[RGMIITEST]Index for interface %s is %i", interface, device.sll_ifindex);
// Set destination MAC address: you need to fill these out
dst_mac[0] = 0x72; //设置目的网卡地址
dst_mac[1] = 0x40;
dst_mac[2] = 0xB8;
dst_mac[3] = 0xF7;
dst_mac[4] = 0x5A;
dst_mac[5] = 0x64;
// 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] = 'h';
data[1] = 'e';
data[2] = 'l';
data[3] = 'l';
data[4] = 'o';
data[5] = ' ';
data[6] = 'w';
data[7] = 'o';
data[8] = 'r';
data[9] = 'l';
data[10] = 'd';
data[11] = '!';
// 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
LOG("[RGMIITEST]socket() failed ");
return -1;
}
//set recv timeout
struct timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 0;
ret = setsockopt( sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv) );
if(ret != 0)
{
LOG("[RGMIITEST]setsockopt is fail ret = [%d]", ret);
}
// Send ethernet frame to socket.
if ((bytes = sendto(sd, ether_frame, frame_length, 0, (struct sockaddr *)&device,
sizeof(device))) <= 0)
{
close(sd);
LOG("[RGMIITEST]sendto() failed");
return -1;
}
LOG("[RGMIITEST]IP_MAXPACKET = %d", IP_MAXPACKET, bytes);
LOG("[RGMIITEST]sendlen = %d sendto data:", bytes);
LOG("[RGMIITEST]%s", ether_frame);
recvlen = recvfrom(sd,buffer,sizeof(buffer),0,NULL,NULL);
if(recvlen < 0)
{
if(errno == EWOULDBLOCK)
{
LOG("[RGMIITEST] recv timeout");
}
close(sd);
return -1;
}
LOG("[RGMIITEST]recvlen = %d recvfrom data:\n", recvlen);
LOG("[RGMIITEST]%s", buffer);
for(i=0; i<recvlen; i++) {
if(bytes>recvlen)
{
loopback_state=-1;
break;
}
else if(ether_frame[i]!=buffer[i])
{
loopback_state=-1;
LOG("[RGMIITEST]ether_frame[%d]:%02x buffer[%d]:%02x", i, ether_frame[i], i, buffer[i]);
break;
}
}
// Close socket descriptor.
close(sd);
return loopback_state;
}
#endif