From c40060745273379420d9462e3e58388fb18f9ab9 Mon Sep 17 00:00:00 2001 From: sbalineni Date: Mon, 21 Sep 2015 19:50:40 -0700 Subject: [PATCH] DM: l2 interface config for vlan bridging A. If there's a VLAN tag for the interface (i.e. multiple IFLs per IFD) set groups __contrail__ interfaces xe-2/3/2 flexible-vlan-tagging set groups __contrail__ interfaces xe-2/3/2 encapsulation flexible-ethernet-services set groups __contrail__ interfaces xe-2/3/2 unit 2001 vlan-id 2001 set groups __contrail__ interfaces xe-2/3/2 unit 2001 encapsulation vlan-bridge set groups __contrail__ interfaces xe-2/3/2 unit 2002 vlan-id 2002 set groups __contrail__ interfaces xe-2/3/2 unit 2002 encapsulation vlan-bridge B. If there's no VLAN tag for the interface (i.e. single IFL for the IFD) set groups __contrail__ interfaces xe-0/0/1 encapsulation ethernet-bridge set groups __contrail__ interfaces xe-0/0/1 unit 0 family bridge Closes-Bug: #1486154 Change-Id: Ib8d7d1ead9b1bacc0eeeae9d2d7143ac99df182b --- .../device-manager/device_manager/db.py | 21 +++-- .../device_manager/physical_router_config.py | 90 +++++++++++++------ 2 files changed, 77 insertions(+), 34 deletions(-) diff --git a/src/config/device-manager/device_manager/db.py b/src/config/device-manager/device_manager/db.py index 042f69b9f25..cd1eb75940c 100644 --- a/src/config/device-manager/device_manager/db.py +++ b/src/config/device-manager/device_manager/db.py @@ -8,6 +8,7 @@ """ from vnc_api.common.exceptions import NoIdError from physical_router_config import PhysicalRouterConfig +from physical_router_config import JunosInterface from sandesh.dm_introspect import ttypes as sandesh from cfgm_common.vnc_db import DBBase from cfgm_common.uve.physical_router.ttypes import * @@ -291,10 +292,7 @@ def get_vn_li_map(self): if vmi is None: continue vn_id = vmi.virtual_network - if vn_id in vn_dict: - vn_dict[vn_id].append(li.name) - else: - vn_dict[vn_id] = [li.name] + vn_dict.setdefault(vn_id, []).append(JunosInterface(li.name, li.li_type, li.vlan_tag)) return vn_dict #end @@ -317,6 +315,8 @@ def push_config(self): self.config_manager.add_dynamic_tunnels(self.dataplane_ip, GlobalSystemConfigDM.ip_fabric_subnets, bgp_router_ips) + self.config_manager.add_mpls_protocol() + vn_dict = self.get_vn_li_map() self.evaluate_vn_irb_ip_map(set(vn_dict.keys())) vn_irb_ip_map = self.get_vn_irb_ip_map() @@ -359,6 +359,7 @@ def push_config(self): None, vn_obj.vn_network_id) if vn_obj.forwarding_mode in ['l3', 'l2_l3']: + interfaces = [JunosInterface('irb.'+ str(vn_obj.vn_network_id), 'l3', 0)] self.config_manager.add_routing_instance(vrf_name_l3, False, vn_obj.forwarding_mode == 'l2_l3', @@ -367,7 +368,7 @@ def push_config(self): vn_obj.get_prefixes(), None, vn_obj.router_external, - ["irb" + "." + str(vn_obj.vn_network_id)]) + interfaces) break @@ -380,8 +381,8 @@ def push_config(self): vrf_name = vrf_name_l3[:123] + '-nat' interfaces = [] service_ports = self.junos_service_ports.get('service_port') - interfaces.append(service_ports[0] + "." + str(service_port_id)) - interfaces.append(service_ports[0] + "." + str(service_port_id + 1)) + interfaces.append(JunosInterface(service_ports[0] + "." + str(service_port_id), 'l3', 0)) + interfaces.append(JunosInterface(service_ports[0] + "." + str(service_port_id + 1), 'l3', 0)) self.config_manager.add_routing_instance(vrf_name, False, False, @@ -548,6 +549,8 @@ class LogicalInterfaceDM(DBBase): def __init__(self, uuid, obj_dict=None): self.uuid = uuid self.virtual_machine_interface = None + self.vlan_tag = 0 + self.li_type = None self.update(obj_dict) if self.physical_interface: parent = PhysicalInterfaceDM.get(self.physical_interface) @@ -567,6 +570,8 @@ def update(self, obj=None): self.physical_interface = self.get_parent_uuid(obj) self.physical_router = None + self.vlan_tag = obj.get("logical_interface_vlan_tag", 0) + self.li_type = obj.get("logical_interface_type", 0) self.update_single_ref('virtual_machine_interface', obj) self.name = obj['fq_name'][-1] # end update @@ -933,7 +938,7 @@ def handle_pr_deletes(self, current_pr_set): cs_pr_set = set(self.pr_vn_ip_map.keys()) delete_set = cs_pr_set.difference(current_pr_set) for pr_uuid in delete_set: - self.delete_pr(vn_uuid) + self.delete_pr(pr_uuid) #end def get_pr_vn_set(self, pr_uuid): diff --git a/src/config/device-manager/device_manager/physical_router_config.py b/src/config/device-manager/device_manager/physical_router_config.py index 0c6c1318147..9e0e461e024 100644 --- a/src/config/device-manager/device_manager/physical_router_config.py +++ b/src/config/device-manager/device_manager/physical_router_config.py @@ -145,7 +145,7 @@ def add_dynamic_tunnels(self, tunnel_source_ip, ip_fabric_nets, bgp_router_ips): network_id : this is used for configuraing irb interfaces ''' def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_targets, - prefixes=[], gateways=[], router_external=False, + prefixes=[], gateways=[], router_external=False, interfaces=[], vni=None, fip_map=None, network_id=None): self.routing_instances[ri_name] = {'import_targets': import_targets, 'export_targets': export_targets, @@ -189,7 +189,7 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ if fip_map is None: for interface in interfaces: if_element = etree.SubElement(ri, "interface") - etree.SubElement(if_element, "name").text = interface + etree.SubElement(if_element, "name").text = interface.name if ri_opt is None: ri_opt = etree.SubElement(ri, "routing-options") auto_export = "" @@ -203,9 +203,9 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ static_config = etree.SubElement(ri_opt, "static") route_config = etree.SubElement(static_config, "route") etree.SubElement(route_config, "name").text = "0.0.0.0/0" - etree.SubElement(route_config, "next-hop").text = interfaces[0] + etree.SubElement(route_config, "next-hop").text = interfaces[0].name if_element = etree.SubElement(ri, "interface") - etree.SubElement(if_element, "name").text = interfaces[0] + etree.SubElement(if_element, "name").text = interfaces[0].name public_vrf_ips = {} for pip in fip_map.values(): if pip["vrf_name"] not in public_vrf_ips: @@ -218,12 +218,12 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ ri_opt = etree.SubElement(ri_public, "routing-options") static_config = etree.SubElement(ri_opt, "static") if_element = etree.SubElement(ri_public, "interface") - etree.SubElement(if_element, "name").text = interfaces[1] + etree.SubElement(if_element, "name").text = interfaces[1].name for fip in fips: route_config = etree.SubElement(static_config, "route") etree.SubElement(route_config, "name").text = fip + "/32" - etree.SubElement(route_config, "next-hop").text = interfaces[1] + etree.SubElement(route_config, "next-hop").text = interfaces[1].name # add policies for export route targets ps = etree.SubElement(policy_config, "policy-statement") @@ -331,7 +331,7 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ etree.SubElement(vxlan, "vni").text = str(vni) for interface in interfaces: if_element = etree.SubElement(bd, "interface") - etree.SubElement(if_element, "name").text = interface + etree.SubElement(if_element, "name").text = interface.name if is_l2_l3: etree.SubElement(bd, "routing-interface").text = "irb." + str(network_id) #network_id is unique, hence irb evpn_proto_config = etree.SubElement(ri, "protocols") @@ -366,20 +366,8 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ etree.SubElement(addr, "primary") etree.SubElement(addr, "preferred") - for interface in interfaces: - intf = etree.SubElement(interfaces_config, "interface") - intfparts = interface.split(".") - etree.SubElement(intf, "name").text = intfparts[0] - etree.SubElement(intf, "encapsulation").text = "ethernet-bridge" - intf_unit = etree.SubElement(intf, "unit") - etree.SubElement(intf_unit, "name").text = intfparts[1] - family = etree.SubElement(intf_unit, "family") - etree.SubElement(family, "bridge") + self.build_l2_evpn_interface_config(interfaces_config, interfaces) - proto_config = self.proto_config or etree.Element("protocols") - mpls = etree.SubElement(proto_config, "mpls") - intf = etree.SubElement(mpls, "interface") - etree.SubElement(intf, "name").text = "all" #fip services config services_config = self.services_config if fip_map is not None: @@ -394,8 +382,8 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ nat_rule = etree.SubElement(service_set, "nat-rules") etree.SubElement(nat_rule, "name").text = service_name + "-dn-rule" next_hop_service = etree.SubElement(service_set, "next-hop-service") - etree.SubElement(next_hop_service , "inside-service-interface").text = interfaces[0] - etree.SubElement(next_hop_service , "outside-service-interface").text = interfaces[1] + etree.SubElement(next_hop_service , "inside-service-interface").text = interfaces[0].name + etree.SubElement(next_hop_service , "outside-service-interface").text = interfaces[1].name nat = etree.SubElement(services_config, "nat") snat_rule = etree.SubElement(nat, "rule") @@ -431,15 +419,14 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ interfaces_config = self.interfaces_config or etree.Element("interfaces") si_intf = etree.SubElement(interfaces_config, "interface") - intfparts = interfaces[0].split(".") - etree.SubElement(si_intf, "name").text = intfparts[0] + etree.SubElement(si_intf, "name").text = interfaces[0].ifd_name intf_unit = etree.SubElement(si_intf, "unit") - etree.SubElement(intf_unit, "name").text = interfaces[0].split(".")[1] + etree.SubElement(intf_unit, "name").text = interfaces[0].unit family = etree.SubElement(intf_unit, "family") etree.SubElement(family, "inet") etree.SubElement(intf_unit, "service-domain").text = "inside" intf_unit = etree.SubElement(si_intf, "unit") - etree.SubElement(intf_unit, "name").text = interfaces[1].split(".")[1] + etree.SubElement(intf_unit, "name").text = interfaces[1].unit family = etree.SubElement(intf_unit, "family") etree.SubElement(family, "inet") etree.SubElement(intf_unit, "service-domain").text = "outside" @@ -454,6 +441,39 @@ def add_routing_instance(self, ri_name, is_l2, is_l2_l3, import_targets, export_ self.ri_config = ri_config # end add_routing_instance + def build_l2_evpn_interface_config(self, interfaces_config, interfaces): + ifd_map = {} + for interface in interfaces: + ifd_map.setdefault(interface.ifd_name, []).append(interface) + + for ifd_name, interface_list in ifd_map.items(): + intf = etree.SubElement(interfaces_config, "interface") + etree.SubElement(intf, "name").text = ifd_name + if interface_list[0].is_untagged(): + if (len(interface_list) > 1): + self._logger.error("invalid logical interfaces config for ifd %s" % (ifd_name)) + continue + etree.SubElement(intf, "encapsulation").text = "ethernet-bridge" + intf_unit = etree.SubElement(intf, "unit") + etree.SubElement(intf_unit, "name").text = interface_list[0].unit + family = etree.SubElement(intf_unit, "family") + etree.SubElement(family, "bridge") + else: + etree.SubElement(intf, "flexible-vlan-tagging") + etree.SubElement(intf, "encapsulation").text = "flexible-ethernet-services" + for interface in interface_list: + intf_unit = etree.SubElement(intf, "unit") + etree.SubElement(intf_unit, "name").text = interface.unit + etree.SubElement(intf_unit, "encapsulation").text = "vlan-bridge" + etree.SubElement(intf_unit, "vlan-id").text = str(interface.vlan_tag) + #end build_l2_evpn_interface_config + + def add_mpls_protocol(self): + proto_config = self.proto_config or etree.Element("protocols") + mpls = etree.SubElement(proto_config, "mpls") + intf = etree.SubElement(mpls, "interface") + etree.SubElement(intf, "name").text = "all" + def set_global_routing_options(self, bgp_params): if bgp_params['address'] is not None: self.global_routing_options_config = etree.Element("routing-options") @@ -649,3 +669,21 @@ def send_bgp_config(self): # end send_bgp_config # end PhycalRouterConfig + +class JunosInterface(object): + def __init__(self, if_name, if_type, if_vlan_tag = 0): + self.name = if_name + self.if_type = if_type + self.vlan_tag = if_vlan_tag + ifparts = if_name.split('.') + self.ifd_name = ifparts[0] + self.unit = ifparts[1] + #end __init__ + + def is_untagged(self): + if not self.vlan_tag: + return True + return False + #end is_untagged + +#end JunosInterface