cfg::PortSpeed BcmPort::getSpeed() const { int curSpeed{0}; auto rv = opennsl_port_speed_get(unit_, port_, &curSpeed); bcmCheckError( rv, "Failed to get current speed for port ", port_); return cfg::PortSpeed(curSpeed); }
void BcmPort::setSpeed(const shared_ptr<Port>& swPort) { if (isEnabled()) { LOG(ERROR) << "Cannot set port speed while the port is enabled. Port: " << swPort->getName() << " id: " << swPort->getID(); return; } int ret; cfg::PortSpeed desiredPortSpeed; if (swPort->getSpeed() == cfg::PortSpeed::DEFAULT) { int speed; ret = opennsl_port_speed_max(unit_, port_, &speed); bcmCheckError(ret, "failed to get max speed for port", swPort->getID()); desiredPortSpeed = cfg::PortSpeed(speed); } else { desiredPortSpeed = swPort->getSpeed(); } opennsl_port_if_t desiredMode = getDesiredInterfaceMode(desiredPortSpeed, swPort->getID(), swPort->getName()); opennsl_port_if_t curMode; ret = opennsl_port_interface_get(unit_, port_, &curMode); bcmCheckError(ret, "Failed to get current interface setting for port ", swPort->getID()); bool updateSpeed = false; if (curMode != desiredMode) { ret = opennsl_port_interface_set(unit_, port_, desiredMode); bcmCheckError( ret, "failed to set interface type for port ", swPort->getID()); // Changes to the interface setting only seem to take effect on the next // call to opennsl_port_speed_set(). Therefore make sure we update the // speed below, even if the speed is already at the desired setting. updateSpeed = true; } int desiredSpeed = static_cast<int>(desiredPortSpeed); // Unnecessarily updating BCM port speed actually causes // the port to flap, even if this should be a noop, so check current // speed before making speed related changes. Doing so fixes // the interface flaps we were seeing during warm boots if (!updateSpeed && desiredMode != OPENNSL_PORT_IF_KR4) { int curSpeed; ret = opennsl_port_speed_get(unit_, port_, &curSpeed); bcmCheckError( ret, "Failed to get current speed for port ", swPort->getID()); updateSpeed |= (curSpeed != desiredSpeed); } if (updateSpeed) { if (desiredMode == OPENNSL_PORT_IF_KR4) { // We don't need to set speed when mode is KR4, since ports in KR4 mode // do autonegotiation to figure out the speed. setKR4Ability(); } else { ret = opennsl_port_speed_set(unit_, port_, desiredSpeed); bcmCheckError(ret, "failed to set speed, ", desiredSpeed, ", to port ", swPort->getID()); } } }