From 16a5c7faceae285c0180b9464d58ac18f5456236 Mon Sep 17 00:00:00 2001
From: Daniel Czerwonk <daniel@dan-nrw.de>
Date: Sun, 20 May 2018 00:07:55 +0200
Subject: [PATCH] added action to add large communities

---
 .../actions/add_large_community_action.go     | 34 +++++++++
 .../add_large_community_action_test.go        | 75 +++++++++++++++++++
 2 files changed, 109 insertions(+)
 create mode 100644 routingtable/filter/actions/add_large_community_action.go
 create mode 100644 routingtable/filter/actions/add_large_community_action_test.go

diff --git a/routingtable/filter/actions/add_large_community_action.go b/routingtable/filter/actions/add_large_community_action.go
new file mode 100644
index 00000000..17169c31
--- /dev/null
+++ b/routingtable/filter/actions/add_large_community_action.go
@@ -0,0 +1,34 @@
+package actions
+
+import (
+	"strings"
+
+	"github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+	"github.com/bio-routing/bio-rd/route"
+)
+
+type AddLargeCommunityAction struct {
+	communities []*packet.LargeCommunity
+}
+
+func NewAddLargeCommunityAction(coms []*packet.LargeCommunity) *AddLargeCommunityAction {
+	return &AddLargeCommunityAction{
+		communities: coms,
+	}
+}
+
+func (a *AddLargeCommunityAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) {
+	if pa.BGPPath == nil || len(a.communities) == 0 {
+		return pa, false
+	}
+
+	modified := pa.Copy()
+
+	for _, com := range a.communities {
+		modified.BGPPath.LargeCommunities = modified.BGPPath.LargeCommunities + " " + com.String()
+	}
+	modified.BGPPath.LargeCommunities = strings.TrimLeft(modified.BGPPath.LargeCommunities, " ")
+
+	return modified, false
+}
diff --git a/routingtable/filter/actions/add_large_community_action_test.go b/routingtable/filter/actions/add_large_community_action_test.go
new file mode 100644
index 00000000..d2c597fd
--- /dev/null
+++ b/routingtable/filter/actions/add_large_community_action_test.go
@@ -0,0 +1,75 @@
+package actions
+
+import (
+	"testing"
+
+	"github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+	"github.com/bio-routing/bio-rd/route"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestAddingLargeCommunities(t *testing.T) {
+	tests := []struct {
+		name        string
+		current     string
+		communities []*packet.LargeCommunity
+		expected    string
+	}{
+		{
+			name: "add one to empty",
+			communities: []*packet.LargeCommunity{
+				&packet.LargeCommunity{
+					GlobalAdministrator: 1,
+					DataPart1:           2,
+					DataPart2:           3,
+				},
+			},
+			expected: "(1,2,3)",
+		},
+		{
+			name:    "add one to existing",
+			current: "(5,6,7)",
+			communities: []*packet.LargeCommunity{
+				&packet.LargeCommunity{
+					GlobalAdministrator: 1,
+					DataPart1:           2,
+					DataPart2:           3,
+				},
+			},
+			expected: "(5,6,7) (1,2,3)",
+		},
+		{
+			name:    "add two to existing",
+			current: "(5,6,7)",
+			communities: []*packet.LargeCommunity{
+				&packet.LargeCommunity{
+					GlobalAdministrator: 1,
+					DataPart1:           2,
+					DataPart2:           3,
+				},
+				&packet.LargeCommunity{
+					GlobalAdministrator: 7,
+					DataPart1:           8,
+					DataPart2:           9,
+				},
+			},
+			expected: "(5,6,7) (1,2,3) (7,8,9)",
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(te *testing.T) {
+			p := &route.Path{
+				BGPPath: &route.BGPPath{
+					LargeCommunities: test.current,
+				},
+			}
+
+			a := NewAddLargeCommunityAction(test.communities)
+			modPath, _ := a.Do(net.Prefix{}, p)
+
+			assert.Equal(te, test.expected, modPath.BGPPath.LargeCommunities)
+		})
+	}
+}
-- 
GitLab