| #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 |