diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go index e008205a2ad95e97872c0a691a479efe42888c24..77b861110faf912a4ddbb0bb3510072b877a659c 100644 --- a/protocols/bgp/packet/bgp.go +++ b/protocols/bgp/packet/bgp.go @@ -14,6 +14,7 @@ const ( NLRIMaxLen = 5 CommunityLen = 4 LargeCommunityLen = 12 + ClusterIDLen = 4 OpenMsg = 1 UpdateMsg = 2 @@ -66,6 +67,8 @@ const ( AtomicAggrAttr = 6 AggregatorAttr = 7 CommunitiesAttr = 8 + OriginatorIDAttr = 9 + ClusterListAttr = 10 AS4PathAttr = 17 AS4AggregatorAttr = 18 LargeCommunitiesAttr = 32 diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index 77025f38ef976917f088509a8481aa3e53a363a5..8544d86b4f88d97e2a308c4c9387f88ec2b971cd 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -99,6 +99,14 @@ func decodePathAttr(buf *bytes.Buffer, opt *types.Options) (pa *PathAttribute, c if err := pa.decodeCommunities(buf); err != nil { return nil, consumed, fmt.Errorf("Failed to decode Community: %v", err) } + case OriginatorIDAttr: + if err := pa.decodeOriginatorID(buf); err != nil { + return nil, consumed, fmt.Errorf("Failed to decode OriginatorID: %v", err) + } + case ClusterListAttr: + if err := pa.decodeClusterList(buf); err != nil { + return nil, consumed, fmt.Errorf("Failed to decode OriginatorID: %v", err) + } case MultiProtocolReachNLRICode: if err := pa.decodeMultiProtocolReachNLRI(buf); err != nil { return nil, consumed, fmt.Errorf("Failed to multi protocol reachable NLRI: %v", err) @@ -364,6 +372,30 @@ func (pa *PathAttribute) decodeUint32(buf *bytes.Buffer, attrName string) error return nil } +func (pa *PathAttribute) decodeOriginatorID(buf *bytes.Buffer) error { + return pa.decodeUint32(buf, "OriginatorID") +} + +func (pa *PathAttribute) decodeClusterList(buf *bytes.Buffer) error { + if pa.Length%ClusterIDLen != 0 { + return fmt.Errorf("Unable to read ClusterList path attribute. Length %d is not divisible by %d", pa.Length, ClusterIDLen) + } + + count := pa.Length / ClusterIDLen + cids := make([]uint32, count) + + for i := uint16(0); i < count; i++ { + v, err := read4BytesAsUint32(buf) + if err != nil { + return err + } + cids[i] = v + } + + pa.Value = cids + return nil +} + func (pa *PathAttribute) setLength(buf *bytes.Buffer) (int, error) { bytesRead := 0 if pa.ExtendedLength { diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index d881fa7eb8b99c5480574272f3315076d2f5a302..7224d4e1047e28c5ab6b1999db01b9dcbd2d5e4d 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -293,6 +293,10 @@ func (s *establishedState) processAttributes(attrs *packet.PathAttribute, path * path.BGPPath.Communities = pa.Value.([]uint32) case packet.LargeCommunitiesAttr: path.BGPPath.LargeCommunities = pa.Value.([]types.LargeCommunity) + case packet.OriginatorIDAttr: + path.BGPPath.OriginatorID = pa.Value.(uint32) + case packet.ClusterListAttr: + path.BGPPath.ClusterList = pa.Value.([]uint32) default: unknownAttr := s.processUnknownAttribute(pa) if unknownAttr != nil {