summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/rip/send.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/tdi/isn/rip/send.c')
-rw-r--r--private/ntos/tdi/isn/rip/send.c524
1 files changed, 524 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/rip/send.c b/private/ntos/tdi/isn/rip/send.c
new file mode 100644
index 000000000..22810fe6c
--- /dev/null
+++ b/private/ntos/tdi/isn/rip/send.c
@@ -0,0 +1,524 @@
+/*******************************************************************/
+/* Copyright(c) 1993 Microsoft Corporation */
+/*******************************************************************/
+
+//***
+//
+// Filename: send.c
+//
+// Description: send packet routines
+//
+// Author: Stefan Solomon (stefans) October 11, 1993.
+//
+// Revision History:
+//
+//***
+
+#include "rtdefs.h"
+
+VOID
+SendPacketComplete(PPACKET_TAG pktp);
+
+UINT
+SendPropagatedPacketComplete(PPACKET_TAG pktp);
+
+VOID
+UpdateSendStatistics(PNICCB niccb,
+ PPACKET_TAG pktp);
+
+VOID
+SetType20PktDestNet(PPACKET_TAG pktp);
+
+VOID
+UpdateRipResponseTickCount(PUCHAR hdrp,
+ PNICCB niccbp);
+
+
+//*** max send pkts queued limit: over this limit the send pkts get discarded
+
+ULONG MaxSendPktsQueued = MAX_SEND_PKTS_QUEUED;
+
+//***
+//
+// Function: SendPacket
+//
+// Descr: enqueues the packet in the requested Nic queue and initiates
+// the send
+//
+// Params: Packet
+//
+// Returns: none
+//
+//***
+
+VOID
+SendPacket(PPACKET_TAG pktp)
+{
+ PNDIS_PACKET pktdescrp;
+ NDIS_STATUS NdisStatus;
+ UINT BufferCount;
+ PNDIS_BUFFER FirstBufferp;
+ USHORT pktlen;
+ PNICCB niccbp;
+ PUCHAR hdrp;
+
+ RtPrint(DBG_SEND, ("IpxRouter: SendPacket: pktp=0x%x\n", pktp));
+
+ // get the packet length
+ hdrp = pktp->DataBufferp;
+ GETSHORT2USHORT(&pktlen, hdrp + IPXH_LENGTH);
+
+ // get the pkt descr ptr
+ pktdescrp = CONTAINING_RECORD(pktp, NDIS_PACKET, ProtocolReserved);
+
+ // adjust the length of the packet to send
+ NdisQueryPacket(pktdescrp,
+ NULL,
+ &BufferCount,
+ &FirstBufferp,
+ NULL);
+
+ NdisAdjustBufferLength(FirstBufferp, pktlen);
+
+ // chain the mac hdr buff descr at the front (the mac hdr buff descr
+ // already points at the Mac header in the packet tag)
+ NdisChainBufferAtFront(pktdescrp, pktp->HeaderBuffDescrp);
+
+ // get the Nic Cb ptr where we should send this packet
+ niccbp = NicCbPtrTab[pktp->RemoteAddress.NicId];
+
+ // Do not send if it doesn't fit the max frame size
+ // for this adapter
+ if(pktlen > niccbp->MaximumPacketSize) {
+
+ SendPacketComplete(pktp);
+ return;
+ }
+
+ // if the packet is a RIP Response, update the tick count in the
+ // network entry fields
+ UpdateRipResponseTickCount(hdrp, niccbp);
+
+ ACQUIRE_SPIN_LOCK(&niccbp->NicLock);
+
+ // check Nic Status. Do not send on a closed Nic
+ if(niccbp->NicState != NIC_ACTIVE) {
+
+ RELEASE_SPIN_LOCK(&niccbp->NicLock);
+
+ SendPacketComplete(pktp);
+ return;
+ }
+
+ // check if we are allowed to queue this packet (we aren't over limit)
+ if(niccbp->SendPktsQueuedCount >= MaxSendPktsQueued) {
+
+ RELEASE_SPIN_LOCK(&niccbp->NicLock);
+
+ SendPacketComplete(pktp);
+ return;
+ }
+
+
+ // Nic is active, we can send
+ UpdateSendStatistics(niccbp, pktp);
+
+ // set the QUEUE owner of the packet
+ pktp->QueueOwnerNicCbp = niccbp;
+
+ // enqueue the packet in the NIC's send list and wait for the
+ // transfer to complete
+ InsertTailList(&niccbp->SendQueue, &pktp->PacketLinkage);
+
+ // increment the queued pkts counter
+ niccbp->SendPktsQueuedCount++;
+
+ RELEASE_SPIN_LOCK(&niccbp->NicLock);
+
+ // send the packet
+ NdisStatus = IpxSendPacket(&pktp->RemoteAddress,
+ pktdescrp,
+ pktlen,
+ 0);
+
+
+ if(NdisStatus != NDIS_STATUS_PENDING) {
+
+ RtSendComplete(pktdescrp, NdisStatus);
+ }
+}
+
+//***
+//
+// Function: RtSendComplete
+//
+// Descr: called by the IPX driver when send completed
+//
+// Params:
+//
+// Returns:
+//
+//***
+
+VOID
+RtSendComplete(PNDIS_PACKET pktdescrp,
+ NDIS_STATUS NdisStatus)
+{
+ PNICCB niccbp;
+ PPACKET_TAG pktp;
+
+ pktp = (PPACKET_TAG)pktdescrp->ProtocolReserved;
+
+ RtPrint(DBG_SEND, ("IpxRouter: RtSendComplete: pktp=0x%x\n", pktp));
+
+ niccbp = pktp->QueueOwnerNicCbp;
+
+#if DBG
+ // this is for debugging purposes
+ if(NdisStatus != NDIS_STATUS_SUCCESS) {
+
+ RtPrint(DBG_NOTIFY, ("IpxRouter: SendPacket: FAILED with %xl\n", NdisStatus));
+ }
+#endif
+
+ // dequeue the packet from the send queue and complete processing
+ ACQUIRE_SPIN_LOCK(&niccbp->NicLock);
+
+ RemoveEntryList(&pktp->PacketLinkage);
+
+ // decrement queued send pkts counter
+ niccbp->SendPktsQueuedCount--;
+
+ RELEASE_SPIN_LOCK(&niccbp->NicLock);
+
+ // complete the send packet processing
+ SendPacketComplete(pktp);
+}
+
+//***
+//
+// Function: SendPacketComplete
+//
+// Descr: post send processing
+//
+// Params: Packet
+//
+// Returns: None
+//
+//***
+
+VOID
+SendPacketComplete(PPACKET_TAG pktp)
+{
+ PNDIS_PACKET NdisPacket;
+ PNDIS_BUFFER NdisBuffer = NULL;
+ UINT BufferCount;
+
+ RtPrint(DBG_SEND, ("IpxRouter: SendPacketComplete: Entered\n"));
+
+ // unchain the first buffer descriptor (MacHeader)
+ NdisPacket = CONTAINING_RECORD(pktp, NDIS_PACKET, ProtocolReserved);
+ NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
+ ASSERT(NdisBuffer == pktp->HeaderBuffDescrp);
+
+ // readjust the original buffer descriptor length
+ // get the pkt descr ptr
+ NdisQueryPacket(NdisPacket,
+ NULL,
+ &BufferCount,
+ &NdisBuffer,
+ NULL);
+
+ NdisAdjustBufferLength(NdisBuffer, pktp->DataBufferLength);
+ NdisRecalculatePacketCounts(NdisPacket);
+
+ // what to do next is controlled by the packet type
+ switch(pktp->PacketType) {
+
+ case RCV_PACKET:
+
+ // this has been a routed packet or a directed rip reply
+ // free it to the rcv pkt pool and discharge the nic
+
+ FreeRcvPkt(pktp);
+
+ break;
+
+ case RIP_SEND_PACKET:
+
+ // call the completion routines for these guys
+ SendRipPktCompleted(pktp);
+
+ break;
+
+ case PROPAGATED_BCAST_PACKET:
+
+ // send the packet on the next available net (if any left) or return it
+ // to the pool
+ if(SendPropagatedPacketComplete(pktp)) {
+
+ RtPrint(DBG_NETBIOS, ("IpxRouter: SendPacketComplete: free propagated pkt 0x%x\n", pktp));
+
+ // can't propagate further, return to rcv pkt pool
+ FreeRcvPkt(pktp);
+ }
+
+ break;
+
+ default:
+
+ // !!! break
+ ASSERT(FALSE);
+ break;
+ }
+}
+
+//***
+//
+// Function: SendPropagatedPacket
+//
+// Descr: marks the packet as a propagated packet type and sends it
+// starting at the beginning of the LanNics list
+//
+// Params: Packet
+//
+// Returns: none
+//
+//***
+
+VOID
+SendPropagatedPacket(PPACKET_TAG pktp)
+{
+ USHORT i;
+ PNICCB niccbp;
+
+ // check if there is an active Nic to send on next and if this Nic is
+ // active and is not the packet owner nic
+ for(i=0; i<MaximumNicCount; i++) {
+
+ niccbp = NicCbPtrTab[i];
+
+ if((niccbp->NicState == NIC_ACTIVE) &&
+ (IsNetbiosRoutingAllowed(pktp->PacketOwnerNicCbp, niccbp)) &&
+ (!IsNetInNbPacket(pktp, niccbp))) {
+
+ // send the packet on this nic
+ pktp->PacketType = PROPAGATED_BCAST_PACKET;
+ pktp->RemoteAddress.NicId = niccbp->NicId;
+ memcpy(pktp->RemoteAddress.MacAddress, bcastaddress, 6);
+
+ RtPrint(DBG_NETBIOS, ("IpxRouter: SendPropagatedPacket: send pkt 0x%x on Nic %d\n", pktp, niccbp->NicId));
+ SetType20PktDestNet(pktp);
+ SendPacket(pktp);
+
+ return;
+ }
+ }
+
+ // can't propagate this packet, free it
+ FreeRcvPkt(pktp);
+}
+
+//***
+//
+// Function: SendPropagatedPacketComplete
+//
+// Descr: If there is a next active NicCb to send the packet on, queues
+// the packet in the propagation list and queues a Dpc to send the
+// packet on this Nic.
+//
+// Params: Packet
+//
+// Returns: 0 - packet queued for propagation, 1 - can't propagate further
+//
+//***
+
+UINT
+SendPropagatedPacketComplete(PPACKET_TAG pktp)
+{
+ PNICCB niccbp; // nic that has sent the packet
+ USHORT i;
+
+ // check if there is another active Nic to send on next and if this Nic is
+ // active and is not the packet owner nic
+ for(i=pktp->RemoteAddress.NicId+1; // next Nic Id
+ i<MaximumNicCount;
+ i++) {
+
+ niccbp = NicCbPtrTab[i];
+
+ if((niccbp->NicState == NIC_ACTIVE) &&
+ (IsNetbiosRoutingAllowed(pktp->PacketOwnerNicCbp, niccbp)) &&
+ (!IsNetInNbPacket(pktp, niccbp))) {
+
+ // We have found the next nic.
+ pktp->RemoteAddress.NicId = i;
+
+ // queue the packet for a propagated send.
+ ACQUIRE_SPIN_LOCK(&PropagatedPktsListLock);
+
+ InsertTailList(&PropagatedPktsList, &pktp->PacketLinkage);
+
+ if(!PropagatedPktsDpcQueued) {
+
+ // queue a Dpc to send the packet
+ KeInsertQueueDpc(&PropagatedPktsDpc, NULL, NULL);
+ PropagatedPktsDpcQueued = TRUE;
+ }
+
+ RELEASE_SPIN_LOCK(&PropagatedPktsListLock);
+
+ return 0;
+ }
+ }
+
+ // we are done with this packet
+ return 1;
+}
+
+//***
+//
+// Function: SendNextPropagatedPacket
+//
+// Descr: DPC called routine which dequeues the next packet from the
+// propagated packets list and sends it
+//
+// Params: none
+//
+// Returns: none
+//
+//***
+
+
+VOID
+SendNextPropagatedPkt(PKDPC Dpc,
+ PVOID DefferedContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2)
+{
+ PLIST_ENTRY lep;
+ PPACKET_TAG pktp;
+ LIST_ENTRY sendlist;
+
+ InitializeListHead(&sendlist);
+
+ // get next item from the propagated bcast queue and send it
+
+ ACQUIRE_SPIN_LOCK(&PropagatedPktsListLock);
+
+ PropagatedPktsDpcQueued = FALSE;
+
+ while(!IsListEmpty(&PropagatedPktsList)) {
+
+ lep = RemoveHeadList(&PropagatedPktsList);
+ InsertTailList(&sendlist, lep);
+ }
+
+ RELEASE_SPIN_LOCK(&PropagatedPktsListLock);
+
+ while(!IsListEmpty(&sendlist)) {
+
+ lep = RemoveHeadList(&sendlist);
+ pktp = CONTAINING_RECORD(lep, PACKET_TAG, PacketLinkage);
+ SetType20PktDestNet(pktp);
+ SendPacket(pktp);
+ }
+}
+
+VOID
+UpdateSendStatistics(PNICCB niccbp,
+ PPACKET_TAG pktp)
+{
+ PUCHAR hdrp;
+ USHORT srcsock;
+
+ switch(pktp->PacketType) {
+
+ case RCV_PACKET:
+
+ hdrp = pktp->DataBufferp;
+ GETSHORT2USHORT(&srcsock, hdrp + IPXH_DESTSOCK);
+
+ if(srcsock == IPX_RIP_SOCKET) {
+
+ niccbp->StatRipSent++;
+ }
+ else
+ {
+ niccbp->StatRoutedSent++;
+ }
+
+ break;
+
+ case RIP_SEND_PACKET:
+
+ niccbp->StatRipSent++;
+ break;
+
+ case PROPAGATED_BCAST_PACKET:
+
+ niccbp->StatType20Sent++;
+ break;
+
+ default:
+
+ break;
+
+ }
+}
+
+VOID
+SetType20PktDestNet(PPACKET_TAG pktp)
+{
+ PNICCB niccbp;
+ PUCHAR hdrp;
+
+ // get the Nic Cb ptr where we should send this packet
+ niccbp = NicCbPtrTab[pktp->RemoteAddress.NicId];
+
+ // set the destination net in the packet
+ hdrp = pktp->DataBufferp;
+
+ memcpy(hdrp + IPXH_DESTNET, niccbp->Network, 4);
+}
+
+
+VOID
+UpdateRipResponseTickCount(PUCHAR hdrp,
+ PNICCB niccbp)
+{
+ USHORT resplen;
+ USHORT pktlen;
+ USHORT srcsock;
+ USHORT opcode;
+ USHORT nrofticks;
+
+ // check if this is a RIP Response packet
+ GETSHORT2USHORT(&srcsock, hdrp + IPXH_SRCSOCK);
+ if(srcsock != IPX_RIP_SOCKET) {
+
+ return;
+ }
+
+ GETSHORT2USHORT(&opcode, hdrp + RIP_OPCODE);
+ if(opcode != RIP_RESPONSE) {
+
+ return;
+ }
+
+ //*** RIP Response Packet ***
+
+ // get the response packet length
+ GETSHORT2USHORT(&pktlen, hdrp + IPXH_LENGTH);
+
+ // for each network entry, increment the number of ticks so that
+ // we add the nr of ticks for the nic to send the packet on
+ for(resplen = RIP_INFO;
+ resplen < pktlen;
+ resplen += NE_ENTRYSIZE) {
+
+ GETSHORT2USHORT(&nrofticks, hdrp + resplen + NE_NROFTICKS);
+ nrofticks += niccbp->TickCount;
+ PUTUSHORT2SHORT(hdrp + resplen + NE_NROFTICKS, nrofticks);
+ }
+}