diff options
author | Serguei Bezverkhi <sbezverk@cisco.com> | 2020-05-04 08:46:17 -0400 |
---|---|---|
committer | Serguei Bezverkhi <sbezverk@cisco.com> | 2020-05-04 08:46:17 -0400 |
commit | f11ece918f233e62a98c0d40b4ec3a90417aa3a6 (patch) | |
tree | 1ae3b5d543d3de18f529fd8a331dd5ed19bd4cdb | |
parent | df76b278eee6799463e0feec8396fb66a3280bb2 (diff) |
adding prefix_sid_attr
Signed-off-by: Serguei Bezverkhi <sbezverk@cisco.com>
-rw-r--r-- | pkg/packet/bgp/bgp.go | 234 | ||||
-rw-r--r-- | pkg/packet/bgp/prefix_sid.go | 303 |
2 files changed, 306 insertions, 231 deletions
diff --git a/pkg/packet/bgp/bgp.go b/pkg/packet/bgp/bgp.go index 7adabe95..98408109 100644 --- a/pkg/packet/bgp/bgp.go +++ b/pkg/packet/bgp/bgp.go @@ -7833,237 +7833,6 @@ type PathAttributeLs struct { TLVs []LsTLVInterface } -func (p *PathAttributeLs) Extract() *LsAttribute { - l := &LsAttribute{} - - for _, tlv := range p.TLVs { - switch v := tlv.(type) { - case *LsTLVNodeFlagBits: - l.Node.Flags = v.Extract() - - case *LsTLVOpaqueNodeAttr: - l.Node.Opaque = &v.Attr - - case *LsTLVNodeName: - l.Node.Name = &v.Name - - case *LsTLVIsisArea: - l.Node.IsisArea = &v.Area - - case *LsTLVLocalIPv4RouterID: - l.Node.LocalRouterID = &v.IP - l.Link.LocalRouterID = &v.IP - - case *LsTLVLocalIPv6RouterID: - l.Node.LocalRouterIDv6 = &v.IP - l.Link.LocalRouterIDv6 = &v.IP - - case *LsTLVSrCapabilities: - l.Node.SrCapabilties = v.Extract() - - case *LsTLVSrAlgorithm: - l.Node.SrAlgorithms = &v.Algorithm - - case *LsTLVSrLocalBlock: - l.Node.SrLocalBlock = v.Extract() - - case *LsTLVRemoteIPv4RouterID: - l.Link.RemoteRouterID = &v.IP - - case *LsTLVRemoteIPv6RouterID: - l.Link.RemoteRouterIDv6 = &v.IP - - case *LsTLVAdminGroup: - l.Link.AdminGroup = &v.AdminGroup - - case *LsTLVMaxLinkBw: - l.Link.Bandwidth = &v.Bandwidth - - case *LsTLVMaxReservableLinkBw: - l.Link.ReservableBandwidth = &v.Bandwidth - - case *LsTLVUnreservedBw: - l.Link.UnreservedBandwidth = &v.Bandwidth - - case *LsTLVSrlg: - l.Link.Srlgs = &v.Srlgs - - case *LsTLVTEDefaultMetric: - l.Link.DefaultTEMetric = &v.Metric - - case *LsTLVIGPMetric: - l.Link.IGPMetric = &v.Metric - - case *LsTLVOpaqueLinkAttr: - l.Link.Opaque = &v.Attr - - case *LsTLVLinkName: - l.Link.Name = &v.Name - - case *LsTLVAdjacencySID: - l.Link.SrAdjacencySID = &v.SID - - case *LsTLVIGPFlags: - l.Prefix.IGPFlags = v.Extract() - - case *LsTLVOpaquePrefixAttr: - l.Prefix.Opaque = &v.Attr - - case *LsTLVPrefixSID: - l.Prefix.SrPrefixSID = &v.SID - } - } - - return l -} - -func (p *PathAttributeLs) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { - tlvs, err := p.PathAttribute.DecodeFromBytes(data) - if err != nil { - return err - } - - for len(tlvs) >= tlvHdrLen { - t := &LsTLV{} - _, err := t.DecodeFromBytes(tlvs) - if err != nil { - return err - } - - var tlv LsTLVInterface - switch t.Type { - // Node NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.1) - case LS_TLV_NODE_FLAG_BITS: - tlv = &LsTLVNodeFlagBits{} - - case LS_TLV_OPAQUE_NODE_ATTR: - tlv = &LsTLVOpaqueNodeAttr{} - - case LS_TLV_NODE_NAME: - tlv = &LsTLVNodeName{} - - case LS_TLV_ISIS_AREA: - tlv = &LsTLVIsisArea{} - - // Used by Link NLRI as well. - case LS_TLV_IPV4_LOCAL_ROUTER_ID: - tlv = &LsTLVLocalIPv4RouterID{} - - // Used by Link NLRI as well. - case LS_TLV_IPV6_LOCAL_ROUTER_ID: - tlv = &LsTLVLocalIPv6RouterID{} - - // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Node NLRI - case LS_TLV_SR_CAPABILITIES: - tlv = &LsTLVSrCapabilities{} - - case LS_TLV_SR_ALGORITHM: - tlv = &LsTLVSrAlgorithm{} - - case LS_TLV_SR_LOCAL_BLOCK: - tlv = &LsTLVSrLocalBlock{} - - // Link NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.2) - case LS_TLV_IPV4_REMOTE_ROUTER_ID: - tlv = &LsTLVRemoteIPv4RouterID{} - - case LS_TLV_IPV6_REMOTE_ROUTER_ID: - tlv = &LsTLVRemoteIPv6RouterID{} - - case LS_TLV_ADMIN_GROUP: - tlv = &LsTLVAdminGroup{} - - case LS_TLV_MAX_LINK_BANDWIDTH: - tlv = &LsTLVMaxLinkBw{} - - case LS_TLV_MAX_RESERVABLE_BANDWIDTH: - tlv = &LsTLVMaxReservableLinkBw{} - - case LS_TLV_UNRESERVED_BANDWIDTH: - tlv = &LsTLVUnreservedBw{} - - case LS_TLV_SRLG: - tlv = &LsTLVSrlg{} - - case LS_TLV_TE_DEFAULT_METRIC: - tlv = &LsTLVTEDefaultMetric{} - - case LS_TLV_IGP_METRIC: - tlv = &LsTLVIGPMetric{} - - case LS_TLV_OPAQUE_LINK_ATTR: - tlv = &LsTLVOpaqueLinkAttr{} - - case LS_TLV_LINK_NAME: - tlv = &LsTLVLinkName{} - - // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Link NLRI - case LS_TLV_ADJACENCY_SID: - tlv = &LsTLVAdjacencySID{} - - // Prefix NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.3) - case LS_TLV_IGP_FLAGS: - tlv = &LsTLVIGPFlags{} - - case LS_TLV_OPAQUE_PREFIX_ATTR: - tlv = &LsTLVOpaquePrefixAttr{} - - // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Prefix NLRI - case LS_TLV_PREFIX_SID: - tlv = &LsTLVPrefixSID{} - - default: - tlvs = tlvs[t.Len():] - continue - } - - if err := tlv.DecodeFromBytes(tlvs); err != nil { - return err - } - tlvs = tlvs[t.Len():] - - p.TLVs = append(p.TLVs, tlv) - } - - return nil -} - -func (p *PathAttributeLs) Serialize(options ...*MarshallingOption) ([]byte, error) { - buf := []byte{} - - for _, tlv := range p.TLVs { - s, err := tlv.Serialize() - if err != nil { - return nil, err - } - buf = append(buf, s...) - } - - return p.PathAttribute.Serialize(buf, options...) -} - -func (p *PathAttributeLs) String() string { - var buf bytes.Buffer - - for _, tlv := range p.TLVs { - buf.WriteString(fmt.Sprintf("%s ", tlv.String())) - } - - return fmt.Sprintf("{LsAttributes: %s}", buf.String()) -} - -func (p *PathAttributeLs) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type BGPAttrType `json:"type"` - Flags BGPAttrFlag `json:"flags"` - LsAttribute - }{ - p.GetType(), - p.GetFlags(), - *p.Extract(), - }) -} - func AfiSafiToRouteFamily(afi uint16, safi uint8) RouteFamily { return RouteFamily(int(afi)<<16 | int(safi)) } @@ -8285,6 +8054,7 @@ const ( _ BGP_ATTR_TYPE_LS // = 29 BGP_ATTR_TYPE_LARGE_COMMUNITY BGPAttrType = 32 + BGP_ATTR_TYPE_PREFIX_SID = 40 ) // NOTIFICATION Error Code RFC 4271 4.5. @@ -12373,6 +12143,8 @@ func GetPathAttribute(data []byte) (PathAttributeInterface, error) { return &PathAttributeLargeCommunities{}, nil case BGP_ATTR_TYPE_LS: return &PathAttributeLs{}, nil + case BGP_ATTR_TYPE_PREFIX_SID: + return &PathAttributePrefixSID{}, nil } return &PathAttributeUnknown{}, nil } diff --git a/pkg/packet/bgp/prefix_sid.go b/pkg/packet/bgp/prefix_sid.go new file mode 100644 index 00000000..4ae727f5 --- /dev/null +++ b/pkg/packet/bgp/prefix_sid.go @@ -0,0 +1,303 @@ +package bgp + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" +) + +type PrefixSIDTLVType uint16 + +type PrefixSIDTLV struct { + Type PrefixSIDTLVType + Length uint16 +} + +type PrefixSIDTLVInterface interface { + Len() int + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + String() string + MarshalJSON() ([]byte, error) +} + +type PathAttributePrefixSID struct { + PathAttribute + TLVs []PrefixSIDTLVInterface +} + +func (s *PrefixSIDTLV) Len() int { + return int(s.Length) + tlvHdrLen +} + +func (s *PrefixSIDTLV) Serialize(value []byte) ([]byte, error) { + if len(value) != int(s.Length) { + return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed") + } + + buf := make([]byte, tlvHdrLen+len(value)) + binary.BigEndian.PutUint16(buf[:2], uint16(s.Type)) + binary.BigEndian.PutUint16(buf[2:4], uint16(s.Length)) + copy(buf[4:], value) + + return buf, nil +} + +func (s *PrefixSIDTLV) DecodeFromBytes(data []byte) ([]byte, error) { + if len(data) < tlvHdrLen { + return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed") + } + // l.Type = PrefixSIDTLVType(binary.BigEndian.Uint16(data[:2])) + // l.Length = binary.BigEndian.Uint16(data[2:4]) + + // if len(data) < l.Len() { + // return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed") + // } + + return data[tlvHdrLen:s.Len()], nil +} + +//type LsAttributePrefix struct { +// IGPFlags *LsIGPFlags `json:"igp_flags,omitempty"` +// Opaque *[]byte `json:"opaque,omitempty"` +// +// SrPrefixSID *uint32 `json:"sr_prefix_sid,omitempty"` +//} + +type PrefixSIDAttribute struct { + // Node LsAttributeNode `json:"node"` + // Link LsAttributeLink `json:"link"` + // Prefix LsAttributePrefix `json:"prefix"` +} + +func (p *PathAttributePrefixSID) Extract() *PrefixSIDAttribute { + s := &PrefixSIDAttribute{} + + // for _, tlv := range p.TLVs { + // switch v := tlv.(type) { + // case *LsTLVNodeFlagBits: + // l.Node.Flags = v.Extract() + + // case *LsTLVOpaqueNodeAttr: + // l.Node.Opaque = &v.Attr + + // case *LsTLVNodeName: + // l.Node.Name = &v.Name + + // case *LsTLVIsisArea: + // l.Node.IsisArea = &v.Area + + // case *LsTLVLocalIPv4RouterID: + // l.Node.LocalRouterID = &v.IP + // l.Link.LocalRouterID = &v.IP + + // case *LsTLVLocalIPv6RouterID: + // l.Node.LocalRouterIDv6 = &v.IP + // l.Link.LocalRouterIDv6 = &v.IP + + // case *LsTLVSrCapabilities: + // l.Node.SrCapabilties = v.Extract() + + // case *LsTLVSrAlgorithm: + // l.Node.SrAlgorithms = &v.Algorithm + + // case *LsTLVSrLocalBlock: + // l.Node.SrLocalBlock = v.Extract() + + // case *LsTLVRemoteIPv4RouterID: + // l.Link.RemoteRouterID = &v.IP + + // case *LsTLVRemoteIPv6RouterID: + // l.Link.RemoteRouterIDv6 = &v.IP + + // case *LsTLVAdminGroup: + // l.Link.AdminGroup = &v.AdminGroup + + // case *LsTLVMaxLinkBw: + // l.Link.Bandwidth = &v.Bandwidth + + // case *LsTLVMaxReservableLinkBw: + // l.Link.ReservableBandwidth = &v.Bandwidth + + // case *LsTLVUnreservedBw: + // l.Link.UnreservedBandwidth = &v.Bandwidth + + // case *LsTLVSrlg: + // l.Link.Srlgs = &v.Srlgs + + // case *LsTLVTEDefaultMetric: + // l.Link.DefaultTEMetric = &v.Metric + + // case *LsTLVIGPMetric: + // l.Link.IGPMetric = &v.Metric + + // case *LsTLVOpaqueLinkAttr: + // l.Link.Opaque = &v.Attr + + // case *LsTLVLinkName: + // l.Link.Name = &v.Name + + // case *LsTLVAdjacencySID: + // l.Link.SrAdjacencySID = &v.SID + + // case *LsTLVIGPFlags: + // l.Prefix.IGPFlags = v.Extract() + + // case *LsTLVOpaquePrefixAttr: + // l.Prefix.Opaque = &v.Attr + + // case *LsTLVPrefixSID: + // l.Prefix.SrPrefixSID = &v.SID + // } + // } + + return s +} + +func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + tlvs, err := p.PathAttribute.DecodeFromBytes(data) + if err != nil { + return err + } + + for len(tlvs) >= tlvHdrLen { + t := &PrefixSIDTLV{} + _, err := t.DecodeFromBytes(tlvs) + if err != nil { + return err + } + + var tlv PrefixSIDTLVInterface + // switch t.Type { + // // Node NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.1) + // case LS_TLV_NODE_FLAG_BITS: + // tlv = &LsTLVNodeFlagBits{} + + // case LS_TLV_OPAQUE_NODE_ATTR: + // tlv = &LsTLVOpaqueNodeAttr{} + + // case LS_TLV_NODE_NAME: + // tlv = &LsTLVNodeName{} + + // case LS_TLV_ISIS_AREA: + // tlv = &LsTLVIsisArea{} + + // // Used by Link NLRI as well. + // case LS_TLV_IPV4_LOCAL_ROUTER_ID: + // tlv = &LsTLVLocalIPv4RouterID{} + + // // Used by Link NLRI as well. + // case LS_TLV_IPV6_LOCAL_ROUTER_ID: + // tlv = &LsTLVLocalIPv6RouterID{} + + // // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Node NLRI + // case LS_TLV_SR_CAPABILITIES: + // tlv = &LsTLVSrCapabilities{} + + // case LS_TLV_SR_ALGORITHM: + // tlv = &LsTLVSrAlgorithm{} + + // case LS_TLV_SR_LOCAL_BLOCK: + // tlv = &LsTLVSrLocalBlock{} + + // // Link NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.2) + // case LS_TLV_IPV4_REMOTE_ROUTER_ID: + // tlv = &LsTLVRemoteIPv4RouterID{} + + // case LS_TLV_IPV6_REMOTE_ROUTER_ID: + // tlv = &LsTLVRemoteIPv6RouterID{} + + // case LS_TLV_ADMIN_GROUP: + // tlv = &LsTLVAdminGroup{} + + // case LS_TLV_MAX_LINK_BANDWIDTH: + // tlv = &LsTLVMaxLinkBw{} + + // case LS_TLV_MAX_RESERVABLE_BANDWIDTH: + // tlv = &LsTLVMaxReservableLinkBw{} + + // case LS_TLV_UNRESERVED_BANDWIDTH: + // tlv = &LsTLVUnreservedBw{} + + // case LS_TLV_SRLG: + // tlv = &LsTLVSrlg{} + + // case LS_TLV_TE_DEFAULT_METRIC: + // tlv = &LsTLVTEDefaultMetric{} + + // case LS_TLV_IGP_METRIC: + // tlv = &LsTLVIGPMetric{} + + // case LS_TLV_OPAQUE_LINK_ATTR: + // tlv = &LsTLVOpaqueLinkAttr{} + + // case LS_TLV_LINK_NAME: + // tlv = &LsTLVLinkName{} + + // // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Link NLRI + // case LS_TLV_ADJACENCY_SID: + // tlv = &LsTLVAdjacencySID{} + + // // Prefix NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.3) + // case LS_TLV_IGP_FLAGS: + // tlv = &LsTLVIGPFlags{} + + // case LS_TLV_OPAQUE_PREFIX_ATTR: + // tlv = &LsTLVOpaquePrefixAttr{} + + // // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Prefix NLRI + // case LS_TLV_PREFIX_SID: + // tlv = &LsTLVPrefixSID{} + + // default: + // tlvs = tlvs[t.Len():] + // continue + // } + + if err := tlv.DecodeFromBytes(tlvs); err != nil { + return err + } + tlvs = tlvs[t.Len():] + + p.TLVs = append(p.TLVs, tlv) + } + + return nil +} + +func (p *PathAttributePrefixSID) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := []byte{} + + for _, tlv := range p.TLVs { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributePrefixSID) String() string { + var buf bytes.Buffer + + for _, tlv := range p.TLVs { + buf.WriteString(fmt.Sprintf("%s ", tlv.String())) + } + + return fmt.Sprintf("{LsAttributes: %s}", buf.String()) +} + +func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Flags BGPAttrFlag `json:"flags"` + PrefixSIDAttribute + }{ + p.GetType(), + p.GetFlags(), + *p.Extract(), + }) +} |