def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        static_routes = ri_conf.get("static_routes", {})
        no_vrf_table_label = ri_conf.get("no_vrf_table_label", False)
        restrict_proxy_arp = ri_conf.get("restrict_proxy_arp", False)

        self.routing_instances[ri_name] = ri_conf
        ri_config = self.ri_config or RoutingInstances()
        policy_config = self.policy_config or PolicyOptions()
        ri = Instance(name=ri_name)
        ri_config.add_instance(ri)
        ri_opt = None
        if router_external and is_l2 == False:
            ri_opt = RoutingInstanceRoutingOptions(static=Static(route=[Route(name="0.0.0.0/0", next_table="inet.0")]))
            ri.set_routing_options(ri_opt)

        # for both l2 and l3
        ri.set_vrf_import(DMUtils.make_import_name(ri_name))
        ri.set_vrf_export(DMUtils.make_export_name(ri_name))

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            if ri_opt is None:
                ri_opt = RoutingInstanceRoutingOptions()
                ri.set_routing_options(ri_opt)
            if prefixes and fip_map is None:
                static_config = ri_opt.get_static()
                if not static_config:
                    static_config = Static()
                    ri_opt.set_static(static_config)
                rib_config_v6 = None
                static_config_v6 = None
                for prefix in prefixes:
                    if ":" in prefix and not rib_config_v6:
                        static_config_v6 = Static()
                        rib_config_v6 = RIB(name=ri_name + ".inet6.0")
                        rib_config_v6.set_static(static_config_v6)
                        ri_opt.set_rib(rib_config_v6)
                    if ":" in prefix:
                        static_config_v6.add_route(Route(name=prefix, discard=""))
                    else:
                        static_config.add_route(Route(name=prefix, discard=""))
                    if router_external:
                        self.add_to_global_ri_opts(prefix)

            ri.set_instance_type("vrf")
            if not no_vrf_table_label:
                ri.set_vrf_table_label("")  # only for l3
            if fip_map is None:
                for interface in interfaces:
                    ri.add_interface(Interface(name=interface.name))
            if static_routes:
                self.add_static_routes(ri_opt, static_routes)
            if has_ipv4_prefixes:
                ri_opt.set_auto_export(AutoExport(family=Family(inet=FamilyInet(unicast=""))))
            if has_ipv6_prefixes:
                ri_opt.set_auto_export(AutoExport(family=Family(inet6=FamilyInet6(unicast=""))))
        else:
            ri.set_instance_type("virtual-switch")

        if fip_map is not None:
            if ri_opt is None:
                ri_opt = RoutingInstanceRoutingOptions()
                ri.set_routing_options(ri_opt)
            static_config = ri_opt.get_static()
            if not static_config:
                static_config = Static()
                ri_opt.set_static(static_config)
            static_config.add_route(Route(name="0.0.0.0/0", next_hop=interfaces[0].name))
            ri.add_interface(Interface(name=interfaces[0].name))

            public_vrf_ips = {}
            for pip in fip_map.values():
                if pip["vrf_name"] not in public_vrf_ips:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                ri_public = Instance(name=public_vrf)
                ri_config.add_instance(ri_public)
                ri_public.add_interface(Interface(name=interfaces[1].name))

                ri_opt = RoutingInstanceRoutingOptions()
                ri_public.set_routing_options(ri_opt)
                static_config = Static()
                ri_opt.set_static(static_config)

                for fip in fips:
                    static_config.add_route(Route(name=fip + "/32", next_hop=interfaces[1].name))

        # add policies for export route targets
        ps = PolicyStatement(name=DMUtils.make_export_name(ri_name))
        then = Then()
        ps.set_term(Term(name="t1", then=then))
        for route_target in export_targets:
            comm = Community(add="", community_name=DMUtils.make_community_name(route_target))
            then.add_community(comm)
        if fip_map is not None:
            # for nat instance
            then.set_reject("")
        else:
            then.set_accept("")
        policy_config.add_policy_statement(ps)

        # add policies for import route targets
        ps = PolicyStatement(name=DMUtils.make_import_name(ri_name))
        from_ = From()
        term = Term(name="t1", fromxx=from_)
        ps.set_term(term)
        for route_target in import_targets:
            from_.add_community(DMUtils.make_community_name(route_target))
        term.set_then(Then(accept=""))
        ps.set_then(Then(reject=""))
        policy_config.add_policy_statement(ps)

        # add firewall config for public VRF
        forwarding_options_config = self.forwarding_options_config
        firewall_config = self.firewall_config
        if router_external and is_l2 == False:
            forwarding_options_config = self.forwarding_options_config or ForwardingOptions()
            firewall_config = self.firewall_config or Firewall()
            if has_ipv4_prefixes and not self.inet4_forwarding_filter:
                # create single instance inet4 filter
                self.inet4_forwarding_filter = self.add_inet_public_vrf_filter(
                    forwarding_options_config, firewall_config, "inet"
                )
            if has_ipv6_prefixes and not self.inet6_forwarding_filter:
                # create single instance inet6 filter
                self.inet6_forwarding_filter = self.add_inet_public_vrf_filter(
                    forwarding_options_config, firewall_config, "inet6"
                )
            if has_ipv4_prefixes:
                # add terms to inet4 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
                # insert before the last term
                terms = self.inet4_forwarding_filter.get_term()
                terms = [term] + (terms or [])
                self.inet4_forwarding_filter.set_term(terms)
            if has_ipv6_prefixes:
                # add terms to inet6 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet6")
                # insert before the last term
                terms = self.inet6_forwarding_filter.get_term()
                terms = [term] + (terms or [])
                self.inet6_forwarding_filter.set_term(terms)

        if fip_map is not None:
            firewall_config = firewall_config or Firewall()
            f = FirewallFilter(name=DMUtils.make_private_vrf_filter_name(ri_name))
            ff = firewall_config.get_family()
            if not ff:
                ff = FirewallFamily()
                firewall_config.set_family(ff)
            inet = ff.get_inet()
            if not inet:
                inet = FirewallInet()
                ff.set_inet(inet)
            inet.add_filter(f)

            term = Term(name=DMUtils.make_vrf_term_name(ri_name))
            from_ = From()
            for fip_user_ip in fip_map.keys():
                from_.add_source_address(fip_user_ip)
            term.set_from(from_)
            term.set_then(Then(routing_instance=[ri_name]))
            f.add_term(term)

            term = Term(name="default-term", then=Then(accept=""))
            f.add_term(term)

            interfaces_config = self.interfaces_config or Interfaces()
            irb_intf = Interface(name="irb")
            interfaces_config.add_interface(irb_intf)

            intf_unit = Unit(name=str(network_id))
            if restrict_proxy_arp:
                intf_unit.set_proxy_arp(ProxyArp(restricted=""))
            inet = FamilyInet()
            inet.set_filter(InetFilter(input=DMUtils.make_private_vrf_filter_name(ri_name)))
            intf_unit.set_family(Family(inet=inet))
            irb_intf.add_unit(intf_unit)

        # add L2 EVPN and BD config
        bd_config = None
        interfaces_config = self.interfaces_config
        proto_config = self.proto_config
        if is_l2 and vni is not None and self.is_family_configured(self.bgp_params, "e-vpn"):
            ri.set_vtep_source_interface("lo0.0")
            bd_config = BridgeDomains()
            ri.set_bridge_domains(bd_config)
            bd = Domain(name=DMUtils.make_bridge_name(vni), vlan_id="none", vxlan=VXLan(vni=vni))
            bd_config.add_domain(bd)
            for interface in interfaces:
                bd.add_interface(Interface(name=interface.name))
            if is_l2_l3:
                # network_id is unique, hence irb
                bd.set_routing_interface("irb." + str(network_id))
            ri.set_protocols(RoutingInstanceProtocols(evpn=Evpn(encapsulation="vxlan", extended_vni_list="all")))

            interfaces_config = self.interfaces_config or Interfaces()
            if is_l2_l3:
                irb_intf = Interface(name="irb", gratuitous_arp_reply="")
                interfaces_config.add_interface(irb_intf)
                if gateways is not None:
                    intf_unit = Unit(name=str(network_id))
                    irb_intf.add_unit(intf_unit)
                    family = Family()
                    intf_unit.set_family(family)
                    inet = None
                    inet6 = None
                    for (irb_ip, gateway) in gateways:
                        if ":" in irb_ip:
                            if not inet6:
                                inet6 = FamilyInet6()
                                family.set_inet6(inet6)
                            addr = Address()
                            inet6.add_address(addr)
                        else:
                            if not inet:
                                inet = FamilyInet()
                                family.set_inet(inet)
                            addr = Address()
                            inet.add_address(addr)
                        addr.set_name(irb_ip)
                        if len(gateway) and gateway != "0.0.0.0":
                            addr.set_virtual_gateway_address(gateway)

            lo_intf = Interface(name="lo0")
            interfaces_config.add_interface(lo_intf)
            fam_inet = FamilyInet(address=[Address(name=self.bgp_params["address"] + "/32", primary="", preferred="")])
            intf_unit = Unit(name="0", family=Family(inet=fam_inet))
            lo_intf.add_unit(intf_unit)

            self.build_l2_evpn_interface_config(interfaces_config, interfaces)

        # fip services config
        services_config = self.services_config
        if fip_map is not None:
            services_config = self.services_config or Services()
            service_name = DMUtils.make_services_set_name(ri_name)
            service_set = ServiceSet(name=service_name)
            services_config.add_service_set(service_set)
            nat_rule = NATRules(name=service_name + "-sn-rule")
            service_set.add_nat_rules(NATRules(name=DMUtils.make_snat_rule_name(ri_name)))
            service_set.add_nat_rules(NATRules(name=DMUtils.make_dnat_rule_name(ri_name)))
            next_hop_service = NextHopService(
                inside_service_interface=interfaces[0].name, outside_service_interface=interfaces[1].name
            )
            service_set.set_next_hop_service(next_hop_service)

            nat = NAT(allow_overlapping_nat_pools="")
            services_config.add_nat(nat)
            snat_rule = Rule(name=DMUtils.make_snat_rule_name(ri_name), match_direction="input")
            nat.add_rule(snat_rule)
            dnat_rule = Rule(name=DMUtils.make_dnat_rule_name(ri_name), match_direction="output")
            nat.add_rule(dnat_rule)

            for pip, fip_vn in fip_map.items():
                fip = fip_vn["floating_ip"]
                term = Term(name=DMUtils.make_ip_term_name(pip))
                snat_rule.set_term(term)
                # private ip
                from_ = From(source_address=[pip + "/32"])
                term.set_from(from_)
                # public ip
                then_ = Then()
                term.set_then(then_)
                translated = Translated(source_prefix=fip + "/32", translation_type=TranslationType(basic_nat44=""))
                then_.set_translated(translated)

                term = Term(name=DMUtils.make_ip_term_name(fip))
                dnat_rule.set_term(term)

                # public ip
                from_ = From(destination_address=[fip + "/32"])
                term.set_from(from_)
                # private ip
                then_ = Then()
                term.set_then(then_)
                translated = Translated(destination_prefix=pip + "/32", translation_type=TranslationType(dnat_44=""))
                then_.set_translated(translated)

            interfaces_config = self.interfaces_config or Interfaces()
            si_intf = Interface(name=interfaces[0].ifd_name)
            interfaces_config.add_interface(si_intf)

            intf_unit = Unit(name=interfaces[0].unit)
            si_intf.add_unit(intf_unit)
            family = Family(inet=FamilyInet())
            intf_unit.set_family(family)
            intf_unit.set_service_domain("inside")

            intf_unit = Unit(name=interfaces[1].unit)
            si_intf.add_unit(intf_unit)
            family = Family(inet=FamilyInet())
            intf_unit.set_family(family)
            intf_unit.set_service_domain("outside")

        self.forwarding_options_config = forwarding_options_config
        self.firewall_config = firewall_config
        self.policy_config = policy_config
        self.proto_config = proto_config
        self.interfaces_config = interfaces_config
        self.services_config = services_config
        self.route_targets |= import_targets | export_targets
        self.ri_config = ri_config
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        vn = ri_conf.get("vn")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        network_id = ri_conf.get("network_id", None)

        self.routing_instances[ri_name] = ri_conf
        ri_config = self.ri_config or RoutingInstances(
            comment=DMUtils.routing_instances_comment())
        policy_config = self.policy_config or PolicyOptions(
            comment=DMUtils.policy_options_comment())
        ri = Instance(name=ri_name)

        ri_config.add_instance(ri)
        ri_opt = None

        # for both l2 and l3
        ri.set_vrf_import(DMUtils.make_import_name(ri_name))
        ri.set_vrf_export(DMUtils.make_export_name(ri_name))

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            if ri_opt is None:
                ri_opt = RoutingInstanceRoutingOptions()
                ri.set_routing_options(ri_opt)

            ri.set_instance_type("vrf")
            for interface in interfaces:
                ri.add_interface(Interface(name=interface.name))
            family = Family()
            if has_ipv4_prefixes:
                family.set_inet(FamilyInet(unicast=''))
            if has_ipv6_prefixes:
                family.set_inet6(FamilyInet6(unicast=''))
            if has_ipv4_prefixes or has_ipv6_prefixes:
                auto_export = AutoExport(family=family)
                ri_opt.set_auto_export(auto_export)
        else:
            ri.set_instance_type("virtual-switch")

        # add policies for export route targets
        ps = PolicyStatement(name=DMUtils.make_export_name(ri_name))
        ps.set_comment(DMUtils.vn_ps_comment(vn, "Export"))
        then = Then()
        ps.add_term(Term(name="t1", then=then))
        for route_target in export_targets:
            comm = Community(
                add='',
                community_name=DMUtils.make_community_name(route_target))
            then.add_community(comm)
            then.set_accept('')
            self.add_vni_option(network_id,
                                DMUtils.make_community_name(route_target))
        policy_config.add_policy_statement(ps)
        self.add_to_global_switch_opts(DMUtils.make_export_name(ri_name),
                                       False)

        # add policies for import route targets
        ps = PolicyStatement(name=DMUtils.make_import_name(ri_name))
        ps.set_comment(DMUtils.vn_ps_comment(vn, "Import"))
        from_ = From()
        term = Term(name="t1", fromxx=from_)
        ps.add_term(term)
        for route_target in import_targets:
            from_.add_community(DMUtils.make_community_name(route_target))
            self.add_vni_option(network_id,
                                DMUtils.make_community_name(route_target))
        term.set_then(Then(accept=''))
        ps.set_then(Then(reject=''))
        policy_config.add_policy_statement(ps)
        self.add_to_global_switch_opts(DMUtils.make_import_name(ri_name), True)

        # add vlan config
        if is_l2 and vni and self.is_family_configured(self.bgp_params,
                                                       "e-vpn"):
            self.add_vlan_config(ri_name, vni)

        # add L2 EVPN and BD config
        interfaces_config = self.interfaces_config
        proto_config = self.proto_config
        if (is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            ri.set_vtep_source_interface("lo0.0")
            evpn = Evpn(encapsulation='vxlan', extended_vni_list='all')
            self.set_evpn_default_gateway_params(evpn)
            ri.set_protocols(RoutingInstanceProtocols(evpn=evpn))

            interfaces_config = self.interfaces_config or Interfaces(
                comment=DMUtils.interfaces_comment())
            if is_l2_l3:
                irb_intf = Interface(name='irb', gratuitous_arp_reply='')
                interfaces_config.add_interface(irb_intf)
                if gateways is not None:
                    intf_unit = Unit(name=str(network_id),
                                     comment=DMUtils.vn_irb_comment(
                                         vn, False, is_l2_l3))
                    irb_intf.add_unit(intf_unit)
                    if self.is_spine():
                        intf_unit.set_proxy_macip_advertisement('')
                    family = Family()
                    intf_unit.set_family(family)
                    inet = None
                    inet6 = None
                    for (irb_ip, gateway) in gateways:
                        if ':' in irb_ip:
                            if not inet6:
                                inet6 = FamilyInet6()
                                family.set_inet6(inet6)
                            addr = Address()
                            inet6.add_address(addr)
                        else:
                            if not inet:
                                inet = FamilyInet()
                                family.set_inet(inet)
                            addr = Address()
                            inet.add_address(addr)
                        addr.set_name(irb_ip)
                        addr.set_comment(DMUtils.irb_ip_comment(irb_ip))
                        if len(gateway) and gateway != '0.0.0.0':
                            addr.set_virtual_gateway_address(gateway)

            self.build_l2_evpn_interface_config(interfaces_config, interfaces,
                                                vn)

        if (not is_l2 and not is_l2_l3 and gateways):
            interfaces_config = self.interfaces_config or Interfaces(
                comment=DMUtils.interfaces_comment())
            ifl_num = str(1000 + int(network_id))
            lo_intf = Interface(name="lo0")
            interfaces_config.add_interface(lo_intf)
            intf_unit = Unit(name=ifl_num,
                             comment=DMUtils.l3_lo_intf_comment(vn))
            lo_intf.add_unit(intf_unit)
            family = Family()
            intf_unit.set_family(family)
            inet = None
            inet6 = None
            for (lo_ip, _) in gateways:
                subnet = lo_ip
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    if not inet6:
                        inet6 = FamilyInet6()
                        family.set_inet6(inet6)
                    addr = Address()
                    inet6.add_address(addr)
                    lo_ip = ip + '/' + '128'
                else:
                    if not inet:
                        inet = FamilyInet()
                        family.set_inet(inet)
                    addr = Address()
                    inet.add_address(addr)
                    lo_ip = ip + '/' + '32'
                addr.set_name(lo_ip)
                addr.set_comment(DMUtils.lo0_ip_comment(subnet))
            ri.add_interface(
                Interface(name="lo0." + ifl_num,
                          comment=DMUtils.lo0_ri_intf_comment(vn)))

        self.policy_config = policy_config
        self.proto_config = proto_config
        self.interfaces_config = interfaces_config
        self.route_targets |= import_targets | export_targets
        self.ri_config = ri_config
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        vn = ri_conf.get("vn")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        is_internal_vn = True if '_contrail_lr_internal_vn_' in vn.name else False
        highest_encapsulation_priority = \
            ri_conf.get("highest_encapsulation_priority") or "MPLSoGRE"

        self.routing_instances[ri_name] = ri_conf
        self.ri_config = self.ri_config or []
        self.policy_config = self.policy_config or\
                             Policy(comment=DMUtils.policy_options_comment())
        ri = RoutingInstance(name=ri_name)
        if vn:
            is_nat = True if fip_map else False
            ri.set_comment(
                DMUtils.vn_ri_comment(vn, is_l2, is_l2_l3, is_nat,
                                      router_external))
        self.ri_config.append(ri)

        ri.set_is_public_network(router_external)

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            ri.set_instance_type("vrf")
            if fip_map is None:
                for interface in interfaces:
                    ri.add_interfaces(LogicalInterface(name=interface.name))
        else:
            if highest_encapsulation_priority == "VXLAN":
                ri.set_routing_instance_type("virtual-switch")
            elif highest_encapsulation_priority in ["MPLSoGRE", "MPLSoUDP"]:
                ri.set_routing_instance_type("evpn")

        if is_internal_vn:
            self.internal_vn_ris.append(ri)
            self.add_bogus_lo0(ri, network_id, vn)

        if self.is_spine() and is_l2_l3:
            self.add_irb_config(ri_conf)
            self.attach_irb(ri_conf, ri)

        if fip_map is not None:
            ri.add_interfaces(LogicalInterface(name=interfaces[0].name))

            public_vrf_ips = {}
            for pip in fip_map.values():
                if pip["vrf_name"] not in public_vrf_ips:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                floating_ips = []
                ri.add_floating_ip_list(
                    FloatingIpList(public_routing_instance=public_vrf,
                                   floating_ips=floating_ips))
                for fip in fips:
                    floating_ips.append(FloatingIpMap(floating_ip=fip))

        # add policies for export route targets
        if self.is_spine():
            p = PolicyRule(name=DMUtils.make_export_name(ri_name))
            p.set_comment(DMUtils.vn_ps_comment(vn, "Export"))
            then = Then()
            p.add_term(Term(name="t1", then=then))
            for route_target in export_targets:
                then.add_community(DMUtils.make_community_name(route_target))
            then.set_accept_or_reject(True)
            self.policy_config.add_policy_rule(p)

        # add policies for import route targets
        p = PolicyRule(name=DMUtils.make_import_name(ri_name))
        p.set_comment(DMUtils.vn_ps_comment(vn, "Import"))

        # add term switch policy
        from_ = From()
        term = Term(name=DMUtils.get_switch_policy_name(), fromxx=from_)
        p.add_term(term)
        from_.add_community(DMUtils.get_switch_policy_name())
        term.set_then(Then(accept_or_reject=True))

        from_ = From()
        term = Term(name="t1", fromxx=from_)
        p.add_term(term)
        for route_target in import_targets:
            from_.add_community(DMUtils.make_community_name(route_target))
            if not is_internal_vn:
                self.add_vni_option(vni or network_id, route_target)
        term.set_then(Then(accept_or_reject=True))
        self.policy_config.add_policy_rule(p)

        # add L2 EVPN and BD config
        if (is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            # add vlan config
            vlan_conf = self.add_vlan_config(ri_name, vni, is_l2_l3,
                                             "irb." + str(network_id))
            self.interfaces_config = self.interfaces_config or []
            self.build_l2_evpn_interface_config(self.interfaces_config,
                                                interfaces, vn, vlan_conf)

        if (not is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            ri.set_vtep_source_interface("lo0.0")
            evpn = self.build_evpn_config()
            if evpn:
                ri.set_protocols(RoutingInstanceProtocols(evpn=evpn))
            #add vlans
            self.add_ri_vlan_config(ri, vni)

        if (not is_l2 and not is_l2_l3 and gateways):
            self.interfaces_config = self.interfaces_config or []
            ifl_num = str(1000 + int(network_id))
            lo_intf = Interface(name="lo0")
            interfaces_config.add_interface(lo_intf)
            intf_unit = Unit(name=ifl_num,
                             comment=DMUtils.l3_lo_intf_comment(vn))
            lo_intf.add_logical_interfaces(intf_unit)
            family = Family()
            intf_unit.set_family(family)
            inet = None
            inet6 = None
            for (lo_ip, _) in gateways:
                subnet = lo_ip
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    if not inet6:
                        inet6 = FamilyInet6()
                        family.set_inet6(inet6)
                    addr = Address()
                    inet6.add_address(addr)
                    lo_ip = ip + '/' + '128'
                else:
                    if not inet:
                        inet = FamilyInet()
                        family.set_inet(inet)
                    addr = Address()
                    inet.add_address(addr)
                    lo_ip = ip + '/' + '32'
                addr.set_name(lo_ip)
                addr.set_comment(DMUtils.lo0_ip_comment(subnet))
            ri.add_interface(
                Interface(name="lo0." + ifl_num,
                          comment=DMUtils.lo0_ri_intf_comment(vn)))

        self.route_targets |= import_targets | export_targets
Esempio n. 4
0
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        vn = ri_conf.get("vn")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        network_id = ri_conf.get("network_id", None)
        is_internal_vn = True if '_contrail_lr_internal_vn_' in vn.name else False

        self.routing_instances[ri_name] = ri_conf
        ri_config = None
        policy_config = self.policy_config or \
                       PolicyOptions(comment=DMUtils.policy_options_comment())
        ri = None
        ri_opt = None
        ri_config = self.ri_config or \
                   RoutingInstances(comment=DMUtils.routing_instances_comment())
        ri = Instance(name=ri_name)
        if not is_l2:
            ri_config.add_instance(ri)
            ri.set_vrf_import(DMUtils.make_import_name(ri_name))
            ri.set_vrf_export(DMUtils.make_export_name(ri_name))

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            if ri_opt is None:
                ri_opt = RoutingInstanceRoutingOptions()
                ri.set_routing_options(ri_opt)

            ri.set_instance_type("vrf")
            for interface in interfaces:
                ri.add_interface(Interface(name=interface.name))
            family = Family()
            if has_ipv4_prefixes:
                family.set_inet(FamilyInet(unicast=''))
            if has_ipv6_prefixes:
                family.set_inet6(FamilyInet6(unicast=''))
            if has_ipv4_prefixes or has_ipv6_prefixes:
                auto_export = AutoExport(family=family)
                ri_opt.set_auto_export(auto_export)

        if is_internal_vn:
            self.internal_vn_ris.append(ri)
            self.add_bogus_lo0(ri, network_id, vn)

        if self.is_spine() and is_l2_l3:
            self.add_irb_config(ri_conf)
            self.attach_irb(ri_conf, ri)

        # add policies for export route targets
        if self.is_spine():
            ps = PolicyStatement(name=DMUtils.make_export_name(ri_name))
            ps.set_comment(DMUtils.vn_ps_comment(vn, "Export"))
            then = Then()
            ps.add_term(Term(name="t1", then=then))
            for route_target in export_targets:
                comm = Community(
                    add='',
                    community_name=DMUtils.make_community_name(route_target))
                then.add_community(comm)
                then.set_accept('')
            policy_config.add_policy_statement(ps)
            self.add_to_global_switch_opts(DMUtils.make_export_name(ri_name),
                                           False)

        # add policies for import route targets
        ps = PolicyStatement(name=DMUtils.make_import_name(ri_name))
        ps.set_comment(DMUtils.vn_ps_comment(vn, "Import"))

        # add term switch policy
        from_ = From()
        term = Term(name=DMUtils.get_switch_policy_name(), fromxx=from_)
        ps.add_term(term)
        from_.add_community(DMUtils.get_switch_policy_name())
        term.set_then(Then(accept=''))

        from_ = From()
        term = Term(name="t1", fromxx=from_)
        ps.add_term(term)
        for route_target in import_targets:
            from_.add_community(DMUtils.make_community_name(route_target))
            if not is_internal_vn:
                self.add_vni_option(vni or network_id, route_target)
        term.set_then(Then(accept=''))
        policy_config.add_policy_statement(ps)
        self.add_to_global_switch_opts(DMUtils.make_import_name(ri_name), True)

        # add L2 EVPN and BD config
        interfaces_config = self.interfaces_config
        if (is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            # add vlan config
            vlan_conf = self.add_vlan_config(ri_name, vni, is_l2_l3,
                                             "irb." + str(network_id))
            interfaces_config = self.interfaces_config or Interfaces(
                comment=DMUtils.interfaces_comment())
            self.build_l2_evpn_interface_config(interfaces_config, interfaces,
                                                vn, vlan_conf)

        if (not is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            ri.set_vtep_source_interface("lo0.0")
            evpn = self.build_evpn_config()
            if evpn:
                ri.set_protocols(RoutingInstanceProtocols(evpn=evpn))
            #add vlans
            self.add_ri_vlan_config(ri, vni)

        if (not is_l2 and not is_l2_l3 and gateways):
            interfaces_config = self.interfaces_config or \
                               Interfaces(comment=DMUtils.interfaces_comment())
            ifl_num = str(1000 + int(network_id))
            lo_intf = Interface(name="lo0")
            interfaces_config.add_interface(lo_intf)
            intf_unit = Unit(name=ifl_num,
                             comment=DMUtils.l3_lo_intf_comment(vn))
            lo_intf.add_unit(intf_unit)
            family = Family()
            intf_unit.set_family(family)
            inet = None
            inet6 = None
            for (lo_ip, _) in gateways:
                subnet = lo_ip
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    if not inet6:
                        inet6 = FamilyInet6()
                        family.set_inet6(inet6)
                    addr = Address()
                    inet6.add_address(addr)
                    lo_ip = ip + '/' + '128'
                else:
                    if not inet:
                        inet = FamilyInet()
                        family.set_inet(inet)
                    addr = Address()
                    inet.add_address(addr)
                    lo_ip = ip + '/' + '32'
                addr.set_name(lo_ip)
                addr.set_comment(DMUtils.lo0_ip_comment(subnet))
            ri.add_interface(
                Interface(name="lo0." + ifl_num,
                          comment=DMUtils.lo0_ri_intf_comment(vn)))

        self.policy_config = policy_config
        self.interfaces_config = interfaces_config
        self.route_targets |= import_targets | export_targets
        self.ri_config = ri_config
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        static_routes = ri_conf.get("static_routes", {})
        no_vrf_table_label = ri_conf.get("no_vrf_table_label", False)
        restrict_proxy_arp = ri_conf.get("restrict_proxy_arp", False)

        self.routing_instances[ri_name] = ri_conf

        ri_config = self.ri_config or etree.Element("routing-instances")
        policy_config = self.policy_config or etree.Element("policy-options")
        ri = etree.SubElement(ri_config, "instance")
        etree.SubElement(ri, "name").text = ri_name
        ri_opt = None
        if router_external and is_l2 == False:
            ri_opt = etree.SubElement(ri, "routing-options")
            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-table").text = "inet.0"

        # for both l2 and l3
        etree.SubElement(ri,
                         "vrf-import").text = DMUtils.make_import_name(ri_name)
        etree.SubElement(ri,
                         "vrf-export").text = DMUtils.make_export_name(ri_name)

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            if ri_opt is None:
                ri_opt = etree.SubElement(ri, "routing-options")
            if prefixes and fip_map is None:
                static_config = etree.SubElement(ri_opt, "static")
                rib_config_v6 = None
                static_config_v6 = None
                for prefix in prefixes:
                    if ':' in prefix and not rib_config_v6:
                        rib_config_v6 = etree.SubElement(ri_opt, "rib")
                        etree.SubElement(rib_config_v6,
                                         "name").text = ri_name + ".inet6.0"
                        static_config_v6 = etree.SubElement(
                            rib_config_v6, "static")
                    if ':' in prefix:
                        route_config = etree.SubElement(
                            static_config_v6, "route")
                    else:
                        route_config = etree.SubElement(static_config, "route")
                    etree.SubElement(route_config, "name").text = prefix
                    etree.SubElement(route_config, "discard")
                    if router_external:
                        self.add_to_global_ri_opts(prefix)

            etree.SubElement(ri, "instance-type").text = "vrf"
            if not no_vrf_table_label:
                etree.SubElement(ri, "vrf-table-label")  # only for l3
            if fip_map is None:
                for interface in interfaces:
                    if_element = etree.SubElement(ri, "interface")
                    etree.SubElement(if_element, "name").text = interface.name
            if ri_opt is None:
                ri_opt = etree.SubElement(ri, "routing-options")
            if static_routes:
                self.add_static_routes(ri_opt, static_routes)
            if has_ipv4_prefixes:
                auto_export = """<auto-export>
                                <family><inet><unicast/></inet></family>
                            </auto-export>"""
                ri_opt.append(etree.fromstring(auto_export))
            if has_ipv6_prefixes:
                auto_export = """<auto-export>
                                <family><inet6><unicast/></inet6></family>
                            </auto-export>"""
                ri_opt.append(etree.fromstring(auto_export))
        else:
            etree.SubElement(ri, "instance-type").text = "virtual-switch"

        if fip_map is not None:
            if ri_opt is None:
                ri_opt = etree.SubElement(ri, "routing-options")
            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].name
            if_element = etree.SubElement(ri, "interface")
            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:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                ri_public = etree.SubElement(ri_config, "instance")
                etree.SubElement(ri_public, "name").text = public_vrf
                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].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].name

        # add policies for export route targets
        ps = etree.SubElement(policy_config, "policy-statement")
        etree.SubElement(ps, "name").text = DMUtils.make_export_name(ri_name)
        term = etree.SubElement(ps, "term")
        etree.SubElement(term, "name").text = "t1"
        then = etree.SubElement(term, "then")
        for route_target in export_targets:
            comm = etree.SubElement(then, "community")
            etree.SubElement(comm, "add")
            etree.SubElement(
                comm, "community-name").text = DMUtils.make_community_name(
                    route_target)
        if fip_map is not None:
            # for nat instance
            etree.SubElement(then, "reject")
        else:
            etree.SubElement(then, "accept")

        # add policies for import route targets
        ps = etree.SubElement(policy_config, "policy-statement")
        etree.SubElement(ps, "name").text = DMUtils.make_import_name(ri_name)
        term = etree.SubElement(ps, "term")
        etree.SubElement(term, "name").text = "t1"
        from_ = etree.SubElement(term, "from")
        for route_target in import_targets:
            target_name = DMUtils.make_community_name(route_target)
            etree.SubElement(from_, "community").text = target_name
        then = etree.SubElement(term, "then")
        etree.SubElement(then, "accept")
        then = etree.SubElement(ps, "then")
        etree.SubElement(then, "reject")

        # add firewall config for public VRF
        forwarding_options_config = self.forwarding_options_config
        firewall_config = self.firewall_config
        if router_external and is_l2 == False:
            forwarding_options_config = (self.forwarding_options_config or
                                         etree.Element("forwarding-options"))
            firewall_config = self.firewall_config or etree.Element("firewall")
            if has_ipv4_prefixes and not self.inet4_forwarding_filter:
                #create single instance inet4 filter
                self.inet4_forwarding_filter = self.add_inet_public_vrf_filter(
                    forwarding_options_config, firewall_config, "inet4",
                    "inet")
            if has_ipv6_prefixes and not self.inet6_forwarding_filter:
                #create single instance inet6 filter
                self.inet6_forwarding_filter = self.add_inet_public_vrf_filter(
                    forwarding_options_config, firewall_config, "inet6",
                    "inet6")
            if has_ipv4_prefixes:
                #add terms to inet4 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
                # insert after 'name' element but before the last term
                self.inet4_forwarding_filter.insert(1, term)
            if has_ipv6_prefixes:
                #add terms to inet6 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet6")
                # insert after 'name' element but before the last term
                self.inet6_forwarding_filter.insert(1, term)

        if fip_map is not None:
            firewall_config = self.firewall_config or etree.Element("firewall")
            fc = etree.SubElement(firewall_config, "family")
            inet = etree.SubElement(fc, "inet")
            f = etree.SubElement(inet, "filter")
            etree.SubElement(
                f, "name").text = DMUtils.make_private_vrf_filter_name(ri_name)
            term = etree.SubElement(f, "term")
            etree.SubElement(term,
                             "name").text = DMUtils.make_vrf_term_name(ri_name)
            from_ = etree.SubElement(term, "from")
            for fip_user_ip in fip_map.keys():
                etree.SubElement(from_, "source-address").text = fip_user_ip
            then_ = etree.SubElement(term, "then")
            etree.SubElement(then_, "routing-instance").text = ri_name
            term = etree.SubElement(f, "term")
            etree.SubElement(term, "name").text = "default-term"
            then_ = etree.SubElement(term, "then")
            etree.SubElement(then_, "accept")

            interfaces_config = self.interfaces_config or etree.Element(
                "interfaces")
            irb_intf = etree.SubElement(interfaces_config, "interface")
            etree.SubElement(irb_intf, "name").text = "irb"
            intf_unit = etree.SubElement(irb_intf, "unit")
            etree.SubElement(intf_unit, "name").text = str(network_id)
            if restrict_proxy_arp:
                proxy_arp = etree.SubElement(intf_unit, "proxy-arp")
                etree.SubElement(proxy_arp, "restricted")
            family = etree.SubElement(intf_unit, "family")
            inet = etree.SubElement(family, "inet")
            f = etree.SubElement(inet, "filter")
            iput = etree.SubElement(f, "input")
            etree.SubElement(
                iput,
                "filter-name").text = DMUtils.make_private_vrf_filter_name(
                    ri_name)

        # add L2 EVPN and BD config
        bd_config = None
        interfaces_config = self.interfaces_config
        proto_config = self.proto_config
        if (is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            etree.SubElement(ri, "vtep-source-interface").text = "lo0.0"
            bd_config = etree.SubElement(ri, "bridge-domains")
            bd = etree.SubElement(bd_config, "domain")
            etree.SubElement(bd, "name").text = DMUtils.make_bridge_name(vni)
            etree.SubElement(bd, "vlan-id").text = 'none'
            vxlan = etree.SubElement(bd, "vxlan")
            etree.SubElement(vxlan, "vni").text = str(vni)
            for interface in interfaces:
                if_element = etree.SubElement(bd, "interface")
                etree.SubElement(if_element, "name").text = interface.name
            if is_l2_l3:
                # network_id is unique, hence irb
                etree.SubElement(
                    bd, "routing-interface").text = "irb." + str(network_id)
            evpn_proto_config = etree.SubElement(ri, "protocols")
            evpn = etree.SubElement(evpn_proto_config, "evpn")
            etree.SubElement(evpn, "encapsulation").text = "vxlan"
            etree.SubElement(evpn, "extended-vni-list").text = "all"

            interfaces_config = self.interfaces_config or etree.Element(
                "interfaces")
            if is_l2_l3:
                irb_intf = etree.SubElement(interfaces_config, "interface")
                etree.SubElement(irb_intf, "name").text = "irb"
                etree.SubElement(irb_intf, "gratuitous-arp-reply")
                if gateways is not None:
                    intf_unit = etree.SubElement(irb_intf, "unit")
                    etree.SubElement(intf_unit, "name").text = str(network_id)
                    family = etree.SubElement(intf_unit, "family")
                    inet = None
                    inet6 = None
                    for (irb_ip, gateway) in gateways:
                        if ':' in irb_ip:
                            if not inet6:
                                inet6 = etree.SubElement(family, "inet6")
                            addr = etree.SubElement(inet6, "address")
                        else:
                            if not inet:
                                inet = etree.SubElement(family, "inet")
                            addr = etree.SubElement(inet, "address")
                        etree.SubElement(addr, "name").text = irb_ip
                        if len(gateway) and gateway != '0.0.0.0':
                            etree.SubElement(
                                addr, "virtual-gateway-address").text = gateway

            lo_intf = etree.SubElement(interfaces_config, "interface")
            etree.SubElement(lo_intf, "name").text = "lo0"
            intf_unit = etree.SubElement(lo_intf, "unit")
            etree.SubElement(intf_unit, "name").text = "0"
            family = etree.SubElement(intf_unit, "family")
            inet = etree.SubElement(family, "inet")
            addr = etree.SubElement(inet, "address")
            etree.SubElement(addr,
                             "name").text = self.bgp_params['address'] + "/32"
            etree.SubElement(addr, "primary")
            etree.SubElement(addr, "preferred")

            self.build_l2_evpn_interface_config(interfaces_config, interfaces)

        # fip services config
        services_config = self.services_config
        if fip_map is not None:
            services_config = self.services_config or etree.Element("services")
            # mx has limitation for service-set and nat-rule name length,
            # allowed max 63 chars
            service_name = DMUtils.make_services_set_name(ri_name)
            service_set = etree.SubElement(services_config, "service-set")
            etree.SubElement(service_set, "name").text = service_name
            nat_rule = etree.SubElement(service_set, "nat-rules")
            etree.SubElement(
                nat_rule, "name").text = DMUtils.make_snat_rule_name(ri_name)
            nat_rule = etree.SubElement(service_set, "nat-rules")
            etree.SubElement(
                nat_rule, "name").text = DMUtils.make_dnat_rule_name(ri_name)
            next_hop_service = etree.SubElement(service_set,
                                                "next-hop-service")
            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")
            etree.SubElement(nat, "allow-overlapping-nat-pools")
            snat_rule = etree.SubElement(nat, "rule")
            etree.SubElement(
                snat_rule, "name").text = DMUtils.make_snat_rule_name(ri_name)
            etree.SubElement(snat_rule, "match-direction").text = "input"
            dnat_rule = etree.SubElement(nat, "rule")
            etree.SubElement(
                dnat_rule, "name").text = DMUtils.make_dnat_rule_name(ri_name)
            etree.SubElement(dnat_rule, "match-direction").text = "output"

            for pip, fip_vn in fip_map.items():
                fip = fip_vn["floating_ip"]
                term = etree.SubElement(snat_rule, "term")
                etree.SubElement(term,
                                 "name").text = DMUtils.make_ip_term_name(pip)
                from_ = etree.SubElement(term, "from")
                src_addr = etree.SubElement(from_, "source-address")
                # private ip
                etree.SubElement(src_addr, "name").text = pip + "/32"
                then_ = etree.SubElement(term, "then")
                translated = etree.SubElement(then_, "translated")
                etree.SubElement(
                    translated,
                    "source-prefix").text = fip + "/32"  # public ip
                translation_type = etree.SubElement(translated,
                                                    "translation-type")
                etree.SubElement(translation_type, "basic-nat44")

                term = etree.SubElement(dnat_rule, "term")
                etree.SubElement(term,
                                 "name").text = DMUtils.make_ip_term_name(fip)
                from_ = etree.SubElement(term, "from")
                src_addr = etree.SubElement(from_, "destination-address")
                etree.SubElement(src_addr,
                                 "name").text = fip + "/32"  # public ip
                then_ = etree.SubElement(term, "then")
                translated = etree.SubElement(then_, "translated")
                etree.SubElement(
                    translated,
                    "destination-prefix").text = pip + "/32"  # source ip
                translation_type = etree.SubElement(translated,
                                                    "translation-type")
                etree.SubElement(translation_type, "dnat-44")

            interfaces_config = self.interfaces_config or etree.Element(
                "interfaces")
            si_intf = etree.SubElement(interfaces_config, "interface")
            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].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].unit
            family = etree.SubElement(intf_unit, "family")
            etree.SubElement(family, "inet")
            etree.SubElement(intf_unit, "service-domain").text = "outside"

        self.forwarding_options_config = forwarding_options_config
        self.firewall_config = firewall_config
        self.policy_config = policy_config
        self.proto_config = proto_config
        self.interfaces_config = interfaces_config
        self.services_config = services_config
        self.route_targets |= import_targets | export_targets
        self.ri_config = ri_config
Esempio n. 6
0
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        static_routes = ri_conf.get("static_routes", {})
        no_vrf_table_label = ri_conf.get("no_vrf_table_label", False)
        restrict_proxy_arp = ri_conf.get("restrict_proxy_arp", False)
        highest_enapsulation_priority = \
                  ri_conf.get("highest_enapsulation_priority") or "MPLSoGRE"

        self.routing_instances[ri_name] = ri_conf
        ri_config = self.ri_config or RoutingInstances()
        policy_config = self.policy_config or PolicyOptions()
        ri = Instance(name=ri_name)
        ri_config.add_instance(ri)
        ri_opt = None
        if router_external and is_l2 == False:
            ri_opt = RoutingInstanceRoutingOptions(static=Static(
                route=[Route(name="0.0.0.0/0", next_table="inet.0")]))
            ri.set_routing_options(ri_opt)

        # for both l2 and l3
        ri.set_vrf_import(DMUtils.make_import_name(ri_name))
        ri.set_vrf_export(DMUtils.make_export_name(ri_name))

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            if ri_opt is None:
                ri_opt = RoutingInstanceRoutingOptions()
                ri.set_routing_options(ri_opt)
            if prefixes and fip_map is None:
                static_config = ri_opt.get_static()
                if not static_config:
                    static_config = Static()
                    ri_opt.set_static(static_config)
                rib_config_v6 = None
                static_config_v6 = None
                for prefix in prefixes:
                    if ':' in prefix and not rib_config_v6:
                        static_config_v6 = Static()
                        rib_config_v6 = RIB(name=ri_name + ".inet6.0")
                        rib_config_v6.set_static(static_config_v6)
                        ri_opt.set_rib(rib_config_v6)
                    if ':' in prefix:
                        static_config_v6.add_route(
                            Route(name=prefix, discard=''))
                    else:
                        static_config.add_route(Route(name=prefix, discard=''))
                    if router_external:
                        self.add_to_global_ri_opts(prefix)

            ri.set_instance_type("vrf")
            if not no_vrf_table_label:
                ri.set_vrf_table_label('')  # only for l3
            if fip_map is None:
                for interface in interfaces:
                    ri.add_interface(Interface(name=interface.name))
            if static_routes:
                self.add_static_routes(ri_opt, static_routes)
            if has_ipv4_prefixes:
                ri_opt.set_auto_export(
                    AutoExport(family=Family(inet=FamilyInet(unicast=''))))
            if has_ipv6_prefixes:
                ri_opt.set_auto_export(
                    AutoExport(family=Family(inet6=FamilyInet6(unicast=''))))
        else:
            if highest_enapsulation_priority == "VXLAN":
                ri.set_instance_type("virtual-switch")
            elif highest_enapsulation_priority in ["MPLSoGRE", "MPLSoUDP"]:
                ri.set_instance_type("evpn")

        if fip_map is not None:
            if ri_opt is None:
                ri_opt = RoutingInstanceRoutingOptions()
                ri.set_routing_options(ri_opt)
            static_config = ri_opt.get_static()
            if not static_config:
                static_config = Static()
                ri_opt.set_static(static_config)
            static_config.add_route(
                Route(name="0.0.0.0/0", next_hop=interfaces[0].name))
            ri.add_interface(Interface(name=interfaces[0].name))

            public_vrf_ips = {}
            for pip in fip_map.values():
                if pip["vrf_name"] not in public_vrf_ips:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                ri_public = Instance(name=public_vrf)
                ri_config.add_instance(ri_public)
                ri_public.add_interface(Interface(name=interfaces[1].name))

                ri_opt = RoutingInstanceRoutingOptions()
                ri_public.set_routing_options(ri_opt)
                static_config = Static()
                ri_opt.set_static(static_config)

                for fip in fips:
                    static_config.add_route(
                        Route(name=fip + "/32", next_hop=interfaces[1].name))

        # add policies for export route targets
        ps = PolicyStatement(name=DMUtils.make_export_name(ri_name))
        then = Then()
        ps.set_term(Term(name="t1", then=then))
        for route_target in export_targets:
            comm = Community(
                add='',
                community_name=DMUtils.make_community_name(route_target))
            then.add_community(comm)
        if fip_map is not None:
            # for nat instance
            then.set_reject('')
        else:
            then.set_accept('')
        policy_config.add_policy_statement(ps)

        # add policies for import route targets
        ps = PolicyStatement(name=DMUtils.make_import_name(ri_name))
        from_ = From()
        term = Term(name="t1", fromxx=from_)
        ps.set_term(term)
        for route_target in import_targets:
            from_.add_community(DMUtils.make_community_name(route_target))
        term.set_then(Then(accept=''))
        ps.set_then(Then(reject=''))
        policy_config.add_policy_statement(ps)

        # add firewall config for public VRF
        forwarding_options_config = self.forwarding_options_config
        firewall_config = self.firewall_config
        if router_external and is_l2 == False:
            forwarding_options_config = (self.forwarding_options_config
                                         or ForwardingOptions())
            firewall_config = self.firewall_config or Firewall()
            if has_ipv4_prefixes and not self.inet4_forwarding_filter:
                #create single instance inet4 filter
                self.inet4_forwarding_filter = self.add_inet_public_vrf_filter(
                    forwarding_options_config, firewall_config, "inet")
            if has_ipv6_prefixes and not self.inet6_forwarding_filter:
                #create single instance inet6 filter
                self.inet6_forwarding_filter = self.add_inet_public_vrf_filter(
                    forwarding_options_config, firewall_config, "inet6")
            if has_ipv4_prefixes:
                #add terms to inet4 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
                # insert before the last term
                terms = self.inet4_forwarding_filter.get_term()
                terms = [term] + (terms or [])
                self.inet4_forwarding_filter.set_term(terms)
            if has_ipv6_prefixes:
                #add terms to inet6 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet6")
                # insert before the last term
                terms = self.inet6_forwarding_filter.get_term()
                terms = [term] + (terms or [])
                self.inet6_forwarding_filter.set_term(terms)

        if fip_map is not None:
            firewall_config = firewall_config or Firewall()
            f = FirewallFilter(
                name=DMUtils.make_private_vrf_filter_name(ri_name))
            ff = firewall_config.get_family()
            if not ff:
                ff = FirewallFamily()
                firewall_config.set_family(ff)
            inet = ff.get_inet()
            if not inet:
                inet = FirewallInet()
                ff.set_inet(inet)
            inet.add_filter(f)

            term = Term(name=DMUtils.make_vrf_term_name(ri_name))
            from_ = From()
            for fip_user_ip in fip_map.keys():
                from_.add_source_address(fip_user_ip)
            term.set_from(from_)
            term.set_then(Then(routing_instance=[ri_name]))
            f.add_term(term)

            term = Term(name="default-term", then=Then(accept=''))
            f.add_term(term)

            interfaces_config = self.interfaces_config or Interfaces()
            irb_intf = Interface(name="irb")
            interfaces_config.add_interface(irb_intf)

            intf_unit = Unit(name=str(network_id))
            if restrict_proxy_arp:
                intf_unit.set_proxy_arp(ProxyArp(restricted=''))
            inet = FamilyInet()
            inet.set_filter(
                InetFilter(
                    input=DMUtils.make_private_vrf_filter_name(ri_name)))
            intf_unit.set_family(Family(inet=inet))
            irb_intf.add_unit(intf_unit)

        # add L2 EVPN and BD config
        bd_config = None
        interfaces_config = self.interfaces_config
        proto_config = self.proto_config
        if (is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            ri.set_vtep_source_interface("lo0.0")
            if highest_enapsulation_priority == "VXLAN":
                bd_config = BridgeDomains()
                ri.set_bridge_domains(bd_config)
                bd = Domain(name=DMUtils.make_bridge_name(vni),
                            vlan_id='none',
                            vxlan=VXLan(vni=vni))
                bd_config.add_domain(bd)
                for interface in interfaces:
                    bd.add_interface(Interface(name=interface.name))
                if is_l2_l3:
                    # network_id is unique, hence irb
                    bd.set_routing_interface("irb." + str(network_id))
                ri.set_protocols(
                    RoutingInstanceProtocols(evpn=Evpn(
                        encapsulation='vxlan', extended_vni_list='all')))
            elif highest_enapsulation_priority in ["MPLSoGRE", "MPLSoUDP"]:
                ri.set_vlan_id('none')
                if is_l2_l3:
                    # network_id is unique, hence irb
                    ri.set_routing_interface("irb." + str(network_id))
                evpn = Evpn()
                for interface in interfaces:
                    evpn.add_interface(Interface(name=interface.name))
                ri.set_protocols(RoutingInstanceProtocols(evpn=evpn))

            interfaces_config = self.interfaces_config or Interfaces()
            if is_l2_l3:
                irb_intf = Interface(name='irb', gratuitous_arp_reply='')
                interfaces_config.add_interface(irb_intf)
                if gateways is not None:
                    intf_unit = Unit(name=str(network_id))
                    irb_intf.add_unit(intf_unit)
                    family = Family()
                    intf_unit.set_family(family)
                    inet = None
                    inet6 = None
                    for (irb_ip, gateway) in gateways:
                        if ':' in irb_ip:
                            if not inet6:
                                inet6 = FamilyInet6()
                                family.set_inet6(inet6)
                            addr = Address()
                            inet6.add_address(addr)
                        else:
                            if not inet:
                                inet = FamilyInet()
                                family.set_inet(inet)
                            addr = Address()
                            inet.add_address(addr)
                        addr.set_name(irb_ip)
                        if len(gateway) and gateway != '0.0.0.0':
                            addr.set_virtual_gateway_address(gateway)

            lo_intf = Interface(name="lo0")
            interfaces_config.add_interface(lo_intf)
            fam_inet = FamilyInet(address=[
                Address(name=self.bgp_params['address'] + "/32",
                        primary='',
                        preferred='')
            ])
            intf_unit = Unit(name="0", family=Family(inet=fam_inet))
            lo_intf.add_unit(intf_unit)

            self.build_l2_evpn_interface_config(interfaces_config, interfaces)

        if (not is_l2 and not is_l2_l3 and gateways):
            interfaces_config = self.interfaces_config or Interfaces()
            ifl_num = str(1000 + int(network_id))
            lo_intf = Interface(name="lo0")
            interfaces_config.add_interface(lo_intf)
            intf_unit = Unit(name=ifl_num)
            lo_intf.add_unit(intf_unit)
            family = Family()
            intf_unit.set_family(family)
            inet = None
            inet6 = None
            for (lo_ip, _) in gateways:
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    if not inet6:
                        inet6 = FamilyInet6()
                        family.set_inet6(inet6)
                    addr = Address()
                    inet6.add_address(addr)
                    lo_ip = ip + '/' + '128'
                else:
                    if not inet:
                        inet = FamilyInet()
                        family.set_inet(inet)
                    addr = Address()
                    inet.add_address(addr)
                    lo_ip = ip + '/' + '32'
                addr.set_name(lo_ip)
            ri.add_interface(Interface(name="lo0." + ifl_num))

        # fip services config
        services_config = self.services_config
        if fip_map is not None:
            services_config = self.services_config or Services()
            service_name = DMUtils.make_services_set_name(ri_name)
            service_set = ServiceSet(name=service_name)
            services_config.add_service_set(service_set)
            nat_rule = NATRules(name=service_name + "-sn-rule")
            service_set.add_nat_rules(
                NATRules(name=DMUtils.make_snat_rule_name(ri_name)))
            service_set.add_nat_rules(
                NATRules(name=DMUtils.make_dnat_rule_name(ri_name)))
            next_hop_service = NextHopService(
                inside_service_interface=interfaces[0].name,
                outside_service_interface=interfaces[1].name)
            service_set.set_next_hop_service(next_hop_service)

            nat = NAT(allow_overlapping_nat_pools='')
            services_config.add_nat(nat)
            snat_rule = Rule(name=DMUtils.make_snat_rule_name(ri_name),
                             match_direction="input")
            nat.add_rule(snat_rule)
            dnat_rule = Rule(name=DMUtils.make_dnat_rule_name(ri_name),
                             match_direction="output")
            nat.add_rule(dnat_rule)

            for pip, fip_vn in fip_map.items():
                fip = fip_vn["floating_ip"]
                term = Term(name=DMUtils.make_ip_term_name(pip))
                snat_rule.set_term(term)
                # private ip
                from_ = From(source_address=[pip + "/32"])
                term.set_from(from_)
                # public ip
                then_ = Then()
                term.set_then(then_)
                translated = Translated(
                    source_prefix=fip + "/32",
                    translation_type=TranslationType(basic_nat44=''))
                then_.set_translated(translated)

                term = Term(name=DMUtils.make_ip_term_name(fip))
                dnat_rule.set_term(term)

                # public ip
                from_ = From(destination_address=[fip + "/32"])
                term.set_from(from_)
                # private ip
                then_ = Then()
                term.set_then(then_)
                translated = Translated(
                    destination_prefix=pip + "/32",
                    translation_type=TranslationType(dnat_44=''))
                then_.set_translated(translated)

            interfaces_config = self.interfaces_config or Interfaces()
            si_intf = Interface(name=interfaces[0].ifd_name)
            interfaces_config.add_interface(si_intf)

            intf_unit = Unit(name=interfaces[0].unit)
            si_intf.add_unit(intf_unit)
            family = Family(inet=FamilyInet())
            intf_unit.set_family(family)
            intf_unit.set_service_domain("inside")

            intf_unit = Unit(name=interfaces[1].unit)
            si_intf.add_unit(intf_unit)
            family = Family(inet=FamilyInet())
            intf_unit.set_family(family)
            intf_unit.set_service_domain("outside")

        self.forwarding_options_config = forwarding_options_config
        self.firewall_config = firewall_config
        self.policy_config = policy_config
        self.proto_config = proto_config
        self.interfaces_config = interfaces_config
        self.services_config = services_config
        self.route_targets |= import_targets | export_targets
        self.ri_config = ri_config
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        static_routes = ri_conf.get("static_routes", {})
        no_vrf_table_label = ri_conf.get("no_vrf_table_label", False)
        restrict_proxy_arp = ri_conf.get("restrict_proxy_arp", False)

        self.routing_instances[ri_name] = ri_conf

        ri_config = self.ri_config or etree.Element("routing-instances")
        policy_config = self.policy_config or etree.Element("policy-options")
        ri = etree.SubElement(ri_config, "instance")
        etree.SubElement(ri, "name").text = ri_name
        ri_opt = None
        if router_external and is_l2 == False:
            ri_opt = etree.SubElement(ri, "routing-options")
            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-table").text = "inet.0"

        # for both l2 and l3
        etree.SubElement(ri, "vrf-import").text = DMUtils.make_import_name(ri_name)
        etree.SubElement(ri, "vrf-export").text = DMUtils.make_export_name(ri_name)

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            if ri_opt is None:
                ri_opt = etree.SubElement(ri, "routing-options")
            if prefixes and fip_map is None:
                static_config = etree.SubElement(ri_opt, "static")
                rib_config_v6 = None
                static_config_v6 = None
                for prefix in prefixes:
                    if ':' in prefix and not rib_config_v6:
                        rib_config_v6 = etree.SubElement(ri_opt, "rib")
                        etree.SubElement(rib_config_v6, "name").text = ri_name + ".inet6.0"
                        static_config_v6 = etree.SubElement(rib_config_v6, "static")
                    if ':' in prefix:
                        route_config = etree.SubElement(static_config_v6, "route")
                    else:
                        route_config = etree.SubElement(static_config, "route")
                    etree.SubElement(route_config, "name").text = prefix
                    etree.SubElement(route_config, "discard")
                    if router_external:
                        self.add_to_global_ri_opts(prefix)

            etree.SubElement(ri, "instance-type").text = "vrf"
            if not no_vrf_table_label:
                etree.SubElement(ri, "vrf-table-label")  # only for l3
            if fip_map is None:
                for interface in interfaces:
                    if_element = etree.SubElement(ri, "interface")
                    etree.SubElement(if_element, "name").text = interface.name
            if ri_opt is None:
                ri_opt = etree.SubElement(ri, "routing-options")
            if static_routes:
                self.add_static_routes(ri_opt, static_routes)
            if has_ipv4_prefixes:
                auto_export = """<auto-export>
                                <family><inet><unicast/></inet></family>
                            </auto-export>"""
                ri_opt.append(etree.fromstring(auto_export))
            if has_ipv6_prefixes:
                auto_export = """<auto-export>
                                <family><inet6><unicast/></inet6></family>
                            </auto-export>"""
                ri_opt.append(etree.fromstring(auto_export))
        else:
            etree.SubElement(ri, "instance-type").text = "virtual-switch"

        if fip_map is not None:
            if ri_opt is None:
                ri_opt = etree.SubElement(ri, "routing-options")
            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].name
            if_element = etree.SubElement(ri, "interface")
            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:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                ri_public = etree.SubElement(ri_config, "instance")
                etree.SubElement(ri_public, "name").text = public_vrf
                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].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].name

        # add policies for export route targets
        ps = etree.SubElement(policy_config, "policy-statement")
        etree.SubElement(ps, "name").text = DMUtils.make_export_name(ri_name)
        term = etree.SubElement(ps, "term")
        etree.SubElement(term, "name").text = "t1"
        then = etree.SubElement(term, "then")
        for route_target in export_targets:
            comm = etree.SubElement(then, "community")
            etree.SubElement(comm, "add")
            etree.SubElement(
                comm, "community-name").text = DMUtils.make_community_name(route_target)
        if fip_map is not None:
            # for nat instance
            etree.SubElement(then, "reject")
        else:
            etree.SubElement(then, "accept")

        # add policies for import route targets
        ps = etree.SubElement(policy_config, "policy-statement")
        etree.SubElement(ps, "name").text = DMUtils.make_import_name(ri_name)
        term = etree.SubElement(ps, "term")
        etree.SubElement(term, "name").text = "t1"
        from_ = etree.SubElement(term, "from")
        for route_target in import_targets:
            target_name = DMUtils.make_community_name(route_target)
            etree.SubElement(from_, "community").text = target_name
        then = etree.SubElement(term, "then")
        etree.SubElement(then, "accept")
        then = etree.SubElement(ps, "then")
        etree.SubElement(then, "reject")

        # add firewall config for public VRF
        forwarding_options_config = self.forwarding_options_config
        firewall_config = self.firewall_config
        if router_external and is_l2 == False:
            forwarding_options_config = (self.forwarding_options_config or
                                           etree.Element("forwarding-options"))
            firewall_config = self.firewall_config or etree.Element("firewall")
            if has_ipv4_prefixes and not self.inet4_forwarding_filter:
                #create single instance inet4 filter
                self.inet4_forwarding_filter = self.add_inet_public_vrf_filter(
                                                       forwarding_options_config,
                                                       firewall_config, "inet4", "inet")
            if has_ipv6_prefixes and not self.inet6_forwarding_filter:
                #create single instance inet6 filter
                self.inet6_forwarding_filter = self.add_inet_public_vrf_filter(
                                                       forwarding_options_config,
                                                       firewall_config, "inet6", "inet6")
            if has_ipv4_prefixes:
                #add terms to inet4 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
                # insert after 'name' element but before the last term
                self.inet4_forwarding_filter.insert(1, term)
            if has_ipv6_prefixes:
                #add terms to inet6 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet6")
                # insert after 'name' element but before the last term
                self.inet6_forwarding_filter.insert(1, term)

        if fip_map is not None:
            firewall_config = self.firewall_config or etree.Element("firewall")
            fc = etree.SubElement(firewall_config, "family")
            inet = etree.SubElement(fc, "inet")
            f = etree.SubElement(inet, "filter")
            etree.SubElement(
                f, "name").text = DMUtils.make_private_vrf_filter_name(ri_name)
            term = etree.SubElement(f, "term")
            etree.SubElement(term, "name").text = DMUtils.make_vrf_term_name(ri_name)
            from_ = etree.SubElement(term, "from")
            for fip_user_ip in fip_map.keys():
                etree.SubElement(from_, "source-address").text = fip_user_ip
            then_ = etree.SubElement(term, "then")
            etree.SubElement(then_, "routing-instance").text = ri_name
            term = etree.SubElement(f, "term")
            etree.SubElement(term, "name").text = "default-term"
            then_ = etree.SubElement(term, "then")
            etree.SubElement(then_, "accept")

            interfaces_config = self.interfaces_config or etree.Element(
                "interfaces")
            irb_intf = etree.SubElement(interfaces_config, "interface")
            etree.SubElement(irb_intf, "name").text = "irb"
            intf_unit = etree.SubElement(irb_intf, "unit")
            etree.SubElement(intf_unit, "name").text = str(network_id)
            if restrict_proxy_arp:
                proxy_arp = etree.SubElement(intf_unit, "proxy-arp")
                etree.SubElement(proxy_arp, "restricted")
            family = etree.SubElement(intf_unit, "family")
            inet = etree.SubElement(family, "inet")
            f = etree.SubElement(inet, "filter")
            iput = etree.SubElement(f, "input")
            etree.SubElement(
                iput,
                "filter-name").text = DMUtils.make_private_vrf_filter_name(ri_name)

        # add L2 EVPN and BD config
        bd_config = None
        interfaces_config = self.interfaces_config
        proto_config = self.proto_config
        if (is_l2 and vni is not None and
                self.is_family_configured(self.bgp_params, "e-vpn")):
            etree.SubElement(ri, "vtep-source-interface").text = "lo0.0"
            bd_config = etree.SubElement(ri, "bridge-domains")
            bd = etree.SubElement(bd_config, "domain")
            etree.SubElement(bd, "name").text = DMUtils.make_bridge_name(vni)
            etree.SubElement(bd, "vlan-id").text = 'none'
            vxlan = etree.SubElement(bd, "vxlan")
            etree.SubElement(vxlan, "vni").text = str(vni)
            for interface in interfaces:
                if_element = etree.SubElement(bd, "interface")
                etree.SubElement(if_element, "name").text = interface.name
            if is_l2_l3:
                # network_id is unique, hence irb
                etree.SubElement(
                    bd, "routing-interface").text = "irb." + str(network_id)
            evpn_proto_config = etree.SubElement(ri, "protocols")
            evpn = etree.SubElement(evpn_proto_config, "evpn")
            etree.SubElement(evpn, "encapsulation").text = "vxlan"
            etree.SubElement(evpn, "extended-vni-list").text = "all"

            interfaces_config = self.interfaces_config or etree.Element(
                "interfaces")
            if is_l2_l3:
                irb_intf = etree.SubElement(interfaces_config, "interface")
                etree.SubElement(irb_intf, "name").text = "irb"
                etree.SubElement(irb_intf, "gratuitous-arp-reply")
                if gateways is not None:
                    intf_unit = etree.SubElement(irb_intf, "unit")
                    etree.SubElement(intf_unit, "name").text = str(network_id)
                    family = etree.SubElement(intf_unit, "family")
                    inet = None
                    inet6 = None
                    for (irb_ip, gateway) in gateways:
                        if ':' in irb_ip:
                            if not inet6:
                                inet6 = etree.SubElement(family, "inet6")
                            addr = etree.SubElement(inet6, "address")
                        else:
                            if not inet:
                                inet = etree.SubElement(family, "inet")
                            addr = etree.SubElement(inet, "address")
                        etree.SubElement(addr, "name").text = irb_ip
                        if len(gateway) and gateway != '0.0.0.0':
                            etree.SubElement(
                                addr, "virtual-gateway-address").text = gateway

            lo_intf = etree.SubElement(interfaces_config, "interface")
            etree.SubElement(lo_intf, "name").text = "lo0"
            intf_unit = etree.SubElement(lo_intf, "unit")
            etree.SubElement(intf_unit, "name").text = "0"
            family = etree.SubElement(intf_unit, "family")
            inet = etree.SubElement(family, "inet")
            addr = etree.SubElement(inet, "address")
            etree.SubElement(addr, "name").text = self.bgp_params[
                'address'] + "/32"
            etree.SubElement(addr, "primary")
            etree.SubElement(addr, "preferred")

            self.build_l2_evpn_interface_config(interfaces_config, interfaces)

        # fip services config
        services_config = self.services_config
        if fip_map is not None:
            services_config = self.services_config or etree.Element("services")
            # mx has limitation for service-set and nat-rule name length,
            # allowed max 63 chars
            service_name = DMUtils.make_services_set_name(ri_name)
            service_set = etree.SubElement(services_config, "service-set")
            etree.SubElement(service_set, "name").text = service_name
            nat_rule = etree.SubElement(service_set, "nat-rules")
            etree.SubElement(nat_rule, "name").text = DMUtils.make_snat_rule_name(ri_name)
            nat_rule = etree.SubElement(service_set, "nat-rules")
            etree.SubElement(nat_rule, "name").text = DMUtils.make_dnat_rule_name(ri_name)
            next_hop_service = etree.SubElement(
                service_set, "next-hop-service")
            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")
            etree.SubElement(nat, "allow-overlapping-nat-pools")
            snat_rule = etree.SubElement(nat, "rule")
            etree.SubElement(
                snat_rule, "name").text = DMUtils.make_snat_rule_name(ri_name)
            etree.SubElement(snat_rule, "match-direction").text = "input"
            dnat_rule = etree.SubElement(nat, "rule")
            etree.SubElement(
                dnat_rule, "name").text = DMUtils.make_dnat_rule_name(ri_name)
            etree.SubElement(dnat_rule, "match-direction").text = "output"

            for pip, fip_vn in fip_map.items():
                fip = fip_vn["floating_ip"]
                term = etree.SubElement(snat_rule, "term")
                etree.SubElement(
                    term, "name").text = DMUtils.make_ip_term_name(pip)
                from_ = etree.SubElement(term, "from")
                src_addr = etree.SubElement(from_, "source-address")
                # private ip
                etree.SubElement(src_addr, "name").text = pip + "/32"
                then_ = etree.SubElement(term, "then")
                translated = etree.SubElement(then_, "translated")
                etree.SubElement(
                    translated,
                    "source-prefix").text = fip + "/32"  # public ip
                translation_type = etree.SubElement(
                    translated, "translation-type")
                etree.SubElement(translation_type, "basic-nat44")

                term = etree.SubElement(dnat_rule, "term")
                etree.SubElement(
                    term, "name").text = DMUtils.make_ip_term_name(fip)
                from_ = etree.SubElement(term, "from")
                src_addr = etree.SubElement(from_, "destination-address")
                etree.SubElement(
                    src_addr, "name").text = fip + "/32"  # public ip
                then_ = etree.SubElement(term, "then")
                translated = etree.SubElement(then_, "translated")
                etree.SubElement(
                    translated,
                    "destination-prefix").text = pip + "/32"  # source ip
                translation_type = etree.SubElement(
                    translated, "translation-type")
                etree.SubElement(translation_type, "dnat-44")

            interfaces_config = self.interfaces_config or etree.Element(
                "interfaces")
            si_intf = etree.SubElement(interfaces_config, "interface")
            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].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].unit
            family = etree.SubElement(intf_unit, "family")
            etree.SubElement(family, "inet")
            etree.SubElement(intf_unit, "service-domain").text = "outside"

        self.forwarding_options_config = forwarding_options_config
        self.firewall_config = firewall_config
        self.policy_config = policy_config
        self.proto_config = proto_config
        self.interfaces_config = interfaces_config
        self.services_config = services_config
        self.route_targets |= import_targets | export_targets
        self.ri_config = ri_config
Esempio n. 8
0
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        vn = ri_conf.get("vn")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        is_dci = ri_conf.get("is_dci_network", False)
        connected_dci_network = ri_conf.get("connected_dci_network")
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        is_internal_vn = True if '_contrail_lr_internal_vn_' in vn.name else False
        is_dci_vn = True if '_contrail_dci_internal_vn_' in vn.name else False
        encapsulation_priorities = \
           ri_conf.get("encapsulation_priorities") or ["MPLSoGRE"]

        ri = RoutingInstance(name=ri_name)
        if vn:
            is_nat = True if fip_map else False
            ri.set_comment(
                DMUtils.vn_ri_comment(vn, is_l2, is_l2_l3, is_nat,
                                      router_external))
        self.ri_map[ri_name] = ri

        ri.set_virtual_network_id(str(network_id))
        ri.set_vxlan_id(str(vni))
        ri.set_virtual_network_is_internal(is_internal_vn or is_dci_vn)
        ri.set_is_public_network(router_external)
        if is_l2_l3:
            ri.set_virtual_network_mode('l2-l3')
        elif is_l2:
            ri.set_virtual_network_mode('l2')
        else:
            ri.set_virtual_network_mode('l3')

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            ri.set_routing_instance_type("vrf")
            if fip_map is None:
                for interface in interfaces:
                    self.add_ref_to_list(ri.get_interfaces(), interface.name)
                if prefixes:
                    for prefix in prefixes:
                        ri.add_static_routes(self.get_route_for_cidr(prefix))
                        ri.add_prefixes(self.get_subnet_for_cidr(prefix))
        else:
            if encapsulation_priorities[0] == "VXLAN":
                ri.set_routing_instance_type("virtual-switch")
            elif (any(x in encapsulation_priorities
                      for x in ["MPLSoGRE", "MPLSoUDP"])):
                ri.set_routing_instance_type("evpn")

        if is_internal_vn:
            self.internal_vn_ris.append(ri)
        if is_dci_vn:
            self.dci_vn_ris.append(ri)

        if is_internal_vn or router_external or is_dci_vn:
            self.add_bogus_lo0(ri, network_id, vn)

        if self.is_gateway() and is_l2_l3:
            self.add_irb_config(ri_conf)
            self.attach_irb(ri_conf, ri)

        if fip_map is not None:
            self.add_ref_to_list(ri.get_interfaces(), interfaces[0].name)

            public_vrf_ips = {}
            for pip in fip_map.values():
                if pip["vrf_name"] not in public_vrf_ips:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                ri_public = RoutingInstance(name=public_vrf)
                self.ri_map[public_vrf] = ri_public
                self.add_ref_to_list(ri_public.get_interfaces(),
                                     interfaces[1].name)
                floating_ips = []
                for fip in fips:
                    ri_public.add_static_routes(
                        Route(prefix=fip,
                              prefix_len=32,
                              next_hop=interfaces[1].name,
                              comment=DMUtils.fip_egress_comment()))
                    floating_ips.append(FloatingIpMap(floating_ip=fip + "/32"))
                ri_public.add_floating_ip_list(
                    FloatingIpList(public_routing_instance=public_vrf,
                                   floating_ips=floating_ips))

        # add firewall config for public VRF
        if router_external and is_l2 is False:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            if has_ipv4_prefixes and not self.inet4_forwarding_filter:
                # create single instance inet4 filter
                self.inet4_forwarding_filter = self.add_inet_public_vrf_filter(
                    self.firewall_config, "inet")
            if has_ipv6_prefixes and not self.inet6_forwarding_filter:
                # create single instance inet6 filter
                self.inet6_forwarding_filter = self.add_inet_public_vrf_filter(
                    self.firewall_config, "inet6")
            if has_ipv4_prefixes:
                # add terms to inet4 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
                # insert before the last term
                terms = self.inet4_forwarding_filter.get_terms()
                terms = [term] + (terms or [])
                self.inet4_forwarding_filter.set_terms(terms)
            if has_ipv6_prefixes:
                # add terms to inet6 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet6")
                # insert before the last term
                terms = self.inet6_forwarding_filter.get_terms()
                terms = [term] + (terms or [])
                self.inet6_forwarding_filter.set_terms(terms)

        # add firewall config for DCI Network
        if is_dci:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            self.dci_forwarding_filter[vn.uuid] = self.add_inet_vrf_filter(
                self.firewall_config, ri_name)
            # add terms to inet4 filter
            term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
            # insert before the last term
            terms = self.dci_forwarding_filter[vn.uuid].get_terms()
            terms = [term] + (terms or [])
            self.dci_forwarding_filter[vn.uuid].set_terms(terms)

        if fip_map is not None:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            f = FirewallFilter(
                name=DMUtils.make_private_vrf_filter_name(ri_name))
            f.set_comment(DMUtils.vn_firewall_comment(vn, "private"))
            self.firewall_config.add_firewall_filters(f)

            term = Term(name=DMUtils.make_vrf_term_name(ri_name))
            from_ = From()
            for fip_user_ip in fip_map.keys():
                from_.add_source_address(self.get_subnet_for_cidr(fip_user_ip))
            term.set_from(from_)
            term.set_then(Then(routing_instance=[ri_name]))
            f.add_terms(term)

            irb_intf, li_map = self.set_default_pi('irb', 'irb')
            intf_name = 'irb.' + str(network_id)
            intf_unit = self.set_default_li(li_map, intf_name, network_id)
            intf_unit.set_comment(DMUtils.vn_irb_fip_inet_comment(vn))
            intf_unit.set_family("inet")
            intf_unit.add_firewall_filters(
                DMUtils.make_private_vrf_filter_name(ri_name))
            self.add_ref_to_list(ri.get_routing_interfaces(), intf_name)

        if gateways is not None:
            for (ip, gateway) in gateways:
                ri.add_gateways(
                    GatewayRoute(ip_address=self.get_subnet_for_cidr(ip),
                                 gateway=self.get_subnet_for_cidr(gateway)))

        # add L2 EVPN and BD config
        if (is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            vlan = None
            if encapsulation_priorities[0] == "VXLAN":
                vlan = Vlan(name=DMUtils.make_bridge_name(vni), vxlan_id=vni)
                vlan.set_comment(DMUtils.vn_bd_comment(vn, "VXLAN"))
                self.vlan_map[vlan.get_name()] = vlan
                for interface in interfaces:
                    self.add_ref_to_list(vlan.get_interfaces(), interface.name)
                if is_l2_l3:
                    # network_id is unique, hence irb
                    irb_intf = "irb." + str(network_id)
                    self.add_ref_to_list(vlan.get_interfaces(), irb_intf)
            elif (any(x in encapsulation_priorities
                      for x in ["MPLSoGRE", "MPLSoUDP"])):
                self.init_evpn_config(encapsulation_priorities[1])
                self.evpn.set_comment(
                    DMUtils.vn_evpn_comment(vn, encapsulation_priorities[1]))
                for interface in interfaces:
                    self.add_ref_to_list(self.evpn.get_interfaces(),
                                         interface.name)

            self.build_l2_evpn_interface_config(interfaces, vn, vlan)

        if (not is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            self.init_evpn_config()
            if not is_internal_vn and not is_dci_vn:
                # add vlans
                self.add_ri_vlan_config(ri_name, vni)

        if (not is_l2 and not is_l2_l3 and gateways):
            ifl_num = 1000 + int(network_id)
            lo_intf, li_map = self.set_default_pi('lo0', 'loopback')
            intf_name = 'lo0.' + str(ifl_num)
            intf_unit = self.set_default_li(li_map, intf_name, ifl_num)
            intf_unit.set_comment(DMUtils.l3_lo_intf_comment(vn))
            for (lo_ip, _) in gateways:
                subnet = lo_ip
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    lo_ip = ip + '/' + '128'
                else:
                    lo_ip = ip + '/' + '32'
                intf_unit.add_ip_list(lo_ip)
            self.add_ref_to_list(ri.get_loopback_interfaces(), intf_name)

        # fip services config
        if fip_map is not None:
            nat_rules = NatRules(allow_overlapping_nat_pools=True,
                                 name=DMUtils.make_services_set_name(ri_name),
                                 comment=DMUtils.service_set_comment(vn))
            ri.set_nat_rules(nat_rules)
            snat_rule = NatRule(name=DMUtils.make_snat_rule_name(ri_name),
                                comment=DMUtils.service_set_nat_rule_comment(
                                    vn, "SNAT"),
                                direction="input",
                                translation_type="basic-nat44")
            snat_rule.set_comment(DMUtils.snat_rule_comment())
            nat_rules.add_rules(snat_rule)
            dnat_rule = NatRule(name=DMUtils.make_dnat_rule_name(ri_name),
                                comment=DMUtils.service_set_nat_rule_comment(
                                    vn, "DNAT"),
                                direction="output",
                                translation_type="dnat-44")
            dnat_rule.set_comment(DMUtils.dnat_rule_comment())
            nat_rules.add_rules(dnat_rule)
            nat_rules.set_inside_interface(interfaces[0].name)
            nat_rules.set_outside_interface(interfaces[1].name)

            for pip, fip_vn in fip_map.items():
                fip = fip_vn["floating_ip"]
                # private ip
                snat_rule.add_source_addresses(self.get_subnet_for_cidr(pip))
                # public ip
                snat_rule.add_source_prefixes(self.get_subnet_for_cidr(fip))

                # public ip
                dnat_rule.add_destination_addresses(
                    self.get_subnet_for_cidr(fip))
                # private ip
                dnat_rule.add_destination_prefixes(
                    self.get_subnet_for_cidr(pip))

            self.add_ref_to_list(ri.get_ingress_interfaces(),
                                 interfaces[0].name)
            self.add_ref_to_list(ri.get_egress_interfaces(),
                                 interfaces[1].name)

        for target in import_targets:
            self.add_to_list(ri.get_import_targets(), target)

        for target in export_targets:
            self.add_to_list(ri.get_export_targets(), target)
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        vn = ri_conf.get("vn")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        network_id = ri_conf.get("network_id", None)

        self.routing_instances[ri_name] = ri_conf
        ri_config = None
        policy_config = self.policy_config or \
                       PolicyOptions(comment=DMUtils.policy_options_comment())
        ri = None
        ri_opt = None
        if not is_l2:
            ri_config = self.ri_config or \
                   RoutingInstances(comment=DMUtils.routing_instances_comment())
            ri = Instance(name=ri_name)
            ri_config.add_instance(ri)
            ri.set_vrf_import(DMUtils.make_import_name(ri_name))
            ri.set_vrf_export(DMUtils.make_export_name(ri_name))

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            if ri_opt is None:
                ri_opt = RoutingInstanceRoutingOptions()
                ri.set_routing_options(ri_opt)

            ri.set_instance_type("vrf")
            for interface in interfaces:
                ri.add_interface(Interface(name=interface.name))
            family = Family()
            if has_ipv4_prefixes:
                family.set_inet(FamilyInet(unicast=''))
            if has_ipv6_prefixes:
                family.set_inet6(FamilyInet6(unicast=''))
            if has_ipv4_prefixes or has_ipv6_prefixes:
                auto_export = AutoExport(family=family)
                ri_opt.set_auto_export(auto_export)

        # add policies for export route targets
        if self.is_spine():
            ps = PolicyStatement(name=DMUtils.make_export_name(ri_name))
            ps.set_comment(DMUtils.vn_ps_comment(vn, "Export"))
            then = Then()
            ps.add_term(Term(name="t1", then=then))
            for route_target in export_targets:
                comm = Community(add='',
                             community_name=DMUtils.make_community_name(route_target))
                then.add_community(comm)
                then.set_accept('')
            policy_config.add_policy_statement(ps)
            self.add_to_global_switch_opts(DMUtils.make_export_name(ri_name), False)

        # add policies for import route targets
        ps = PolicyStatement(name=DMUtils.make_import_name(ri_name))
        ps.set_comment(DMUtils.vn_ps_comment(vn, "Import"))

        # add term switch policy
        from_ = From()
        term = Term(name=DMUtils.get_switch_policy_name(), fromxx=from_)
        ps.add_term(term)
        from_.add_community(DMUtils.get_switch_policy_name())
        term.set_then(Then(accept=''))

        from_ = From()
        term = Term(name="t1", fromxx=from_)
        ps.add_term(term)
        for route_target in import_targets:
            from_.add_community(DMUtils.make_community_name(route_target))
            if not self.is_spine():
                self.add_vni_option(vni or network_id, route_target)
        term.set_then(Then(accept=''))
        policy_config.add_policy_statement(ps)
        self.add_to_global_switch_opts(DMUtils.make_import_name(ri_name), True)

        # add L2 EVPN and BD config
        interfaces_config = self.interfaces_config
        if (is_l2 and vni is not None and
                self.is_family_configured(self.bgp_params, "e-vpn")):
            # add vlan config
            vlan_conf = self.add_vlan_config(ri_name, vni)
            interfaces_config = self.interfaces_config or Interfaces(comment=DMUtils.interfaces_comment())
            if is_l2_l3 and self.is_spine():
                irb_intf = Interface(name='irb', gratuitous_arp_reply='')
                interfaces_config.add_interface(irb_intf)
                if gateways is not None:
                    intf_unit = Unit(name=str(network_id),
                                     comment=DMUtils.vn_irb_comment(vn, False, is_l2_l3))
                    irb_intf.add_unit(intf_unit)
                    if self.is_spine():
                        intf_unit.set_proxy_macip_advertisement('')
                    family = Family()
                    intf_unit.set_family(family)
                    inet = None
                    inet6 = None
                    for (irb_ip, gateway) in gateways:
                        if ':' in irb_ip:
                            if not inet6:
                                inet6 = FamilyInet6()
                                family.set_inet6(inet6)
                            addr = Address()
                            inet6.add_address(addr)
                        else:
                            if not inet:
                                inet = FamilyInet()
                                family.set_inet(inet)
                            addr = Address()
                            inet.add_address(addr)
                        addr.set_name(irb_ip)
                        addr.set_comment(DMUtils.irb_ip_comment(irb_ip))
                        if len(gateway) and gateway != '0.0.0.0':
                            addr.set_virtual_gateway_address(gateway)
            self.build_l2_evpn_interface_config(interfaces_config,
                                              interfaces, vn, vlan_conf)

        if (not is_l2 and vni is not None and
                self.is_family_configured(self.bgp_params, "e-vpn")):
            ri.set_vtep_source_interface("lo0.0")
            evpn = self.build_evpn_config()
            if evpn:
                ri.set_protocols(RoutingInstanceProtocols(evpn=evpn))
            #add vlans
            self.add_ri_vlan_config(ri, vni)

        if (not is_l2 and not is_l2_l3 and gateways):
            interfaces_config = self.interfaces_config or \
                               Interfaces(comment=DMUtils.interfaces_comment())
            ifl_num = str(1000 + int(network_id))
            lo_intf = Interface(name="lo0")
            interfaces_config.add_interface(lo_intf)
            intf_unit = Unit(name=ifl_num, comment=DMUtils.l3_lo_intf_comment(vn))
            lo_intf.add_unit(intf_unit)
            family = Family()
            intf_unit.set_family(family)
            inet = None
            inet6 = None
            for (lo_ip, _) in gateways:
                subnet = lo_ip
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    if not inet6:
                        inet6 = FamilyInet6()
                        family.set_inet6(inet6)
                    addr = Address()
                    inet6.add_address(addr)
                    lo_ip = ip + '/' + '128'
                else:
                    if not inet:
                        inet = FamilyInet()
                        family.set_inet(inet)
                    addr = Address()
                    inet.add_address(addr)
                    lo_ip = ip + '/' + '32'
                addr.set_name(lo_ip)
                addr.set_comment(DMUtils.lo0_ip_comment(subnet))
            ri.add_interface(Interface(name="lo0." + ifl_num,
                                       comment=DMUtils.lo0_ri_intf_comment(vn)))

        self.policy_config = policy_config
        self.interfaces_config = interfaces_config
        self.route_targets |= import_targets | export_targets
        self.ri_config = ri_config
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        vn = ri_conf.get("vn")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        is_dci = ri_conf.get("is_dci_network", False)
        connected_dci_network = ri_conf.get("connected_dci_network")
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        is_internal_vn = True if '_contrail_lr_internal_vn_' in vn.name else False
        is_dci_vn = True if '_contrail_dci_internal_vn_' in vn.name else False
        encapsulation_priorities = \
           ri_conf.get("encapsulation_priorities") or ["MPLSoGRE"]

        ri = RoutingInstance(name=ri_name)
        if vn:
            is_nat = True if fip_map else False
            ri.set_comment(DMUtils.vn_ri_comment(vn, is_l2, is_l2_l3, is_nat,
                                                 router_external))
        self.ri_map[ri_name] = ri

        ri.set_virtual_network_id(str(network_id))
        ri.set_vxlan_id(str(vni))
        ri.set_virtual_network_is_internal(is_internal_vn or is_dci_vn)
        ri.set_is_public_network(router_external)
        if is_l2_l3:
            ri.set_virtual_network_mode('l2-l3')
        elif is_l2:
            ri.set_virtual_network_mode('l2')
        else:
            ri.set_virtual_network_mode('l3')

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            ri.set_routing_instance_type("vrf")
            if fip_map is None:
                for interface in interfaces:
                    self.add_ref_to_list(ri.get_interfaces(), interface.name)
                if prefixes:
                    for prefix in prefixes:
                        ri.add_static_routes(self.get_route_for_cidr(prefix))
                        ri.add_prefixes(self.get_subnet_for_cidr(prefix))
        else:
            if encapsulation_priorities[0] == "VXLAN":
                ri.set_routing_instance_type("virtual-switch")
            elif (any(x in encapsulation_priorities for x in ["MPLSoGRE", "MPLSoUDP"])):
                ri.set_routing_instance_type("evpn")

        if is_internal_vn:
            self.internal_vn_ris.append(ri)
        if is_dci_vn:
            self.dci_vn_ris.append(ri)

        if is_internal_vn or router_external or is_dci_vn:
            self.add_bogus_lo0(ri, network_id, vn)

        if self.is_gateway() and is_l2_l3:
            self.add_irb_config(ri_conf)
            self.attach_irb(ri_conf, ri)

        if fip_map is not None:
            self.add_ref_to_list(ri.get_interfaces(), interfaces[0].name)

            public_vrf_ips = {}
            for pip in fip_map.values():
                if pip["vrf_name"] not in public_vrf_ips:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                ri_public = RoutingInstance(name=public_vrf)
                self.ri_map[public_vrf] = ri_public
                self.add_ref_to_list(ri_public.get_interfaces(), interfaces[1].name)
                floating_ips = []
                for fip in fips:
                    ri_public.add_static_routes(
                        Route(prefix=fip,
                              prefix_len=32,
                              next_hop=interfaces[1].name,
                              comment=DMUtils.fip_egress_comment()))
                    floating_ips.append(FloatingIpMap(floating_ip=fip + "/32"))
                ri_public.add_floating_ip_list(FloatingIpList(
                    public_routing_instance=public_vrf,
                    floating_ips=floating_ips))

        # add firewall config for public VRF
        if router_external and is_l2 is False:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            if has_ipv4_prefixes and not self.inet4_forwarding_filter:
                # create single instance inet4 filter
                self.inet4_forwarding_filter = self.add_inet_public_vrf_filter(
                    self.firewall_config, "inet")
            if has_ipv6_prefixes and not self.inet6_forwarding_filter:
                # create single instance inet6 filter
                self.inet6_forwarding_filter = self.add_inet_public_vrf_filter(
                    self.firewall_config, "inet6")
            if has_ipv4_prefixes:
                # add terms to inet4 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
                # insert before the last term
                terms = self.inet4_forwarding_filter.get_terms()
                terms = [term] + (terms or [])
                self.inet4_forwarding_filter.set_terms(terms)
            if has_ipv6_prefixes:
                # add terms to inet6 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet6")
                # insert before the last term
                terms = self.inet6_forwarding_filter.get_terms()
                terms = [term] + (terms or [])
                self.inet6_forwarding_filter.set_terms(terms)

        # add firewall config for DCI Network
        if is_dci:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            self.dci_forwarding_filter[vn.uuid] = self.add_inet_vrf_filter(
                    self.firewall_config, ri_name)
            # add terms to inet4 filter
            term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
            # insert before the last term
            terms = self.dci_forwarding_filter[vn.uuid].get_terms()
            terms = [term] + (terms or [])
            self.dci_forwarding_filter[vn.uuid].set_terms(terms)

        if fip_map is not None:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            f = FirewallFilter(
                name=DMUtils.make_private_vrf_filter_name(ri_name))
            f.set_comment(DMUtils.vn_firewall_comment(vn, "private"))
            self.firewall_config.add_firewall_filters(f)

            term = Term(name=DMUtils.make_vrf_term_name(ri_name))
            from_ = From()
            for fip_user_ip in fip_map.keys():
                from_.add_source_address(self.get_subnet_for_cidr(fip_user_ip))
            term.set_from(from_)
            term.set_then(Then(routing_instance=[ri_name]))
            f.add_terms(term)

            irb_intf, li_map = self.set_default_pi('irb', 'irb')
            intf_name = 'irb.' + str(network_id)
            intf_unit = self.set_default_li(li_map, intf_name, network_id)
            intf_unit.set_comment(DMUtils.vn_irb_fip_inet_comment(vn))
            intf_unit.set_family("inet")
            intf_unit.add_firewall_filters(
                DMUtils.make_private_vrf_filter_name(ri_name))
            self.add_ref_to_list(ri.get_routing_interfaces(), intf_name)

        if gateways is not None:
            for (ip, gateway) in gateways:
                ri.add_gateways(GatewayRoute(
                    ip_address=self.get_subnet_for_cidr(ip),
                    gateway=self.get_subnet_for_cidr(gateway)))

        # add L2 EVPN and BD config
        if (is_l2 and vni is not None and
                self.is_family_configured(self.bgp_params, "e-vpn")):
            vlan = None
            if encapsulation_priorities[0] == "VXLAN":
                vlan = Vlan(name=DMUtils.make_bridge_name(vni), vxlan_id=vni)
                vlan.set_comment(DMUtils.vn_bd_comment(vn, "VXLAN"))
                self.vlan_map[vlan.get_name()] = vlan
                for interface in interfaces:
                    self.add_ref_to_list(vlan.get_interfaces(), interface.name)
                if is_l2_l3:
                    # network_id is unique, hence irb
                    irb_intf = "irb." + str(network_id)
                    self.add_ref_to_list(vlan.get_interfaces(), irb_intf)
            elif (any(x in encapsulation_priorities for x in ["MPLSoGRE", "MPLSoUDP"])):
                self.init_evpn_config(encapsulation_priorities[1])
                self.evpn.set_comment(
                      DMUtils.vn_evpn_comment(vn, encapsulation_priorities[1]))
                for interface in interfaces:
                    self.add_ref_to_list(self.evpn.get_interfaces(), interface.name)

            self.build_l2_evpn_interface_config(interfaces, vn, vlan)

        if (not is_l2 and vni is not None and
                self.is_family_configured(self.bgp_params, "e-vpn")):
            self.init_evpn_config()
            if not is_internal_vn and not is_dci_vn:
                # add vlans
                self.add_ri_vlan_config(ri_name, vni)

        if (not is_l2 and not is_l2_l3 and gateways):
            ifl_num = 1000 + int(network_id)
            lo_intf, li_map = self.set_default_pi('lo0', 'loopback')
            intf_name = 'lo0.' + str(ifl_num)
            intf_unit = self.set_default_li(li_map, intf_name, ifl_num)
            intf_unit.set_comment(DMUtils.l3_lo_intf_comment(vn))
            for (lo_ip, _) in gateways:
                subnet = lo_ip
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    lo_ip = ip + '/' + '128'
                else:
                    lo_ip = ip + '/' + '32'
                self.add_ip_address(intf_unit, lo_ip)
            self.add_ref_to_list(ri.get_loopback_interfaces(), intf_name)

        # fip services config
        if fip_map is not None:
            nat_rules = NatRules(allow_overlapping_nat_pools=True,
                                 name=DMUtils.make_services_set_name(ri_name),
                                 comment=DMUtils.service_set_comment(vn))
            ri.set_nat_rules(nat_rules)
            snat_rule = NatRule(
                name=DMUtils.make_snat_rule_name(ri_name),
                comment=DMUtils.service_set_nat_rule_comment(vn, "SNAT"),
                direction="input", translation_type="basic-nat44")
            snat_rule.set_comment(DMUtils.snat_rule_comment())
            nat_rules.add_rules(snat_rule)
            dnat_rule = NatRule(
                name=DMUtils.make_dnat_rule_name(ri_name),
                comment=DMUtils.service_set_nat_rule_comment(vn, "DNAT"),
                direction="output", translation_type="dnat-44")
            dnat_rule.set_comment(DMUtils.dnat_rule_comment())
            nat_rules.add_rules(dnat_rule)
            nat_rules.set_inside_interface(interfaces[0].name)
            nat_rules.set_outside_interface(interfaces[1].name)

            for pip, fip_vn in fip_map.items():
                fip = fip_vn["floating_ip"]
                # private ip
                snat_rule.add_source_addresses(self.get_subnet_for_cidr(pip))
                # public ip
                snat_rule.add_source_prefixes(self.get_subnet_for_cidr(fip))

                # public ip
                dnat_rule.add_destination_addresses(
                    self.get_subnet_for_cidr(fip))
                # private ip
                dnat_rule.add_destination_prefixes(
                    self.get_subnet_for_cidr(pip))

            self.add_ref_to_list(ri.get_ingress_interfaces(), interfaces[0].name)
            self.add_ref_to_list(ri.get_egress_interfaces(), interfaces[1].name)

        for target in import_targets:
            self.add_to_list(ri.get_import_targets(), target)

        for target in export_targets:
            self.add_to_list(ri.get_export_targets(), target)
    def add_routing_instance(self, ri_conf):
        ri_name = ri_conf.get("ri_name")
        vn = ri_conf.get("vn")
        is_l2 = ri_conf.get("is_l2", False)
        is_l2_l3 = ri_conf.get("is_l2_l3", False)
        import_targets = ri_conf.get("import_targets", set())
        export_targets = ri_conf.get("export_targets", set())
        prefixes = ri_conf.get("prefixes", [])
        gateways = ri_conf.get("gateways", [])
        router_external = ri_conf.get("router_external", False)
        interfaces = ri_conf.get("interfaces", [])
        vni = ri_conf.get("vni", None)
        fip_map = ri_conf.get("fip_map", None)
        network_id = ri_conf.get("network_id", None)
        is_internal_vn = True if '_contrail_lr_internal_vn_' in vn.name else False
        highest_encapsulation_priority = \
            ri_conf.get("highest_encapsulation_priority") or "MPLSoGRE"

        self.routing_instances[ri_name] = ri_conf
        self.ri_config = self.ri_config or []
        self.policy_config = self.policy_config or\
                             Policy(comment=DMUtils.policy_options_comment())
        ri = RoutingInstance(name=ri_name)
        if vn:
            is_nat = True if fip_map else False
            ri.set_comment(
                DMUtils.vn_ri_comment(vn, is_l2, is_l2_l3, is_nat,
                                      router_external))
        self.ri_config.append(ri)

        ri.set_virtual_network_id(str(network_id))
        ri.set_vxlan_id(str(vni))
        ri.set_virtual_network_is_internal(is_internal_vn)
        ri.set_is_public_network(router_external)
        if is_l2_l3:
            ri.set_virtual_network_mode('l2-l3')
        elif is_l2:
            ri.set_virtual_network_mode('l2')
        else:
            ri.set_virtual_network_mode('l3')

        has_ipv6_prefixes = DMUtils.has_ipv6_prefixes(prefixes)
        has_ipv4_prefixes = DMUtils.has_ipv4_prefixes(prefixes)

        if not is_l2:
            ri.set_routing_instance_type("vrf")
            if fip_map is None:
                for interface in interfaces:
                    ri.add_interfaces(LogicalInterface(name=interface.name))
                if prefixes:
                    for prefix in prefixes:
                        ri.add_static_routes(self.get_route_for_cidr(prefix))
                        ri.add_prefixes(self.get_subnet_for_cidr(prefix))
        else:
            if highest_encapsulation_priority == "VXLAN":
                ri.set_routing_instance_type("virtual-switch")
            elif highest_encapsulation_priority in ["MPLSoGRE", "MPLSoUDP"]:
                ri.set_routing_instance_type("evpn")

        if is_internal_vn:
            self.internal_vn_ris.append(ri)
            self.add_bogus_lo0(ri, network_id, vn)

        if self.is_spine() and is_l2_l3:
            self.add_irb_config(ri_conf)
            self.attach_irb(ri_conf, ri)

        if fip_map is not None:
            ri.add_interfaces(LogicalInterface(name=interfaces[0].name))

            public_vrf_ips = {}
            for pip in fip_map.values():
                if pip["vrf_name"] not in public_vrf_ips:
                    public_vrf_ips[pip["vrf_name"]] = set()
                public_vrf_ips[pip["vrf_name"]].add(pip["floating_ip"])

            for public_vrf, fips in public_vrf_ips.items():
                ri.add_interfaces(LogicalInterface(name=interfaces[1].name))
                floating_ips = []
                for fip in fips:
                    ri.add_static_routes(
                        Route(prefix=fip,
                              prefix_len=32,
                              next_hop=interfaces[1].name,
                              comment=DMUtils.fip_egress_comment()))
                    floating_ips.append(FloatingIpMap(floating_ip=fip + "/32"))
                ri.add_floating_ip_list(
                    FloatingIpList(public_routing_instance=public_vrf,
                                   floating_ips=floating_ips))

        # add policies for export route targets
        if self.is_spine():
            p = PolicyRule(name=DMUtils.make_export_name(ri_name))
            p.set_comment(DMUtils.vn_ps_comment(vn, "Export"))
            then = Then()
            p.add_term(Term(name="t1", then=then))
            for route_target in export_targets:
                then.add_community(DMUtils.make_community_name(route_target))
            then.set_accept_or_reject(True)
            self.policy_config.add_policy_rule(p)

        # add policies for import route targets
        p = PolicyRule(name=DMUtils.make_import_name(ri_name))
        p.set_comment(DMUtils.vn_ps_comment(vn, "Import"))

        # add term switch policy
        from_ = From()
        term = Term(name=DMUtils.get_switch_policy_name(), fromxx=from_)
        p.add_term(term)
        from_.add_community(DMUtils.get_switch_policy_name())
        term.set_then(Then(accept_or_reject=True))

        from_ = From()
        term = Term(name="t1", fromxx=from_)
        p.add_term(term)
        for route_target in import_targets:
            from_.add_community(DMUtils.make_community_name(route_target))
            if not is_internal_vn:
                self.add_vni_option(vni or network_id, route_target)
        term.set_then(Then(accept_or_reject=True))
        self.policy_config.add_policy_rule(p)

        # add firewall config for public VRF
        if router_external and is_l2 is False:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            if has_ipv4_prefixes and not self.inet4_forwarding_filter:
                # create single instance inet4 filter
                self.inet4_forwarding_filter = self.add_inet_public_vrf_filter(
                    self.firewall_config, "inet")
            if has_ipv6_prefixes and not self.inet6_forwarding_filter:
                # create single instance inet6 filter
                self.inet6_forwarding_filter = self.add_inet_public_vrf_filter(
                    self.firewall_config, "inet6")
            if has_ipv4_prefixes:
                # add terms to inet4 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet4")
                # insert before the last term
                terms = self.inet4_forwarding_filter.get_terms()
                terms = [term] + (terms or [])
                self.inet4_forwarding_filter.set_terms(terms)
            if has_ipv6_prefixes:
                # add terms to inet6 filter
                term = self.add_inet_filter_term(ri_name, prefixes, "inet6")
                # insert before the last term
                terms = self.inet6_forwarding_filter.get_terms()
                terms = [term] + (terms or [])
                self.inet6_forwarding_filter.set_terms(terms)

        if fip_map is not None:
            self.firewall_config = self.firewall_config or Firewall(
                comment=DMUtils.firewall_comment())
            f = FirewallFilter(
                name=DMUtils.make_private_vrf_filter_name(ri_name))
            f.set_comment(DMUtils.vn_firewall_comment(vn, "private"))
            self.firewall_config.add_firewall_filters(f)

            term = Term(name=DMUtils.make_vrf_term_name(ri_name))
            from_ = From()
            for fip_user_ip in fip_map.keys():
                from_.add_source_address(fip_user_ip)
            term.set_from(from_)
            term.set_then(Then(routing_instance=[ri_name]))
            f.add_terms(term)

            irb_intf = PhysicalInterface(name='irb', interface_type='irb')
            self.interfaces_config.append(irb_intf)
            intf_unit = LogicalInterface(
                name="irb." + str(network_id),
                unit=network_id,
                comment=DMUtils.vn_irb_fip_inet_comment(vn))
            irb_intf.add_logical_interfaces(intf_unit)
            intf_unit.set_family("inet")
            intf_unit.add_firewall_filters(
                DMUtils.make_private_vrf_filter_name(ri_name))
            ri.add_routing_interfaces(intf_unit)

        if gateways is not None:
            for (ip, gateway) in gateways:
                ri.add_gateways(
                    GatewayRoute(ip_address=self.get_subnet_for_cidr(ip),
                                 gateway=self.get_subnet_for_cidr(gateway)))

        # add L2 EVPN and BD config
        if (is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            vlan = None
            if self.is_spine():
                if highest_encapsulation_priority == "VXLAN":
                    self.vlans_config = self.vlans_config or []
                    vlan = Vlan(name=DMUtils.make_bridge_name(vni),
                                vxlan_id=vni,
                                vlan_or_bridge_domain=False)
                    vlan.set_comment(DMUtils.vn_bd_comment(vn, "VXLAN"))
                    self.vlans_config.append(vlan)
                    for interface in interfaces:
                        vlan.add_interfaces(
                            LogicalInterface(name=interface.name))
                    if is_l2_l3:
                        # network_id is unique, hence irb
                        irb_intf = "irb." + str(network_id)
                        vlan.add_interfaces(LogicalInterface(name=irb_intf))
                elif highest_encapsulation_priority in [
                        "MPLSoGRE", "MPLSoUDP"
                ]:
                    self.evpn = Evpn(
                        encapsulation=highest_encapsulation_priority)
                    self.evpn.set_comment(
                        DMUtils.vn_evpn_comment(
                            vn, highest_encapsulation_priority))
                    for interface in interfaces:
                        self.evpn.add_interfaces(
                            LogicalInterface(name=interface.name))
            else:
                # add vlan config
                vlan = self.add_vlan_config(ri_name, vni, is_l2_l3,
                                            "irb." + str(network_id))

            self.interfaces_config = self.interfaces_config or []
            self.build_l2_evpn_interface_config(self.interfaces_config,
                                                interfaces, vn, vlan)

        if (not is_l2 and vni is not None
                and self.is_family_configured(self.bgp_params, "e-vpn")):
            self.evpn = self.build_evpn_config()
            # add vlans
            self.add_ri_vlan_config(ri, vni)

        if (not is_l2 and not is_l2_l3 and gateways):
            self.interfaces_config = self.interfaces_config or []
            ifl_num = 1000 + int(network_id)
            lo_intf = PhysicalInterface(name="lo0", interface_type='loopback')
            self.interfaces_config.append(lo_intf)
            intf_unit = LogicalInterface(
                name="lo0." + str(ifl_num),
                unit=ifl_num,
                comment=DMUtils.l3_lo_intf_comment(vn))
            lo_intf.add_logical_interfaces(intf_unit)
            for (lo_ip, _) in gateways:
                subnet = lo_ip
                (ip, _) = lo_ip.split('/')
                if ':' in lo_ip:
                    lo_ip = ip + '/' + '128'
                else:
                    lo_ip = ip + '/' + '32'
                intf_unit.add_ip_list(
                    IpType(address=lo_ip,
                           comment=DMUtils.lo0_ip_comment(subnet)))
            ri.add_loopback_interfaces(
                LogicalInterface(name="lo0." + str(ifl_num),
                                 comment=DMUtils.lo0_ri_intf_comment(vn)))

        # fip services config
        if fip_map is not None:
            nat_rules = NatRules(allow_overlapping_nat_pools=True,
                                 name=DMUtils.make_services_set_name(ri_name),
                                 comment=DMUtils.service_set_comment(vn))
            ri.set_nat_rules(nat_rules)
            snat_rule = NatRule(name=DMUtils.make_snat_rule_name(ri_name),
                                comment=DMUtils.service_set_nat_rule_comment(
                                    vn, "SNAT"),
                                direction="input",
                                translation_type="basic-nat44")
            snat_rule.set_comment(DMUtils.snat_rule_comment())
            nat_rules.add_rules(snat_rule)
            dnat_rule = NatRule(name=DMUtils.make_dnat_rule_name(ri_name),
                                comment=DMUtils.service_set_nat_rule_comment(
                                    vn, "DNAT"),
                                direction="output",
                                translation_type="dnat-44")
            dnat_rule.set_comment(DMUtils.dnat_rule_comment())
            nat_rules.add_rules(dnat_rule)
            nat_rules.set_inside_interface(interfaces[0].name)
            nat_rules.set_outside_interface(interfaces[1].name)

            for pip, fip_vn in fip_map.items():
                fip = fip_vn["floating_ip"]
                # private ip
                snat_rule.add_source_addresses(self.get_subnet_for_cidr(pip))
                # public ip
                snat_rule.add_source_prefixes(self.get_subnet_for_cidr(fip))

                # public ip
                dnat_rule.add_destination_addresses(
                    self.get_subnet_for_cidr(fip))
                # private ip
                dnat_rule.add_destination_prefixes(
                    self.get_subnet_for_cidr(pip))

            intf_unit = LogicalInterface(
                name=interfaces[0].name,
                unit=interfaces[0].unit,
                comment=DMUtils.service_intf_comment("Ingress"))
            intf_unit.set_family("inet")
            ri.add_service_interfaces(intf_unit)

            intf_unit = LogicalInterface(
                name=interfaces[1].name,
                unit=interfaces[1].unit,
                comment=DMUtils.service_intf_comment("Egress"))
            intf_unit.set_family("inet")
            ri.add_service_interfaces(intf_unit)

        for target in import_targets:
            ri.add_import_targets(target)

        for target in export_targets:
            ri.add_export_targets(target)