Implement data-driven YAML switch/port/vlan configuration
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:
parent
51bf50076b
commit
704df5b09d
|
@ -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
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
|||
/cmake-build-debug
|
||||
/cmake-build-*
|
||||
/build
|
||||
.idea
|
||||
/deps/IES/build
|
9
.gitmodules
vendored
9
.gitmodules
vendored
|
@ -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
|
||||
|
|
|
@ -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
42
build-deps.sh
Executable 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
|
20
build-ies.sh
20
build-ies.sh
|
@ -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
288
config.example.yml
Normal 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
1
deps/argparse
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit b9583b42ab64aa6b985997fa88d1834d6de03a31
|
1
deps/rapidyaml
vendored
Submodule
1
deps/rapidyaml
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 6993a7c56f4d064997a4df63fc16380ef6381d68
|
1
deps/sha2
vendored
Submodule
1
deps/sha2
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 79116b5d5d449311c27a24e16c99d8bccb4d1301
|
|
@ -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++];
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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, ¶meter);
|
||||
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)
|
|
@ -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;
|
||||
};
|
|
@ -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"}},
|
||||
}}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
62
src/fsmd.cpp
62
src/fsmd.cpp
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue