diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go
index 41a2113f8e6cb85cb0250d0333908071dc03fd79..c3a80b93aa666e18525e702d12530d66381c36c9 100644
--- a/protocols/bgp/packet/bgp.go
+++ b/protocols/bgp/packet/bgp.go
@@ -51,13 +51,14 @@ const (
 	MalformedASPath           = 11
 
 	// Attribute Type Codes
-	OriginAttr     = 1
-	ASPathAttr     = 2
-	NextHopAttr    = 3
-	MEDAttr        = 4
-	LocalPrefAttr  = 5
-	AtomicAggrAttr = 6
-	AggregatorAttr = 7
+	OriginAttr      = 1
+	ASPathAttr      = 2
+	NextHopAttr     = 3
+	MEDAttr         = 4
+	LocalPrefAttr   = 5
+	AtomicAggrAttr  = 6
+	AggregatorAttr  = 7
+	CommunitiesAttr = 8
 
 	// ORIGIN values
 	IGP        = 0
diff --git a/protocols/bgp/packet/decoder_test.go b/protocols/bgp/packet/decoder_test.go
index a69b4acbcc8e985fad6a9a58637214d4c3496c49..c2222e6da95735a9faeedbb5db8cc12fbe34fb74 100644
--- a/protocols/bgp/packet/decoder_test.go
+++ b/protocols/bgp/packet/decoder_test.go
@@ -651,7 +651,6 @@ func TestDecodeUpdateMsg(t *testing.T) {
 				3,              // Attribute Type code (Next Hop)
 				4,              // Length
 				10, 11, 12, 13, // Next Hop
-
 			},
 			wantFail: false,
 			expected: &BGPUpdate{
@@ -745,7 +744,6 @@ func TestDecodeUpdateMsg(t *testing.T) {
 				4,          // Attribute Type code (Next Hop)
 				4,          // Length
 				0, 0, 1, 0, // MED 256
-
 			},
 			wantFail: false,
 			expected: &BGPUpdate{
@@ -852,7 +850,6 @@ func TestDecodeUpdateMsg(t *testing.T) {
 				5,          // Attribute Type code (Local Pref)
 				4,          // Length
 				0, 0, 1, 0, // Local Pref 256
-
 			},
 			wantFail: false,
 			expected: &BGPUpdate{
@@ -1262,6 +1259,94 @@ func TestDecodeUpdateMsg(t *testing.T) {
 				},
 			},
 		},
+		{
+			// 2 withdraws with two path attributes (Communities + Origin), valid update
+			testNum: 17,
+			input: []byte{0, 5, 8, 10, 16, 192, 168,
+				0, 16, // Total Path Attribute Length
+
+				0,          // Attribute flags
+				8,          // Attribute Type code (Community)
+				8,          // Length
+				0, 0, 1, 0, // Arbitrary Community
+				0, 0, 1, 1, // Arbitrary Community
+
+				255,  // Attribute flags
+				1,    // Attribute Type code (ORIGIN)
+				0, 1, // Length
+				2, // INCOMPLETE
+
+			},
+			wantFail: false,
+			expected: &BGPUpdate{
+				WithdrawnRoutesLen: 5,
+				WithdrawnRoutes: &NLRI{
+					IP:     strAddr("10.0.0.0"),
+					Pfxlen: 8,
+					Next: &NLRI{
+						IP:     strAddr("192.168.0.0"),
+						Pfxlen: 16,
+					},
+				},
+				TotalPathAttrLen: 16,
+				PathAttributes: &PathAttribute{
+					Optional:       false,
+					Transitive:     false,
+					Partial:        false,
+					ExtendedLength: false,
+					Length:         8,
+					TypeCode:       8,
+					Value:          []uint32{256, 257},
+					Next: &PathAttribute{
+						Optional:       true,
+						Transitive:     true,
+						Partial:        true,
+						ExtendedLength: true,
+						Length:         1,
+						TypeCode:       1,
+						Value:          uint8(2),
+					},
+				},
+			},
+		},
+		{
+			// 2 withdraws with two path attributes (ORIGIN + Community), invalid update (too short community)
+			testNum: 18,
+			input: []byte{0, 5, 8, 10, 16, 192, 168,
+				0, 11, // Total Path Attribute Length
+
+				255,  // Attribute flags
+				1,    // Attribute Type code (ORIGIN)
+				0, 1, // Length
+				2, // INCOMPLETE
+
+				0,       // Attribute flags
+				8,       // Attribute Type code (Community)
+				3,       // Length
+				0, 0, 1, // Arbitrary Community
+			},
+			wantFail: true,
+			expected: nil,
+		},
+		{
+			// 2 withdraws with two path attributes (ORIGIN + Community), invalid update (too long community)
+			testNum: 19,
+			input: []byte{0, 5, 8, 10, 16, 192, 168,
+				0, 13, // Total Path Attribute Length
+
+				255,  // Attribute flags
+				1,    // Attribute Type code (ORIGIN)
+				0, 1, // Length
+				2, // INCOMPLETE
+
+				0,             // Attribute flags
+				8,             // Attribute Type code (Community)
+				5,             // Length
+				0, 0, 1, 0, 1, // Arbitrary Community
+			},
+			wantFail: true,
+			expected: nil,
+		},
 	}
 
 	for _, test := range tests {
diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go
index 4db07c1d9f89b69ff292c7167228b3bfd47df3cf..846767989f400f1ede2fcf1e2c9202f33ad10974 100644
--- a/protocols/bgp/packet/path_attributes.go
+++ b/protocols/bgp/packet/path_attributes.go
@@ -84,6 +84,10 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err
 		}
 	case AtomicAggrAttr:
 		// Nothing to do for 0 octet long attribute
+	case CommunitiesAttr:
+		if err := pa.decodeCommunities(buf); err != nil {
+			return nil, consumed, fmt.Errorf("Failed to decode Community: %v", err)
+		}
 	default:
 		if err := pa.decodeUnknown(buf); err != nil {
 			return nil, consumed, fmt.Errorf("Failed to decode unknown attribute: %v", err)
@@ -227,6 +231,27 @@ func (pa *PathAttribute) decodeAggregator(buf *bytes.Buffer) error {
 	return dumpNBytes(buf, pa.Length-p)
 }
 
+func (pa *PathAttribute) decodeCommunities(buf *bytes.Buffer) error {
+	if pa.Length%4 != 0 {
+		return fmt.Errorf("Unable to read community path attribute length %d is not divisible by 4", pa.Length)
+	}
+	comNumber := pa.Length / 4
+	var com = make([]uint32, comNumber)
+	for i := uint16(0); i < comNumber; i++ {
+		c := [4]byte{}
+		n, err := buf.Read(c[:])
+		if err != nil {
+			return err
+		}
+		if n != 4 {
+			return fmt.Errorf("Unable to read next hop: buf.Read read %d bytes", n)
+		}
+		com[i] = fourBytesToUint32(c)
+	}
+	pa.Value = com
+	return nil
+}
+
 func (pa *PathAttribute) setLength(buf *bytes.Buffer) (int, error) {
 	bytesRead := 0
 	if pa.ExtendedLength {
diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go
index fc342e821871667f3d4fe7aab18e5d50e225674a..e20efb18015ea38b07587d043f76cdbfa531bba8 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -790,7 +790,7 @@ func (fsm *FSM) established() int {
 		case recvMsg := <-fsm.msgRecvCh:
 			msg, err := packet.Decode(bytes.NewBuffer(recvMsg.msg))
 			if err != nil {
-				fmt.Printf("Failed to decode BGP message: %v\n", recvMsg.msg)
+				fmt.Printf("Failed to decode BGP message: %v msg: %v\n", err, recvMsg.msg)
 				switch bgperr := err.(type) {
 				case packet.BGPError:
 					sendNotification(fsm.con, bgperr.ErrorCode, bgperr.ErrorSubCode)