def cli_detailed_attributes(self): # TODO: Report capabilities (is it possible to report the unknown ones too?" # TODO: Report neighbor direction in show command if self.neighbor_system_id: your_system_id_str = utils.system_id_str(self.neighbor_system_id) else: your_system_id_str = "" if self.neighbor_link_id: your_link_id_str = "{}".format(self.neighbor_link_id) else: your_link_id_str = "" attributes = [ ["Name", self.name], ["System ID", utils.system_id_str(self.system_id)], ["IPv4 Address", self.address], ["LIE UDP Source Port", self.port], ["Link ID", self.local_id], ["Level", self.level], ["Flood UDP Port", self.flood_port], ["MTU", self.link_mtu_size], ["POD", self.pod], ["Hold Time", self.holdtime], ["Not a ZTP Offer", self.not_a_ztp_offer], ["You Are Not a ZTP Flood Repeater", self.not_a_ztp_offer], ["Your System ID", your_system_id_str], ["Your Local ID", your_link_id_str], ] return attributes
def cli_details_table(self): # TODO: Report capabilities (is it possible to report the unknown ones too?" if self.neighbor_system_id: your_system_id_str = system_id_str(self.neighbor_system_id) else: your_system_id_str = "" if self.neighbor_link_id: your_link_id_str = "{}".format(self.neighbor_link_id) else: your_link_id_str = "" tab = Table(separators=False) tab.add_rows([ ["Name", self.name], ["System ID", system_id_str(self.system_id)], ["IPv4 Address", self.ipv4_address], ["IPv6 Address", self.ipv6_address], ["LIE UDP Source Port", self.port], ["Link ID", self.local_id], ["Level", self.level], ["Flood UDP Port", self.flood_port], ["MTU", self.link_mtu_size], ["POD", self.pod], ["Hold Time", self.holdtime], ["Not a ZTP Offer", self.not_a_ztp_offer], ["You are Flood Repeater", self.you_are_flood_repeater], ["Your System ID", your_system_id_str], ["Your Local ID", your_link_id_str], ]) return tab
def action_process_lie(self, event_data): (protocol_packet, (from_address, from_port)) = event_data # TODO: This is a simplistic way of implementing the hold timer. Use a real timer instead. self._time_ticks_since_lie_received = 0 # Sections B.1.4.1 and B.1.4.2 new_neighbor = neighbor.Neighbor(protocol_packet, from_address, from_port) (accept, rule, offer_to_ztp, warning) = self.is_received_lie_acceptable(protocol_packet) if not accept: self._lie_accept_or_reject = "Rejected" self._lie_accept_or_reject_rule = rule if warning: self.rx_warning("Received LIE packet rejected: %s", rule) else: self.rx_info("Received LIE packet rejected: %s", rule) self.action_cleanup() if offer_to_ztp: self.send_offer_to_ztp_fsm(new_neighbor) self.fsm.push_event(self.Event.UNACCEPTABLE_HEADER) return self._lie_accept_or_reject = "Accepted" self._lie_accept_or_reject_rule = rule # Section B.1.4.3 # Note: We send an offer to the ZTP state machine directly from here instead of pushing an # UPDATE_ZTP_OFFER event (see deviation DEV-2 in doc/deviations) self.send_offer_to_ztp_fsm(new_neighbor) if not self.neighbor: self.info("New neighbor detected with system-id %s", utils.system_id_str(protocol_packet.header.sender)) self.neighbor = new_neighbor self.fsm.push_event(self.Event.NEW_NEIGHBOR) self.check_three_way() return # Section B.1.4.3.1 if new_neighbor.system_id != self.neighbor.system_id: self.info("Neighbor system-id changed from %s to %s", utils.system_id_str(self.neighbor.system_id), utils.system_id_str(new_neighbor.system_id)) self.fsm.push_event(self.Event.MULTIPLE_NEIGHBORS) return # Section B.1.4.3.2 if new_neighbor.level != self.neighbor.level: self.info("Neighbor level changed from %s to %s", self.neighbor.level, new_neighbor.level) self.fsm.push_event(self.Event.NEIGHBOR_CHANGED_LEVEL) return # Section B.1.4.3.3 if new_neighbor.address != self.neighbor.address: self.info("Neighbor address changed from %s to %s", self.neighbor.address, new_neighbor.address) self.fsm.push_event(self.Event.NEIGHBOR_CHANGED_ADDRESS) return # Section B.1.4.3.4 if self.check_minor_change(new_neighbor): self.fsm.push_event(self.Event.NEIGHBOR_CHANGED_MINOR_FIELDS) self.neighbor = new_neighbor # TODO: The draft does not specify this, but it is needed # Section B.1.4.3.5 self.check_three_way()
def check_reflection(self): # Does the received LIE packet (which is now stored in _neighbor) report us as the neighbor? if self.neighbor.neighbor_system_id != self._node.system_id: self.info("Neighbor does not report us as neighbor (system-id %s instead of %s", utils.system_id_str(self.neighbor.neighbor_system_id), utils.system_id_str(self._node.system_id)) return False if self.neighbor.neighbor_link_id != self.local_id: self.info("Neighbor does not report us as neighbor (link-id %s instead of %s", self.neighbor.neighbor_link_id, self.local_id) return False return True
def cli_level_attributes(self): if self._running: return [ self._name, utils.system_id_str(self._system_id), self._running, self._configured_level_symbol, self.level_value_str() ] else: return [ self._name, utils.system_id_str(self._system_id), self._running, self._configured_level_symbol, '?' ]
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)] ]
def node_element_str(element): lines = [] if element.name is not None: lines.append("Name: " + str(element.name)) lines.append("Level: " + str(element.level)) if element.flags is not None: lines.append("Flags:") if element.flags.overload is not None: lines.append(" Overload: " + str(element.flags.overload)) if element.capabilities is not None: lines.append("Capabilities:") if element.capabilities.flood_reduction is not None: lines.append(" Flood reduction: " + str(element.capabilities.flood_reduction)) if element.capabilities.hierarchy_indications is not None: lines.append(" Leaf indications: " + hierarchy_indications_str(element.capabilities.hierarchy_indications)) sorted_neighbors = sortedcontainers.SortedDict(element.neighbors) for system_id, neighbor in sorted_neighbors.items(): lines.append("Neighbor: " + utils.system_id_str(system_id)) lines.append(" Level: " + str(neighbor.level)) if neighbor.cost is not None: lines.append(" Cost: " + str(neighbor.cost)) if neighbor.bandwidth is not None: lines.append(" Bandwidth: " + bandwidth_str(neighbor.bandwidth)) if neighbor.link_ids is not None: sorted_link_ids = sorted(neighbor.link_ids) for link_id_pair in sorted_link_ids: lines.append(" Link: " + link_id_pair_str(link_id_pair)) return lines
def cli_summary_attributes(self): if self._neighbor: return [ self._interface_name, self._neighbor.name, utils.system_id_str(self._neighbor.system_id), self._fsm.state.name ] else: return [self._interface_name, "", "", self._fsm.state.name]
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)] ]
def cli_detailed_attributes(self): return [["Name", self._name], ["Passive", self._passive], ["Running", self.is_running()], ["System ID", utils.system_id_str(self._system_id)], ["Configured Level", self._configured_level_symbol], ["Leaf Only", self._leaf_only], ["Leaf 2 Leaf", self._leaf_2_leaf], ["Superspine Flag", self._superspine_flag], [ "Zero Touch Provisioning (ZTP) Enabled", self.zero_touch_provisioning_enabled() ], ["ZTP FSM State", self._fsm.state.name], [ "ZTP Hold Down Timer", self._hold_down_timer.remaining_time_str() ], [ "Highest Available Level (HAL)", self._highest_available_level ], [ "Highest Adjacency Three-way (HAT)", self._highest_adjacency_three_way ], ["Level Value", self.level_value_str()], [ "Receive LIE IPv4 Multicast Address", self._rx_lie_ipv4_mcast_address ], [ "Transmit LIE IPv4 Multicast Address", self._tx_lie_ipv4_mcast_address ], [ "Receive LIE IPv6 Multicast Address", self._rx_lie_ipv6_mcast_address ], [ "Transmit LIE IPv6 Multicast Address", self._tx_lie_ipv6_mcast_address ], ["Receive LIE Port", self._rx_lie_port], ["Transmit LIE Port", self._tx_lie_port], [ "LIE Send Interval", "{} secs".format(self._lie_send_interval_secs) ], ["Receive TIE Port", self._rx_tie_port]]
def cli_detailed_attributes(self): return [ ["Interface Name", self.name], ["Advertised Name", self._advertised_name], ["Interface IPv4 Address", self._ipv4_address], ["Metric", self._metric], ["Receive LIE IPv4 Multicast Address", self._rx_lie_ipv4_mcast_address], ["Transmit LIE IPv4 Multicast Address", self._tx_lie_ipv4_mcast_address], ["Receive LIE IPv6 Multicast Address", self._rx_lie_ipv6_mcast_address], ["Transmit LIE IPv6 Multicast Address", self._tx_lie_ipv6_mcast_address], ["Receive LIE Port", self._rx_lie_port], ["Transmit LIE Port", self._tx_lie_port], ["Receive TIE Port", self._rx_tie_port], ["System ID", utils.system_id_str(self._node.system_id)], ["Local ID", self.local_id], ["MTU", self._mtu], ["POD", self._pod], ["Failure", self.failure_str()], ["State", self.state_name], ["Received LIE Accepted or Rejected", self._lie_accept_or_reject], ["Received LIE Accept or Reject Reason", self._lie_accept_or_reject_rule], ["Neighbor", "True" if self.neighbor else "False"] ]
def cli_summary_attributes(self): return [ self._name, utils.system_id_str(self._system_id), self._running ]