Skip to content

Commit

Permalink
[sonic-cfggen]: Read ACL interfaces information from minigrap (#419)
Browse files Browse the repository at this point in the history
* Enable translate_acl to read acl attaching from minigraph
* Add AclInterfaces into test t0 graph
* Expose minigraph_ports according
  • Loading branch information
taoyl-ms authored and Shuotian Cheng committed Mar 22, 2017
1 parent 6a6bc88 commit bd77f9a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 16 deletions.
31 changes: 26 additions & 5 deletions src/sonic-config-engine/minigraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def parse_dpg(dpg, hname):

ipintfs = child.find(str(QName(ns, "IPInterfaces")))
intfs = []
intfnames = {}
vlan_map = {}
pc_map = {}
for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
Expand Down Expand Up @@ -177,6 +178,7 @@ def parse_dpg(dpg, hname):
if peer_addr_val is not None:
intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
intfs.append(intf)
intfnames[intf['alias']] = { 'alias': intf['name'] }

pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
pc_intfs = []
Expand Down Expand Up @@ -237,10 +239,27 @@ def parse_dpg(dpg, hname):
vlan_attributes.update(addrtuple)
vlan_intfs.append(copy.deepcopy(vlan_attributes))
vlans[vintfname] = vlan_attributes


return intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, vlans, pcs
return None, None, None, None, None
aclintfs = child.find(str(QName(ns, "AclInterfaces")))
acls = {}
for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
aclname = aclintf.find(str(QName(ns, "InAcl"))).text
aclattach = aclintf.find(str(QName(ns, "AttachTo"))).text.split(';')
acl_intfs = []
for member in aclattach:
member = member.strip()
if port_alias_map.has_key(member):
member = port_alias_map[member]
if pcs.has_key(member):
acl_intfs.extend(pcs[member]['members']) # For ACL attaching to port channels, we break them into port channel members
elif vlans.has_key(member):
print >> sys.stderr, "Warning: ACL "+aclname+" is attached to a Vlan interface, which is currently not supported"
elif intfnames.has_key(member):
acl_intfs.append(member)
if acl_intfs:
acls[aclname] = acl_intfs

return intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, intfnames, vlans, pcs, acls
return None, None, None, None, None, None, None, None

def parse_cpg(cpg, hname):
bgp_sessions = []
Expand Down Expand Up @@ -394,7 +413,7 @@ def parse_xml(filename, platform=None, port_config_file=None):

for child in root:
if child.tag == str(QName(ns, "DpgDec")):
(intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, vlans, pcs) = parse_dpg(child, hostname)
(intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, ports, vlans, pcs, acls) = parse_dpg(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_asn) = parse_cpg(child, hostname)
elif child.tag == str(QName(ns, "PngDec")):
Expand All @@ -418,9 +437,11 @@ def parse_xml(filename, platform=None, port_config_file=None):
results['minigraph_vlan_interfaces'] = vlan_intfs
results['minigraph_portchannel_interfaces'] = pc_intfs
results['minigraph_vlans'] = vlans
results['minigraph_ports'] = ports
results['minigraph_portchannels'] = pcs
results['minigraph_mgmt_interface'] = mgmt_intf
results['minigraph_lo_interfaces'] = lo_intfs
results['minigraph_acls'] = acls
results['minigraph_neighbors'] = neighbors
results['minigraph_devices'] = devices
results['minigraph_underlay_neighbors'] = u_neighbors
Expand Down
9 changes: 8 additions & 1 deletion src/sonic-config-engine/tests/t0-sample-graph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,14 @@
</IPInterface>
</IPInterfaces>
<DataAcls/>
<AclInterfaces/>
<AclInterfaces>
<AclInterface>
<AttachTo>
PortChannel01;PortChannel02;PortChannel03;PortChannel04
</AttachTo>
<InAcl>DataAcl</InAcl>
</AclInterface>
</AclInterfaces>
<DownstreamSummaries/>
<DownstreamSummarySet xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
</DeviceDataPlaneInfo>
Expand Down
6 changes: 6 additions & 0 deletions src/sonic-config-engine/tests/test_cfggen.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def setUp(self):
self.test_dir = os.path.dirname(os.path.realpath(__file__))
self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen')
self.sample_graph = os.path.join(self.test_dir, 'sample_graph.xml')
self.sample_graph_t0 = os.path.join(self.test_dir, 't0-sample-graph.xml')

def run_script(self, argument):
print '\n Running sonic-cfggen ' + argument
Expand Down Expand Up @@ -59,3 +60,8 @@ def test_render_template(self):
output = self.run_script(argument)
self.assertEqual(output.strip(), 'value1\nvalue2')

def test_minigraph_acl(self):
argument = '-m "' + self.sample_graph_t0 + '" -v minigraph_acls'
output = self.run_script(argument)
self.assertEqual(output.strip(), "{'DataAcl': ['Ethernet112', 'Ethernet116', 'Ethernet120', 'Ethernet124']}")

38 changes: 28 additions & 10 deletions src/sonic-config-engine/translate_acl
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/usr/bin/env python

import openconfig_acl
import pyangbind.lib.pybindJSON as pybindJSON

import sys
import os.path
import json
import argparse

import openconfig_acl
import pyangbind.lib.pybindJSON as pybindJSON
from minigraph import parse_xml

def dump_json(filename, data):
with open(filename, 'w') as outfile:
json.dump(data, outfile, indent=4, sort_keys=True, separators=(',', ':'))
Expand Down Expand Up @@ -97,7 +98,7 @@ def generate_rule_json(table_name, rule, max_priority):
return rule_data

def generate_table_json(aclset, aclname, port, max_priority, output_path='.'):
table_name = aclname.replace(" ", "_")
table_name = aclname.replace(" ", "_").replace("-", "_")
#table_name = generate_random_table_name()

table_props = {}
Expand All @@ -119,21 +120,38 @@ def generate_table_json(aclset, aclname, port, max_priority, output_path='.'):

dump_json(os.path.join(output_path, "rules_for_"+table_name+".json"), rule_data)

def translate_acl(filename, output_path, port, max_priority):
def translate_acl_fixed_port(filename, output_path, port, max_priority):
yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl")
for aclsetname in yang_acl.acl.acl_sets.acl_set:
aclset = yang_acl.acl.acl_sets.acl_set[aclsetname]
generate_table_json(aclset, aclsetname, port, max_priority, output_path)
return

def translate_acl(filename, output_path, attach_to, max_priority):
yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl")
print attach_to.keys()
for aclsetname in yang_acl.acl.acl_sets.acl_set:
aclset = yang_acl.acl.acl_sets.acl_set[aclsetname]
generate_table_json(aclset, aclsetname, port, max_priority, output_path)
tablename = aclsetname.replace(" ", "_").replace("-", "_")
if attach_to.has_key(tablename):
port = ','.join(attach_to[tablename])
aclset = yang_acl.acl.acl_sets.acl_set[aclsetname]
generate_table_json(aclset, aclsetname, port, max_priority, output_path)
return

def main():
parser = argparse.ArgumentParser(description="Translate openconfig ACL json into SONiC ACL jsons")
parser.add_argument('input', metavar='INPUT', help='input json file in openconfig format')
parser.add_argument('-p', '--port', default='Ethernet0', help='the port(s) that this ACL is binding to')
parser.add_argument('-m', '--max-priority', type=int, default=10000, help='the priority number of the first rule in ACL entries')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-p', '--port', help='the port(s) that this ACL is attached to')
group.add_argument('-m', '--minigraph', help='read ACL attaching information from minigraph')
parser.add_argument('-n', '--max-priority', type=int, default=10000, help='the priority number of the first rule in ACL entries')
parser.add_argument('-o', '--output-path', default='.', help='output directory where SONiC ACL jsons will be generated')
args = parser.parse_args()
translate_acl(args.input, args.output_path, args.port, args.max_priority)
if args.port:
translate_acl_fixed_port(args.input, args.output_path, args.port, args.max_priority)
elif args.minigraph:
mini_data = parse_xml(args.minigraph)
translate_acl(args.input, args.output_path, mini_data['minigraph_acls'], args.max_priority)

if __name__ == "__main__":
main()

0 comments on commit bd77f9a

Please sign in to comment.