📄 net.c
字号:
/* Verify that the device is up. */
if ( (device->dev_flags & (DV_UP | DV_RUNNING)) != (DV_UP | DV_RUNNING) )
return (NU_HOST_UNREACHABLE);
if (ro)
rt = ro->rt_route;
/* Verify the route is up. Both gwroute and rt are set equal to the route
located by IP_Send. */
if(rt)
{
/* If the route is not up then try to locate an alternate route. */
if ((rt->rt_flags & RT_UP) == 0)
{
if ( (rt = RTAB_Find_Route(dest)) != NU_NULL)
rt->rt_refcnt--;
else
return (NU_HOST_UNREACHABLE);
}
}
switch(dest->sck_family)
{
case SK_FAM_IP:
/* Resolve the MAC address. */
if (ARP_Resolve(device, dest, mac_dest, buf_ptr) != NU_SUCCESS)
/* To the upper layer protocols this is the same as a
successful send. */
return NU_SUCCESS;
type = EIP;
break;
case SK_FAM_UNSPEC:
/* Family is unspecified. This should be an ARP packet. */
/* Point to the ethernet header information, and extract the type
and destination address. */
eh = (ARP_MAC_HEADER *)dest;
memcpy (mac_dest, eh->ar_mac.ar_mac_ether.dest, DADDLEN);
type = eh->ar_mac.ar_mac_ether.type;
break;
default:
return -1;
}
/* Move back the data pointer to make room for the MAC layer and adjust the
packet length. */
buf_ptr->data_ptr -= device->dev_hdrlen;
buf_ptr->data_len += device->dev_hdrlen;
buf_ptr->mem_total_data_len += device->dev_hdrlen;
/* Initialize the ethernet header. */
PUT16(buf_ptr->data_ptr, ETHER_TYPE_OFFSET, type);
PUT_STRING(buf_ptr->data_ptr, ETHER_DEST_OFFSET, mac_dest, DADDLEN);
PUT_STRING(buf_ptr->data_ptr, ETHER_ME_OFFSET, device->dev_mac_addr, DADDLEN);
#if (INCLUDE_SNMP == NU_TRUE)
/* Is this a unicast or a non-unicast packet. */
if ( (buf_ptr->mem_flags & NET_BCAST) || (buf_ptr->mem_flags & NET_MCAST) )
SNMP_ifOutNUcastPkts_Inc(device->dev_index);
else
SNMP_ifOutUcastPkts_Inc(device->dev_index);
#endif
#ifdef PACKET
/* Pass the packet to the device. */
device->dev_start(device, buf_ptr);
/* The packet has been transmitted. Deallocate the buffer. */
MEM_One_Buffer_Chain_Free (buf_ptr, buf_ptr->mem_dlist);
#else
old_int = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);
/* Place the buffer on the device's transmit queue. */
MEM_Buffer_Enqueue(&device->dev_transq, buf_ptr);
++device->dev_transq_length;
/* SPR #0541 */
/* Increment the number of packet on the out going Q */
SNMP_ifOutQLen_Inc(device->dev_index);
/* If this is the first buffer in the transmit queue we need to resume the
* transmit task. If not another packet is already being transmitted. */
if(device->dev_transq.head == buf_ptr)
{
NU_Local_Control_Interrupts(old_int);
/* Resume the the transmit task. */
device->dev_start(device, buf_ptr);
}
else
NU_Local_Control_Interrupts(old_int);
#endif
return(NU_SUCCESS);
} /* NET_Ether_Send */
/*************************************************************************
*
* FUNCTION
*
* NET_Add_Multi
*
* DESCRIPTION
*
* When an ethernet multicast group is joined this function adds an
* entry to the list of ethernet multicast addresses a device should
* receive. If the specified address is already registered with the
* device the reference count is incremented.
*
* INPUTS
*
* *dev
* *d_req
*
* OUTPUTS
*
* NU_SUCCESS
* NU_MEM_ALLOC
* NU_RESET
* -1
*
*************************************************************************/
STATUS NET_Add_Multi(DV_DEVICE_ENTRY *dev, DV_REQ *d_req)
{
UINT8 multi_addr[6];
INT irq_level;
NET_MULTI *em;
UINT8 temp[4];
irq_level = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);
PUT32(temp, 0, LONGSWAP(d_req->dvr_addr));
/* Convert the IP address to a multicast ethernet address. */
NET_MAP_IP_TO_ETHER_MULTI(temp, multi_addr);
/* Verify that the ethernet multicast address is valid. */
if (((multi_addr[0] & 0xFF) != 1) || ((multi_addr[2] & 0xFF) != 0x5e))
{
NU_Local_Control_Interrupts(irq_level);
return (-1);
}
/* Has this address already been added to the list. */
for ( em = dev->dev_ethermulti;
em != NU_NULL && (memcmp(em->nm_addr, multi_addr, 6) != 0);
em = em->nm_next);
if(em != NU_NULL)
{
/* Found a match. Increment the reference count. */
em->nm_refcount++;
NU_Local_Control_Interrupts(irq_level);
return (NU_SUCCESS);
}
/* This is a new address. Allocate some memory for it. */
if (NU_Allocate_Memory(&System_Memory, (VOID **)&em,
sizeof (*em), (UNSIGNED)NU_NO_SUSPEND) != NU_SUCCESS)
{
NU_Local_Control_Interrupts(irq_level);
return(NU_MEM_ALLOC);
}
/* Initialize the new entry. */
memcpy(em->nm_addr, multi_addr, 6);
em->nm_device = dev;
em->nm_refcount = 1;
/* Link it into the list. */
em->nm_next = dev->dev_ethermulti;
dev->dev_ethermulti = em;
/* Restore the previous interrupt lockout level. */
NU_Local_Control_Interrupts(irq_level);
return(NU_RESET);
} /* NET_Add_Multi */
/*************************************************************************
*
* FUNCTION
*
* NET_Del_Multi
*
* DESCRIPTION
*
* When an ethernet multicast group is dropped this function will
* delete the entry from the list of ethernet multicast addresses
* this device should receive if the refernce count drops to 0.
* Else the reference count is decremented.
*
* INPUTS
*
* *dev
* *d_req
*
* OUTPUTS
*
* NU_SUCCESS
* NU_INVAL
* NU_RESET
* -1
*
*************************************************************************/
STATUS NET_Del_Multi(DV_DEVICE_ENTRY *dev, DV_REQ *d_req)
{
UINT8 multi_addr[6];
INT irq_level;
NET_MULTI *em;
NET_MULTI **ptr;
UINT8 temp[4];
irq_level = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);
PUT32(temp, 0, LONGSWAP(d_req->dvr_addr));
/* Convert the IP address to a multicast ethernet address. */
NET_MAP_IP_TO_ETHER_MULTI(temp, multi_addr);
/* Verify that the ethernet multicast address is valid. */
if (((multi_addr[0] & 0xFF) != 1) || ((multi_addr[2] & 0xFF) != 0x5e))
{
NU_Local_Control_Interrupts(irq_level);
return (-1);
}
/* Find this address in the list. */
for ( em = dev->dev_ethermulti;
em != NU_NULL && (memcmp(em->nm_addr, multi_addr, 6) != 0);
em = em->nm_next);
if(em == NU_NULL)
{
/* Found a match. Increment the reference count. */
NU_Local_Control_Interrupts(irq_level);
return (NU_INVAL);
}
/* If this is not the last refernce then return after decremanting the
reference count. */
if (--em->nm_refcount != 0)
{
NU_Local_Control_Interrupts(irq_level);
return(NU_SUCCESS);
}
/* If we made this far then there are no more references to this entry.
So unlink and deallocte it. */
for ( ptr = &em->nm_device->dev_ethermulti;
*ptr != em;
ptr = &(*ptr)->nm_next)
continue;
*ptr = (*ptr)->nm_next;
/* Restore the previous interrupt lockout level. */
NU_Local_Control_Interrupts(irq_level);
/* Deallocate the structure. */
NU_Deallocate_Memory(em);
return(NU_RESET);
} /* NET_Del_Multi */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -