88import logging
99import json
1010import ipaddress
11+ import ast
12+ import random
1113
1214from tests .common .config_reload import config_reload
1315
3941_TEMP_CONFIG_DB = "/home/admin/config_db_copp_backup.json"
4042
4143
42- def limit_policer (dut , pps_limit , nn_target_namespace ):
44+ def limit_policer (dut , pps_limit , nn_target_namespace , neighbor_miss_trap_supported ):
4345 """
4446 Updates the COPP configuration in the SWSS container to respect a given rate limit.
4547
@@ -64,12 +66,13 @@ def limit_policer(dut, pps_limit, nn_target_namespace):
6466 config_format = "config_db"
6567
6668 dut .script (
67- cmd = "{} {} {} {} {} {}" .format (_UPDATE_COPP_SCRIPT ,
68- pps_limit ,
69- _BASE_COPP_CONFIG ,
70- _TEMP_COPP_CONFIG ,
71- config_format ,
72- dut .facts ["asic_type" ])
69+ cmd = "{} {} {} {} {} {} {}" .format (_UPDATE_COPP_SCRIPT ,
70+ pps_limit ,
71+ _BASE_COPP_CONFIG ,
72+ _TEMP_COPP_CONFIG ,
73+ config_format ,
74+ dut .facts ["asic_type" ],
75+ neighbor_miss_trap_supported )
7376 )
7477
7578 if config_format == "app_db" :
@@ -474,3 +477,114 @@ def get_lo_ipv4(duthost):
474477 break
475478
476479 return loopback_ip
480+
481+
482+ def get_copp_trap_capabilities (duthost ):
483+ """
484+ Fetches supported trap IDs from COPP_TRAP_CAPABILITY_TABLE in STATE_DB and returns them as a list.
485+ Args:
486+ duthost (SonicHost): The target device.
487+ Returns:
488+ list: A list of supported trap IDs.
489+ """
490+
491+ trap_ids = duthost .shell ("sonic-db-cli STATE_DB HGET 'COPP_TRAP_CAPABILITY_TABLE|traps' trap_ids" )['stdout' ]
492+ return trap_ids .split ("," )
493+
494+
495+ def parse_show_copp_configuration (duthost ):
496+ """
497+ Parses the output of the `show copp configuration` command into a structured dictionary.
498+ Args:
499+ duthost (SonicHost): The target device.
500+ Returns:
501+ dict: A dictionary mapping trap IDs to their configuration details.
502+ """
503+
504+ copp_config_output = duthost .shell ("show copp configuration" )["stdout" ]
505+ copp_config_lines = copp_config_output .splitlines ()
506+
507+ # Parse the command output into a structured format
508+ copp_config_data = {}
509+ for line in copp_config_lines [1 :]: # Skip the header line
510+ fields = line .split ()
511+ if len (fields ) >= 8 :
512+ trap_id = fields [0 ]
513+ copp_config_data [trap_id ] = {
514+ "trap_group" : fields [1 ],
515+ "trap_action" : fields [2 ],
516+ "cbs" : fields [3 ],
517+ "cir" : fields [4 ],
518+ "meter_type" : fields [5 ],
519+ "mode" : fields [6 ],
520+ "hw_status" : fields [7 ]
521+ }
522+
523+ return copp_config_data
524+
525+
526+ def is_trap_installed (duthost , trap_id ):
527+ """
528+ Checks if a specific trap is installed by parsing the output of `show copp configuration`.
529+ Args:
530+ dut (SonicHost): The target device
531+ trap_id: The trap ID to check.
532+ Returns:
533+ bool: True if the trap is installed, False otherwise.
534+ """
535+
536+ output = parse_show_copp_configuration (duthost )
537+ assert trap_id in output , f"Trap { trap_id } not found in the configuration"
538+ assert "hw_status" in output [trap_id ], f"hw_status not found for trap { trap_id } "
539+
540+ return output [trap_id ]["hw_status" ] == "installed"
541+
542+
543+ def get_trap_hw_status (duthost ):
544+ """
545+ Retrieves the hw_status for traps from the STATE_DB.
546+ Args:
547+ dut (SonicHost): The target device
548+ Returns:
549+ dict: A dictionary mapping trap IDs to their hw_status.
550+ """
551+
552+ state_db_data = duthost .shell ("sonic-db-cli STATE_DB KEYS 'COPP_TRAP_TABLE|*'" )["stdout" ]
553+ state_db_data = state_db_data .splitlines ()
554+ hw_status = {}
555+
556+ for key in state_db_data :
557+ trap_id = key .split ("|" )[- 1 ]
558+ trap_data = duthost .shell (f"sonic-db-cli STATE_DB HGETALL '{ key } '" )["stdout" ]
559+ trap_data_dict = ast .literal_eval (trap_data )
560+ hw_status [trap_id ] = trap_data_dict .get ("hw_status" , "not-installed" )
561+
562+ return hw_status
563+
564+
565+ def get_random_copp_trap_config (duthost ):
566+ """
567+ Retrieves a random CoPP trap config from /etc/sonic/copp_cfg.json on the DUT.
568+ Returns the trap ID, its group, and related config details from COPP_TRAP and COPP_GROUP sections
569+ Args:
570+ duthost (SonicHost): The target device.
571+ Returns:
572+ tuple: A tuple containing the following elements:
573+ - str: The first trap ID associated with the selected trap.
574+ - str: The trap group associated with the selected trap.
575+ - dict: The configuration details of the selected trap group from the `COPP_GROUP` section.
576+ """
577+
578+ copp_cfg = json .loads (duthost .shell ("cat /etc/sonic/copp_cfg.json" )["stdout" ])
579+
580+ # Get all traps from COPP_TRAP
581+ copp_trap_cfg = copp_cfg .get ("COPP_TRAP" , {})
582+ traps = list (copp_trap_cfg .keys ())
583+ assert traps , "No traps found in copp_cfg.json"
584+
585+ # Randomly select one trap
586+ selected_trap = random .choice (traps )
587+ trap_data = copp_cfg ["COPP_TRAP" ][selected_trap ]
588+ trap_ids = trap_data .get ("trap_ids" , "" ).split ("," )
589+ trap_group = trap_data .get ("trap_group" , "" )
590+ return trap_ids [0 ], trap_group , copp_cfg ["COPP_GROUP" ][trap_group ]
0 commit comments