|
| 1 | +# [SAI] Synchronous Ethernet |
| 2 | +------------------------------------------------------------------------------- |
| 3 | + Title | Synchronous Ethernet |
| 4 | +-------------|----------------------------------------------------------------- |
| 5 | + Authors | Rajesh Perumal, Ravindranath C K (Marvell) |
| 6 | + Status | In review |
| 7 | + Type | Standards track |
| 8 | + Created | 2025-02-20 |
| 9 | + SAI-Version | 1.16 |
| 10 | +------------------------------------------------------------------------------- |
| 11 | + |
| 12 | +## 1.0 Introduction |
| 13 | + |
| 14 | +The aim of the Synchronous Ethernet(SyncE) is to transfer timing(frequency) over the Ethernet physical layer across a network. |
| 15 | +SyncE synchronizes the system clock(which drives the tx frequency) at the Switch device. The switch NPU can have one or more |
| 16 | +SyncE clocks. The SyncE clocks recover the frequency from any port of the switch and inputs it to the system clock. |
| 17 | + SyncE relies on Ethernet port, System clock, the recovered clock signal from SyncE clock and |
| 18 | +the quality of recovered clock signal. As the Ethernet port programming can be done through an already available SAI_OBJECT_TYPE_PORT object, |
| 19 | +the SyncE clock programming and the SSM for SyncE is focused in this proposal. |
| 20 | + |
| 21 | +## 2.0 Behavior |
| 22 | + |
| 23 | +### SyncE clock object |
| 24 | + |
| 25 | + |
| 26 | +SyncE clock and an Ethernet port needs to be associated to setup the the clock source for the associated SyncE clock object. |
| 27 | +The recovered clock signal will be fed to the System clock. System clock drives the Ethernet Tx(frequency) with the help of |
| 28 | +these SyncE clock sources. SyncE clock has the following attributes : clock-status, clock-hardware-id and clock-src-port. |
| 29 | + |
| 30 | + |
| 31 | +```mermaid |
| 32 | +classDiagram |
| 33 | + class SYNCE_CLOCK { |
| 34 | + - src_port |
| 35 | + - clock_hardware_id |
| 36 | + - clock_valid |
| 37 | + - clock_force_valid |
| 38 | + } |
| 39 | +
|
| 40 | + class PORT { |
| 41 | + - ... |
| 42 | + } |
| 43 | +
|
| 44 | + class SWITCH { |
| 45 | + - port_list |
| 46 | + - synce_clock_list [proposed] |
| 47 | + } |
| 48 | +
|
| 49 | +
|
| 50 | + %% Relationships |
| 51 | + SWITCH --> SYNCE_CLOCK : SYNCE_CLOCK_LIST |
| 52 | + SWITCH --> PORT : PORT_LIST |
| 53 | + PORT <-- SYNCE_CLOCK : SRC_PORT |
| 54 | +
|
| 55 | +style PORT fill:#bbf,stroke:#f66,stroke-width:2px,color:green; |
| 56 | +style SWITCH fill:#bbf,stroke:#f66,stroke-width:2px,color:green; |
| 57 | +
|
| 58 | +``` |
| 59 | + |
| 60 | +### SSM over ESMC for SyncE |
| 61 | +SyncE relies on quality of recovered clock which needs to be communicated through synchronization status message(SSM) over the |
| 62 | +Ethernet synchronization messaging channel(ESMC). To trap the SSM PDUs, new Hostif trap is added. |
| 63 | + |
| 64 | +## 3.0 SAI Enhancement |
| 65 | + |
| 66 | +### 1. New object type for SyncE clock |
| 67 | + |
| 68 | +```c |
| 69 | + SAI_OBJECT_TYPE_SYNCE_CLOCK = 114, |
| 70 | +``` |
| 71 | + |
| 72 | + |
| 73 | +```c |
| 74 | +/** |
| 75 | + * @brief Enum defining SyncE attributes. |
| 76 | + */ |
| 77 | +typedef enum _sai_synce_clock_attr_t |
| 78 | +{ |
| 79 | + /** |
| 80 | + * @brief Start of attributes |
| 81 | + */ |
| 82 | + SAI_SYNCE_CLOCK_ATTR_START = 0x00000000, |
| 83 | + /** |
| 84 | + * @brief Synchronous ethernet(SyncE) clock source port |
| 85 | + * |
| 86 | + * Sets the Port to be the source for SyncE |
| 87 | + * |
| 88 | + * @type sai_object_id_t |
| 89 | + * @objects SAI_OBJECT_TYPE_PORT |
| 90 | + * @allownull true |
| 91 | + * @flags CREATE_AND_SET |
| 92 | + * @default SAI_NULL_OBJECT_ID |
| 93 | + */ |
| 94 | + SAI_SYNCE_CLOCK_ATTR_SRC_PORT = SAI_SYNCE_CLOCK_ATTR_START, |
| 95 | + |
| 96 | + /** |
| 97 | + * @brief Synchronous ethernet (SyncE) clock status |
| 98 | + * |
| 99 | + * Gets recovered clock signal with respect to hardware |
| 100 | + * (valid only after attaching the clock to a clock source port) |
| 101 | + * |
| 102 | + * @type bool |
| 103 | + * @flags READ_ONLY |
| 104 | + */ |
| 105 | + SAI_SYNCE_CLOCK_ATTR_CLOCK_VALID, |
| 106 | + |
| 107 | + /** |
| 108 | + * @brief Hardware clock-id |
| 109 | + * |
| 110 | + * Returns the hardware clock-id associated |
| 111 | + * |
| 112 | + * @type sai_uint32_t |
| 113 | + * @flags READ_ONLY |
| 114 | + */ |
| 115 | + SAI_SYNCE_CLOCK_ATTR_CLOCK_HARDWARE_ID, |
| 116 | + |
| 117 | + /** |
| 118 | + * @brief Synchronous ethernet (SyncE) clock status |
| 119 | + * |
| 120 | + * Force set the recovered clock signal state (for debugging) |
| 121 | + * |
| 122 | + * @type sai_synce_recovered_clock_state_t |
| 123 | + * @flags CREATE_AND_SET |
| 124 | + * @default SAI_SYNCE_CLOCK_FORCE_VALID_DISABLE |
| 125 | + */ |
| 126 | + SAI_SYNCE_CLOCK_ATTR_DEBUG_FORCE_CLOCK_VALID, |
| 127 | + |
| 128 | + /** |
| 129 | + * @brief End of attributes |
| 130 | + */ |
| 131 | + SAI_SYNCE_CLOCK_ATTR_END, |
| 132 | + /** Custom range base value */ |
| 133 | + SAI_SYNCE_CLOCK_ATTR_CUSTOM_RANGE_START = 0x10000000, |
| 134 | + |
| 135 | + /** End of custom range base */ |
| 136 | + SAI_SYNCE_CLOCK_ATTR_CUSTOM_RANGE_END |
| 137 | + |
| 138 | +} sai_synce_clock_attr_t; |
| 139 | + |
| 140 | +/** |
| 141 | + * @brief Attribute data for #SAI_SYNCE_CLOCK_ATTR_DEBUG_FORCE_CLOCK_VALID |
| 142 | + */ |
| 143 | +typedef enum _sai_synce_recovered_clock_state_t |
| 144 | +{ |
| 145 | + /** Valid signal set as per device fault status */ |
| 146 | + SAI_SYNCE_CLOCK_FORCE_VALID_DISABLE, |
| 147 | + |
| 148 | + /** Valid signal forced to valid */ |
| 149 | + SAI_SYNCE_CLOCK_FORCE_ENABLE_VALID, |
| 150 | + |
| 151 | + /** Valid signal forced to invalid */ |
| 152 | + SAI_SYNCE_CLOCK_FORCE_ENABLE_INVALID, |
| 153 | + |
| 154 | +} sai_synce_recovered_clock_state_t; |
| 155 | + |
| 156 | +/** |
| 157 | + * @brief Create SyncE clock |
| 158 | + * |
| 159 | + * @param[out] synce_id SyncE clock id |
| 160 | + * @param[in] switch_id The Switch id |
| 161 | + * @param[in] attr_count Number of attributes |
| 162 | + * @param[in] attr_list Array of attributes |
| 163 | + * |
| 164 | + * @return #SAI_STATUS_SUCCESS on success, failure status code on error |
| 165 | + */ |
| 166 | +typedef sai_status_t (*sai_create_synce_clock_fn)( |
| 167 | + _Out_ sai_object_id_t *synce_clock_id, |
| 168 | + _In_ sai_object_id_t switch_id, |
| 169 | + _In_ uint32_t attr_count, |
| 170 | + _In_ const sai_attribute_t *attr_list); |
| 171 | + |
| 172 | +/** |
| 173 | + * @brief Remove SyncE clock |
| 174 | + * |
| 175 | + * @param[in] synce_id SyncE clock id |
| 176 | + * |
| 177 | + * @return #SAI_STATUS_SUCCESS on success, failure status code on error |
| 178 | + */ |
| 179 | +typedef sai_status_t (*sai_remove_synce_clock_fn)( |
| 180 | + _In_ sai_object_id_t synce_clock_id); |
| 181 | + |
| 182 | +/** |
| 183 | + * @brief Set SyncE clock Attribute |
| 184 | + * |
| 185 | + * @param[in] synce_id SyncE clock id |
| 186 | + * @param[in] attr Attribute to set |
| 187 | + * |
| 188 | + * @return #SAI_STATUS_SUCCESS on success, failure status code on error |
| 189 | + */ |
| 190 | +typedef sai_status_t (*sai_set_synce_clock_attribute_fn)( |
| 191 | + _In_ sai_object_id_t synce_clock_id, |
| 192 | + _In_ const sai_attribute_t *attr); |
| 193 | + |
| 194 | +/** |
| 195 | + * @brief Get SyncE clock attribute |
| 196 | + * |
| 197 | + * @param[in] synce_id SyncE clock id |
| 198 | + * @param[in] attr_count Number of attributes |
| 199 | + * @param[inout] attr_list Array of attributes |
| 200 | + * |
| 201 | + * @return #SAI_STATUS_SUCCESS on success, failure status code on error |
| 202 | + */ |
| 203 | +typedef sai_status_t (*sai_get_synce_clock_attribute_fn)( |
| 204 | + _In_ sai_object_id_t synce_clock_id, |
| 205 | + _In_ uint32_t attr_count, |
| 206 | + _Inout_ sai_attribute_t *attr_list); |
| 207 | +``` |
| 208 | +
|
| 209 | +### 2. New hostif trap for SSM over ESMC PDUs |
| 210 | +
|
| 211 | +```c |
| 212 | + /** |
| 213 | + * @brief ITU-T G.8264/Y.1364 Ethernet synchronization messaging channel (ESMC) protocol |
| 214 | + * (Dst Mac = 01-80-C2-00-00-02 EtherType = 0x8809 Slow Protocol Subtype = 0xA) |
| 215 | + * (default packet action is drop) |
| 216 | + */ |
| 217 | + SAI_HOSTIF_TRAP_TYPE_ESMC = 0x00008003, |
| 218 | +``` |
| 219 | + |
| 220 | +### 3. Switch attributes for SyncE clock |
| 221 | +```c |
| 222 | + /** |
| 223 | + * @brief Maximum number of SyncE clocks supported |
| 224 | + * |
| 225 | + * @type sai_uint32_t |
| 226 | + * @flags READ_ONLY |
| 227 | + */ |
| 228 | + SAI_SWITCH_ATTR_MAX_SYNCE_CLOCK_COUNT, |
| 229 | + |
| 230 | + /** |
| 231 | + * |
| 232 | + *@brief List of SyncE clock objects on the Switch |
| 233 | + * |
| 234 | + *@type sai_object_list_t |
| 235 | + *@flags READ_ONLY |
| 236 | + *@objects SAI_OBJECT_TYPE_SYNCE_CLOCK |
| 237 | + *@default internal |
| 238 | + */ |
| 239 | + SAI_SWITCH_ATTR_SYNCE_CLOCK_LIST, |
| 240 | +``` |
| 241 | + |
| 242 | +## 4.0 API Example |
| 243 | + |
| 244 | +The API workflow is as given below, |
| 245 | +1. Get the maximum number of available SyncE clocks from the switch |
| 246 | +2. Get the list of available SyncE clocks from the switch |
| 247 | +3. Update the clock source by associating an Ethernet port to the SyncE clock object |
| 248 | +4. Update the clock source by updating the port at SyncE clock object |
| 249 | +5. Remove the clock source by setting NULL oid to SyncE clock object |
| 250 | +6. Get and set SyncE clock object |
| 251 | + |
| 252 | +### 1. Get the maximum SyncE-clock objects present at the switch |
| 253 | + |
| 254 | +```c |
| 255 | +attr_count = 0; |
| 256 | +attr_list[attr_count++].id = SAI_SWITCH_ATTR_MAX_SYNCE_CLOCK_COUNT; |
| 257 | +sai_get_switch_attribute_fn(switch_id, attr_count, attr_list) ; |
| 258 | +synce_clocks_count = attr_list[0].value.u32; |
| 259 | +``` |
| 260 | +### 2. Get the list of SyncE-clock objects present at the switch |
| 261 | +```c |
| 262 | +attr_count = 0; |
| 263 | +attr_clock_list[attr_count].id = SAI_SWITCH_ATTR_SYNCE_CLOCK_LIST; |
| 264 | +attr_clock_list[attr_count].value.objlist.count = synce_clocks_count; |
| 265 | +attr_clock_list[attr_count++].value.objlist.list = malloc(synce_clocks_count * sizeof(sai_object_id_t)) |
| 266 | +sai_get_switch_attribute_fn(switch_id, attr_count, attr_clock_list) ; |
| 267 | +``` |
| 268 | +### 3. Associate a port to the SyncE-clock object to make it a clock source |
| 269 | +```c |
| 270 | +attr_count = 0; |
| 271 | +attr_list[attr_count].id = SAI_SYNCE_CLOCK_ATTR_SRC_PORT ; |
| 272 | +attr_list[attr_count++].value.oid = port_oid; |
| 273 | + |
| 274 | +sai_object_t clock0_oid = attr_clock_list[0].value.oid; |
| 275 | + |
| 276 | +sai_set_synce_clock_fn(clock0_oid, switch_oid, attr_count, attr_list) ; |
| 277 | +``` |
| 278 | +
|
| 279 | +### 4. Update the clock source by updating the port at SyncE clock object |
| 280 | +
|
| 281 | +```c |
| 282 | +synce_attr.id = SAI_SYNCE_CLOCK_ATTR_SRC_PORT; |
| 283 | +synce_attr.value.oid = new_port_oid; |
| 284 | +sai_set_synce_clock_fn (clock0_oid, synce_attr); |
| 285 | +``` |
| 286 | + |
| 287 | +### 5. Remove a port from clock source by setting NULL oid to SyncE object |
| 288 | + |
| 289 | +```c |
| 290 | +synce_attr.id = SAI_SYNCE_CLOCK_ATTR_SRC_PORT; |
| 291 | +synce_attr.value.oid = SAI_NULL_OBJECT_ID; |
| 292 | +sai_set_synce_clock_fn (synce_oid, synce_attr) ; |
| 293 | +``` |
| 294 | +
|
| 295 | +### 6. Getting/Setting syncE-clock attributes |
| 296 | +```c |
| 297 | +/** Get Synce-clock */ |
| 298 | +
|
| 299 | +attr_count = 0; |
| 300 | +
|
| 301 | +attr_list[attr_count++].id = SAI_SYNCE_CLOCK_ATTR_CLOCK_VALID; |
| 302 | +attr_list[attr_count++].id = SAI_SYNCE_CLOCK_ATTR_CLOCK_HARDWARE_ID; |
| 303 | +sai_get_synce_clock_fn (synce_clock_oid, attr_count, attr_list) ; |
| 304 | +
|
| 305 | +
|
| 306 | +/** Set Synce-clock state by force */ |
| 307 | +synce_clock_attr.id = SAI_SYNCE_CLOCK_ATTR_DEBUG_FORCE_CLOCK_STATE; |
| 308 | +synce_clock_attr.value.u32 = SAI_SYNCE_CLOCK_FORCE_ENABLE_VALID; |
| 309 | +
|
| 310 | +sai_set_synce_clock_fn (synce_clock_oid, synce_clock_attr) ; |
| 311 | +``` |
0 commit comments