Implement data-driven YAML switch/port/vlan configuration
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing

Implemented extra missing fields, added VPD hash match

Add extra configuration required for external port tagging, maybe do it via config
This commit is contained in:
DataHoarder 2021-11-10 19:32:29 +01:00
parent 51bf50076b
commit 704df5b09d
18 changed files with 1541 additions and 251 deletions

View file

@ -18,6 +18,6 @@ steps:
commands:
- apt update
- DEBIAN_FRONTEND=noninteractive apt install -y clang cmake autoconf automake libtool-bin
- ./build-ies.sh
- ./build-deps.sh
- ./build.sh
...

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
/cmake-build-debug
/cmake-build-*
/build
.idea
/deps/IES/build

9
.gitmodules vendored
View file

@ -1,3 +1,12 @@
[submodule "deps/IES"]
path = deps/IES
url = https://git.gammaspectra.live/FM10K/IES
[submodule "deps/argparse"]
path = deps/argparse
url = https://github.com/p-ranav/argparse
[submodule "deps/rapidyaml"]
path = deps/rapidyaml
url = https://github.com/biojppm/rapidyaml
[submodule "deps/sha2"]
path = deps/sha2
url = https://github.com/ogay/sha2.git

View file

@ -1,29 +1,44 @@
cmake_minimum_required(VERSION 3.13)
project(fsm)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions -frtti -D_FM_ARCH_64 -DFM_SUPPORT_FM10000 -D_GNU_SOURCE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -frtti -D_FM_ARCH_64 -DFM_SUPPORT_FM10000 -D_GNU_SOURCE")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions -fPIC -frtti -D_FM_ARCH_64 -DFM_SUPPORT_FM10000 -D_GNU_SOURCE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -fPIC -frtti -D_FM_ARCH_64 -DFM_SUPPORT_FM10000 -D_GNU_SOURCE")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG")
set(CMAKE_LD_FLAGS "${CMAKE_LD_FLAGS} -Wl,--no-as-needed")
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
include_directories(src)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
include_directories(deps/IES/build/include)
include_directories(deps/IES/build/include/alos)
include_directories(deps/IES/build/include/alos/linux)
include_directories(deps/IES/build/include/std/intel)
include_directories(deps/IES/build/include/common)
include_directories(deps/IES/build/include/platforms)
include_directories(deps/IES/build/include/platforms/libertyTrail)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
include_directories(src)
find_library(libFocalpointSDK NAMES FocalpointSDK PATHS ${PROJECT_SOURCE_DIR}/deps/IES/build/lib NO_DEFAULT_PATH REQUIRED)
find_library(libLTStdPlatform NAMES LTStdPlatform PATHS ${PROJECT_SOURCE_DIR}/deps/IES/build/lib NO_DEFAULT_PATH REQUIRED)
find_library(libryml NAMES ryml PATHS ${PROJECT_SOURCE_DIR}/deps/rapidyaml/install/lib NO_DEFAULT_PATH REQUIRED)
add_executable(fsmd src/fsmd.cpp src/device/PCIEDevice.cpp src/fm10k/FM10K.cpp src/fm10k/Functions.cpp src/fm10k/Port.cpp src/fm10k/IES.cpp)
add_executable(fsmd src/fsmd.cpp deps/sha2/sha2.c src/device/PCIEDevice.cpp src/fm10k/FM10K.cpp src/fm10k/Functions.cpp src/fm10k/Port.cpp src/fm10k/IES.cpp)
add_executable(fsm src/fsm.cpp)
target_link_libraries(fsmd ${libFocalpointSDK} ${libLTStdPlatform} dl)
target_include_directories(fsmd PUBLIC
deps/IES/build/include
deps/IES/build/include/alos
deps/IES/build/include/alos/linux
deps/IES/build/include/std/intel
deps/IES/build/include/common
deps/IES/build/include/platforms
deps/IES/build/include/platforms/libertyTrail
deps/sha2
deps/rapidyaml/install/include
deps/argparse/include
)
target_link_options(fsmd PRIVATE -static-libgcc -static-libstdc++ "LINKER:--as-needed")
target_link_libraries(fsmd "${libryml}" "${libFocalpointSDK}" "${libLTStdPlatform}" dl)

42
build-deps.sh Executable file
View file

@ -0,0 +1,42 @@
#!/bin/bash
set -ex
pushd "${0%/*}"
export CC=clang
export CXX=clang++
pushd deps
pushd IES
if [[ -d "build" ]]; then
rm -r build
fi
mkdir build
if command -v git &> /dev/null; then
git clean -f -d -x
fi
export CFLAGS="-ggdb -O0"
export CXXFLAGS="-ggdb -O0"
./autogen.sh
./configure --enable-shared --prefix "$(pwd)/build"
make clean
make -j$(nproc)
make install
popd
pushd rapidyaml
if [[ -d "build" ]]; then
rm -r build
fi
if [[ -d "install" ]]; then
rm -r install
fi
mkdir build
mkdir install
pushd build
export CFLAGS="-D_GNU_SOURCE -ggdb -O2"
export CXXFLAGS="-D_GNU_SOURCE -ggdb -O2"
cmake .. -DRYML_BUILD_TESTS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_INSTALL_PREFIX="$(pwd)/../install"
make -j$(nproc)
make install

View file

@ -1,20 +0,0 @@
#!/bin/bash
set -ex
pushd "${0%/*}"
pushd deps/IES
if [[ -d "build" ]]; then
rm -r build
fi
mkdir build
export CC=clang
export CXX=clang++
export CFLAGS="-ggdb -O0"
export CXXFLAGS="-ggdb -O0"
git clean -f -d -x
./autogen.sh
./configure --enable-shared --prefix "$(pwd)/build"
make clean
make -j$(nproc)
make install

288
config.example.yml Normal file
View file

@ -0,0 +1,288 @@
platform:
# Device to match configuration against. Program will exit if model does not match
device: "FM10840_B0"
# Device VPD hash to match against. Use this when multiple FM10K with different serial numbers exist on system.
#device_vpd_hash: "d3effea257d1348331a212d60d0b96ec1225c69a93c7e9fa1689b7f445c7d489"
#device_vpd_hash: "f67978856fa13d7e2ce4f0af8971bfbe633447f91ca5791ec5add3c6860fc70d"
configuration:
# A preset to use, if any
preset: "FM10840_B0_2x100G"
#preset: "FM10840_B0_8x25G"
# Extra configuration entries (or whole file) follow here in order
entries:
# Required to have working VLAN tagging (802.1Q)
- ["api.port.allowFtagVlanTagging", "bool", "true"]
#- ["api.platform.config.debug", "text", "CONFIG,MOD_STATE,MOD_LED,MOD_INTR,MOD_TYPE,PLAT_LOG"]
#- ["api.platform.lib.config.debug", "text", "I2C_RW,I2C_MUX,PORT_LED"]
#- ["api.platform.config.switch.0.portIndex.1.ethernetMode", "text", "40GBase-SR4"]
#- ["api.platform.config.switch.0.portIndex.2.ethernetMode", "text", "40GBase-SR4"]
# Override 100G ports to 10G
#- ["api.platform.config.switch.0.portIndex.1.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.2.ethernetMode", "text", "10GBase-SR"]
# Override 25G ports to 10G
#- ["api.platform.config.switch.0.portIndex.1.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.2.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.3.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.4.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.5.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.6.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.7.ethernetMode", "text", "10GBase-SR"]
#- ["api.platform.config.switch.0.portIndex.8.ethernetMode", "text", "10GBase-SR"]
switch:
attributes:
# Frame timeout in milliseconds. see FM_FRAME_AGING_TIME_MSEC
#frame_aging_milliseconds:
# Specifies which logical port to redirect CPU traffic to.
# The logical port can be a physical port or a LAG port.
# FM_REDIRECT_CPU_TRAFFIC
# Defaults to api.platform.config.switch.0.cpuPort
#cpu_port:
# shared (default), per_vlan, multiple (not supported?)
stp_mode: shared
lag:
# static (default, static groups, discard), dynamic (pass to application)
#mode: static
#pruning: true
vlan_learning:
# VLAN learning mode. Values: independent (default), shared
mode: independent
# The VLAN to learn on when mode is shared (default 1)
vlan: 1
trap:
# The 48-bit CPU MAC address (default: 0x000000000000).
# Frames received by the switch with this destination MAC address will
# be automatically trapped to the CPU.
cpu_mac: 0x000000000000
8021x: true
bpdu: true
lacp: true
garp: true
# This trap is only valid for routed frames.
mtu_violation: true
# Broadcast flooding control. Values: forward, discard, forward_without_cpu (default), per_port
broadcast_flooding: forward
# Flood all multicast frames for which the multicast address is unknown on lookup to all ports including the CPU.
# Note that the CPU will only receive unknown multicast frames on VLANs for which the CPU port is a member.
# Multicast flooding control. Values: forward, discard, forward_without_cpu (default), per_port
multicast_flooding: forward
# Flood all unicast frames for which the destination address is unknown on lookup.
# Note that the CPU will only receive unknown unicast frames on VLANs for which the CPU port is a member.
# Unicast flooding control. Values: forward, discard, forward_without_cpu (default), per_port
unicast_flooding: forward
# Must create vlans so they exist
vlans:
-
id: 1
attributes:
# If enabled, then a frame may be sent out the VLAN it came in on.
# On FM10000 devices, disabling reflection on a VLAN disables switching
# frames on this VLAN between Virtual Functions on the same PCIe port.
reflect: true
# A VLAN must have this attribute enabled in order for traffic ingressing on the VLAN to be routed.
# When this attribute is disabled, ingressing traffic will only be switched at layer 2.
# Default false
routable: false
-
id: 2
attributes:
reflect: true
routable: false
# Definitions here share keys. First default, eth, pcie, special, cpu entries are applied, then specific port numbers
ports:
-
# Default port definitions, except internal
port: default
attributes:
tagging:
# Selects the port tagging mode for this port. Values (see fm_portTaggingMode struct): 8021q (default), 8021ad_customer, 8021ad_provider, pseudo1, pseudo2
mode: 8021q
# The port's default VLAN. Tagging rules still apply from VLAN definition. The default value is 1.
vid: 1
# The port's default priority (0 - 7). The default value is 0.
priority: 0
# The port's default second VLAN. The default value is 1.
#vid2: 1
# The port's default second priority (0 - 7). The default value is 0.
#priority2: 0
# Whether the ingress VLAN-tagged frame's VLAN fields should be replaced with the port's default VLAN fields,
# as specified by the ''tagging.vid'', ''tagging.priority'', and ''tagging.cfi'' attributes. Default false
#
# Note that this attribute does not affect the selection of the internal switch priority of the frame (in the case of SWPRI being chosen from VLAN priority),
# as SWPRI is chosen before the port's default VLAN values are applied. See ''FM_PORT_SWPRI_SOURCE'' and ''FM_PORT_SWPRI_DSCP_PREF'' for details on the selection of SWPRI.
replace: false
# The port's default CFI (0 - 1). The default value is 0.
# Also known as Drop eligible indicator (DEI). May be used separately or in conjunction with PCP to indicate frames eligible to be dropped in the presence of congestion.
cfi: 0
# The port's default DSCP (0 - 63). Default value is 0.
dscp: 0
# Defines the type of ISL tag (if any) present on frames ingressing on this port.
# On FM10000, this attribute supports f56 or none (default) on Ethernet ports, but only none is supported for PCIe and TE ports.
# Values: none, f56
#isl_format:
# The port's default internal switch priority (0 - 15). Default value is 0.
switch_priority: 0
drop:
# Dropping frames that incur an ingress VLAN boundary violation. Default false
boundary_violation: false
# Dropping of untagged frames on ingress. Default false. See notes for FM_PORT_DROP_UNTAGGED
untagged: false
# Dropping of tagged frames on ingress. Default false. See notes for FM_PORT_DROP_TAGGED
tagged: false
loopback:
# Internal loopback control. Frames emitted from the switch fabric towards an egress port are processed all the way
# through the Ethernet port logic, then looped back from transmit to receive at the SerDes level, complete with preamble and IFG.
# Can only be set on eth ports. Values: off (default), tx2rx, rx2tx
mode: off
# Whether frames emitted out of the switch fabric toward an egress port are instead looped back into the fabric.
# Since such frames do not touch the Ethernet port logic of the chip, they will not have a preamble, nor do they invoke an IFG.
# The associated port logic will be put in a standby mode so that any frames received at the port will not enter the switch fabric.
# Values: off (default), tx2rx, rx2tx
fabric: off
# Indicates whether loopback suppression is enabled or disabled for a port.
# Value is either true (default) or false (default for TE ports).
# Note that this attribute has no effect when a port is a member of a link aggregation group.
#suppression: true
parser:
# How far in OSI model packets are parsed before stopping.
# l2 (default)
# l3 - Set to this value to enable any L3 features, such as IGMP snooping, routing, IGMP storm control and L3 ACLs.
# l4 - Set FM_PORT_PARSER to this value to enable L4 ACLs (default for TE ports), in addition to L3 features.
# all
mode: l2
# When two VLAN tags are present and identical in a packet, then this attribute defines which one is considered as first.
# Setting to false (default) makes VLAN1 first, VLAN2 second.
#first_vlan2: false
# Whether VID2 (VLAN ID in the second VLAN tag) is sent before VID1 (VLAN ID in the first VLAN tag) or after VID1.
# Setting to true sends the VID2 first, then VID1 second.
# Setting to false (default) sends the VID1 first, VID2 second.
#first_vid2: false
# A port must have this attribute enabled in order for traffic ingressing on the port to be routed.
# When this attribute is disabled, ingressing traffic will only be switched at layer 2.
routable: false
# Egress updating of fields
update:
# Defines whether the port should decrement the TTL field on outgoing routed frames. Default true
#ttl: true
# Defines whether the port may modify the DSCP field on outgoing routed frames. Default true
#dscp: true
# Defines whether the port should modify the VLAN priority field on egress. Default false
#vlan_priority: false
# Defines whether the port should modify the VLAN2 priority field on egress. Default false
#vlan2_priority: false
# A bit mask indicating the fields that will be updated on a routed frame.
# The mask consists of the OR of any of the following fields: DMAC, SMAC, VLAN
# Default is [DMAC, SMAC, VLAN]
routed: [DMAC, SMAC, VLAN]
broadcast:
# Whether a port is to prune flooded broadcast frames
#pruning: false
# Flooding control for per_port switch value. Values: forward_without_cpu, trap, forward, discard
#flooding: forward_without_cpu
multicast:
# Whether a port is to prune flooded broadcast frames
#pruning: false
# Flooding control for per_port switch value. Values: forward_without_cpu, trap, forward, discard
#flooding: forward_without_cpu
unicast:
# Whether a port is to prune flooded broadcast frames
#pruning: false
# Flooding control for per_port switch value. Values: forward_without_cpu, trap, forward, discard
#flooding: forward_without_cpu
# Indicates whether the port is an internal port in a multi-switch environment (port connects the switch to another switch).
# Value is either FM_ENABLED or FM_DISABLED (default).
# On FM10000, this attribute is always FM_DISABLED for PCIe ports and FM_ENABLED for TE ports.
#internal: false
vlans:
-
id: 1
# Tag egressing frames or not with ISL tag format, or VLAN other tagging mode defined, default false
tag: false
# Values: disabled, listening, learning, forwarding, blocking
stp: forwarding
-
id: 2
tag: true
stp: forwarding
-
# Default PCIe port definitions
port: pcie
attributes:
-
# Default port definitions
port: [special, eth, cpu]
attributes:
# Learning of source addresses on this port: true (default) or false (default for PEP and TE ports).
# Note: This attribute must be enabled for the address table security features to apply to frames received on the port.
learning: true
-
# Default epl/ETH port definitions
port: eth
attributes:
# Maximum frame size in bytes, ranging from 0 to 15360 for FM10000
# For FM10000, default value for an Ethernet port is 1536 and PCIE port is 15360.
# Note that a specified value will be rounded up to the nearest multiple of 4.
#
# In FM10000, frame size is computed from DMAC till the end of FCS.
# Hence the maximum frame size is actually MTU plus size of L2 header and FCS.
# E.g., if the non-vlan tagged netdev interface (of PCIE) on the host has MTU 15342,
# then the corresponding Max Frame Size is 15342 + 14 (L2 header) + 4 (FCS) = 15360.
max_frame_size: 9036
-
# CPU port definitions
port: cpu
attributes:
-
# Port 1 definitions. As defined on platform configuration. This should be one of the QSFP (#1?) ports
port: 1
attributes:
# The N-bit egress port mask to use when this port is the ingress port.
# A one bit in the mask indicates that frames from this port can be forwarded to the port represented by the bit.
# Each bit position corresponds to the logical port number of the egress port.
# To allow, for example, ports 0, 1, 2, 3 to communicate here, use either raw mask value (0xf) or list form [0, 1, 2, 3]. -1 to allow all known but self
#mask: -1

1
deps/argparse vendored Submodule

@ -0,0 +1 @@
Subproject commit b9583b42ab64aa6b985997fa88d1834d6de03a31

1
deps/rapidyaml vendored Submodule

@ -0,0 +1 @@
Subproject commit 6993a7c56f4d064997a4df63fc16380ef6381d68

1
deps/sha2 vendored Submodule

@ -0,0 +1 @@
Subproject commit 79116b5d5d449311c27a24e16c99d8bccb4d1301

View file

@ -7,6 +7,7 @@
#include <sstream>
#include "PCIEDevice.h"
#include "fm10k/FM10K.h"
#include "sha2.h"
std::vector<uint8_t> get_file_contents(const std::string& path){
std::ifstream file;
@ -89,6 +90,25 @@ std::vector<PCIEDevice::DeviceEntry> PCIEDevice::DeviceEntry::find() {
return entries;
}
std::string PCIEDevice::DeviceEntry::getVPDHash() const {
static char syms[] = "0123456789abcdef";
unsigned char digest[SHA256_DIGEST_SIZE];
memset(digest,0, sizeof(digest));
std::string data;
data.resize(SHA256_DIGEST_SIZE * 2);
auto& vpd = getVPD().get("Product Name");
sha256(vpd.data(), vpd.size(), digest);
for(auto i = 0; i < SHA256_DIGEST_SIZE; ++i){
data[i * 2] = syms[(digest[i] >> 4) & 0xf];
data[i * 2 + 1] = syms[digest[i] & 0xf];
}
return data;
}
PCIEDevice::PCIEDevice(const PCIEDevice::DeviceEntry& device) : m_device (device){
m_bar4Resource = open(m_device.getPath().c_str(), O_RDWR);
if(m_bar4Resource <= 0){
@ -196,6 +216,11 @@ void PCIEDevice::VitalProductData::fillFromEntry(const std::vector<uint8_t> &v,
m_vpd.emplace(std::move(keyword), std::move(data));
}
const std::vector<uint8_t>& PCIEDevice::VitalProductData::get(const std::string &key) const {
static std::vector<uint8_t> NOT_FOUND;
return m_vpd.find(key) != m_vpd.end() ? m_vpd.at(key) : NOT_FOUND;
}
PCIEDevice::VitalProductData::ResourceType::ResourceType(const std::vector<uint8_t>& s, size_t& offset) {
uint8_t h = s[offset++];

View file

@ -38,6 +38,7 @@ public:
explicit VitalProductData(const std::vector<uint8_t>& s);
const std::vector<uint8_t>& get(const std::string& key) const;
private:
void fillFromEntry(const std::vector<uint8_t>& v, size_t& offset);
@ -71,6 +72,8 @@ public:
return m_vpd;
}
std::string getVPDHash() const;
uint16_t getVendor() const{
return m_vendor;
}

View file

@ -4,6 +4,10 @@
#include "device/PCIEDevice.h"
#include <chrono>
#include <thread>
#include <iostream>
#include "ryml.hpp"
#include "c4/std/string.hpp"
#include "IES_SDK.h"
FM10K::FM10K::FM10K(std::unique_ptr<Device> device) : m_device(std::move(device)) {
@ -276,10 +280,188 @@ void FM10K::FM10K::wait_ns(uint32_t nanoseconds) {
std::this_thread::sleep_for(std::chrono::nanoseconds (nanoseconds));
}
bool FM10K::FM10K::initialize() const {
std::string getYAMLString(c4::yml::NodeRef ref, const std::string& def = ""){
if(ref.valid() && !ref.is_seed() && ref.has_val()){
std::string s;
c4::from_chars(ref.val(), &s);
return s;
}
return def;
}
int32_t getYAMLInteger(c4::yml::NodeRef ref, int32_t def = 0){
if(ref.valid() && !ref.is_seed() && ref.has_val() && ref.val().is_integer()){
int32_t s;
if(atoi_first(ref.val(), &s)){
return s;
}
}
return def;
}
int64_t getYAMLInteger64(c4::yml::NodeRef ref, int64_t def = 0){
if(ref.valid() && !ref.is_seed() && ref.has_val() && ref.val().is_integer()){
int64_t s;
if(atoi_first(ref.val(), &s)){
return s;
}
}
return def;
}
uint32_t getYAMLUnsignedInteger(c4::yml::NodeRef ref, uint32_t def = 0){
if(ref.valid() && !ref.is_seed() && ref.has_val() && ref.val().is_integer()){
uint32_t s;
if(atou_first(ref.val(), &s)){
return s;
}
}
return def;
}
uint64_t getYAMLUnsignedInteger64(c4::yml::NodeRef ref, uint64_t def = 0){
if(ref.valid() && !ref.is_seed() && ref.has_val() && ref.val().is_integer()){
uint64_t s;
if(atou_first(ref.val(), &s)){
return s;
}
}
return def;
}
bool getYAMLBool(c4::yml::NodeRef ref, bool def = false){
if(ref.valid() && !ref.is_seed() && ref.has_val()){
if(ref.val() == "true"){
return true;
} else if(ref.val() == "false"){
return false;
}
}
return def;
}
static std::unordered_map<std::string, fm_int> STP_STATE_MAP = {
{"disabled", FM_STP_STATE_DISABLED},
{"listening", FM_STP_STATE_LISTENING},
{"learning", FM_STP_STATE_LEARNING},
{"forwarding", FM_STP_STATE_FORWARDING},
{"blocking", FM_STP_STATE_BLOCKING},
};
static std::unordered_map<std::string, fm_int> TAGGING_MODE_MAP = {
{"8021q", FM_PORT_TAGGING_8021Q},
{"8021ad_customer", FM_PORT_TAGGING_8021AD_CUST},
{"8021ad_provider", FM_PORT_TAGGING_8021AD_PROV},
{"pseudo1", FM_PORT_TAGGING_PSEUDO1},
{"pseudo2", FM_PORT_TAGGING_PSEUDO2},
};
static std::unordered_map<std::string, fm_int> ISL_FORMAT_MAP = {
{"none", FM_ISL_TAG_NONE},
{"f32", FM_ISL_TAG_F32},
{"f56", FM_ISL_TAG_F56},
{"f64", FM_ISL_TAG_F64},
{"f96", FM_ISL_TAG_F96},
{"other_32", FM_ISL_TAG_OTHER_32B},
{"other_64", FM_ISL_TAG_OTHER_64B},
{"other_96", FM_ISL_TAG_OTHER_96B},
};
static std::unordered_map<std::string, fm_int> LOOPBACK_MODE_MAP = {
{"off", FM_PORT_LOOPBACK_OFF},
{"rx2tx", FM_PORT_LOOPBACK_RX2TX},
{"tx2rx", FM_PORT_LOOPBACK_TX2RX},
};
static std::unordered_map<std::string, fm_int> PARSER_MODE_MAP = {
{"l2", FM_PORT_PARSER_STOP_AFTER_L2},
{"l3", FM_PORT_PARSER_STOP_AFTER_L3},
{"l4", FM_PORT_PARSER_STOP_AFTER_L4},
{"all", FM_PORT_PARSER_PARSE_ALL},
};
static std::unordered_map<std::string, fm_int> BFLOOD_MODE_MAP = {
{"forward_without_cpu", FM_PORT_BCAST_FWD_EXCPU},
{"forward", FM_PORT_BCAST_FWD},
{"discard", FM_PORT_BCAST_DISCARD},
{"trap", FM_PORT_BCAST_TRAP},
};
static std::unordered_map<std::string, fm_int> MFLOOD_MODE_MAP = {
{"forward_without_cpu", FM_PORT_MCAST_FWD_EXCPU},
{"forward", FM_PORT_MCAST_FWD},
{"discard", FM_PORT_MCAST_DISCARD},
{"trap", FM_PORT_MCAST_TRAP},
};
static std::unordered_map<std::string, fm_int> UFLOOD_MODE_MAP = {
{"forward_without_cpu", FM_PORT_UCAST_FWD_EXCPU},
{"forward", FM_PORT_UCAST_FWD},
{"discard", FM_PORT_UCAST_DISCARD},
{"trap", FM_PORT_UCAST_TRAP},
};
static std::unordered_map<std::string, fm_int> VLAN_LEARNING_MODE = {
{"independent", FM_VLAN_LEARNING_MODE_INDEPENDENT},
{"shared", FM_VLAN_LEARNING_MODE_SHARED}
};
static std::unordered_map<std::string, fm_int> STP_MODE = {
{"shared", FM_SPANNING_TREE_SHARED},
{"per_vlan", FM_SPANNING_TREE_PER_VLAN},
{"multiple", FM_SPANNING_TREE_MULTIPLE},
};
static std::unordered_map<std::string, fm_int> LAG_MODE = {
{"static", FM_MODE_STATIC},
{"dynamic", FM_MODE_DYNAMIC},
};
fm_int getMapState(const std::string& k, const std::unordered_map<std::string, fm_int>& m){
assert(m.find(k) != m.end());
return m.at(k);
}
bool FM10K::FM10K::initialize(const ryml::Tree& tree) const {
auto& ies = IES::getInstance();
if(!ies.loadKnownConfiguration(getHardwareInformationString() + "_AUTO_100G")){
return false;
auto root = tree.rootref();
if(!root["platform"].is_seed() && root["platform"].is_map()){
if(!root["platform"]["configuration"]["preset"].is_seed()){
auto conf = getYAMLString(root["platform"]["configuration"]["preset"]);
std::cout << "Loading know configuration " << conf << std::endl;
if(!ies.loadKnownConfiguration(conf)){
return false;
}
}
if(!root["platform"]["configuration"]["entries"].is_seed() && root["platform"]["configuration"]["entries"].is_seq()){
for(auto e : root["platform"]["configuration"]["entries"]){
if(e.is_seq() && e.num_children() == 3){ //Conf mapping
auto key = getYAMLString(e[0]);
auto type = e[1];
auto value = getYAMLString(e[2]);
if(type == "text"){
ies.replaceConfigEntry(key, IES::TlvType::Text, value);
}else if(type == "int"){
ies.replaceConfigEntry(key, IES::TlvType::Integer, value);
}else if(type == "bool"){
ies.replaceConfigEntry(key, IES::TlvType::Boolean, value);
}else if(type == "null"){
ies.replaceConfigEntry(key, IES::TlvType::Null, value);
}else{
std::abort();
}
}
}
}
}
auto pcieDevice = dynamic_cast<PCIEDevice*>(m_device.get());
@ -295,5 +477,357 @@ bool FM10K::FM10K::initialize() const {
//ies.addConfigEntry("api.platform.lib.config.debug", IES::TlvType::Text, "I2C_RW,I2C_MUX,DUMP_CFG");
//ies.addConfigEntry("api.debug.initLoggingCategories", IES::TlvType::Text, "FM_LOG_CAT_LOGGING|FM_LOG_CAT_LINK_STATE|FM_LOG_CAT_ALOS|FM_LOG_CAT_DEBUG|FM_LOG_CAT_PHY|FM_LOG_CAT_PLATFORM|FM_LOG_CAT_EVENT|FM_LOG_CAT_SWITCH|FM_LOG_CAT_MAILBOX|FM_LOG_CAT_PORT|FM_LOG_CAT_SERDES|FM_LOG_CAT_EVENT_INTR|FM_LOG_CAT_STATE_MACHINE|FM_LOG_CAT_GENERAL|FM_LOG_CAT_API|FM_LOG_CAT_PORT_AUTONEG");
return ies.init();
if(ies.init()){
if(!root["vlans"].is_seed() && root["vlans"].is_seq()){
for(auto vlan : root["vlans"]){
if(!vlan.is_map()){
std::abort();
}
auto vid = getYAMLUnsignedInteger(vlan["id"], 0xFFFF);
if(vid == 0xFFFF){
std::abort();
}
std::cout << "Creating VLAN " << vid;
ies.fmCreateVlan(vid);
if(!vlan["attributes"].is_seed() && vlan["attributes"].is_map()){
for(auto attr : vlan["attributes"]){
std::string key;
c4::from_chars(attr.key(), &key);
if(key == "reflect"){
auto val = getYAMLBool(attr, true);
std::cout << " " << key << " = " << (val ? "true" : "false");
ies.fmSetVlanAttribute(vid, FM_VLAN_REFLECT, val);
}else if(key == "routable"){
auto val = getYAMLBool(attr, true);
std::cout << " " << key << " = " << (val ? "true" : "false");
ies.fmSetVlanAttribute(vid, FM_VLAN_ROUTABLE, val);
}
}
}
std::cout << std::endl;
}
}
if(!root["ports"].is_seed() && root["ports"].is_seq()){
auto ports = root["ports"];
auto applyPortSettings = [&ies](c4::yml::NodeRef portEntry, int logicalPort, int physicalPort, int cpi, bool isInternalPort, bool isPCIePort, bool isSpecialPort, bool isEplPort, bool isCpuPort){
if(!portEntry["internal"].is_seed()){
ies.fmSetPortAttribute(logicalPort, FM_PORT_INTERNAL, getYAMLBool(portEntry["internal"], false));
}
if(!portEntry["vlans"].is_seed() && portEntry["vlans"].is_seq()){
for (auto portVlan : portEntry["vlans"]) {
auto vid = getYAMLUnsignedInteger(portVlan["id"], 0xFFFF);
if(vid == 0xFFFF){
std::abort();
}
std::cout << "Add port " << logicalPort << " to vlan " << vid << std::endl;
ies.fmAddVlanPort(vid, logicalPort, getYAMLBool(portVlan["tag"], true));
ies.fmSetVlanPortState(vid, logicalPort, getMapState(getYAMLString(portVlan["stp"], "forwarding"), STP_STATE_MAP));
}
}
if(!portEntry["attributes"].is_seed() && portEntry["attributes"].is_map()){
for (auto attr : portEntry["attributes"]) {
std::string key;
c4::from_chars(attr.key(), &key);
if(key == "learning"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_LEARNING, getYAMLBool(attr, !(isPCIePort || isSpecialPort)));
}else if(key == "learning"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_MAX_FRAME_SIZE, getYAMLUnsignedInteger(attr, FM10000_PCIE_MAX_FRAME_SIZE));
}else if(key == "switch_priority"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DEF_SWPRI, getYAMLUnsignedInteger(attr, 0));
}else if(key == "routable"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_ROUTABLE, getYAMLBool(attr, isSpecialPort));
}else if (key == "tagging" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "mode"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_TAGGING_MODE, getMapState(getYAMLString(attr2), TAGGING_MODE_MAP));
}else if(key2 == "vid"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DEF_VLAN, getYAMLUnsignedInteger(attr2, 1));
}else if(key2 == "priority"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DEF_PRI, getYAMLUnsignedInteger(attr2, 0));
}else if(key2 == "vid2"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DEF_VLAN2, getYAMLUnsignedInteger(attr2, 1));
}else if(key2 == "priority2"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DEF_PRI2, getYAMLUnsignedInteger(attr2, 0));
}else if(key2 == "replace"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_REPLACE_VLAN_FIELDS, getYAMLBool(attr2, false));
}else if(key2 == "cfi"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DEF_CFI, getYAMLUnsignedInteger(attr2, 0));
}else if(key2 == "dscp"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DEF_DSCP, getYAMLUnsignedInteger(attr2, 0));
}else if(key2 == "isl_format"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_ISL_TAG_FORMAT, getMapState(getYAMLString(attr2, "none"), ISL_FORMAT_MAP));
}
}
}else if (key == "drop" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "boundary_violation"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DROP_BV, getYAMLBool(attr2, false));
}else if(key2 == "untagged"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DROP_UNTAGGED, getYAMLBool(attr2, false));
}else if(key2 == "tagged"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_DROP_TAGGED, getYAMLBool(attr2, false));
}
}
}else if (key == "loopback" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "suppression"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_LOOPBACK_SUPPRESSION, getYAMLBool(attr2, true));
}else if(key2 == "mode" && isEplPort){
ies.fmSetPortAttribute(logicalPort, FM_PORT_LOOPBACK, getMapState(getYAMLString(attr2, "off"), LOOPBACK_MODE_MAP));
}else if(key2 == "fabric"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_FABRIC_LOOPBACK, getMapState(getYAMLString(attr2, "off"), LOOPBACK_MODE_MAP));
}
}
}else if (key == "parser" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "first_vlan2"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_PARSER_VLAN2_FIRST, getYAMLBool(attr2, false));
}else if(key2 == "first_vid2"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_MODIFY_VID2_FIRST, getYAMLBool(attr2, false));
}else if(key2 == "mode"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_PARSER, getMapState(getYAMLString(attr2, "l2"), PARSER_MODE_MAP));
}
}
}else if (key == "update" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "ttl"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_UPDATE_TTL, getYAMLBool(attr2, true));
}else if(key2 == "dscp"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_UPDATE_DSCP, getYAMLBool(attr2, true));
}else if(key2 == "vlan_priority"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_TXVPRI, getYAMLBool(attr2, false));
}else if(key2 == "vlan_priority2"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_TXVPRI2, getYAMLBool(attr2, false));
}else if(key2 == "routed" && attr2.is_seq()){
fm_uint32 f = 0;
for(auto s : attr2){
if(s == "DMAC"){
f |= FM_PORT_ROUTED_FRAME_UPDATE_DMAC;
}else if(s == "SMAC"){
f |= FM_PORT_ROUTED_FRAME_UPDATE_SMAC;
}else if(s == "VLAN"){
f |= FM_PORT_ROUTED_FRAME_UPDATE_VLAN;
}
}
ies.fmSetPortAttribute(logicalPort, FM_PORT_ROUTED_FRAME_UPDATE_FIELDS, f);
}
}
}else if (key == "broadcast" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "pruning"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_BCAST_PRUNING, getYAMLBool(attr2, false));
}else if(key2 == "flooding"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_BCAST_FLOODING, getMapState(getYAMLString(attr2, "forward_without_cpu"), BFLOOD_MODE_MAP));
}
}
}else if (key == "multicast" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "pruning"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_MCAST_PRUNING, getYAMLBool(attr2, false));
}else if(key2 == "flooding"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_MCAST_FLOODING, getMapState(getYAMLString(attr2, "forward_without_cpu"), MFLOOD_MODE_MAP));
}
}
}else if (key == "unicast" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "pruning"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_UCAST_PRUNING, getYAMLBool(attr2, false));
}else if(key2 == "flooding"){
ies.fmSetPortAttribute(logicalPort, FM_PORT_UCAST_FLOODING, getMapState(getYAMLString(attr2, "forward_without_cpu"), UFLOOD_MODE_MAP));
}
}
}else if(key == "mask"){
auto switchInfo = ies.fmGetSwitchInfo();
fm_bitArray bitArray;
if(fmCreateBitArray(&bitArray, switchInfo.numCardPorts) != FM_OK){
std::abort();
}
if(attr.is_seq()){
for(auto b : attr){
fmSetBitArrayBit(&bitArray, getYAMLInteger(b), 1);
}
}else if(attr.val() == "-1"){
for(auto i = 0; i < switchInfo.numCardPorts; ++i){
if(i != logicalPort){
fmSetBitArrayBit(&bitArray, i, 1);
}
}
}
if(::fmSetPortAttribute(ies.fmGetSwitch(), logicalPort, FM_PORT_MASK_WIDE, &bitArray) != FM_OK){
std::abort();
}
fmDeleteBitArray(&bitArray);
}
}
}
};
ies.iteratePorts([&ies, &ports, &applyPortSettings](int logicalPort, int physicalPort, int cpi, bool isInternalPort, bool isPCIePort, bool isSpecialPort, bool isEplPort, bool isCpuPort){
std::cout << "port#" << logicalPort << " phys#" << physicalPort << " cpi#" << cpi
<< (isInternalPort ? " internal" : "")
<< (isPCIePort ? " pcie" : "")
<< (isSpecialPort ? " special" : "")
<< (isEplPort ? " epl" : "")
<< (isCpuPort ? " cpu" : "")
<< std::endl;
if(!isInternalPort){
ies.fmSetPortState(logicalPort, FM_PORT_STATE_UP, 0);
}
for(const auto& entryKind : std::vector<std::string>({"default", "eth", "pcie", "special", "internal", "cpu"})){
if(entryKind != "internal" && isInternalPort){
//Specifically disallow setting internal in "default"
continue;
}else if(entryKind == "eth" && !isEplPort){
continue;
}else if(entryKind == "pcie" && !isPCIePort){
continue;
}else if(entryKind == "special" && !isSpecialPort){
continue;
}else if(entryKind == "cpu" && !isCpuPort){
continue;
}
std::cout << "Applying " << entryKind << " settings" << std::endl;
for(auto portEntry : ports){
if(portEntry["port"].is_seq()){
for(auto e : portEntry["port"]){
if(e.val() == entryKind){
applyPortSettings(portEntry, logicalPort, physicalPort, cpi, isInternalPort, isPCIePort, isSpecialPort, isEplPort, isCpuPort);
}
}
}else if(portEntry["port"].val() == entryKind){
applyPortSettings(portEntry, logicalPort, physicalPort, cpi, isInternalPort, isPCIePort, isSpecialPort, isEplPort, isCpuPort);
}
}
}
for(auto portEntry : ports){
if(portEntry["port"].is_seq()){
for(auto e : portEntry["port"]){
if(e.val().is_integer() && getYAMLUnsignedInteger(e) == logicalPort){
applyPortSettings(portEntry, logicalPort, physicalPort, cpi, isInternalPort, isPCIePort, isSpecialPort, isEplPort, isCpuPort);
}
}
}else if(portEntry["port"].val().is_integer() && getYAMLUnsignedInteger(portEntry["port"]) == logicalPort){
std::cout << "Applying port# " << logicalPort << " settings" << std::endl;
applyPortSettings(portEntry, logicalPort, physicalPort, cpi, isInternalPort, isPCIePort, isSpecialPort, isEplPort, isCpuPort);
}
}
});
}
if(!root["switch"].is_seed() && root["switch"].is_seq()){
if(!root["switch"]["attributes"].is_seed() && root["switch"]["attributes"].is_map()){
for(auto attr : root["switch"]["attributes"]){
std::string key;
c4::from_chars(attr.key(), &key);
if(key == "broadcast_flooding"){
ies.fmSetSwitchAttribute(FM_BCAST_FLOODING, getMapState(getYAMLString(attr, "forward_without_cpu"), BFLOOD_MODE_MAP));
}else if(key == "multicast_flooding"){
ies.fmSetSwitchAttribute(FM_MCAST_FLOODING, getMapState(getYAMLString(attr, "forward_without_cpu"), MFLOOD_MODE_MAP));
}else if(key == "unicast_flooding"){
ies.fmSetSwitchAttribute(FM_UCAST_FLOODING, getMapState(getYAMLString(attr, "forward_without_cpu"), UFLOOD_MODE_MAP));
}else if(key == "cpu_port"){
ies.fmSetSwitchAttribute(FM_REDIRECT_CPU_TRAFFIC, getYAMLInteger(attr));
}else if(key == "frame_aging_milliseconds"){
ies.fmSetSwitchAttribute(FM_FRAME_AGING_TIME_MSEC, getYAMLInteger(attr));
}else if (key == "vlan_learning" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "vlan" && ies.fmGetSwitchAttribute<fm_int>(FM_VLAN_LEARNING_SHARED_VLAN) == FM_VLAN_LEARNING_MODE_SHARED){
ies.fmSetSwitchAttribute(FM_VLAN_LEARNING_SHARED_VLAN, getYAMLUnsignedInteger(attr2, 1));
}else if(key2 == "mode"){
ies.fmSetSwitchAttribute(FM_VLAN_LEARNING_MODE, getMapState(getYAMLString(attr2, "independent"), VLAN_LEARNING_MODE));
}
}
}else if (key == "lag" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "mode"){
ies.fmSetSwitchAttribute(FM_LAG_MODE, getMapState(getYAMLString(attr2, "static"), LAG_MODE));
}else if(key2 == "pruning"){
ies.fmSetSwitchAttribute(FM_LAG_PRUNING, getYAMLBool(attr2, true));
}
}
}else if (key == "trap" && attr.is_map()){
for(auto attr2 : attr){
std::string key2;
c4::from_chars(attr2.key(), &key2);
if(key2 == "cpu_mac"){
ies.fmSetSwitchAttribute(FM_CPU_MAC, static_cast<fm_macaddr>(getYAMLUnsignedInteger64(attr2, 0x000000000000)));
}else if(key2 == "8021x"){
ies.fmSetSwitchAttribute(FM_TRAP_IEEE_8021X, getYAMLBool(attr2, true));
}else if(key2 == "bpdu"){
ies.fmSetSwitchAttribute(FM_TRAP_IEEE_BPDU, getYAMLBool(attr2, true));
}else if(key2 == "lacp"){
ies.fmSetSwitchAttribute(FM_TRAP_IEEE_LACP, getYAMLBool(attr2, true));
}else if(key2 == "garp"){
ies.fmSetSwitchAttribute(FM_TRAP_IEEE_GARP, getYAMLBool(attr2, true));
}else if(key2 == "mtu_violation"){
ies.fmSetSwitchAttribute(FM_TRAP_MTU_VIOLATIONS, getYAMLBool(attr2, true));
}
}
}else if(key == "stp_mode"){
ies.fmSetSwitchAttribute(FM_SPANNING_TREE_MODE, getMapState(getYAMLString(attr, "shared"), STP_MODE));
}
}
}
std::cout << std::endl;
}
std::cout << "Switch is UP, all ports are now enabled" << std::endl;
return true;
}
return false;
}

View file

@ -25,6 +25,10 @@ __f->fields. f = v
auto __f = FM10K_MAP_REGISTER(i, t, o); \
__f->fields. f = v
namespace c4::yml {
class Tree;
}
namespace FM10K{
class FM10K {
@ -114,7 +118,7 @@ namespace FM10K{
return portIndex < m_ports.size() ? &m_ports.back() : nullptr;
}
bool initialize() const;
bool initialize(const c4::yml::Tree& tree) const;
bool isPEPEnabled(uint8_t pep) const;

View file

@ -61,20 +61,23 @@ bool FM10K::IES::init() {
std::abort();
}
//if(fmEnableLoggingLevel(FM_LOG_LEVEL_ALL_VERBOSE) != FM_OK){
/*
if(fmEnableLoggingLevel(FM_LOG_LEVEL_ALL) != FM_OK){
std::abort();
}
*/
//if(fmEnableLoggingCategory(FM_LOG_CAT_ALL) != FM_OK){
//must remove "api.platform.lib.config.debug"
/*
if(fmSetLoggingFilter(FM_LOG_CAT_SWITCH | FM_LOG_CAT_PLATFORM, FM_LOG_LEVEL_ALL_VERBOSE,
nullptr, nullptr) != FM_OK){
std::abort();
}
*/
if(fmCreateSemaphore("seq", FM_SEM_BINARY, &IES_Static::semaphore, 0) != FM_OK){
std::abort();
@ -92,202 +95,6 @@ bool FM10K::IES::init() {
std::abort();
}
uint32_t defaultVlan = 1;
//Initialize VLANs
for(uint32_t vlan = 0; vlan < FM10000_MAX_VLAN; ++vlan){
fmCreateVlan(IES_Static::sw, vlan);
}
{
fm_bool vr = FM_ENABLED;
fmSetVlanAttribute(IES_Static::sw, 0, FM_VLAN_REFLECT, &vr);
}
{
fm_status err;
fm_int port;
fm_switchInfo swInfo;
fm_bool pi = FM_DISABLED;
fm_bool vr = FM_ENABLED;
fmGetSwitchInfo(IES_Static::sw, &swInfo);
/* init non cpu ports and put them into their own vlan, make sure */
/* the parser goes to l4, no vlan boundary check, and routable */
for(fm_int cpi = 1; cpi < swInfo.numCardPorts; ++cpi){
err = fmMapCardinalPort(IES_Static::sw, cpi, &port, nullptr);
if(err != FM_OK){
std::abort();
}
printf("cpi=%d, port=%d\n", cpi, port);
err = fmGetPortAttribute(IES_Static::sw, port, FM_PORT_INTERNAL, &pi);
if (err != FM_OK) {
printf("skip port %d\n", port);
continue;
}
if (pi == FM_ENABLED) {
printf("skip internal port %d\n", port);
continue;
}
fm_bool is_pcie = FALSE;
fm_bool is_fibm = FALSE;
err = fmIsPciePort(IES_Static::sw, port, &is_pcie);
if (err != FM_OK){
std::abort();
}
err = fmIsSpecialPort(IES_Static::sw, port, &is_fibm);
if (err != FM_OK){
std::abort();
}
err = fmSetVlanAttribute(IES_Static::sw, defaultVlan, FM_VLAN_REFLECT, &vr);
if (err != FM_OK){
std::abort();
}
err = fmSetPortState(IES_Static::sw, port, FM_PORT_STATE_UP, 0);
if (err != FM_OK){
std::abort();
}
printf("set port %d to UP\n", port);
err = fmAddVlanPort(IES_Static::sw, defaultVlan, port, FALSE);
if (err != FM_OK){
std::abort();
}
printf("add port %d to default vlan %u\n", port, defaultVlan);
err = fmSetVlanPortState(IES_Static::sw, defaultVlan, port, FM_STP_STATE_FORWARDING);
if (err != FM_OK){
std::abort();
}
printf("set STP state of port %d in vlan %u to forwarding\n", port, defaultVlan);
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_DEF_VLAN, &defaultVlan);
if (err != FM_OK){
std::abort();
}
printf("set pvid for port %d to vlan %u\n", port, defaultVlan);
//This drops unknown vlans that violate constraints
fm_bool bv = FM_DISABLED;
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_DROP_BV, &bv);
if (err != FM_OK){
std::abort();
}
printf("set FM_PORT_DROP_BV for port %d to %d\n", port, bv);
{
fm_int pc = FM_PORT_PARSER_STOP_AFTER_L2;//FM_PORT_PARSER_STOP_AFTER_L4;
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_PARSER, &pc);
if (err != FM_OK){
std::abort();
}
printf("set FM_PORT_PARSER for port %d to %d\n", port, pc);
}
{
//Only switch, not routing
fm_bool re = FM_DISABLED;
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_ROUTABLE, &re);
if (err != FM_OK){
std::abort();
}
printf("set FM_PORT_ROUTABLE for port %d to %d\n", port, re);
}
{
if(!is_fibm && !is_pcie){
fm_int fs = 10000;
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_MAX_FRAME_SIZE, &fs);
if (err != FM_OK){
std::abort();
}
printf("set FM_PORT_MAX_FRAME_SIZE for port %d to %d\n", port, fs);
}
}
{
// enable learning only for Ethernet ports
fm_int le = !is_pcie;
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_LEARNING, &le);
if (err != FM_OK){
std::abort();
}
printf("set FM_PORT_LEARNING for port %d to %d\n", port, le);
}
}
}
/* port cpu port on default vlan */
{
fm_int port;
auto err = fmGetCpuPort(IES_Static::sw, &port);
if(err != FM_OK){
std::abort();
}
printf("find cpu port %d\n", port);
err = fmAddVlanPort(IES_Static::sw, defaultVlan, port, FALSE);
if(err != FM_OK){
std::abort();
}
printf("add port %d to default vlan %u\n", port, defaultVlan);
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_DEF_VLAN, &defaultVlan);
if(err != FM_OK){
std::abort();
}
printf("set pvid for port %d to vlan %u\n", port, defaultVlan);
{
fm_int pc = FM_PORT_PARSER_STOP_AFTER_L2;//FM_PORT_PARSER_STOP_AFTER_L4;
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_PARSER, &pc);
if (err != FM_OK){
std::abort();
}
printf("set FM_PORT_PARSER for port %d to %d\n", port, pc);
}
{
fm_int le = FM_ENABLED;
err = fmSetPortAttribute(IES_Static::sw, port, FM_PORT_LEARNING, &le);
if (err != FM_OK){
std::abort();
}
printf("set FM_PORT_LEARNING for port %d to %d\n", port, le);
}
}
{
fm_int bf = FM_BCAST_FWD;
fm_int mf = FM_MCAST_FWD;
fm_int uf = FM_UCAST_FWD;
auto err = fmSetSwitchAttribute(IES_Static::sw, FM_BCAST_FLOODING, &bf);
if (err != FM_OK){
std::abort();
}
err = fmSetSwitchAttribute(IES_Static::sw, FM_MCAST_FLOODING, &mf);
if (err != FM_OK){
std::abort();
}
err = fmSetSwitchAttribute(IES_Static::sw, FM_UCAST_FLOODING, &uf);
if (err != FM_OK){
std::abort();
}
}
printf("Switch is UP, all ports are now enabled\n");
//TODO: setup routing
//Restore cwd
if(chdir(tempcwd) != 0){
std::abort();
@ -491,4 +298,168 @@ void FM10K::IES::teardown() {
}
}
template<typename T>
void FM10K::IES::fmSetVlanAttribute(uint16_t vlan, int attribute, T value) const {
auto status = ::fmSetVlanAttribute(IES_Static::sw, vlan, attribute, &value);
if(status != FM_OK){
throw IESException(status);
}
}
template<typename T>
void FM10K::IES::fmSetPortAttribute(int port, int attribute, T value) const {
auto status = ::fmSetPortAttribute(IES_Static::sw, port, attribute, &value);
if(status != FM_OK){
throw IESException(status);
}
}
template<typename T>
void FM10K::IES::fmSetSwitchAttribute(int attribute, T value) const {
auto status = ::fmSetSwitchAttribute(IES_Static::sw, attribute, &value);
if(status != FM_OK){
throw IESException(status);
}
}
template<typename T>
T FM10K::IES::fmGetSwitchAttribute(int attribute) const {
T parameter{};
auto status = ::fmGetSwitchAttribute(IES_Static::sw, attribute, &parameter);
if(status != FM_OK){
throw IESException(status);
}
return parameter;
}
struct _fm_switchInfo FM10K::IES::fmGetSwitchInfo() const {
fm_switchInfo info{};
auto status = ::fmGetSwitchInfo(IES_Static::sw, &info);
if(status != FM_OK){
throw IESException(status);
}
return info;
}
void FM10K::IES::fmSetPortState(int port, int mode, int submode) const {
auto status = ::fmSetPortState(IES_Static::sw, port, mode, submode);
if(status != FM_OK){
throw IESException(status);
}
}
void FM10K::IES::fmCreateVlan(uint16_t vlan) const {
auto status = ::fmCreateVlan(IES_Static::sw, vlan);
if(status != FM_OK){
throw IESException(status);
}
}
void FM10K::IES::fmAddVlanPort(uint16_t vlan, int port, bool tagVlan) const {
auto status = ::fmAddVlanPort(IES_Static::sw, vlan, port, tagVlan);
if(status != FM_OK){
throw IESException(status);
}
}
void FM10K::IES::fmSetVlanPortState(uint16_t vlan, int port, int state) const {
auto status = ::fmSetVlanPortState(IES_Static::sw, vlan, port, state);
if(status != FM_OK){
throw IESException(status);
}
}
template<typename T>
T FM10K::IES::fmGetPortAttribute(int port, int attribute) const {
T value{};
auto status = ::fmGetPortAttribute(IES_Static::sw, port, attribute, &value);
if(status != FM_OK){
throw IESException(status);
}
return value;
}
template<typename T>
T FM10K::IES::fmGetVlanAttribute(uint16_t vlan, int attribute) const {
T value{};
auto status = ::fmGetVlanAttribute(IES_Static::sw, vlan, attribute, &value);
if(status != FM_OK){
throw IESException(status);
}
return value;
}
bool FM10K::IES::fmIsPciePort(int port) const {
fm_bool value{};
auto status = ::fmIsPciePort(IES_Static::sw, port, &value);
if(status != FM_OK){
throw IESException(status);
}
return value;
}
bool FM10K::IES::fmIsSpecialPort(int port) const {
fm_bool value{};
auto status = ::fmIsSpecialPort(IES_Static::sw, port, &value);
if(status != FM_OK){
throw IESException(status);
}
return value;
}
bool FM10K::IES::fmIsEplPort(int port) const {
fm_bool value{};
auto status = ::fmIsEplPort(IES_Static::sw, port, &value);
if(status != FM_OK){
throw IESException(status);
}
return value;
}
void FM10K::IES::iteratePorts(const std::function<void(int logicalPort, int physicalPort, int cpi, bool isInternalPort, bool isPCIePort, bool isSpecialPort, bool isEplPort, bool isCpuPort)>& callback) const {
auto swInfo = fmGetSwitchInfo();
fm_int cpuPort;
auto err = fmGetCpuPort(IES_Static::sw, &cpuPort);
if(err != FM_OK){
std::abort();
}
for(fm_int cpi = 0; cpi < swInfo.numCardPorts; ++cpi){
fm_int logicalPort;
fm_int physicalPort;
if(::fmMapCardinalPort(IES_Static::sw, cpi, &logicalPort, &physicalPort) != FM_OK){
std::abort();
}
bool isInternalPort;
try{
isInternalPort = fmGetPortAttribute<fm_bool>(logicalPort, FM_PORT_INTERNAL);
}catch (const IESException& e){
continue;
}
callback(logicalPort, physicalPort, cpi, isInternalPort, fmIsPciePort(logicalPort), fmIsSpecialPort(logicalPort), fmIsEplPort(logicalPort), cpuPort == logicalPort);
}
}
int FM10K::IES::fmGetSwitch() const {
return IES_Static::sw;
}
FM10K::IES::IES() = default;
IESException::IESException(int status) : m_msg(fmErrorMsg(status)) {
}
#define CREATE_ATTRIBUTE_TYPE(T) \
template void FM10K::IES::fmSetVlanAttribute(uint16_t vlan, int attribute, T value) const; \
template T FM10K::IES::fmGetVlanAttribute(uint16_t vlan, int attribute) const; \
template void FM10K::IES::fmSetPortAttribute(int port, int attribute, T value) const; \
template T FM10K::IES::fmGetPortAttribute(int port, int attribute) const; \
template void FM10K::IES::fmSetSwitchAttribute(int attribute, T value) const; \
template T FM10K::IES::fmGetSwitchAttribute(int attribute) const;
CREATE_ATTRIBUTE_TYPE(bool)
CREATE_ATTRIBUTE_TYPE(fm_int)
CREATE_ATTRIBUTE_TYPE(fm_uint)
CREATE_ATTRIBUTE_TYPE(fm_macaddr)

View file

@ -5,8 +5,10 @@
#include <map>
#include <string>
#include <vector>
#include <functional>
struct _fm_eventPort;
struct _fm_switchInfo;
namespace FM10K {
@ -51,6 +53,40 @@ namespace FM10K {
bool init();
void teardown();
struct _fm_switchInfo fmGetSwitchInfo() const;
void iteratePorts(const std::function<void(int logicalPort, int physicalPort, int cpi, bool isInternalPort, bool isPCIePort, bool isSpecialPort, bool isEplPort, bool isCpuPort)>& callback) const;
bool fmIsPciePort(int port) const;
bool fmIsSpecialPort(int port) const;
bool fmIsEplPort(int port) const;
void fmSetPortState(int port, int mode, int submode) const;
void fmCreateVlan(uint16_t vlan) const;
void fmAddVlanPort(uint16_t vlan, int port, bool tagVlan) const;
void fmSetVlanPortState(uint16_t vlan, int port, int state) const;
template<typename T>
void fmSetVlanAttribute(uint16_t vlan, int attribute, T value) const;
template<typename T>
T fmGetVlanAttribute(uint16_t vlan, int attribute) const;
template<typename T>
void fmSetPortAttribute(int port, int attribute, T value) const;
template<typename T>
T fmGetPortAttribute(int port, int attribute) const;
template<typename T>
void fmSetSwitchAttribute(int attribute, T value) const;
template<typename T>
T fmGetSwitchAttribute(int attribute) const;
int fmGetSwitch() const;
private:
IES();
@ -69,3 +105,14 @@ namespace FM10K {
}
class IESException : public std::exception{
public:
explicit IESException(int status);
const char* what() const noexcept override
{
return m_msg.c_str();
}
const std::string m_msg;
};

View file

@ -17,21 +17,21 @@ namespace FM10K {
namespace IES_Static {
using TlvType = FM10K::IES::TlvType;
static std::unordered_map<std::string, std::vector<std::pair<std::string, std::pair<TlvType, std::string>>>> knownConfigurations = {
{"FM10840_B0_AUTO_100G", {
{"FM10840_B0_2x100G", {
{"api.platform.config.numSwitches", {TlvType::Integer, "1"}},
{"api.platform.config.platformName", {TlvType::Text, "rrc_2x100gm"}},
{"api.platform.config.debug", {TlvType::Text, "CONFIG,MOD_STATE,MOD_LED,MOD_INTR,MOD_TYPE,PLAT_LOG"}},
//{"api.platform.config.debug", {TlvType::Text, "CONFIG,MOD_STATE,MOD_LED,MOD_INTR,MOD_TYPE,PLAT_LOG"}},
//{"api.platform.lib.config.debug", {TlvType::Text, "I2C_RW,I2C_MUX,PORT_LED"}},
{"api.platform.config.switch.0.switchNumber", {TlvType::Integer, "0"}},
{"api.platform.config.switch.0.uioDevName", {TlvType::Text, "/dev/uio0"}}, //TODO: delete this if not in use
{"api.platform.config.switch.0.uioDevName", {TlvType::Text, "/dev/uio0"}},
{"api.platform.config.switch.0.resource4DevName", {TlvType::Text, ""}}, //TODO: delete this if not in use
{"api.platform.config.switch.0.resource4DevName", {TlvType::Text, ""}},
{"api.platform.config.switch.0.msiEnabled", {TlvType::Boolean, "true"}},
@ -304,6 +304,328 @@ namespace FM10K {
{"api.platform.config.switch.0.VDDS.hwResourceId", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.3.type", {TlvType::Text, "VRM"}},
{"api.platform.lib.config.hwResourceId.3.vrm.busSelType", {TlvType::Text, "PCAMUX"}},
{"api.platform.lib.config.hwResourceId.3.vrm.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.3.vrm.model", {TlvType::Text, "IR"}},
{"api.platform.lib.config.hwResourceId.3.vrm.addr", {TlvType::Integer, "0x08"}},
{"api.platform.lib.config.hwResourceId.3.vrm.pcaMux.index", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.3.vrm.pcaMux.value", {TlvType::Integer, "0x04"}},
{"api.platform.config.switch.0.VDDF.hwResourceId", {TlvType::Integer, "259"}},
}},
{"FM10840_B0_8x25G", {
{"api.platform.config.numSwitches", {TlvType::Integer, "1"}},
{"api.platform.config.platformName", {TlvType::Text, "rrc_2x100gm"}},
{"api.platform.config.switch.0.switchNumber", {TlvType::Integer, "0"}},
{"api.platform.config.switch.0.uioDevName", {TlvType::Text, "/dev/uio0"}},
{"api.platform.config.switch.0.resource4DevName", {TlvType::Text, ""}},
{"api.platform.config.switch.0.msiEnabled", {TlvType::Boolean, "true"}},
{"api.platform.config.switch.0.ledPollPeriodMsec", {TlvType::Integer, "200"}},
{"api.platform.config.switch.0.ledBlinkMode", {TlvType::Text, "HW_ASSISTED"}},
{"api.platform.config.switch.0.i2cClkDivider", {TlvType::Integer, "52"}},
{"api.platform.config.switch.0.i2cResetGpio", {TlvType::Integer, "5"}},
{"api.platform.config.switch.0.xcvrPollPeriodMsec", {TlvType::Integer, "1000"}},
{"api.platform.config.switch.0.numPorts", {TlvType::Integer, "13"}},
{"api.platform.config.switch.0.cpuPort", {TlvType::Integer, "12"}},
{"api.platform.config.switch.0.bootCfg.mgmtPep", {TlvType::Integer, "-1"}},
{"api.platform.config.switch.0.bootCfg.pep.0.mode", {TlvType::Boolean, "0"}},
{"api.platform.config.switch.0.bootCfg.pep.2.mode", {TlvType::Boolean, "0"}},
{"api.platform.config.switch.0.bootCfg.pep.4.mode", {TlvType::Boolean, "0"}},
{"api.platform.config.switch.0.bootCfg.pep.6.mode", {TlvType::Boolean, "0"}},
{"api.platform.config.switch.0.bootCfg.pep.0.enable", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.bootCfg.pep.2.enable", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.bootCfg.pep.4.enable", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.bootCfg.pep.6.enable", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.bootCfg.pep.8.enable", {TlvType::Boolean, "0"}},
{"api.platform.config.switch.0.bootCfg.pep.0.bar4Allowed", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.bootCfg.pep.2.bar4Allowed", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.bootCfg.pep.4.bar4Allowed", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.bootCfg.pep.6.bar4Allowed", {TlvType::Boolean, "1"}},
{"api.platform.config.switch.0.portIndex.0.portMapping", {TlvType::Text, "\"LOG=0 PCIE=8\""}},
{"api.platform.config.switch.0.portIndex.1.portMapping", {TlvType::Text, "\"LOG=1 EPL=1 LANE=0\""}},
{"api.platform.config.switch.0.portIndex.2.portMapping", {TlvType::Text, "\"LOG=2 EPL=1 LANE=1\""}},
{"api.platform.config.switch.0.portIndex.3.portMapping", {TlvType::Text, "\"LOG=3 EPL=1 LANE=2\""}},
{"api.platform.config.switch.0.portIndex.4.portMapping", {TlvType::Text, "\"LOG=4 EPL=1 LANE=3\""}},
{"api.platform.config.switch.0.portIndex.5.portMapping", {TlvType::Text, "\"LOG=5 EPL=7 LANE=0\""}},
{"api.platform.config.switch.0.portIndex.6.portMapping", {TlvType::Text, "\"LOG=6 EPL=7 LANE=1\""}},
{"api.platform.config.switch.0.portIndex.7.portMapping", {TlvType::Text, "\"LOG=7 EPL=7 LANE=2\""}},
{"api.platform.config.switch.0.portIndex.8.portMapping", {TlvType::Text, "\"LOG=8 EPL=7 LANE=3\""}},
{"api.platform.config.switch.0.portIndex.9.portMapping", {TlvType::Text, "\"LOG=9 PCIE=0\""}},
{"api.platform.config.switch.0.portIndex.10.portMapping", {TlvType::Text, "\"LOG=10 PCIE=2\""}},
{"api.platform.config.switch.0.portIndex.11.portMapping", {TlvType::Text, "\"LOG=11 PCIE=4\""}},
{"api.platform.config.switch.0.portIndex.12.portMapping", {TlvType::Text, "\"LOG=12 PCIE=6\""}},
{"api.platform.config.switch.0.port.default.interfaceType", {TlvType::Text, "NONE"}},
{"api.platform.config.switch.0.portIndex.1.interfaceType", {TlvType::Text, "QSFP_LANE0"}},
{"api.platform.config.switch.0.portIndex.2.interfaceType", {TlvType::Text, "QSFP_LANE1"}},
{"api.platform.config.switch.0.portIndex.3.interfaceType", {TlvType::Text, "QSFP_LANE2"}},
{"api.platform.config.switch.0.portIndex.4.interfaceType", {TlvType::Text, "QSFP_LANE3"}},
{"api.platform.config.switch.0.portIndex.5.interfaceType", {TlvType::Text, "QSFP_LANE0"}},
{"api.platform.config.switch.0.portIndex.6.interfaceType", {TlvType::Text, "QSFP_LANE1"}},
{"api.platform.config.switch.0.portIndex.7.interfaceType", {TlvType::Text, "QSFP_LANE2"}},
{"api.platform.config.switch.0.portIndex.8.interfaceType", {TlvType::Text, "QSFP_LANE3"}},
{"api.platform.config.switch.0.portIndex.0.speed", {TlvType::Integer, SPEED_10G}},
{"api.platform.config.switch.0.portIndex.1.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.2.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.3.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.4.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.5.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.6.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.7.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.8.speed", {TlvType::Integer, SPEED_25G}},
{"api.platform.config.switch.0.portIndex.9.speed", {TlvType::Integer, SPEED_50G}},
{"api.platform.config.switch.0.portIndex.10.speed", {TlvType::Integer, SPEED_50G}},
{"api.platform.config.switch.0.portIndex.11.speed", {TlvType::Integer, SPEED_50G}}, //? second PCIe group
{"api.platform.config.switch.0.portIndex.12.speed", {TlvType::Integer, SPEED_50G}}, //? second PCIe group
{"api.platform.config.switch.0.port.default.ethernetMode", {TlvType::Text, "DISABLED"}},
{"api.platform.config.switch.0.portIndex.1.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.portIndex.2.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.portIndex.3.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.portIndex.4.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.portIndex.5.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.portIndex.6.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.portIndex.7.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.portIndex.8.ethernetMode", {TlvType::Text, "AUTODETECT"}},
{"api.platform.config.switch.0.port.default.capability", {TlvType::Text, "NONE"}},
{"api.platform.config.switch.0.portIndex.1.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.portIndex.2.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.portIndex.3.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.portIndex.4.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.portIndex.5.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.portIndex.6.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.portIndex.7.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.portIndex.8.capability",{TlvType::Text, "LAG,ROUTE,10G,25G,SW_LED"}},
{"api.platform.config.switch.0.port.default.lanePolarity", {TlvType::Text, "INVERT_NONE"}},
{"api.platform.config.switch.0.port.default.preCursorCopper", {TlvType::Integer, "0"}},
{"api.platform.config.switch.0.sharedLibraryName", {TlvType::Text, "libLTStdPlatform.so"}},
{"api.platform.config.switch.0.sharedLibrary.disable", {TlvType::Text, "GetPortIntrPending,EnablePortIntr"}},
{"api.platform.lib.config.bus0.i2cDevName", {TlvType::Text, "switchI2C"}},
{"api.platform.lib.config.pcaMux.count", {TlvType::Integer, "1"}},
{"api.platform.lib.config.pcaMux.0.model", {TlvType::Text, "PCA9545"}},
{"api.platform.lib.config.pcaMux.0.addr", {TlvType::Integer, "0x58"}},
{"api.platform.lib.config.pcaMux.0.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.pcaIo.count", {TlvType::Integer, "6"}},
{"api.platform.lib.config.pcaIo.0.model", {TlvType::Text, "PCA9538"}},
{"api.platform.lib.config.pcaIo.0.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.pcaIo.0.addr", {TlvType::Integer, "0x60"}},
{"api.platform.lib.config.pcaIo.1.model", {TlvType::Text, "PCA9538"}},
{"api.platform.lib.config.pcaIo.1.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.pcaIo.1.addr", {TlvType::Integer, "0x61"}},
{"api.platform.lib.config.pcaIo.2.model", {TlvType::Text, "PCA9538"}},
{"api.platform.lib.config.pcaIo.2.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.pcaIo.2.addr", {TlvType::Integer, "0x62"}},
{"api.platform.lib.config.pcaIo.3.model", {TlvType::Text, "PCA9538"}},
{"api.platform.lib.config.pcaIo.3.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.pcaIo.3.addr", {TlvType::Integer, "0x64"}},
{"api.platform.lib.config.pcaIo.4.model", {TlvType::Text, "PCA9538"}},
{"api.platform.lib.config.pcaIo.4.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.pcaIo.4.addr", {TlvType::Integer, "0x65"}},
{"api.platform.lib.config.pcaIo.5.model", {TlvType::Text, "PCA9538"}},
{"api.platform.lib.config.pcaIo.5.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.pcaIo.5.addr", {TlvType::Integer, "0x66"}},
{"api.platform.lib.config.xcvrState.default.modPrsL.pin", {TlvType::Integer, "2"}},
{"api.platform.lib.config.xcvrState.default.intL.pin", {TlvType::Integer, "1"}},
{"api.platform.lib.config.xcvrState.default.resetL.pin", {TlvType::Integer, "3"}},
{"api.platform.lib.config.xcvrState.default.lpMode.pin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.count", {TlvType::Integer, "4"}},
{"api.platform.config.switch.0.portIndex.1.hwResourceId", {TlvType::Integer, "0"}},
{"api.platform.config.switch.0.portIndex.2.hwResourceId", {TlvType::Integer, "0"}},
{"api.platform.config.switch.0.portIndex.3.hwResourceId", {TlvType::Integer, "0"}},
{"api.platform.config.switch.0.portIndex.4.hwResourceId", {TlvType::Integer, "0"}},
{"api.platform.config.switch.0.portIndex.5.hwResourceId", {TlvType::Integer, "1"}},
{"api.platform.config.switch.0.portIndex.6.hwResourceId", {TlvType::Integer, "1"}},
{"api.platform.config.switch.0.portIndex.7.hwResourceId", {TlvType::Integer, "1"}},
{"api.platform.config.switch.0.portIndex.8.hwResourceId", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.0.interfaceType", {TlvType::Text, "QSFP"}},
{"api.platform.lib.config.hwResourceId.0.xcvrI2C.busSelType", {TlvType::Text, "PCAMUX"}},
{"api.platform.lib.config.hwResourceId.0.xcvrI2C.pcaMux.index", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.0.xcvrI2C.pcaMux.value", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.0.xcvrState.pcaIo.index", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.0.xcvrState.pcaIo.basePin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.0.xcvrState.pcaIo.modPrsL.pin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.0.xcvrState.pcaIo.intL.pin", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.0.xcvrState.pcaIo.resetL.pin", {TlvType::Integer, "4"}},
{"api.platform.lib.config.hwResourceId.0.xcvrState.pcaIo.lpMode.pin", {TlvType::Integer, "5"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.pcaIo.index", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.0.pcaIo.pin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.1.pcaIo.pin", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.1.pcaIo.usage", {TlvType::Text, "LINK,40G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.2.pcaIo.pin", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.2.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.3.pcaIo.pin", {TlvType::Integer, "3"}},
{"api.platform.lib.config.hwResourceId.0.portLed.0.3.pcaIo.usage",{TlvType::Text, "LINK,100G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.1.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.0.portLed.1.pcaIo.index", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.0.portLed.1.0.pcaIo.pin", {TlvType::Integer, "4"}},
{"api.platform.lib.config.hwResourceId.0.portLed.1.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.1.1.pcaIo.pin", {TlvType::Integer, "5"}},
{"api.platform.lib.config.hwResourceId.0.portLed.1.1.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.2.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.0.portLed.2.pcaIo.index", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.0.portLed.2.0.pcaIo.pin", {TlvType::Integer, "6"}},
{"api.platform.lib.config.hwResourceId.0.portLed.2.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.2.1.pcaIo.pin", {TlvType::Integer, "7"}},
{"api.platform.lib.config.hwResourceId.0.portLed.2.1.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.3.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.0.portLed.3.pcaIo.index", {TlvType::Integer, "4"}},
{"api.platform.lib.config.hwResourceId.0.portLed.3.0.pcaIo.pin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.0.portLed.3.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.0.portLed.3.1.pcaIo.pin", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.0.portLed.3.1.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.1.interfaceType", {TlvType::Text, "QSFP"}},
{"api.platform.lib.config.hwResourceId.1.xcvrI2C.busSelType", {TlvType::Text, "PCAMUX"}},
{"api.platform.lib.config.hwResourceId.1.xcvrI2C.pcaMux.index", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.1.xcvrI2C.pcaMux.value", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.1.xcvrState.pcaIo.index", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.1.xcvrState.pcaIo.basePin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.1.xcvrState.pcaIo.modPrsL.pin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.1.xcvrState.pcaIo.intL.pin", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.1.xcvrState.pcaIo.resetL.pin", {TlvType::Integer, "4"}},
{"api.platform.lib.config.hwResourceId.1.xcvrState.pcaIo.lpMode.pin", {TlvType::Integer, "5"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.pcaIo.index", {TlvType::Integer, "5"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.0.pcaIo.pin", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.1.pcaIo.pin", {TlvType::Integer, "1"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.1.pcaIo.usage", {TlvType::Text, "LINK,40G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.2.pcaIo.pin", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.2.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.3.pcaIo.pin", {TlvType::Integer, "3"}},
{"api.platform.lib.config.hwResourceId.1.portLed.0.3.pcaIo.usage", {TlvType::Text, "LINK,100G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.1.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.1.portLed.1.pcaIo.index", {TlvType::Integer, "5"}},
{"api.platform.lib.config.hwResourceId.1.portLed.1.0.pcaIo.pin", {TlvType::Integer, "4"}},
{"api.platform.lib.config.hwResourceId.1.portLed.1.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.1.1.pcaIo.pin", {TlvType::Integer, "5"}},
{"api.platform.lib.config.hwResourceId.1.portLed.1.1.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.2.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.1.portLed.2.pcaIo.index", {TlvType::Integer, "5"}},
{"api.platform.lib.config.hwResourceId.1.portLed.2.0.pcaIo.pin", {TlvType::Integer, "6"}},
{"api.platform.lib.config.hwResourceId.1.portLed.2.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.2.1.pcaIo.pin", {TlvType::Integer, "7"}},
{"api.platform.lib.config.hwResourceId.1.portLed.2.1.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.3.type", {TlvType::Text, "PCA"}},
{"api.platform.lib.config.hwResourceId.1.portLed.3.pcaIo.index", {TlvType::Integer, "4"}},
{"api.platform.lib.config.hwResourceId.1.portLed.3.0.pcaIo.pin", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.1.portLed.3.0.pcaIo.usage", {TlvType::Text, "LINK,10G"}},
{"api.platform.lib.config.hwResourceId.1.portLed.3.1.pcaIo.pin", {TlvType::Integer, "3"}},
{"api.platform.lib.config.hwResourceId.1.portLed.3.1.pcaIo.usage", {TlvType::Text, "LINK,25G"}},
{"api.platform.lib.config.hwResourceId.2.type", {TlvType::Text, "VRM"}},
{"api.platform.lib.config.hwResourceId.2.vrm.busSelType", {TlvType::Text, "PCAMUX"}},
{"api.platform.lib.config.hwResourceId.2.vrm.bus", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.2.vrm.model", {TlvType::Text, "IR"}},
{"api.platform.lib.config.hwResourceId.2.vrm.addr", {TlvType::Integer, "0x08"}},
{"api.platform.lib.config.hwResourceId.2.vrm.pcaMux.index", {TlvType::Integer, "0"}},
{"api.platform.lib.config.hwResourceId.2.vrm.pcaMux.value", {TlvType::Integer, "0x04"}},
{"api.platform.config.switch.0.VDDS.hwResourceId", {TlvType::Integer, "2"}},
{"api.platform.lib.config.hwResourceId.3.type", {TlvType::Text, "VRM"}},
{"api.platform.lib.config.hwResourceId.3.vrm.busSelType", {TlvType::Text, "PCAMUX"}},
{"api.platform.lib.config.hwResourceId.3.vrm.bus", {TlvType::Integer, "0"}},
@ -314,6 +636,7 @@ namespace FM10K {
{"api.platform.config.switch.0.VDDF.hwResourceId", {TlvType::Integer, "259"}},
}}
};
}
}

View file

@ -5,10 +5,14 @@
#include <csignal>
#include <unistd.h>
#include <thread>
#include <fstream>
#include "device/PCIEDevice.h"
#include "fm10k/FM10K.h"
#include "fm10k/registers/Register.h"
#include "fm10k/IES.h"
#include "argparse/argparse.hpp"
#include "ryml.hpp"
#include "c4/std/string.hpp"
template <typename T> std::string tohex(T v){
std::stringstream o;
@ -24,7 +28,40 @@ static void int_handler(int sig){
std::cout << "STOPPING DUE TO SIGNAL " << sig << std::endl;
}
int main() {
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("fsmd", "0.1.0");
program.add_argument("-c", "--config").help("Path to YAML switch configuration.").default_value<std::string>("config.yml");
program.add_argument("-v", "--verbose").help("Enable verbose mode").default_value<bool>(false).implicit_value(true);
try{
program.parse_args(argc, argv);
}catch(const std::runtime_error& err){
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
ryml::Tree config;
try{
std::ifstream f;
std::stringstream buffer;
f.open(program.get("--config"));
buffer << f.rdbuf();
config = ryml::parse(ryml::to_csubstr(buffer.str()));
}catch(const std::runtime_error& err){
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
if(config.empty()){
std::cerr << "Empty config file" << std::endl;
std::cerr << program;
std::exit(1);
}
auto entries = PCIEDevice::DeviceEntry::find();
std::cout << "Found " << entries.size() << " FM10K management device(s)." << std::endl;
@ -35,11 +72,23 @@ int main() {
std::cout << "dev.path: " << dev->getDeviceEntry().getPath() << std::endl;
std::cout << "dev.vendor: " << tohex(dev->getDeviceEntry().getVendor()) << std::endl;
std::cout << "dev.class: " << tohex(dev->getDeviceEntry().getClass()) << std::endl;
auto vpdHash = dev->getDeviceEntry().getVPDHash();
std::cout << "dev.vpd_hash: " << vpdHash << std::endl;
FM10K::FM10K fm10k(std::move(dev));
std::cout << "Device Model_Stepping: " << fm10k.getHardwareInformationString() << std::endl;
auto p = config.rootref()["platform"];
if(p.is_map()){ //Match value
if(!p["device"].is_seed() && p["device"].val() != fm10k.getHardwareInformationString()){
continue;
}
if(!p["device_vpd_hash"].is_seed() && p["device_vpd_hash"].val() != vpdHash){
continue;
}
}
auto fuseData_0 = fm10k.mapRegister<FM10K::registers::MGMT::FUSE_DATA_0>();
std::cout << "FUSE_DATA_0: " << tohex(fuseData_0->value) << std::endl;
std::cout << "FUSE_DATA_0.VDDF_VRM: " << FM10K::VR12_VID_to_Millivolts(fuseData_0->fields.VDDS_VRM) << std::endl;
@ -48,29 +97,26 @@ int main() {
auto deviceCfg = fm10k.mapRegister<FM10K::registers::MGMT::DEVICE_CFG>();
std::cout << "DEVICE_CFG: " << tohex(deviceCfg->value) << std::endl;
std::cout << "trying to initialize: ";
std::cout << "trying to initialize: " << std::endl;
auto& port = fm10k.addPort(1, 1);
port.m_portType = Port::PortType::EPL;
port.m_interfaceType = Port::InterfaceType::QSFP_LANE0;
if(fm10k.initialize()){
if(fm10k.initialize(config)){
std::cout << "success" << std::endl;
signal(SIGINT, int_handler);
signal(SIGTERM, int_handler);
do{
using namespace std::chrono_literals;
std::this_thread::yield();
//TODO: check work
std::this_thread::sleep_for(1000ms);
FM10K::FM10K::wait(1000);
} while (!stopLoop);
break;
}else{
std::cout << "fail" << std::endl;
}
break;
}
FM10K::IES::getInstance().teardown();