''' Created on Sep 27, 2011 @author: ochipara ''' from random import randint, seed class Packet(): def __init__(self, source, seq, packet_length = 8): # source - the source of the packet # seq - is the sequence number of the packet # packet_length - length of packet in terms of # of slots # remaining_time - remaining time until completion of the packet # corrupted - is the packet corrupted or not self.source = source self.seq = 0 self.packet_length = packet_length self.remaining_time = packet_length - 1 self.corrupted = False def key(self): return (self.node_id, self.seq) def __str__(self): return "src: %d seq: %d corrupted: %d remain: %d" % (self.source, self.seq, self.corrupted, self.remaining_time) class Node(): def __init__(self, node_id): # queue stores the queue for the node, its maximum size is controlled by max_queue_size # head represents the packet that is currently processed # time_to_tx - controls when a new packet is to generated by the application # backoff_counter, cw - should control the backoff counter and the contention window self.node_id = node_id self.queue = [] self.max_queue_size = 16 self.head = None self.avgerage_tx_rate = 100 self.time_to_tx = randint(0, self.avgerage_tx_rate * 2) self.cw = 64 self.backoff_counter = 0 self.seq = 0 def new_packet(self): packet = Packet(self.node_id, self.seq) self.seq += 1 return packet def generate_traffic(self): if (self.time_to_tx == 0): self.time_to_tx = randint(0, self.avgerage_tx_rate * 2) return self.new_packet() else: self.time_to_tx = self.time_to_tx - 1 return None def drop(self, p): print "drop packet" def execute(self, slot, carrier_sense): # node_it - the id of the node # slot - the current slot number # returns the packet the node will transmit # simulate pkt transmission at a rate of 1pkt / 10 slots new_packet = self.generate_traffic() if (new_packet != None): if (len(self.queue) + 1 < self.max_queue_size): self.queue.append(new_packet) else: self.drop(new_packet) if len(self.queue) > 0 and self.head == None: self.head = self.queue[0] self.queue = self.queue[1:] # initialize the backoff counter self.backoff_counter = randint(0, self.cw) if (self.head != None): # start attempting to transmit if (self.backoff_counter == 0): # transmit the packet tmp = self.head self.head = None return tmp else: self.backoff_counter = self.backoff_counter - 1 return None def simulate(nodes, num_slots): concurrent_packets = {} sent_packets = [] for t in range(num_slots): carrier_sense = (len(concurrent_packets) > 0) for n in nodes: packet = nodes[n].execute(t, carrier_sense) if (packet != None): print t, "sending", str(packet) concurrent_packets[packet.key] = packet # mark the packets as corrupted if there are concurrent transmissions # remove the packets that have completed their time to_delete = [] for packet_key in concurrent_packets: packet = concurrent_packets[packet_key] packet.corrupted = packet.corrupted | (len(concurrent_packets) > 1) packet.remaining_time = packet.remaining_time - 1 if (packet.remaining_time == 0): to_delete.append(packet_key) for packet_key in to_delete: sent_packets.append(concurrent_packets[packet_key]) del concurrent_packets[packet_key] # compute stats correct = 0.0 bad = 0 for pkt in sent_packets: if pkt.corrupted: bad +=1 else: correct += 1 total = correct + bad print "good: %.2f (%d) bad: %.2f (%d)" % ((correct / total * 100), correct, (bad / total * 100), bad) if __name__ == "__main__": seed(5000) # make sure you have a reproducible result num_nodes = 2 nodes = {} for n in range(num_nodes): nodes[n] = Node(n) simulate(nodes, 1000)