-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathconfig.go
188 lines (158 loc) · 5.01 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
* Copyright 2020, 2021, 2022 Hewlett Packard Enterprise Development LP
* Other additional copyright holders may be indicated within.
*
* The entirety of this work is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fabric
import (
_ "embed"
"fmt"
"io/ioutil"
"os"
"gopkg.in/yaml.v2"
sf "github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models"
)
//go:embed config_default.yaml
var configFileDefault []byte
//go:embed config_dp1a.yaml
var configFileDP1a []byte
type ConfigFile struct {
Version string
Metadata struct {
Name string
}
ManagementConfig ManagementConfig `yaml:"managementConfig"`
Switches []SwitchConfig
ManagementPortCount int
UpstreamPortCount int
DownstreamPortCount int
}
type ManagementConfig struct {
PrimaryDevice int32 `yaml:"primaryDevice"`
SecondaryDevice int32 `yaml:"secondaryDevice"`
}
type SwitchConfig struct {
Id string
Metadata struct {
Name string
}
PciGen int32 `yaml:"pciGen"`
Ports []PortConfig
ManagementPortCount int
UpstreamPortCount int
DownstreamPortCount int
}
type PortConfig struct {
Id string
Name string
Type string
Port int
Slot int
Width int
}
func loadConfig() (*ConfigFile, error) {
var config = new(ConfigFile)
var configFile = findConfig()
if err := yaml.Unmarshal(configFile, config); err != nil {
return config, err
}
// For usability we convert the port index to a string - this
// allows for easier comparisons for functions receiving portId
// as a string. We also tally the number of each port type
for switchIdx := range config.Switches {
s := &config.Switches[switchIdx]
for _, p := range s.Ports {
switch p.getPortType() {
case sf.MANAGEMENT_PORT_PV130PT:
s.ManagementPortCount++
if s.UpstreamPortCount != 0 {
return nil, fmt.Errorf("management USP must be listed first in config.yaml")
}
case sf.UPSTREAM_PORT_PV130PT:
s.UpstreamPortCount++
case sf.DOWNSTREAM_PORT_PV130PT:
s.DownstreamPortCount++
case sf.INTERSWITCH_PORT_PV130PT:
continue
default:
return nil, fmt.Errorf("unhandled port type %s in config.yaml", p.Type)
}
}
config.ManagementPortCount += s.ManagementPortCount
config.UpstreamPortCount += s.UpstreamPortCount
config.DownstreamPortCount += s.DownstreamPortCount
}
// Only a single management endpoint for ALL switches (but unique ports)
if config.ManagementPortCount != len(config.Switches) {
if !config.IsManagementRoutingEnabled() {
return nil, fmt.Errorf("Switch Ports: Expected %d Management Ports, Received: %d", len(config.Switches), config.ManagementPortCount)
}
}
return config, nil
}
func findConfig() []byte {
// Detect which configuration we are running. DP1a is using port 32, which is a x4 port which
// maps to all drives (9 locally, 9 over the fabric interconnect). We identify this configuration
// using the known PCIe topology for DP1a, which has the device listed at address 0b:00.1.
devicePath := "/sys/bus/pci/devices/0000:0b:00.1/device"
if _, err := os.Stat(devicePath); !os.IsNotExist(err) {
device, _ := ioutil.ReadFile(devicePath)
if string(device) == "0x4200\n" {
return configFileDP1a
}
}
return configFileDefault
}
// Method returns True if the management configuration has routing enabled, False otherwise.
// Management Routing is when one PAX is controlled through another device - this is needed
// on bringup configurations where there is not a Rabbit-P that is connected to both systems.
func (c *ConfigFile) IsManagementRoutingEnabled() bool {
return c.ManagementConfig.PrimaryDevice != c.ManagementConfig.SecondaryDevice
}
// func (c *ConfigFile) findSwitch(switchId string) (*SwitchConfig, error) {
// for _, s := range c.Switches {
// if s.Id == switchId {
// return &s, nil
// }
// }
// return nil, fmt.Errorf("Switch %s not found", switchId)
// }
// func (c *ConfigFile) findSwitchPort(switchId string, portId string) (*PortConfig, error) {
// s, err := c.findSwitch(switchId)
// if err != nil {
// return nil, err
// }
// for _, port := range s.Ports {
// if portId == port.Id {
// return &port, nil
// }
// }
// return nil, fmt.Errorf("Switch %s Port %s not found", switchId, portId)
// }
func (p *PortConfig) getPortType() sf.PortV130PortType {
switch p.Type {
case "InterswitchPort":
return sf.INTERSWITCH_PORT_PV130PT
case "UpstreamPort":
return sf.UPSTREAM_PORT_PV130PT
case "DownstreamPort":
return sf.DOWNSTREAM_PORT_PV130PT
case "ManagementPort":
return sf.MANAGEMENT_PORT_PV130PT
default:
return sf.UNCONFIGURED_PORT_PV130PT
}
}