#include #include #include "tcp.h" #include "demux.h" // Demux.c // This files implements the software demultiplexer that gets packets // to the user space immediately. #define MAX_ENTRIES 128 TableEntry DemuxTable[MAX_ENTRIES]; #define NUMBER_OF_HINTS 2 int Hints[NUMBER_OF_HINTS]; // Most recently looked up table entries // Q operations. Put here, instead of header file, because tcp // file uses same ops but without pointers to the Q structure #define HEAD(Q) (Q->head) #define TAIL(Q) (Q->tail) #define NOT_EMPTY(Q) (Q->head!=Q->tail) #define Q_FULL(Q) (Q->head==(Q->tail+1)%MAX_Q_SIZE) #define ENQ(Q) (Q->tail=(Q->tail+1)%MAX_Q_SIZE) #define DEQ(Q) (Q->head=(Q->head+1)%MAX_Q_SIZE) // Initialize the demux table. If Q is NULL, table entry is empty void InitTable() { int i; for (i=0; iflags_offset & 0x3FFF) != 0) { HandleUncommonPacket(Packet); return; } // Check incoming packet for type (we already know it is IP) if ((Packet->ttl_proto & 0x00ff) == TCP_PROTO_NUMBER) { // Check hint 0 i=Hints[0]; if (Packet->source_IP==DemuxTable[i].SourceIP && Packet->ports==DemuxTable[i].Ports) { queue=DemuxTable[i].UserQ; // Push on user Q if (Q_FULL(queue)) { // HandleQOverflow(queue, Packet); return; } queue->data[TAIL(queue)]=Packet; ENQ(queue); return; } // Check hint 1 i=Hints[1]; if (Packet->source_IP==DemuxTable[i].SourceIP && Packet->ports==DemuxTable[i].Ports) { queue=DemuxTable[i].UserQ; // Push on user Q if (Q_FULL(queue)) { // HandleQOverflow(queue, Packet); return; } queue->data[TAIL(queue)]=Packet; ENQ(queue); return; } // Do a full search for (i=0; isource_IP==DemuxTable[i].SourceIP && Packet->ports==DemuxTable[i].Ports) { queue=DemuxTable[i].UserQ; // Push on user Q if (Q_FULL(queue)) { // HandleQOverflow(queue, Packet); return; } queue->data[TAIL(queue)]=Packet; ENQ(queue); // Update hints Hints[1]=Hints[0]; Hints[0]=i; return; } } // Drop packet } // Handle UDP or other packet type }