Esempio n. 1
0
 def __find_next_seq_number(seq_numbers, has_community, route_map_name):
     """
     Find a next available "Allow list" route-map entry number
     :param seq_numbers: a list of already used sequence numbers
     :param has_community: True, if the route-map entry has community
     :return: next available route-map sequence number
     """
     used_sequence_numbers = set(seq_numbers)
     sequence_number = None
     if has_community:  # put entries without communities after 29999
         start_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITH_COMMUNITY_START
         end_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITH_COMMUNITY_END
     else:
         start_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITHOUT_COMMUNITY_START
         end_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITHOUT_COMMUNITY_END
     for i in range(start_seq, end_seq, 10):
         if i not in used_sequence_numbers:
             sequence_number = i
             break
     if sequence_number is None:
         raise RuntimeError("No free sequence numbers for '%s'" %
                            route_map_name)
     info = sequence_number, "yes" if has_community else "no"
     log_debug(
         "BGPAllowListMgr::__find_next_seq_number '%d' has_community='%s'" %
         info)
     return sequence_number
Esempio n. 2
0
 def __update_prefix_list(self, af, pl_name, allow_list):
     """
     Create or update a prefix-list with name pl_name.
     :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list
     :param pl_name: prefix-list name
     :param allow_list: prefix-list entries
     :return: True if updating was successful, False otherwise
     """
     assert af == self.V4 or af == self.V6
     constant_list = self.__get_constant_list(af)
     allow_list = self.__to_prefix_list(allow_list)
     log_debug(
         "BGPAllowListMgr::__update_prefix_list. af='%s' prefix-list name=%s"
         % (af, pl_name))
     exist, correct = self.__is_prefix_list_valid(af, pl_name, allow_list,
                                                  constant_list)
     if correct:
         log_debug(
             "BGPAllowListMgr::__update_prefix_list. the prefix-list '%s' exists and correct"
             % pl_name)
         return []
     family = self.__af_to_family(af)
     cmds = []
     seq_no = 10
     if exist:
         cmds.append('no %s prefix-list %s' % (family, pl_name))
     for entry in constant_list + allow_list:
         cmds.append('%s prefix-list %s seq %d %s' %
                     (family, pl_name, seq_no, entry))
         seq_no += 10
     return cmds
Esempio n. 3
0
 def __generate_names(deployment_id, community_value):
     """
     Generate prefix-list names for a given peer_ip and community value
     :param deployment_id: deployment_id for which we're going to filter prefixes
     :param community_value: community, which we want to use to filter prefixes
     :return: a dictionary with names
     """
     if community_value == BGPAllowListMgr.EMPTY_COMMUNITY:
         community_name = BGPAllowListMgr.EMPTY_COMMUNITY
     else:
         community_name = BGPAllowListMgr.COMMUNITY_NAME_TMPL % (
             deployment_id, community_value)
     names = {
         "pl_v4":
         BGPAllowListMgr.PL_NAME_TMPL %
         (deployment_id, community_value, '4'),
         "pl_v6":
         BGPAllowListMgr.PL_NAME_TMPL %
         (deployment_id, community_value, '6'),
         "rm_v4":
         BGPAllowListMgr.RM_NAME_TMPL % (deployment_id, '4'),
         "rm_v6":
         BGPAllowListMgr.RM_NAME_TMPL % (deployment_id, '6'),
         "community":
         community_name,
     }
     arguments = deployment_id, community_value, str(names)
     log_debug(
         "BGPAllowListMgr::__generate_names. deployment_id: %d, community: %s. names: %s"
         % arguments)
     return names
Esempio n. 4
0
    def __remove_policy(self, deployment_id, community_value):
        """
        Remove "allow list" policy for given deployment_id and community_value
        :param deployment_id: deployment id which policy will be removed
        :param community_value: community value to match for the removed policy
        """
        # remove all related entries from the configuration
        # put default rule to the route-map
        info = deployment_id, community_value
        msg = "BGPAllowListMgr::Removing 'Allow list' policy."
        msg += " deployment_id '%s'. community: '%s'"
        log_info(msg % info)

        names = self.__generate_names(deployment_id, community_value)
        self.cfg_mgr.update()
        cmds = []
        cmds += self.__remove_allow_route_map_entry(self.V4, names['pl_v4'],
                                                    names['community'],
                                                    names['rm_v4'])
        cmds += self.__remove_allow_route_map_entry(self.V6, names['pl_v6'],
                                                    names['community'],
                                                    names['rm_v6'])
        cmds += self.__remove_prefix_list(self.V4, names['pl_v4'])
        cmds += self.__remove_prefix_list(self.V6, names['pl_v6'])
        cmds += self.__remove_community(names['community'])
        if cmds:
            rc = self.cfg_mgr.push_list(cmds)
            rc = rc and self.__restart_peers(deployment_id)
            log_debug(
                "BGPAllowListMgr::__remove_policy. 'Allow list' policy was removed. rc:%s"
                % rc)
        else:
            log_debug("BGPAllowListMgr::__remove_policy. Nothing to remove")
        log_info('BGPAllowListMgr::Done')
Esempio n. 5
0
 def __parse_allow_route_map_entries(self, af, route_map_name):
     """
     Parse "Allow list" route-map entries.
     :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list
     :return: A tuple, First element: True if operation was successful, False otherwise
                       Second element: list of object with parsed route-map entries
     """
     assert af == self.V4 or af == self.V6
     log_debug(
         "BGPAllowListMgr::__parse_allow_route_map_entries. af='%s', rm='%s'"
         % (af, route_map_name))
     match_string = 'route-map %s permit ' % route_map_name
     entries = {}
     inside_route_map = False
     route_map_seq_number = None
     pl_allow_list_name = None
     community_name = self.EMPTY_COMMUNITY
     if af == self.V4:
         match_pl_allow_list = 'match ip address prefix-list '
     else:  # self.V6
         match_pl_allow_list = 'match ipv6 address prefix-list '
     match_community = 'match community '
     conf = self.cfg_mgr.get_text()
     for line in conf + [""]:
         if inside_route_map:
             if line.strip().startswith(match_pl_allow_list):
                 pl_allow_list_name = line.strip()[len(match_pl_allow_list
                                                       ):]
                 continue
             elif line.strip().startswith(match_community):
                 community_name = line.strip()[len(match_community):]
                 continue
             else:
                 if pl_allow_list_name is not None:
                     entries[route_map_seq_number] = {
                         'pl_allow_list': pl_allow_list_name,
                         'community': community_name,
                     }
                 else:
                     if route_map_seq_number != 65535:
                         log_warn(
                             "BGPAllowListMgr::Found incomplete route-map '%s' entry. seq_no=%d"
                             % (route_map_name, route_map_seq_number))
                 inside_route_map = False
                 pl_allow_list_name = None
                 community_name = self.EMPTY_COMMUNITY
                 route_map_seq_number = None
         if line.startswith(match_string):
             found = line[len(match_string):]
             assert found.isdigit()
             route_map_seq_number = int(found)
             inside_route_map = True
     return entries
Esempio n. 6
0
 def __update_community(self, community_name, community_value):
     """
     Update community for a peer
     :param community_name: name of the community to update
     :param community_value: community value for the peer
     :return: True if operation was successful, False otherwise
     """
     log_debug(
         "BGPAllowListMgr::__update_community. community_name='%s' community='%s'"
         % (community_name, community_value))
     if community_value == self.EMPTY_COMMUNITY:  # we don't need to do anything for EMPTY community
         log_debug(
             "BGPAllowListMgr::__update_community. Empty community. exiting"
         )
         return []
     cmds = []
     exists, found_community_value = self.__is_community_presented(
         community_name)
     if exists:
         if community_value == found_community_value:
             log_debug(
                 "BGPAllowListMgr::__update_community. community '%s' is already presented"
                 % community_name)
             return []
         else:
             msg = "BGPAllowListMgr::__update_community. "
             msg += "community '%s' is already presented, but community value should be updated" % community_name
             log_debug(msg)
             cmds.append("no bgp community-list standard %s" %
                         community_name)
     cmds.append('bgp community-list standard %s permit %s' %
                 (community_name, community_value))
     return cmds
Esempio n. 7
0
 def __is_community_presented(self, community_name):
     """
     Return True if community for the peer_ip exists
     :param community_name: community value for the peer
     :return: A tuple. First element: True if operation was successful, False otherwise
                       Second element: community value if the first element is True no value otherwise
     """
     log_debug("BGPAllowListMgr::__is_community_presented. community='%s'" %
               community_name)
     match_string = 'bgp community-list standard %s permit ' % community_name
     conf = self.cfg_mgr.get_text()
     found = [
         line.strip() for line in conf
         if line.strip().startswith(match_string)
     ]
     if not found:
         return False, None
     community_value = found[0].replace(match_string, '')
     return True, community_value
Esempio n. 8
0
 def __remove_prefix_list(self, af, pl_name):
     """
     Remove prefix-list in the address-family af.
     :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list
     :param pl_name: list of prefix-list names
     :return: True if operation was successful, False otherwise
     """
     assert af == self.V4 or af == self.V6
     log_debug(
         "BGPAllowListMgr::__remove_prefix_lists. af='%s' pl_names='%s'" %
         (af, pl_name))
     exist, _ = self.__is_prefix_list_valid(af, pl_name, [], [])
     if not exist:
         log_debug(
             "BGPAllowListMgr::__remove_prefix_lists: prefix_list '%s' not found"
             % pl_name)
         return []
     family = self.__af_to_family(af)
     return ["no %s prefix-list %s" % (family, pl_name)]
Esempio n. 9
0
 def handler(self, key, op, data):
     """
     This method is executed on each add/remove event on the table.
     :param key: key of the table entry
     :param op: operation on the table entry. Could be either 'SET' or 'DEL'
     :param data: associated data of the event. Empty for 'DEL' operation.
     """
     if op == swsscommon.SET_COMMAND:
         if self.directory.available_deps(self.deps):  # all required dependencies are set in the Directory?
             res = self.set_handler(key, data)
             if not res:  # set handler returned False, which means it is not ready to process is. Save it for later.
                 log_debug("'SET' handler returned NOT_READY for the Manager: %s" % self.__class__)
                 self.set_queue.append((key, data))
         else:
             log_debug("Not all dependencies are met for the Manager: %s" % self.__class__)
             self.set_queue.append((key, data))
     elif op == swsscommon.DEL_COMMAND:
         self.del_handler(key)
     else:
         log_err("Invalid operation '%s' for key '%s'" % (op, key))
Esempio n. 10
0
 def __find_route_map_entry(entries, allow_address_pl_name, community_name):
     """
     Find route-map entry with given allow_address prefix list name and community name in the parsed route-map.
     :param entries: entries of parsed route-map
     :param allow_address_pl_name: name of the "allow address" prefix-list
     :param community_name: name of the "allow address" community name
     :return: a tuple. The first element of the tuple is True, if the route-map entry was found, False otherwise.
                       The second element of the tuple has a sequence number of the entry.
     """
     for sequence_number, values in entries.items():
         if sequence_number == 65535:
             continue
         allow_list_presented = values[
             'pl_allow_list'] == allow_address_pl_name
         community_presented = values['community'] == community_name
         if allow_list_presented and community_presented:
             log_debug(
                 "BGPAllowListMgr::__find_route_map_entry. found route-map '%s' entry"
                 % allow_address_pl_name)
             return True, sequence_number
     return False, None
Esempio n. 11
0
 def __remove_allow_route_map_entry(self, af, allow_address_pl_name,
                                    community_name, route_map_name):
     """
     Add or update a "Allow address" route-map entry with the parameters
     :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list
     :return: True if operation was successful, False otherwise
     """
     assert af == self.V4 or af == self.V6
     info = af, route_map_name, allow_address_pl_name, community_name
     log_debug(
         "BGPAllowListMgr::__update_allow_route_map_entry. af='%s' Allow rm='%s' pl='%s' cl='%s'"
         % info)
     entries = self.__parse_allow_route_map_entries(af, route_map_name)
     found, seq_number = self.__find_route_map_entry(
         entries, allow_address_pl_name, community_name)
     if not found:
         log_debug(
             "BGPAllowListMgr::__update_allow_route_map_entry. Not found route-map '%s' entry"
             % allow_address_pl_name)
         return []
     return ['no route-map %s permit %d' % (route_map_name, seq_number)]
Esempio n. 12
0
 def __update_allow_route_map_entry(self, af, allow_address_pl_name,
                                    community_name, route_map_name):
     """
     Add or update a "Allow address" route-map entry with the parameters
     :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list
     :return: True if operation was successful, False otherwise
     """
     assert af == self.V4 or af == self.V6
     info = af, route_map_name, allow_address_pl_name, community_name
     log_debug(
         "BGPAllowListMgr::__update_allow_route_map_entry. af='%s' Allow rm='%s' pl='%s' cl='%s'"
         % info)
     entries = self.__parse_allow_route_map_entries(af, route_map_name)
     found, _ = self.__find_route_map_entry(entries, allow_address_pl_name,
                                            community_name)
     if found:
         log_debug(
             "BGPAllowListMgr::__update_allow_route_map_entry. route-map='%s' is already found"
             % route_map_name)
         return []
     seq_number = self.__find_next_seq_number(
         entries.keys(), community_name != self.EMPTY_COMMUNITY,
         route_map_name)
     info = af, seq_number, allow_address_pl_name, community_name
     out = "af='%s' seqno='%d' Allow pl='%s' cl='%s'" % info
     log_debug("BGPAllowListMgr::__update_allow_route_map_entry. %s" % out)
     ip_version = "" if af == self.V4 else "v6"
     cmds = [
         'route-map %s permit %d' % (route_map_name, seq_number),
         ' match ip%s address prefix-list %s' %
         (ip_version, allow_address_pl_name)
     ]
     if not community_name.endswith(self.EMPTY_COMMUNITY):
         cmds.append(" match community %s" % community_name)
     return cmds
Esempio n. 13
0
 def __update_policy(self, deployment_id, community_value, prefixes_v4,
                     prefixes_v6):
     """
     Update "allow list" policy with parameters
     :param deployment_id: deployment id which policy will be changed
     :param community_value: community value to match for the updated policy
     :param prefixes_v4: a list of v4 prefixes for the updated policy
     :param prefixes_v6: a list of v6 prefixes for the updated policy
     """
     # update all related entries with the information
     info = deployment_id, community_value, str(prefixes_v4), str(
         prefixes_v6)
     msg = "BGPAllowListMgr::Updating 'Allow list' policy."
     msg += " deployment_id '%s'. community: '%s'"
     msg += " prefix_v4 '%s'. prefix_v6: '%s'"
     log_info(msg % info)
     names = self.__generate_names(deployment_id, community_value)
     self.cfg_mgr.update()
     cmds = []
     cmds += self.__update_prefix_list(self.V4, names['pl_v4'], prefixes_v4)
     cmds += self.__update_prefix_list(self.V6, names['pl_v6'], prefixes_v6)
     cmds += self.__update_community(names['community'], community_value)
     cmds += self.__update_allow_route_map_entry(self.V4, names['pl_v4'],
                                                 names['community'],
                                                 names['rm_v4'])
     cmds += self.__update_allow_route_map_entry(self.V6, names['pl_v6'],
                                                 names['community'],
                                                 names['rm_v6'])
     if cmds:
         rc = self.cfg_mgr.push_list(cmds)
         rc = rc and self.__restart_peers(deployment_id)
         log_debug(
             "BGPAllowListMgr::__update_policy. The peers were updated: rc=%s"
             % rc)
     else:
         log_debug("BGPAllowListMgr::__update_policy. Nothing to update")
     log_info("BGPAllowListMgr::Done")
Esempio n. 14
0
 def __remove_community(self, community_name):
     """
     Remove community for a peer
     :param community_name: community value for the peer
     :return: True if operation was successful, False otherwise
     """
     log_debug("BGPAllowListMgr::__remove_community. community='%s'" %
               community_name)
     if community_name == self.EMPTY_COMMUNITY:  # we don't need to do anything for EMPTY community
         log_debug(
             "BGPAllowListMgr::__remove_community. There is nothing to remove in empty community"
         )
         return []
     exists, _ = self.__is_community_presented(community_name)
     if not exists:
         log_debug(
             "BGPAllowListMgr::__remove_community. Community is already removed."
         )
         return []
     return ['no bgp community-list standard %s' % community_name]