[C] 纯文本查看 复制代码
static void eth_iface_run (NET_ETH_CFG *h) {
NET_FRAME *frame;
if (sys->Flags & SYS_FLAG_SEC2) {
/* Sync timings for ETH thread */
ctrl->th.SecTick = true;
}
else if (ctrl->th.ChangeSt) {
if (ctrl->th.LinkState == ARM_ETH_LINK_UP) {
DEBUGF (ETH,"Link %d up\n",h->IfNum);
DEBUG_INFO (ctrl->th.LinkInfo);
EvrNetETH_LinkUpStatus (h->IfNum, ctrl->th.LinkInfo);
net_eth_config_mcast (h->IfNum);
netETH_Notify (h->IfNum, netETH_LinkUp, ctrl->th.LinkInfo);
if (h->If->Ip4Cfg && !h->If->Ip4Cfg->DhcpCfg) {
/* Send Gratuitous ARP here if DHCP is disabled */
net_arp_notify (h->If);
}
h->If->State->LinkUp = true;
}
else {
DEBUGF (ETH,"Link %d down\n",h->IfNum);
EvrNetETH_LinkDownStatus (h->IfNum);
netETH_Notify (h->IfNum, netETH_LinkDown, 0);
h->If->State->LinkUp = false;
}
ctrl->th.ChangeSt = false;
}
/* Check if a frame has been received */
if (ctrl->q_head == ctrl->q_tail) {
return;
}
sys->Busy = true;
#ifdef ACHILLES_TEST
if (h->IfNum == 0) eth_test.n_proc++;
#endif
/* Global parameters for input frame processing */
sys->RxIpAddr = NULL;
sys->RxOffload = h->If->State->Offload;
DEBUGF (ETH,"*** Process_frame %d ***\n",h->IfNum);
frame = ctrl->rx_q[ctrl->q_tail & (ETH_QSIZE-1)];
__COMPILER_BARRIER();
ctrl->q_tail++;
EvrNetETH_ReceiveFrame (h->IfNum, frame->length);
if (ctrl->VlanId != 0) {
/* VLAN enabled on interface */
if (!eth_vlan_accept (h, frame)) {
/* VLAN ID is not ours, dump the frame */
DEBUGF (ETH," Discarded, VLAN invalid\n");
EvrNetETH_VlanInvalid (h->IfNum);
net_mem_free (frame);
return;
}
}
DEBUG_INF2 (frame->data, frame->length);
EvrNetETH_ShowFrameHeader (frame->data);
switch (ntohs(ETH_FRAME(frame)->Prot)) {
case ETH_PROT_ARP:
if (!h->If->Ip4Cfg) {
DEBUGF (ETH," Discarded, %s:IPv4 disabled\n",h->If->Name);
EvrNetETH_Ip4Disabled (h->IfNum);
break;
}
net_arp_process (h->If, frame);
break;
case ETH_PROT_IP4:
if (!h->If->Ip4Cfg) {
DEBUGF (ETH," Discarded, %s:IPv4 disabled\n",h->If->Name);
EvrNetETH_Ip4Disabled (h->IfNum);
break;
}
if (net_mac_comp (ETH_FRAME(frame)->DstAddr, h->MacAddr)) {
/* Link-layer addressed, destination address our local MAC */
sys->Flags |= SYS_FLAG_LINKADDR;
}
/* Check IPv4 header and update ARP cache */
if (!net_ip4_chk_frame (h->If, frame)) {
break;
}
/* In NIC teaming mode, which is used for load balancing, all */
/* broadcasts and multicasts are sent from the Primary NIC. */
if (!eth_is_ucast4 (ETH_FRAME(frame)->DstAddr)) {
/* Add the sender's IP of bc/mc packet to the ARP cache */
net_arp_cache_add (h->If, IP4_FRAME(frame)->SrcAddr,
ETH_FRAME(frame)->SrcAddr);
}
else {
/* Early cache & resolve sender's IP of unicast packet */
net_arp_cache_early (h->If, IP4_FRAME(frame)->SrcAddr,
ETH_FRAME(frame)->SrcAddr);
}
/* Process fragmented frame reassembly */
frame = net_ip4_reass_frame (frame);
if (frame == NULL) {
/* Reassembly has taken over this frame */
return;
}
/* Now check IPv4 frame protocol type */
switch (IP4_FRAME(frame)->Prot) {
case IP4_PROT_ICMP:
net_icmp_process (h->If, frame);
break;
case IP4_PROT_IGMP:
net_igmp_process (h->If, frame);
break;
case IP4_PROT_UDP:
net_udp_process (h->If, frame, IP_VER4);
break;
case IP4_PROT_TCP:
net_tcp_process (h->If, frame, IP_VER4);
break;
}
break;
case ETH_PROT_IP6:
#ifdef Network_IPv6
if (!h->If->Ip6Cfg) {
DEBUGF (ETH," Discarded, %s:IPv6 disabled\n",h->If->Name);
EvrNetETH_Ip6Disabled (h->IfNum);
break;
}
/* Check IPv6 header and update Neighbor cache */
if (!net_ip6_chk_frame (h->If, frame)) {
break;
}
/* Frame is accepted */
if (!(ETH_FRAME(frame)->DstAddr[0] & 0x01)) {
/* Refresh unicast sender in neighbor cache */
if ((IP6_FRAME(frame)->NextHdr == IP6_PROT_UDP) ||
(IP6_FRAME(frame)->NextHdr == IP6_PROT_TCP)) {
net_ndp_cache_refresh (h->If, IP6_FRAME(frame)->SrcAddr,
ETH_FRAME(frame)->SrcAddr);
}
}
/* Process fragmented frame reassembly */
frame = net_ip6_reass_frame (frame);
if (frame == NULL) {
/* Reassembly has taken over this frame */
return;
}
/* Now check IPv6 frame protocol type */
switch (IP6_FRAME(frame)->NextHdr) {
case IP6_PROT_ICMP:
net_icmp6_process (h->If, frame);
break;
case IP6_PROT_UDP:
net_udp_process (h->If, frame, IP_VER6);
break;
case IP6_PROT_TCP:
net_tcp_process (h->If, frame, IP_VER6);
break;
}
#endif
break;
default:
/* Not supported, unknown Ethernet protocol */
DEBUGF (ETH," Discarded, Unknown protocol\n");
EvrNetETH_ProtocolUnknown(h->IfNum, ntohs(ETH_FRAME(frame)->Prot));
netETH_ReceiveRaw (h->IfNum, frame->data, frame->length);
break;
}
/* Release memory allocated for frame */
net_mem_free (frame);
}