📄 nnetdrv.c
字号:
NERRS_Log_Error (NERR_FATAL, __FILE__, __LINE__);
SNMP_ifOutErrors_Inc(device->dev_index);
}
/* Initialize the data required to generate the events. Note that the
MNTID field was initialized up above. */
mGeneventOut->SelfID = MNT_ID;
mGeneventOut->MemPtr = MNT_Header_Ptr->MNT_hdr_cpuDesc;
mGeneventOut->Count = mRingputInfo->Count;
status = DeviceIoControl (hDriver,
(DWORD) IOCTL_MULTI_GENEVENT,
mGeneventOut,
sizeof(ULONG) * (3 + mGeneventOut->Count),
&successCount,
sizeof(ULONG),
&cbReturned,
0);
/* Check to see that all the events were generated. */
if (successCount != mGeneventOut->Count)
{
SNMP_ifOutErrors_Inc(device->dev_index);
NERRS_Log_Error (NERR_SEVERE, __FILE__, __LINE__);
}
SNMP_ifOutOctets(device->dev_index, pack_addr->mem_total_data_len);
}
else
{
/* The following steps must be performed to process this packet.
1) First we need the ID of the MNT process to which the packet is
to be sent. That is simple enough. It can be extracted from
the packet (the destination ethernet address is also the ID.)
Unless this is destined for a node on a real network. This can
also be determined from the ethernet address. In which case we
send it to NDIS whose ID is always 0.
2) Once we know the ID a ringget can be performed to extract a
buffer from the buffer free list. ringget should return either
a pointer or an offset from the beginning of the common memory
area. In either case the packet can be copied to this buffer.
3) Next a ringput is performed to place the now ready buffer
into the receive list for the destination node, whether that be
NDIS or some MNT process.
4) Finally a genevent will be performed to let the receiving node
know that a packet is awaiting processing.
*/
/* Is this packet destined for a node on the virtual network or for a
node on the real network. If destined for the virtual network then
the ID is the same as the last octet of the ethernet address. Else
the ID equals 0, i.e., the ID for the NDIS driver.
*/
if( (memcmp(dlayer->dest, "\0\0\0\0\0", 5) == 0)
&& ((dlayer->dest[5] - (CHAR)VNET_BaseEtherAddr) < (LONG)VNET_Ncpu)
&& (dlayer->dest[5] != 0))
{
/* The packet is destined for the virtual network.
The destination id = last octet of ether addr - base ether addr. */
dest_id = dlayer->dest[5] - (CHAR)VNET_BaseEtherAddr;
}
else
{
/* This packet needs to go to the NDIS driver. */
dest_id = 0;
}
mnt_cpu_ptr = MNT_Header_Ptr->MNT_hdr_cpuDesc;
if(!mnt_cpu_ptr[dest_id].MNT_cd_active)
return -1;
/* Do a ringget from the buffer free list. */
/* We will need to provide the pointer to the anchor and a pointer to
the freelist ring. Note that the driver needs the address that was
mapped by NDIS. */
ringgetInfo.MemPtr = NDISComMemStart;
ringgetInfo.RingPtr = ItoKval(MNT_Header_Ptr->MNT_hdr_pFreeRing,
PMNT_RING,
NDISComMemStart);
if (!DeviceIoControl (hDriver,
(DWORD) IOCTL_RINGGET,
&ringgetInfo,
sizeof(ringgetInfo),
&bufferOffset,
sizeof(bufferOffset),
&cbReturned,
0) )
{
SNMP_ifOutErrors_Inc(device->dev_index);
NERRS_Log_Error (NERR_SEVERE, __FILE__, __LINE__);
return -1;
}
/* Was a buffer retrieved? */
if(bufferOffset == 0)
{
SNMP_ifOutErrors_Inc(device->dev_index);
return -1;
}
buf_node_ptr = ItoKval(bufferOffset, PMNT_BUF_NODE, CommonMemPtr);
/* Copy the packet from the buffer chain. */
/* Do the parent buffer first */
memcpy((CHAR *)CommonMemPtr + (ULONG)buf_node_ptr->MNT_b_addr,
buf_ptr->data_ptr, buf_ptr->data_len);
/* Update the bytes copied. */
bytes_copied = buf_ptr->data_len;
/* Loop through the chain if needed and copy all buffers. */
while (buf_ptr->next_buffer != NU_NULL)
{
/* Move to the next buffer in the chain */
buf_ptr = buf_ptr->next_buffer;
/* Copy the data */
memcpy((CHAR *)CommonMemPtr + (ULONG)buf_node_ptr->MNT_b_addr + bytes_copied,
buf_ptr->mem_packet, buf_ptr->data_len);
/* Update the bytes copied. */
bytes_copied += buf_ptr->data_len;
} /* end while there are buffers in the chain */
buf_node_ptr -> MNT_b_len = (UINT16) pack_addr->mem_total_data_len;
ringputInfo.MemPtr = NDISComMemStart;
ringputInfo.RingPtr =
ItoKval(MNT_Header_Ptr->MNT_hdr_cpuDesc[dest_id].MNT_cd_pInputRing,
PMNT_RING,
NDISComMemStart);
ringputInfo.BuffNodeOffset = bufferOffset;
status = DeviceIoControl (hDriver,
(DWORD) IOCTL_RINGPUT,
&ringputInfo,
sizeof(ringputInfo),
&ringputStatus,
sizeof(ringputStatus),
&cbReturned,
0);
if ((!status) || (ringputStatus == 0))
{
NERRS_Log_Error (NERR_SEVERE, __FILE__, __LINE__);
SNMP_ifOutErrors_Inc(device->dev_index);
return -1;
}
/* Now set the event to let the destination node know that a packet is
waiting to be processed.
*/
/* First initialize the data required to generate an event. */
geneventInfo.SelfID = MNT_ID;
geneventInfo.MemPtr = MNT_Header_Ptr->MNT_hdr_cpuDesc;
geneventInfo.MNTID = dest_id;
/* Generate the event. */
if(!DeviceIoControl (hDriver,
IOCTL_GENEVENT,
&geneventInfo,
sizeof(geneventInfo),
NULL,
0,
&cbReturned,
0) )
{
SNMP_ifOutErrors_Inc(device->dev_index);
NERRS_Log_Error (NERR_SEVERE, __FILE__, __LINE__);
return -1;
}
SNMP_ifOutOctets(device->dev_index, pack_addr->mem_total_data_len);
}
return (NU_SUCCESS);
} /* end NU_Xmit */
/******************************************************************************
* FUNCTION
*
* VDRV_ISR
*
* DESCRIPTION
*
* This is the entry point for the simulated interrupt. It is actually
* called, however, from the NT receive thread NU_Recv_Packet. This
* function retrieves a packet from this receive ring. The received
* packet is placed onto the buffer_list where it can be processed by the
* upper layer software. Once the packet is copied the receive HISR is
* activated.
*
* AUTHOR
*
* Glen Johnson
*
* INPUTS
*
* none
*
* OUTPUTS
*
* sshort : Returns NU_SUCCESS if ok, else -1
*
*
******************************************************************************/
INT VDRV_ISR(INT vector)
{
INT bufferOffset = 0;
NET_BUFFER *buf_ptr, *work_buf;
IOCTL_OUT_RINGGET ringgetInfo;
IOCTL_OUT_RINGPUT ringputInfo;
IPKT *pkt_ptr;
DWORD cbReturned;
MNT_BUF_NODE *buf_node_ptr;
#if (INCLUDE_SNMP == NU_TRUE)
INT octets;
#endif
INT pktlen;
INT ringputStatus;
DV_DEVICE_ENTRY *device;
INT32 bytes_left;
UINT8 *work_ptr;
/* Find the device for this interrupt. */
device = DEV_Get_Dev_For_Vector(vector);
if (device == NU_NULL)
return -1;
/* Do a ringget from our receive list. */
/* We will need to provide the pointer to the anchor and the offset to
the freelist ring. */
ringgetInfo.MemPtr = NDISComMemStart;
ringgetInfo.RingPtr = ItoKval(
MNT_Header_Ptr->MNT_hdr_cpuDesc[MNT_ID].MNT_cd_pInputRing,
PMNT_RING,
NDISComMemStart);
/* Get the packet. */
if (!DeviceIoControl (hDriver,
(DWORD) IOCTL_RINGGET,
&ringgetInfo,
sizeof(ringgetInfo),
&bufferOffset,
sizeof(bufferOffset),
&cbReturned,
0) )
{
SNMP_ifInErrors_Inc(device->dev_index);
NERRS_Log_Error (NERR_SEVERE, __FILE__, __LINE__);
return -1;
}
/* Was a packetretrieved? */
if(bufferOffset == 0)
{
SNMP_ifInErrors_Inc(device->dev_index);
return -1;
}
buf_node_ptr = (MNT_BUF_NODE *)((CHAR *)CommonMemPtr + bufferOffset);
pkt_ptr = (IPKT *)((CHAR *)CommonMemPtr + (ULONG)buf_node_ptr->MNT_b_addr);
/* Now determine how big the packet is. The only way I know to do this is
to extract the info from the packet itself. Switch on the packet type. */
switch (INTSWAP(pkt_ptr->d.type))
{ /* what to do with it? */
case EARP:
case ERARP:
pktlen = sizeof(ARP_LAYER) + sizeof(DLAYER);
break;
case EIP:
/* For an IP packet the size is computed by adding together the IP
data length, the IP header, and the size of the ethernet header.
*/
pktlen = INTSWAP(pkt_ptr->i.ip_tlen) + sizeof(DLAYER);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -