def computeLoads(self): """ Computes the load of each link in the target net """ loads = {} for link in self.links.values(): loads[str(link)] = str(createQuantity(link.computeLoad("direct"))) + "b/s, direct. " + str(createQuantity(link.computeLoad("inverse"))) + "b/s, inverse." printIfVerbose(str(link) + " carries " + loads[str(link)] + " over the flows: " + str([str(s) for s in link.flows])) return loads
def isDirectWith(self, nodeA, nodeB): """ Returns true if nodeB comes after nodeA in the target's path, false otherwise """ direct = None if nodeA == nodeB: print("ERROR: Tried to see if {0} was direct with respect to identical nodes {1}".format(self, nodeA)) raise ValueError completePath = [self.source] + self.path # XML path does not contain the source for node in completePath: if node == nodeA: if direct == False: return False elif direct == True: print("ERROR: This is a circular path that does not contain node B?") raise ValueError # Circular path that does not contain nodeB? else: direct = True elif node == nodeB: if direct == True: return True elif direct == False: print("ERROR: This is a circular path that does not contain node B?") raise ValueError # Circular path that does not contain nodeA? else: direct = False if direct == True: print("ERROR: {0} does not contain node B: {1}".format(self, nodeB)) printIfVerbose([str(k) for k in completePath]) elif direct == False: print("ERROR: {0} does not contain node A: {1}".format(self, nodeA)) printIfVerbose([str(k) for k in completePath]) else: print("ERROR: {0} does not contain neither {1} nor {2}".format(self, nodeA, nodeB)) raise ValueError
def stabilityPrint(thing, arrival): printIfVerbose("{0} has a transmission capacity {1}b/s and an arrival curve {2}b/s".format(thing, createQuantity(thing.transmission_capacity), createQuantity(arrival)))
def computeTargetArrivalAffine(self, target): """ Computes target's output arrival affine curve, total delay up to this point, backlog, and total arrival curves incoming to this outgoing port of the node Relies on theorem 1 calculation to find the delay given a known arrival curve and a know service curve, and on theorem 2 to calculate the arrival curve at the output of a node knowing the maximum delay through that node and the input arrival curve. This calculation is highly recursive! It will call itself on all nodes within the paths of all flows using the same output link of this node as the one used by the given target. """ printIfVerbose("Calculating affine output arrival of {0} for flux {1}\n".format(str(self), str(target))) totalArrival = AffineCurve(0, 0) tempArrival = AffineCurve(0, 0) totalDelay = 0 # Stores the flow's delay bound up until this node link = target.findOutgoingLink(self) # Find out the outgoing link of this traffic linkDelayCalculated = self.delayBoundsPerLink[link] >= 0 flows = link.getFlowsInSameDirection(target) # If source, if self == target.source: for flow in flows.values(): tempArrival = flow.computeArrivalAffine() if flow == target.parentFlow: arrival = tempArrival totalArrival += tempArrival # Otherwise as per theorem 2, we can obtain it by computing the output affine of the intervening nodes else: # Calculate the output arrival by recursively calling this function on said node for flow in flows.values(): currentTarget = flow.findTargetPassingThroughNode(self) previousNode = currentTarget.findPreviousNode(self) if not linkDelayCalculated or flow == target.parentFlow: tempOutput = previousNode.computeTargetArrivalAffine(currentTarget) tempArrival = tempOutput["outputArrival"] tempDelay = tempOutput["delay"] if flow == target.parentFlow: totalDelay += tempDelay # Add the delay up to this point arrival = tempArrival totalArrival += tempArrival printIfVerbose("Looking at node " + str(self.name)) printIfVerbose("The input arrival curve to {0} for {1} is {2}".format(self, target.parentFlow, arrival)) # Now we need to factor in how multiplexing flows affects the service curve of the node service = self.getWorstCaseService(target) printIfVerbose("The adjusted service curve of {0} is {1}".format(link,service)) printIfVerbose("The aggregate arrival curve to {0} for {1} is {2}".format(self, link, totalArrival)) backlog = computeTheorem1Backlog(totalArrival, service) printIfVerbose("Backlog for {0} is {1}".format(self, backlog)) # Next, calculate the incurred delay in this node given the new arrival and service curves if not linkDelayCalculated: delay = computeTheorem1Delay(totalArrival, service) # Store values for future reference self.delayBoundsPerLink[link] = delay self.totalArrivalsPerLink[link] = totalArrival self.backlogsPerLink[link] = backlog else: delay = self.delayBoundsPerLink[link] totalArrival = self.totalArrivalsPerLink[link] backlog = self.backlogsPerLink[link] totalDelay += delay printIfVerbose("Delay at node {0} is {1}s".format(self.name, createQuantity(delay))) outputArrival = arrival.delayBy(delay) printIfVerbose("The output arrival curve of {0} for {1} is {2} \n".format(self, target.parentFlow, outputArrival)) return {"outputArrival": outputArrival, "delay": totalDelay, "totalArrival": totalArrival, "backlog": backlog}
def parseXML(XMLPath): """ Parses an XML file with the appropriat format for the exercice and creates its data structure, returning a network object """ tree = parse(XMLPath) root = tree.getroot() for child in root: # Parse the network first if child.tag == "network": printIfVerbose("Building a " + child.tag + " called " + child.attrib["name"]) name = "" overhead = 0 transmission_capacity = 0 x_type = "" for attributeName in child.attrib: if attributeName == "name": name = child.attrib[attributeName] elif attributeName == "overhead": overhead = 8 * interpretQuantity( child.attrib[attributeName]) elif attributeName == "transmission-capacity": transmission_capacity = interpretQuantity( child.attrib[attributeName]) elif attributeName == "x-type": x_type = child.attrib[attributeName] net = Classes.Network(name, overhead, transmission_capacity, x_type) break else: print("ERROR: Could not find a network node!") # All attribute assignation referring to network nodes are first done as strings, and then # the corresponding nodes are assigned AFTER we've ensured all the nodes have been created. for child in root: printIfVerbose("Building a " + child.tag + " called " + child.attrib["name"]) if child.tag == "station": name = "" transmission_capacity = 0 x = 0 y = 0 for attributeName in child.attrib: if attributeName == "name": name = child.attrib[attributeName] elif attributeName == "transmission-capacity": transmission_capacity = interpretQuantity( child.attrib[attributeName]) elif attributeName == "x": x = child.attrib[attributeName] elif attributeName == "y": y = child.attrib[attributeName] newStation = Classes.Station(name, transmission_capacity, x, y) newStation.setNetwork(net) net.stations[name] = newStation elif child.tag == "switch": name = "" transmission_capacity = 0 x = 0 y = 0 redundancy = "Unspecified" for attributeName in child.attrib: if attributeName == "name": name = child.attrib[attributeName] elif attributeName == "transmission-capacity": transmission_capacity = interpretQuantity( child.attrib[attributeName]) elif attributeName == "x": x = child.attrib[attributeName] elif attributeName == "y": y = child.attrib[attributeName] elif attributeName == "redundancy": redundancy = child.attrib[attributeName] newSwitch = Classes.Switch(name, transmission_capacity, x, y) if redundancy != "Unspecified": newSwitch.setRedundancy(redundancy) newSwitch.setNetwork(net) net.switches[name] = newSwitch elif child.tag == "link": name = "" start = "" startPort = "" end = "" endPort = "" transmission_capacity = 0 for attributeName in child.attrib: if attributeName == "name": name = child.attrib[attributeName] elif attributeName == "from": start = child.attrib[attributeName] elif attributeName == "fromPort": startPort = child.attrib[attributeName] elif attributeName == "to": end = child.attrib[attributeName] elif attributeName == "toPort": endPort = child.attrib[attributeName] elif attributeName == "transmission-capacity": transmission_capacity = interpretQuantity( child.attrib[attributeName]) newLink = Classes.Link(name, start, startPort, end, endPort, transmission_capacity) newLink.setNetwork(net) net.links[name] = newLink elif child.tag == "flow": deadline = 0 jitter = 0 max_payload = 0 name = "" period = 0 priority = 0 source = "" redundancy = "MAIN" for attributeName in child.attrib: if attributeName == "deadline": deadline = interpretQuantity(child.attrib[attributeName]) elif attributeName == "jitter": jitter = interpretQuantity(child.attrib[attributeName]) elif attributeName == "max-payload": max_payload = 8 * interpretQuantity( child.attrib[attributeName]) elif attributeName == "name": name = child.attrib[attributeName] elif attributeName == "period": period = 1e-3 * interpretQuantity( child.attrib[attributeName]) elif attributeName == "priority": priorityString = child.attrib[attributeName] if priorityString == "Low": priority = 0 elif priorityString == "High": priority = 1 else: print( "ERROR: The priority string for {0} is not admitted!" .format(name)) elif attributeName == "transmission-capacity": transmission_capacity = interpretQuantity( child.attrib[attributeName]) elif attributeName == "source": source = child.attrib[attributeName] #Find the end system and add it to the targets list newFlow = Classes.Flow(deadline, jitter, max_payload, name, period, priority, source) newFlow.setNetwork(net) net.flows[name] = newFlow for targetElement in child: # Gather attributes targetStationName = targetElement.attrib["name"] sourceStationName = child.attrib["source"] try: redundancy = child.attrib["redundancy"] except: redundancy = "Unspecified" # Create target target = Classes.Target(targetStationName, sourceStationName, newFlow) # Assign redundancy if redundancy != "Unspecified": target.setRedundancy(redundancy) # Add target to flow targets newFlow.targets[targetStationName] = target # Build target's path for pathComponent in targetElement: pathNodeName = pathComponent.attrib["node"] target.path.append(pathNodeName) target.setNetwork(net) # Nodes have been asigned as names, correct to objects for link in net.links.values(): link.start = net.getNode(link.start) link.end = net.getNode(link.end) for flow in net.flows.values(): source = net.getNode(flow.source) flow.source = source for target in flow.targets.values(): target.target = net.getNode(target.target) target.source = net.getNode(target.source) for i in range(len(target.path)): target.path[i] = net.getNode(target.path[i]) printIfVerbose("Path for target " + target.name + " is " + str([str(s) for s in target.path])) if not target.hasPath(): print("ERROR: " + str(target) + " path was not built correctly!") # Initializes some variables net.initializeNodes() printIfVerbose("The network has been fully built!") return net