diff --git a/routingtable/filter/actions/add_community_action.go b/routingtable/filter/actions/add_community_action.go new file mode 100644 index 0000000000000000000000000000000000000000..01ad05f62936574bb576d55fe1c7bcf23697a38f --- /dev/null +++ b/routingtable/filter/actions/add_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 AddCommunityAction struct { + communities []uint32 +} + +func NewAddCommunityAction(coms []uint32) *AddCommunityAction { + return &AddCommunityAction{ + communities: coms, + } +} + +func (a *AddCommunityAction) 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.Communities = modified.BGPPath.Communities + " " + packet.CommunityStringForUint32(com) + } + modified.BGPPath.Communities = strings.TrimLeft(modified.BGPPath.Communities, " ") + + return modified, false +} diff --git a/routingtable/filter/actions/add_community_action_test.go b/routingtable/filter/actions/add_community_action_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0687e86c4bc80b8648d172cb125449962dea9cf6 --- /dev/null +++ b/routingtable/filter/actions/add_community_action_test.go @@ -0,0 +1,57 @@ +package actions + +import ( + "testing" + + "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/route" + "github.com/stretchr/testify/assert" +) + +func TestAddingCommunities(t *testing.T) { + tests := []struct { + name string + current string + communities []uint32 + expected string + }{ + { + name: "add one to empty", + communities: []uint32{ + 65538, + }, + expected: "(1,2)", + }, + { + name: "add one to existing", + current: "(1,2)", + communities: []uint32{ + 196612, + }, + expected: "(1,2) (3,4)", + }, + { + name: "add two to existing", + current: "(1,2)", + communities: []uint32{ + 196612, 327686, + }, + expected: "(1,2) (3,4) (5,6)", + }, + } + + for _, test := range tests { + t.Run(test.name, func(te *testing.T) { + p := &route.Path{ + BGPPath: &route.BGPPath{ + Communities: test.current, + }, + } + + a := NewAddCommunityAction(test.communities) + modPath, _ := a.Do(net.Prefix{}, p) + + assert.Equal(te, test.expected, modPath.BGPPath.Communities) + }) + } +}