diff --git a/acl_loader/main.py b/acl_loader/main.py index c50efec032..ae5df7a356 100644 --- a/acl_loader/main.py +++ b/acl_loader/main.py @@ -766,6 +766,50 @@ def incremental_update(self): for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.set_entry(self.ACL_RULE, key, self.rules_info[key]) + def add_rule(self): + """ + Perform update/addition of new rules only. Get existing rules from + Config DB. Compare with rules specified in file and perform corresponding + modifications. Do not delete the existing rules. Handles only dataplane rules + :return: + """ + + # TODO: Alternate command for adding rules in dataplane ACLs instead of removing + # all the rules and populating like in full/incremental. + new_rules = set(self.rules_info.keys()) + new_dataplane_rules = set() + current_rules = set(self.rules_db_info.keys()) + current_dataplane_rules = set() + + for key in new_rules: + table_name = key[0] + if self.tables_db_info[table_name]['type'].upper() != self.ACL_TABLE_TYPE_CTRLPLANE: + new_dataplane_rules.add(key) + + for key in current_rules: + table_name = key[0] + if self.tables_db_info[table_name]['type'].upper() != self.ACL_TABLE_TYPE_CTRLPLANE: + current_dataplane_rules.add(key) + + added_dataplane_rules = new_dataplane_rules.difference(current_dataplane_rules) + removed_dataplane_rules = current_dataplane_rules.difference(new_dataplane_rules) + existing_dataplane_rules = new_rules.intersection(current_dataplane_rules) + + for key in added_dataplane_rules: + self.configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) + # Program for per-asic namespace corresponding to front asic also if present. + # For control plane ACL it's not needed but to keep all db in sync program everywhere + for namespace_configdb in self.per_npu_configdb.values(): + namespace_configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) + + for key in existing_dataplane_rules: + if not operator.eq(self.rules_info[key], self.rules_db_info[key]): + self.configdb.set_entry(self.ACL_RULE, key, self.rules_info[key]) + # Program for per-asic namespace corresponding to front asic also if present. + # For control plane ACL it's not needed but to keep all db in sync program everywhere + for namespace_configdb in self.per_npu_configdb.values(): + namespace_configdb.set_entry(self.ACL_RULE, key, self.rules_info[key]) + def delete(self, table=None, rule=None): """ :param table: @@ -1068,6 +1112,17 @@ def incremental(ctx, filename, session_name, mirror_stage, max_priority): acl_loader.load_rules_from_file(filename) acl_loader.incremental_update() +@cli.command() +@click.argument('filename', type=click.Path(exists=True)) +@click.pass_context +def add(ctx, filename): + """ + Add ACL rules. + """ + acl_loader = ctx.obj["acl_loader"] + + acl_loader.load_rules_from_file(filename) + acl_loader.add_rule() @cli.command() @click.argument('table', required=False) diff --git a/config/main.py b/config/main.py index 004b40bdb4..bc80f3bfd5 100644 --- a/config/main.py +++ b/config/main.py @@ -5579,6 +5579,20 @@ def table(ctx, table_name, table_type, description, ports, stage): config_db.set_entry("ACL_TABLE", table_name, table_info) +# +# 'add' subcommand +# + +@add.command() +@click.argument('file_name', required=True) +def rule(file_name): + """ + Add ACL rule + """ + log.log_info("'config acl add rule {}' executing...".format(file_name)) + command = "acl-loader add {}".format(file_name) + clicommon.run_command(command) + # # 'remove' subgroup ('config acl remove ...') # @@ -5600,10 +5614,28 @@ def table(table_name): """ Remove ACL table """ + log.log_info("'config acl remove table {}' executing...".format(table_name)) + command = "acl-loader delete {}".format(table_name) + clicommon.run_command(command) + config_db = ConfigDBConnector() config_db.connect() config_db.set_entry("ACL_TABLE", table_name, None) +# +# 'delete' subcommand +# + +@remove.command() +@click.argument("table_name", required=True, metavar="") +@click.argument("rule_name", required=True, metavar="") +def rule(table_name, rule_name): + """ + Remove ACL rule + """ + log.log_info("'config acl remove rule {} {}' executing...".format(table_name, rule_name)) + command = "acl-loader delete {} {}".format(table_name, rule_name) + clicommon.run_command(command) # # 'acl update' group