Xcvrd changes to support 400G ZR configuration#270
Conversation
| except AttributeError: | ||
| # Skip if these essential routines are not available | ||
| self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_READY | ||
| assert 1 == 0 |
|
@snider-nokia can you review? |
|
@jaganbal-a @shyam77git please review |
|
@qinchuanares please review |
|
|
||
| found, port_info = port_tbl.get(lport) | ||
| if found and 'laser_freq' in dict(port_info): | ||
| freq = dict(port_info)['laser_freq'] |
There was a problem hiding this comment.
what if found is True but no frequency is configured in port_info? It's likely to happen when a ZR module is plugged but freq config is missing. Do we see the port to be err-disabled?
There was a problem hiding this comment.
the port_info{} dictionary represents the PORT table in CONFIG_DB. If laser frequency is NOT configured, then we move on with the module's default frequency.
There was a problem hiding this comment.
freq init value == 0 in this function. Does it mean when we see freq == 0, it will set module frequency to the default frequency? Can we test this feature with a ZR module by erasing the port's frequency config and see how the module will be configured.
There was a problem hiding this comment.
yes module comes with default frequency if not configured
|
|
||
| found, port_info = port_tbl.get(lport) | ||
| if found and 'tx_power' in dict(port_info): | ||
| power = dict(port_info)['tx_power'] |
There was a problem hiding this comment.
Similarly. What if found is True but no tx power is configured on the port. Should we enable a default power setting?
There was a problem hiding this comment.
The default is the module's default. This API gets the value explicitly configured by the user
There was a problem hiding this comment.
Similar to the previous comment, Can we test this feature with a ZR module by erasing the port's tx power config and see how the module will be configured.
There was a problem hiding this comment.
If tx power is not configured, module comes with module's default Tx power.
| if api.is_coherent_module(): | ||
| tx_power = self.port_dict[lport]['tx_power'] | ||
| # Prevent configuring same tx power multiple times | ||
| if 0 != tx_power and tx_power != api.get_tx_config_power(): |
There was a problem hiding this comment.
what does it mean when tx_power == 0?
There was a problem hiding this comment.
it means no 'tx_power' missing in the PORT table of CONFIG_DB. See get_configured_tx_power()
| freq = self.port_dict[lport]['laser_freq'] | ||
| # If user requested frequency is NOT the same as configured on the module | ||
| # force datapath re-initialization | ||
| if 0 != freq and freq != api.get_laser_config_freq(): |
There was a problem hiding this comment.
what does it mean when freq == 0?
There was a problem hiding this comment.
It means 'laser_freq' is missing in PORT table of CONFIG_DB. see get_configured_laser_freq()
There was a problem hiding this comment.
Understood. It means the no laser_freq is configured in config_db.
|
|
||
|
|
||
| @patch('xcvrd.xcvrd.XcvrTableHelper') | ||
| def test_CmisManagerTask_get_configured_freq(self, mock_table_helper): |
There was a problem hiding this comment.
Can we add failure case? For instance, 1. when config_freq is out of allowed freq range. 2. when config_freq does not fall on 75GHz grid.
There was a problem hiding this comment.
This API tests get_configured_laser_freq() which obtains the configured value from the PORT table of CONFIG_DB. Invalid frequency is validated here sonic-net/sonic-utilities#2197
There was a problem hiding this comment.
Am I looking at the correct place https://github.com/prgeor/sonic-utilities/blob/ba58d985b2483d24fb68821f11c6507dd08de567/scripts/portconfig#L337? seems like it's only validating the case when freq is <= 0? Does it verify the provisioned frequency is within the min and max advertised supported freq values?
| assert task.get_configured_laser_freq('Ethernet0') == 193100 | ||
|
|
||
| @patch('xcvrd.xcvrd.XcvrTableHelper') | ||
| def test_CmisManagerTask_get_configured_tx_power(self, mock_table_helper): |
There was a problem hiding this comment.
Similarly can we add failure case? 1. when configured tx power is out of range.
There was a problem hiding this comment.
This API simply get the configured tx_power from the CONFIG_DB. The user input for TX power is validated here sonic-net/sonic-utilities#2197. Please do note, tx_power can be configured even if transceiver is NOT plugged in, so we cannot validate tx_power in that case.
There was a problem hiding this comment.
Is this the right place that it validates tx power https://github.com/prgeor/sonic-utilities/blob/ba58d985b2483d24fb68821f11c6507dd08de567/scripts/portconfig#L332? Does it mean it only allows one digit after decimal point? Does it verify the configured tx power is within the min and max advertised supported tx power values?
| if api.is_coherent_module(): | ||
| tx_power = self.port_dict[lport]['tx_power'] | ||
| # Prevent configuring same tx power multiple times | ||
| if 0 != tx_power and tx_power != api.get_tx_config_power(): |
There was a problem hiding this comment.
this check helps preventing reprogramming during xcvrd restart?
There was a problem hiding this comment.
this check helps preventing reprogramming during xcvrd restart?
@jaganbal-a YES
| if 'tx_power' not in self.port_dict[lport]: | ||
| self.port_dict[lport]['tx_power'] = self.get_configured_tx_power(lport) | ||
| if 'laser_freq' not in self.port_dict[lport]: | ||
| self.port_dict[lport]['laser_freq'] = self.get_configured_laser_freq(lport) |
There was a problem hiding this comment.
I think get_configured_tx_power_from_dict() naming is appropriate as it reading from dict and not from the device. similar for get_configured_laser_freq().
There was a problem hiding this comment.
@jaganbal-a the configured frequency is read from the DB. see comment inside get_configured_tx_power()
There was a problem hiding this comment.
I see the get_configured_tx_power() read from DB, but the naming sounds like it read from the device.
So I would suggest the naming get_configured_tx_power_from_dict()
There was a problem hiding this comment.
@jaganbal-a please check latest changes
| self.port_dict[lport]['laser_freq'] = int(port_change_event.port_dict['laser_freq']) | ||
| if 'tx_power' in port_change_event.port_dict: | ||
| self.port_dict[lport]['tx_power'] = float(port_change_event.port_dict['tx_power']) | ||
|
|
There was a problem hiding this comment.
With CMIS state reset to INSERTED upon any event for the port, the coherent module will be read continuously for Tx power and frequency.
There was a problem hiding this comment.
port_dict[] is updated by reading the configuration values from the DB, not by reading the module
There was a problem hiding this comment.
It is not about port_dict[].
When the CMIS state is reset, the state changes to INSERTED. Once the CMIS state is INSERTED, the below piece of code executed continuously in the CMIS mgr task worker. api.get_tx_config_power() and api.get_laser_config_freq() query the device with that.
Configure the target output power if ZR module
if api.is_coherent_module():
tx_power = self.port_dict[lport]['tx_power']
# Prevent configuring same tx power multiple times
if 0 != tx_power and tx_power != api.get_tx_config_power():
There was a problem hiding this comment.
as discussed offline, this is not specific to tx_power or laser_freq. Currently don't have a subscription mechanism to listen only to the interested fields. This is the git issue to improve on this #259
There was a problem hiding this comment.
I agree and hopefully #259 converges soon.
Note: currently there is no overhead due to this issue. But with the this PR changes the optical module will be read for both freq and tx-power register offsets in continuous fashion.
|
ZR-log.txt |
|
@prgeor I checked the test log. For TX power configuration, we would not want data path to be reinitialized. It should be done when data path is always activated and tx is enabled. |
Can you please capture show interface transceiver eeprom -d for the interfaces having ZR with tx and freq configuration? |
jaganbal-a
left a comment
There was a problem hiding this comment.
Added response to the existing comments.
@qinchuanares can you point me to the CMIS reference where you find this requirement. Here is what I in section 7.5.2. There is no strict requirement to program TX power in datapath activated state. At CMIS_STATE_INSERTED, module is either in Low power mode or in High power mode. |
Added the log in the description. please check |
|
Frequency should be displayed as part of show int transceiver CLI. Please raise a git issue. |
0e31af1
Update sonic-platform-daemons submodule pointer to include the following: * Xcvrd changes to support 400G ZR configuration ([sonic-net#270](sonic-net/sonic-platform-daemons#270)) * [ycabled] add secure channel support for grpc dualtor active-active connectivity ([sonic-net#275](sonic-net/sonic-platform-daemons#275)) Signed-off-by: dprital <[email protected]>
* Xcvrd changes to support 400G ZR configuration * Fix test failures * Improve code coverage * Addressed review comments
…#270) Description The code that decodes the content of the ONIE syseeprom includes a flag to enable/disable displaying the content of the vendor extension TLV. This flag is currently set to 'disable'. Hence the 'show platform syseeprom' command shows the presence and size of the vendor extension TLV but does not show its content. This commit sets the flag to 'enable' so that the vendor extension TLV content is displayed. Motivation and Context The 'show platform syseeprom' command shows that the Vendor Extension TLV is present but does not show its content. Here's what that looks like on an example platform.

Description
400G ZR configuration support
Motivation and Context
400G ZR needs configuration changes for laser frequency and Tx target output power
How Has This Been Tested?
Xcvrd honors the configuration changes for both Tx power and laser frequency:
Configured frequency
Additional Information (Optional)