diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index 8416f972151f7f99deaf1288bf991d930172bc1f..f1aae242153e09da32de808fabe40efbcc719456 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -235,25 +235,12 @@ func (pa *PathAttribute) decodeAggregator(buf *bytes.Buffer) error { 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.Address = fourBytesToUint32(addr) - + p += 6 pa.Value = aggr - p += 4 - return dumpNBytes(buf, pa.Length-p) } @@ -505,10 +492,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 { @@ -651,6 +642,23 @@ func PathAttributes(p *route.Path, iBGP bool) (*PathAttribute, error) { last.Next = nextHop last = nextHop + if p.BGPPath.AtomicAggregate { + atomicAggr := &PathAttribute{ + TypeCode: AtomicAggrAttr, + } + last.Next = atomicAggr + last = atomicAggr + } + + if p.BGPPath.Aggregator != nil { + aggregator := &PathAttribute{ + TypeCode: AggregatorAttr, + Value: p.BGPPath.Aggregator, + } + last.Next = aggregator + last = aggregator + } + if iBGP { localPref := &PathAttribute{ TypeCode: LocalPrefAttr, diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index 7cd0887c2795eac3492d697e287ebbe090d8038d..4a0966e6b3dee2a6bbbf3bb4712247eefc7696e1 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -1138,15 +1138,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, }, } @@ -1511,7 +1515,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"), + }, }, }, }, @@ -1530,7 +1537,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 @@ -1538,7 +1545,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 @@ -1577,8 +1584,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 @@ -1716,7 +1724,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"), + }, }, }, }, @@ -1735,7 +1746,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 @@ -1745,7 +1756,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 @@ -1784,8 +1795,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 3a1379bbc654dc616c9c5a5fd2c9dae5eba23c52..b5740c57b9d32ef299d2e783c87b16d06a6e0b14 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -245,7 +245,8 @@ func (s *establishedState) processAttributes(attrs *packet.PathAttribute, path * path.BGPPath.ASPath = pa.Value.(types.ASPath) path.BGPPath.ASPathLen = path.BGPPath.ASPath.Length() case packet.AggregatorAttr: - path.BGPPath.Aggregator = pa.Value.(types.Aggregator) + aggr := pa.Value.(types.Aggregator) + path.BGPPath.Aggregator = &aggr case packet.AtomicAggrAttr: path.BGPPath.AtomicAggregate = true case packet.CommunitiesAttr: diff --git a/route/bgp_path.go b/route/bgp_path.go index 314c8505e93ea96bc52c475403f4495e4aa87650..ee9aca8343129a52aebf5eac6cd487dc489cb466 100644 --- a/route/bgp_path.go +++ b/route/bgp_path.go @@ -21,7 +21,7 @@ type BGPPath struct { MED uint32 EBGP bool AtomicAggregate bool - Aggregator types.Aggregator + Aggregator *types.Aggregator BGPIdentifier uint32 Source bnet.IP Communities []uint32