diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go index 4835484d0b6254f03c03188fcfe446c9ddc0e324..622b46f37b115dd27779a285284d177d75695230 100644 --- a/protocols/bgp/packet/bgp.go +++ b/protocols/bgp/packet/bgp.go @@ -57,17 +57,17 @@ const ( AdministrativeReset = 4 // Attribute Type Codes - OriginAttr = 1 - ASPathAttr = 2 - NextHopAttr = 3 - MEDAttr = 4 - LocalPrefAttr = 5 - AtomicAggrAttr = 6 - AggregatorAttr = 7 - CommunitiesAttr = 8 - AS4PathAttr = 17 - AS4AggregatorAttr = 18 - LargeCommunityAttr = 32 + OriginAttr = 1 + ASPathAttr = 2 + NextHopAttr = 3 + MEDAttr = 4 + LocalPrefAttr = 5 + AtomicAggrAttr = 6 + AggregatorAttr = 7 + CommunitiesAttr = 8 + AS4PathAttr = 17 + AS4AggregatorAttr = 18 + LargeCommunitiesAttr = 32 // ORIGIN values IGP = 0 diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index a6ee368aa67713d9359732752cfab31e91b22fc0..071a7c55b0f0c6207dcd124ff2d36043ab00365a 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -96,7 +96,7 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err if err := pa.decodeAS4Aggregator(buf); err != nil { return nil, consumed, fmt.Errorf("Failed to skip not supported AS4Aggregator: %v", err) } - case LargeCommunityAttr: + case LargeCommunitiesAttr: if err := pa.decodeLargeCommunities(buf); err != nil { return nil, consumed, fmt.Errorf("Failed to decode large communities: %v", err) } @@ -448,7 +448,7 @@ func (pa *PathAttribute) serialize(buf *bytes.Buffer) uint8 { pathAttrLen = pa.serializeAggregator(buf) case CommunitiesAttr: pathAttrLen = pa.serializeCommunities(buf) - case LargeCommunityAttr: + case LargeCommunitiesAttr: pathAttrLen = pa.serializeLargeCommunities(buf) } @@ -580,7 +580,7 @@ func (pa *PathAttribute) serializeLargeCommunities(buf *bytes.Buffer) uint8 { attrFlags = setTransitive(attrFlags) attrFlags = setPartial(attrFlags) buf.WriteByte(attrFlags) - buf.WriteByte(LargeCommunityAttr) + buf.WriteByte(LargeCommunitiesAttr) length := uint8(LargeCommunityLen * len(coms)) @@ -693,7 +693,25 @@ func LargeCommunityAttributeForString(s string) (*PathAttribute, error) { } return &PathAttribute{ - TypeCode: LargeCommunityAttr, + TypeCode: LargeCommunitiesAttr, + Value: coms, + }, nil +} + +func CommunityAttributeForString(s string) (*PathAttribute, error) { + strs := strings.Split(s, " ") + coms := make([]uint32, len(strs)) + + var err error + for i, str := range strs { + coms[i], err = ParseCommunityString(str) + if err != nil { + return nil, err + } + } + + return &PathAttribute{ + TypeCode: CommunitiesAttr, Value: coms, }, nil } diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index 0cc3c3f6861b0616a1b2e054b825626c58187bbc..75915d34c81f3895b92dfcdfdc43c91af094f971 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -1289,7 +1289,7 @@ func TestSerializeLargeCommunities(t *testing.T) { { name: "2 large communities", input: &PathAttribute{ - TypeCode: LargeCommunityAttr, + TypeCode: LargeCommunitiesAttr, Value: []LargeCommunity{ { GlobalAdministrator: 1, @@ -1314,7 +1314,7 @@ func TestSerializeLargeCommunities(t *testing.T) { { name: "empty list of communities", input: &PathAttribute{ - TypeCode: LargeCommunityAttr, + TypeCode: LargeCommunitiesAttr, Value: []LargeCommunity{}, }, expected: []byte{}, @@ -1345,7 +1345,7 @@ func TestSerializeCommunities(t *testing.T) { { name: "2 communities", input: &PathAttribute{ - TypeCode: LargeCommunityAttr, + TypeCode: LargeCommunitiesAttr, Value: []uint32{ 131080, 16778241, }, diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go index b1d1f745127941582b1f4c422acc45f9f7e0573e..b5b554dd60f5302b09a68bc5f37744137013f281 100644 --- a/protocols/bgp/server/fsm.go +++ b/protocols/bgp/server/fsm.go @@ -847,7 +847,7 @@ func (fsm *FSM) established() int { path.BGPPath.ASPathLen = pa.ASPathLen() case packet.CommunitiesAttr: path.BGPPath.Communities = pa.CommunityString() - case packet.LargeCommunityAttr: + case packet.LargeCommunitiesAttr: path.BGPPath.LargeCommunities = pa.LargeCommunityString() } } diff --git a/protocols/bgp/server/update_helper.go b/protocols/bgp/server/update_helper.go index 22bfeec52ad72e603583452c9bc9f70be314f4a7..6873ca8db7c50ce449f23d43777fdc2d27744965 100644 --- a/protocols/bgp/server/update_helper.go +++ b/protocols/bgp/server/update_helper.go @@ -46,10 +46,20 @@ func pathAttribues(p *route.Path, fsm *FSM) (*packet.PathAttribute, error) { func addOptionalPathAttribues(p *route.Path, parent *packet.PathAttribute) error { current := parent + if len(p.BGPPath.Communities) > 0 { + communities, err := packet.CommunityAttributeForString(p.BGPPath.Communities) + if err != nil { + return fmt.Errorf("Could not create communities attribute: %v", err) + } + + current.Next = communities + current = communities + } + if len(p.BGPPath.LargeCommunities) > 0 { largeCommunities, err := packet.LargeCommunityAttributeForString(p.BGPPath.LargeCommunities) if err != nil { - return fmt.Errorf("Could not create large community attribute: %v", err) + return fmt.Errorf("Could not create large communities attribute: %v", err) } current.Next = largeCommunities