diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go index f75ce7a0c4403e8d1530c198099d2cbefa605923..c6776ace6c41f6ccbfd8e2b126f38fc5c16d4798 100644 --- a/protocols/bgp/packet/bgp.go +++ b/protocols/bgp/packet/bgp.go @@ -140,8 +140,3 @@ type PathAttribute struct { Value interface{} Next *PathAttribute } - -type Aggretator struct { - Addr uint32 - ASN uint16 -} diff --git a/protocols/bgp/packet/decoder_test.go b/protocols/bgp/packet/decoder_test.go index b2ee41a00cd2fbb88e71e48cc4c7c4e525fdf497..a874ba1041d35c3ca3476251096cef5320dbbc70 100644 --- a/protocols/bgp/packet/decoder_test.go +++ b/protocols/bgp/packet/decoder_test.go @@ -1195,9 +1195,9 @@ func TestDecodeUpdateMsg(t *testing.T) { ExtendedLength: false, Length: 6, TypeCode: 7, - Value: Aggretator{ - ASN: uint16(258), - Addr: strAddr("10.11.12.13"), + Value: types.Aggregator{ + ASN: uint16(258), + Address: strAddr("10.11.12.13"), }, }, }, diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index 56eb039c21907c6d580dadc57459a5a2f03bb505..f592af68c359cae74837725d823d9cac5bc6075a 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -224,28 +224,15 @@ func (pa *PathAttribute) decodeLocalPref(buf *bytes.Buffer) error { } func (pa *PathAttribute) decodeAggregator(buf *bytes.Buffer) error { - aggr := Aggretator{} + aggr := types.Aggregator{} p := uint16(0) - err := decode(buf, []interface{}{&aggr.ASN}) + err := decode(buf, []interface{}{&aggr.ASN, &aggr.Address}) if err != nil { return err } - p += 2 - - addr := [4]byte{} - n, err := buf.Read(addr[:]) - if err != nil { - return err - } - if n != 4 { - return fmt.Errorf("Unable to read next hop: buf.Read read %d bytes", n) - } - aggr.Addr = fourBytesToUint32(addr) - + p += 6 pa.Value = aggr - p += 4 - return dumpNBytes(buf, pa.Length-p) } @@ -497,10 +484,14 @@ func (pa *PathAttribute) serializeAggregator(buf *bytes.Buffer) uint8 { attrFlags = setTransitive(attrFlags) buf.WriteByte(attrFlags) buf.WriteByte(AggregatorAttr) - length := uint8(2) + length := uint8(6) buf.WriteByte(length) - buf.Write(convert.Uint16Byte(pa.Value.(uint16))) - return 5 + + aggregator := pa.Value.(types.Aggregator) + buf.Write(convert.Uint16Byte(aggregator.ASN)) + buf.Write(convert.Uint32Byte(aggregator.Address)) + + return 9 } func (pa *PathAttribute) serializeCommunities(buf *bytes.Buffer) uint8 { @@ -622,33 +613,56 @@ func (pa *PathAttribute) AddOptionalPathAttributes(p *route.Path) *PathAttribute } // PathAttributes converts a path object into a linked list of path attributes -func PathAttributes(p *route.Path) (*PathAttribute, error) { +func PathAttributes(p *route.Path, iBGP bool) (*PathAttribute, error) { asPath := &PathAttribute{ TypeCode: ASPathAttr, Value: p.BGPPath.ASPath, } + last := asPath origin := &PathAttribute{ TypeCode: OriginAttr, Value: p.BGPPath.Origin, } - asPath.Next = origin + last.Next = origin + last = origin nextHop := &PathAttribute{ TypeCode: NextHopAttr, Value: p.BGPPath.NextHop, } - origin.Next = nextHop + last.Next = nextHop + last = nextHop + + if p.BGPPath.AtomicAggregate { + atomicAggr := &PathAttribute{ + TypeCode: AtomicAggrAttr, + } + last.Next = atomicAggr + last = atomicAggr + } - localPref := &PathAttribute{ - TypeCode: LocalPrefAttr, - Value: p.BGPPath.LocalPref, + if p.BGPPath.Aggregator != nil { + aggregator := &PathAttribute{ + TypeCode: AggregatorAttr, + Value: p.BGPPath.Aggregator, + } + last.Next = aggregator + last = aggregator + } + + if iBGP { + localPref := &PathAttribute{ + TypeCode: LocalPrefAttr, + Value: p.BGPPath.LocalPref, + } + last.Next = localPref + last = localPref } - nextHop.Next = localPref - optionals := localPref.AddOptionalPathAttributes(p) + optionals := last.AddOptionalPathAttributes(p) - last := optionals + last = optionals for _, unknownAttr := range p.BGPPath.UnknownAttributes { last.Next = &PathAttribute{ TypeCode: unknownAttr.TypeCode, diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index 93a0b2e515f0dfb9f0a0dde543085a37fb3c52c3..dea391e069527f65f33c946c421da91632d37373 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -563,9 +563,9 @@ func TestDecodeAggregator(t *testing.T) { wantFail: false, expected: &PathAttribute{ Length: 6, - Value: Aggretator{ - ASN: 222, - Addr: strAddr("10.20.30.40"), + Value: types.Aggregator{ + ASN: 222, + Address: strAddr("10.20.30.40"), }, }, }, @@ -1137,15 +1137,19 @@ func TestSerializeAggregator(t *testing.T) { name: "Test #1", input: &PathAttribute{ TypeCode: AggregatorAttr, - Value: uint16(174), + Value: types.Aggregator{ + ASN: 174, + Address: strAddr("10.20.30.40"), + }, }, expected: []byte{ 192, // Attribute flags 7, // Type - 2, // Length + 6, // Length 0, 174, // Value = 174 + 10, 20, 30, 40, }, - expectedLen: 5, + expectedLen: 9, }, } @@ -1510,7 +1514,10 @@ func TestSerialize(t *testing.T) { TypeCode: AtomicAggrAttr, Next: &PathAttribute{ TypeCode: AggregatorAttr, - Value: uint16(200), + Value: types.Aggregator{ + ASN: 200, + Address: strAddr("10.20.30.40"), + }, }, }, }, @@ -1529,7 +1536,7 @@ func TestSerialize(t *testing.T) { }, expected: []byte{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0, 86, // Length + 0, 90, // Length 2, // Msg Type // Withdraws @@ -1537,7 +1544,7 @@ func TestSerialize(t *testing.T) { 8, 10, // Withdraw 10/8 16, 192, 168, // Withdraw 192.168/16 - 0, 50, // Total Path Attribute Length + 0, 54, // Total Path Attribute Length // ORIGIN 64, // Attr. Flags @@ -1576,8 +1583,9 @@ func TestSerialize(t *testing.T) { // Aggregator 192, // Attr. Flags 7, // Attr. Type Code - 2, // Length + 6, // Length 0, 200, // Aggregator ASN = 200 + 10, 20, 30, 40, // Aggregator Address // NLRI 24, 8, 8, 8, // 8.8.8.0/24 @@ -1715,7 +1723,10 @@ func TestSerializeAddPath(t *testing.T) { TypeCode: AtomicAggrAttr, Next: &PathAttribute{ TypeCode: AggregatorAttr, - Value: uint16(200), + Value: types.Aggregator{ + ASN: 200, + Address: strAddr("10.20.30.40"), + }, }, }, }, @@ -1734,7 +1745,7 @@ func TestSerializeAddPath(t *testing.T) { }, expected: []byte{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0, 102, // Length + 0, 106, // Length 2, // Msg Type // Withdraws @@ -1744,7 +1755,7 @@ func TestSerializeAddPath(t *testing.T) { 0, 0, 0, 0, // Path Identifier 16, 192, 168, // Withdraw 192.168/16 - 0, 50, // Total Path Attribute Length + 0, 54, // Total Path Attribute Length // ORIGIN 64, // Attr. Flags @@ -1783,8 +1794,9 @@ func TestSerializeAddPath(t *testing.T) { // Aggregator 192, // Attr. Flags 7, // Attr. Type Code - 2, // Length + 6, // Length 0, 200, // Aggregator ASN = 200 + 10, 20, 30, 40, // Aggregator Address // NLRI 0, 0, 0, 0, // Path Identifier diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index 99fb64e52ce1bf05b99231b80e9f257c8bfc1c1f..9aced1fe480489ed116960262318750f74e7b5ee 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -244,6 +244,11 @@ func (s *establishedState) processAttributes(attrs *packet.PathAttribute, path * case packet.ASPathAttr: path.BGPPath.ASPath = pa.Value.(types.ASPath) path.BGPPath.ASPathLen = path.BGPPath.ASPath.Length() + case packet.AggregatorAttr: + aggr := pa.Value.(types.Aggregator) + path.BGPPath.Aggregator = &aggr + case packet.AtomicAggrAttr: + path.BGPPath.AtomicAggregate = true case packet.CommunitiesAttr: path.BGPPath.Communities = pa.Value.([]uint32) case packet.LargeCommunitiesAttr: diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index d7c32fd1dcdbeb362ab20799456a014725ba2c31..dedae8ef54a63f3afc73a355636534150c69492a 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -86,7 +86,7 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { for key, pathNLRIs := range u.toSend { budget = packet.MaxLen - packet.HeaderLen - packet.MinUpdateLen - int(pathNLRIs.path.BGPPath.Length()) - pathAttrs, err = packet.PathAttributes(pathNLRIs.path) + pathAttrs, err = packet.PathAttributes(pathNLRIs.path, u.iBGP) if err != nil { log.Errorf("Unable to get path attributes: %v", err) continue diff --git a/protocols/bgp/types/BUILD.bazel b/protocols/bgp/types/BUILD.bazel index cd582779e7275027d66fadef922165706b2c5003..5f94662087b2e46f593e4386d2bac21e65896225 100644 --- a/protocols/bgp/types/BUILD.bazel +++ b/protocols/bgp/types/BUILD.bazel @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "aggregator.go", "as_path.go", "community.go", "large_community.go", diff --git a/protocols/bgp/types/aggregator.go b/protocols/bgp/types/aggregator.go new file mode 100644 index 0000000000000000000000000000000000000000..8fba9cb384a16393a5aa4e0f939c5b185a6db346 --- /dev/null +++ b/protocols/bgp/types/aggregator.go @@ -0,0 +1,7 @@ +package types + +// Aggregator represents an AGGREGATOR attribute (type code 7) as in RFC4271 +type Aggregator struct { + ASN uint16 + Address uint32 +} diff --git a/route/bgp_path.go b/route/bgp_path.go index 9945739b62a2318dca4e7553a2487f9527c70b2e..fbca2255f620b8b49a9d7bc57490754316b412de 100644 --- a/route/bgp_path.go +++ b/route/bgp_path.go @@ -19,6 +19,8 @@ type BGPPath struct { Origin uint8 MED uint32 EBGP bool + AtomicAggregate bool + Aggregator *types.Aggregator BGPIdentifier uint32 Source uint32 Communities []uint32