| /* |
| * Copyright 2018-present Open Networking Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.onosproject.drivers.barefoot.pro; |
| |
| import org.apache.thrift.TException; |
| import org.apache.thrift.protocol.TBinaryProtocol; |
| import org.apache.thrift.protocol.TMultiplexedProtocol; |
| import org.apache.thrift.protocol.TProtocol; |
| import org.apache.thrift.transport.TSocket; |
| import org.apache.thrift.transport.TTransport; |
| import org.onosproject.drivers.barefoot.pro.pal.pal; |
| import org.onosproject.drivers.barefoot.pro.pal.pal_autoneg_policy_t; |
| import org.onosproject.drivers.barefoot.pro.pal.pal_fec_type_t; |
| import org.onosproject.drivers.barefoot.pro.pal.pal_port_speed_t; |
| import org.onosproject.incubator.net.config.basics.PortDescriptionsConfig; |
| import org.onosproject.net.Device; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.config.NetworkConfigService; |
| import org.onosproject.net.device.PortDescription; |
| import org.onosproject.provider.general.device.api.GeneralProviderDeviceConfig; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.List; |
| import java.util.Map; |
| |
| import static java.lang.Boolean.parseBoolean; |
| |
| /** |
| * Class to configure ports on Tofino. |
| */ |
| final class TofinoPortConfigurator { |
| |
| private final Logger log = LoggerFactory.getLogger(getClass()); |
| |
| private static final String P4RUNTIME = "p4runtime"; |
| private static final String PROTOCOL_KEY_IP = "ip"; |
| private static final String DEVICE_ID = "deviceId"; |
| private static final String AUTONEG = "autoneg"; |
| private static final int PAL_MGMT_PORT = 9090; |
| private static final String PAL_THRIFT_SERVICE = "pal"; |
| |
| private static final pal_fec_type_t DEFAULT_FEC_TYPE = |
| pal_fec_type_t.BF_FEC_TYP_NONE; |
| |
| private final NetworkConfigService netcfgService; |
| |
| TofinoPortConfigurator(NetworkConfigService netcfgService) { |
| this.netcfgService = netcfgService; |
| } |
| |
| // FIXME Currently use thrift, may use gNMI to manage it in the future. |
| public void setupPorts(DeviceId deviceId) { |
| GeneralProviderDeviceConfig providerConfig = netcfgService |
| .getConfig(deviceId, GeneralProviderDeviceConfig.class); |
| PortDescriptionsConfig portConfig = netcfgService |
| .getConfig(deviceId, PortDescriptionsConfig.class); |
| |
| Map<String, String> values = providerConfig.protocolsInfo() |
| .get(P4RUNTIME).configValues(); |
| |
| String ip = values.get(PROTOCOL_KEY_IP); |
| byte tofinoDeviceId = Byte.parseByte(values.get(DEVICE_ID)); |
| |
| List<PortDescription> ports = portConfig.portDescriptions(); |
| |
| if (ports == null) { |
| log.warn("Empty port configuration for {}, won't add any port", deviceId); |
| return; |
| } |
| |
| ports.forEach(port -> { |
| pal_port_speed_t speed = getPortSpeed(port.portSpeed()); |
| String anString = port.annotations().value(AUTONEG); |
| pal_autoneg_policy_t an = anString != null && parseBoolean(anString) |
| ? pal_autoneg_policy_t.BF_AN_FORCE_ENABLE |
| : pal_autoneg_policy_t.BF_AN_FORCE_DISABLE; |
| addAndEnablePort(deviceId, port.portNumber().name(), |
| ip, tofinoDeviceId, |
| (int) port.portNumber().toLong(), speed, |
| DEFAULT_FEC_TYPE, an); |
| }); |
| } |
| |
| private pal_port_speed_t getPortSpeed(long speed) { |
| // Mbps -> BF_SPEED (1G~100G) |
| speed = speed / 1000; |
| |
| if (speed >= 100) { |
| return pal_port_speed_t.BF_SPEED_100G; |
| } |
| if (speed >= 50) { |
| return pal_port_speed_t.BF_SPEED_50G; |
| } |
| if (speed >= 40) { |
| return pal_port_speed_t.BF_SPEED_40G; |
| } |
| if (speed >= 25) { |
| return pal_port_speed_t.BF_SPEED_25G; |
| } |
| if (speed >= 10) { |
| return pal_port_speed_t.BF_SPEED_10G; |
| } |
| |
| return pal_port_speed_t.BF_SPEED_1G; |
| } |
| |
| private void addAndEnablePort(DeviceId deviceId, String portName, String ip, |
| byte tofinoDeviceId, |
| int dp, pal_port_speed_t speed, |
| pal_fec_type_t fec, |
| pal_autoneg_policy_t an) { |
| log.info("Adding port {} to {}: dp={}, speed={}, an={}, fec={}", |
| portName, deviceId, dp, speed.name(), an.name(), fec.name()); |
| |
| TTransport transport = new TSocket(ip, PAL_MGMT_PORT); |
| try { |
| transport.open(); |
| TProtocol protocol = new TBinaryProtocol(transport); |
| TMultiplexedProtocol mProtocol = new TMultiplexedProtocol( |
| protocol, PAL_THRIFT_SERVICE); |
| pal.Client client = new pal.Client(mProtocol); |
| client.pal_port_add(tofinoDeviceId, dp, speed, fec); |
| client.pal_port_an_set(tofinoDeviceId, dp, an); |
| client.pal_port_enable(tofinoDeviceId, dp); |
| } catch (TException x) { |
| log.error("Error adding port {} to device {}:\n{}", |
| dp, tofinoDeviceId, ip, x); |
| } finally { |
| if (transport.isOpen()) { |
| transport.close(); |
| } |
| } |
| } |
| } |