# clockdemo program structure

clockdemo consists of the following files:

File | Contains
--- | ---
clockdemo.c | Main source code.
clockdemo.exe | Compiled executable.
clockresource.c | Auxiliary functions invoked by functions in clockdemo to manage timing reference information such as, trunks.
clockresource.h | Defines for clockresource.c.
priority.txt | Sample clocking priority list file.

clockdemo performs three main tasks:

- Monitors for clocking changes (for example, trunk signal failures).

- Determines what to do when there is a change.

- Reconfigures clocking on the boards.

When a change to a timing reference or board requires changes to the clocking configuration, clockdemo determines the minimum number of steps to take to rectify the situation, to avoid reconfiguring boards unnecessarily.

The code for each of clockdemo's tasks is encapsulated in the main section of the program. The loop is triggered at regular intervals (regulated by the timeout set using the -t option on the command line). It is also triggered whenever an NMS OAM board started or board stopped event is received. The main section contains the following functions:

Function | Description
--- | ---
_clock_monitor | Polls all boards and returns the board status results in an array.
_clock_control | Determines an action to take (if necessary) for each board based upon the status results.
_clock_reconfigure | Reconfigures affected boards based upon the determined action.

The following illustration shows clockdemo main functions:

## main

The main section of the program does the following:

Step | Action
1 | Initializes variables and parses the command line options.
2 | Invokes _initData_file to read and parse the configuration file.
3 | Attempts to open the switch for each listed board (by invoking swiOpenSwitch), and builds an array of switch handles (swihd_array[]).
4 | Based on the information from the configuration file, determines the primary and fallback timing references for the primary master, and the fallback timing reference for the secondary master.
5 | Builds an array (h110_parms[]) containing the new configuration for each affected board.
6 | Configures the primary and secondary master by invoking swiConfigBoardClock with h110_parms[].
7 | Registers to receive NMS OAM events.
8 | Invokes swiGetBoardClock for each board to determine its clocking status, and stores the results in an array (h110_query_parms[]).
9 | Invokes _printClockStatus to print the initial clocking status to the screen.
10 | Enters the while loop described in the previous illustration.
11 | Updates the screen based on clocking changes.
12 | Shuts down if the Q key is pressed.

## _clock_monitor

_clock_monitor is called at regular intervals by the while loop in the main section. Its purpose is to determine whether a clocking change has occurred by monitoring the clocking status of each board and the status of each trunk involved in clocking. It returns an integer indicating one or more of six possible states. This information is used by the _clock_control function to determine whether to perform any clocking reconfiguration.

_clock_monitor is passed the following information:

Parameter | Description
--- | ---
num_of_boards | Number of boards in the chassis
swihd_array[] | Array containing the handles of all boards opened in the main section of the program.

_clock_monitor returns the following information:

Parameter | Description
--- | ---
clock_status | Integer indicating the type of clocking change (if any): 0: No clocking change has occurred. CLKSYS_STATUS_FALLBACK_OCCURRED (0x01): Fallback has occurred. CLKSYS_STATUS_A_FAIL (0x02): A_CLOCK is no longer being driven. CLKSYS_STATUS_B_FAIL (0x04): B_CLOCK is no longer being driven. CLKSYS_STATUS_INCONSISTENT (0x08): Fallback has occurred on some boards but not all boards. This can occur if the primary master is switching between its primary and fallback timing references, but is still managing to drive the system clock successfully. CLKSYS_STATUS_REFERENCE_CHANGED (0x10): A_CLOCK and B_CLOCK have not failed, but one of the trunks designated as a fallback source has failed.
h110_query_parms[] | Updated array containing the clocking status information for each board. This information consists of the following: Its A_CLOCK status Its B_CLOCK status Whether fallback occurred or not
(Managed in clockresource.c) | A global structure containing the updated status of each trunk on each board.

_clock_monitor does the following:

Step | Action
1 | Checks each board in swihd_array[] to determine whether it exists.
2 | Polls the status of each existing board using swiGetBoardClock. This updates h110_query_parms[] for the board.
3 | If more than 50 percent of the boards report that A_CLOCK failed, includes CLKSYS_STATUS_A_FAIL in the returned clock_status.
4 | If more than 50 percent of the boards report that B_CLOCK failed, includes CLKSYS_STATUS_B_FAIL in the returned clock_status.
5 | If fallback is reported by a board, includes CLKSYS_STATUS_FALLBACK_OCCURRED in the returned clock_status.
6 | If fallback is reported by a board, but there is no clock failure, includes CLKSYS_STATUS_INCONSISTENT in the returned clock_status.
7 | If one of the trunks designated as a fallback source has failed, includes CLKSYS_STATUS_REFERENCE_CHANGED in the returned clock_status.
8 | Updates the global structure containing the updated status of each trunk on each board.

## _clock_control

_clock_control is called at regular intervals by the while loop in the main section, directly after _clock_monitor returns. It uses the information returned by _clock_monitor to determine if any action is necessary to reconfigure the clocks. It returns an action code describing the action to be taken (if any).

_clock_control is passed the following information:

Parameter | Description
--- | ---
clock_status | Code returned by _clock_monitor describing the status of the system clocks and timing references.
h110_parms[] | The previous set of clocking settings made to each board by clockdemo.
h110_query_parms[] | Array containing the clocking status information for each board, updated by _clock_monitor.
num_of_boards | Number of boards in the system.

_clock_control returns the following information:

Parameter | Description
--- | ---
action | Integer describing one or more actions to take (if any): CLKSYS_ACTION_NONE (0x0): Take no action. CLKSYS_ACTION_RELOAD (0x01): Reload each board's current configuration. CLKSYS_ACTION_NEW_PRIMARY (0x02): Configure a new primary master. CLKSYS_ACTION_NEW_SECONDARY (0x04): Configure a new secondary master. CLKSYS_ACTION_RELOAD_PRIMARY_FALLBACK (0x08): Reload the primary master's current configuration. Do not change any other boards.
h110_parms[] | An updated set of clock settings to make to one or more boards.

_clock_control does the following:

Step | Action
1 | Calls _find_master. This function examines h110_parms[] and returns indices to the boards in the array configured as primary and secondary master. _find_master also determines which clock (A_CLOCK or B_CLOCK) is being used as the primary system clock.
2 | If the primary clock (A_CLOCK or B_CLOCK) has failed: Calls _choose_new_primary to choose a new primary master based on the configuration file. Calls _choose_new_secondary to choose a new secondary master based on the configuration file. Updates the h110_parms[] array describing the new system-wide configuration. Includes CLKSYS_ACTION_NEW_PRIMARY and CLKSYS_ACTION_NEW_SECONDARY in the returned action.
3 | If the primary clock (A_CLOCK or B_CLOCK) is functional, but the secondary clock (B_CLOCK or A_CLOCK) failed: Calls _choose_new_secondary to choose a new secondary master based on the configuration file. Updates the h110_parms[] array to describe a new configuration in which the old secondary master is now a slave. Includes CLKSYS_ACTION_NEW_SECONDARY in the returned action.
4 | If CLKSYS_STATUS_INCONSISTENT was returned by _clock_monitor: Updates the h110_parms[] array to describe a configuration in which all secondary master and slave boards reporting clock inconsistency are reloaded with their current configurations. If the primary master reported an inconsistency, selects a new fallback source for the primary master. Includes CLKSYS_ACTION_RELOAD in the returned action.
5 | If CLKSYS_STATUS_REFERENCE_CHANGED was returned by _clock_monitor: Determines new fallback sources based on the priorities set in the configuration file. If the source is on another board, chooses a new secondary master. Updates h110_parms[] to describe the new configuration. Includes CLKSYS_ACTION_NEW_PRIMARY, CLKSYS_ACTION_NEW_SECONDARY, and/or CLKSYS_ACTION_RELOAD_PRIMARY_FALLBACK in the returned action as appropriate.

## _clock_reconfigure

_clock_reconfigure is called at regular intervals by the while loop in the main section. It is called directly after _clock_control returns, unless action is CLKSYS_ACTION_NONE. It reconfigures one or more of the boards in the system based upon the action returned by _clock_control.

_clock_reconfigure is passed the following information:

Parameter | Description
--- | ---
action | Action code returned by _clock_control.
h110_parms[] | Array updated by _clock_control describing the new configuration to set.
swihd_array[] | Array of switch handles.
num_of_boards | Number of boards in the system.
h110_query_parms[] | Array updated by _clock_monitor containing the current configuration as reported by swiGetBoardClock.

_clock_reconfigure does the following:

Step | Action
1 | If action is CLKSYS_ACTION_RELOAD: Compares various parameters in h110_query_parms[] (the configuration reported by the boards) with equivalent parameters in h110_parms[] (the new configuration specified by _clock_control). If any of the parameters do not match, reconfigures the boards as specified in h110_parms[].
2 | If action is CLKSYS_ACTION_NEW_PRIMARY and the board number of the primary master has changed: Sets all boards to standalone mode. Configures the primary master as specified in h110_parms[]. Configures the secondary master as specified in h110_parms[]. Configures the slaves as specified in h110_parms[].
3 | If action is CLKSYS_ACTION_NEW_PRIMARY and the board number of the primary master has NOT changed: Configures the primary master as specified in h110_parms[].
4 | If action is CLKSYS_ACTION_NEW_SECONDARY: Reconfigures the old secondary master as a slave, as specified in h110_parms[]. Configures the new secondary master as specified in h110_parms[].
5 | If action is CLKSYS_ACTION_RELOAD_PRIMARY_FALLBACK: Gets the primary master's old configuration, and reloads it. Does not disturb other boards.