'''
Created on Jan 24, 2011
@author: peyman kazemian
'''
from sts.headerspace.headerspace.hs import *
from array import array
from sts.headerspace.headerspace.wildcard_dictionary import wildcard_dictionary
import logging
log = logging.getLogger("headerspace")
[docs]def ports_to_hex(ports):
return map(port_to_hex, ports)
[docs]def port_to_hex(port):
return hex(port)
[docs]class TF(object):
'''
models a box transfer function, a network transfer function or a topology transfer function
'''
[docs] def __init__(self, hsa_format):
'''
Constructor
'''
# For backwards compabibility
if type(hsa_format) == int:
self.length = hsa_format
self.format = None
else:
self.length = hsa_format["length"] * 2
self.format = hsa_format
self.rules = []
self.custom_rules = []
self.lazy_eval_nibbles = []
self.inport_to_rule = {}
self.outport_to_rule = {}
self.id_to_rule = {}
self.next_id = 0
self.prefix_id = ""
self.lazy_eval_active = False
self.send_on_receiving_port = False
# TRIAL - won't be saved upon tf.save()
self.hash_table_active = False
self.hash_nibble_indices = []
self.inport_to_hash_table = {}
[docs] def set_prefix_id(self,str_prefix):
self.prefix_id = str_prefix
[docs] def set_send_on_receiving_port(self, val):
self.send_on_receiving_port = val
[docs] def generate_next_id(self):
self.next_id = self.next_id + 1
return "%s_%d"%(self.prefix_id,self.next_id)
[docs] def set_lazy_evaluate(self,list_of_nibbles):
self.lazy_eval_nibbles = list_of_nibbles
[docs] def activate_lazy_eval(self):
self.lazy_eval_active = True
[docs] def deactivate_lazy_eval(self):
self.lazy_eval_active = False
[docs] def activate_hash_table(self,nibble_indices):
self.hash_table_active = True
self.hash_nibble_indices = nibble_indices
for key in self.inport_to_rule.keys():
self.inport_to_hash_table[key] = wildcard_dictionary(4,50)
for rule in self.inport_to_rule[key]:
tmp = []
for index in self.hash_nibble_indices:
tmp.append(rule["match"][index])
self.inport_to_hash_table[key].add_entry(tmp,rule)
[docs] def deactivate_hash_table(self):
self.hash_table_active = False
[docs] def print_influences(self):
'''
For each rule, shows the list of higher priority rules that has an intersection with
the rule, and also the lower priority rules that has an intersection with the rule,
in two separate lists.
'''
for rule in self.rules:
print "%s Rule Match: %s,%s"%(rule["action"],byte_array_to_pretty_hs_string(rule["match"]),rule["in_ports"])
print "Affected by:"
for aff in rule["affected_by"]:
print "%s: On Ports %s, Intersect= %s"%(byte_array_to_pretty_hs_string(aff[0]["match"]),aff[2],
byte_array_to_pretty_hs_string(aff[1]))
print "Influence on:"
for aff in rule["influence_on"]:
print "%s"%(byte_array_to_pretty_hs_string(aff["match"]))
print "-------------------"
[docs] def hs_string(self, byte_array):
match = headerspace(self.format)
match.add_hs(byte_array)
return str(match)
[docs] def to_string(self):
strings = []
for rule in self.rules:
match = self.hs_string(rule['match'])
if (rule['action'] == 'rw'):
mask = self.hs_string(rule['mask'])
rewrite = self.hs_string(rule['rewrite'])
string = "in_ports: %s, match: %s => ((h & %s) | %s, %s)" % ((rule['in_ports']), \
match, mask, rewrite, (rule['out_ports']))
strings.append(string)
if (rule['action'] == 'fwd'):
string = "in_ports: %s, match: %s => (h , %s)" % ((rule['in_ports']), \
match, (rule['out_ports']))
strings.append(string)
if (rule['action'] == 'link'):
string = "in_ports: %s => out_ports: %s" % ((rule['in_ports']), \
(rule['out_ports']))
strings.append(string)
if (rule['action'] == 'custom'):
string = "match: %s , transform: %s" % (rule['match'].__name__, \
rule['transform'].__name__)
strings.append(string)
return strings
[docs] def inv_to_string(self):
strings = []
for rule in self.rules:
if (rule['action'] == 'rw'):
inv_match = byte_array_to_hs_string(rule['inverse_match'])
mask = byte_array_to_hs_string(rule['mask'])
inv_rewrite = byte_array_to_hs_string(rule['inverse_rewrite'])
string = "out_ports: %s match: %s => ((h & %s) | %s, %s)" % ((rule['out_ports']), \
inv_match, mask, inv_rewrite, (rule['in_ports']))
strings.append(string)
if (rule['action'] == 'fwd'):
match = byte_array_to_hs_string(rule['match'])
string = "out_ports: %s match: %s => (h , %s)" % ((rule['out_ports']), \
match, (rule['in_ports']))
strings.append(string)
if (rule['action'] == 'link'):
string = "out_ports: %s => in_ports: %s)" % ((rule['out_ports']), \
(rule['in_ports']))
strings.append(string)
return strings
@staticmethod
[docs] def create_multirewrite_rule(in_ports, match, rules):
'''
creates a rule that if matches on in_ports, match, does all the actions
in rules. the in_ports,matches in rules will be the same as in_ports, match
in the multi-rewrite rule.
'''
rule = {}
rule["in_ports"] = in_ports
if match.__class__ == str:
rule["match"] = hs_string_to_byte_array(match)
elif match.__class__ == bytearray:
rule["match"] = bytearray(match)
else:
rule["match"] = None
rule["rules"] = rules
rule["influence_on"] = []
rule["affected_by"] = []
return rule
@staticmethod
[docs] def create_custom_rule(match,transform,inv_match,inv_transform,file_name,lines):
rule = {}
rule["match"] = match
rule["inv_match"] = inv_match
rule["transform"] = transform
rule["inv_transform"] = inv_transform
if file_name != None:
rule["file"] = file_name
else:
rule["file"] = ""
rule["line"] = []
rule["line"].extend(lines)
rule["id"] = None
return rule
@staticmethod
[docs] def create_standard_rule(in_ports, match, out_ports, mask, rewrite,file_name="",lines=[]):
'''
Create a rule using input arguments. Use None if an input is not applicable.
'''
rule = {}
rule["in_ports"] = in_ports
rule["out_ports"] = out_ports
if match.__class__ == str:
rule["match"] = hs_string_to_byte_array(match)
elif match.__class__ == bytearray:
rule["match"] = bytearray(match)
else:
rule["match"] = None
if mask.__class__ == str:
rule["mask"] = hs_string_to_byte_array(mask)
elif mask.__class__ == bytearray:
rule["mask"] = bytearray(mask)
else:
rule["mask"] = None
if rewrite.__class__ == str:
rule["rewrite"] = hs_string_to_byte_array(rewrite)
elif rewrite.__class__ == bytearray:
rule["rewrite"] = bytearray(rewrite)
else:
rule["rewrite"] = None
rule["influence_on"] = []
rule["affected_by"] = []
if file_name != None:
rule["file"] = file_name
else:
rule["file"] = ""
rule["line"] = []
rule["line"].extend(lines)
rule["id"] = None
return rule
@staticmethod
[docs] def standard_rule_to_string(std_rule):
string = ""
string += "ID = %s, "%std_rule["id"]
string += "in_ports = %s, "%(std_rule["in_ports"])
string += "match = %s, "%byte_array_to_hs_string(std_rule["match"])
string += "mask = %s, "%byte_array_to_hs_string(std_rule["mask"])
string += "rewrite = %s, "%byte_array_to_hs_string(std_rule["rewrite"])
string += "out_ports = %s"%(std_rule["out_ports"])
return string
[docs] def find_influences(self, priority):
'''
After inserting the new_rule, into self.rules, call this method to update the
rule dependencies.
@priority: priority or position of the new rule in the table
'''
new_rule = self.rules[priority]
for i in range(0,priority):
if self.rules[i]["action"] == "rw" or self.rules[i]["action"] == "fwd":
common_ports = [val for val in new_rule["in_ports"] if val in self.rules[i]["in_ports"]]
intersect = byte_array_intersect(self.rules[i]["match"],new_rule["match"])
if len(intersect) > 0 and len(common_ports) > 0:
new_rule["affected_by"].append((self.rules[i],intersect,common_ports))
self.rules[i]["influence_on"].append(self.rules[priority])
for i in range(priority+1,len(self.rules)):
if self.rules[i]["action"] == "rw" or self.rules[i]["action"] == "fwd":
common_ports = [val for val in new_rule["in_ports"] if val in self.rules[i]["in_ports"]]
intersect = byte_array_intersect(self.rules[i]["match"],new_rule["match"])
if len(intersect) > 0 and len(common_ports) > 0:
new_rule["influence_on"].append(self.rules[i])
self.rules[i]["affected_by"].append((self.rules[priority],intersect,common_ports))
[docs] def set_fast_lookup_pointers(self, priority):
new_rule = self.rules[priority]
in_ports = self.rules[priority]["in_ports"]
out_ports = self.rules[priority]["out_ports"]
for p in in_ports:
port = "%d"%p
if port not in self.inport_to_rule.keys():
self.inport_to_rule[port] = []
self.inport_to_rule[port].append(new_rule)
for p in out_ports:
port = "%d"%p
if port not in self.outport_to_rule.keys():
self.outport_to_rule[port] = []
self.outport_to_rule[port].append(new_rule)
self.id_to_rule[new_rule["id"]] = new_rule
[docs] def add_rewrite_rule(self, rule, priority= -1):
'''
rule is a dictionary with following keys:
* 'match': a bytearray of length self.length describing the header formats that
match this rule.
* 'in_ports': the list of input port numbers to match on
* 'mask': a bytearray of length self.length that masks all the bits that won't
be rewritten
* 'rewrite': a bytearray of length self.length that rewrites the desired bits.
* 'out_ports': the list of output port numbers.
'''
extended_rule = rule.copy()
extended_rule['match'] = bytearray(rule['match'])
extended_rule['mask'] = bytearray(rule['mask'])
# Mask rewrite
extended_rule['rewrite'] = byte_array_and(byte_array_not(rule['mask']), rule['rewrite'])
extended_rule['action'] = "rw"
masked = byte_array_and(rule['match'], rule['mask'])
rng = byte_array_or(masked, rule['rewrite'])
extended_rule['inverse_match'] = rng
extended_rule['inverse_rewrite'] = byte_array_and(byte_array_not(rule['mask']), rule['match'])
extended_rule["id"] = self.generate_next_id()
if (priority == -1 or priority >= len(self.rules)):
self.rules.append(extended_rule)
priority = len(self.rules) - 1
else:
self.rules.insert(priority, extended_rule)
self.find_influences(priority)
self.set_fast_lookup_pointers(priority)
[docs] def add_fwd_rule(self, rule, priority=-1):
'''
* 'match': a bytearray of length self.length describing the header formats that
match this rule.
* 'in_ports': the list of input port numbers to match on
* 'out_ports': the list of output port numbers.
'''
extended_rule = rule.copy()
extended_rule['match'] = bytearray(rule['match'])
extended_rule['action'] = "fwd"
extended_rule['inverse_match'] = None
extended_rule['inverse_rewrite'] = None
extended_rule["id"] = self.generate_next_id()
if (priority == -1 or priority >= len(self.rules)):
self.rules.append(extended_rule)
priority = len(self.rules) - 1
else:
self.rules.insert(priority, extended_rule)
#self.find_influences(priority)
self.set_fast_lookup_pointers(priority)
[docs] def add_link_rule(self, rule, priority = -1):
'''
This is useful for topology transfer fucntions
* 'in_ports': the list of input port numbers to match on
* 'out_port': the list of output port numbers.
WARNING: Use link rule only in Topology Transfer Function. Don't mix it with other
type of rules.
'''
extended_rule = rule.copy()
extended_rule['action'] = "link"
extended_rule['inverse_match'] = None
extended_rule['inverse_rewrite'] = None
extended_rule["id"] = self.generate_next_id()
if (priority == -1):
self.rules.append(extended_rule)
priority = len(self.rules) - 1
else:
self.rules.insert(priority, extended_rule)
self.set_fast_lookup_pointers(priority)
[docs] def add_custom_rule(self, rule, priority=-1):
'''
Add a custom rule. You need to provide a function for finding math
and a function for creating output header.
rule should have the following entries:
* 'match': a pointer to the function for finding if a packet match this rule.
the function should accept (headerspace,in_port) as input and returns a list of
headerspace objects that match this rule
* 'transform': a pointer to a function which outputs a list of (headerspace, list of out_ports)
pairs as the output of the rule.
* 'inv_match': a pointer to the function for finding if an output packet can be
generated by this rule. The function format is like "match'.
* 'inv_transform': a pointer to a function which outputs a list of (headerspace,
list of in_ports) pairs as the output of the inverse rule.
WARNING: use custom rules in a transfer function with only custom rules. Interaction between
custom rules and rewrite/fw rules is not defined.
'''
extended_rule = rule.copy()
extended_rule['action'] = "custom"
extended_rule["id"] = self.generate_next_id()
if (priority == -1):
self.rules.append(extended_rule)
priority = len(self.rules) - 1
else:
self.rules.insert(priority, extended_rule)
self.id_to_rule[extended_rule["id"]] = extended_rule
self.custom_rules.append(self.rules[priority])
[docs] def apply_rewrite_rule(self,rule,hs,port,applied_rules=None):
mod_outports = list(rule["out_ports"])
'''
if (not self.send_on_receiving_port) and (port in mod_outports):
mod_outports.remove(port)
'''
if len(mod_outports) == 0:
return []
new_hs = hs.copy_intersect(rule['match'])
if new_hs.count() > 0 and port in rule["in_ports"]:
for i in range(0,len(new_hs.hs_list)):
barr = byte_array_or(byte_array_and(new_hs.hs_list[i],rule['mask']),rule['rewrite'])
new_hs.hs_list[i] = barr
for (r, h, in_ports) in rule["affected_by"]:
if port in in_ports and (applied_rules == None or r["id"] in applied_rules):
new_hs.diff_hs(h)
for i in range(0,len(new_hs.hs_diff)):
barr = byte_array_or(byte_array_and(new_hs.hs_diff[i],rule['mask']),rule['rewrite'])
new_hs.hs_diff[i] = barr
#new_hs.clean_up()
if (new_hs.count() == 0):
return []
new_hs.push_applied_tf_rule(self,rule["id"],port)
applied_rules.append(rule["id"])
return [(new_hs,mod_outports)]
else:
return []
[docs] def apply_fwd_rule(self,rule,hs,port,applied_rules=None):
mod_outports = list(rule["out_ports"])
'''
if (not self.send_on_receiving_port) and (port in mod_outports):
mod_outports.remove(port)
'''
if len(mod_outports) == 0:
return []
new_hs = hs.copy_intersect(rule['match'])
if new_hs.count() > 0 and port in rule["in_ports"]:
for (r, h, in_ports) in rule["affected_by"]:
if port in in_ports and (applied_rules == None or r["id"] in applied_rules):
new_hs.diff_hs(h)
#new_hs.clean_up()
if (new_hs.count() == 0):
return []
new_hs.push_applied_tf_rule(self,rule["id"],port)
applied_rules.append(rule["id"])
return [(new_hs,mod_outports)]
else:
return []
[docs] def apply_link_rule(self,rule,hs,port):
if port in rule["in_ports"]:
ohs = hs.copy()
ohs.push_applied_tf_rule(self,rule["id"],port)
return [(ohs,list(rule['out_ports']))]
else:
return []
[docs] def apply_custom_rule(self,rule,hs,port):
result = []
matches = rule["match"](hs,port)
if len(matches) > 0:
for match in matches:
tmp_hp = rule["transform"](match,port)
for (out_hs,out_ports) in tmp_hp:
if out_hs.count() > 0:
out_hs.push_applied_tf_rule(self,rule["id"],port)
result.append((out_hs,out_ports))
return result
[docs] def T(self,hs,port):
'''
returns a list of (hs, list of output ports) as a result of applying transfer function.
hs will have A-B format, where A is the intersection of hs and the rule's match struct
and B will be union of match bytes of all the rules that influence on the matching rule.
'''
result = []
applied_rules = []
rule_set = []
#TODO: Hack! fix it
if self.inport_to_rule.has_key("%d"%port) and (not self.hash_table_active or len(hs.hs_list)>1):
rule_set = self.inport_to_rule["%d"%port]
elif self.hash_table_active and self.inport_to_hash_table.has_key("%d"%port):
tmp = []
for index in self.hash_nibble_indices:
tmp.append(hs.hs_list[0][index])
rule_set = self.inport_to_hash_table["%d"%port].find_entry(tmp)
for rule in rule_set:
#check if this rule qualifies for lazy evaluation
if (self.lazy_eval_active and self.is_qualified_for_lazy_eval(rule)):
lazy_hs = hs.copy()
lazy_hs.add_lazy_tf_rule(self,rule["id"],port)
result.append(lazy_hs,rule["out_ports"])
# link rule
elif rule['action'] == "link":
result.extend(self.apply_link_rule(rule, hs, port))
# rewrite rule
elif rule['action'] == "rw":
result.extend(self.apply_rewrite_rule(rule, hs, port,applied_rules))
# forward rule
elif rule['action'] == "fwd":
result.extend(self.apply_fwd_rule(rule, hs, port,applied_rules))
# custom rules
for rule in self.custom_rules:
result.extend(self.apply_custom_rule(rule, hs, port))
return result
[docs] def T_rule(self,rule_id,hs,port):
'''
Apply rule with id = rule_id to (hs,port)
Output is a list of [hs,list_of_out_ports].
'''
result = []
if self.id_to_rule.has_key(rule_id):
rule = self.id_to_rule[rule_id]
if rule['action'] == "link":
result = self.apply_link_rule(rule, hs, port)
elif rule['action'] == "rw":
result = self.apply_rewrite_rule(rule, hs, port)
elif rule['action'] == "fwd":
result = self.apply_fwd_rule(rule, hs, port)
elif rule['action'] == "custom":
result = self.apply_custom_rule(rule, hs, port)
return result
[docs] def apply_inv_link_rule(self,rule,hs,port):
if (port in rule["out_ports"]):
ihs = hs.copy()
ihs.push_applied_tf_rule(self,rule["id"],port)
return [(ihs,list(rule['in_ports']))]
else:
return []
[docs] def apply_inv_rewrite_rule(self,rule,hs,port):
result = []
new_hs = hs.copy_intersect(rule['inverse_match'])
if new_hs.count() > 0:
for i in range(0,len(new_hs.hs_list)):
barr = byte_array_or(byte_array_and(new_hs.hs_list[i],rule['mask']),rule['inverse_rewrite'])
new_hs.hs_list[i] = barr
for i in range(0,len(new_hs.hs_diff)):
barr = byte_array_or(byte_array_and(new_hs.hs_diff[i],rule['mask']),rule['inverse_rewrite'])
new_hs.hs_diff[i] = barr
for p in rule["in_ports"]:
next_hs = new_hs.copy()
for (r, h, in_ports) in rule["affected_by"]:
if p in in_ports:
next_hs.diff_hs(h)
next_hs.clean_up()
if (next_hs.count() != 0):
next_hs.push_applied_tf_rule(self,rule["id"],port)
result.append((next_hs,[p]))
return result
[docs] def apply_inv_fwd_rule(self,rule,hs,port):
result = []
new_hs = hs.copy_intersect(rule['match'])
if new_hs.count() > 0:
for p in rule["in_ports"]:
next_hs = new_hs.copy()
for (r, h, in_ports) in rule["affected_by"]:
if p in in_ports:
next_hs.diff_hs(h)
next_hs.clean_up()
if (next_hs.count() != 0):
next_hs.push_applied_tf_rule(self,rule["id"],port)
result.append((next_hs,[p]))
return result
[docs] def apply_inv_custom_rule(self,rule,hs,port):
result = []
matches = rule["inv_match"](hs,port)
for match in matches:
tmp_hp = rule["inv_transform"](match,port)
for (in_hs,in_ports) in tmp_hp:
if in_hs.count() > 0:
in_hs.push_applied_tf_rule(self,rule["id"],port)
result.append((in_hs,in_ports))
return result
[docs] def T_inv(self,hs,port):
'''
returns a list of (hs, list of in_ports) as possible inputs that can cause this (hs,port).
The format of hs and returned headerspace object, is like T() method above.
'''
result = []
if self.outport_to_rule.has_key("%d"%port):
for rule in self.outport_to_rule["%d"%port]:
#check if rule qualifies for lazy eval
if (self.lazy_eval_active and self.is_qualified_for_lazy_eval(rule)):
lazy_hs = hs.copy()
lazy_hs.add_lazy_tf_rule(self,rule["id"],port)
result.append(lazy_hs,rule["in_ports"])
# link rule
elif rule['action'] == "link":
result.extend(self.apply_inv_link_rule(rule, hs, port))
# rewrite rule
elif rule['action'] == "rw":
result.extend(self.apply_inv_rewrite_rule(rule, hs, port))
# forward rules
elif rule['action'] == "fwd":
result.extend(self.apply_inv_fwd_rule(rule, hs, port))
# custom rules
for rule in self.custom_rules:
result.extend(self.apply_inv_custom_rule(rule, hs, port))
return result
[docs] def T_inv_rule(self,rule_id,hs,port):
'''
Apply rule with id = rule_id to (hs,port)
Output is a list of [hs,list_of_out_ports].
'''
result = []
if self.id_to_rule.has_key(rule_id):
rule = self.id_to_rule[rule_id]
if rule['action'] == "link":
result = self.apply_inv_link_rule(rule, hs, port)
elif rule['action'] == "rw":
result = self.apply_inv_rewrite_rule(rule, hs, port)
elif rule['action'] == "fwd":
result = self.apply_inv_fwd_rule(rule, hs, port)
elif rule['action'] == "custom":
result = self.apply_inv_custom_rule(rule, hs, port)
return result
[docs] def is_qualified_for_lazy_eval(self,rule):
'''
This is a simple version of checking for lazy evaluation.
TODO: implement a more complex version that understand packet header rather than
just looking at some bit positions
'''
if rule["action"] == "rw":
no_rewrite_outside_lazy = True
one_rewrite_inside_lazy = False
for i in range(len(rule["mask"])):
if i in self.lazy_eval_nibbles:
if rule["mask"][i] != 0xaa:
one_rewrite_inside_lazy = True
else:
if rule["mask"][i] != 0xaa:
no_rewrite_outside_lazy = False
return (no_rewrite_outside_lazy and one_rewrite_inside_lazy)
else:
return False
[docs] def save_object_to_file(self, file):
'''
saves all the non-custom transfer function rules to a file
'''
log.debug("=== Saving transfer function to file %s ==="%file)
f = open(file, 'w')
f.write("%d$%s$%d$%d$%d$\n"%(self.length,self.prefix_id,self.next_id,self.lazy_eval_active,self.send_on_receiving_port))
for nibble in self.lazy_eval_nibbles:
f.write("%d$"%nibble)
f.write("#\n")
for rule in self.rules:
f.write("%s$"%rule["action"])
f.write("%s$"%list(rule["in_ports"]))
f.write("%s$"%byte_array_to_hs_string(rule["match"]))
f.write("%s$"%byte_array_to_hs_string(rule["mask"]))
f.write("%s$"%byte_array_to_hs_string(rule["rewrite"]))
f.write("%s$"%byte_array_to_hs_string(rule["inverse_match"]))
f.write("%s$"%byte_array_to_hs_string(rule["inverse_rewrite"]))
f.write("%s$"%list(rule["out_ports"]))
f.write("#")
for ra in rule["affected_by"]:
f.write("%d;%s;%s#"%(self.rules.index(ra[0]),byte_array_to_hs_string(ra[1]),ra[2]))
f.write("$")
f.write("#")
for io in rule["influence_on"]:
f.write("%d#"%self.rules.index(io))
f.write("$%s$"%rule["file"])
for ln in rule["line"]:
f.write("%d,"%ln)
f.write("$%s$\n"%rule["id"])
f.close()
log.debug("=== Transfer function saved to file %s ==="%file)
[docs] def load_object_from_file(self, file):
'''
load object from file, and replace the current object.
'''
log.debug("=== Loading transfer function from file %s ==="%file)
f = open(file,'r')
self.rules = []
first_line = f.readline()
tokens = first_line.split('$')
self.length = int(tokens[0])
self.prefix_id = tokens[1]
self.next_id = int(tokens[2])
if (int(tokens[3]) == 1):
self.lazy_eval_active = True
else:
self.lazy_eval_active = False
if (int(tokens[4]) == 1):
self.send_on_receiving_port = True
else:
self.send_on_receiving_port = False
second_line = f.readline()
tokens = second_line.split('#')[0].split('$')
for n in tokens:
if n != "":
self.lazy_eval_nibbles.append(int(n))
for line in f:
tokens = line.split('$')
new_rule = {}
# action
new_rule["action"] = tokens[0]
# in_ports
in_p = tokens[1].strip('[]').split(', ')
new_rule["in_ports"] = []
for p in in_p:
if p != "":
new_rule["in_ports"].append(int(p))
# match
match = hs_string_to_byte_array(tokens[2])
new_rule["match"] = match
# mask
mask = hs_string_to_byte_array(tokens[3])
new_rule["mask"] = mask
# rewrite
rewrite = hs_string_to_byte_array(tokens[4])
new_rule["rewrite"] = rewrite
# inverse_match
inverse_match = hs_string_to_byte_array(tokens[5])
new_rule["inverse_match"] = inverse_match
# inverse_rewrite
inverse_rewrite = hs_string_to_byte_array(tokens[6])
new_rule["inverse_rewrite"] = inverse_rewrite
# out_ports
out_p = tokens[7].strip('[]').split(', ')
new_rule["out_ports"] = []
for p in out_p:
if p != "":
new_rule["out_ports"].append(int(p))
# affected by
new_rule["affected_by"] = []
affect_list = tokens[8].split('#')
for affect in affect_list:
if affect != "":
elems = affect.split(';')
aff_p = elems[2].strip('[]').split(', ')
prts = []
for p in aff_p:
if p != "":
prts.append(int(p))
new_affect = (int(elems[0]),hs_string_to_byte_array(elems[1]),prts)
new_rule["affected_by"].append(new_affect)
# influence on
new_rule["influence_on"] = []
influence_list = tokens[9].split('#')
for influence in influence_list:
if influence != "":
new_rule["influence_on"].append(int(influence))
new_rule["file"] = tokens[10]
lns = tokens[11].split(',')
new_rule["line"] = []
for ln in lns:
if ln != "":
new_rule["line"].append(int(ln))
new_rule["id"] = tokens[12]
# Save new rule
self.rules.append(new_rule)
f.close()
# now replace index in affected_by and influence_on fields to the pointer to rules.
for indx in range(len(self.rules)):
rule = self.rules[indx]
influences = []
for idex in rule["influence_on"]:
influences.append(self.rules[idex])
rule["influence_on"] = influences
affects = []
for r in rule["affected_by"]:
new_affect = (self.rules[r[0]],r[1],r[2])
affects.append(new_affect)
rule["affected_by"] = affects
self.set_fast_lookup_pointers(indx)
log.debug("=== Transfer function loaded from file %s ==="%file)
def __str__(self):
strs = self.to_string()
return "\n".join(strs)