// Thread which will handle dequeing and re-enqueing based on the status // and the flags for all ports in the output buffer void *output_monitor_routine(void *arg) { packet_t in_pkt ; ip_address_t address ; int dest_port=0 ; int loop_count= 0 ; element_to_queue * element ; while(!die) { // Only care dequing if there are elements. if((output_buffer->size > 0)) { // This will indeed dequeue the packet, but we may // have to put it back if the port isn't ready. queue_lock(output_buffer) ; dequeue(output_buffer,&in_pkt) ; queue_unlock(output_buffer) ; // Fetch the IP & lookup destination port ip_address_copy(&(in_pkt.address),&address); dest_port = cam_lookup_address(&address) ; if((dest_port != -1) && (dest_port < 4)) { // Wait for the lock port_lock(&(out_port[dest_port])) ; // If the flag is busy from the last write, then // we have to put the packet back in the queue and just // have to wait until we get to it again. if(out_port[dest_port].flag) { element = calloc(1,sizeof(element_to_queue)) ; packet_copy(&in_pkt,&(element->packet)); queue_lock(output_buffer) ; enqueue(element,output_buffer) ; queue_unlock(output_buffer) ; port_unlock(&(out_port[dest_port])) ; continue ; } // Port ready to be written , so go ahead and write. packet_copy(&in_pkt,&(out_port[dest_port].packet)); out_port[dest_port].flag = TRUE ; port_unlock(&(out_port[dest_port])) ; } } // Make sure it tried to at least deque 5 elements, before we // make it sleep. if(loop_count > LOOP_COUNT) { loop_count = 0 ; sleep() ; } else loop_count++ ; } }
void *switch_thread_routine(void *arg) { int i, k; // For loops while (!die) { // Check if the in ports have any pending packets for (i = 0; i < 4; i++) { port_lock(&(in_port[i])); if (in_port[i].flag) { // If flag is set, deal with the packet int target_port = cam_lookup_address(&in_port[i].packet.address); port_lock(&(out_port[target_port])); // If the target out port is free, send the packet to it. // Else, add the current packet to the port's buffer. if (!out_port[target_port].flag) { out_port[target_port].packet.address = in_port[i].packet.address; out_port[target_port].packet.payload = in_port[i].packet.payload; out_port[target_port].flag = 1; } else { // If the buffer isn't full, add the packet. // Packet will be lost if the buffer is full. if (pending[target_port] < BUFFER_SIZE) { buffers[target_port][++pending[target_port]].address = in_port[i].packet.address; buffers[target_port][pending[target_port]].payload = in_port[i].packet.payload; } } in_port[i].flag = 0; port_unlock(&(out_port[target_port])); } port_unlock(&(in_port[i])); } // Check if the out ports have any pending packets in their buffers for (k = 0; k < 4; k++) { port_lock(&(out_port[k])); // If the output port is free and has packets in its buffer, send pcaktes to the port. if (!out_port[k].flag && pending[k] >= 0) { out_port[k].packet.address = buffers[k][pending[k]].address; out_port[k].packet.payload = buffers[k][pending[k]].payload; out_port[k].flag = 1; pending[k]--; } port_unlock(&(out_port[k])); } } }
void *switch_thread_routine(void *arg) { int inputPortNumber, outputPortNumber, i, j; // For loops int inputPortPriorities[NUM_PORTS]; int outputPortPriorities[NUM_PORTS]; // ex. virtualOutputQueues[inputPort][outputPort] packet_t virtualOutputQueues[NUM_PORTS][NUM_PORTS][VOQ_SIZE]; int virtualOutputQueueReadIndex[NUM_PORTS][NUM_PORTS]; int virtualOutputQueueWriteIndex[NUM_PORTS][NUM_PORTS]; packet_t outputBuffer[NUM_PORTS][OUTPUT_BUFFER_SIZE]; int outputBufferReadIndex[NUM_PORTS]; int outputBufferWriteIndex[NUM_PORTS]; // Initialize the buffers memset(inputPortPriorities, 0, NUM_PORTS * sizeof(int)); memset(outputPortPriorities, 0, NUM_PORTS * sizeof(int)); memset(virtualOutputQueues, 0, NUM_PORTS * NUM_PORTS * VOQ_SIZE * sizeof(packet_t)); memset(virtualOutputQueueReadIndex, 0, NUM_PORTS * NUM_PORTS * sizeof(int)); memset(virtualOutputQueueWriteIndex, 0, NUM_PORTS * NUM_PORTS * sizeof(int)); memset(outputBuffer, 0, NUM_PORTS * OUTPUT_BUFFER_SIZE * sizeof(packet_t)); memset(outputBufferReadIndex, 0, NUM_PORTS * sizeof(int)); memset(outputBufferWriteIndex, 0, NUM_PORTS * sizeof(int)); while (!die) { // Check if the in ports have any pending packets // Add them to the appropriate VOQ for (inputPortNumber = 0; inputPortNumber < NUM_PORTS; inputPortNumber++) { port_lock(&(in_port[inputPortNumber])); if (in_port[inputPortNumber].flag) { // If flag is set, deal with the packet int outputPortNumber = cam_lookup_address(&in_port[inputPortNumber].packet.address); int queueWriteIndex = virtualOutputQueueWriteIndex[inputPortNumber][outputPortNumber]; virtualOutputQueues[inputPortNumber][outputPortNumber][queueWriteIndex].address = in_port[inputPortNumber].packet.address; virtualOutputQueues[inputPortNumber][outputPortNumber][queueWriteIndex].payload = in_port[inputPortNumber].packet.payload; // Increment the write pointer for the virtual output queue virtualOutputQueueWriteIndex[inputPortNumber][outputPortNumber] = (queueWriteIndex + 1) % VOQ_SIZE; int voqwi = virtualOutputQueueWriteIndex[inputPortNumber][outputPortNumber]; // Clear the flag, we've got the packet in a virtual output queue in_port[inputPortNumber].flag = 0; } port_unlock(&(in_port[inputPortNumber])); } // Run a round of the RR-New scheduling algorithm if any of the queues are non-empty // Request phase int totalRequests = 0; // ex. requests[outputPortNumber][inputPortNumber] = TRUE int requests[NUM_PORTS][NUM_PORTS]; for (inputPortNumber = 0; inputPortNumber < NUM_PORTS; inputPortNumber++) { for (outputPortNumber = 0; outputPortNumber < NUM_PORTS; outputPortNumber++) { int queueReadIndex = virtualOutputQueueReadIndex[inputPortNumber][outputPortNumber]; int queueWriteIndex = virtualOutputQueueWriteIndex[inputPortNumber][outputPortNumber]; if (queueReadIndex != queueWriteIndex) { // Indicates the presence of a packet totalRequests++; requests[outputPortNumber][inputPortNumber] = TRUE; } else { // No request to see here... requests[outputPortNumber][inputPortNumber] = FALSE; } } } // We only need to go through the grant/accept phase if there were requests if (totalRequests > 0) { cellTimeCounter++; // Grant phase // ex. grantedRequests[inputPortNumber][outputPortNumber] = TRUE int grantedRequests[NUM_PORTS][NUM_PORTS]; for (outputPortNumber = 0; outputPortNumber < NUM_PORTS; outputPortNumber++) { // Initialize granted to FALSE for (inputPortNumber = 0; inputPortNumber < NUM_PORTS; inputPortNumber++) { grantedRequests[inputPortNumber][outputPortNumber] = FALSE; } // Start at the priority pointer, look for the first request to grant inputPortNumber = outputPortPriorities[outputPortNumber]; for (i = 0; i < NUM_PORTS; i++) { if (requests[outputPortNumber][inputPortNumber]) { grantedRequests[inputPortNumber][outputPortNumber] = TRUE; break; } inputPortNumber = (inputPortNumber + 1) % NUM_PORTS; } } // Accept phase for (inputPortNumber = 0; inputPortNumber < NUM_PORTS; inputPortNumber++) { // Start at the priority pointer, look for the first grant to accept outputPortNumber = inputPortPriorities[inputPortNumber]; for (i = 0; i < NUM_PORTS; i++) { if (grantedRequests[inputPortNumber][outputPortNumber]) { // Accept! Send the packet over int queueReadIndex = virtualOutputQueueReadIndex[inputPortNumber][outputPortNumber]; packet_t packet = virtualOutputQueues[inputPortNumber][outputPortNumber][queueReadIndex]; virtualOutputQueueReadIndex[inputPortNumber][outputPortNumber] = (queueReadIndex + 1) % VOQ_SIZE; port_lock(&(out_port[outputPortNumber])); // If the target out port is free, send the packet to it. // Else, add the current packet to the port's buffer. if (!out_port[outputPortNumber].flag) { out_port[outputPortNumber].packet.address = packet.address; out_port[outputPortNumber].packet.payload = packet.payload; out_port[outputPortNumber].flag = 1; } else { // Add the packet to the output buffer to be read later int writeIndex = outputBufferWriteIndex[outputPortNumber]; outputBuffer[outputPortNumber][writeIndex].address = packet.address; outputBuffer[outputPortNumber][writeIndex].payload = packet.payload; // Bump the write index outputBufferWriteIndex[outputPortNumber] = (writeIndex + 1) % OUTPUT_BUFFER_SIZE; } port_unlock(&(out_port[outputPortNumber])); // Update the priority trackers inputPortPriorities[inputPortNumber] = (outputPortNumber + 1) % NUM_PORTS; outputPortPriorities[outputPortNumber] = (inputPortNumber + 1) % NUM_PORTS; // We're done here... break; } // Haven't accepted anything yet, keep on tryin' outputPortNumber = (outputPortNumber + 1) % NUM_PORTS; } } } // Check if the out ports have any pending packets in their buffers for (outputPortNumber = 0; outputPortNumber < NUM_PORTS; outputPortNumber++) { port_lock(&(out_port[outputPortNumber])); // If the output port is free and has packets in its buffer, send them int readIndex = outputBufferReadIndex[outputPortNumber]; int writeIndex = outputBufferWriteIndex[outputPortNumber]; if (!out_port[outputPortNumber].flag && readIndex != writeIndex) { packet_t packet = outputBuffer[outputPortNumber][readIndex]; out_port[outputPortNumber].packet.address = packet.address; out_port[outputPortNumber].packet.payload = packet.payload; out_port[outputPortNumber].flag = 1; outputBufferReadIndex[outputPortNumber] = (readIndex + 1) % OUTPUT_BUFFER_SIZE; } port_unlock(&(out_port[outputPortNumber])); } } }