Exemplo n.º 1
0
 def cli_summary_attributes(self):
     if self.dest_type == DEST_TYPE_NODE:
         destination_str = utils.system_id_str(self.system_id)
         if self.name:
             destination_str += " (" + self.name + ")"
     elif self.dest_type == DEST_TYPE_PREFIX:
         destination_str = packet_common.ip_prefix_str(self.prefix)
     elif self.dest_type == DEST_TYPE_POS_DISAGG_PREFIX or \
         self.dest_type == DEST_TYPE_NEG_DISAGG_PREFIX:
         destination_str = packet_common.ip_prefix_str(self.prefix) + " (Disagg)"
     else:
         assert False
     if self.tags:
         tags_str = list(self.tags)
     else:
         tags_str = ""
     if self.positively_disaggregate:
         disaggregate_str = 'Positive'
     elif self.negatively_disaggregate:
         disaggregate_str = 'Negative'
     else:
         disaggregate_str = ''
     return [
         destination_str,
         self.cost,
         sorted(self.predecessors),
         tags_str,
         disaggregate_str,
         [str(next_hop) for next_hop in sorted(self.ipv4_next_hops)],
         [str(next_hop) for next_hop in sorted(self.ipv6_next_hops)]
     ]
Exemplo n.º 2
0
    def put_route(self, rte):
        """
        Add a RibRoute object to the Destination object associated to the prefix.
        :param rte: (RibRoute) the object to add to the Destination associated to the prefix
        :return:
        """

        packet_common.assert_prefix_address_family(rte.prefix, self.address_family)
        rte.stale = False
        self.debug("Put %s", rte)
        # If there is no Destination object for the prefix, create a new Destination object
        # for the given prefix and insert it in the Trie
        prefix = packet_common.ip_prefix_str(rte.prefix)
        if not self.destinations.has_key(prefix):
            prefix_destination = _Destination(self, rte.prefix)
            self.destinations.insert(prefix, prefix_destination)
        else:
            prefix_destination = self.destinations.get(prefix)
        # Insert desired route in destination object
        best_changed = prefix_destination.put_route(rte)

        # Get children prefixes before performing actions on the prefix
        # (it can be deleted from the Trie)
        children_prefixes = self.destinations.children(
            packet_common.ip_prefix_str(prefix_destination.prefix))

        # If best route changed in Destination object
        if best_changed:
            # Update prefix in the fib
            self.fib.put_route(prefix_destination.best_route)
            # Try to delete superfluous children
            if not self._delete_superfluous_children(prefix_destination, children_prefixes):
                # If children have not been deleted, update them
                self._update_prefix_children(children_prefixes)
Exemplo n.º 3
0
 def all_prefix_routes(self, prefix):
     assert_prefix_address_family(prefix, self.address_family)
     prefix_str = ip_prefix_str(prefix)
     if self.destinations.has_key(prefix_str):
         destination = self.destinations[prefix_str]
         for rib_route in destination.rib_routes:
             yield rib_route
Exemplo n.º 4
0
 def update_fib(self, prefix, child_prefix_strs):
     # The child_prefix_strs have to be passed as a parameter, because they need to be collected
     # before the parent is potentially deleted by the calling function.
     # Locate the best RIB route for the prefix (None if there is no RIB route for the prefix).
     prefix_str = ip_prefix_str(prefix)
     if self.destinations.has_key(prefix_str):
         destination = self.destinations.get(prefix_str)
         rib_route = destination.best_route()
     else:
         rib_route = None
     # Determine the next-hops for the corresponding FIB route. If the next-hops is an empty
     # list [] it means it is a discard route. If the next-hops is None it means there should not
     # be a FIB route.
     if rib_route:
         fib_next_hops = rib_route.compute_fib_next_hops()
     else:
         fib_next_hops = None
     # Update the FIB route accordingly.
     if fib_next_hops is not None:
         fib_route = FibRoute(prefix, fib_next_hops)
         self.fib.put_route(fib_route)
     else:
         self.fib.del_route(prefix)
     # Recursively update the FIB for all child routes: their negative next-hops, if any, may
     # have to be recomputed if a parent route changed.
     for child_prefix_str in child_prefix_strs:
         child_destination = self.destinations[child_prefix_str]
         child_rib_route = child_destination.best_route()
         child_prefix = child_rib_route.prefix
         grand_child_prefix_strs = self.destinations.children(
             child_prefix_str)
         self.update_fib(child_prefix, grand_child_prefix_strs)
Exemplo n.º 5
0
 def cli_summary_attributes(self):
     return [
         packet_common.ip_prefix_str(self.prefix),
         constants.owner_str(self.owner),
         list(map(lambda x: str(x[0]) if x[1] else "~%s" % str(x[0]),
                  self._get_nexthops_sorted()))
     ]
Exemplo n.º 6
0
 def __str__(self):
     all_next_hops = self._get_nexthops_sorted()
     return "%s: %s -> %s" % (constants.owner_str(self.owner),
                              packet_common.ip_prefix_str(self.prefix),
                              ", ".join(
                                  map(lambda x: str(x[0]) if x[1] else "~%s" % str(x[0]),
                                      all_next_hops)))
Exemplo n.º 7
0
 def get_route(self, rte_prefix, owner):
     packet_common.assert_prefix_address_family(rte_prefix, self.address_family)
     prefix = packet_common.ip_prefix_str(rte_prefix)
     if self.destinations.has_key(prefix):
         return self.destinations.get(prefix).get_route(owner)
     else:
         return None
Exemplo n.º 8
0
 def all_prefix_routes(self, rte_prefix):
     packet_common.assert_prefix_address_family(rte_prefix, self.address_family)
     prefix = packet_common.ip_prefix_str(rte_prefix)
     if self.destinations.has_key(prefix):
         destination = self.destinations[prefix]
         for rte in destination.routes:
             yield rte
Exemplo n.º 9
0
 def cli_summary_attributes(self):
     if self.is_discard_route():
         return [
             packet_common.ip_prefix_str(self.prefix), "Discard", "", "", ""
         ]
     nhops = sorted(self.next_hops)
     types = ["Positive" for _ in nhops]
     interfaces = [
         nh.interface if nh.interface is not None else "" for nh in nhops
     ]
     addresses = [
         nh.address if nh.address is not None else "" for nh in nhops
     ]
     weights = [nh.weight if nh.weight is not None else "" for nh in nhops]
     return [
         packet_common.ip_prefix_str(self.prefix), types, interfaces,
         addresses, weights
     ]
Exemplo n.º 10
0
    def parent_prefix_dest(self):
        """
        :return: the Destination object associated to the parent prefix of the current one
        """
        parent_prefix = self.rib.destinations.parent(packet_common.ip_prefix_str(self.prefix))
        if parent_prefix is None:
            return None

        return self.rib.destinations.get(parent_prefix)
Exemplo n.º 11
0
 def put_route(self, rib_route):
     assert_prefix_address_family(rib_route.prefix, self.address_family)
     rib_route.stale = False
     self.debug("Put %s", rib_route)
     prefix = rib_route.prefix
     prefix_str = ip_prefix_str(prefix)
     if not self.destinations.has_key(prefix_str):
         destination = Destination(self, prefix)
         self.destinations.insert(prefix_str, destination)
     else:
         destination = self.destinations.get(prefix_str)
     best_changed = destination.put_route(rib_route)
     if best_changed:
         child_prefix_strs = self.destinations.children(prefix_str)
         self.update_fib(prefix, child_prefix_strs)
Exemplo n.º 12
0
 def cli_summary_attributes(self):
     if self.dest_type == DEST_TYPE_NODE:
         destination_str = utils.system_id_str(self.system_id)
         if self.name:
             destination_str += " (" + self.name + ")"
     else:
         destination_str = packet_common.ip_prefix_str(self.prefix)
     if self.tags:
         tags_str = list(self.tags)
     else:
         tags_str = ""
     return [
         destination_str, self.cost,
         sorted(self.predecessors), tags_str,
         [str(next_hop) for next_hop in sorted(self.next_hops)]
     ]
Exemplo n.º 13
0
 def cli_route_prefix_table(self, table_nr, prefix):
     prefix_str = packet_common.ip_prefix_str(prefix)
     route = None
     for rte in self.ipr.get_routes():
         route_table_nr = rte.get_attr('RTA_TABLE')
         dst_prefix_str = self.kernel_route_dst_prefix_str(rte)
         if (table_nr == route_table_nr) and (dst_prefix_str == prefix_str):
             route = rte
             break
     if route is None:
         return None
     links = self.ipr.get_links()
     tab = table.Table(separators=False)
     next_hops = self.kernel_route_nhops(route, links)
     next_hops_cell = []
     for nhop in next_hops:
         next_hop_str = str(nhop[0]) + " " + str(nhop[1]) + " " + str(
             nhop[2])
         next_hops_cell.append(next_hop_str)
     tab.add_row(["Table", self.table_nr_to_name(table_nr)])
     tab.add_row(
         ["Address Family",
          self.af_str(self.af_str(route["family"]))])
     tab.add_row(["Destination", prefix_str])
     tab.add_row(["Type", self.route_type_str(route["type"])])
     tab.add_row(["Protocol", self.proto_str(route["proto"])])
     tab.add_row(["Scope", self.scope_str(route["scope"])])
     tab.add_row(["Next-hops", next_hops_cell])
     tab.add_row(["Priority", self.to_str(route.get_attr('RTA_PRIORITY'))])
     tab.add_row(["Preference", self.to_str(route.get_attr('RTA_PREF'))])
     tab.add_row([
         "Preferred Source Address",
         self.to_str(route.get_attr('RTA_PREFSRC'))
     ])
     tab.add_row(["Source", self.kernel_route_src_prefix_str(route)])
     tab.add_row(["Flow", self.to_str(route.get_attr('RTA_FLOW'))])
     tab.add_row([
         "Encapsulation Type",
         self.to_str(route.get_attr('RTA_ENCAP_TYPE'))
     ])
     tab.add_row(
         ["Encapsulation",
          self.to_str(route.get_attr('RTA_ENCAP'))])
     tab.add_row(["Metrics", self.to_str(route.get_attr('RTA_METRICS'))])
     tab.add_row(["Type of Service", route["tos"]])
     tab.add_row(["Flags", route["flags"]])
     return tab
Exemplo n.º 14
0
 def del_route(self, prefix):
     if not self.platform_supported:
         return False
     if self._table_nr == -1:
         return False
     dst = packet_common.ip_prefix_str(prefix)
     try:
         self.ipr.route('del', table=self._table_nr, dst=dst, proto=RTPROT_RIFT)
     except pyroute2.netlink.exceptions.NetlinkError as err:
         if err.code != errno.ESRCH:  # It is not an error to delete a non-existing route
             self.error("Netlink error \"%s\" deleting route to %s", err, dst)
         return False
     except OSError as err:
         self.error("OS error \"%s\" deleting route to %s", err, dst)
         return False
     else:
         self.debug("Delete route to %s", prefix)
         return True
Exemplo n.º 15
0
 def del_route(self, rte_prefix, owner):
     """
     Delete given prefix and owner RibRoute object.
     If no more RibRoute objects are available, also delete Destination from trie and
     from the FIB.
     :param rte_prefix: (string) prefix to delete
     :param owner: (int) owner of the prefix
     :return: (boolean) if the route has been deleted or not
     """
     packet_common.assert_prefix_address_family(rte_prefix, self.address_family)
     destination_deleted = False
     best_changed = False
     children_prefixes = None
     prefix = packet_common.ip_prefix_str(rte_prefix)
     # Check if the prefix is stored in the trie
     if self.destinations.has_key(prefix):
         # Get children prefixes before performing actions on the prefix
         # (it can be deleted from the Trie)
         children_prefixes = self.destinations.children(prefix)
         destination = self.destinations.get(prefix)
         # Delete route from the Destination object
         deleted, best_changed = destination.del_route(owner)
         # Route was not present in Destination object, nothing to do
         if deleted:
             self.debug("Delete %s", prefix)
         else:
             self.debug("Attempted delete %s (not present)", prefix)
             return deleted
         if not destination.routes:
             # No more routes available for current prefix, delete it from trie and FIB
             self.destinations.delete(prefix)
             self.fib.del_route(rte_prefix)
             destination_deleted = True
         elif best_changed:
             # Best route changed, push it in the FIB
             self.fib.put_route(destination.best_route)
     else:
         deleted = False
     if deleted and (best_changed or destination_deleted):
         # If route has been deleted and an event occurred
         # (best changed or destination deleted), update children
         self._update_prefix_children(children_prefixes)
     return deleted
Exemplo n.º 16
0
 def put_route(self, rte):
     if not self.platform_supported or self._simulated_interfaces:
         return False
     if self._table_nr == -1:
         return False
     dst = packet_common.ip_prefix_str(rte.prefix)
     # No next hops means that the route is unreachable.
     if not rte.next_hops:
         kernel_args = {"type": "unreachable"}
     elif len(rte.next_hops) == 1:
         nhop = rte.next_hops[0]
         kernel_args = self.nhop_to_kernel_args(nhop, dst)
         if kernel_args == {}:
             self.del_route(rte.prefix)
             return False
     else:
         kernel_args = {"multipath": []}
         for nhop in rte.next_hops:
             nhop_args = self.nhop_to_kernel_args(nhop, dst)
             if nhop_args:
                 kernel_args["multipath"].append(nhop_args)
         if kernel_args["multipath"] == []:
             self.del_route(rte.prefix)
             return False
     try:
         self.ipr.route('replace',
                        table=self._table_nr,
                        dst=dst,
                        proto=RTPROT_RIFT,
                        priority=RTPRIORITY_RIFT,
                        **kernel_args)
     except pyroute2.netlink.exceptions.NetlinkError as err:
         self.error("Netlink error %s replacing route to %s: %s", err, dst,
                    kernel_args)
         return False
     except OSError as err:
         self.error("OS error \"%s\" replacing route to %s: %s", err, dst,
                    kernel_args)
         return False
     else:
         self.debug("Replace route to \"%s\": %s", dst, kernel_args)
         return True
Exemplo n.º 17
0
 def del_route(self, prefix, owner):
     assert_prefix_address_family(prefix, self.address_family)
     prefix_str = ip_prefix_str(prefix)
     if self.destinations.has_key(prefix_str):
         destination = self.destinations.get(prefix_str)
         child_prefix_strs = self.destinations.children(prefix_str)
         deleted, best_changed = destination.del_route(owner)
         # If that was the last route for the destination, delete the destination itself
         if not destination.rib_routes:
             del self.destinations[prefix_str]
     else:
         deleted = False
         best_changed = False
     if deleted:
         self.debug("Delete %s", prefix)
     else:
         self.debug("Attempted delete %s (not present)", prefix)
     if best_changed:
         self.update_fib(prefix, child_prefix_strs)
     return deleted
Exemplo n.º 18
0
 def __str__(self):
     sorted_next_hops = sorted([str(next_hop) for next_hop in self.next_hops])
     return "%s -> %s" % (packet_common.ip_prefix_str(self.prefix), ", ".join(sorted_next_hops))
Exemplo n.º 19
0
 def __repr__(self):
     next_hops_str = ", ".join(
         [str(next_hop) for next_hop in sorted(self.next_hops)])
     return "%s -> %s" % (packet_common.ip_prefix_str(
         self.prefix), next_hops_str)
Exemplo n.º 20
0
 def get_route(self, prefix, owner):
     assert_prefix_address_family(prefix, self.address_family)
     prefix = ip_prefix_str(prefix)
     if self.destinations.has_key(prefix):
         return self.destinations.get(prefix).get_route(owner)
     return None
Exemplo n.º 21
0
 def cli_summary_attributes(self):
     return [
         packet_common.ip_prefix_str(self.prefix),
         [str(next_hop) for next_hop in self.next_hops]
     ]
Exemplo n.º 22
0
 def __str__(self):
     return ("route to " + packet_common.ip_prefix_str(self.prefix) +
             " via " + ", ".join(str(nhop) for nhop in self.next_hops) +
             " owned by " + constants.owner_str(self.owner))
Exemplo n.º 23
0
 def parent_destination(self):
     parent_prefix = self.rib.destinations.parent(
         packet_common.ip_prefix_str(self.prefix))
     if parent_prefix is None:
         return None
     return self.rib.destinations.get(parent_prefix)
Exemplo n.º 24
0
 def cli_summary_attributes(self):
     return [
         packet_common.ip_prefix_str(self.prefix),
         constants.owner_str(self.owner),
         [str(next_hop) for next_hop in sorted(self.next_hops)]
     ]
Exemplo n.º 25
0
 def __repr__(self):
     next_hops_str = ", ".join(
         [str(next_hop) for next_hop in sorted(self.next_hops)])
     return "%s: %s -> %s" % (owner_str(
         self.owner), ip_prefix_str(self.prefix), next_hops_str)