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 server
import (
"encoding/hex"
"fmt"
"strconv"
"strings"
)
const (
EidLenHex = 32
EidIdxDie = 10
EidIdxFeStart = 12
EidIdxFeEnd = 14
EidIdxPortStart = 10
EidIdxPortEnd = 12
EidIdxUboeFirstByteStart = 12
EidIdxUboeFirstByteEnd = 14
EidUboeIPv4TailLen = 8
)
const (
DieIdBitMask = 0xC
DieIdBitShift = 2
UboeBitMask = 0xC
FeMask = 0x7F
phyPortMask = 0x3F
HexBase = 16
IntBitSize = 64
)
const (
UboeIPv4Byte0Start = 0
UboeIPv4Byte1Start = 2
UboeIPv4Byte2Start = 4
UboeIPv4ByteStep = 2
)
type UrmaDevice struct {
EidList []string
}
func GetPhyPortByEid(eid string) int {
s := eid[EidIdxPortStart:EidIdxPortEnd]
v, err := strconv.ParseInt(s, HexBase, IntBitSize)
if err != nil {
return -1
}
return int(v & int64(phyPortMask))
}
func GetPgEid(eids []string) (string, error) {
for _, eid := range eids {
if GetPhyPortByEid(eid) == phyPortMask {
return eid, nil
}
}
return "", fmt.Errorf("pg eid not found")
}
func IsPgEid(eid string) bool {
return GetPhyPortByEid(eid) == phyPortMask
}
func GetDieIdByEid(eid string) int {
ch := eid[EidIdxDie:EidIdxDie+1]
v, err := strconv.ParseInt(ch, HexBase, IntBitSize)
if err != nil {
return -1
}
return int((v & int64(DieIdBitMask)) >> DieIdBitShift)
}
func GetFeIdByEid(eid string) int {
s := eid[EidIdxFeStart:EidIdxFeEnd]
v, err := strconv.ParseInt(s, HexBase, IntBitSize)
if err != nil {
return -1
}
return int(v & int64(FeMask))
}
func IsUboeEid(eid string) bool {
ch := eid[EidIdxUboeFirstByteEnd:EidIdxUboeFirstByteEnd+1]
v, err := strconv.ParseInt(ch, HexBase, IntBitSize)
if err != nil {
return false
}
return (v & UboeBitMask) == UboeBitMask
}
func GetUboeIPv4ByEid(eid string) (string, error) {
ipHex := eid[len(eid)-EidUboeIPv4TailLen:]
firstByteHex := eid[EidIdxUboeFirstByteStart:EidIdxUboeFirstByteEnd]
b0, err0 := strconv.ParseInt(firstByteHex, HexBase, IntBitSize)
b1, err1 := strconv.ParseInt(ipHex[UboeIPv4Byte0Start:UboeIPv4Byte0Start+UboeIPv4ByteStep], HexBase, IntBitSize)
b2, err2 := strconv.ParseInt(ipHex[UboeIPv4Byte1Start:UboeIPv4Byte1Start+UboeIPv4ByteStep], HexBase, IntBitSize)
b3, err3 := strconv.ParseInt(ipHex[UboeIPv4Byte2Start:UboeIPv4Byte2Start+UboeIPv4ByteStep], HexBase, IntBitSize)
if err0 != nil || err1 != nil || err2 != nil || err3 != nil {
return "", fmt.Errorf("parse ip failed")
}
if b0 == 0xfe {
return "", fmt.Errorf("link-local ip, skip")
}
return fmt.Sprintf("%d.%d.%d.%d", b0, b1, b2, b3), nil
}
func (u *UrmaDevice) GetFeId() int {
if len(u.EidList) == 0 {
return -1
}
return GetFeIdByEid(u.EidList[0])
}
func (u *UrmaDevice) GetDieId() int {
if len(u.EidList) == 0 {
return -1
}
return GetDieIdByEid(u.EidList[0])
}
func (u *UrmaDevice) GetPgEid() (string, error) {
return GetPgEid(u.EidList)
}
func (u *UrmaDevice) IsUboe() bool {
if len(u.EidList) == 0 {
return false
}
return IsUboeEid(u.EidList[0])
}
func (u *UrmaDevice) GetUboeIPv4() (string, error) {
for _, eid := range u.EidList {
ip, err := GetUboeIPv4ByEid(eid)
if err == nil {
return ip, nil
}
}
return "", fmt.Errorf("no valid uboe ip found")
}
func (u *UrmaDevice) GetDieIdByEid(eid string) int {
return GetDieIdByEid(eid)
}
func (u *UrmaDevice) GetPhyPortByEid(eid string) int {
return GetPhyPortByEid(eid)
}
func RawBytesToEidString(raw []byte) string {
return strings.ToLower(hex.EncodeToString(raw))
}
type ParsedEid struct {
Eid string
Die int
Fe int
Port int
IsPg bool
}
type ParsedUrma struct {
Raw *UrmaDevice
Eids []ParsedEid
PgEid string
Die int
Fe int
IsUboe bool
IPv4 string
}
func ParseUrmaDevices(list []*UrmaDevice) []*ParsedUrma {
result := make([]*ParsedUrma, 0)
for _, u := range list {
if u == nil {
continue
}
p := &ParsedUrma{
Raw: u,
Eids: make([]ParsedEid, 0),
}
p.Die = u.GetDieId()
p.Fe = u.GetFeId()
p.IsUboe = u.IsUboe()
for _, eid := range u.EidList {
pe := ParsedEid{
Eid: eid,
Die: GetDieIdByEid(eid),
Fe: GetFeIdByEid(eid),
Port: GetPhyPortByEid(eid),
IsPg: IsPgEid(eid),
}
if pe.IsPg {
p.PgEid = eid
}
p.Eids = append(p.Eids, pe)
}
if p.IsUboe {
ip, _ := u.GetUboeIPv4()
p.IPv4 = ip
}
result = append(result, p)
}
return result
}