From 7732db025f2733978dfe81be4396a92070d6e403 Mon Sep 17 00:00:00 2001
From: Daniel Czerwonk <daniel@dan-nrw.de>
Date: Thu, 31 May 2018 21:19:19 +0200
Subject: [PATCH] sending communities

---
 protocols/bgp/packet/bgp.go                  | 22 ++++++++---------
 protocols/bgp/packet/path_attributes.go      | 26 +++++++++++++++++---
 protocols/bgp/packet/path_attributes_test.go |  6 ++---
 protocols/bgp/server/fsm.go                  |  2 +-
 protocols/bgp/server/update_helper.go        | 12 ++++++++-
 5 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go
index 4835484d..622b46f3 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 a6ee368a..071a7c55 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 0cc3c3f6..75915d34 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 b1d1f745..b5b554dd 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 22bfeec5..6873ca8d 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
-- 
GitLab