diff options
Diffstat (limited to 'pkg/packet/bgp')
-rw-r--r-- | pkg/packet/bgp/bgp.go | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/pkg/packet/bgp/bgp.go b/pkg/packet/bgp/bgp.go index 98408109..20d210ab 100644 --- a/pkg/packet/bgp/bgp.go +++ b/pkg/packet/bgp/bgp.go @@ -28,6 +28,8 @@ import ( "sort" "strconv" "strings" + + "github.com/golang/glog" ) type MarshallingOption struct { @@ -7833,6 +7835,237 @@ 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)) } @@ -12144,6 +12377,7 @@ func GetPathAttribute(data []byte) (PathAttributeInterface, error) { case BGP_ATTR_TYPE_LS: return &PathAttributeLs{}, nil case BGP_ATTR_TYPE_PREFIX_SID: + glog.Infof("><SB> BGP Prefix SI attribute detected: %+v", data) return &PathAttributePrefixSID{}, nil } return &PathAttributeUnknown{}, nil |