📄 nwip.pc
字号:
staticvoid ExpandReassemblyBuffer( GlomoNode* node, IpReassemblyBufferType* reassemblyBuffer, int minSize) { int newSize; Message* biggerBufferPacket = GLOMO_MsgAlloc(node, 0, 0, 0); newSize= (reassemblyBuffer->sizeLimit * REASSEMBLY_BUFFER_EXPANSION_MULTIPLIER); if (newSize < minSize) { assert(minSize <= IP_MAXPACKET); newSize = minSize; }//if// if (newSize > IP_MAXPACKET) { newSize = IP_MAXPACKET; }//if// GLOMO_MsgPacketAlloc(node, biggerBufferPacket, newSize); memcpy(biggerBufferPacket->packet, reassemblyBuffer->packetUnderConstruction->packet, reassemblyBuffer->sizeLimit); reassemblyBuffer->sizeLimit = newSize; GLOMO_MsgFree(node, reassemblyBuffer->packetUnderConstruction); reassemblyBuffer->packetUnderConstruction = biggerBufferPacket;}//// Simple Bit vector manipulation macros.//#define BitIsSet(BitVector, Index) \ ((BitVector[(Index)/8] & (1 << ((Index) % 8))) != 0) #define SetBit(BitVector, Index) \ BitVector[(Index)/8] |= (1 << ((Index) % 8));//// FUNCTION CheckForFragmentBufferCompletion() //// PURPOSE Checks the reassembly buffer to if it is complete.// The answer is passed back in the "packetIsComplete" // boolean output variable.//staticvoid CheckForFragmentBufferCompletion( IpReassemblyBufferType* reassemblyBuffer, BOOL* packetIsComplete){ int I; int lastIndex = reassemblyBuffer->endFragmentOffset / reassemblyBuffer->fragmentationSize; // Set the extra bits in the end char in the bit vector, if they // have not already been set. if (!BitIsSet(reassemblyBuffer->fragmentIsHereBitTable, lastIndex)) { for(I = lastIndex; (I < ((lastIndex/8) + 1) * 8); I++) { SetBit(reassemblyBuffer->fragmentIsHereBitTable, I); }//for// }//if// // Super fast byte comparison. All the bits of the bit vector must // be 1. for(I = 0; (I < ((lastIndex/8) + 1)); I++) { if (reassemblyBuffer->fragmentIsHereBitTable[I] != 0xFF) { *packetIsComplete = FALSE; return; }//if// }//for// *packetIsComplete = TRUE;} //// FUNCTION AddFragmentToReassemblyBuffer() //// PURPOSE Adds the data in a packet fragment to the reassembly buffer.// if that was the last fragment the routine sets a boolean// ("packetIsComplete") and returns a pointer to the complete// packet ("competedPacket").// staticvoid AddFragmentToReassemblyBuffer( GlomoNode* node, IpReassemblyBufferType* reassemblyBuffer, const Message* msg, BOOL* packetIsComplete, Message** completedPacket){ // // Determine the length and where the fragment's data should go. // Expand the reassembly buffer if the packet is too large. // Message* bufferPacket = NULL; IpHeaderType* ipHeader = (IpHeaderType*)msg->packet; int ipHeaderSize = IpHeaderSize(ipHeader); int fragmentOffset = FragmentOffset(ipHeader); int fragmentDataLength = ipHeader->ip_len - ipHeaderSize; char* fragmentData = msg->packet + IpHeaderSize(ipHeader); int packetLengthSoFar = ipHeaderSize + fragmentOffset + fragmentDataLength; *packetIsComplete = FALSE; reassemblyBuffer->expirationDate = simclock() + NETWORK_IP_REASS_BUFF_TIMER; if (packetLengthSoFar > reassemblyBuffer->sizeLimit) { ExpandReassemblyBuffer(node, reassemblyBuffer, packetLengthSoFar); }//if// // // Copy in the fragment's data into the reassembly buffer. Then // set the bit in the table to says that the fragment has arrived. // Currently one bit for each equally sized fragment (except last). // Its not totally general, but probably is good enough. // bufferPacket = reassemblyBuffer->packetUnderConstruction; memcpy( &(bufferPacket->packet[ipHeaderSize + fragmentOffset]), fragmentData, fragmentDataLength); if (ipHeader->ip_more_fragments == 0) { reassemblyBuffer->endFragmentHasArrived = TRUE; reassemblyBuffer->endFragmentOffset = fragmentOffset; } else { int fragmentIndex; if (reassemblyBuffer->fragmentationSize == 0) { reassemblyBuffer->fragmentationSize = fragmentDataLength; }//if// // Only simple same sized fragments implemented. assert(fragmentDataLength == reassemblyBuffer->fragmentationSize); fragmentIndex = fragmentOffset / reassemblyBuffer->fragmentationSize; assert(fragmentIndex < MAX_IP_FRAGMENTS_SIMPLE_CASE); SetBit(reassemblyBuffer->fragmentIsHereBitTable, fragmentIndex); }//if// // // Check to see if all fragments have arrived and the packet is complete. // if ((reassemblyBuffer->endFragmentHasArrived) && (reassemblyBuffer->fragmentationSize != 0)) { CheckForFragmentBufferCompletion(reassemblyBuffer, packetIsComplete); if (*packetIsComplete) { *completedPacket = reassemblyBuffer->packetUnderConstruction; reassemblyBuffer->packetUnderConstruction = NULL; }//if// }//if//}//AddFragmentToReassemblyBuffer////// FUNCTION InitializeReassemblyBuffer() //// PURPOSE Initializes a new reassembly buffer with a packet fragment.//staticvoid InitializeReassemblyBuffer( GlomoNode* node, IpReassemblyBufferType* reassemblyBuffer, const Message* msg){ int I; BOOL NotUsed; IpHeaderType* msgIpHeader = (IpHeaderType *) msg->packet; int ipHeaderSize = IpHeaderSize(msgIpHeader); IpHeaderType* bufferIpHeader = NULL; // // Allocate a message to act as a reassembly buffer. // reassemblyBuffer->sizeLimit = SMALL_REASSEMBLY_BUFFER_SIZE; reassemblyBuffer->packetUnderConstruction = GLOMO_MsgAlloc(node, 0, 0, 0); GLOMO_MsgPacketAlloc(node, reassemblyBuffer->packetUnderConstruction, reassemblyBuffer->sizeLimit); // // Copy over the IP packet header and set the fields in the // reassembly buffer to initial values including setting the // "fragment is here" bit table to all 0's. // memcpy( reassemblyBuffer->packetUnderConstruction->packet, msg->packet, ipHeaderSize); bufferIpHeader = (IpHeaderType*)reassemblyBuffer->packetUnderConstruction->packet; bufferIpHeader->ip_len = 0; SetFragmentOffset(bufferIpHeader, 0); reassemblyBuffer->fragmentationSize = 0; reassemblyBuffer->endFragmentHasArrived = FALSE; reassemblyBuffer->endFragmentOffset = 0; for(I = 0; I < (MAX_IP_FRAGMENTS_SIMPLE_CASE/8); I++) { reassemblyBuffer->fragmentIsHereBitTable[I] = 0; } // Add the fragment's data to the reassembly buffer. AddFragmentToReassemblyBuffer(node, reassemblyBuffer, msg, &NotUsed, 0);}//// FUNCTION ProcessFragmentAndMaybeBuildCompletePacket() //// PURPOSE Creates or finds an existing reassembly buffer and moves// the data from the passed message fragment into the buffer.// Then detects whether if all pieces of the packet has arrived// and if it has it passes the completed packet out and// deletes that reassembly buffer. The routine also scans// for expired reassembly buffers (only when creating a new// buffer).//staticvoid ProcessFragmentAndMaybeBuildCompletePacket( GlomoNode* node, const Message* msg, BOOL* packetIsComplete, Message** completedPacket) { GlomoNetworkIp* ipLayer = (GlomoNetworkIp *)node->networkData.networkVar; IpReassemblyBufferType* reassemblyBuffer = NULL; BOOL foundAnExistingBuffer; *packetIsComplete = FALSE; IpReassemblyBufferList_FindOrCreateNew( &ipLayer->reassemblyBufferList, msg, &reassemblyBuffer, &foundAnExistingBuffer); if (!foundAnExistingBuffer) { InitializeReassemblyBuffer(node, reassemblyBuffer, msg); RemoveExpiredIpReassemblyBuffers( node, &ipLayer->reassemblyBufferList, simclock()); } else { if (!ReassemblyBufferHasExpired(reassemblyBuffer, simclock())) { AddFragmentToReassemblyBuffer(node, reassemblyBuffer, msg, packetIsComplete, completedPacket); if (*packetIsComplete) { IpReassemblyBufferList_Delete( &ipLayer->reassemblyBufferList, &reassemblyBuffer); }//if// }//if// }//if//}//ProcessFragmentAndMaybeBuildCompletePacket////-----------------------------------------------------------------------------//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// ROUTING FUNCTIONS//// Simple functions to look at and set the out of memory// alignment addresses.//staticNODE_ADDR ConvertRawAddressBytesToNodeAddress(char RawAddressBytes[]) { // Done because the address bytes may be out of alignment // on certain processors. NODE_ADDR nodeAddress; memcpy(&nodeAddress, RawAddressBytes, sizeof(NODE_ADDR)); return nodeAddress;}staticvoid SetRawAddressBytes(NODE_ADDR nodeAddress, char RawAddressBytes[]) { // Done because the address bytes may be out of alignment // on certain processors. memcpy(RawAddressBytes, &nodeAddress, sizeof(NODE_ADDR));}//// FUNCTION SourceRouteThePacket()//// PURPOSE Find the next hop in the source route and send the// packet. // staticvoid SourceRouteThePacket(GlomoNode *node, Message *msg) { IpOptionsHeaderType* ipOptions = IpHeaderSourceRouteOptionField((IpHeaderType*)msg->packet); if (ipOptions->ptr < ipOptions->len) { // Extract Next Address // The definition of "ptr" seems to number 1 as the // first byte of the the options field. char* routeRawAddressBytes = (char*)ipOptions + ipOptions->ptr - 1; NODE_ADDR nextHop = ConvertRawAddressBytesToNodeAddress(routeRawAddressBytes); // Record Route (Replace next address with this node's address). ipOptions->ptr += sizeof(NODE_ADDR); NetworkIpSendPacketToMacLayer( node, msg, DEFAULT_INTERFACE, nextHop); } else { assert(FALSE); abort(); /* Drop it, strange */ GLOMO_MsgFree(node, msg); }//if//} //// FUNCTION RouteThePacketUsingLookupTable()//// PURPOSE Tries to route and send the packet using the "forwarding// lookup table. // staticvoid RouteThePacketUsingLookupTable(GlomoNode *node, Message *msg) { GlomoNetworkIp* ipLayer = (GlomoNetworkIp *)node->networkData.networkVar; IpHeaderType *ipHeader = (IpHeaderType *) msg->packet; InterfaceIdType interfaceId; NODE_ADDR nextHop; NetworkGetInterfaceAndNextHopFromForwardingTable(node, ipHeader->ip_dst, &interfaceId, &nextHop); if (nextHop == NETWORK_UNREACHABLE) { ipLayer->stats.numNetworkUnreachableDrops++; GLOMO_MsgFree(node, msg); return; } NetworkIpSendPacketToMacLayer(node, msg, interfaceId, nextHop);}//// FUNCTION RoutePacketAndSendToMac()//// PURPOSE Figure out the next hop in the route and send the packet.// First the "routing function" is checked and if that fails// the default source route or lookup table route is used.// staticvoid RoutePacketAndSendToMac(GlomoNode *node, Message *msg) { GlomoNetworkIp *ipLayer = (GlomoNetworkIp *)node->networkData.networkVar; IpHeaderType *ipHeader = (IpHeaderType *) msg->packet; // // Check if its a broadcast. // if (ipHeader->ip_dst == ANY_DEST) { NetworkIpSendPacketToMacLayer(node, msg, DEFAULT_INTERFACE, ANY_DEST); } else { // First Try to route with the routing protocol supplied routing // function. If the function doesn't exists or // fails to find a route, then try standard lookup table // or source routing. BOOL PacketWasRouted = FALSE; if (ipLayer->routerFunction != NULL) { (ipLayer->routerFunction)( node, msg, ipHeader->ip_dst, &PacketWasRouted); }//if// if (!PacketWasRouted) { if (IpHeaderHasSourceRoute(ipHeader)) { SourceRouteThePacket(node, msg); } else { RouteThePacketUsingLookupTable(node, msg); }//if// }//if// }//if//}//RoutePacketAndSendToMac////-----------------------------------------------------------------------------// FRAGMENTATION ROUTINES//// FUNCTION NetworkIpSendPacketToMacLayer()//// PURPOSE Sends a IP packet to the MAC layer. If the packet is too// large it is fragmented. The next hop's node address// is specified in "nextHop". void NetworkIpSendPacketToMacLayer( GlomoNode* node, Message* msg,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -