Skip to content

Commit

Permalink
Merge pull request #56 from trustywolf/feature/srv6
Browse files Browse the repository at this point in the history
Add explicit SRv6-TE Policy support
  • Loading branch information
watal committed Feb 19, 2023
2 parents 7db1528 + f86777a commit 29087f5
Show file tree
Hide file tree
Showing 5 changed files with 476 additions and 166 deletions.
2 changes: 1 addition & 1 deletion pkg/packet/pcep/capability.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func PolaCapability() []CapabilityInterface {
},
&PathSetupTypeCapability{
Length: uint16(10),
PathSetupTypes: Psts{PST_RSVP_TE, PST_SR_TE},
PathSetupTypes: Psts{PST_RSVP_TE, PST_SR_TE, PST_SRV6_TE},
SubTlvs: []TlvInterface{
&SrPceCapability{
UnlimitedMSD: false,
Expand Down
212 changes: 133 additions & 79 deletions pkg/packet/pcep/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ func NewKeepaliveMessage() (*KeepaliveMessage, error) {
return m, nil
}

// PCRpt Message
type PCRptMessage struct {
type StateReport struct {
SrpObject *SrpObject
LspObject *LspObject
EroObject *EroObject
Expand All @@ -147,65 +146,8 @@ type PCRptMessage struct {
VendorInformationObject *VendorInformationObject
}

func (m *PCRptMessage) DecodeFromBytes(messageBody []uint8) error {
// TODO: Supports multiple <state-report>'s stacked PCRpt Message.
// https://datatracker.ietf.org/doc/html/rfc8231#section-6.1
// Currently, when more than 2 <state-report> come in, One object has multiple object information.
var commonObjectHeader CommonObjectHeader
if err := commonObjectHeader.DecodeFromBytes(messageBody); err != nil {
return err
}

switch commonObjectHeader.ObjectClass {
case OC_BANDWIDTH:
bandwidthObject := &BandwidthObject{}
if err := bandwidthObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
m.BandwidthObjects = append(m.BandwidthObjects, bandwidthObject)
case OC_METRIC:
metricObject := &MetricObject{}
if err := metricObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
m.MetricObjects = append(m.MetricObjects, metricObject)
case OC_ERO:
if err := m.EroObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_LSPA:
if err := m.LspaObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_LSP:
if err := m.LspObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_SRP:
if err := m.SrpObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_ASSOCIATION:
if err := m.AssociationObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_VENDOR_INFORMATION:
if err := m.VendorInformationObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
default:
}

if int(commonObjectHeader.ObjectLength) < len(messageBody) {
if err := m.DecodeFromBytes(messageBody[commonObjectHeader.ObjectLength:]); err != nil {
return err
}
}
return nil
}

func NewPCRptMessage() *PCRptMessage {
m := &PCRptMessage{
func NewStateReport() (*StateReport, error) {
sr := &StateReport{
SrpObject: &SrpObject{},
LspObject: &LspObject{},
EroObject: &EroObject{},
Expand All @@ -215,30 +157,128 @@ func NewPCRptMessage() *PCRptMessage {
AssociationObject: &AssociationObject{},
VendorInformationObject: &VendorInformationObject{},
}
return m
return sr, nil
}

func (m *PCRptMessage) ToSRPolicy(pcc PccType) table.SRPolicy {
func (sr *StateReport) ToSRPolicy(pcc PccType) table.SRPolicy {
srPolicy := table.SRPolicy{
PlspId: m.LspObject.PlspId,
Name: m.LspObject.Name,
PlspId: sr.LspObject.PlspId,
Name: sr.LspObject.Name,
SegmentList: []table.Segment{},
SrcAddr: m.LspObject.SrcAddr,
DstAddr: m.LspObject.DstAddr,
SrcAddr: sr.LspObject.SrcAddr,
DstAddr: sr.LspObject.DstAddr,
}
if pcc == CISCO_LEGACY {
srPolicy.Color = m.VendorInformationObject.Color()
srPolicy.Preference = m.VendorInformationObject.Preference()
srPolicy.Color = sr.VendorInformationObject.Color()
srPolicy.Preference = sr.VendorInformationObject.Preference()
} else {
srPolicy.Color = m.AssociationObject.Color()
srPolicy.Preference = m.AssociationObject.Preference()
srPolicy.Color = sr.AssociationObject.Color()
srPolicy.Preference = sr.AssociationObject.Preference()
}

srPolicy.SegmentList = m.EroObject.ToSegmentList()
srPolicy.SegmentList = sr.EroObject.ToSegmentList()

return srPolicy
}

// PCRpt Message
type PCRptMessage struct {
StateReports []*StateReport
}

func (m *PCRptMessage) DecodeFromBytes(messageBody []uint8) error {
// To determine the delimitation of StateReports from the order of object classes
var previousOC uint8
var sr *StateReport
for len(messageBody) != 0 {
var commonObjectHeader CommonObjectHeader
if err := commonObjectHeader.DecodeFromBytes(messageBody); err != nil {
return err
}
switch commonObjectHeader.ObjectClass {
case OC_BANDWIDTH:
previousOC = OC_BANDWIDTH
bandwidthObject := &BandwidthObject{}
if err := bandwidthObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
sr.BandwidthObjects = append(sr.BandwidthObjects, bandwidthObject)
case OC_METRIC:
previousOC = OC_METRIC
metricObject := &MetricObject{}
if err := metricObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
sr.MetricObjects = append(sr.MetricObjects, metricObject)
case OC_ERO:
previousOC = OC_METRIC
if err := sr.EroObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_LSPA:
previousOC = OC_LSPA
if err := sr.LspaObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_LSP:
if previousOC != OC_SRP {
// If sr is not zero value, this StateReport is already updated.
var err error
if sr != nil {
m.StateReports = append(m.StateReports, sr)
}
sr, err = NewStateReport()
if err != nil {
return err
}
}

previousOC = OC_LSP
if err := sr.LspObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_SRP:
// If sr is not zero value, this StateReport is already updated.
var err error
if sr != nil {
m.StateReports = append(m.StateReports, sr)
}
sr, err = NewStateReport()
if err != nil {
return err
}

previousOC = OC_SRP
if err = sr.SrpObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_ASSOCIATION:
previousOC = OC_ASSOCIATION
if err := sr.AssociationObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
case OC_VENDOR_INFORMATION:
previousOC = OC_VENDOR_INFORMATION
if err := sr.VendorInformationObject.DecodeFromBytes(messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil {
return err
}
default:
}
messageBody = messageBody[commonObjectHeader.ObjectLength:]
}
if sr != nil {
m.StateReports = append(m.StateReports, sr)
}
return nil
}

func NewPCRptMessage() *PCRptMessage {
m := &PCRptMessage{
StateReports: []*StateReport{},
}
return m
}

// PCInitiate Message
type PCInitiateMessage struct {
SrpObject *SrpObject
Expand All @@ -254,15 +294,22 @@ func (m *PCInitiateMessage) Serialize() ([]uint8, error) {
if err != nil {
return nil, err
}
endpointsObjectLength, err := m.EndpointsObject.getByteLength()
if err != nil {
return nil, err
}
pcinitiateMessageLength := COMMON_HEADER_LENGTH +
m.SrpObject.getByteLength() +
m.LspObject.getByteLength() +
m.EndpointsObject.getByteLength() +
endpointsObjectLength +
eroObjectLength

byteSrpObject := m.SrpObject.Serialize()
byteLspObject := m.LspObject.Serialize()
byteEndpointsObject := m.EndpointsObject.Serialize()
byteEndpointsObject, err := m.EndpointsObject.Serialize()
if err != nil {
return nil, err
}
byteEroObject, err := m.EroObject.Serialize()
if err != nil {
return nil, err
Expand All @@ -272,8 +319,15 @@ func (m *PCInitiateMessage) Serialize() ([]uint8, error) {
byteAssociationObject := []uint8{}

if m.AssociationObject != nil {
byteAssociationObject = append(byteAssociationObject, m.AssociationObject.Serialize()...)
pcinitiateMessageLength += m.AssociationObject.getByteLength()
byteAssociationObject, err = m.AssociationObject.Serialize()
if err != nil {
return nil, err
}
associationObjectLength, err := m.AssociationObject.getByteLength()
if err != nil {
return nil, err
}
pcinitiateMessageLength += associationObjectLength
}
if m.VendorInformationObject != nil {
byteVendorInformationObject = append(byteVendorInformationObject, m.VendorInformationObject.Serialize()...)
Expand All @@ -299,13 +353,13 @@ func NewPCInitiateMessage(srpId uint32, lspName string, segmentList []table.Segm

m := &PCInitiateMessage{}
var err error
if m.SrpObject, err = NewSrpObject(srpId, false); err != nil {
if m.SrpObject, err = NewSrpObject(segmentList, srpId, false); err != nil {
return nil, err
}
if m.LspObject, err = NewLspObject(lspName, 0); err != nil { // PLSP-ID = 0
return nil, err
}
if m.EndpointsObject, err = NewEndpointsObject(OT_EP_IPV4, dstAddr, srcAddr); err != nil {
if m.EndpointsObject, err = NewEndpointsObject(dstAddr, srcAddr); err != nil {
return nil, err
}
if m.EroObject, err = NewEroObject(segmentList); err != nil {
Expand Down Expand Up @@ -365,7 +419,7 @@ func NewPCUpdMessage(srpId uint32, lspName string, plspId uint32, segmentList []
m := &PCUpdMessage{}
var err error

if m.SrpObject, err = NewSrpObject(srpId, false); err != nil {
if m.SrpObject, err = NewSrpObject(segmentList, srpId, false); err != nil {
return nil, err
}
if m.LspObject, err = NewLspObject(lspName, plspId); err != nil {
Expand Down
Loading

0 comments on commit 29087f5

Please sign in to comment.