diff --git a/routingtable/filter/community_filter.go b/routingtable/filter/community_filter.go
new file mode 100644
index 0000000000000000000000000000000000000000..9d384e54ad0a58ee622e3d2b0bb1b857c867b0c3
--- /dev/null
+++ b/routingtable/filter/community_filter.go
@@ -0,0 +1,15 @@
+package filter
+
+import (
+	"strings"
+
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+)
+
+type CommunityFilter struct {
+	community uint32
+}
+
+func (f *CommunityFilter) Matches(communityString string) bool {
+	return strings.Contains(communityString, packet.CommunityStringForUint32(f.community))
+}
diff --git a/routingtable/filter/term_condition.go b/routingtable/filter/term_condition.go
index 003b9dcbc021e75cd28d3039efbad2d00bf1d109..a7e0a4330d21e1678d8aacc03e429632506cf61b 100644
--- a/routingtable/filter/term_condition.go
+++ b/routingtable/filter/term_condition.go
@@ -8,6 +8,7 @@ import (
 type TermCondition struct {
 	prefixLists           []*PrefixList
 	routeFilters          []*RouteFilter
+	communityFilters      []*CommunityFilter
 	largeCommunityFilters []*LargeCommunityFilter
 }
 
@@ -19,7 +20,10 @@ func NewTermCondition(prefixLists []*PrefixList, routeFilters []*RouteFilter) *T
 }
 
 func (f *TermCondition) Matches(p net.Prefix, pa *route.Path) bool {
-	return f.matchesAnyPrefixList(p) || f.machtchesAnyRouteFilter(p) || f.machtchesAnyLageCommunityFilter(pa)
+	return f.matchesAnyPrefixList(p) ||
+		f.machtchesAnyRouteFilter(p) ||
+		f.machtchesAnyLageCommunityFilter(pa) ||
+		f.machtchesAnyCommunityFilter(pa)
 }
 
 func (t *TermCondition) matchesAnyPrefixList(p net.Prefix) bool {
@@ -42,6 +46,20 @@ func (t *TermCondition) machtchesAnyRouteFilter(p net.Prefix) bool {
 	return false
 }
 
+func (t *TermCondition) machtchesAnyCommunityFilter(pa *route.Path) bool {
+	if pa.BGPPath == nil {
+		return false
+	}
+
+	for _, l := range t.communityFilters {
+		if l.Matches(pa.BGPPath.Communities) {
+			return true
+		}
+	}
+
+	return false
+}
+
 func (t *TermCondition) machtchesAnyLageCommunityFilter(pa *route.Path) bool {
 	if pa.BGPPath == nil {
 		return false
diff --git a/routingtable/filter/term_condition_test.go b/routingtable/filter/term_condition_test.go
index 6e9b89f20eb226faebdd3856fa4bc61a97388a4e..3d8558ab2d47abf957c5f8e294edccf06ab6fbb4 100644
--- a/routingtable/filter/term_condition_test.go
+++ b/routingtable/filter/term_condition_test.go
@@ -16,6 +16,7 @@ func TestMatches(t *testing.T) {
 		bgpPath               *route.BGPPath
 		prefixLists           []*PrefixList
 		routeFilters          []*RouteFilter
+		communityFilters      []*CommunityFilter
 		largeCommunityFilters []*LargeCommunityFilter
 		expected              bool
 	}{
@@ -108,6 +109,25 @@ func TestMatches(t *testing.T) {
 			},
 			expected: true,
 		},
+		{
+			name:   "community matches",
+			prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
+			bgpPath: &route.BGPPath{
+				Communities: "(1,2) (3,4) (5,6)",
+			},
+			communityFilters: []*CommunityFilter{
+				&CommunityFilter{196612}, // (3,4)
+			},
+			expected: true,
+		},
+		{
+			name:   "community does not match",
+			prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
+			communityFilters: []*CommunityFilter{
+				&CommunityFilter{196608}, // (3,0)
+			},
+			expected: false,
+		},
 		{
 			name:   "large community matches",
 			prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
@@ -145,6 +165,7 @@ func TestMatches(t *testing.T) {
 	for _, test := range tests {
 		t.Run(test.name, func(te *testing.T) {
 			f := NewTermCondition(test.prefixLists, test.routeFilters)
+			f.communityFilters = test.communityFilters
 			f.largeCommunityFilters = test.largeCommunityFilters
 
 			pa := &route.Path{