Beispiel #1
0
    def update_bier_encap_entry(self, switch=None):
        """
        Add bier encap entry for given prefix
        :param switch: switch where rules should be installed
        :return:
        """

        valid_entries = []

        for mc_addr in GroupManager.get_mc_addresses():
            for domain in GroupManager.get_domains_for_mc_addr(mc_addr):
                domain = int(domain)
                bitstring = BierComputation.compute_bier_header(
                    mc_addr=mc_addr, domain=domain)

                entry = TableEntry(switch=switch,
                                   match_fields={
                                       "hdr.ipv4.dstAddr": mc_addr,
                                   },
                                   action_name="ingress.ipv4_c.add_bier",
                                   action_params={"bs": bitstring})

                if TableEntryManager.handle_table_entry(
                        manager=self.table_manager,
                        table_name="ingress.ipv4_c.encap_ipv4",
                        table_entry=entry):
                    Log.async_debug("Installed encap ipv4 rule for", switch,
                                    mc_addr, bitstring)

                valid_entries.append(entry.match_fields)

        self.table_manager.remove_invalid_entries(
            switch=switch,
            table_name="ingress.ipv4_c.encap_ipv4",
            valid_entries=valid_entries)
Beispiel #2
0
    def update_ipv4_entries(self, switch=None):
        """
        Update ipv4 entries based on shortest path on switch
        :param switch: switch where ipv4 entries will be installed
        :return:
        """

        paths = TopologyManager.get_paths(domain_id=0)
        valid_entries = []

        cur_dev = TopologyManager.get_device(switch)

        for dst in [d for d in paths.get(switch, {})
                    if d != switch]:  # don't check path from i->i
            # get the next_hop towards the destination along the shortest path
            dst_dev = TopologyManager.get_device(dst)
            next_hop = TopologyManager.get_next_hop(start_node=switch,
                                                    destination_node=dst,
                                                    domain_id=0)

            port = cur_dev.get_device_to_port(next_hop.get_name())

            entry = TableEntry(
                switch=switch,
                match_fields={
                    "hdr.ipv4.dstAddr": (str(dst_dev.get_ip()), 32),
                    "meta.ports.status":
                    (BierComputation.id_to_bitstring(id=int(port)),
                     BierComputation.id_to_bitstring(id=int(port)))
                },
                action_name="ingress.ipv4_c.forward",
                action_params={"port": int(port)},
                priority=1)

            if TableEntryManager.handle_table_entry(
                    manager=self.table_manager,
                    table_name="ingress.ipv4_c.ipv4",
                    table_entry=entry):
                Log.async_debug("Installed IPv4 forwarding rule for", switch,
                                "->", dst)

            valid_entries.append(entry.match_fields)

        # Add decap entry
        entry = TableEntry(
            switch=cur_dev.get_name(),
            match_fields={"hdr.ipv4.dstAddr": (str(cur_dev.get_ip()), 32)},
            action_name="ingress.ipv4_c.decap",
            priority=1)

        if TableEntryManager.handle_table_entry(
                manager=self.table_manager,
                table_name="ingress.ipv4_c.ipv4",
                table_entry=entry):
            Log.async_debug("Installed IPv4 decap rule for", switch)

        valid_entries.append(entry.match_fields)

        return valid_entries
Beispiel #3
0
    def PortMessage(self, request, context):
        """
        This method receives a port message
        """
        Log.async_info("Got port message")
        Log.async_debug(request)

        # this event is not catched yet
        # for demonstration purpose, the topology doesn't get updated
        # on a link failure
        Event.trigger("port_message", message=request)

        return proto.connection_pb2.Status(code=1, message="Accepted")
Beispiel #4
0
    def add_ipv4_decap_rule(self, *args, **kwargs):
        """
        Adds an ipv4 decap rule for the switch
        This event is triggered when a switch is arbitrated
        :return:
        """
        device = TopologyManager.get_device(kwargs.get('name'))
        entry = TableEntry(switch=device.get_name(),
                           match_fields={"hdr.ipv4.dstAddr": device.get_ip()},
                           action_name="ingress.tunnel_c.ipv4_decap")

        if TableEntryManager.handle_table_entry(
                manager=self.table_manager,
                table_name="ingress.tunnel_c.decap_ipv4",
                table_entry=entry):
            Log.async_debug("Ipv4 decap rule installed for",
                            kwargs.get('name'))
Beispiel #5
0
    def connect(self):
        """
        All switches grpc addresses are in ascending order.
        Connect until a connection can't be established
        :return:
        """

        for switch in Configuration.get("switches"):
            try:
                self.__connections[switch["name"]] = SwitchConnection(
                    grpc_address='127.0.0.1:{0}'.format(
                        switch["local_controller_port"]))
                Log.async_debug("Connected to controller on port",
                                switch["local_controller_port"])
                Event.trigger('switch_connected', name=switch["name"])
            except grpc.RpcError as e:
                raise SwitchConnectionFailed(switch["name"],
                                             switch["local_controller_port"])

        Log.async_info("Connected to", len(self.__connections), "controller")
        Configuration.set('connected', True)
Beispiel #6
0
    def update_bier_decap_rule(self, switch=None):
        """
        Updates the bier decap rules based on the current topology
        :param switch: switch where decap rules should be installed
        :return:
        """
        valid_entries = []

        # bier decap rules
        for domain in TopologyManager.get_domain_for_device(switch):
            domain = int(domain)
            bfr_id = BierComputation.id_to_bitstring(
                TopologyManager.get_device(switch).get_bfr_id(domain))

            entry = TableEntry(switch=switch,
                               match_fields={
                                   "hdr.bier[0].BitString": (bfr_id, bfr_id),
                                   "hdr.bier[0].Domain": domain
                               },
                               action_name="ingress.tunnel_c.bier_decap",
                               action_params={"decapBit": bfr_id},
                               priority=1)

            if TableEntryManager.handle_table_entry(
                    manager=self.table_manager,
                    table_name="ingress.tunnel_c.decap_bier",
                    table_entry=entry):
                Log.async_debug("BIER decap rule updated on", switch,
                                "for domain", domain)

            valid_entries.append(entry.match_fields)

        self.table_manager.remove_invalid_entries(
            switch=switch,
            table_name="ingress.tunnel_c.decap_bier",
            valid_entries=valid_entries)
Beispiel #7
0
    def update_bier_forwarding_entries(self, switch=None):
        """
        Adds bier forwarding entry for given switch in specifc domain
        :param switch:
        :param domain: domain identifier
        :return:
        """

        table_name = "ingress.bier_c.bift"

        valid_entries = []

        for domain in TopologyManager.get_domain_for_device(switch):
            domain = int(domain)
            bift = BierComputation.build_bift(switch=switch, domain=domain)

            for entry in bift:
                bit_string = BierComputation.id_to_bitstring(id=entry)

                out_port = TopologyManager.get_device(
                    switch).get_device_to_port(bift.get(entry)[1])

                # generate default bier entry
                e = TableEntry(
                    switch=switch,
                    match_fields={
                        "meta.bier_md.remainingBits": (bit_string, bit_string),
                        "meta.ports.status":
                        (BierComputation.id_to_bitstring(id=out_port),
                         BierComputation.id_to_bitstring(id=out_port))
                    },
                    action_name="ingress.bier_c.forward",
                    action_params={
                        "fbm": bift.get(entry)[0],
                        "port": out_port
                    },
                    priority=1)

                if TableEntryManager.handle_table_entry(
                        manager=self.table_manager,
                        table_name=table_name,
                        table_entry=e):
                    Log.async_debug("Installed BIER rule for", switch,
                                    "to bfr-id", entry)

                valid_entries.append(e.match_fields)

                # generate bier-frr link protection entry for this switch and bfr
                if Configuration.get('protection') == 'Link':
                    frr_entry = self.update_frr_link_protection(
                        switch=switch,
                        domain=domain,
                        port=out_port,
                        to_id=entry,
                        fbm=bift.get(entry)[0],
                        next_hop=bift.get(entry)[1])

                    if TableEntryManager.handle_table_entry(
                            manager=self.table_manager,
                            table_name=table_name,
                            table_entry=frr_entry):
                        Log.async_debug(
                            "Installed BIER-FRR link protection rule for",
                            switch)

                    valid_entries.append(frr_entry.match_fields)

                # generate bier-frr node protection entry for this switch and bfr
                if Configuration.get('protection') == 'Node':
                    frr_entry = self.update_frr_node_protection(
                        switch=switch,
                        domain=domain,
                        port=out_port,
                        to_id=entry,
                        fbm=bift.get(entry)[0],
                        next_hop=bift.get(entry)[1])

                    if frr_entry:
                        if TableEntryManager.handle_table_entry(
                                manager=self.table_manager,
                                table_name=table_name,
                                table_entry=frr_entry):
                            Log.async_debug(
                                "Installed BIER-FRR node protection rule for",
                                switch, "to", entry)

                        valid_entries.append(frr_entry.match_fields)

        bfr_id = BierComputation.id_to_bitstring(
            TopologyManager.get_device(switch).get_bfr_id(0))
        # Add decap entry
        entry = TableEntry(
            switch=switch,
            match_fields={"meta.bier_md.remainingBits": (bfr_id, bfr_id)},
            action_name="ingress.bier_c.decap",
            action_params={"decapBit": bfr_id},
            priority=1)

        if TableEntryManager.handle_table_entry(manager=self.table_manager,
                                                table_name=table_name,
                                                table_entry=entry):
            Log.async_debug("Installed BIER decap rule for", switch)

        valid_entries.append(entry.match_fields)

        self.table_manager.remove_invalid_entries(switch=switch,
                                                  table_name=table_name,
                                                  valid_entries=valid_entries)