嵌入式 hi3518平台以太网网络模块设计包括重连机制和网线检测机制

<span style="font-family:Courier New;">
#include <sys/types.h>  
#include <string.h>  
#include <stdlib.h>  
#include <sys/ioctl.h>  
#include <sys/stat.h>  
#include <stdio.h>  
#include <string.h>  
#include <errno.h>  
#include <net/if.h>  
#include <sys/utsname.h>  
#include <limits.h>  
#include <ctype.h>     
#include <sys/socket.h>  
#include <arpa/inet.h>     
#include <linux/sockios.h>  
#include <sys/socket.h>   
#include <netinet/ip.h>   
#include <netinet/ip_icmp.h>   
#include <netdb.h>  
#include <netinet/in.h>

#define JOSEPH_LOOP_INTERFACE 			"lo"
#define JOSEPH_ETH_INTERFACE 			"eth0"
#define JOSEPH_WIRLESS_INTERFACE 		"wlan0"

#define ETHTOOL_GLINK   				0x0000000a   /* Get link status (ethtool_value) */  
#define JSOEPH_NET_CHECK_PACKET_SIZE    4096   
#define JOSEPH_NET_CHECK_TIME			3000

typedef struct Joseph_Net_Interface_Info
{
	int net_device_type;// 0 ~ eth0 ; 1 ~ wlan ;3 ~ ppp0
	int net_device_priority;// 0 ~ eth0 ; 1 ~ wlan ;3 ~ ppp0
	int	net_device_status;//0 ~ down; 1 ~ up
	int net_device_link_status;//0 ~ no ;1 ~ yes
	char net_device_name[8];
	char net_device_ip[16];
	char net_device_mac_info[32];
	char net_device_gw_info[16];
	char net_device_mask_info[16];
	char net_device_broadcast_info[16];
		
}JOSEPH_NET_INTERFACE_INFO;

typedef struct Joseph_Ethtool_Value {  
	unsigned int   cmd;  
	unsigned int   data;   
}JOSEPH_ETHTOOL_VALUE;

enum Joseph_Net_Device_Type
{
	JOSEPH_ETH = 0,
	JOSEPH_WIFI = 1,
	JOSEPH_3G = 2,
}JOSEPH_NET_DEVICE_TYPE;

unsigned short Joseph_Cal_Chksum(unsigned short *addr, int len)	
{  
	int nleft=len;  
	int sum=0;  
	unsigned short *w=addr;  
	unsigned short answer=0;	

	while(nleft > 1)	
	{  
	  sum += *w++;	
	  nleft -= 2;  
	}  

	if( nleft == 1)  
	{ 		
	  *(unsigned char *)(&answer) = *(unsigned char *)w;  
	  sum += answer;  
	}  

	sum = (sum >> 16) + (sum & 0xffff);  
	sum += (sum >> 16);  
	answer = ~sum;  

	return answer;  
}  

int Joseph_Ping( char *ips,char *srcip , int timeout)
{ 	   

	int n;
	pid_t pid;	
	int maxfds = 0;	 
	fd_set readfds;	 

	struct ip *iph;	 
	struct icmp *icmp;	
	struct timeval *tval; 		 
	struct sockaddr_in addr;	  
	struct sockaddr_in from;
	struct ifreq ifr;
	
	bzero(&addr,sizeof(addr));
	addr.sin_family = AF_INET;	
	addr.sin_addr.s_addr = inet_addr(ips);	

	int sockfd;	 
	sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 
	if (sockfd < 0)	 
	{    
	  printf("ip:%s,socket error\n",ips);	 
	  return -1;    
	}    

	struct timeval timeo;
	timeo.tv_sec = timeout / 1000;
	timeo.tv_usec = timeout % 1000;	 

#if 0

	/*set src ip*/
	bzero(&from,sizeof(from));	/* 设定Ip信息 */
	from.sin_family = AF_INET;	
	from.sin_addr.s_addr = inet_addr(srcip);	

	if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF,(struct sockaddr *)&from, sizeof(from)) == -1)    
	{    
	  printf("ip:%s,setsockopt error \n",srcip);	 
	  return ERROR;
	}  
	bind(sockfd,(struct sockaddr *)&addr, sizeof(addr));
#else

	strcpy(ifr.ifr_name, srcip);
	if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
	{
		printf("can't bind to interface %s\n",ifr.ifr_name);
	}
	
#endif

	if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo)) == -1)    
	{    
		printf("ip:%s,setsockopt error\n",ips);	 
		return -1;    
	}
	else
	{
		;
	}

	char sendpacket[JSOEPH_NET_CHECK_PACKET_SIZE];    
	char recvpacket[JSOEPH_NET_CHECK_PACKET_SIZE];    

	memset(sendpacket, 0, sizeof(sendpacket)); 	

	pid = getpid();   

	icmp=(struct icmp*)sendpacket; 
	icmp->icmp_type = ICMP_ECHO;
	icmp->icmp_code = 0;	
	icmp->icmp_cksum = 0;	 
	icmp->icmp_seq = 0;    
	icmp->icmp_id = pid;   
	tval = (struct timeval *)icmp->icmp_data;	  
	gettimeofday(tval,NULL);	  
	icmp->icmp_cksum=Joseph_Cal_Chksum((unsigned short *)icmp,sizeof(struct icmp));

	n = sendto(sockfd, (char *)&sendpacket, sizeof(struct icmp), 0, (struct sockaddr *)&addr, sizeof(addr));	  
	if (n < 1)	
	{    
		printf("ip:%s,sendto error\n",ips);	 
		return -1;    
	} 	 
	   
	while(1) 
	{    
	  FD_ZERO(&readfds);
	  FD_SET(sockfd, &readfds);    
	  maxfds = sockfd + 1;	  
	  n = select(maxfds, &readfds, NULL, NULL, &timeo);    
	  if (n <= 0)	 
	  {    
		  printf("ip:%s,Time out error\n",ips);    
		  close(sockfd);	
		  return -1;    
	  }    
		
	  memset(recvpacket, 0, sizeof(recvpacket));	
	  int fromlen = sizeof(from);
	  n = recvfrom(sockfd, recvpacket, sizeof(recvpacket), 0, (struct sockaddr *)&from, (socklen_t *)&fromlen);    
	  if (n < 1)
	  {	  
		  return -1;
	  }    
			
	  char *from_ip = (char *)inet_ntoa(from.sin_addr); 	 
	  if (strcmp(from_ip,ips) != 0) 
	  {    
		  printf("NowPingip:%s Fromip:%s\nNowPingip is not same to Fromip,so Joseph_Ping wrong!\n",ips,from_ip);	 
		  continue;  
	  }    
		
	  iph = (struct ip *)recvpacket;		
	  icmp = (struct icmp *)(recvpacket + (iph->ip_hl << 2));

	  if (icmp->icmp_type == ICMP_ECHOREPLY && icmp->icmp_id == pid)
		  return 0;
	  else		 
		  continue;	 
	} 

	return 0;
}
  
int Joseph_Check_Net_Status(char *if_name)  
{  
	int Qy_Ret = 0;
	if(strlen(if_name) <= 0)
	{
		Qy_Ret = -1;
		return Qy_Ret;
	}
	
	char aPing[16]="202.108.22.5";	/* Joseph_Ping form ip  */

	if(Joseph_Ping(aPing,if_name,JOSEPH_NET_CHECK_TIME) == 0)  
	{  
		printf("Network is Ok!\n"); 
		Qy_Ret = 0;
	}  
	else	
	{  
		printf("Network is Bad!\n");
		Qy_Ret = -1;
	}

	return Qy_Ret;
}


/*
Author : kj
Time : 2014-08-09
Function :
	get ip gw mac broadcast
*/
int Joseph_Get_Net_Device_Info(JOSEPH_NET_INTERFACE_INFO *Joseph_Net_Interface_Info_In)
{
	int Qy_Ret = 0;
	int device_itertion = 0;
	int Joseph_Net_Interface_Sfd = 0;
	int Joseph_Net_Interface_exist = 0;
	struct ifreq Joseph_Net_Ifr;
	struct ifconf Joseph_Ifc;
	struct sockaddr_in *sin = (struct sockaddr_in*)&Joseph_Net_Ifr.ifr_addr;
	struct sockaddr_in *broadcast = (struct sockaddr_in*)&Joseph_Net_Ifr.ifr_broadaddr;

	if(Joseph_Net_Interface_Info_In == NULL)
	{
		Qy_Ret = -1;
		return Qy_Ret;
	}
	
	Joseph_Net_Interface_Sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(Joseph_Net_Interface_Sfd < 0){
		perror("socket error");
		return -1;
	}
	
	memset(&Joseph_Net_Ifr,0,sizeof(Joseph_Net_Ifr));

	Joseph_Ifc.ifc_len = sizeof(Joseph_Net_Ifr);
	Joseph_Ifc.ifc_buf = (caddr_t)&Joseph_Net_Ifr;

			
	for(device_itertion = 1;device_itertion < 5;device_itertion++)
	{
		Joseph_Net_Ifr.ifr_ifindex = device_itertion;
		Qy_Ret = ioctl(Joseph_Net_Interface_Sfd,SIOCGIFNAME,&Joseph_Net_Ifr);
		if(Qy_Ret)
		{
			Joseph_Net_Interface_exist = 0;
		}
		else
		{
			if(strcmp(Joseph_Net_Ifr.ifr_name,Joseph_Net_Interface_Info_In->net_device_name) == 0)
			{
				printf("The %dst net device is : %s\n",Joseph_Net_Ifr.ifr_ifindex,Joseph_Net_Ifr.ifr_name);
				Joseph_Net_Interface_exist = 1;

				/*Judge card type of net device*/
				Qy_Ret = ioctl (Joseph_Net_Interface_Sfd, SIOCGIFFLAGS,&Joseph_Net_Ifr);

				if(!Qy_Ret)
				{
					/*judge the status of net device*/
					if (Joseph_Net_Ifr.ifr_flags & IFF_UP)
					{
						puts("the interface status is UP");
					
					}
					else
					{
						puts("the interface status is DOWN");
					}
				}
				break;
			}
		}

	}
	if(Joseph_Net_Interface_exist == 0)
	{
		printf("%s:[%d] No Such Device of %s !\n",__FUNCTION__,__LINE__,Joseph_Net_Interface_Info_In->net_device_name);
		return -1;
	}


	/*get net device mac addr*/
	Qy_Ret = ioctl(Joseph_Net_Interface_Sfd,SIOCGIFHWADDR,&Joseph_Net_Ifr);
	if(!Qy_Ret)
	{
		sprintf(Joseph_Net_Interface_Info_In->net_device_mac_info,"%02x:%02x:%02x:%02x:%02x:%02x",\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[0],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[1],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[2],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[3],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[4],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[5]);
		
		printf("Mac address is : %02x:%02x:%02x:%02x:%02x:%02x\n",\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[0],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[1],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[2],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[3],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[4],\
			(unsigned char)Joseph_Net_Ifr.ifr_hwaddr.sa_data[5]);

	}
	else
	{
		printf("Mac address is : 00:00:00:00:00:00\n");
	}

	/*get net device ip */
	memset(Joseph_Net_Interface_Info_In->net_device_ip,0,16);
	Qy_Ret = ioctl(Joseph_Net_Interface_Sfd,SIOCGIFADDR,&Joseph_Net_Ifr);
	if(!Qy_Ret)
	{
		inet_ntop(AF_INET,&sin->sin_addr.s_addr,Joseph_Net_Interface_Info_In->net_device_ip,16);
		printf("IP address is : %s\n",Joseph_Net_Interface_Info_In->net_device_ip);
	}else
	{
		printf("IP address is : 0.0.0.0\n");
	}

	/*get broadcast addr*/
	memset(Joseph_Net_Interface_Info_In->net_device_broadcast_info,0,16);
	Qy_Ret = ioctl(Joseph_Net_Interface_Sfd,SIOCGIFBRDADDR,&Joseph_Net_Ifr);
	if(!Qy_Ret)
	{
		inet_ntop(AF_INET,&broadcast->sin_addr.s_addr,Joseph_Net_Interface_Info_In->net_device_broadcast_info,16);
		printf("BROADCAST IP is : %s\n",Joseph_Net_Interface_Info_In->net_device_broadcast_info);
	}else
	{
		printf("BROADCAST IP is : 0.0.0.0\n");
	}

	/*get mask info*/
	Qy_Ret = ioctl(Joseph_Net_Interface_Sfd,SIOCGIFNETMASK,&Joseph_Net_Ifr);

	if (!Qy_Ret)	
	{  
		inet_ntop(AF_INET,&sin->sin_addr.s_addr,Joseph_Net_Interface_Info_In->net_device_mask_info,16);
		printf("NetMask is : %s\n",Joseph_Net_Interface_Info_In->net_device_mask_info); 
	}  

	return Qy_Ret;
}

/**************************************************************** 
   return value:  
   -1 -- error , details can check errno  
   1  -- interface link up  
   0  -- interface link down.  
****************************************************************/
int Joseph_Get_Netlink_Status(const char *if_name)  
{  
    int skfd;  
    struct ifreq ifr;  
    JOSEPH_ETHTOOL_VALUE edata;  
    edata.cmd = ETHTOOL_GLINK;  
    edata.data = 0;  
    memset(&ifr, 0, sizeof(ifr));  
    strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);  
    ifr.ifr_data = (char *)&edata;  
    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) == 0)  
        return -1;  
    if (ioctl(skfd, SIOCETHTOOL, &ifr) == -1)  
    {  
       close(skfd);       
       return -1;  
    }  
    close(skfd);  
    return edata.data;  
}  

int main(int argc,char *argv[])
{
	int Qy_Ret = 0;

	JOSEPH_NET_INTERFACE_INFO Joseph_Net_Interface_Info;
	memset(&Joseph_Net_Interface_Info,0,sizeof(JOSEPH_NET_INTERFACE_INFO));

	if(argc < 2)
	{
		Qy_Ret = -1;
		return Qy_Ret;
	}
	
	system("ifconfig eth0 up");
	sleep(3);

	strcpy(Joseph_Net_Interface_Info.net_device_name,argv[1]);


	Qy_Ret = Joseph_Get_Netlink_Status(argv[1]);
	if(Qy_Ret == 1)
	{
		printf("%s:[%d] The netlink is up !\n",__FUNCTION__,__LINE__);
	}
	else
	{
		printf("%s:[%d] The netlink is down , Begin go to wifi !\n",__FUNCTION__,__LINE__);
		return -1;
	}

NET_INIT:

	/*after 5s , if no ip ,then killall udhcpc ,then go to wifi*/
	system("killall -9 udhcpc");
	
	system("udhcpc -i eth0");

	Qy_Ret = Joseph_Check_Net_Status(argv[1]);
	if(Qy_Ret == 0)
	{
		Joseph_Get_Net_Device_Info(&Joseph_Net_Interface_Info);		
	}

NET_RUN:
	while(1)
	{
		Qy_Ret = Joseph_Get_Netlink_Status(argv[1]);
		if(Qy_Ret == 1)
		{
			printf("Net link status: %s\n", Qy_Ret == 1 ? "up" : "down");
			Qy_Ret = Joseph_Check_Net_Status(argv[1]);
			if(Qy_Ret < 0)
			{
				break;//do nothing
			}
			
		}
		else
		{
			printf("%s:[%d] The netlink is down !\n",__FUNCTION__,__LINE__);	
		}
		sleep(1);
	}
	
	goto NET_INIT;

	return Qy_Ret;
}

</span>

你可能感兴趣的:(嵌入式 hi3518平台以太网网络模块设计包括重连机制和网线检测机制)